@lumx/react 3.11.3 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +5 -1
- package/index.js +23 -11
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/dialog/Dialog.test.tsx +16 -0
- package/src/components/dialog/Dialog.tsx +66 -56
- package/src/components/lightbox/Lightbox.test.tsx +18 -0
- package/src/components/lightbox/Lightbox.tsx +10 -8
- package/src/components/popover-dialog/PopoverDialog.stories.tsx +2 -1
- package/src/components/popover-dialog/PopoverDialog.test.tsx +21 -1
- package/src/components/popover-dialog/PopoverDialog.tsx +2 -1
- package/src/components/user-block/UserBlock.stories.tsx +29 -2
- package/src/components/user-block/UserBlock.test.tsx +15 -3
- package/src/components/user-block/UserBlock.tsx +15 -4
package/package.json
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"url": "https://github.com/lumapps/design-system/issues"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@lumx/core": "^3.
|
|
10
|
-
"@lumx/icons": "^3.
|
|
9
|
+
"@lumx/core": "^3.12.0",
|
|
10
|
+
"@lumx/icons": "^3.12.0",
|
|
11
11
|
"@popperjs/core": "^2.5.4",
|
|
12
12
|
"body-scroll-lock": "^3.1.5",
|
|
13
13
|
"classnames": "^2.3.2",
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
"build:storybook": "storybook build"
|
|
111
111
|
},
|
|
112
112
|
"sideEffects": false,
|
|
113
|
-
"version": "3.
|
|
113
|
+
"version": "3.12.0"
|
|
114
114
|
}
|
|
@@ -6,6 +6,7 @@ import { render, screen } from '@testing-library/react';
|
|
|
6
6
|
import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
|
|
7
7
|
import userEvent from '@testing-library/user-event';
|
|
8
8
|
import { ThemeSentinel } from '@lumx/react/testing/utils/ThemeSentinel';
|
|
9
|
+
import { Heading, HeadingLevelProvider } from '@lumx/react';
|
|
9
10
|
|
|
10
11
|
const CLASSNAME = Dialog.className as string;
|
|
11
12
|
|
|
@@ -33,6 +34,21 @@ describe(`<${Dialog.displayName}>`, () => {
|
|
|
33
34
|
expect(container).toHaveAttribute('aria-modal', 'true');
|
|
34
35
|
});
|
|
35
36
|
|
|
37
|
+
it('should have reset the heading level context', () => {
|
|
38
|
+
setup(
|
|
39
|
+
// Heading inside the dialog
|
|
40
|
+
{ children: <Heading>Title</Heading> },
|
|
41
|
+
{
|
|
42
|
+
// This level context should not affect headings inside the dialog
|
|
43
|
+
wrapper({ children }) {
|
|
44
|
+
return <HeadingLevelProvider level={3}>{children}</HeadingLevelProvider>;
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
// Heading inside should use the dialog heading level 2
|
|
49
|
+
expect(screen.queryByRole('heading', { name: 'Title', level: 2 })).toBeInTheDocument();
|
|
50
|
+
});
|
|
51
|
+
|
|
36
52
|
describe('Events', () => {
|
|
37
53
|
it('should trigger `onClose` when pressing `escape` key', async () => {
|
|
38
54
|
const onClose = jest.fn();
|
|
@@ -3,7 +3,7 @@ import { createPortal } from 'react-dom';
|
|
|
3
3
|
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
|
|
6
|
-
import { Progress, ProgressVariant, Size } from '@lumx/react';
|
|
6
|
+
import { HeadingLevelProvider, Progress, ProgressVariant, Size } from '@lumx/react';
|
|
7
7
|
|
|
8
8
|
import { DIALOG_TRANSITION_DURATION, DOCUMENT } from '@lumx/react/constants';
|
|
9
9
|
import { useCallbackOnEscape } from '@lumx/react/hooks/useCallbackOnEscape';
|
|
@@ -212,67 +212,77 @@ export const Dialog = forwardRef<DialogProps, HTMLDivElement>((props, ref) => {
|
|
|
212
212
|
>
|
|
213
213
|
<div className={`${CLASSNAME}__overlay`} />
|
|
214
214
|
|
|
215
|
-
<
|
|
216
|
-
<
|
|
217
|
-
<
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
215
|
+
<HeadingLevelProvider level={2}>
|
|
216
|
+
<ThemeProvider value={undefined}>
|
|
217
|
+
<section
|
|
218
|
+
className={`${CLASSNAME}__container`}
|
|
219
|
+
role="dialog"
|
|
220
|
+
aria-modal="true"
|
|
221
|
+
{...dialogProps}
|
|
221
222
|
>
|
|
222
|
-
<
|
|
223
|
-
{
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
headerChildProps
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
223
|
+
<ClickAwayProvider
|
|
224
|
+
callback={!shouldPreventCloseOnClickAway && onClose}
|
|
225
|
+
childrenRefs={clickAwayRefs}
|
|
226
|
+
parentRef={rootRef}
|
|
227
|
+
>
|
|
228
|
+
<div className={`${CLASSNAME}__wrapper`} ref={wrapperRef}>
|
|
229
|
+
{(header || headerChildContent) && (
|
|
230
|
+
<header
|
|
231
|
+
{...headerChildProps}
|
|
232
|
+
className={classNames(
|
|
233
|
+
`${CLASSNAME}__header`,
|
|
234
|
+
(forceHeaderDivider || hasTopIntersection) &&
|
|
235
|
+
`${CLASSNAME}__header--has-divider`,
|
|
236
|
+
headerChildProps?.className,
|
|
237
|
+
)}
|
|
238
|
+
>
|
|
239
|
+
{header}
|
|
240
|
+
{headerChildContent}
|
|
241
|
+
</header>
|
|
242
|
+
)}
|
|
237
243
|
|
|
238
|
-
<div ref={mergeRefs(contentRef, localContentRef)} className={`${CLASSNAME}__content`}>
|
|
239
244
|
<div
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
+
ref={mergeRefs(contentRef, localContentRef)}
|
|
246
|
+
className={`${CLASSNAME}__content`}
|
|
247
|
+
>
|
|
248
|
+
<div
|
|
249
|
+
className={`${CLASSNAME}__sentinel ${CLASSNAME}__sentinel--top`}
|
|
250
|
+
ref={setSentinelTop}
|
|
251
|
+
/>
|
|
245
252
|
|
|
246
|
-
|
|
247
|
-
className={`${CLASSNAME}__sentinel ${CLASSNAME}__sentinel--bottom`}
|
|
248
|
-
ref={setSentinelBottom}
|
|
249
|
-
/>
|
|
250
|
-
</div>
|
|
253
|
+
{content}
|
|
251
254
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
`${CLASSNAME}__footer`,
|
|
257
|
-
(forceFooterDivider || hasBottomIntersection) &&
|
|
258
|
-
`${CLASSNAME}__footer--has-divider`,
|
|
259
|
-
footerChildProps?.className,
|
|
260
|
-
)}
|
|
261
|
-
>
|
|
262
|
-
{footer}
|
|
263
|
-
{footerChildContent}
|
|
264
|
-
</footer>
|
|
265
|
-
)}
|
|
266
|
-
|
|
267
|
-
{isLoading && (
|
|
268
|
-
<div className={`${CLASSNAME}__progress-overlay`}>
|
|
269
|
-
<Progress variant={ProgressVariant.circular} />
|
|
255
|
+
<div
|
|
256
|
+
className={`${CLASSNAME}__sentinel ${CLASSNAME}__sentinel--bottom`}
|
|
257
|
+
ref={setSentinelBottom}
|
|
258
|
+
/>
|
|
270
259
|
</div>
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
260
|
+
|
|
261
|
+
{(footer || footerChildContent) && (
|
|
262
|
+
<footer
|
|
263
|
+
{...footerChildProps}
|
|
264
|
+
className={classNames(
|
|
265
|
+
`${CLASSNAME}__footer`,
|
|
266
|
+
(forceFooterDivider || hasBottomIntersection) &&
|
|
267
|
+
`${CLASSNAME}__footer--has-divider`,
|
|
268
|
+
footerChildProps?.className,
|
|
269
|
+
)}
|
|
270
|
+
>
|
|
271
|
+
{footer}
|
|
272
|
+
{footerChildContent}
|
|
273
|
+
</footer>
|
|
274
|
+
)}
|
|
275
|
+
|
|
276
|
+
{isLoading && (
|
|
277
|
+
<div className={`${CLASSNAME}__progress-overlay`}>
|
|
278
|
+
<Progress variant={ProgressVariant.circular} />
|
|
279
|
+
</div>
|
|
280
|
+
)}
|
|
281
|
+
</div>
|
|
282
|
+
</ClickAwayProvider>
|
|
283
|
+
</section>
|
|
284
|
+
</ThemeProvider>
|
|
285
|
+
</HeadingLevelProvider>
|
|
276
286
|
</div>,
|
|
277
287
|
document.body,
|
|
278
288
|
)
|
|
@@ -5,6 +5,7 @@ import { queryByClassName } from '@lumx/react/testing/utils/queries';
|
|
|
5
5
|
import { render, screen } from '@testing-library/react';
|
|
6
6
|
import { ThemeSentinel } from '@lumx/react/testing/utils/ThemeSentinel';
|
|
7
7
|
|
|
8
|
+
import { Heading, HeadingLevelProvider } from '@lumx/react';
|
|
8
9
|
import { Lightbox, LightboxProps } from './Lightbox';
|
|
9
10
|
|
|
10
11
|
const CLASSNAME = Lightbox.className as string;
|
|
@@ -22,6 +23,23 @@ const setup = (props: Partial<LightboxProps> = {}, { wrapper }: SetupRenderOptio
|
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
describe(`<${Lightbox.displayName}>`, () => {
|
|
26
|
+
it('should have reset the heading level context', () => {
|
|
27
|
+
setup(
|
|
28
|
+
{
|
|
29
|
+
// Heading inside the lightbox
|
|
30
|
+
children: <Heading>Title</Heading>,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
// This level context should not affect headings inside the lightbox
|
|
34
|
+
wrapper({ children }) {
|
|
35
|
+
return <HeadingLevelProvider level={3}>{children}</HeadingLevelProvider>;
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
// Heading inside should use the lightbox heading level 2
|
|
40
|
+
expect(screen.queryByRole('heading', { name: 'Title', level: 2 })).toBeInTheDocument();
|
|
41
|
+
});
|
|
42
|
+
|
|
25
43
|
// Common tests suite.
|
|
26
44
|
commonTestsSuiteRTL(setup, {
|
|
27
45
|
baseClassName: CLASSNAME,
|
|
@@ -4,7 +4,7 @@ import classNames from 'classnames';
|
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
5
|
|
|
6
6
|
import { mdiClose } from '@lumx/icons';
|
|
7
|
-
import { IconButton, IconButtonProps } from '@lumx/react';
|
|
7
|
+
import { HeadingLevelProvider, IconButton, IconButtonProps } from '@lumx/react';
|
|
8
8
|
import { DIALOG_TRANSITION_DURATION, DOCUMENT } from '@lumx/react/constants';
|
|
9
9
|
import { GenericProps, HasTheme } from '@lumx/react/utils/type';
|
|
10
10
|
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
|
|
@@ -162,13 +162,15 @@ export const Lightbox = forwardRef<LightboxProps, HTMLDivElement>((props, ref) =
|
|
|
162
162
|
/>
|
|
163
163
|
</div>
|
|
164
164
|
)}
|
|
165
|
-
<
|
|
166
|
-
<
|
|
167
|
-
<
|
|
168
|
-
{
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
165
|
+
<HeadingLevelProvider level={2}>
|
|
166
|
+
<ThemeProvider value={undefined}>
|
|
167
|
+
<ClickAwayProvider callback={!preventAutoClose && onClose} childrenRefs={clickAwayRefs}>
|
|
168
|
+
<div ref={childrenRef} className={`${CLASSNAME}__wrapper`} role="presentation">
|
|
169
|
+
{children}
|
|
170
|
+
</div>
|
|
171
|
+
</ClickAwayProvider>
|
|
172
|
+
</ThemeProvider>
|
|
173
|
+
</HeadingLevelProvider>
|
|
172
174
|
</div>,
|
|
173
175
|
document.body,
|
|
174
176
|
);
|
|
@@ -40,7 +40,7 @@ export const WithButtonTrigger = (props: any) => {
|
|
|
40
40
|
/**
|
|
41
41
|
* Example PopoverDialog using an icon button as a trigger
|
|
42
42
|
*/
|
|
43
|
-
export const WithIconButtonTrigger = (props: any) => {
|
|
43
|
+
export const WithIconButtonTrigger = ({ children, ...props }: any) => {
|
|
44
44
|
const anchorRef = React.useRef(null);
|
|
45
45
|
const [isOpen, close, open] = useBooleanState(false);
|
|
46
46
|
|
|
@@ -57,6 +57,7 @@ export const WithIconButtonTrigger = (props: any) => {
|
|
|
57
57
|
{...props}
|
|
58
58
|
>
|
|
59
59
|
<Button onClick={close}>Close</Button>
|
|
60
|
+
{children}
|
|
60
61
|
</PopoverDialog>
|
|
61
62
|
</>
|
|
62
63
|
);
|
|
@@ -2,8 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import { render, screen, within } from '@testing-library/react';
|
|
3
3
|
import userEvent from '@testing-library/user-event';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Heading, HeadingLevelProvider } from '@lumx/react';
|
|
6
6
|
import { WithButtonTrigger, WithIconButtonTrigger } from './PopoverDialog.stories';
|
|
7
|
+
import { PopoverDialog } from './PopoverDialog';
|
|
7
8
|
|
|
8
9
|
jest.mock('@lumx/react/utils/browser/isFocusVisible');
|
|
9
10
|
|
|
@@ -117,4 +118,23 @@ describe(`<${PopoverDialog.displayName}>`, () => {
|
|
|
117
118
|
// Focus restored to the trigger element
|
|
118
119
|
expect(triggerElement).toHaveFocus();
|
|
119
120
|
});
|
|
121
|
+
|
|
122
|
+
it('should have reset the heading level context', async () => {
|
|
123
|
+
render(
|
|
124
|
+
// This level context should not affect headings inside the popover dialog
|
|
125
|
+
|
|
126
|
+
<HeadingLevelProvider level={3}>
|
|
127
|
+
<WithIconButtonTrigger>
|
|
128
|
+
{/* Heading inside the popover dialog */}
|
|
129
|
+
<Heading>Title</Heading>
|
|
130
|
+
</WithIconButtonTrigger>
|
|
131
|
+
</HeadingLevelProvider>,
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// Open popover
|
|
135
|
+
await userEvent.click(screen.getByRole('button', { name: 'Open popover' }));
|
|
136
|
+
|
|
137
|
+
// Heading inside should use the popover dialog heading level 2
|
|
138
|
+
expect(screen.getByRole('heading', { name: 'Title', level: 2 })).toBeInTheDocument();
|
|
139
|
+
});
|
|
120
140
|
});
|
|
@@ -6,6 +6,7 @@ import { HasAriaLabelOrLabelledBy } from '@lumx/react/utils/type';
|
|
|
6
6
|
import { getRootClassName } from '@lumx/react/utils/className';
|
|
7
7
|
import { forwardRef } from '@lumx/react/utils/react/forwardRef';
|
|
8
8
|
|
|
9
|
+
import { HeadingLevelProvider } from '@lumx/react/components/heading';
|
|
9
10
|
import { Popover, PopoverProps } from '../popover/Popover';
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -65,7 +66,7 @@ export const PopoverDialog = forwardRef<PopoverDialogProps, HTMLDivElement>((pro
|
|
|
65
66
|
closeOnEscape
|
|
66
67
|
withFocusTrap
|
|
67
68
|
>
|
|
68
|
-
{children}
|
|
69
|
+
<HeadingLevelProvider level={2}>{children}</HeadingLevelProvider>
|
|
69
70
|
</Popover>
|
|
70
71
|
);
|
|
71
72
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import { mdiStar } from '@lumx/icons';
|
|
4
|
-
import { Badge, ColorPalette, Icon, Orientation, Size } from '@lumx/react';
|
|
3
|
+
import { mdiMenuDown, mdiStar } from '@lumx/icons';
|
|
4
|
+
import { Badge, ColorPalette, Icon, IconButton, Orientation, Size, Text } from '@lumx/react';
|
|
5
5
|
import { CustomLink } from '@lumx/react/stories/utils/CustomLink';
|
|
6
6
|
|
|
7
7
|
import { AVATAR_IMAGES } from '@lumx/react/stories/controls/image';
|
|
@@ -31,11 +31,38 @@ export const AvatarAndName = {
|
|
|
31
31
|
args: { ...AvatarOnly.args, name: 'Emmitt O. Lum' },
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
/** Avatar and children */
|
|
35
|
+
export const AvatarAndCustomName = {
|
|
36
|
+
args: { ...AvatarOnly.args, name: <Text as="span">Emmitt O. Lum</Text> },
|
|
37
|
+
};
|
|
38
|
+
|
|
34
39
|
/** Avatar, name and secondary fields */
|
|
35
40
|
export const AvatarAndNameAndSecondaryFields = {
|
|
36
41
|
args: { ...AvatarAndName.args, fields: ['Creative developer', 'Denpasar'] },
|
|
37
42
|
};
|
|
38
43
|
|
|
44
|
+
/** With Right component */
|
|
45
|
+
export const WithAfter = {
|
|
46
|
+
args: {
|
|
47
|
+
...AvatarAndName.args,
|
|
48
|
+
fields: ['Creative developer', 'Denpasar'],
|
|
49
|
+
after: <IconButton label="View" icon={mdiMenuDown} emphasis="low" />,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** With after component */
|
|
54
|
+
export const WithAdditionalFields = {
|
|
55
|
+
args: {
|
|
56
|
+
...AvatarAndName.args,
|
|
57
|
+
fields: ['Creative developer', 'Denpasar'],
|
|
58
|
+
additionalFields: (
|
|
59
|
+
<Text as="span" typography="body1">
|
|
60
|
+
Works at the Toronto office
|
|
61
|
+
</Text>
|
|
62
|
+
),
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
39
66
|
/** Size variants */
|
|
40
67
|
export const SizesAndOrientations = {
|
|
41
68
|
...AvatarAndNameAndSecondaryFields,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
|
|
4
|
-
import { render, within } from '@testing-library/react';
|
|
4
|
+
import { render, within, screen } from '@testing-library/react';
|
|
5
5
|
import { getByClassName, queryByClassName } from '@lumx/react/testing/utils/queries';
|
|
6
|
-
import { Thumbnail } from '@lumx/react';
|
|
6
|
+
import { Text, Thumbnail } from '@lumx/react';
|
|
7
7
|
import userEvent from '@testing-library/user-event';
|
|
8
8
|
|
|
9
9
|
import { UserBlock, UserBlockProps } from './UserBlock';
|
|
@@ -22,8 +22,9 @@ const setup = (propsOverride: Partial<UserBlockProps> = {}, { wrapper }: SetupRe
|
|
|
22
22
|
const avatar = queryByClassName(userBlock, `${CLASSNAME}__avatar`);
|
|
23
23
|
const thumbnail = avatar && queryByClassName(avatar, Thumbnail.className as string);
|
|
24
24
|
const fields = queryByClassName(userBlock, `${CLASSNAME}__fields`);
|
|
25
|
+
const after = queryByClassName(userBlock, `${CLASSNAME}__after`);
|
|
25
26
|
|
|
26
|
-
return { props, userBlock, name, avatar, thumbnail, fields };
|
|
27
|
+
return { props, userBlock, name, avatar, thumbnail, fields, after };
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
describe(`<${UserBlock.displayName}>`, () => {
|
|
@@ -78,6 +79,17 @@ describe(`<${UserBlock.displayName}>`, () => {
|
|
|
78
79
|
expect(within(fields as any).getByText('Field 1')).toBeInTheDocument();
|
|
79
80
|
expect(within(fields as any).getByText('Field 2')).toBeInTheDocument();
|
|
80
81
|
});
|
|
82
|
+
|
|
83
|
+
it('should render additional fields', () => {
|
|
84
|
+
setup({ additionalFields: <Text as="span">Works in Toronto</Text> });
|
|
85
|
+
expect(screen.queryByText(/works in toronto/i)).toBeInTheDocument();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should render after', () => {
|
|
89
|
+
const { after } = setup({ after: <Text as="span">After</Text> });
|
|
90
|
+
expect(after).toBeInTheDocument();
|
|
91
|
+
expect(screen.queryByText(/after/i)).toBeInTheDocument();
|
|
92
|
+
});
|
|
81
93
|
});
|
|
82
94
|
|
|
83
95
|
// Common tests suite.
|
|
@@ -32,7 +32,7 @@ export interface UserBlockProps extends GenericProps, HasTheme {
|
|
|
32
32
|
/** Multiple action toolbar content. */
|
|
33
33
|
multipleActions?: ReactNode;
|
|
34
34
|
/** User name. */
|
|
35
|
-
name?:
|
|
35
|
+
name?: React.ReactNode;
|
|
36
36
|
/** Props to pass to the name block. */
|
|
37
37
|
nameProps?: GenericProps;
|
|
38
38
|
/** Orientation. */
|
|
@@ -47,6 +47,10 @@ export interface UserBlockProps extends GenericProps, HasTheme {
|
|
|
47
47
|
onMouseEnter?(): void;
|
|
48
48
|
/** On mouse leave callback. */
|
|
49
49
|
onMouseLeave?(): void;
|
|
50
|
+
/** Display additional fields below the original name and fields */
|
|
51
|
+
additionalFields?: React.ReactNode;
|
|
52
|
+
/** Display an additional element after the entire component. (to the right if orientation is horizontal, at the bottom if orientation is vertical) */
|
|
53
|
+
after?: React.ReactNode;
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
/**
|
|
@@ -92,6 +96,9 @@ export const UserBlock = forwardRef<UserBlockProps, HTMLDivElement>((props, ref)
|
|
|
92
96
|
simpleAction,
|
|
93
97
|
size,
|
|
94
98
|
theme = defaultTheme,
|
|
99
|
+
children,
|
|
100
|
+
additionalFields,
|
|
101
|
+
after,
|
|
95
102
|
...forwardedProps
|
|
96
103
|
} = props;
|
|
97
104
|
let componentSize = size;
|
|
@@ -131,7 +138,9 @@ export const UserBlock = forwardRef<UserBlockProps, HTMLDivElement>((props, ref)
|
|
|
131
138
|
return <NameComponent {...nProps}>{name}</NameComponent>;
|
|
132
139
|
}, [avatarProps, isClickable, linkAs, linkProps, name, nameProps, onClick]);
|
|
133
140
|
|
|
134
|
-
const
|
|
141
|
+
const shouldDisplayFields = componentSize !== Size.s && componentSize !== Size.xs;
|
|
142
|
+
|
|
143
|
+
const fieldsBlock: ReactNode = fields && shouldDisplayFields && (
|
|
135
144
|
<div className={`${CLASSNAME}__fields`}>
|
|
136
145
|
{fields.map((field: string, idx: number) => (
|
|
137
146
|
<span key={idx} className={`${CLASSNAME}__field`}>
|
|
@@ -164,16 +173,18 @@ export const UserBlock = forwardRef<UserBlockProps, HTMLDivElement>((props, ref)
|
|
|
164
173
|
theme={theme}
|
|
165
174
|
/>
|
|
166
175
|
)}
|
|
167
|
-
{(fields || name) && (
|
|
176
|
+
{(fields || name || children || additionalFields) && (
|
|
168
177
|
<div className={`${CLASSNAME}__wrapper`}>
|
|
169
|
-
{nameBlock}
|
|
178
|
+
{children || nameBlock}
|
|
170
179
|
{fieldsBlock}
|
|
180
|
+
{shouldDisplayFields ? additionalFields : null}
|
|
171
181
|
</div>
|
|
172
182
|
)}
|
|
173
183
|
{shouldDisplayActions && simpleAction && <div className={`${CLASSNAME}__action`}>{simpleAction}</div>}
|
|
174
184
|
{shouldDisplayActions && multipleActions && (
|
|
175
185
|
<div className={`${CLASSNAME}__actions`}>{multipleActions}</div>
|
|
176
186
|
)}
|
|
187
|
+
{after ? <div className={`${CLASSNAME}__after`}>{after}</div> : null}
|
|
177
188
|
</div>
|
|
178
189
|
);
|
|
179
190
|
});
|