@lumx/react 2.1.4 → 2.1.5

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.
@@ -1,8 +1,10 @@
1
- import { b as _objectWithoutProperties, c as _extends } from './_rollupPluginBabelHelpers.js';
1
+ import { b as _objectWithoutProperties, _ as _objectSpread2, c as _extends } from './_rollupPluginBabelHelpers.js';
2
2
  import { Size, Orientation, Theme } from './components.js';
3
3
  import React, { forwardRef } from 'react';
4
4
  import { g as getRootClassName, c as classnames, h as handleBasicClasses } from './getRootClassName.js';
5
5
  import { A as Avatar } from './Avatar2.js';
6
+ import { r as renderLink } from './renderLink.js';
7
+ import { isEmpty } from 'lodash';
6
8
 
7
9
  /**
8
10
  * Component display name.
@@ -43,7 +45,9 @@ var UserBlock = forwardRef(function (props, ref) {
43
45
  simpleAction = props.simpleAction,
44
46
  size = props.size,
45
47
  theme = props.theme,
46
- forwardedProps = _objectWithoutProperties(props, ["avatarProps", "className", "fields", "multipleActions", "name", "onClick", "onMouseEnter", "onMouseLeave", "orientation", "simpleAction", "size", "theme"]);
48
+ linkProps = props.linkProps,
49
+ linkAs = props.linkAs,
50
+ forwardedProps = _objectWithoutProperties(props, ["avatarProps", "className", "fields", "multipleActions", "name", "onClick", "onMouseEnter", "onMouseLeave", "orientation", "simpleAction", "size", "theme", "linkProps", "linkAs"]);
47
51
 
48
52
  var componentSize = size; // Special case - When using vertical orientation force the size to be Sizes.l.
49
53
 
@@ -52,12 +56,37 @@ var UserBlock = forwardRef(function (props, ref) {
52
56
  }
53
57
 
54
58
  var shouldDisplayActions = orientation === Orientation.vertical;
55
- var nameBlock = name && // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-noninteractive-tabindex,jsx-a11y/no-static-element-interactions
56
- React.createElement("span", {
57
- className: "".concat(CLASSNAME, "__name"),
58
- onClick: onClick,
59
- tabIndex: onClick ? 0 : -1
60
- }, name);
59
+ var isLink = Boolean((linkProps === null || linkProps === void 0 ? void 0 : linkProps.href) || linkAs);
60
+ var isClickable = !!onClick || isLink;
61
+ var nameBlock = React.useMemo(function () {
62
+ if (isEmpty(name)) {
63
+ return null;
64
+ }
65
+
66
+ var nameClassName = classnames(handleBasicClasses({
67
+ prefix: "".concat(CLASSNAME, "__name"),
68
+ isClickable: isClickable
69
+ }), isLink && (linkProps === null || linkProps === void 0 ? void 0 : linkProps.className));
70
+
71
+ if (isLink) {
72
+ return renderLink(_objectSpread2({}, linkProps, {
73
+ linkAs: linkAs,
74
+ className: nameClassName
75
+ }), name);
76
+ }
77
+
78
+ if (onClick) {
79
+ return React.createElement("button", {
80
+ onClick: onClick,
81
+ type: "button",
82
+ className: nameClassName
83
+ }, name);
84
+ }
85
+
86
+ return React.createElement("span", {
87
+ className: nameClassName
88
+ }, name);
89
+ }, [isClickable, isLink, linkAs, linkProps, name, onClick]);
61
90
  var fieldsBlock = fields && componentSize !== Size.s && React.createElement("div", {
62
91
  className: "".concat(CLASSNAME, "__fields")
63
92
  }, fields.map(function (aField, idx) {
@@ -73,18 +102,19 @@ var UserBlock = forwardRef(function (props, ref) {
73
102
  prefix: CLASSNAME,
74
103
  orientation: orientation,
75
104
  size: componentSize,
76
- theme: theme
105
+ theme: theme,
106
+ isClickable: isClickable
77
107
  })),
78
108
  onMouseLeave: onMouseLeave,
79
109
  onMouseEnter: onMouseEnter
80
- }), avatarProps && React.createElement("div", {
81
- className: "".concat(CLASSNAME, "__avatar")
82
- }, React.createElement(Avatar, _extends({}, avatarProps, {
110
+ }), avatarProps && React.createElement(Avatar, _extends({
111
+ linkProps: linkProps
112
+ }, avatarProps, {
113
+ className: classnames("".concat(CLASSNAME, "__avatar"), avatarProps.className),
83
114
  size: componentSize,
84
115
  onClick: onClick,
85
- tabIndex: onClick ? 0 : -1,
86
116
  theme: theme
87
- }))), (fields || name) && React.createElement("div", {
117
+ })), (fields || name) && React.createElement("div", {
88
118
  className: "".concat(CLASSNAME, "__wrapper")
89
119
  }, nameBlock, fieldsBlock), shouldDisplayActions && simpleAction && React.createElement("div", {
90
120
  className: "".concat(CLASSNAME, "__action")
@@ -1 +1 @@
1
- {"version":3,"file":"UserBlock.js","sources":["../../../src/components/user-block/UserBlock.tsx"],"sourcesContent":["import React, { forwardRef, ReactNode } from 'react';\n\nimport classNames from 'classnames';\n\nimport { Avatar, Orientation, Size, Theme } from '@lumx/react';\n\nimport { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';\nimport { AvatarProps } from '../avatar/Avatar';\n\n/**\n * User block sizes.\n */\nexport type UserBlockSize = Extract<Size, 's' | 'm' | 'l'>;\n\n/**\n * Defines the props of the component.\n */\nexport interface UserBlockProps extends GenericProps {\n /** Props to pass to the avatar. */\n avatarProps?: AvatarProps;\n /** Simple action toolbar content. */\n simpleAction?: ReactNode;\n /** Multiple action toolbar content. */\n multipleActions?: ReactNode;\n /** Additional fields used to describe the user. */\n fields?: string[];\n /** User name. */\n name?: string;\n /** Orientation. */\n orientation?: Orientation;\n /** Size variant. */\n size?: UserBlockSize;\n /** Theme adapting the component to light or dark background. */\n theme?: Theme;\n /** On click callback. */\n onClick?(): void;\n /** On mouse enter callback. */\n onMouseEnter?(): void;\n /** On mouse leave callback. */\n onMouseLeave?(): void;\n}\n\n/**\n * Component display name.\n */\nconst COMPONENT_NAME = 'UserBlock';\n\n/**\n * Component default class name and class prefix.\n */\nconst CLASSNAME = getRootClassName(COMPONENT_NAME);\n\n/**\n * Component default props.\n */\nconst DEFAULT_PROPS: Partial<UserBlockProps> = {\n orientation: Orientation.horizontal,\n size: Size.m,\n theme: Theme.light,\n};\n\n/**\n * UserBlock component.\n *\n * @param props Component props.\n * @param ref Component ref.\n * @return React element.\n */\nexport const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props, ref) => {\n const {\n avatarProps,\n className,\n fields,\n multipleActions,\n name,\n onClick,\n onMouseEnter,\n onMouseLeave,\n orientation,\n simpleAction,\n size,\n theme,\n ...forwardedProps\n } = props;\n let componentSize = size;\n\n // Special case - When using vertical orientation force the size to be Sizes.l.\n if (orientation === Orientation.vertical) {\n componentSize = Size.l;\n }\n\n const shouldDisplayActions: boolean = orientation === Orientation.vertical;\n\n const nameBlock: ReactNode = name && (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-noninteractive-tabindex,jsx-a11y/no-static-element-interactions\n <span className={`${CLASSNAME}__name`} onClick={onClick} tabIndex={onClick ? 0 : -1}>\n {name}\n </span>\n );\n\n const fieldsBlock: ReactNode = fields && componentSize !== Size.s && (\n <div className={`${CLASSNAME}__fields`}>\n {fields.map((aField: string, idx: number) => (\n <span key={idx} className={`${CLASSNAME}__field`}>\n {aField}\n </span>\n ))}\n </div>\n );\n\n return (\n <div\n ref={ref}\n {...forwardedProps}\n className={classNames(\n className,\n handleBasicClasses({ prefix: CLASSNAME, orientation, size: componentSize, theme }),\n )}\n onMouseLeave={onMouseLeave}\n onMouseEnter={onMouseEnter}\n >\n {avatarProps && (\n <div className={`${CLASSNAME}__avatar`}>\n <Avatar\n {...avatarProps}\n size={componentSize}\n onClick={onClick}\n tabIndex={onClick ? 0 : -1}\n theme={theme}\n />\n </div>\n )}\n {(fields || name) && (\n <div className={`${CLASSNAME}__wrapper`}>\n {nameBlock}\n {fieldsBlock}\n </div>\n )}\n {shouldDisplayActions && simpleAction && <div className={`${CLASSNAME}__action`}>{simpleAction}</div>}\n {shouldDisplayActions && multipleActions && (\n <div className={`${CLASSNAME}__actions`}>{multipleActions}</div>\n )}\n </div>\n );\n});\nUserBlock.displayName = COMPONENT_NAME;\nUserBlock.className = CLASSNAME;\nUserBlock.defaultProps = DEFAULT_PROPS;\n"],"names":["COMPONENT_NAME","CLASSNAME","getRootClassName","DEFAULT_PROPS","orientation","Orientation","horizontal","size","Size","m","theme","Theme","light","UserBlock","forwardRef","props","ref","avatarProps","className","fields","multipleActions","name","onClick","onMouseEnter","onMouseLeave","simpleAction","forwardedProps","componentSize","vertical","l","shouldDisplayActions","nameBlock","fieldsBlock","s","map","aField","idx","classNames","handleBasicClasses","prefix","displayName","defaultProps"],"mappings":"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"}
1
+ {"version":3,"file":"UserBlock.js","sources":["../../../src/components/user-block/UserBlock.tsx"],"sourcesContent":["import React, { forwardRef, ReactNode } from 'react';\n\nimport classNames from 'classnames';\n\nimport { Avatar, Orientation, Size, Theme } from '@lumx/react';\n\nimport { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';\nimport { isEmpty } from 'lodash';\nimport { renderLink } from '@lumx/react/utils/renderLink';\nimport { AvatarProps } from '../avatar/Avatar';\n\n/**\n * User block sizes.\n */\nexport type UserBlockSize = Extract<Size, 's' | 'm' | 'l'>;\n\n/**\n * Defines the props of the component.\n */\nexport interface UserBlockProps extends GenericProps {\n /** Props to pass to the avatar. */\n avatarProps?: AvatarProps;\n /** Props to pass to the link wrapping the avatar thumbnail. */\n linkProps?: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>;\n /** Custom react component for the link (can be used to inject react router Link). */\n linkAs?: 'a' | any;\n /** Simple action toolbar content. */\n simpleAction?: ReactNode;\n /** Multiple action toolbar content. */\n multipleActions?: ReactNode;\n /** Additional fields used to describe the user. */\n fields?: string[];\n /** User name. */\n name?: string;\n /** Orientation. */\n orientation?: Orientation;\n /** Size variant. */\n size?: UserBlockSize;\n /** Theme adapting the component to light or dark background. */\n theme?: Theme;\n /** On click callback. */\n onClick?(): void;\n /** On mouse enter callback. */\n onMouseEnter?(): void;\n /** On mouse leave callback. */\n onMouseLeave?(): void;\n}\n\n/**\n * Component display name.\n */\nconst COMPONENT_NAME = 'UserBlock';\n\n/**\n * Component default class name and class prefix.\n */\nconst CLASSNAME = getRootClassName(COMPONENT_NAME);\n\n/**\n * Component default props.\n */\nconst DEFAULT_PROPS: Partial<UserBlockProps> = {\n orientation: Orientation.horizontal,\n size: Size.m,\n theme: Theme.light,\n};\n\n/**\n * UserBlock component.\n *\n * @param props Component props.\n * @param ref Component ref.\n * @return React element.\n */\nexport const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props, ref) => {\n const {\n avatarProps,\n className,\n fields,\n multipleActions,\n name,\n onClick,\n onMouseEnter,\n onMouseLeave,\n orientation,\n simpleAction,\n size,\n theme,\n linkProps,\n linkAs,\n ...forwardedProps\n } = props;\n let componentSize = size;\n\n // Special case - When using vertical orientation force the size to be Sizes.l.\n if (orientation === Orientation.vertical) {\n componentSize = Size.l;\n }\n\n const shouldDisplayActions: boolean = orientation === Orientation.vertical;\n\n const isLink = Boolean(linkProps?.href || linkAs);\n const isClickable = !!onClick || isLink;\n\n const nameBlock: ReactNode = React.useMemo(() => {\n if (isEmpty(name)) {\n return null;\n }\n const nameClassName = classNames(\n handleBasicClasses({ prefix: `${CLASSNAME}__name`, isClickable }),\n isLink && linkProps?.className,\n );\n if (isLink) {\n return renderLink({ ...linkProps, linkAs, className: nameClassName }, name);\n }\n if (onClick) {\n return (\n <button onClick={onClick} type=\"button\" className={nameClassName}>\n {name}\n </button>\n );\n }\n return <span className={nameClassName}>{name}</span>;\n }, [isClickable, isLink, linkAs, linkProps, name, onClick]);\n\n const fieldsBlock: ReactNode = fields && componentSize !== Size.s && (\n <div className={`${CLASSNAME}__fields`}>\n {fields.map((aField: string, idx: number) => (\n <span key={idx} className={`${CLASSNAME}__field`}>\n {aField}\n </span>\n ))}\n </div>\n );\n\n return (\n <div\n ref={ref}\n {...forwardedProps}\n className={classNames(\n className,\n handleBasicClasses({ prefix: CLASSNAME, orientation, size: componentSize, theme, isClickable }),\n )}\n onMouseLeave={onMouseLeave}\n onMouseEnter={onMouseEnter}\n >\n {avatarProps && (\n <Avatar\n linkProps={linkProps}\n {...avatarProps}\n className={classNames(`${CLASSNAME}__avatar`, avatarProps.className)}\n size={componentSize}\n onClick={onClick}\n theme={theme}\n />\n )}\n {(fields || name) && (\n <div className={`${CLASSNAME}__wrapper`}>\n {nameBlock}\n {fieldsBlock}\n </div>\n )}\n {shouldDisplayActions && simpleAction && <div className={`${CLASSNAME}__action`}>{simpleAction}</div>}\n {shouldDisplayActions && multipleActions && (\n <div className={`${CLASSNAME}__actions`}>{multipleActions}</div>\n )}\n </div>\n );\n});\nUserBlock.displayName = COMPONENT_NAME;\nUserBlock.className = CLASSNAME;\nUserBlock.defaultProps = DEFAULT_PROPS;\n"],"names":["COMPONENT_NAME","CLASSNAME","getRootClassName","DEFAULT_PROPS","orientation","Orientation","horizontal","size","Size","m","theme","Theme","light","UserBlock","forwardRef","props","ref","avatarProps","className","fields","multipleActions","name","onClick","onMouseEnter","onMouseLeave","simpleAction","linkProps","linkAs","forwardedProps","componentSize","vertical","l","shouldDisplayActions","isLink","Boolean","href","isClickable","nameBlock","React","useMemo","isEmpty","nameClassName","classNames","handleBasicClasses","prefix","renderLink","fieldsBlock","s","map","aField","idx","displayName","defaultProps"],"mappings":"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"}
@@ -10,6 +10,7 @@ import 'lodash/noop';
10
10
  import './constants.js';
11
11
  import './mergeRefs.js';
12
12
  import './Avatar2.js';
13
+ import './renderLink.js';
13
14
  import './Icon2.js';
14
15
  import './clamp.js';
15
16
  import './Thumbnail2.js';
@@ -1 +1 @@
1
- {"version":3,"file":"user-block.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"user-block.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -7,8 +7,8 @@
7
7
  },
8
8
  "dependencies": {
9
9
  "@juggle/resize-observer": "^3.2.0",
10
- "@lumx/core": "^2.1.4",
11
- "@lumx/icons": "^2.1.4",
10
+ "@lumx/core": "^2.1.5",
11
+ "@lumx/icons": "^2.1.5",
12
12
  "@popperjs/core": "^2.5.4",
13
13
  "body-scroll-lock": "^3.1.5",
14
14
  "classnames": "^2.2.6",
@@ -78,7 +78,6 @@
78
78
  "ts-jest": "^26.2.0",
79
79
  "tsconfig-paths-webpack-plugin": "^3.2.0",
80
80
  "typescript": "^4.1.2",
81
- "version-changelog": "^3.1.1",
82
81
  "yargs": "^15.4.1",
83
82
  "yarn": "^1.19.1"
84
83
  },
@@ -123,9 +122,6 @@
123
122
  "storybook": "start-storybook -s ../site-demo/static/ -p 9000"
124
123
  },
125
124
  "sideEffects": false,
126
- "version": "2.1.4",
127
- "resolutions": {
128
- "**/style-loader": "^1.0.0"
129
- },
130
- "gitHead": "de78ddf378468c55a56149bcb4568e66a9a88f32"
125
+ "version": "2.1.5",
126
+ "gitHead": "ad5125402db165c2a7d37fb72327153b80193759"
131
127
  }
@@ -36,6 +36,10 @@ export interface AvatarProps extends GenericProps {
36
36
  ThumbnailProps,
37
37
  'image' | 'alt' | 'size' | 'theme' | 'align' | 'fillHeight' | 'variant' | 'aspectRatio'
38
38
  >;
39
+ /** Props to pass to the link wrapping the thumbnail. */
40
+ linkProps?: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>;
41
+ /** Custom react component for the link (can be used to inject react router Link). */
42
+ linkAs?: 'a' | any;
39
43
  }
40
44
 
41
45
  /**
@@ -75,6 +79,8 @@ export const Avatar: Comp<AvatarProps, HTMLDivElement> = forwardRef((props, ref)
75
79
  size,
76
80
  theme,
77
81
  thumbnailProps,
82
+ linkProps,
83
+ linkAs,
78
84
  ...forwardedProps
79
85
  } = props;
80
86
 
@@ -85,6 +91,8 @@ export const Avatar: Comp<AvatarProps, HTMLDivElement> = forwardRef((props, ref)
85
91
  className={classNames(className, handleBasicClasses({ prefix: CLASSNAME, size, theme }))}
86
92
  >
87
93
  <Thumbnail
94
+ linkProps={linkProps}
95
+ linkAs={linkAs}
88
96
  className={`${CLASSNAME}__thumbnail`}
89
97
  onClick={onClick}
90
98
  onKeyPress={onKeyPress}
@@ -40,7 +40,11 @@ export const DragHandle: Comp<DragHandleProps, HTMLDivElement> = forwardRef((pro
40
40
  {...forwardedProps}
41
41
  className={classNames(className, handleBasicClasses({ prefix: CLASSNAME, theme }))}
42
42
  >
43
- <Icon icon={mdiDragVertical} color={theme === Theme.dark ? ColorPalette.light : undefined} size={Size.xs} />
43
+ <Icon
44
+ icon={mdiDragVertical}
45
+ color={theme === Theme.dark ? ColorPalette.light : ColorPalette.dark}
46
+ size={Size.xs}
47
+ />
44
48
  </div>
45
49
  );
46
50
  });
@@ -18,6 +18,7 @@ import { boolean, select, text } from '@storybook/addon-knobs';
18
18
  import { enumKnob } from '@lumx/react/stories/knobs/enumKnob';
19
19
  import { focusKnob } from '@lumx/react/stories/knobs/focusKnob';
20
20
  import { sizeKnob } from '@lumx/react/stories/knobs/sizeKnob';
21
+ import classNames from 'classnames';
21
22
 
22
23
  export default { title: 'LumX components/thumbnail/Thumbnail' };
23
24
 
@@ -25,6 +26,26 @@ export const Default = () => <Thumbnail alt="Image alt text" image={imageKnob()}
25
26
 
26
27
  export const Clickable = () => <Thumbnail alt="Click me" image={imageKnob()} size={Size.xxl} onClick={console.log} />;
27
28
 
29
+ export const ClickableLink = () => (
30
+ <Thumbnail alt="Click me" image={imageKnob()} size={Size.xxl} linkProps={{ href: 'https://google.fr' }} />
31
+ );
32
+
33
+ const CustomLinkComponent = (props: any) => (
34
+ <a {...props} className={classNames('custom-link-component', props.className)}>
35
+ {props.children}
36
+ </a>
37
+ );
38
+
39
+ export const ClickableCustomLink = () => (
40
+ <Thumbnail
41
+ alt="Click me"
42
+ image={imageKnob()}
43
+ size={Size.xxl}
44
+ linkAs={CustomLinkComponent}
45
+ linkProps={{ href: 'https://google.fr', className: 'custom-class-name' }}
46
+ />
47
+ );
48
+
28
49
  export const DefaultFallback = () => <Thumbnail alt="foo" image="foo" />;
29
50
 
30
51
  export const IconFallback = () => <Thumbnail alt="foo" image="foo" fallback={mdiAbTesting} />;
@@ -5,7 +5,16 @@ import 'jest-enzyme';
5
5
  import { commonTestsSuite, itShouldRenderStories } from '@lumx/react/testing/utils';
6
6
 
7
7
  import { Thumbnail, ThumbnailProps } from './Thumbnail';
8
- import { Clickable, CustomFallback, Default, DefaultFallback, IconFallback, WithBadge } from './Thumbnail.stories';
8
+ import {
9
+ Clickable,
10
+ ClickableCustomLink,
11
+ ClickableLink,
12
+ CustomFallback,
13
+ Default,
14
+ DefaultFallback,
15
+ IconFallback,
16
+ WithBadge,
17
+ } from './Thumbnail.stories';
9
18
 
10
19
  const CLASSNAME = Thumbnail.className as string;
11
20
 
@@ -22,7 +31,16 @@ describe(`<${Thumbnail.displayName}>`, () => {
22
31
  // 1. Test render via snapshot.
23
32
  describe('Snapshots and structure', () => {
24
33
  itShouldRenderStories(
25
- { Default, Clickable, DefaultFallback, CustomFallback, IconFallback, WithBadge },
34
+ {
35
+ Default,
36
+ Clickable,
37
+ ClickableLink,
38
+ ClickableCustomLink,
39
+ DefaultFallback,
40
+ CustomFallback,
41
+ IconFallback,
42
+ WithBadge,
43
+ },
26
44
  Thumbnail,
27
45
  );
28
46
  });
@@ -20,7 +20,6 @@ import { isInternetExplorer } from '@lumx/react/utils/isInternetExplorer';
20
20
  import { mergeRefs } from '@lumx/react/utils/mergeRefs';
21
21
  import { useFocusPoint } from '@lumx/react/components/thumbnail/useFocusPoint';
22
22
  import { useImageLoad } from '@lumx/react/components/thumbnail/useImageLoad';
23
- import { useClickable } from '@lumx/react/components/thumbnail/useClickable';
24
23
  import { FocusPoint, ThumbnailSize, ThumbnailVariant } from './types';
25
24
 
26
25
  type ImgHTMLProps = ImgHTMLAttributes<HTMLImageElement>;
@@ -63,6 +62,10 @@ export interface ThumbnailProps extends GenericProps {
63
62
  theme?: Theme;
64
63
  /** Variant of the component. */
65
64
  variant?: ThumbnailVariant;
65
+ /** Props to pass to the link wrapping the thumbnail. */
66
+ linkProps?: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>;
67
+ /** Custom react component for the link (can be used to inject react router Link). */
68
+ linkAs?: 'a' | any;
66
69
  }
67
70
 
68
71
  /**
@@ -109,6 +112,8 @@ export const Thumbnail: Comp<ThumbnailProps> = forwardRef((props, ref) => {
109
112
  size,
110
113
  theme,
111
114
  variant,
115
+ linkProps,
116
+ linkAs,
112
117
  ...forwardedProps
113
118
  } = props;
114
119
  const imgRef = useRef<HTMLImageElement>(null);
@@ -119,24 +124,44 @@ export const Thumbnail: Comp<ThumbnailProps> = forwardRef((props, ref) => {
119
124
  const isLoading = loadingState === 'isLoading';
120
125
 
121
126
  const [wrapper, setWrapper] = useState<HTMLElement>();
122
- const wrapperProps: any = {
123
- ...forwardedProps,
124
- ref: mergeRefs(setWrapper, ref),
125
- className: classNames(
126
- className,
127
- handleBasicClasses({ align, aspectRatio, prefix: CLASSNAME, size, theme, variant, hasBadge: !!badge }),
128
- isLoading && wrapper?.getBoundingClientRect()?.height && 'lumx-color-background-dark-L6',
129
- fillHeight && `${CLASSNAME}--fill-height`,
130
- ),
131
- // Handle clickable Thumbnail a11y.
132
- ...useClickable(props),
133
- };
127
+
128
+ const isLink = Boolean(linkProps?.href || linkAs);
129
+ const isButton = !!forwardedProps.onClick;
130
+ const isClickable = isButton || isLink;
131
+
132
+ let Wrapper: any = 'div';
133
+ const wrapperProps = { ...forwardedProps };
134
+ if (isLink) {
135
+ Wrapper = linkAs || 'a';
136
+ Object.assign(wrapperProps, linkProps);
137
+ } else if (isButton) {
138
+ Wrapper = 'button';
139
+ }
134
140
 
135
141
  // Update img style according to focus point and aspect ratio.
136
142
  const style = useFocusPoint({ image, focusPoint, aspectRatio, imgRef, loadingState, wrapper });
137
143
 
138
144
  return (
139
- <div {...wrapperProps}>
145
+ <Wrapper
146
+ {...wrapperProps}
147
+ ref={mergeRefs(setWrapper, ref) as any}
148
+ className={classNames(
149
+ linkProps?.className,
150
+ className,
151
+ handleBasicClasses({
152
+ align,
153
+ aspectRatio,
154
+ prefix: CLASSNAME,
155
+ size,
156
+ theme,
157
+ variant,
158
+ isClickable,
159
+ hasBadge: !!badge,
160
+ }),
161
+ isLoading && wrapper?.getBoundingClientRect()?.height && 'lumx-color-background-dark-L6',
162
+ fillHeight && `${CLASSNAME}--fill-height`,
163
+ )}
164
+ >
140
165
  <div
141
166
  className={`${CLASSNAME}__background`}
142
167
  style={{
@@ -169,7 +194,7 @@ export const Thumbnail: Comp<ThumbnailProps> = forwardRef((props, ref) => {
169
194
  ))}
170
195
  {badge &&
171
196
  React.cloneElement(badge, { className: classNames(`${CLASSNAME}__badge`, badge.props.className) })}
172
- </div>
197
+ </Wrapper>
173
198
  );
174
199
  });
175
200
  Thumbnail.displayName = COMPONENT_NAME;
@@ -1,12 +1,9 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`<Thumbnail> Snapshots and structure should render story 'Clickable' 1`] = `
4
- <div
5
- className="lumx-thumbnail lumx-thumbnail--size-xxl lumx-thumbnail--theme-light"
4
+ <button
5
+ className="lumx-thumbnail lumx-thumbnail--size-xxl lumx-thumbnail--theme-light lumx-thumbnail--is-clickable"
6
6
  onClick={[Function]}
7
- onKeyPress={[Function]}
8
- role="button"
9
- tabIndex={0}
10
7
  >
11
8
  <div
12
9
  className="lumx-thumbnail__background"
@@ -25,7 +22,57 @@ exports[`<Thumbnail> Snapshots and structure should render story 'Clickable' 1`]
25
22
  style={Object {}}
26
23
  />
27
24
  </div>
28
- </div>
25
+ </button>
26
+ `;
27
+
28
+ exports[`<Thumbnail> Snapshots and structure should render story 'ClickableCustomLink' 1`] = `
29
+ <CustomLinkComponent
30
+ className="custom-class-name lumx-thumbnail lumx-thumbnail--size-xxl lumx-thumbnail--theme-light lumx-thumbnail--is-clickable"
31
+ href="https://google.fr"
32
+ >
33
+ <div
34
+ className="lumx-thumbnail__background"
35
+ style={
36
+ Object {
37
+ "display": undefined,
38
+ "visibility": "hidden",
39
+ }
40
+ }
41
+ >
42
+ <img
43
+ alt="Click me"
44
+ className="lumx-thumbnail__image"
45
+ loading="lazy"
46
+ src="landscape1.jpg"
47
+ style={Object {}}
48
+ />
49
+ </div>
50
+ </CustomLinkComponent>
51
+ `;
52
+
53
+ exports[`<Thumbnail> Snapshots and structure should render story 'ClickableLink' 1`] = `
54
+ <a
55
+ className="lumx-thumbnail lumx-thumbnail--size-xxl lumx-thumbnail--theme-light lumx-thumbnail--is-clickable"
56
+ href="https://google.fr"
57
+ >
58
+ <div
59
+ className="lumx-thumbnail__background"
60
+ style={
61
+ Object {
62
+ "display": undefined,
63
+ "visibility": "hidden",
64
+ }
65
+ }
66
+ >
67
+ <img
68
+ alt="Click me"
69
+ className="lumx-thumbnail__image"
70
+ loading="lazy"
71
+ src="landscape1.jpg"
72
+ style={Object {}}
73
+ />
74
+ </div>
75
+ </a>
29
76
  `;
30
77
 
31
78
  exports[`<Thumbnail> Snapshots and structure should render story 'CustomFallback' 1`] = `
@@ -6,11 +6,12 @@ import { UserBlock } from './UserBlock';
6
6
 
7
7
  export default { title: 'LumX components/user-block/UserBlock' };
8
8
 
9
- export const Sizes = () => {
9
+ export const Sizes = ({ theme }: any) => {
10
10
  const logAction = (action: string) => () => console.log(action);
11
11
  return [Size.s, Size.m, Size.l].map((size: any) => (
12
12
  <div className="demo-grid" key={size}>
13
13
  <UserBlock
14
+ theme={theme}
14
15
  name="Emmitt O. Lum"
15
16
  fields={['Creative developer', 'Denpasar']}
16
17
  avatarProps={{ image: avatarImageKnob(), alt: 'Avatar' }}
@@ -23,11 +24,31 @@ export const Sizes = () => {
23
24
  ));
24
25
  };
25
26
 
26
- export const WithBadge = () => {
27
+ export const WithLinks = ({ theme }: any) => {
28
+ const logAction = (action: string) => () => console.log(action);
29
+ return [Size.s, Size.m, Size.l].map((size: any) => (
30
+ <div className="demo-grid" key={size}>
31
+ <UserBlock
32
+ theme={theme}
33
+ name="Emmitt O. Lum"
34
+ linkProps={{ href: 'https://www.lumapps.com', target: '_blank' }}
35
+ fields={['Creative developer', 'Denpasar']}
36
+ avatarProps={{ image: avatarImageKnob(), alt: 'Avatar' }}
37
+ size={size}
38
+ onMouseEnter={logAction('Mouse entered')}
39
+ onMouseLeave={logAction('Mouse left')}
40
+ onClick={logAction('UserBlock clicked')}
41
+ />
42
+ </div>
43
+ ));
44
+ };
45
+
46
+ export const WithBadge = ({ theme }: any) => {
27
47
  const logAction = (action: string) => () => console.log(action);
28
48
  return (
29
49
  <div className="demo-grid">
30
50
  <UserBlock
51
+ theme={theme}
31
52
  name="Emmitt O. Lum"
32
53
  fields={['Creative developer', 'Denpasar']}
33
54
  avatarProps={{
@@ -42,19 +63,19 @@ export const WithBadge = () => {
42
63
  size={Size.m}
43
64
  onMouseEnter={logAction('Mouse entered')}
44
65
  onMouseLeave={logAction('Mouse left')}
45
- onClick={logAction('UserBlock clicked')}
46
66
  />
47
67
  </div>
48
68
  );
49
69
  };
50
70
 
51
- export const InList = () => {
71
+ export const InList = ({ theme }: any) => {
52
72
  const logAction = (action: string) => () => console.log(action);
53
73
  return (
54
74
  <div className="demo-grid">
55
75
  <List itemPadding={Size.big}>
56
76
  <ListItem className="lumx-color-background-dark-L6" size={Size.big}>
57
77
  <UserBlock
78
+ theme={theme}
58
79
  name="Emmitt O. Lum"
59
80
  fields={['Creative developer', 'Denpasar']}
60
81
  avatarProps={{
@@ -74,6 +95,7 @@ export const InList = () => {
74
95
  </ListItem>
75
96
  <ListItem className="lumx-color-background-dark-L6" size={Size.big}>
76
97
  <UserBlock
98
+ theme={theme}
77
99
  name="Emmitt O. Lum"
78
100
  fields={['Creative developer', 'Denpasar']}
79
101
  avatarProps={{
@@ -93,6 +115,7 @@ export const InList = () => {
93
115
  </ListItem>
94
116
  <ListItem className="lumx-color-background-dark-L6" size={Size.big}>
95
117
  <UserBlock
118
+ theme={theme}
96
119
  name="Emmitt O. Lum"
97
120
  fields={['Creative developer', 'Denpasar']}
98
121
  avatarProps={{
@@ -5,6 +5,8 @@ import classNames from 'classnames';
5
5
  import { Avatar, Orientation, Size, Theme } from '@lumx/react';
6
6
 
7
7
  import { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';
8
+ import { isEmpty } from 'lodash';
9
+ import { renderLink } from '@lumx/react/utils/renderLink';
8
10
  import { AvatarProps } from '../avatar/Avatar';
9
11
 
10
12
  /**
@@ -18,6 +20,10 @@ export type UserBlockSize = Extract<Size, 's' | 'm' | 'l'>;
18
20
  export interface UserBlockProps extends GenericProps {
19
21
  /** Props to pass to the avatar. */
20
22
  avatarProps?: AvatarProps;
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;
21
27
  /** Simple action toolbar content. */
22
28
  simpleAction?: ReactNode;
23
29
  /** Multiple action toolbar content. */
@@ -80,6 +86,8 @@ export const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props
80
86
  simpleAction,
81
87
  size,
82
88
  theme,
89
+ linkProps,
90
+ linkAs,
83
91
  ...forwardedProps
84
92
  } = props;
85
93
  let componentSize = size;
@@ -91,12 +99,29 @@ export const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props
91
99
 
92
100
  const shouldDisplayActions: boolean = orientation === Orientation.vertical;
93
101
 
94
- const nameBlock: ReactNode = name && (
95
- // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-noninteractive-tabindex,jsx-a11y/no-static-element-interactions
96
- <span className={`${CLASSNAME}__name`} onClick={onClick} tabIndex={onClick ? 0 : -1}>
97
- {name}
98
- </span>
99
- );
102
+ const isLink = Boolean(linkProps?.href || linkAs);
103
+ const isClickable = !!onClick || isLink;
104
+
105
+ const nameBlock: ReactNode = React.useMemo(() => {
106
+ if (isEmpty(name)) {
107
+ return null;
108
+ }
109
+ const nameClassName = classNames(
110
+ handleBasicClasses({ prefix: `${CLASSNAME}__name`, isClickable }),
111
+ isLink && linkProps?.className,
112
+ );
113
+ if (isLink) {
114
+ return renderLink({ ...linkProps, linkAs, className: nameClassName }, name);
115
+ }
116
+ if (onClick) {
117
+ return (
118
+ <button onClick={onClick} type="button" className={nameClassName}>
119
+ {name}
120
+ </button>
121
+ );
122
+ }
123
+ return <span className={nameClassName}>{name}</span>;
124
+ }, [isClickable, isLink, linkAs, linkProps, name, onClick]);
100
125
 
101
126
  const fieldsBlock: ReactNode = fields && componentSize !== Size.s && (
102
127
  <div className={`${CLASSNAME}__fields`}>
@@ -114,21 +139,20 @@ export const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props
114
139
  {...forwardedProps}
115
140
  className={classNames(
116
141
  className,
117
- handleBasicClasses({ prefix: CLASSNAME, orientation, size: componentSize, theme }),
142
+ handleBasicClasses({ prefix: CLASSNAME, orientation, size: componentSize, theme, isClickable }),
118
143
  )}
119
144
  onMouseLeave={onMouseLeave}
120
145
  onMouseEnter={onMouseEnter}
121
146
  >
122
147
  {avatarProps && (
123
- <div className={`${CLASSNAME}__avatar`}>
124
- <Avatar
125
- {...avatarProps}
126
- size={componentSize}
127
- onClick={onClick}
128
- tabIndex={onClick ? 0 : -1}
129
- theme={theme}
130
- />
131
- </div>
148
+ <Avatar
149
+ linkProps={linkProps}
150
+ {...avatarProps}
151
+ className={classNames(`${CLASSNAME}__avatar`, avatarProps.className)}
152
+ size={componentSize}
153
+ onClick={onClick}
154
+ theme={theme}
155
+ />
132
156
  )}
133
157
  {(fields || name) && (
134
158
  <div className={`${CLASSNAME}__wrapper`}>