@lumx/react 2.2.17 → 2.2.19
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/SideNavigationItem.js +8 -4
- package/esm/_internal/SideNavigationItem.js.map +1 -1
- package/esm/_internal/Tooltip2.js +10 -12
- package/esm/_internal/Tooltip2.js.map +1 -1
- package/esm/_internal/UserBlock.js +9 -2
- package/esm/_internal/UserBlock.js.map +1 -1
- package/esm/_internal/useFocusTrap.js +22 -13
- package/esm/_internal/useFocusTrap.js.map +1 -1
- package/esm/_internal/user-block.js +1 -0
- package/esm/_internal/user-block.js.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/package.json +5 -5
- package/src/components/dialog/Dialog.stories.tsx +4 -1
- package/src/components/dialog/__snapshots__/Dialog.test.tsx.snap +85 -77
- package/src/components/side-navigation/SideNavigation.stories.tsx +26 -0
- package/src/components/side-navigation/SideNavigationItem.test.tsx +19 -2
- package/src/components/side-navigation/SideNavigationItem.tsx +10 -2
- package/src/components/side-navigation/__snapshots__/SideNavigationItem.test.tsx.snap +1 -1
- package/src/components/tooltip/Tooltip.tsx +2 -5
- package/src/components/tooltip/useTooltipOpen.tsx +7 -4
- package/src/components/user-block/UserBlock.stories.tsx +4 -4
- package/src/components/user-block/UserBlock.tsx +9 -3
- package/src/components/user-block/__snapshots__/UserBlock.test.tsx.snap +51 -8
- package/src/hooks/useBooleanState.tsx +4 -10
- package/src/hooks/useFocusTrap.ts +2 -28
- package/src/stories/generated/Dialog/Demos.stories.tsx +1 -0
- package/src/utils/focus/getFirstAndLastFocusable.test.ts +128 -0
- package/src/utils/focus/getFirstAndLastFocusable.ts +27 -0
- package/types.d.ts +6 -1
|
@@ -65,7 +65,8 @@ var CLASSNAME$1 = getRootClassName(COMPONENT_NAME$1);
|
|
|
65
65
|
*/
|
|
66
66
|
|
|
67
67
|
var DEFAULT_PROPS = {
|
|
68
|
-
emphasis: Emphasis.high
|
|
68
|
+
emphasis: Emphasis.high,
|
|
69
|
+
closeMode: 'unmount'
|
|
69
70
|
};
|
|
70
71
|
/**
|
|
71
72
|
* SideNavigationItem component.
|
|
@@ -88,17 +89,20 @@ var SideNavigationItem = forwardRef(function (props, ref) {
|
|
|
88
89
|
onActionClick = props.onActionClick,
|
|
89
90
|
onClick = props.onClick,
|
|
90
91
|
toggleButtonProps = props.toggleButtonProps,
|
|
91
|
-
|
|
92
|
+
_props$closeMode = props.closeMode,
|
|
93
|
+
closeMode = _props$closeMode === void 0 ? 'unmount' : _props$closeMode,
|
|
94
|
+
forwardedProps = _objectWithoutProperties(props, ["children", "className", "emphasis", "icon", "isOpen", "isSelected", "label", "linkAs", "linkProps", "onActionClick", "onClick", "toggleButtonProps", "closeMode"]);
|
|
92
95
|
|
|
93
96
|
var content = children && Children.toArray(children).filter(isComponent(SideNavigationItem));
|
|
94
97
|
var hasContent = !isEmpty(content);
|
|
95
98
|
var shouldSplitActions = Boolean(onActionClick);
|
|
99
|
+
var showChildren = hasContent && isOpen;
|
|
96
100
|
return React.createElement("li", _extends({
|
|
97
101
|
ref: ref
|
|
98
102
|
}, forwardedProps, {
|
|
99
103
|
className: classnames(className, handleBasicClasses({
|
|
100
104
|
emphasis: emphasis,
|
|
101
|
-
isOpen:
|
|
105
|
+
isOpen: showChildren,
|
|
102
106
|
isSelected: isSelected,
|
|
103
107
|
prefix: CLASSNAME$1
|
|
104
108
|
}))
|
|
@@ -135,7 +139,7 @@ var SideNavigationItem = forwardRef(function (props, ref) {
|
|
|
135
139
|
className: "".concat(CLASSNAME$1, "__chevron"),
|
|
136
140
|
icon: isOpen ? mdiChevronUp : mdiChevronDown,
|
|
137
141
|
size: Size.xs
|
|
138
|
-
})),
|
|
142
|
+
})), (closeMode === 'hide' || showChildren) && React.createElement("ul", {
|
|
139
143
|
className: "".concat(CLASSNAME$1, "__children")
|
|
140
144
|
}, content));
|
|
141
145
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SideNavigationItem.js","sources":["../../../src/components/side-navigation/SideNavigation.tsx","../../../src/components/side-navigation/SideNavigationItem.tsx"],"sourcesContent":["import React, { Children, forwardRef, ReactNode } from 'react';\n\nimport classNames from 'classnames';\n\nimport { SideNavigationItem, Theme } from '@lumx/react';\n\nimport { Comp, GenericProps, getRootClassName, handleBasicClasses, isComponent } from '@lumx/react/utils';\n\n/**\n * Defines the props of the component.\n */\nexport interface SideNavigationProps extends GenericProps {\n /** SideNavigationItem elements. */\n children: ReactNode;\n /** Theme adapting the component to light or dark background. */\n theme?: Theme;\n}\n\n/**\n * Component display name.\n */\nconst COMPONENT_NAME = 'SideNavigation';\n\n/**\n * Component default class name and class prefix.\n */\nconst CLASSNAME = getRootClassName(COMPONENT_NAME);\n\n/**\n * SideNavigation component.\n *\n * @param props Component props.\n * @param ref Component ref.\n * @return React element.\n */\nexport const SideNavigation: Comp<SideNavigationProps, HTMLUListElement> = forwardRef((props, ref) => {\n const { children, className, theme, ...forwardedProps } = props;\n const content = Children.toArray(children).filter(isComponent(SideNavigationItem));\n\n return (\n <ul\n ref={ref}\n {...forwardedProps}\n className={classNames(\n className,\n theme === Theme.dark && 'lumx-color-font-light-N',\n handleBasicClasses({ prefix: CLASSNAME }),\n )}\n >\n {content}\n </ul>\n );\n});\nSideNavigation.displayName = COMPONENT_NAME;\nSideNavigation.className = CLASSNAME;\n","import React, { Children, forwardRef, ReactNode } from 'react';\n\nimport classNames from 'classnames';\nimport isEmpty from 'lodash/isEmpty';\n\nimport { mdiChevronDown, mdiChevronUp } from '@lumx/icons';\n\nimport { Emphasis, Icon, Size, IconButton, IconButtonProps } from '@lumx/react';\n\nimport {\n Callback,\n Comp,\n GenericProps,\n getRootClassName,\n handleBasicClasses,\n isComponent,\n onEnterPressed,\n} from '@lumx/react/utils';\nimport { renderLink } from '@lumx/react/utils/renderLink';\n\n/**\n * Defines the props of the component.\n */\nexport interface SideNavigationItemProps extends GenericProps {\n /** SideNavigationItem elements. */\n children?: ReactNode;\n /** Emphasis variant. */\n emphasis?: Emphasis;\n /** Label content. */\n label: string | ReactNode;\n /** Icon (SVG path). */\n icon?: string;\n /** Whether the component is open or not. */\n isOpen?: boolean;\n /** Whether the component is selected or not. */\n isSelected?: boolean;\n /** Custom react component for the link (can be used to inject react router Link). */\n linkAs?: 'a' | any;\n /** Props to pass to the link (minus those already set by the SideNavigationItem props). */\n linkProps?: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>;\n /** Props to pass to the toggle button (minus those already set by the SideNavigationItem props). */\n toggleButtonProps: Pick<IconButtonProps, 'label'> &\n Omit<IconButtonProps, 'label' | 'onClick' | 'icon' | 'emphasis' | 'color' | 'size'>;\n /** On action button click callback. */\n onActionClick?(evt: React.MouseEvent): void;\n /** On click callback. */\n onClick?(evt: React.MouseEvent): void;\n}\n\n/**\n * Component display name.\n */\nconst COMPONENT_NAME = 'SideNavigationItem';\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<SideNavigationItemProps> = {\n emphasis: Emphasis.high,\n};\n\n/**\n * SideNavigationItem component.\n *\n * @param props Component props.\n * @param ref Component ref.\n * @return React element.\n */\nexport const SideNavigationItem: Comp<SideNavigationItemProps, HTMLLIElement> = forwardRef((props, ref) => {\n const {\n children,\n className,\n emphasis,\n icon,\n isOpen,\n isSelected,\n label,\n linkAs,\n linkProps,\n onActionClick,\n onClick,\n toggleButtonProps,\n ...forwardedProps\n } = props;\n\n const content = children && Children.toArray(children).filter(isComponent(SideNavigationItem));\n const hasContent = !isEmpty(content);\n const shouldSplitActions = Boolean(onActionClick);\n\n return (\n <li\n ref={ref}\n {...forwardedProps}\n className={classNames(\n className,\n handleBasicClasses({\n emphasis,\n isOpen,\n isSelected,\n prefix: CLASSNAME,\n }),\n )}\n >\n {shouldSplitActions ? (\n <div className={`${CLASSNAME}__wrapper`}>\n {renderLink(\n {\n linkAs,\n ...linkProps,\n className: `${CLASSNAME}__link`,\n onClick,\n tabIndex: 0,\n },\n icon && <Icon className={`${CLASSNAME}__icon`} icon={icon} size={Size.xs} />,\n <span>{label}</span>,\n )}\n\n <IconButton\n {...toggleButtonProps}\n className={`${CLASSNAME}__toggle`}\n icon={isOpen ? mdiChevronUp : mdiChevronDown}\n size={Size.m}\n emphasis={Emphasis.low}\n onClick={onActionClick}\n />\n </div>\n ) : (\n renderLink(\n {\n linkAs,\n ...linkProps,\n className: `${CLASSNAME}__link`,\n tabIndex: 0,\n onClick,\n onKeyDown: onClick ? onEnterPressed(onClick as Callback) : undefined,\n },\n icon && <Icon className={`${CLASSNAME}__icon`} icon={icon} size={Size.xs} />,\n <span>{label}</span>,\n hasContent && (\n <Icon\n className={`${CLASSNAME}__chevron`}\n icon={isOpen ? mdiChevronUp : mdiChevronDown}\n size={Size.xs}\n />\n ),\n )\n )}\n\n {hasContent && isOpen && <ul className={`${CLASSNAME}__children`}>{content}</ul>}\n </li>\n );\n});\nSideNavigationItem.displayName = COMPONENT_NAME;\nSideNavigationItem.className = CLASSNAME;\nSideNavigationItem.defaultProps = DEFAULT_PROPS;\n"],"names":["COMPONENT_NAME","CLASSNAME","getRootClassName","SideNavigation","forwardRef","props","ref","children","className","theme","forwardedProps","content","Children","toArray","filter","isComponent","SideNavigationItem","classNames","Theme","dark","handleBasicClasses","prefix","displayName","DEFAULT_PROPS","emphasis","Emphasis","high","icon","isOpen","isSelected","label","linkAs","linkProps","onActionClick","onClick","toggleButtonProps","hasContent","isEmpty","shouldSplitActions","Boolean","renderLink","tabIndex","Size","xs","mdiChevronUp","mdiChevronDown","m","low","onKeyDown","onEnterPressed","undefined","defaultProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SideNavigationItem.js","sources":["../../../src/components/side-navigation/SideNavigation.tsx","../../../src/components/side-navigation/SideNavigationItem.tsx"],"sourcesContent":["import React, { Children, forwardRef, ReactNode } from 'react';\n\nimport classNames from 'classnames';\n\nimport { SideNavigationItem, Theme } from '@lumx/react';\n\nimport { Comp, GenericProps, getRootClassName, handleBasicClasses, isComponent } from '@lumx/react/utils';\n\n/**\n * Defines the props of the component.\n */\nexport interface SideNavigationProps extends GenericProps {\n /** SideNavigationItem elements. */\n children: ReactNode;\n /** Theme adapting the component to light or dark background. */\n theme?: Theme;\n}\n\n/**\n * Component display name.\n */\nconst COMPONENT_NAME = 'SideNavigation';\n\n/**\n * Component default class name and class prefix.\n */\nconst CLASSNAME = getRootClassName(COMPONENT_NAME);\n\n/**\n * SideNavigation component.\n *\n * @param props Component props.\n * @param ref Component ref.\n * @return React element.\n */\nexport const SideNavigation: Comp<SideNavigationProps, HTMLUListElement> = forwardRef((props, ref) => {\n const { children, className, theme, ...forwardedProps } = props;\n const content = Children.toArray(children).filter(isComponent(SideNavigationItem));\n\n return (\n <ul\n ref={ref}\n {...forwardedProps}\n className={classNames(\n className,\n theme === Theme.dark && 'lumx-color-font-light-N',\n handleBasicClasses({ prefix: CLASSNAME }),\n )}\n >\n {content}\n </ul>\n );\n});\nSideNavigation.displayName = COMPONENT_NAME;\nSideNavigation.className = CLASSNAME;\n","import React, { Children, forwardRef, ReactNode } from 'react';\n\nimport classNames from 'classnames';\nimport isEmpty from 'lodash/isEmpty';\n\nimport { mdiChevronDown, mdiChevronUp } from '@lumx/icons';\n\nimport { Emphasis, Icon, Size, IconButton, IconButtonProps } from '@lumx/react';\n\nimport {\n Callback,\n Comp,\n GenericProps,\n getRootClassName,\n handleBasicClasses,\n isComponent,\n onEnterPressed,\n} from '@lumx/react/utils';\nimport { renderLink } from '@lumx/react/utils/renderLink';\n\n/**\n * Defines the props of the component.\n */\nexport interface SideNavigationItemProps extends GenericProps {\n /** SideNavigationItem elements. */\n children?: ReactNode;\n /** Emphasis variant. */\n emphasis?: Emphasis;\n /** Label content. */\n label: string | ReactNode;\n /** Icon (SVG path). */\n icon?: string;\n /** Whether the component is open or not. */\n isOpen?: boolean;\n /** Whether the component is selected or not. */\n isSelected?: boolean;\n /** Custom react component for the link (can be used to inject react router Link). */\n linkAs?: 'a' | any;\n /** Props to pass to the link (minus those already set by the SideNavigationItem props). */\n linkProps?: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>;\n /** Props to pass to the toggle button (minus those already set by the SideNavigationItem props). */\n toggleButtonProps: Pick<IconButtonProps, 'label'> &\n Omit<IconButtonProps, 'label' | 'onClick' | 'icon' | 'emphasis' | 'color' | 'size'>;\n /**\n * Choose how the children are hidden when closed\n * ('hide' keeps the children in DOM but hide them, 'unmount' remove the children from the DOM).\n */\n closeMode?: 'hide' | 'unmount';\n /** On action button click callback. */\n onActionClick?(evt: React.MouseEvent): void;\n /** On click callback. */\n onClick?(evt: React.MouseEvent): void;\n}\n\n/**\n * Component display name.\n */\nconst COMPONENT_NAME = 'SideNavigationItem';\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<SideNavigationItemProps> = {\n emphasis: Emphasis.high,\n closeMode: 'unmount',\n};\n\n/**\n * SideNavigationItem component.\n *\n * @param props Component props.\n * @param ref Component ref.\n * @return React element.\n */\nexport const SideNavigationItem: Comp<SideNavigationItemProps, HTMLLIElement> = forwardRef((props, ref) => {\n const {\n children,\n className,\n emphasis,\n icon,\n isOpen,\n isSelected,\n label,\n linkAs,\n linkProps,\n onActionClick,\n onClick,\n toggleButtonProps,\n closeMode = 'unmount',\n ...forwardedProps\n } = props;\n\n const content = children && Children.toArray(children).filter(isComponent(SideNavigationItem));\n const hasContent = !isEmpty(content);\n const shouldSplitActions = Boolean(onActionClick);\n const showChildren = hasContent && isOpen;\n\n return (\n <li\n ref={ref}\n {...forwardedProps}\n className={classNames(\n className,\n handleBasicClasses({\n emphasis,\n isOpen: showChildren,\n isSelected,\n prefix: CLASSNAME,\n }),\n )}\n >\n {shouldSplitActions ? (\n <div className={`${CLASSNAME}__wrapper`}>\n {renderLink(\n {\n linkAs,\n ...linkProps,\n className: `${CLASSNAME}__link`,\n onClick,\n tabIndex: 0,\n },\n icon && <Icon className={`${CLASSNAME}__icon`} icon={icon} size={Size.xs} />,\n <span>{label}</span>,\n )}\n\n <IconButton\n {...toggleButtonProps}\n className={`${CLASSNAME}__toggle`}\n icon={isOpen ? mdiChevronUp : mdiChevronDown}\n size={Size.m}\n emphasis={Emphasis.low}\n onClick={onActionClick}\n />\n </div>\n ) : (\n renderLink(\n {\n linkAs,\n ...linkProps,\n className: `${CLASSNAME}__link`,\n tabIndex: 0,\n onClick,\n onKeyDown: onClick ? onEnterPressed(onClick as Callback) : undefined,\n },\n icon && <Icon className={`${CLASSNAME}__icon`} icon={icon} size={Size.xs} />,\n <span>{label}</span>,\n hasContent && (\n <Icon\n className={`${CLASSNAME}__chevron`}\n icon={isOpen ? mdiChevronUp : mdiChevronDown}\n size={Size.xs}\n />\n ),\n )\n )}\n\n {(closeMode === 'hide' || showChildren) && <ul className={`${CLASSNAME}__children`}>{content}</ul>}\n </li>\n );\n});\nSideNavigationItem.displayName = COMPONENT_NAME;\nSideNavigationItem.className = CLASSNAME;\nSideNavigationItem.defaultProps = DEFAULT_PROPS;\n"],"names":["COMPONENT_NAME","CLASSNAME","getRootClassName","SideNavigation","forwardRef","props","ref","children","className","theme","forwardedProps","content","Children","toArray","filter","isComponent","SideNavigationItem","classNames","Theme","dark","handleBasicClasses","prefix","displayName","DEFAULT_PROPS","emphasis","Emphasis","high","closeMode","icon","isOpen","isSelected","label","linkAs","linkProps","onActionClick","onClick","toggleButtonProps","hasContent","isEmpty","shouldSplitActions","Boolean","showChildren","renderLink","tabIndex","Size","xs","mdiChevronUp","mdiChevronDown","m","low","onKeyDown","onEnterPressed","undefined","defaultProps"],"mappings":"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"}
|
|
@@ -136,13 +136,15 @@ function useTooltipOpen(delay, anchorElement) {
|
|
|
136
136
|
var _events$_i = _slicedToArray(_events[_i], 3),
|
|
137
137
|
node = _events$_i[0],
|
|
138
138
|
eventType = _events$_i[1],
|
|
139
|
-
|
|
139
|
+
eventHandler = _events$_i[2];
|
|
140
140
|
|
|
141
|
-
node.addEventListener(eventType,
|
|
141
|
+
node.addEventListener(eventType, eventHandler);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
return function () {
|
|
145
|
-
//
|
|
145
|
+
// Clear pending timers.
|
|
146
|
+
if (timer) clearTimeout(timer); // Detach events.
|
|
147
|
+
|
|
146
148
|
var _iteratorNormalCompletion = true;
|
|
147
149
|
var _didIteratorError = false;
|
|
148
150
|
var _iteratorError = undefined;
|
|
@@ -152,9 +154,9 @@ function useTooltipOpen(delay, anchorElement) {
|
|
|
152
154
|
var _step$value = _slicedToArray(_step.value, 3),
|
|
153
155
|
node = _step$value[0],
|
|
154
156
|
eventType = _step$value[1],
|
|
155
|
-
|
|
157
|
+
eventHandler = _step$value[2];
|
|
156
158
|
|
|
157
|
-
node.removeEventListener(eventType,
|
|
159
|
+
node.removeEventListener(eventType, eventHandler);
|
|
158
160
|
}
|
|
159
161
|
} catch (err) {
|
|
160
162
|
_didIteratorError = true;
|
|
@@ -209,20 +211,16 @@ var ARROW_SIZE = 8;
|
|
|
209
211
|
var Tooltip = forwardRef(function (props, ref) {
|
|
210
212
|
var _ref, _attributes$popper;
|
|
211
213
|
|
|
212
|
-
if (!DOCUMENT) {
|
|
213
|
-
// Can't render in SSR.
|
|
214
|
-
return null;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
214
|
var label = props.label,
|
|
218
215
|
children = props.children,
|
|
219
216
|
className = props.className,
|
|
220
217
|
delay = props.delay,
|
|
221
218
|
placement = props.placement,
|
|
222
219
|
forceOpen = props.forceOpen,
|
|
223
|
-
forwardedProps = _objectWithoutProperties(props, ["label", "children", "className", "delay", "placement", "forceOpen"]);
|
|
220
|
+
forwardedProps = _objectWithoutProperties(props, ["label", "children", "className", "delay", "placement", "forceOpen"]); // Disable in SSR or without a label.
|
|
221
|
+
|
|
224
222
|
|
|
225
|
-
if (!label) {
|
|
223
|
+
if (!DOCUMENT || !label) {
|
|
226
224
|
return React.createElement(React.Fragment, null, children);
|
|
227
225
|
}
|
|
228
226
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip2.js","sources":["../../../src/components/tooltip/useInjectTooltipRef.tsx","../../../src/utils/browserDoesNotSupportHover.ts","../../../src/components/tooltip/useTooltipOpen.tsx","../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import { mergeRefs } from '@lumx/react/utils/mergeRefs';\nimport get from 'lodash/get';\nimport React, { cloneElement, ReactNode, useMemo } from 'react';\n\n/**\n * Add ref and ARIA attribute(s) in tooltip children or wrapped children.\n * Button, IconButton, Icon and React HTML elements don't need to be wrapped but any other kind of children (array, fragment, custom components)\n * will be wrapped in a <span>.\n *\n * @param children Original tooltip anchor.\n * @param setAnchorElement Set tooltip anchor element.\n * @param isOpen Whether the tooltip is open or not.\n * @param id Tooltip id.\n * @return tooltip anchor.\n */\nexport const useInjectTooltipRef = (\n children: ReactNode,\n setAnchorElement: (e: HTMLDivElement) => void,\n isOpen: boolean,\n id: string,\n): ReactNode => {\n return useMemo(() => {\n const ariaProps = { 'aria-describedby': isOpen ? id : undefined };\n if (\n children &&\n get(children, '$$typeof') &&\n get(children, 'props.disabled') !== true &&\n get(children, 'props.isDisabled') !== true\n ) {\n const element = children as any;\n\n return cloneElement(element, {\n ...element.props,\n ...ariaProps,\n ref: mergeRefs(element.ref, setAnchorElement),\n });\n }\n return (\n <div className=\"lumx-tooltip-anchor-wrapper\" ref={setAnchorElement} {...ariaProps}>\n {children}\n </div>\n );\n }, [isOpen, id, children, setAnchorElement]);\n};\n","/** Return true if the browser does not support pointer hover */\nexport const browserDoesNotSupportHover = (): boolean => !!window.matchMedia?.('(hover: none)').matches;\n","import { onEscapePressed } from '@lumx/react/utils';\nimport { useEffect, useState } from 'react';\nimport { browserDoesNotSupportHover } from '@lumx/react/utils/browserDoesNotSupportHover';\nimport { TOOLTIP_HOVER_DELAY, TOOLTIP_LONG_PRESS_DELAY } from '@lumx/react/constants';\n\n/**\n * Hook controlling tooltip visibility using mouse hover the anchor and delay.\n *\n * @param delay Delay in millisecond to display the tooltip.\n * @param anchorElement Tooltip anchor element.\n * @return whether or not to show the tooltip.\n */\nexport function useTooltipOpen(delay: number | undefined, anchorElement: HTMLElement | null): boolean {\n const [isOpen, setIsOpen] = useState(false);\n\n useEffect(() => {\n if (!anchorElement) {\n return undefined;\n }\n let timer: number | undefined;\n let openStartTime: number | undefined;\n let shouldOpen: boolean | undefined;\n\n // Run timer to defer updating the isOpen state.\n const deferUpdate = (duration: number) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n setIsOpen(!!shouldOpen);\n }, duration) as any;\n };\n\n const hoverNotSupported = browserDoesNotSupportHover();\n const hasTouch = 'ontouchstart' in window;\n\n // Adapt open/close delay\n const openDelay = delay || (hoverNotSupported ? TOOLTIP_LONG_PRESS_DELAY.open : TOOLTIP_HOVER_DELAY.open);\n const closeDelay = hoverNotSupported ? TOOLTIP_LONG_PRESS_DELAY.close : TOOLTIP_HOVER_DELAY.close;\n\n // Open (or/and cancel closing) of tooltip.\n const open = () => {\n if (shouldOpen && !timer) return;\n shouldOpen = true;\n openStartTime = Date.now();\n deferUpdate(openDelay);\n };\n\n // Close or cancel opening of tooltip\n const close = (overrideDelay = closeDelay) => {\n if (!shouldOpen && !timer) return;\n shouldOpen = false;\n deferUpdate(overrideDelay);\n };\n const closeImmediately = () => close(0);\n\n /**\n * Handle touchend event\n * If `touchend` comes before the open delay => cancel tooltip (close immediate).\n * Else if `touchend` comes after the open delay => tooltip takes priority, the anchor's default touch end event is prevented.\n */\n const touchEnd = (evt: Event) => {\n if (!openStartTime) return;\n if (Date.now() - openStartTime >= openDelay) {\n // Tooltip take priority, event prevented.\n evt.stopPropagation();\n evt.preventDefault();\n anchorElement.focus();\n // Close with delay.\n close();\n } else {\n // Close immediately.\n closeImmediately();\n }\n };\n\n // Adapt event to browsers with or without `hover` support.\n const events: Array<[Node, Event['type'], any]> = hoverNotSupported\n ? [\n [anchorElement, hasTouch ? 'touchstart' : 'mousedown', open],\n [anchorElement, hasTouch ? 'touchend' : 'mouseup', touchEnd],\n ]\n : [\n [anchorElement, 'mouseenter', open],\n [anchorElement, 'mouseleave', close],\n [anchorElement, 'mouseup', closeImmediately],\n ];\n\n // Events always applied no matter the browser:.\n events.push(\n // Open on focus.\n [anchorElement, 'focusin', open],\n // Close on lost focus.\n [anchorElement, 'focusout', closeImmediately],\n // Close on ESC keydown\n [anchorElement, 'keydown', onEscapePressed(closeImmediately)],\n );\n\n // Attach events\n for (const [node, eventType, evenHandler] of events) {\n node.addEventListener(eventType, evenHandler);\n }\n return () => {\n // Detach events.\n for (const [node, eventType, evenHandler] of events) {\n node.removeEventListener(eventType, evenHandler);\n }\n };\n }, [anchorElement, delay]);\n\n return isOpen;\n}\n","/* eslint-disable react-hooks/rules-of-hooks */\nimport React, { forwardRef, ReactNode, useMemo, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { usePopper } from 'react-popper';\nimport { uid } from 'uid';\n\nimport classNames from 'classnames';\n\nimport { Placement } from '@lumx/react/components/popover/Popover';\n\nimport { DOCUMENT } from '@lumx/react/constants';\n\nimport { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';\nimport { mergeRefs } from '@lumx/react/utils/mergeRefs';\n\nimport { useInjectTooltipRef } from './useInjectTooltipRef';\nimport { useTooltipOpen } from './useTooltipOpen';\n\n/** Position of the tooltip relative to the anchor element. */\nexport type TooltipPlacement = Extract<Placement, 'top' | 'right' | 'bottom' | 'left'>;\n\n/**\n * Defines the props of the component.\n */\nexport interface TooltipProps extends GenericProps {\n /** Anchor (element on which we activate the tooltip). */\n children: ReactNode;\n /** Delay (in ms) before closing the tooltip. */\n delay?: number;\n /** Whether the tooltip is displayed even without the mouse hovering the anchor. */\n forceOpen?: boolean;\n /** Label text. */\n label?: string | null | false;\n /** Placement of the tooltip relative to the anchor. */\n placement?: TooltipPlacement;\n}\n\n/**\n * Component display name.\n */\nconst COMPONENT_NAME = 'Tooltip';\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<TooltipProps> = {\n placement: Placement.BOTTOM,\n};\n\n/**\n * Arrow size (in pixel).\n */\nconst ARROW_SIZE = 8;\n\n/**\n * Tooltip component.\n *\n * @param props Component props.\n * @param ref Component ref.\n * @return React element.\n */\nexport const Tooltip: Comp<TooltipProps, HTMLDivElement> = forwardRef((props, ref) => {\n if (!DOCUMENT) {\n // Can't render in SSR.\n return null;\n }\n const { label, children, className, delay, placement, forceOpen, ...forwardedProps } = props;\n if (!label) {\n return <>{children}</>;\n }\n\n const id = useMemo(() => `tooltip-${uid()}`, []);\n\n const [popperElement, setPopperElement] = useState<null | HTMLElement>(null);\n const [anchorElement, setAnchorElement] = useState<null | HTMLElement>(null);\n const { styles, attributes } = usePopper(anchorElement, popperElement, {\n placement,\n modifiers: [\n {\n name: 'offset',\n options: { offset: [0, ARROW_SIZE] },\n },\n ],\n });\n\n const position = attributes?.popper?.['data-popper-placement'] ?? placement;\n const isOpen = useTooltipOpen(delay, anchorElement) || forceOpen;\n const wrappedChildren = useInjectTooltipRef(children, setAnchorElement, isOpen as boolean, id);\n\n return (\n <>\n {wrappedChildren}\n {isOpen &&\n createPortal(\n <div\n ref={mergeRefs(ref, setPopperElement)}\n {...forwardedProps}\n id={id}\n role=\"tooltip\"\n aria-label={label}\n className={classNames(className, handleBasicClasses({ prefix: CLASSNAME, position }))}\n style={styles.popper}\n {...attributes.popper}\n >\n <div className={`${CLASSNAME}__arrow`} />\n <div className={`${CLASSNAME}__inner`}>\n {label.indexOf('\\n') !== -1\n ? label.split('\\n').map((sentence: string) => <p key={sentence}>{sentence}</p>)\n : label}\n </div>\n </div>,\n document.body,\n )}\n </>\n );\n});\nTooltip.displayName = COMPONENT_NAME;\nTooltip.className = CLASSNAME;\nTooltip.defaultProps = DEFAULT_PROPS;\n"],"names":["useInjectTooltipRef","children","setAnchorElement","isOpen","id","useMemo","ariaProps","undefined","get","element","cloneElement","props","ref","mergeRefs","browserDoesNotSupportHover","window","matchMedia","matches","useTooltipOpen","delay","anchorElement","useState","setIsOpen","useEffect","timer","openStartTime","shouldOpen","deferUpdate","duration","clearTimeout","setTimeout","hoverNotSupported","hasTouch","openDelay","TOOLTIP_LONG_PRESS_DELAY","open","TOOLTIP_HOVER_DELAY","closeDelay","close","Date","now","overrideDelay","closeImmediately","touchEnd","evt","stopPropagation","preventDefault","focus","events","push","onEscapePressed","node","eventType","evenHandler","addEventListener","removeEventListener","COMPONENT_NAME","CLASSNAME","getRootClassName","DEFAULT_PROPS","placement","Placement","BOTTOM","ARROW_SIZE","Tooltip","forwardRef","DOCUMENT","label","className","forceOpen","forwardedProps","uid","popperElement","setPopperElement","usePopper","modifiers","name","options","offset","styles","attributes","position","popper","wrappedChildren","createPortal","classNames","handleBasicClasses","prefix","indexOf","split","map","sentence","document","body","displayName","defaultProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Tooltip2.js","sources":["../../../src/components/tooltip/useInjectTooltipRef.tsx","../../../src/utils/browserDoesNotSupportHover.ts","../../../src/components/tooltip/useTooltipOpen.tsx","../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import { mergeRefs } from '@lumx/react/utils/mergeRefs';\nimport get from 'lodash/get';\nimport React, { cloneElement, ReactNode, useMemo } from 'react';\n\n/**\n * Add ref and ARIA attribute(s) in tooltip children or wrapped children.\n * Button, IconButton, Icon and React HTML elements don't need to be wrapped but any other kind of children (array, fragment, custom components)\n * will be wrapped in a <span>.\n *\n * @param children Original tooltip anchor.\n * @param setAnchorElement Set tooltip anchor element.\n * @param isOpen Whether the tooltip is open or not.\n * @param id Tooltip id.\n * @return tooltip anchor.\n */\nexport const useInjectTooltipRef = (\n children: ReactNode,\n setAnchorElement: (e: HTMLDivElement) => void,\n isOpen: boolean,\n id: string,\n): ReactNode => {\n return useMemo(() => {\n const ariaProps = { 'aria-describedby': isOpen ? id : undefined };\n if (\n children &&\n get(children, '$$typeof') &&\n get(children, 'props.disabled') !== true &&\n get(children, 'props.isDisabled') !== true\n ) {\n const element = children as any;\n\n return cloneElement(element, {\n ...element.props,\n ...ariaProps,\n ref: mergeRefs(element.ref, setAnchorElement),\n });\n }\n return (\n <div className=\"lumx-tooltip-anchor-wrapper\" ref={setAnchorElement} {...ariaProps}>\n {children}\n </div>\n );\n }, [isOpen, id, children, setAnchorElement]);\n};\n","/** Return true if the browser does not support pointer hover */\nexport const browserDoesNotSupportHover = (): boolean => !!window.matchMedia?.('(hover: none)').matches;\n","import { onEscapePressed } from '@lumx/react/utils';\nimport { useEffect, useState } from 'react';\nimport { browserDoesNotSupportHover } from '@lumx/react/utils/browserDoesNotSupportHover';\nimport { TOOLTIP_HOVER_DELAY, TOOLTIP_LONG_PRESS_DELAY } from '@lumx/react/constants';\n\n/**\n * Hook controlling tooltip visibility using mouse hover the anchor and delay.\n *\n * @param delay Delay in millisecond to display the tooltip.\n * @param anchorElement Tooltip anchor element.\n * @return whether or not to show the tooltip.\n */\nexport function useTooltipOpen(delay: number | undefined, anchorElement: HTMLElement | null): boolean {\n const [isOpen, setIsOpen] = useState(false);\n\n useEffect(() => {\n if (!anchorElement) {\n return undefined;\n }\n let timer: number | undefined;\n let openStartTime: number | undefined;\n let shouldOpen: boolean | undefined;\n\n // Run timer to defer updating the isOpen state.\n const deferUpdate = (duration: number) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n setIsOpen(!!shouldOpen);\n }, duration) as any;\n };\n\n const hoverNotSupported = browserDoesNotSupportHover();\n const hasTouch = 'ontouchstart' in window;\n\n // Adapt open/close delay\n const openDelay = delay || (hoverNotSupported ? TOOLTIP_LONG_PRESS_DELAY.open : TOOLTIP_HOVER_DELAY.open);\n const closeDelay = hoverNotSupported ? TOOLTIP_LONG_PRESS_DELAY.close : TOOLTIP_HOVER_DELAY.close;\n\n // Open (or/and cancel closing) of tooltip.\n const open = () => {\n if (shouldOpen && !timer) return;\n shouldOpen = true;\n openStartTime = Date.now();\n deferUpdate(openDelay);\n };\n\n // Close or cancel opening of tooltip\n const close = (overrideDelay = closeDelay) => {\n if (!shouldOpen && !timer) return;\n shouldOpen = false;\n deferUpdate(overrideDelay);\n };\n const closeImmediately = () => close(0);\n\n /**\n * Handle touchend event\n * If `touchend` comes before the open delay => cancel tooltip (close immediate).\n * Else if `touchend` comes after the open delay => tooltip takes priority, the anchor's default touch end event is prevented.\n */\n const touchEnd = (evt: Event) => {\n if (!openStartTime) return;\n if (Date.now() - openStartTime >= openDelay) {\n // Tooltip take priority, event prevented.\n evt.stopPropagation();\n evt.preventDefault();\n anchorElement.focus();\n // Close with delay.\n close();\n } else {\n // Close immediately.\n closeImmediately();\n }\n };\n\n // Adapt event to browsers with or without `hover` support.\n const events: Array<[Node, Event['type'], any]> = hoverNotSupported\n ? [\n [anchorElement, hasTouch ? 'touchstart' : 'mousedown', open],\n [anchorElement, hasTouch ? 'touchend' : 'mouseup', touchEnd],\n ]\n : [\n [anchorElement, 'mouseenter', open],\n [anchorElement, 'mouseleave', close],\n [anchorElement, 'mouseup', closeImmediately],\n ];\n\n // Events always applied no matter the browser:.\n events.push(\n // Open on focus.\n [anchorElement, 'focusin', open],\n // Close on lost focus.\n [anchorElement, 'focusout', closeImmediately],\n // Close on ESC keydown\n [anchorElement, 'keydown', onEscapePressed(closeImmediately)],\n );\n\n // Attach events\n for (const [node, eventType, eventHandler] of events) {\n node.addEventListener(eventType, eventHandler);\n }\n return () => {\n // Clear pending timers.\n if (timer) clearTimeout(timer);\n\n // Detach events.\n for (const [node, eventType, eventHandler] of events) {\n node.removeEventListener(eventType, eventHandler);\n }\n };\n }, [anchorElement, delay]);\n\n return isOpen;\n}\n","/* eslint-disable react-hooks/rules-of-hooks */\nimport React, { forwardRef, ReactNode, useMemo, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { usePopper } from 'react-popper';\nimport { uid } from 'uid';\n\nimport classNames from 'classnames';\n\nimport { Placement } from '@lumx/react/components/popover/Popover';\n\nimport { DOCUMENT } from '@lumx/react/constants';\n\nimport { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';\nimport { mergeRefs } from '@lumx/react/utils/mergeRefs';\n\nimport { useInjectTooltipRef } from './useInjectTooltipRef';\nimport { useTooltipOpen } from './useTooltipOpen';\n\n/** Position of the tooltip relative to the anchor element. */\nexport type TooltipPlacement = Extract<Placement, 'top' | 'right' | 'bottom' | 'left'>;\n\n/**\n * Defines the props of the component.\n */\nexport interface TooltipProps extends GenericProps {\n /** Anchor (element on which we activate the tooltip). */\n children: ReactNode;\n /** Delay (in ms) before closing the tooltip. */\n delay?: number;\n /** Whether the tooltip is displayed even without the mouse hovering the anchor. */\n forceOpen?: boolean;\n /** Label text. */\n label?: string | null | false;\n /** Placement of the tooltip relative to the anchor. */\n placement?: TooltipPlacement;\n}\n\n/**\n * Component display name.\n */\nconst COMPONENT_NAME = 'Tooltip';\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<TooltipProps> = {\n placement: Placement.BOTTOM,\n};\n\n/**\n * Arrow size (in pixel).\n */\nconst ARROW_SIZE = 8;\n\n/**\n * Tooltip component.\n *\n * @param props Component props.\n * @param ref Component ref.\n * @return React element.\n */\nexport const Tooltip: Comp<TooltipProps, HTMLDivElement> = forwardRef((props, ref) => {\n const { label, children, className, delay, placement, forceOpen, ...forwardedProps } = props;\n // Disable in SSR or without a label.\n if (!DOCUMENT || !label) {\n return <>{children}</>;\n }\n\n const id = useMemo(() => `tooltip-${uid()}`, []);\n\n const [popperElement, setPopperElement] = useState<null | HTMLElement>(null);\n const [anchorElement, setAnchorElement] = useState<null | HTMLElement>(null);\n const { styles, attributes } = usePopper(anchorElement, popperElement, {\n placement,\n modifiers: [\n {\n name: 'offset',\n options: { offset: [0, ARROW_SIZE] },\n },\n ],\n });\n\n const position = attributes?.popper?.['data-popper-placement'] ?? placement;\n const isOpen = useTooltipOpen(delay, anchorElement) || forceOpen;\n const wrappedChildren = useInjectTooltipRef(children, setAnchorElement, isOpen as boolean, id);\n\n return (\n <>\n {wrappedChildren}\n {isOpen &&\n createPortal(\n <div\n ref={mergeRefs(ref, setPopperElement)}\n {...forwardedProps}\n id={id}\n role=\"tooltip\"\n aria-label={label}\n className={classNames(className, handleBasicClasses({ prefix: CLASSNAME, position }))}\n style={styles.popper}\n {...attributes.popper}\n >\n <div className={`${CLASSNAME}__arrow`} />\n <div className={`${CLASSNAME}__inner`}>\n {label.indexOf('\\n') !== -1\n ? label.split('\\n').map((sentence: string) => <p key={sentence}>{sentence}</p>)\n : label}\n </div>\n </div>,\n document.body,\n )}\n </>\n );\n});\nTooltip.displayName = COMPONENT_NAME;\nTooltip.className = CLASSNAME;\nTooltip.defaultProps = DEFAULT_PROPS;\n"],"names":["useInjectTooltipRef","children","setAnchorElement","isOpen","id","useMemo","ariaProps","undefined","get","element","cloneElement","props","ref","mergeRefs","browserDoesNotSupportHover","window","matchMedia","matches","useTooltipOpen","delay","anchorElement","useState","setIsOpen","useEffect","timer","openStartTime","shouldOpen","deferUpdate","duration","clearTimeout","setTimeout","hoverNotSupported","hasTouch","openDelay","TOOLTIP_LONG_PRESS_DELAY","open","TOOLTIP_HOVER_DELAY","closeDelay","close","Date","now","overrideDelay","closeImmediately","touchEnd","evt","stopPropagation","preventDefault","focus","events","push","onEscapePressed","node","eventType","eventHandler","addEventListener","removeEventListener","COMPONENT_NAME","CLASSNAME","getRootClassName","DEFAULT_PROPS","placement","Placement","BOTTOM","ARROW_SIZE","Tooltip","forwardRef","label","className","forceOpen","forwardedProps","DOCUMENT","uid","popperElement","setPopperElement","usePopper","modifiers","name","options","offset","styles","attributes","position","popper","wrappedChildren","createPortal","classNames","handleBasicClasses","prefix","indexOf","split","map","sentence","document","body","displayName","defaultProps"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import { g as getRootClassName, c as classnames, h as handleBasicClasses } from
|
|
|
5
5
|
import isEmpty from 'lodash/isEmpty';
|
|
6
6
|
import { A as Avatar } from './Avatar2.js';
|
|
7
7
|
import { L as Link } from './Link2.js';
|
|
8
|
+
import set from 'lodash/set';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Component display name.
|
|
@@ -77,10 +78,15 @@ var UserBlock = forwardRef(function (props, ref) {
|
|
|
77
78
|
linkAs: linkAs,
|
|
78
79
|
color: ColorPalette.dark
|
|
79
80
|
}));
|
|
81
|
+
} // Disable avatar focus since the name block is the same link / same button.
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if (avatarProps) {
|
|
85
|
+
set(avatarProps, ['thumbnailProps', 'tabIndex'], -1);
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
return React.createElement(NameComponent, nProps, name);
|
|
83
|
-
}, [isClickable, linkAs, linkProps, name, nameProps, onClick]);
|
|
89
|
+
}, [avatarProps, isClickable, linkAs, linkProps, name, nameProps, onClick]);
|
|
84
90
|
var fieldsBlock = fields && componentSize !== Size.s && React.createElement("div", {
|
|
85
91
|
className: "".concat(CLASSNAME, "__fields")
|
|
86
92
|
}, fields.map(function (field, idx) {
|
|
@@ -103,7 +109,8 @@ var UserBlock = forwardRef(function (props, ref) {
|
|
|
103
109
|
onMouseEnter: onMouseEnter
|
|
104
110
|
}), avatarProps && React.createElement(Avatar, _extends({
|
|
105
111
|
linkAs: linkAs,
|
|
106
|
-
linkProps: linkProps
|
|
112
|
+
linkProps: linkProps,
|
|
113
|
+
alt: ""
|
|
107
114
|
}, avatarProps, {
|
|
108
115
|
className: classnames("".concat(CLASSNAME, "__avatar"), avatarProps.className),
|
|
109
116
|
size: componentSize,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserBlock.js","sources":["../../../src/components/user-block/UserBlock.tsx"],"sourcesContent":["import React, { forwardRef, ReactNode } from 'react';\nimport isEmpty from 'lodash/isEmpty';\nimport classNames from 'classnames';\n\nimport { Avatar, ColorPalette, Link, Orientation, Size, Theme } from '@lumx/react';\nimport { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';\n\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 /** Additional fields used to describe the user. */\n fields?: string[];\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 /** Multiple action toolbar content. */\n multipleActions?: ReactNode;\n /** User name. */\n name?: string;\n /** Props to pass to the name block. */\n nameProps?: GenericProps;\n /** Orientation. */\n orientation?: Orientation;\n /** Simple action toolbar content. */\n simpleAction?: ReactNode;\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 linkProps,\n linkAs,\n multipleActions,\n name,\n nameProps,\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 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 let NameComponent: any = 'span';\n const nProps: any = {\n ...nameProps,\n className: classNames(`${CLASSNAME}__name`, linkProps?.className, nameProps?.className),\n };\n if (isClickable) {\n NameComponent = Link;\n Object.assign(nProps, {\n ...linkProps,\n onClick,\n linkAs,\n color: ColorPalette.dark,\n });\n }\n return <NameComponent {...nProps}>{name}</NameComponent>;\n }, [isClickable, linkAs, linkProps, name, nameProps, onClick]);\n\n const fieldsBlock: ReactNode = fields && componentSize !== Size.s && (\n <div className={`${CLASSNAME}__fields`}>\n {fields.map((field: string, idx: number) => (\n <span key={idx} className={`${CLASSNAME}__field`}>\n {field}\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 linkAs={linkAs}\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","linkProps","linkAs","multipleActions","name","nameProps","onClick","onMouseEnter","onMouseLeave","simpleAction","forwardedProps","componentSize","vertical","l","shouldDisplayActions","isLink","Boolean","href","isClickable","nameBlock","React","useMemo","isEmpty","NameComponent","nProps","classNames","Link","Object","assign","color","ColorPalette","dark","fieldsBlock","s","map","field","idx","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';\nimport isEmpty from 'lodash/isEmpty';\nimport classNames from 'classnames';\nimport set from 'lodash/set';\n\nimport { Avatar, ColorPalette, Link, Orientation, Size, Theme } from '@lumx/react';\nimport { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';\n\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?: Omit<AvatarProps, 'alt'>;\n /** Additional fields used to describe the user. */\n fields?: string[];\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 /** Multiple action toolbar content. */\n multipleActions?: ReactNode;\n /** User name. */\n name?: string;\n /** Props to pass to the name block. */\n nameProps?: GenericProps;\n /** Orientation. */\n orientation?: Orientation;\n /** Simple action toolbar content. */\n simpleAction?: ReactNode;\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 linkProps,\n linkAs,\n multipleActions,\n name,\n nameProps,\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 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 let NameComponent: any = 'span';\n const nProps: any = {\n ...nameProps,\n className: classNames(`${CLASSNAME}__name`, linkProps?.className, nameProps?.className),\n };\n if (isClickable) {\n NameComponent = Link;\n Object.assign(nProps, {\n ...linkProps,\n onClick,\n linkAs,\n color: ColorPalette.dark,\n });\n }\n // Disable avatar focus since the name block is the same link / same button.\n if (avatarProps) {\n set(avatarProps, ['thumbnailProps', 'tabIndex'], -1);\n }\n return <NameComponent {...nProps}>{name}</NameComponent>;\n }, [avatarProps, isClickable, linkAs, linkProps, name, nameProps, onClick]);\n\n const fieldsBlock: ReactNode = fields && componentSize !== Size.s && (\n <div className={`${CLASSNAME}__fields`}>\n {fields.map((field: string, idx: number) => (\n <span key={idx} className={`${CLASSNAME}__field`}>\n {field}\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 linkAs={linkAs}\n linkProps={linkProps}\n alt=\"\"\n {...(avatarProps as any)}\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","linkProps","linkAs","multipleActions","name","nameProps","onClick","onMouseEnter","onMouseLeave","simpleAction","forwardedProps","componentSize","vertical","l","shouldDisplayActions","isLink","Boolean","href","isClickable","nameBlock","React","useMemo","isEmpty","NameComponent","nProps","classNames","Link","Object","assign","color","ColorPalette","dark","set","fieldsBlock","s","map","field","idx","handleBasicClasses","prefix","displayName","defaultProps"],"mappings":"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"}
|
|
@@ -2,8 +2,14 @@ import { useEffect } from 'react';
|
|
|
2
2
|
import { D as DOCUMENT } from './constants.js';
|
|
3
3
|
|
|
4
4
|
/** CSS selector listing all tabbable elements. */
|
|
5
|
+
var TABBABLE_ELEMENTS_SELECTOR = "a[href], button, textarea, input:not([type=\"hidden\"]), [tabindex]";
|
|
6
|
+
/** CSS selector matching element that are disabled (should not receive focus). */
|
|
5
7
|
|
|
6
|
-
var
|
|
8
|
+
var DISABLED_SELECTOR = "[tabindex=\"-1\"], [disabled]:not([disabled=\"false\"]), [aria-disabled]:not([aria-disabled=\"false\"])";
|
|
9
|
+
|
|
10
|
+
var isNotDisabled = function isNotDisabled(element) {
|
|
11
|
+
return !element.matches(DISABLED_SELECTOR);
|
|
12
|
+
};
|
|
7
13
|
/**
|
|
8
14
|
* Get first and last elements focusable in an element.
|
|
9
15
|
*
|
|
@@ -11,20 +17,24 @@ var TABBABLE_ELEMENTS_SELECTOR = "a[href]:not([tabindex=\"-1\"], [disabled], [ar
|
|
|
11
17
|
* @return first and last focusable elements
|
|
12
18
|
*/
|
|
13
19
|
|
|
14
|
-
function getFocusable(parentElement) {
|
|
15
|
-
var focusableElements = parentElement.querySelectorAll(TABBABLE_ELEMENTS_SELECTOR);
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
function getFirstAndLastFocusable(parentElement) {
|
|
22
|
+
var focusableElements = Array.from(parentElement.querySelectorAll(TABBABLE_ELEMENTS_SELECTOR)); // First non disabled element.
|
|
23
|
+
|
|
24
|
+
var first = focusableElements.find(isNotDisabled); // Last non disabled element.
|
|
25
|
+
|
|
26
|
+
var last = focusableElements.reverse().find(isNotDisabled);
|
|
27
|
+
|
|
28
|
+
if (last && first) {
|
|
29
|
+
return {
|
|
30
|
+
first: first,
|
|
31
|
+
last: last
|
|
32
|
+
};
|
|
19
33
|
}
|
|
20
34
|
|
|
21
|
-
|
|
22
|
-
var last = focusableElements[focusableElements.length - 1];
|
|
23
|
-
return {
|
|
24
|
-
first: first,
|
|
25
|
-
last: last
|
|
26
|
-
};
|
|
35
|
+
return {};
|
|
27
36
|
}
|
|
37
|
+
|
|
28
38
|
/**
|
|
29
39
|
* Add a key down event handler to the given root element (document.body by default) to trap the move of focus
|
|
30
40
|
* (TAB and SHIFT-TAB keys) inside the given focusZoneElement.
|
|
@@ -35,7 +45,6 @@ function getFocusable(parentElement) {
|
|
|
35
45
|
* @param rootElement The element on which the key down event will be placed.
|
|
36
46
|
*/
|
|
37
47
|
|
|
38
|
-
|
|
39
48
|
function useFocusTrap(focusZoneElement, focusElement) {
|
|
40
49
|
var rootElement = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DOCUMENT === null || DOCUMENT === void 0 ? void 0 : DOCUMENT.body;
|
|
41
50
|
useEffect(function () {
|
|
@@ -55,7 +64,7 @@ function useFocusTrap(focusZoneElement, focusElement) {
|
|
|
55
64
|
return;
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
var focusable =
|
|
67
|
+
var focusable = getFirstAndLastFocusable(focusZoneElement); // Prevent focus switch if no focusable available.
|
|
59
68
|
|
|
60
69
|
if (!focusable.first) {
|
|
61
70
|
evt.preventDefault();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFocusTrap.js","sources":["../../../src/hooks/useFocusTrap.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"useFocusTrap.js","sources":["../../../src/utils/focus/getFirstAndLastFocusable.ts","../../../src/hooks/useFocusTrap.ts"],"sourcesContent":["/** CSS selector listing all tabbable elements. */\nconst TABBABLE_ELEMENTS_SELECTOR = `a[href], button, textarea, input:not([type=\"hidden\"]), [tabindex]`;\n\n/** CSS selector matching element that are disabled (should not receive focus). */\nconst DISABLED_SELECTOR = `[tabindex=\"-1\"], [disabled]:not([disabled=\"false\"]), [aria-disabled]:not([aria-disabled=\"false\"])`;\n\nconst isNotDisabled = (element: HTMLElement) => !element.matches(DISABLED_SELECTOR);\n\n/**\n * Get first and last elements focusable in an element.\n *\n * @param parentElement The element in which to search focusable elements.\n * @return first and last focusable elements\n */\nexport function getFirstAndLastFocusable(parentElement: HTMLElement) {\n const focusableElements = Array.from(parentElement.querySelectorAll<HTMLElement>(TABBABLE_ELEMENTS_SELECTOR));\n\n // First non disabled element.\n const first = focusableElements.find(isNotDisabled);\n // Last non disabled element.\n const last = focusableElements.reverse().find(isNotDisabled);\n\n if (last && first) {\n return { first, last };\n }\n return {};\n}\n","import { useEffect } from 'react';\n\nimport { DOCUMENT } from '@lumx/react/constants';\nimport { getFirstAndLastFocusable } from '@lumx/react/utils/focus/getFirstAndLastFocusable';\n\n/**\n * Add a key down event handler to the given root element (document.body by default) to trap the move of focus\n * (TAB and SHIFT-TAB keys) inside the given focusZoneElement.\n * Will focus the given focus element when activating the focus trap.\n *\n * @param focusZoneElement The element in which to trap the focus.\n * @param focusElement The element to focus when the focus trap is activated.\n * @param rootElement The element on which the key down event will be placed.\n */\nexport function useFocusTrap(\n focusZoneElement: HTMLElement | null,\n focusElement?: HTMLElement | null,\n rootElement = DOCUMENT?.body,\n): void {\n useEffect(() => {\n if (rootElement && focusZoneElement) {\n (document.activeElement as HTMLElement)?.blur();\n if (focusElement) {\n focusElement.focus();\n }\n\n const onKeyDown = (evt: KeyboardEvent) => {\n const { key } = evt;\n if (key !== 'Tab') {\n return;\n }\n const focusable = getFirstAndLastFocusable(focusZoneElement);\n\n // Prevent focus switch if no focusable available.\n if (!focusable.first) {\n evt.preventDefault();\n return;\n }\n\n if (\n // No previous focus\n !document.activeElement ||\n // Previous focus is at the end of the focus zone.\n (!evt.shiftKey && document.activeElement === focusable.last) ||\n // Previous focus is outside the focus zone\n !focusZoneElement.contains(document.activeElement)\n ) {\n focusable.first.focus();\n evt.preventDefault();\n return;\n }\n\n if (\n // Focus order reversed\n evt.shiftKey &&\n // Previous focus is at the start of the focus zone.\n document.activeElement === focusable.first\n ) {\n focusable.last.focus();\n evt.preventDefault();\n }\n };\n rootElement.addEventListener('keydown', onKeyDown);\n return () => rootElement.removeEventListener('keydown', onKeyDown);\n }\n return undefined;\n }, [focusElement, focusZoneElement, rootElement]);\n}\n"],"names":["TABBABLE_ELEMENTS_SELECTOR","DISABLED_SELECTOR","isNotDisabled","element","matches","getFirstAndLastFocusable","parentElement","focusableElements","Array","from","querySelectorAll","first","find","last","reverse","useFocusTrap","focusZoneElement","focusElement","rootElement","DOCUMENT","body","useEffect","document","activeElement","blur","focus","onKeyDown","evt","key","focusable","preventDefault","shiftKey","contains","addEventListener","removeEventListener","undefined"],"mappings":";;;AAAA;AACA,IAAMA,0BAA0B,wEAAhC;AAEA;;AACA,IAAMC,iBAAiB,4GAAvB;;AAEA,IAAMC,aAAa,GAAG,SAAhBA,aAAgB,CAACC,OAAD;AAAA,SAA0B,CAACA,OAAO,CAACC,OAAR,CAAgBH,iBAAhB,CAA3B;AAAA,CAAtB;AAEA;;;;;;;;AAMO,SAASI,wBAAT,CAAkCC,aAAlC,EAA8D;AACjE,MAAMC,iBAAiB,GAAGC,KAAK,CAACC,IAAN,CAAWH,aAAa,CAACI,gBAAd,CAA4CV,0BAA5C,CAAX,CAA1B,CADiE;;AAIjE,MAAMW,KAAK,GAAGJ,iBAAiB,CAACK,IAAlB,CAAuBV,aAAvB,CAAd,CAJiE;;AAMjE,MAAMW,IAAI,GAAGN,iBAAiB,CAACO,OAAlB,GAA4BF,IAA5B,CAAiCV,aAAjC,CAAb;;AAEA,MAAIW,IAAI,IAAIF,KAAZ,EAAmB;AACf,WAAO;AAAEA,MAAAA,KAAK,EAALA,KAAF;AAASE,MAAAA,IAAI,EAAJA;AAAT,KAAP;AACH;;AACD,SAAO,EAAP;AACH;;ACrBD;;;;;;;;;;AASO,SAASE,YAAT,CACHC,gBADG,EAEHC,YAFG,EAIC;AAAA,MADJC,WACI,uEADUC,QACV,aADUA,QACV,uBADUA,QAAQ,CAAEC,IACpB;AACJC,EAAAA,SAAS,CAAC,YAAM;AACZ,QAAIH,WAAW,IAAIF,gBAAnB,EAAqC;AAAA;;AACjC,cAACM,QAAQ,CAACC,aAAV,8CAAyCC,IAAzC;;AACA,UAAIP,YAAJ,EAAkB;AACdA,QAAAA,YAAY,CAACQ,KAAb;AACH;;AAED,UAAMC,SAAS,GAAG,SAAZA,SAAY,CAACC,GAAD,EAAwB;AAAA,YAC9BC,GAD8B,GACtBD,GADsB,CAC9BC,GAD8B;;AAEtC,YAAIA,GAAG,KAAK,KAAZ,EAAmB;AACf;AACH;;AACD,YAAMC,SAAS,GAAGxB,wBAAwB,CAACW,gBAAD,CAA1C,CALsC;;AAQtC,YAAI,CAACa,SAAS,CAAClB,KAAf,EAAsB;AAClBgB,UAAAA,GAAG,CAACG,cAAJ;AACA;AACH;;AAED;AAEI,SAACR,QAAQ,CAACC,aAAV;AAEC,SAACI,GAAG,CAACI,QAAL,IAAiBT,QAAQ,CAACC,aAAT,KAA2BM,SAAS,CAAChB,IAFvD;AAIA,SAACG,gBAAgB,CAACgB,QAAjB,CAA0BV,QAAQ,CAACC,aAAnC,CANL,EAOE;AACEM,UAAAA,SAAS,CAAClB,KAAV,CAAgBc,KAAhB;AACAE,UAAAA,GAAG,CAACG,cAAJ;AACA;AACH;;AAED;AAEIH,QAAAA,GAAG,CAACI,QAAJ;AAEAT,QAAAA,QAAQ,CAACC,aAAT,KAA2BM,SAAS,CAAClB,KAJzC,EAKE;AACEkB,UAAAA,SAAS,CAAChB,IAAV,CAAeY,KAAf;AACAE,UAAAA,GAAG,CAACG,cAAJ;AACH;AACJ,OAnCD;;AAoCAZ,MAAAA,WAAW,CAACe,gBAAZ,CAA6B,SAA7B,EAAwCP,SAAxC;AACA,aAAO;AAAA,eAAMR,WAAW,CAACgB,mBAAZ,CAAgC,SAAhC,EAA2CR,SAA3C,CAAN;AAAA,OAAP;AACH;;AACD,WAAOS,SAAP;AACH,GA/CQ,EA+CN,CAAClB,YAAD,EAAeD,gBAAf,EAAiCE,WAAjC,CA/CM,CAAT;AAgDH;;;;"}
|
|
@@ -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/esm/index.js
CHANGED
|
@@ -85,5 +85,6 @@ export { T as ThumbnailAspectRatio, a as ThumbnailVariant } from './_internal/ty
|
|
|
85
85
|
export { T as Toolbar } from './_internal/Toolbar2.js';
|
|
86
86
|
export { T as Tooltip } from './_internal/Tooltip2.js';
|
|
87
87
|
export { a as Uploader, U as UploaderVariant } from './_internal/Uploader2.js';
|
|
88
|
+
import 'lodash/set';
|
|
88
89
|
export { U as UserBlock } from './_internal/UserBlock.js';
|
|
89
90
|
//# sourceMappingURL=index.js.map
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.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.2.
|
|
11
|
-
"@lumx/icons": "^2.2.
|
|
10
|
+
"@lumx/core": "^2.2.19",
|
|
11
|
+
"@lumx/icons": "^2.2.19",
|
|
12
12
|
"@popperjs/core": "^2.5.4",
|
|
13
13
|
"body-scroll-lock": "^3.1.5",
|
|
14
14
|
"classnames": "^2.2.6",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"rollup-plugin-typescript-paths": "^1.2.2",
|
|
73
73
|
"test-data-bot": "^0.8.0",
|
|
74
74
|
"ts-jest": "^26.2.0",
|
|
75
|
-
"tsconfig-paths-webpack-plugin": "^3.
|
|
75
|
+
"tsconfig-paths-webpack-plugin": "^3.3.0",
|
|
76
76
|
"typescript": "^4.1.2",
|
|
77
77
|
"yargs": "^15.4.1",
|
|
78
78
|
"yarn": "^1.19.1"
|
|
@@ -120,6 +120,6 @@
|
|
|
120
120
|
"build:storybook": "cd storybook && ./build"
|
|
121
121
|
},
|
|
122
122
|
"sideEffects": false,
|
|
123
|
-
"version": "2.2.
|
|
124
|
-
"gitHead": "
|
|
123
|
+
"version": "2.2.19",
|
|
124
|
+
"gitHead": "075b14a949b8ed5897d5fa8087ea4ff993d90eb5"
|
|
125
125
|
}
|
|
@@ -283,7 +283,8 @@ export const ScrollableDialogWithHeaderAndFooter = ({ theme }: any) => {
|
|
|
283
283
|
);
|
|
284
284
|
};
|
|
285
285
|
|
|
286
|
-
|
|
286
|
+
/** Test dialog focus trap (focus is contained inside the dialog) with all kinds of focusable and non-focusable items */
|
|
287
|
+
export const DialogFocusTrap = ({ theme }: any) => {
|
|
287
288
|
const { button, buttonRef, closeDialog, isOpen } = useOpenButton(theme);
|
|
288
289
|
const [textValue, setTextValue] = useState('value');
|
|
289
290
|
const [checkboxValue, setCheckboxValue] = useState(false);
|
|
@@ -372,6 +373,8 @@ export const DialogWithFocusableElements = ({ theme }: any) => {
|
|
|
372
373
|
|
|
373
374
|
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
|
|
374
375
|
<div tabIndex={0}>Focus div</div>
|
|
376
|
+
|
|
377
|
+
<Button isDisabled={false}>Button explicitly not disabled (should focus)</Button>
|
|
375
378
|
</div>
|
|
376
379
|
</Dialog>
|
|
377
380
|
</>
|