Skip to content

Commit a6da3a4

Browse files
committed
fix: single place for html rendering
1 parent 7bf1245 commit a6da3a4

File tree

20 files changed

+34
-119
lines changed

20 files changed

+34
-119
lines changed

src/lib/kit/components/AccordeonCard/AccordeonCard.tsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {Button, Icon, Text} from '@gravity-ui/uikit';
55
import isString from 'lodash/isString';
66

77
import {block} from '../../utils';
8+
import {HTMLContent} from '../HTMLContent';
89

910
import './AccordeonCard.scss';
1011

@@ -23,7 +24,6 @@ export interface AccordeonCardProps {
2324
titleSize?: 's' | 'm';
2425
alwaysOpen?: boolean;
2526
classNameBody?: string;
26-
renderHtml?: (text: string) => React.ReactNode;
2727
}
2828
export const AccordeonCard: React.FC<AccordeonCardProps> = ({
2929
className,
@@ -38,7 +38,6 @@ export const AccordeonCard: React.FC<AccordeonCardProps> = ({
3838
alwaysOpen,
3939
children,
4040
classNameBody,
41-
renderHtml,
4241
}) => {
4342
const accordeonRef = React.useRef<HTMLDivElement>(null);
4443
const bodyRef = React.useRef<HTMLDivElement>(null);
@@ -90,19 +89,8 @@ export const AccordeonCard: React.FC<AccordeonCardProps> = ({
9089
return null;
9190
}
9291

93-
return (
94-
<React.Fragment>
95-
{renderHtml ? (
96-
renderHtml(description)
97-
) : (
98-
<span
99-
className={b('header-content-description')}
100-
dangerouslySetInnerHTML={{__html: description}}
101-
/>
102-
)}
103-
</React.Fragment>
104-
);
105-
}, [description, renderHtml]);
92+
return <HTMLContent className={b('header-content-description')} html={description} />;
93+
}, [description]);
10694

10795
return (
10896
<div ref={accordeonRef} className={b({empty: Boolean(emptyBody)}, className)}>

src/lib/kit/components/Card/Card.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export interface CardProps {
2323
alwaysOpen?: boolean;
2424
disableHeaderToggle?: boolean;
2525
checkEmptyBody?: boolean;
26-
renderHtml?: (html: string) => React.ReactNode;
2726
}
2827

2928
export const Card: React.FC<CardProps> = ({
@@ -37,7 +36,6 @@ export const Card: React.FC<CardProps> = ({
3736
disableHeaderToggle,
3837
checkEmptyBody,
3938
children,
40-
renderHtml,
4139
}) => {
4240
const containerRef = React.useRef<HTMLDivElement>(null);
4341
const titleRef = React.useRef<HTMLDivElement>(null);
Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,29 @@
11
import React from 'react';
22

3+
import {isFunction} from 'lodash';
4+
5+
import {useRenderHtml as useRenderHtmlForm} from '../../../core/components/Form/hooks/useRenderHtml';
6+
import {useRenderHtml as useRenderHtmlView} from '../../../core/components/View/hooks/useRenderHtml';
7+
38
interface HTMLContentProps {
49
html: string;
10+
className?: string;
511
}
612

7-
export const HTMLContent: React.FC<HTMLContentProps> = ({html}) => {
8-
return <div dangerouslySetInnerHTML={{__html: html}} />;
13+
export const HTMLContent: React.FC<HTMLContentProps> = ({html, className}) => {
14+
const renderHtmlForm = useRenderHtmlForm();
15+
const renderHtmlView = useRenderHtmlView();
16+
17+
const content = React.useMemo(() => {
18+
if (renderHtmlForm && isFunction(renderHtmlForm)) {
19+
return renderHtmlForm(html);
20+
}
21+
if (renderHtmlView && isFunction(renderHtmlView)) {
22+
return renderHtmlView(html);
23+
}
24+
25+
return <div className={className} dangerouslySetInnerHTML={{__html: html}} />;
26+
}, [className, html, renderHtmlForm, renderHtmlView]);
27+
28+
return <React.Fragment>{content}</React.Fragment>;
929
};

src/lib/kit/components/Inputs/TextContent/TextContent.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import {isEmpty} from 'lodash';
55
import cloneDeep from 'lodash/cloneDeep';
66

77
import type {StringIndependentInput, StringSpec} from '../../../../core';
8-
import {useRenderHtml} from '../../../../core/components/Form/hooks/useRenderHtml';
98
import {block} from '../../../utils';
9+
import {HTMLContent} from '../../HTMLContent';
1010
import {LazyLoader} from '../../LazyLoader';
1111

1212
import {loadIcon} from './utils';
@@ -19,14 +19,12 @@ export interface TextContentComponentProps {
1919
spec: StringSpec;
2020
value?: string;
2121
Layout?: React.FC<{spec: StringSpec; children: React.ReactElement}>;
22-
renderHtml?: ReturnType<typeof useRenderHtml>;
2322
}
2423

2524
export const TextContentComponent: React.FC<TextContentComponentProps> = ({
2625
spec,
2726
value,
2827
Layout,
29-
renderHtml,
3028
}) => {
3129
const {textContentParams, layoutDescription} = spec.viewSpec;
3230

@@ -43,7 +41,7 @@ export const TextContentComponent: React.FC<TextContentComponentProps> = ({
4341
<LazyLoader component={loadIcon(textContentParams?.icon)} />
4442
) : undefined;
4543

46-
let content = renderHtml ? renderHtml(text) : <span dangerouslySetInnerHTML={{__html: text}} />;
44+
let content = <HTMLContent html={text} />;
4745

4846
if (textContentParams?.themeAlert) {
4947
const titleAlert =
@@ -114,8 +112,6 @@ export const TextContent: StringIndependentInput = ({
114112
meta,
115113
layoutProps,
116114
}) => {
117-
const renderHtml = useRenderHtml();
118-
119115
const WrappedLayout = React.useMemo(() => {
120116
if (Layout) {
121117
const Component: TextContentComponentProps['Layout'] = (props) => {
@@ -137,12 +133,5 @@ export const TextContent: StringIndependentInput = ({
137133
return undefined;
138134
}, [Layout, layoutProps, input, arrayInput, meta, name]);
139135

140-
return (
141-
<TextContentComponent
142-
spec={spec}
143-
value={input.value}
144-
Layout={WrappedLayout}
145-
renderHtml={renderHtml}
146-
/>
147-
);
136+
return <TextContentComponent spec={spec} value={input.value} Layout={WrappedLayout} />;
148137
};

src/lib/kit/components/Layouts/Accordeon/Accordeon.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type {TextProps} from '@gravity-ui/uikit';
44

55
import type {ArrayLayoutProps, ObjectLayoutProps} from '../../../../core';
66
import {isArrayItem} from '../../../../core';
7-
import {useRenderHtml} from '../../../../core/components/Form/hooks/useRenderHtml';
87
import {ErrorWrapper} from '../../../components';
98
import {useErrorChecker} from '../../../hooks';
109
import {RemoveButton} from '../../RemoveButton';
@@ -25,8 +24,6 @@ export const Accordeon = <
2524
meta,
2625
children,
2726
}: T): JSX.Element => {
28-
const renderHtml = useRenderHtml();
29-
3027
const {variantTitle} = spec.viewSpec.layoutProps || {};
3128

3229
const [open, setOpen] = React.useState(Boolean(spec.viewSpec?.layoutOpen));
@@ -57,7 +54,6 @@ export const Accordeon = <
5754
hideInsteadOfDestroy
5855
withBranchView
5956
variantTitle={variantTitle}
60-
renderHtml={renderHtml}
6157
>
6258
<ErrorWrapper name={name} meta={meta} withoutChildErrorStyles>
6359
{children}

src/lib/kit/components/Layouts/AccordeonCard/AccordeonCardForm.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22

33
import type {ArrayLayoutProps, ObjectLayoutProps} from '../../../../core';
44
import {isArrayItem} from '../../../../core';
5-
import {useRenderHtml} from '../../../../core/components/Form/hooks/useRenderHtml';
65
import {useErrorChecker} from '../../../hooks';
76
import {block} from '../../../utils';
87
import {AccordeonCard} from '../../AccordeonCard';
@@ -20,8 +19,6 @@ export const AccordeonCardForm = <T extends ArrayLayoutProps | ObjectLayoutProps
2019
children,
2120
meta,
2221
}: T): JSX.Element => {
23-
const renderHtml = useRenderHtml();
24-
2522
const [open, setOpen] = React.useState(Boolean(spec.viewSpec?.layoutOpen));
2623

2724
const onDrop = React.useCallback(() => {
@@ -48,7 +45,6 @@ export const AccordeonCardForm = <T extends ArrayLayoutProps | ObjectLayoutProps
4845
open={open}
4946
onToggle={setOpen}
5047
headerActionsTemplate={removeButton}
51-
renderHtml={renderHtml}
5248
>
5349
<ErrorWrapper name={name} meta={meta} withoutChildErrorStyles>
5450
{children}

src/lib/kit/components/Layouts/CardAccordeon.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22

33
import type {FieldValue, LayoutProps, Spec} from '../../../core';
44
import {isArrayItem} from '../../../core';
5-
import {useRenderHtml} from '../../../core/components/Form/hooks/useRenderHtml';
65
import {Card, ErrorWrapper} from '../../components';
76
import {useErrorChecker} from '../../hooks';
87
import {RemoveButton} from '../RemoveButton';
@@ -14,8 +13,6 @@ export const CardAccordeon = <T extends FieldValue, S extends Spec>({
1413
meta,
1514
children,
1615
}: LayoutProps<T, undefined, undefined, S>) => {
17-
const renderHtml = useRenderHtml();
18-
1916
const [open, setOpen] = React.useState(Boolean(spec.viewSpec?.layoutOpen));
2017

2118
const onToggle = React.useCallback(() => setOpen((f) => !f), [setOpen]);
@@ -43,7 +40,6 @@ export const CardAccordeon = <T extends FieldValue, S extends Spec>({
4340
actions={removeButton}
4441
open={open}
4542
onToggle={onToggle}
46-
renderHtml={renderHtml}
4743
>
4844
<ErrorWrapper name={name} meta={meta} withoutChildErrorStyles>
4945
{children}

src/lib/kit/components/Layouts/CardSection.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22

33
import type {FieldValue, LayoutProps, Spec} from '../../../core';
44
import {isArrayItem} from '../../../core';
5-
import {useRenderHtml} from '../../../core/components/Form/hooks/useRenderHtml';
65
import {Card, ErrorWrapper} from '../../components';
76
import {RemoveButton} from '../RemoveButton';
87

@@ -13,8 +12,6 @@ export const CardSection = <T extends FieldValue, S extends Spec>({
1312
meta,
1413
children,
1514
}: LayoutProps<T, undefined, undefined, S>) => {
16-
const renderHtml = useRenderHtml();
17-
1815
const removeButton = React.useMemo(() => {
1916
if (!isArrayItem(name) && (spec.required || !input.value)) {
2017
return null;
@@ -30,7 +27,6 @@ export const CardSection = <T extends FieldValue, S extends Spec>({
3027
description={spec.viewSpec.layoutDescription}
3128
actions={removeButton}
3229
alwaysOpen
33-
renderHtml={renderHtml}
3430
>
3531
<ErrorWrapper name={name} meta={meta} withoutChildErrorStyles>
3632
{children}

src/lib/kit/components/Layouts/Column/Column.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {Button, HelpMark, Icon, Text} from '@gravity-ui/uikit';
55

66
import type {FieldValue, LayoutProps, Spec, StringSpec} from '../../../../core';
77
import {isArrayItem, isArraySpec, isObjectSpec, withGenerateButton} from '../../../../core';
8-
import {useRenderHtml} from '../../../../core/components/Form/hooks/useRenderHtml';
98
import {ErrorWrapper, GenerateRandomValueButton} from '../../../components';
109
import {COMMON_POPOVER_PLACEMENT} from '../../../constants/common';
1110
import {block} from '../../../utils';
@@ -26,7 +25,6 @@ const ColumnBase = <T extends FieldValue, S extends Spec>({
2625
}: LayoutProps<T, undefined, undefined, S> & ColumnProps) => {
2726
const arrayItem = React.useMemo(() => isArrayItem(name), [name]);
2827
const generateButton = React.useMemo(() => withGenerateButton(spec), [spec]);
29-
const renderHtml = useRenderHtml();
3028

3129
return (
3230
<div className={b()}>

src/lib/kit/components/Layouts/Row/Row.tsx

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {Button, HelpMark, Icon, Text} from '@gravity-ui/uikit';
55

66
import type {FieldValue, LayoutProps, Spec, StringSpec} from '../../../../core';
77
import {isArrayItem, isArraySpec, isObjectSpec, withGenerateButton} from '../../../../core';
8-
import {useRenderHtml} from '../../../../core/components/Form/hooks/useRenderHtml';
98
import {ErrorWrapper, GenerateRandomValueButton} from '../../../components';
109
import {COMMON_POPOVER_PLACEMENT} from '../../../constants/common';
1110
import {block} from '../../../utils';
@@ -27,29 +26,16 @@ const RowBase = <T extends FieldValue, S extends Spec>({
2726
verboseDescription,
2827
children,
2928
}: LayoutProps<T, undefined, undefined, S> & RowProps) => {
30-
const renderHtml = useRenderHtml();
31-
3229
const arrayItem = React.useMemo(() => isArrayItem(name), [name]);
3330
const generateButton = React.useMemo(() => withGenerateButton(spec), [spec]);
3431

3532
const verboseDescriptionContent = React.useMemo(() => {
3633
if (verboseDescription && spec.viewSpec.layoutDescription) {
37-
return (
38-
<React.Fragment>
39-
{renderHtml ? (
40-
renderHtml(spec.viewSpec.layoutDescription)
41-
) : (
42-
<div
43-
className={b('description')}
44-
dangerouslySetInnerHTML={{__html: spec.viewSpec.layoutDescription}}
45-
/>
46-
)}
47-
</React.Fragment>
48-
);
34+
return <HTMLContent html={spec.viewSpec.layoutDescription} />;
4935
}
5036

5137
return null;
52-
}, [renderHtml, spec.viewSpec.layoutDescription, verboseDescription]);
38+
}, [spec.viewSpec.layoutDescription, verboseDescription]);
5339

5440
return (
5541
<div className={b()}>

0 commit comments

Comments
 (0)