reshaped 3.3.13 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/bundle.css +1 -1
- package/dist/bundle.d.ts +3 -0
- package/dist/bundle.js +11 -11
- package/dist/components/Autocomplete/Autocomplete.js +34 -24
- package/dist/components/Autocomplete/Autocomplete.types.d.ts +1 -1
- package/dist/components/Autocomplete/tests/Autocomplete.stories.js +8 -1
- package/dist/components/Carousel/Carousel.js +2 -1
- package/dist/components/Carousel/Carousel.types.d.ts +1 -0
- package/dist/components/ContextMenu/ContextMenu.js +2 -2
- package/dist/components/ContextMenu/tests/ContextMenu.test.stories.js +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.js +6 -1
- package/dist/components/DropdownMenu/tests/DropdownMenu.test.stories.js +2 -2
- package/dist/components/Popover/Popover.js +1 -1
- package/dist/components/Popover/tests/Popover.test.stories.js +4 -4
- package/dist/components/ProgressIndicator/ProgressIndicator.d.ts +3 -0
- package/dist/components/ProgressIndicator/ProgressIndicator.js +101 -0
- package/dist/components/ProgressIndicator/ProgressIndicator.module.css +1 -0
- package/dist/components/ProgressIndicator/ProgressIndicator.types.d.ts +9 -0
- package/dist/components/ProgressIndicator/ProgressIndicator.types.js +1 -0
- package/dist/components/ProgressIndicator/index.d.ts +2 -0
- package/dist/components/ProgressIndicator/index.js +1 -0
- package/dist/components/ProgressIndicator/tests/ProgressIndicator.stories.d.ts +19 -0
- package/dist/components/ProgressIndicator/tests/ProgressIndicator.stories.js +85 -0
- package/dist/components/Reshaped/Reshaped.js +4 -5
- package/dist/components/TextField/TextField.module.css +1 -1
- package/dist/components/Toast/tests/Toast.stories.js +22 -7
- package/dist/components/Tooltip/tests/Tooltip.test.stories.js +1 -1
- package/dist/components/_private/Flyout/Flyout.module.css +1 -1
- package/dist/components/_private/Flyout/Flyout.types.d.ts +14 -3
- package/dist/components/_private/Flyout/FlyoutContent.js +37 -7
- package/dist/components/_private/Flyout/FlyoutControlled.js +12 -11
- package/dist/components/_private/Flyout/FlyoutUncontrolled.js +3 -5
- package/dist/components/_private/Flyout/index.d.ts +1 -1
- package/dist/components/_private/Flyout/tests/Flyout.stories.d.ts +79 -13
- package/dist/components/_private/Flyout/tests/Flyout.stories.js +526 -280
- package/dist/components/_private/Flyout/useFlyout.js +9 -3
- package/dist/components/_private/Flyout/utilities/isFullyVisible.d.ts +3 -1
- package/dist/components/_private/Flyout/utilities/isFullyVisible.js +2 -2
- package/dist/hooks/_private/usePrevious.d.ts +2 -0
- package/dist/hooks/_private/usePrevious.js +17 -0
- package/dist/hooks/_private/useSingletonEnvironment.d.ts +1 -1
- package/dist/hooks/_private/useSingletonEnvironment.js +1 -1
- package/dist/hooks/_private/useSingletonKeyboardMode.d.ts +13 -2
- package/dist/hooks/_private/useSingletonKeyboardMode.js +48 -15
- package/dist/hooks/tests/useKeyboardMode.stories.d.ts +6 -0
- package/dist/hooks/tests/useKeyboardMode.stories.js +37 -0
- package/dist/hooks/useKeyboardMode.d.ts +7 -0
- package/dist/hooks/useKeyboardMode.js +13 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/utilities/a11y/index.d.ts +1 -1
- package/dist/utilities/a11y/index.js +1 -1
- package/dist/utilities/a11y/keyboardMode.d.ts +2 -2
- package/dist/utilities/a11y/keyboardMode.js +2 -2
- package/dist/utilities/dom/find.d.ts +4 -1
- package/dist/utilities/dom/find.js +4 -4
- package/dist/utilities/scroll/lockStandard.js +1 -1
- package/package.json +3 -4
- package/dist/components/_private/Flyout/tests/Flyout.test.stories.d.ts +0 -28
- package/dist/components/_private/Flyout/tests/Flyout.test.stories.js +0 -205
@@ -33,7 +33,8 @@ const flyout = (args) => {
|
|
33
33
|
const targetClone = flyoutEl.cloneNode(true);
|
34
34
|
const baseUnit = getComputedStyle(flyoutEl).getPropertyValue("--rs-unit-x1");
|
35
35
|
const unitModifier = baseUnit ? parseInt(baseUnit) : 0;
|
36
|
-
const
|
36
|
+
const internalTriggerBounds = triggerEl?.getBoundingClientRect();
|
37
|
+
const triggerBounds = passedTriggerBounds || internalTriggerBounds;
|
37
38
|
if (!triggerBounds)
|
38
39
|
return;
|
39
40
|
const resolvedTriggerBounds = getRectFromCoordinates(triggerBounds);
|
@@ -56,7 +57,12 @@ const flyout = (args) => {
|
|
56
57
|
// Insert inside shadow root if possible to make sure styles are applied correctly
|
57
58
|
(shadowRoot || document.body).appendChild(targetClone);
|
58
59
|
const flyoutBounds = targetClone.getBoundingClientRect();
|
59
|
-
const
|
60
|
+
const closestRenderContainer = !container && triggerEl ? findClosestRenderContainer({ el: triggerEl }) : undefined;
|
61
|
+
const containerParent = container ||
|
62
|
+
// Only render inside non-scrollable container to make sure it doesn't get clipped by overflow auto
|
63
|
+
// We render those cases in the document root and then sync the position on scroll instead
|
64
|
+
(!closestRenderContainer?.scrollable ? closestRenderContainer?.el : undefined) ||
|
65
|
+
document.body;
|
60
66
|
const containerBounds = containerParent.getBoundingClientRect();
|
61
67
|
const scopeOffset = {
|
62
68
|
top: containerBounds.top + document.documentElement.scrollTop - containerParent.scrollTop,
|
@@ -74,7 +80,7 @@ const flyout = (args) => {
|
|
74
80
|
contentGap: contentGap * unitModifier,
|
75
81
|
contentShift: contentShift * unitModifier,
|
76
82
|
});
|
77
|
-
const visible = isFullyVisible(tested);
|
83
|
+
const visible = isFullyVisible({ ...tested, container });
|
78
84
|
const validPosition = visible || fallbackPositions?.length === 0;
|
79
85
|
// Saving first try in case non of the options work
|
80
86
|
if (validPosition || lastUsedFallback === currentPosition) {
|
@@ -2,5 +2,7 @@ import calculatePosition from "./calculatePosition";
|
|
2
2
|
/**
|
3
3
|
* Check if element visually fits on the screen
|
4
4
|
*/
|
5
|
-
declare const isFullyVisible: (args: ReturnType<typeof calculatePosition>
|
5
|
+
declare const isFullyVisible: (args: ReturnType<typeof calculatePosition> & {
|
6
|
+
container?: HTMLElement | null;
|
7
|
+
}) => boolean;
|
6
8
|
export default isFullyVisible;
|
@@ -2,8 +2,8 @@
|
|
2
2
|
* Check if element visually fits on the screen
|
3
3
|
*/
|
4
4
|
const isFullyVisible = (args) => {
|
5
|
-
const { styles, scopeOffset } = args;
|
6
|
-
const htmlEl = document.documentElement;
|
5
|
+
const { styles, scopeOffset, container } = args;
|
6
|
+
const htmlEl = container || document.documentElement;
|
7
7
|
const pageLeft = htmlEl.scrollLeft;
|
8
8
|
const pageRight = pageLeft + htmlEl.clientWidth;
|
9
9
|
const pageTop = htmlEl.scrollTop;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
"use client";
|
2
|
+
import React from "react";
|
3
|
+
const copy = (value) => {
|
4
|
+
const valueIsDate = value instanceof Date;
|
5
|
+
if (valueIsDate)
|
6
|
+
return String(valueIsDate);
|
7
|
+
const string = JSON.stringify(value);
|
8
|
+
return JSON.parse(string);
|
9
|
+
};
|
10
|
+
const usePrevious = (value, clean = false) => {
|
11
|
+
const ref = React.useRef(clean ? copy(value) : value);
|
12
|
+
React.useEffect(() => {
|
13
|
+
ref.current = clean ? copy(value) : value;
|
14
|
+
}, [value, clean]);
|
15
|
+
return ref.current;
|
16
|
+
};
|
17
|
+
export default usePrevious;
|
@@ -5,5 +5,5 @@ type Context = {
|
|
5
5
|
defaultViewport: G.Viewport;
|
6
6
|
};
|
7
7
|
export declare const SingletonEnvironmentContext: React.Context<Context>;
|
8
|
-
export declare const
|
8
|
+
export declare const useSingletonEnvironment: (defaultRTL?: boolean) => [boolean, React.Dispatch<React.SetStateAction<boolean>>];
|
9
9
|
export {};
|
@@ -4,7 +4,7 @@ export const SingletonEnvironmentContext = React.createContext({
|
|
4
4
|
rtl: [false, () => { }],
|
5
5
|
defaultViewport: "s",
|
6
6
|
});
|
7
|
-
export const
|
7
|
+
export const useSingletonEnvironment = (defaultRTL) => {
|
8
8
|
const state = React.useState(defaultRTL || false);
|
9
9
|
const [isRTL, setRTL] = state;
|
10
10
|
/**
|
@@ -1,2 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
import React from "react";
|
2
|
+
type ContextProps = {
|
3
|
+
disabledRef: React.RefObject<boolean> | null;
|
4
|
+
disable: () => void;
|
5
|
+
enable: () => void;
|
6
|
+
activate: () => void;
|
7
|
+
deactivate: () => void;
|
8
|
+
};
|
9
|
+
export declare const SingletonKeyboardModeContext: React.Context<ContextProps>;
|
10
|
+
export declare const SingletonKeyboardModeProvider: (props: {
|
11
|
+
children: React.ReactNode;
|
12
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
13
|
+
export {};
|
@@ -1,25 +1,58 @@
|
|
1
|
+
"use client";
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
1
3
|
import React from "react";
|
2
4
|
import * as keys from "../../constants/keys.js";
|
3
|
-
import {
|
4
|
-
const
|
5
|
+
import { activateKeyboardMode, deactivateKeyboardMode } from "../../utilities/a11y/index.js";
|
6
|
+
export const SingletonKeyboardModeContext = React.createContext({
|
7
|
+
disabledRef: null,
|
8
|
+
disable: () => { },
|
9
|
+
enable: () => { },
|
10
|
+
activate: () => { },
|
11
|
+
deactivate: () => { },
|
12
|
+
});
|
13
|
+
export const SingletonKeyboardModeProvider = (props) => {
|
14
|
+
const disabledRef = React.useRef(false);
|
15
|
+
const disable = React.useCallback(() => {
|
16
|
+
disabledRef.current = true;
|
17
|
+
}, []);
|
18
|
+
const enable = React.useCallback(() => {
|
19
|
+
disabledRef.current = false;
|
20
|
+
}, []);
|
21
|
+
const activate = React.useCallback(() => {
|
22
|
+
if (disabledRef.current)
|
23
|
+
return;
|
24
|
+
activateKeyboardMode();
|
25
|
+
}, []);
|
26
|
+
const deactivate = React.useCallback(() => {
|
27
|
+
if (disabledRef.current)
|
28
|
+
return;
|
29
|
+
deactivateKeyboardMode();
|
30
|
+
}, []);
|
31
|
+
const handleKeyDown = React.useCallback((e) => {
|
32
|
+
if (e.metaKey || e.altKey || e.ctrlKey)
|
33
|
+
return;
|
34
|
+
// Prevent focus ring from appearing when using mouse but closing with esc
|
35
|
+
if (e.key === keys.ESC)
|
36
|
+
return;
|
37
|
+
activate();
|
38
|
+
}, [activate]);
|
39
|
+
const handleClick = React.useCallback(() => {
|
40
|
+
deactivate();
|
41
|
+
}, [deactivate]);
|
5
42
|
React.useEffect(() => {
|
6
|
-
const handleKeyDown = (e) => {
|
7
|
-
if (e.metaKey || e.altKey || e.ctrlKey)
|
8
|
-
return;
|
9
|
-
// Prevent focus ring from appearing when using mouse but closing with esc
|
10
|
-
if (e.key === keys.ESC)
|
11
|
-
return;
|
12
|
-
enableKeyboardMode();
|
13
|
-
};
|
14
|
-
const handleClick = () => {
|
15
|
-
disableKeyboardMode();
|
16
|
-
};
|
17
43
|
window.addEventListener("keydown", handleKeyDown);
|
18
44
|
window.addEventListener("mousedown", handleClick);
|
19
45
|
return () => {
|
20
46
|
window.removeEventListener("keydown", handleKeyDown);
|
21
47
|
window.removeEventListener("mousedown", handleClick);
|
22
48
|
};
|
23
|
-
}, []);
|
49
|
+
}, [handleClick, handleKeyDown]);
|
50
|
+
const value = React.useMemo(() => ({
|
51
|
+
disabledRef,
|
52
|
+
disable,
|
53
|
+
enable,
|
54
|
+
activate,
|
55
|
+
deactivate,
|
56
|
+
}), [disable, enable, activate, deactivate]);
|
57
|
+
return (_jsx(SingletonKeyboardModeContext.Provider, { value: value, children: props.children }));
|
24
58
|
};
|
25
|
-
export default useSingletonKeyboardMode;
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { expect, userEvent } from "@storybook/test";
|
2
|
+
import Button from "../../components/Button/index.js";
|
3
|
+
import View from "../../components/View/index.js";
|
4
|
+
import useKeyboardMode from "../useKeyboardMode.js";
|
5
|
+
export default { title: "Hooks/useKeyboardMode" };
|
6
|
+
const Component = () => {
|
7
|
+
const { activate, deactivate, disable, enable } = useKeyboardMode();
|
8
|
+
return (<View direction="row" gap={2}>
|
9
|
+
<Button onClick={activate}>Activate</Button>
|
10
|
+
<Button onClick={deactivate}>Deactivate</Button>
|
11
|
+
<Button onClick={disable}>Disable</Button>
|
12
|
+
<Button onClick={enable}>Enable</Button>
|
13
|
+
</View>);
|
14
|
+
};
|
15
|
+
export const base = {
|
16
|
+
name: "base",
|
17
|
+
render: () => <Component />,
|
18
|
+
play: async ({ canvas }) => {
|
19
|
+
const attribute = "data-rs-keyboard";
|
20
|
+
const root = document.documentElement;
|
21
|
+
const activateTrigger = canvas.getAllByRole("button")[0];
|
22
|
+
const deactivateTrigger = canvas.getAllByRole("button")[1];
|
23
|
+
const disableTrigger = canvas.getAllByRole("button")[2];
|
24
|
+
const enableTrigger = canvas.getAllByRole("button")[3];
|
25
|
+
expect(root).not.toHaveAttribute(attribute);
|
26
|
+
await userEvent.click(activateTrigger);
|
27
|
+
expect(root).toHaveAttribute(attribute);
|
28
|
+
await userEvent.click(deactivateTrigger);
|
29
|
+
expect(root).not.toHaveAttribute(attribute);
|
30
|
+
await userEvent.click(disableTrigger);
|
31
|
+
await userEvent.click(activateTrigger);
|
32
|
+
expect(root).not.toHaveAttribute(attribute);
|
33
|
+
await userEvent.click(enableTrigger);
|
34
|
+
await userEvent.click(activateTrigger);
|
35
|
+
expect(root).toHaveAttribute(attribute);
|
36
|
+
},
|
37
|
+
};
|
@@ -0,0 +1,13 @@
|
|
1
|
+
"use client";
|
2
|
+
import React from "react";
|
3
|
+
import { SingletonKeyboardModeContext } from "./_private/useSingletonKeyboardMode.js";
|
4
|
+
const useKeyboardMode = () => {
|
5
|
+
const singletonKeyboardMode = React.useContext(SingletonKeyboardModeContext);
|
6
|
+
return React.useMemo(() => ({
|
7
|
+
enable: singletonKeyboardMode.enable,
|
8
|
+
disable: singletonKeyboardMode.disable,
|
9
|
+
activate: singletonKeyboardMode.activate,
|
10
|
+
deactivate: singletonKeyboardMode.deactivate,
|
11
|
+
}), [singletonKeyboardMode]);
|
12
|
+
};
|
13
|
+
export default useKeyboardMode;
|
package/dist/index.d.ts
CHANGED
@@ -73,6 +73,8 @@ export { default as Popover } from "./components/Popover";
|
|
73
73
|
export type { PopoverProps, PopoverInstance } from "./components/Popover";
|
74
74
|
export { default as Progress } from "./components/Progress";
|
75
75
|
export type { ProgressProps } from "./components/Progress";
|
76
|
+
export { default as ProgressIndicator } from "./components/ProgressIndicator";
|
77
|
+
export type { ProgressIndicatorProps } from "./components/ProgressIndicator";
|
76
78
|
export { default as Radio } from "./components/Radio";
|
77
79
|
export type { RadioProps } from "./components/Radio";
|
78
80
|
export { default as RadioGroup } from "./components/RadioGroup";
|
@@ -124,6 +126,7 @@ export { default as useToggle } from "./hooks/useToggle";
|
|
124
126
|
export { default as useRTL } from "./hooks/useRTL";
|
125
127
|
export { default as useIsomorphicLayoutEffect } from "./hooks/useIsomorphicLayoutEffect";
|
126
128
|
export { default as useHotkeys } from "./hooks/useHotkeys";
|
129
|
+
export { default as useKeyboardMode } from "./hooks/useKeyboardMode";
|
127
130
|
export { default as useResponsiveClientValue } from "./hooks/useResponsiveClientValue";
|
128
131
|
/**
|
129
132
|
* Utilities
|
package/dist/index.js
CHANGED
@@ -37,6 +37,7 @@ export { default as Pagination } from "./components/Pagination/index.js";
|
|
37
37
|
export { default as PinField } from "./components/PinField/index.js";
|
38
38
|
export { default as Popover } from "./components/Popover/index.js";
|
39
39
|
export { default as Progress } from "./components/Progress/index.js";
|
40
|
+
export { default as ProgressIndicator } from "./components/ProgressIndicator/index.js";
|
40
41
|
export { default as Radio } from "./components/Radio/index.js";
|
41
42
|
export { default as RadioGroup } from "./components/RadioGroup/index.js";
|
42
43
|
export { default as Reshaped } from "./components/Reshaped/index.js";
|
@@ -67,6 +68,7 @@ export { default as useToggle } from "./hooks/useToggle.js";
|
|
67
68
|
export { default as useRTL } from "./hooks/useRTL.js";
|
68
69
|
export { default as useIsomorphicLayoutEffect } from "./hooks/useIsomorphicLayoutEffect.js";
|
69
70
|
export { default as useHotkeys } from "./hooks/useHotkeys.js";
|
71
|
+
export { default as useKeyboardMode } from "./hooks/useKeyboardMode.js";
|
70
72
|
export { default as useResponsiveClientValue } from "./hooks/useResponsiveClientValue.js";
|
71
73
|
/**
|
72
74
|
* Utilities
|
@@ -1,4 +1,4 @@
|
|
1
1
|
export { focusableSelector, getActiveElement, focusNextElement, focusPreviousElement, focusFirstElement, focusLastElement, } from "./focus";
|
2
|
-
export {
|
2
|
+
export { activateKeyboardMode, deactivateKeyboardMode, checkKeyboardMode } from "./keyboardMode";
|
3
3
|
export { default as TrapFocus } from "./TrapFocus";
|
4
4
|
export type { TrapMode, FocusableElement } from "./types";
|
@@ -1,3 +1,3 @@
|
|
1
1
|
export { focusableSelector, getActiveElement, focusNextElement, focusPreviousElement, focusFirstElement, focusLastElement, } from "./focus.js";
|
2
|
-
export {
|
2
|
+
export { activateKeyboardMode, deactivateKeyboardMode, checkKeyboardMode } from "./keyboardMode.js";
|
3
3
|
export { default as TrapFocus } from "./TrapFocus.js";
|
@@ -1,3 +1,3 @@
|
|
1
|
-
export declare const
|
2
|
-
export declare const
|
1
|
+
export declare const activateKeyboardMode: () => void;
|
2
|
+
export declare const deactivateKeyboardMode: () => void;
|
3
3
|
export declare const checkKeyboardMode: () => boolean;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
const keyboardModeAttribute = "data-rs-keyboard";
|
2
|
-
export const
|
2
|
+
export const activateKeyboardMode = () => {
|
3
3
|
document.documentElement.setAttribute(keyboardModeAttribute, "true");
|
4
4
|
};
|
5
|
-
export const
|
5
|
+
export const deactivateKeyboardMode = () => {
|
6
6
|
document.documentElement.removeAttribute(keyboardModeAttribute);
|
7
7
|
};
|
8
8
|
export const checkKeyboardMode = () => {
|
@@ -23,13 +23,13 @@ export const findClosestRenderContainer = (args) => {
|
|
23
23
|
if (iteration === 0) {
|
24
24
|
const shadowRoot = getShadowRoot(el);
|
25
25
|
if (shadowRoot?.firstElementChild)
|
26
|
-
return shadowRoot.firstElementChild;
|
26
|
+
return { el: shadowRoot.firstElementChild };
|
27
27
|
}
|
28
28
|
if (el === document.body || !el)
|
29
|
-
return document.body;
|
29
|
+
return { el: document.body };
|
30
30
|
if (isScrollable && el.scrollHeight > el.clientHeight)
|
31
|
-
return el;
|
31
|
+
return { el, scrollable: true };
|
32
32
|
if (isFixed && !overflowOnly)
|
33
|
-
return el;
|
33
|
+
return { el };
|
34
34
|
return findClosestRenderContainer({ el: el.parentElement, iteration: iteration + 1 });
|
35
35
|
};
|
@@ -5,7 +5,7 @@ const styleCache = new StyleCache();
|
|
5
5
|
const lockStandardScroll = (args) => {
|
6
6
|
let container = document.body;
|
7
7
|
if (args.originEl)
|
8
|
-
container = findClosestRenderContainer({ el: args.originEl });
|
8
|
+
container = findClosestRenderContainer({ el: args.originEl }).el;
|
9
9
|
if (args.containerEl)
|
10
10
|
container = args.containerEl;
|
11
11
|
const rect = container.getBoundingClientRect();
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "reshaped",
|
3
3
|
"description": "Professionally crafted design system in React & Figma for building products of any scale and complexity",
|
4
|
-
"version": "3.
|
4
|
+
"version": "3.4.0",
|
5
5
|
"license": "MIT",
|
6
6
|
"email": "hello@reshaped.so",
|
7
7
|
"homepage": "https://reshaped.so",
|
@@ -71,9 +71,8 @@
|
|
71
71
|
"build:cjs": "tsc -p tsconfig.cjs.json && resolve-tspaths -p tsconfig.cjs.json && node ./bin/format-cjs-build.js",
|
72
72
|
"build:css": "postcss \"src/**/*.css\" --dir dist --base src --config tools/build",
|
73
73
|
"build:stories": "tsc -p tsconfig.stories.json && resolve-tspaths -p tsconfig.stories.json",
|
74
|
-
"build:bundle
|
75
|
-
"build:
|
76
|
-
"build:size": "yarn clean && yarn build:esm && yarn build:bundle:vite",
|
74
|
+
"build:bundle": "vite build && cp dist/index.d.ts dist/bundle.d.ts",
|
75
|
+
"build:size": "yarn clean && yarn build:esm && yarn build:bundle",
|
77
76
|
"build:storybook": "storybook build -o dist/app --disable-telemetry",
|
78
77
|
"build:chromatic": "STORYBOOK_ENV=chromatic storybook build",
|
79
78
|
"release": "read -p 'Have you updated chromatic tests?' && yarn release:lib && yarn release:source && yarn build:storybook && yarn release:copy",
|
@@ -1,28 +0,0 @@
|
|
1
|
-
import { StoryObj } from "@storybook/react";
|
2
|
-
import { fn } from "@storybook/test";
|
3
|
-
declare const _default: {
|
4
|
-
title: string;
|
5
|
-
};
|
6
|
-
export default _default;
|
7
|
-
export declare const defaultActive: StoryObj<{
|
8
|
-
handleOpen: ReturnType<typeof fn>;
|
9
|
-
handleClose: ReturnType<typeof fn>;
|
10
|
-
}>;
|
11
|
-
export declare const active: StoryObj<{
|
12
|
-
handleOpen: ReturnType<typeof fn>;
|
13
|
-
handleClose: ReturnType<typeof fn>;
|
14
|
-
}>;
|
15
|
-
export declare const activeFalse: StoryObj<{
|
16
|
-
handleOpen: ReturnType<typeof fn>;
|
17
|
-
handleClose: ReturnType<typeof fn>;
|
18
|
-
}>;
|
19
|
-
export declare const triggerType: StoryObj<{
|
20
|
-
handleOpen: ReturnType<typeof fn>;
|
21
|
-
handleClose: ReturnType<typeof fn>;
|
22
|
-
}>;
|
23
|
-
export declare const disabled: StoryObj<{
|
24
|
-
handleOpen: ReturnType<typeof fn>;
|
25
|
-
}>;
|
26
|
-
export declare const containerRef: StoryObj;
|
27
|
-
export declare const shadowDom: StoryObj;
|
28
|
-
export declare const className: StoryObj;
|
@@ -1,205 +0,0 @@
|
|
1
|
-
import { expect, fn, userEvent, within, waitFor } from "@storybook/test";
|
2
|
-
import Flyout from "../index.js";
|
3
|
-
import Button from "../../../Button/index.js";
|
4
|
-
import Reshaped from "../../../Reshaped/index.js";
|
5
|
-
import { useRef } from "react";
|
6
|
-
import { createRoot } from "react-dom/client";
|
7
|
-
import { sleep } from "../../../../utilities/helpers.js";
|
8
|
-
export default {
|
9
|
-
title: "Internal/Flyout/tests",
|
10
|
-
};
|
11
|
-
export const defaultActive = {
|
12
|
-
name: "defaultActive, uncontrolled",
|
13
|
-
args: {
|
14
|
-
handleOpen: fn(),
|
15
|
-
handleClose: fn(),
|
16
|
-
},
|
17
|
-
render: (args) => (<Flyout onOpen={args.handleOpen} onClose={args.handleClose} defaultActive>
|
18
|
-
<Flyout.Trigger>
|
19
|
-
{(attributes) => <Button attributes={attributes}>Open</Button>}
|
20
|
-
</Flyout.Trigger>
|
21
|
-
<Flyout.Content>Content</Flyout.Content>
|
22
|
-
</Flyout>),
|
23
|
-
play: async ({ canvasElement, args }) => {
|
24
|
-
const canvas = within(canvasElement.ownerDocument.body);
|
25
|
-
const trigger = canvas.getAllByRole("button")[0];
|
26
|
-
let item = canvas.getByText("Content");
|
27
|
-
await sleep(500);
|
28
|
-
await userEvent.click(document.body);
|
29
|
-
await waitFor(() => {
|
30
|
-
expect(args.handleClose).toHaveBeenCalledTimes(1);
|
31
|
-
expect(args.handleClose).toHaveBeenCalledWith();
|
32
|
-
expect(item).not.toBeInTheDocument();
|
33
|
-
});
|
34
|
-
await userEvent.click(trigger);
|
35
|
-
await waitFor(() => {
|
36
|
-
expect(args.handleOpen).toHaveBeenCalledTimes(1);
|
37
|
-
expect(args.handleOpen).toHaveBeenCalledWith();
|
38
|
-
});
|
39
|
-
item = canvas.getByText("Content");
|
40
|
-
expect(item).toBeInTheDocument();
|
41
|
-
},
|
42
|
-
};
|
43
|
-
export const active = {
|
44
|
-
name: "active, controlled",
|
45
|
-
args: {
|
46
|
-
handleOpen: fn(),
|
47
|
-
handleClose: fn(),
|
48
|
-
},
|
49
|
-
render: (args) => (<Flyout onOpen={args.handleOpen} onClose={args.handleClose} active>
|
50
|
-
<Flyout.Trigger>
|
51
|
-
{(attributes) => <Button attributes={attributes}>Open</Button>}
|
52
|
-
</Flyout.Trigger>
|
53
|
-
<Flyout.Content>Content</Flyout.Content>
|
54
|
-
</Flyout>),
|
55
|
-
play: async ({ canvasElement, args }) => {
|
56
|
-
const canvas = within(canvasElement.ownerDocument.body);
|
57
|
-
const item = canvas.getByText("Content");
|
58
|
-
await userEvent.click(document.body);
|
59
|
-
await waitFor(() => {
|
60
|
-
expect(args.handleClose).toHaveBeenCalledTimes(1);
|
61
|
-
expect(args.handleClose).toHaveBeenCalledWith();
|
62
|
-
});
|
63
|
-
expect(item).toBeInTheDocument();
|
64
|
-
},
|
65
|
-
};
|
66
|
-
export const activeFalse = {
|
67
|
-
name: "active false, controlled",
|
68
|
-
args: {
|
69
|
-
handleOpen: fn(),
|
70
|
-
handleClose: fn(),
|
71
|
-
},
|
72
|
-
render: (args) => (<Flyout onOpen={args.handleOpen} onClose={args.handleClose} active={false}>
|
73
|
-
<Flyout.Trigger>
|
74
|
-
{(attributes) => <Button attributes={attributes}>Open</Button>}
|
75
|
-
</Flyout.Trigger>
|
76
|
-
<Flyout.Content>Content</Flyout.Content>
|
77
|
-
</Flyout>),
|
78
|
-
play: async ({ canvasElement, args }) => {
|
79
|
-
const canvas = within(canvasElement.ownerDocument.body);
|
80
|
-
const trigger = canvas.getAllByRole("button")[0];
|
81
|
-
await userEvent.click(trigger);
|
82
|
-
await waitFor(() => {
|
83
|
-
expect(args.handleOpen).toHaveBeenCalledTimes(1);
|
84
|
-
expect(args.handleOpen).toHaveBeenCalledWith();
|
85
|
-
});
|
86
|
-
const item = canvas.queryByText("Content");
|
87
|
-
expect(item).not.toBeInTheDocument();
|
88
|
-
},
|
89
|
-
};
|
90
|
-
export const triggerType = {
|
91
|
-
name: "triggerType hover",
|
92
|
-
args: {
|
93
|
-
handleOpen: fn(),
|
94
|
-
handleClose: fn(),
|
95
|
-
},
|
96
|
-
render: (args) => (<Flyout onOpen={args.handleOpen} onClose={args.handleClose} triggerType="hover">
|
97
|
-
<Flyout.Trigger>
|
98
|
-
{(attributes) => <Button attributes={attributes}>Open</Button>}
|
99
|
-
</Flyout.Trigger>
|
100
|
-
<Flyout.Content>Content</Flyout.Content>
|
101
|
-
</Flyout>),
|
102
|
-
play: async ({ canvasElement, args }) => {
|
103
|
-
const canvas = within(canvasElement.ownerDocument.body);
|
104
|
-
const trigger = canvas.getAllByRole("button")[0];
|
105
|
-
await userEvent.hover(trigger);
|
106
|
-
await waitFor(() => {
|
107
|
-
expect(args.handleOpen).toHaveBeenCalledTimes(1);
|
108
|
-
expect(args.handleOpen).toHaveBeenCalledWith();
|
109
|
-
});
|
110
|
-
await userEvent.unhover(trigger);
|
111
|
-
await waitFor(() => {
|
112
|
-
expect(args.handleClose).toHaveBeenCalledTimes(1);
|
113
|
-
expect(args.handleClose).toHaveBeenCalledWith();
|
114
|
-
});
|
115
|
-
},
|
116
|
-
};
|
117
|
-
export const disabled = {
|
118
|
-
name: "disabled",
|
119
|
-
args: {
|
120
|
-
handleOpen: fn(),
|
121
|
-
},
|
122
|
-
render: () => (<div data-testid="root">
|
123
|
-
<Flyout disabled>
|
124
|
-
<Flyout.Trigger>
|
125
|
-
{(attributes) => <Button attributes={attributes}>Open</Button>}
|
126
|
-
</Flyout.Trigger>
|
127
|
-
<Flyout.Content className="test-classname" attributes={{ "data-testid": "test-id" }}>
|
128
|
-
Content
|
129
|
-
</Flyout.Content>
|
130
|
-
</Flyout>
|
131
|
-
</div>),
|
132
|
-
play: async ({ canvasElement, args }) => {
|
133
|
-
const canvas = within(canvasElement.ownerDocument.body);
|
134
|
-
const button = canvas.getAllByRole("button")[0];
|
135
|
-
await userEvent.click(button);
|
136
|
-
expect(args.handleOpen).toHaveBeenCalledTimes(0);
|
137
|
-
},
|
138
|
-
};
|
139
|
-
export const containerRef = {
|
140
|
-
name: "containerRef",
|
141
|
-
render: () => {
|
142
|
-
const portalRef = useRef(null);
|
143
|
-
return (<div ref={portalRef} data-testid="test-id">
|
144
|
-
<Flyout containerRef={portalRef} active>
|
145
|
-
<Flyout.Trigger>
|
146
|
-
{(attributes) => <Button attributes={attributes}>Trigger</Button>}
|
147
|
-
</Flyout.Trigger>
|
148
|
-
<Flyout.Content>Content</Flyout.Content>
|
149
|
-
</Flyout>
|
150
|
-
</div>);
|
151
|
-
},
|
152
|
-
play: async ({ canvasElement }) => {
|
153
|
-
const canvas = within(canvasElement.ownerDocument.body);
|
154
|
-
const containerEl = canvas.getByTestId("test-id");
|
155
|
-
const contentEl = canvas.getByText("Content");
|
156
|
-
expect(containerEl).toContainElement(contentEl);
|
157
|
-
},
|
158
|
-
};
|
159
|
-
class CustomElement extends window.HTMLElement {
|
160
|
-
constructor() {
|
161
|
-
super();
|
162
|
-
this.attachShadow({ mode: "open" });
|
163
|
-
if (!this.shadowRoot)
|
164
|
-
return;
|
165
|
-
const root = createRoot(this.shadowRoot);
|
166
|
-
root.render(<Reshaped>
|
167
|
-
<Flyout active>
|
168
|
-
<Flyout.Trigger>
|
169
|
-
{(attributes) => <button {...attributes}>Trigger</button>}
|
170
|
-
</Flyout.Trigger>
|
171
|
-
<Flyout.Content>
|
172
|
-
<div id="test-id"/>
|
173
|
-
</Flyout.Content>
|
174
|
-
</Flyout>
|
175
|
-
</Reshaped>);
|
176
|
-
}
|
177
|
-
}
|
178
|
-
window.customElements.define("custom-element-flyout", CustomElement);
|
179
|
-
export const shadowDom = {
|
180
|
-
name: "shadow DOM",
|
181
|
-
// @ts-ignore
|
182
|
-
render: () => <custom-element-flyout />,
|
183
|
-
play: async () => {
|
184
|
-
expect(document.querySelector("custom-element-flyout")?.shadowRoot?.querySelector(`#test-id`)).toBeTruthy();
|
185
|
-
expect(document.body.querySelector(`#test-id`)).toBe(null);
|
186
|
-
},
|
187
|
-
};
|
188
|
-
export const className = {
|
189
|
-
name: "className, attributes",
|
190
|
-
render: () => (<div data-testid="root">
|
191
|
-
<Flyout active>
|
192
|
-
<Flyout.Trigger>
|
193
|
-
{(attributes) => <Button attributes={attributes}>Open</Button>}
|
194
|
-
</Flyout.Trigger>
|
195
|
-
<Flyout.Content className="test-classname" attributes={{ "data-testid": "test-id" }}>
|
196
|
-
Content
|
197
|
-
</Flyout.Content>
|
198
|
-
</Flyout>
|
199
|
-
</div>),
|
200
|
-
play: async ({ canvasElement }) => {
|
201
|
-
const canvas = within(canvasElement.ownerDocument.body);
|
202
|
-
const menu = await canvas.findByTestId("test-id");
|
203
|
-
expect(menu).toHaveClass("test-classname");
|
204
|
-
},
|
205
|
-
};
|