@lumx/react 2.2.0 → 2.2.2
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/esm/_internal/Avatar2.js +5 -1
- package/esm/_internal/Avatar2.js.map +1 -1
- package/esm/_internal/Thumbnail2.js +2 -0
- package/esm/_internal/Thumbnail2.js.map +1 -1
- package/esm/_internal/Tooltip2.js +0 -5
- package/esm/_internal/Tooltip2.js.map +1 -1
- package/esm/_internal/UserBlock.js +42 -17
- package/esm/_internal/UserBlock.js.map +1 -1
- package/esm/_internal/user-block.js +2 -0
- package/esm/_internal/user-block.js.map +1 -1
- package/package.json +4 -4
- package/src/components/avatar/Avatar.stories.tsx +30 -53
- package/src/components/avatar/Avatar.tsx +8 -0
- package/src/components/avatar/__snapshots__/Avatar.test.tsx.snap +193 -330
- package/src/components/thumbnail/Thumbnail.stories.tsx +8 -7
- package/src/components/thumbnail/Thumbnail.test.tsx +1 -7
- package/src/components/thumbnail/Thumbnail.tsx +2 -0
- package/src/components/thumbnail/__snapshots__/Thumbnail.test.tsx.snap +4 -2
- package/src/components/tooltip/Tooltip.stories.tsx +7 -4
- package/src/components/tooltip/useInjectTooltipRef.tsx +1 -3
- package/src/components/user-block/UserBlock.stories.tsx +65 -105
- package/src/components/user-block/UserBlock.test.tsx +6 -0
- package/src/components/user-block/UserBlock.tsx +51 -25
- package/src/components/user-block/__snapshots__/UserBlock.test.tsx.snap +113 -143
- package/src/stories/generated/Badge/Demos.stories.tsx +1 -0
- package/src/stories/generated/Flag/Demos.stories.tsx +6 -0
- package/src/stories/generated/Thumbnail/Demos.stories.tsx +1 -0
- package/src/stories/utils/CustomLink.tsx +7 -0
- package/types.d.ts +14 -4
|
@@ -19,6 +19,7 @@ import { focusKnob } from '@lumx/react/stories/knobs/focusKnob';
|
|
|
19
19
|
import { sizeKnob } from '@lumx/react/stories/knobs/sizeKnob';
|
|
20
20
|
import { action } from '@storybook/addon-actions';
|
|
21
21
|
import classNames from 'classnames';
|
|
22
|
+
import { CustomLink } from '@lumx/react/stories/utils/CustomLink';
|
|
22
23
|
|
|
23
24
|
export default { title: 'LumX components/thumbnail/Thumbnail' };
|
|
24
25
|
|
|
@@ -130,18 +131,12 @@ export const ClickableLink = () => (
|
|
|
130
131
|
/>
|
|
131
132
|
);
|
|
132
133
|
|
|
133
|
-
const CustomLinkComponent = (props: any) => (
|
|
134
|
-
<a {...props} className={classNames('custom-link-component', props.className)}>
|
|
135
|
-
{props.children}
|
|
136
|
-
</a>
|
|
137
|
-
);
|
|
138
|
-
|
|
139
134
|
export const ClickableCustomLink = () => (
|
|
140
135
|
<Thumbnail
|
|
141
136
|
alt="Click me"
|
|
142
137
|
image={imageKnob()}
|
|
143
138
|
size={sizeKnob('Size', Size.xxl)}
|
|
144
|
-
linkAs={
|
|
139
|
+
linkAs={CustomLink}
|
|
145
140
|
linkProps={{ href: 'https://google.fr', className: 'custom-class-name' }}
|
|
146
141
|
/>
|
|
147
142
|
);
|
|
@@ -280,11 +275,13 @@ export const Vertical = () => (
|
|
|
280
275
|
<Thumbnail alt="" aspectRatio="vertical" image={IMAGES.portrait1s200} size="xxl" />
|
|
281
276
|
</FlexBox>
|
|
282
277
|
<h2>With size & smaller image & fill height</h2>
|
|
278
|
+
<small>Unsupported use case (use ratio free with fill height)</small>
|
|
283
279
|
<FlexBox orientation="horizontal" vAlign="center" gap="huge">
|
|
284
280
|
<Thumbnail alt="" aspectRatio="vertical" image={IMAGES.landscape1s200} size="xxl" fillHeight />
|
|
285
281
|
<Thumbnail alt="" aspectRatio="vertical" image={IMAGES.portrait1s200} size="xxl" fillHeight />
|
|
286
282
|
</FlexBox>
|
|
287
283
|
<h2>Constrained parent size & smaller image & fill height</h2>
|
|
284
|
+
<small>Unsupported use case (use ratio free with fill height)</small>
|
|
288
285
|
<FlexBox orientation="horizontal" vAlign="center" gap="huge">
|
|
289
286
|
<div className="parent" style={{ width: 220 }}>
|
|
290
287
|
<Thumbnail alt="" aspectRatio="vertical" image={IMAGES.landscape1s200} fillHeight />
|
|
@@ -334,11 +331,13 @@ export const Wide = () => (
|
|
|
334
331
|
<Thumbnail alt="" aspectRatio="wide" image={IMAGES.portrait1s200} size="xxl" />
|
|
335
332
|
</FlexBox>
|
|
336
333
|
<h2>With size & smaller image & fill height</h2>
|
|
334
|
+
<small>Unsupported use case (use ratio free with fill height)</small>
|
|
337
335
|
<FlexBox orientation="horizontal" vAlign="center" gap="huge">
|
|
338
336
|
<Thumbnail alt="" aspectRatio="wide" image={IMAGES.landscape1s200} size="xxl" fillHeight />
|
|
339
337
|
<Thumbnail alt="" aspectRatio="wide" image={IMAGES.portrait1s200} size="xxl" fillHeight />
|
|
340
338
|
</FlexBox>
|
|
341
339
|
<h2>Constrained parent size & smaller image & fill height</h2>
|
|
340
|
+
<small>Unsupported use case (use ratio free with fill height)</small>
|
|
342
341
|
<FlexBox orientation="horizontal" vAlign="center" gap="huge">
|
|
343
342
|
<div className="parent" style={{ width: 220 }}>
|
|
344
343
|
<Thumbnail alt="" aspectRatio="wide" image={IMAGES.landscape1s200} fillHeight />
|
|
@@ -388,11 +387,13 @@ export const Square = () => (
|
|
|
388
387
|
<Thumbnail alt="" aspectRatio="square" image={IMAGES.portrait1s200} size="xxl" />
|
|
389
388
|
</FlexBox>
|
|
390
389
|
<h2>With size & smaller image & fill height</h2>
|
|
390
|
+
<small>Unsupported use case (use ratio free with fill height)</small>
|
|
391
391
|
<FlexBox orientation="horizontal" vAlign="center" gap="huge">
|
|
392
392
|
<Thumbnail alt="" aspectRatio="square" image={IMAGES.landscape1s200} size="xxl" fillHeight />
|
|
393
393
|
<Thumbnail alt="" aspectRatio="square" image={IMAGES.portrait1s200} size="xxl" fillHeight />
|
|
394
394
|
</FlexBox>
|
|
395
395
|
<h2>Constrained parent size & smaller image & fill height</h2>
|
|
396
|
+
<small>Unsupported use case (use ratio free with fill height)</small>
|
|
396
397
|
<FlexBox orientation="horizontal" vAlign="center" gap="huge">
|
|
397
398
|
<div className="parent" style={{ width: 220 }}>
|
|
398
399
|
<Thumbnail alt="" aspectRatio="square" image={IMAGES.landscape1s200} fillHeight />
|
|
@@ -5,13 +5,7 @@ import 'jest-enzyme';
|
|
|
5
5
|
import { commonTestsSuite, itShouldRenderStories } from '@lumx/react/testing/utils';
|
|
6
6
|
|
|
7
7
|
import { Thumbnail, ThumbnailProps } from './Thumbnail';
|
|
8
|
-
import {
|
|
9
|
-
Clickable,
|
|
10
|
-
ClickableCustomLink,
|
|
11
|
-
ClickableLink,
|
|
12
|
-
Default,
|
|
13
|
-
WithBadge,
|
|
14
|
-
} from './Thumbnail.stories';
|
|
8
|
+
import { Clickable, ClickableCustomLink, ClickableLink, Default, WithBadge } from './Thumbnail.stories';
|
|
15
9
|
|
|
16
10
|
const CLASSNAME = Thumbnail.className as string;
|
|
17
11
|
|
|
@@ -151,6 +151,8 @@ export const Thumbnail: Comp<ThumbnailProps> = forwardRef((props, ref) => {
|
|
|
151
151
|
Object.assign(wrapperProps, linkProps);
|
|
152
152
|
} else if (isButton) {
|
|
153
153
|
Wrapper = 'button';
|
|
154
|
+
wrapperProps.type = forwardedProps.type || 'button';
|
|
155
|
+
wrapperProps['aria-label'] = forwardedProps['aria-label'] || alt;
|
|
154
156
|
}
|
|
155
157
|
|
|
156
158
|
return (
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`<Thumbnail> Snapshots and structure should render story 'Clickable' 1`] = `
|
|
4
4
|
<button
|
|
5
|
+
aria-label="Click me"
|
|
5
6
|
className="lumx-thumbnail lumx-thumbnail--aspect-ratio-original lumx-thumbnail--size-xxl lumx-thumbnail--theme-light lumx-thumbnail--is-clickable lumx-thumbnail--is-loading"
|
|
6
7
|
onClick={[Function]}
|
|
8
|
+
type="button"
|
|
7
9
|
>
|
|
8
10
|
<div
|
|
9
11
|
className="lumx-thumbnail__background"
|
|
@@ -20,7 +22,7 @@ exports[`<Thumbnail> Snapshots and structure should render story 'Clickable' 1`]
|
|
|
20
22
|
`;
|
|
21
23
|
|
|
22
24
|
exports[`<Thumbnail> Snapshots and structure should render story 'ClickableCustomLink' 1`] = `
|
|
23
|
-
<
|
|
25
|
+
<CustomLink
|
|
24
26
|
className="custom-class-name lumx-thumbnail lumx-thumbnail--aspect-ratio-original lumx-thumbnail--size-xxl lumx-thumbnail--theme-light lumx-thumbnail--is-clickable lumx-thumbnail--is-loading"
|
|
25
27
|
href="https://google.fr"
|
|
26
28
|
>
|
|
@@ -35,7 +37,7 @@ exports[`<Thumbnail> Snapshots and structure should render story 'ClickableCusto
|
|
|
35
37
|
style={Object {}}
|
|
36
38
|
/>
|
|
37
39
|
</div>
|
|
38
|
-
</
|
|
40
|
+
</CustomLink>
|
|
39
41
|
`;
|
|
40
42
|
|
|
41
43
|
exports[`<Thumbnail> Snapshots and structure should render story 'ClickableLink' 1`] = `
|
|
@@ -76,13 +76,16 @@ export const EmptyTooltip = () => (
|
|
|
76
76
|
);
|
|
77
77
|
|
|
78
78
|
export const TooltipWithDropdown = () => {
|
|
79
|
-
const
|
|
79
|
+
const [button, setButton] = useState<HTMLElement | null>(null);
|
|
80
|
+
const [isOpen, setOpen] = useState(false);
|
|
80
81
|
return (
|
|
81
82
|
<>
|
|
82
|
-
<Tooltip label=
|
|
83
|
-
<Button ref={
|
|
83
|
+
<Tooltip label={!isOpen && 'Tooltip'} placement="top">
|
|
84
|
+
<Button ref={setButton} onClick={() => setOpen((o) => !o)}>
|
|
85
|
+
Anchor
|
|
86
|
+
</Button>
|
|
84
87
|
</Tooltip>
|
|
85
|
-
<Dropdown anchorRef={
|
|
88
|
+
<Dropdown anchorRef={{ current: button }} isOpen={isOpen}>
|
|
86
89
|
Dropdown
|
|
87
90
|
</Dropdown>
|
|
88
91
|
</>
|
|
@@ -28,9 +28,7 @@ export const useInjectTooltipRef = (
|
|
|
28
28
|
get(children, 'props.isDisabled') !== true
|
|
29
29
|
) {
|
|
30
30
|
const element = children as any;
|
|
31
|
-
|
|
32
|
-
setAnchorElement(element.ref.current);
|
|
33
|
-
}
|
|
31
|
+
|
|
34
32
|
return cloneElement(element, {
|
|
35
33
|
...element.props,
|
|
36
34
|
...ariaProps,
|
|
@@ -1,116 +1,76 @@
|
|
|
1
|
-
import { mdiStar } from '@lumx/icons';
|
|
2
|
-
import { Badge, ColorPalette, Icon, List, ListItem, Size } from '@lumx/react';
|
|
3
|
-
import { AVATAR_IMAGES, avatarImageKnob } from '@lumx/react/stories/knobs/image';
|
|
4
1
|
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { mdiStar } from '@lumx/icons';
|
|
4
|
+
import { Badge, ColorPalette, Icon, Size } from '@lumx/react';
|
|
5
|
+
import { avatarImageKnob } from '@lumx/react/stories/knobs/image';
|
|
6
|
+
import { CustomLink } from '@lumx/react/stories/utils/CustomLink';
|
|
7
|
+
|
|
5
8
|
import { UserBlock } from './UserBlock';
|
|
6
9
|
|
|
7
10
|
export default { title: 'LumX components/user-block/UserBlock' };
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
const logAction = (action: string) => () => console.log(action);
|
|
13
|
+
const sizes = [Size.s, Size.m, Size.l];
|
|
14
|
+
|
|
15
|
+
export const Default = ({ theme }: any) => (
|
|
16
|
+
<UserBlock
|
|
17
|
+
theme={theme}
|
|
18
|
+
name="Emmitt O. Lum"
|
|
19
|
+
fields={['Creative developer', 'Denpasar']}
|
|
20
|
+
avatarProps={{ image: avatarImageKnob(), alt: 'Avatar' }}
|
|
21
|
+
onMouseEnter={logAction('Mouse entered')}
|
|
22
|
+
onMouseLeave={logAction('Mouse left')}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export const Sizes = ({ theme }: any) =>
|
|
27
|
+
sizes.map((size) => (
|
|
28
|
+
<UserBlock
|
|
29
|
+
key={size}
|
|
30
|
+
theme={theme}
|
|
31
|
+
name="Emmitt O. Lum"
|
|
32
|
+
fields={['Creative developer', 'Denpasar']}
|
|
33
|
+
avatarProps={{ image: avatarImageKnob(), alt: 'Avatar' }}
|
|
34
|
+
size={size}
|
|
35
|
+
onMouseEnter={logAction('Mouse entered')}
|
|
36
|
+
onMouseLeave={logAction('Mouse left')}
|
|
37
|
+
/>
|
|
23
38
|
));
|
|
24
|
-
};
|
|
25
39
|
|
|
26
|
-
export const
|
|
27
|
-
const
|
|
40
|
+
export const Clickable = ({ theme }: any) => {
|
|
41
|
+
const baseProps = {
|
|
42
|
+
theme,
|
|
43
|
+
name: 'Emmitt O. Lum',
|
|
44
|
+
fields: ['Creative developer', 'Denpasar'],
|
|
45
|
+
avatarProps: { image: avatarImageKnob(), alt: 'Avatar' },
|
|
46
|
+
} as any;
|
|
28
47
|
return (
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
fields={['Creative developer', 'Denpasar']}
|
|
33
|
-
avatarProps={{
|
|
34
|
-
image: avatarImageKnob(),
|
|
35
|
-
alt: 'Avatar',
|
|
36
|
-
badge: (
|
|
37
|
-
<Badge color={ColorPalette.blue}>
|
|
38
|
-
<Icon icon={mdiStar} />
|
|
39
|
-
</Badge>
|
|
40
|
-
),
|
|
41
|
-
}}
|
|
42
|
-
size={Size.m}
|
|
43
|
-
onMouseEnter={logAction('Mouse entered')}
|
|
44
|
-
onMouseLeave={logAction('Mouse left')}
|
|
45
|
-
onClick={logAction('UserBlock clicked')}
|
|
46
|
-
/>
|
|
47
|
-
</div>
|
|
48
|
-
);
|
|
49
|
-
};
|
|
48
|
+
<>
|
|
49
|
+
<p>As a button</p>
|
|
50
|
+
<UserBlock {...baseProps} onClick={logAction('UserBlock clicked')} />
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
<UserBlock
|
|
58
|
-
name="Emmitt O. Lum"
|
|
59
|
-
fields={['Creative developer', 'Denpasar']}
|
|
60
|
-
avatarProps={{
|
|
61
|
-
image: avatarImageKnob('Avatar 1', AVATAR_IMAGES.avatar1),
|
|
62
|
-
alt: 'Avatar',
|
|
63
|
-
badge: (
|
|
64
|
-
<Badge color={ColorPalette.blue}>
|
|
65
|
-
<Icon icon={mdiStar} />
|
|
66
|
-
</Badge>
|
|
67
|
-
),
|
|
68
|
-
}}
|
|
69
|
-
size={Size.m}
|
|
70
|
-
onMouseEnter={logAction('Mouse entered')}
|
|
71
|
-
onMouseLeave={logAction('Mouse left')}
|
|
72
|
-
onClick={logAction('UserBlock clicked')}
|
|
73
|
-
/>
|
|
74
|
-
</ListItem>
|
|
75
|
-
<ListItem className="lumx-color-background-dark-L6" size={Size.big}>
|
|
76
|
-
<UserBlock
|
|
77
|
-
name="Emmitt O. Lum"
|
|
78
|
-
fields={['Creative developer', 'Denpasar']}
|
|
79
|
-
avatarProps={{
|
|
80
|
-
image: avatarImageKnob('Avatar 2', AVATAR_IMAGES.avatar2),
|
|
81
|
-
alt: 'Avatar',
|
|
82
|
-
badge: (
|
|
83
|
-
<Badge color={ColorPalette.blue}>
|
|
84
|
-
<Icon icon={mdiStar} />
|
|
85
|
-
</Badge>
|
|
86
|
-
),
|
|
87
|
-
}}
|
|
88
|
-
size={Size.m}
|
|
89
|
-
onMouseEnter={logAction('Mouse entered')}
|
|
90
|
-
onMouseLeave={logAction('Mouse left')}
|
|
91
|
-
onClick={logAction('UserBlock clicked')}
|
|
92
|
-
/>
|
|
93
|
-
</ListItem>
|
|
94
|
-
<ListItem className="lumx-color-background-dark-L6" size={Size.big}>
|
|
95
|
-
<UserBlock
|
|
96
|
-
name="Emmitt O. Lum"
|
|
97
|
-
fields={['Creative developer', 'Denpasar']}
|
|
98
|
-
avatarProps={{
|
|
99
|
-
image: avatarImageKnob('Avatar 3', AVATAR_IMAGES.avatar3),
|
|
100
|
-
alt: 'Avatar',
|
|
101
|
-
badge: (
|
|
102
|
-
<Badge color={ColorPalette.blue}>
|
|
103
|
-
<Icon icon={mdiStar} />
|
|
104
|
-
</Badge>
|
|
105
|
-
),
|
|
106
|
-
}}
|
|
107
|
-
size={Size.m}
|
|
108
|
-
onMouseEnter={logAction('Mouse entered')}
|
|
109
|
-
onMouseLeave={logAction('Mouse left')}
|
|
110
|
-
onClick={logAction('UserBlock clicked')}
|
|
111
|
-
/>
|
|
112
|
-
</ListItem>
|
|
113
|
-
</List>
|
|
114
|
-
</div>
|
|
52
|
+
<p>As a link</p>
|
|
53
|
+
<UserBlock {...baseProps} linkProps={{ href: 'https://example.com' }} />
|
|
54
|
+
|
|
55
|
+
<p>As a custom link component</p>
|
|
56
|
+
<UserBlock {...baseProps} linkAs={CustomLink} />
|
|
57
|
+
</>
|
|
115
58
|
);
|
|
116
59
|
};
|
|
60
|
+
|
|
61
|
+
export const WithBadge = ({ theme }: any) => (
|
|
62
|
+
<UserBlock
|
|
63
|
+
theme={theme}
|
|
64
|
+
name="Emmitt O. Lum"
|
|
65
|
+
fields={['Creative developer', 'Denpasar']}
|
|
66
|
+
avatarProps={{
|
|
67
|
+
image: avatarImageKnob(),
|
|
68
|
+
alt: 'Avatar',
|
|
69
|
+
badge: (
|
|
70
|
+
<Badge color={ColorPalette.blue}>
|
|
71
|
+
<Icon icon={mdiStar} />
|
|
72
|
+
</Badge>
|
|
73
|
+
),
|
|
74
|
+
}}
|
|
75
|
+
/>
|
|
76
|
+
);
|
|
@@ -25,6 +25,12 @@ describe(`<${UserBlock.displayName}>`, () => {
|
|
|
25
25
|
// 1. Test render via snapshot.
|
|
26
26
|
describe('Snapshots and structure', () => {
|
|
27
27
|
itShouldRenderStories(stories, UserBlock);
|
|
28
|
+
|
|
29
|
+
it('should forward name props', () => {
|
|
30
|
+
const { wrapper } = setup({ name: 'John Doe', nameProps: { 'data-custom-attribute': true } });
|
|
31
|
+
|
|
32
|
+
expect(wrapper.find('.lumx-user-block__name[data-custom-attribute]')).toHaveLength(1);
|
|
33
|
+
});
|
|
28
34
|
});
|
|
29
35
|
|
|
30
36
|
// Common tests suite.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, { forwardRef, ReactNode } from 'react';
|
|
2
|
-
|
|
2
|
+
import isEmpty from 'lodash/isEmpty';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
|
|
5
|
-
import { Avatar, Orientation, Size, Theme } from '@lumx/react';
|
|
6
|
-
|
|
5
|
+
import { Avatar, ColorPalette, Link, Orientation, Size, Theme } from '@lumx/react';
|
|
7
6
|
import { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';
|
|
7
|
+
|
|
8
8
|
import { AvatarProps } from '../avatar/Avatar';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -18,16 +18,22 @@ export type UserBlockSize = Extract<Size, 's' | 'm' | 'l'>;
|
|
|
18
18
|
export interface UserBlockProps extends GenericProps {
|
|
19
19
|
/** Props to pass to the avatar. */
|
|
20
20
|
avatarProps?: AvatarProps;
|
|
21
|
-
/** Simple action toolbar content. */
|
|
22
|
-
simpleAction?: ReactNode;
|
|
23
|
-
/** Multiple action toolbar content. */
|
|
24
|
-
multipleActions?: ReactNode;
|
|
25
21
|
/** Additional fields used to describe the user. */
|
|
26
22
|
fields?: string[];
|
|
23
|
+
/** Props to pass to the link wrapping the avatar thumbnail. */
|
|
24
|
+
linkProps?: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>;
|
|
25
|
+
/** Custom react component for the link (can be used to inject react router Link). */
|
|
26
|
+
linkAs?: 'a' | any;
|
|
27
|
+
/** Multiple action toolbar content. */
|
|
28
|
+
multipleActions?: ReactNode;
|
|
27
29
|
/** User name. */
|
|
28
30
|
name?: string;
|
|
31
|
+
/** Props to pass to the name block. */
|
|
32
|
+
nameProps?: GenericProps;
|
|
29
33
|
/** Orientation. */
|
|
30
34
|
orientation?: Orientation;
|
|
35
|
+
/** Simple action toolbar content. */
|
|
36
|
+
simpleAction?: ReactNode;
|
|
31
37
|
/** Size variant. */
|
|
32
38
|
size?: UserBlockSize;
|
|
33
39
|
/** Theme adapting the component to light or dark background. */
|
|
@@ -71,8 +77,11 @@ export const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props
|
|
|
71
77
|
avatarProps,
|
|
72
78
|
className,
|
|
73
79
|
fields,
|
|
80
|
+
linkProps,
|
|
81
|
+
linkAs,
|
|
74
82
|
multipleActions,
|
|
75
83
|
name,
|
|
84
|
+
nameProps,
|
|
76
85
|
onClick,
|
|
77
86
|
onMouseEnter,
|
|
78
87
|
onMouseLeave,
|
|
@@ -91,18 +100,35 @@ export const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props
|
|
|
91
100
|
|
|
92
101
|
const shouldDisplayActions: boolean = orientation === Orientation.vertical;
|
|
93
102
|
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
const isLink = Boolean(linkProps?.href || linkAs);
|
|
104
|
+
const isClickable = !!onClick || isLink;
|
|
105
|
+
|
|
106
|
+
const nameBlock: ReactNode = React.useMemo(() => {
|
|
107
|
+
if (isEmpty(name)) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
let NameComponent: any = 'span';
|
|
111
|
+
const nProps: any = {
|
|
112
|
+
...nameProps,
|
|
113
|
+
className: classNames(`${CLASSNAME}__name`, linkProps?.className, nameProps?.className),
|
|
114
|
+
};
|
|
115
|
+
if (isClickable) {
|
|
116
|
+
NameComponent = Link;
|
|
117
|
+
Object.assign(nProps, {
|
|
118
|
+
...linkProps,
|
|
119
|
+
onClick,
|
|
120
|
+
linkAs,
|
|
121
|
+
color: ColorPalette.dark,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return <NameComponent {...nProps}>{name}</NameComponent>;
|
|
125
|
+
}, [isClickable, linkAs, linkProps, name, nameProps, onClick]);
|
|
100
126
|
|
|
101
127
|
const fieldsBlock: ReactNode = fields && componentSize !== Size.s && (
|
|
102
128
|
<div className={`${CLASSNAME}__fields`}>
|
|
103
|
-
{fields.map((
|
|
129
|
+
{fields.map((field: string, idx: number) => (
|
|
104
130
|
<span key={idx} className={`${CLASSNAME}__field`}>
|
|
105
|
-
{
|
|
131
|
+
{field}
|
|
106
132
|
</span>
|
|
107
133
|
))}
|
|
108
134
|
</div>
|
|
@@ -114,21 +140,21 @@ export const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props
|
|
|
114
140
|
{...forwardedProps}
|
|
115
141
|
className={classNames(
|
|
116
142
|
className,
|
|
117
|
-
handleBasicClasses({ prefix: CLASSNAME, orientation, size: componentSize, theme }),
|
|
143
|
+
handleBasicClasses({ prefix: CLASSNAME, orientation, size: componentSize, theme, isClickable }),
|
|
118
144
|
)}
|
|
119
145
|
onMouseLeave={onMouseLeave}
|
|
120
146
|
onMouseEnter={onMouseEnter}
|
|
121
147
|
>
|
|
122
148
|
{avatarProps && (
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
149
|
+
<Avatar
|
|
150
|
+
linkAs={linkAs}
|
|
151
|
+
linkProps={linkProps}
|
|
152
|
+
{...avatarProps}
|
|
153
|
+
className={classNames(`${CLASSNAME}__avatar`, avatarProps.className)}
|
|
154
|
+
size={componentSize}
|
|
155
|
+
onClick={onClick}
|
|
156
|
+
theme={theme}
|
|
157
|
+
/>
|
|
132
158
|
)}
|
|
133
159
|
{(fields || name) && (
|
|
134
160
|
<div className={`${CLASSNAME}__wrapper`}>
|