@lumx/react 3.9.4 → 3.9.5-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +7 -27
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/chip/Chip.test.tsx +15 -0
- package/src/components/chip/Chip.tsx +1 -1
- package/src/components/expansion-panel/ExpansionPanel.test.tsx +32 -2
- package/src/components/expansion-panel/ExpansionPanel.tsx +6 -30
package/package.json
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"url": "https://github.com/lumapps/design-system/issues"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@lumx/core": "^3.9.
|
|
10
|
-
"@lumx/icons": "^3.9.
|
|
9
|
+
"@lumx/core": "^3.9.5-alpha.0",
|
|
10
|
+
"@lumx/icons": "^3.9.5-alpha.0",
|
|
11
11
|
"@popperjs/core": "^2.5.4",
|
|
12
12
|
"body-scroll-lock": "^3.1.5",
|
|
13
13
|
"classnames": "^2.3.2",
|
|
@@ -111,5 +111,5 @@
|
|
|
111
111
|
"build:storybook": "storybook build"
|
|
112
112
|
},
|
|
113
113
|
"sideEffects": false,
|
|
114
|
-
"version": "3.9.
|
|
114
|
+
"version": "3.9.5-alpha.0"
|
|
115
115
|
}
|
|
@@ -168,6 +168,21 @@ describe('<Chip />', () => {
|
|
|
168
168
|
fireEvent.keyDown(chip, { key: 'A', code: 'KeyA' });
|
|
169
169
|
expect(onKeyDown).toHaveBeenCalled();
|
|
170
170
|
});
|
|
171
|
+
|
|
172
|
+
it('should forward key down event and trigger `onClick` when pressing Enter', async () => {
|
|
173
|
+
const user = userEvent.setup();
|
|
174
|
+
const onKeyDown = jest.fn();
|
|
175
|
+
const { chip } = setup({ onClick, onKeyDown });
|
|
176
|
+
|
|
177
|
+
await user.tab();
|
|
178
|
+
expect(chip).toHaveFocus();
|
|
179
|
+
|
|
180
|
+
await userEvent.keyboard('{Enter}');
|
|
181
|
+
|
|
182
|
+
expect(onKeyDown).toHaveBeenCalled();
|
|
183
|
+
expect(onClick).toHaveBeenCalled();
|
|
184
|
+
onClick.mockClear();
|
|
185
|
+
});
|
|
171
186
|
});
|
|
172
187
|
|
|
173
188
|
commonTestsSuiteRTL(setup, { baseClassName: CLASSNAME, forwardClassName: 'chip', forwardAttributes: 'chip' });
|
|
@@ -101,7 +101,7 @@ export const Chip: Comp<ChipProps, HTMLAnchorElement> = forwardRef((props, ref)
|
|
|
101
101
|
const handleKeyDown = (evt: React.KeyboardEvent) => {
|
|
102
102
|
onKeyDown?.(evt);
|
|
103
103
|
if (hasOnClick) {
|
|
104
|
-
onEnterPressed(onClick);
|
|
104
|
+
onEnterPressed(onClick)(evt);
|
|
105
105
|
}
|
|
106
106
|
};
|
|
107
107
|
|
|
@@ -6,6 +6,7 @@ import { getByClassName, queryByClassName } from '@lumx/react/testing/utils/quer
|
|
|
6
6
|
import userEvent from '@testing-library/user-event';
|
|
7
7
|
import { isFocusVisible } from '@lumx/react/utils/isFocusVisible';
|
|
8
8
|
|
|
9
|
+
import { useBooleanState } from '@lumx/react/hooks/useBooleanState';
|
|
9
10
|
import { ExpansionPanel, ExpansionPanelProps } from '.';
|
|
10
11
|
|
|
11
12
|
const CLASSNAME = ExpansionPanel.className as string;
|
|
@@ -14,16 +15,29 @@ jest.mock('@lumx/react/utils/isFocusVisible');
|
|
|
14
15
|
|
|
15
16
|
const mockChildrenContent = 'children content';
|
|
16
17
|
|
|
18
|
+
/** Controlled component that uses a local state to toggle the component */
|
|
19
|
+
const ControlledComponent = (props: ExpansionPanelProps) => {
|
|
20
|
+
const [isOpen, handleClose, handleOpen] = useBooleanState(false);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ExpansionPanel isOpen={isOpen} onClose={handleClose} onOpen={handleOpen} {...props}>
|
|
24
|
+
{mockChildrenContent}
|
|
25
|
+
</ExpansionPanel>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
17
29
|
/**
|
|
18
30
|
* Mounts the component and returns common DOM elements / data needed in multiple tests further down.
|
|
19
31
|
*/
|
|
20
|
-
const setup = (propsOverride: Partial<ExpansionPanelProps> = {}) => {
|
|
32
|
+
const setup = (propsOverride: Partial<ExpansionPanelProps> = {}, options: { controlled?: boolean } = {}) => {
|
|
21
33
|
const props = {
|
|
22
34
|
toggleButtonProps: { label: 'Toggle' },
|
|
23
35
|
children: mockChildrenContent,
|
|
24
36
|
...propsOverride,
|
|
25
37
|
};
|
|
26
|
-
|
|
38
|
+
|
|
39
|
+
const Component = options.controlled ? ControlledComponent : ExpansionPanel;
|
|
40
|
+
const { container } = render(<Component {...props} />);
|
|
27
41
|
|
|
28
42
|
return {
|
|
29
43
|
container,
|
|
@@ -116,6 +130,22 @@ describe(`<${ExpansionPanel.displayName}>`, () => {
|
|
|
116
130
|
expect(onClose).toHaveBeenCalled();
|
|
117
131
|
expect(onToggleOpen).toHaveBeenCalledWith(false, expect.anything());
|
|
118
132
|
});
|
|
133
|
+
|
|
134
|
+
it('should hide children after toggling the expansion panel', async () => {
|
|
135
|
+
const user = userEvent.setup();
|
|
136
|
+
const { query } = setup({}, { controlled: true });
|
|
137
|
+
|
|
138
|
+
// Content is not visible by default
|
|
139
|
+
expect(query.content()).not.toBeInTheDocument();
|
|
140
|
+
|
|
141
|
+
await user.click(query.header() as any);
|
|
142
|
+
|
|
143
|
+
expect(query.content()).toBeInTheDocument();
|
|
144
|
+
|
|
145
|
+
await user.click(query.header() as any);
|
|
146
|
+
|
|
147
|
+
expect(query.content()).not.toBeInTheDocument();
|
|
148
|
+
});
|
|
119
149
|
});
|
|
120
150
|
|
|
121
151
|
// Common tests suite.
|
|
@@ -12,7 +12,8 @@ import { ColorPalette, DragHandle, Emphasis, IconButton, IconButtonProps, Theme
|
|
|
12
12
|
import { Comp, GenericProps, HasTheme, isComponent } from '@lumx/react/utils/type';
|
|
13
13
|
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
|
|
14
14
|
import { partitionMulti } from '@lumx/react/utils/partitionMulti';
|
|
15
|
-
import {
|
|
15
|
+
import { useTransitionVisibility } from '@lumx/react/hooks/useTransitionVisibility';
|
|
16
|
+
import { EXPANSION_PANEL_TRANSITION_DURATION } from '@lumx/core/js/constants';
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Defines the props of the component.
|
|
@@ -81,7 +82,6 @@ export const ExpansionPanel: Comp<ExpansionPanelProps, HTMLDivElement> = forward
|
|
|
81
82
|
...forwardedProps
|
|
82
83
|
} = props;
|
|
83
84
|
|
|
84
|
-
const [isChildrenVisible, setIsChildrenVisible] = useState(isOpen);
|
|
85
85
|
const children: ReactNode[] = Children.toArray(anyChildren);
|
|
86
86
|
|
|
87
87
|
// Partition children by types.
|
|
@@ -96,34 +96,16 @@ export const ExpansionPanel: Comp<ExpansionPanelProps, HTMLDivElement> = forward
|
|
|
96
96
|
);
|
|
97
97
|
|
|
98
98
|
const toggleOpen = (event: React.MouseEvent) => {
|
|
99
|
-
const hasReducedMotionEnabled = WINDOW?.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches;
|
|
100
99
|
const shouldOpen = !isOpen;
|
|
101
100
|
|
|
102
101
|
if (isFunction(onOpen) && shouldOpen) {
|
|
103
102
|
onOpen(event);
|
|
104
|
-
// On open, we immediately show children
|
|
105
|
-
setIsChildrenVisible(true);
|
|
106
103
|
}
|
|
107
104
|
if (isFunction(onClose) && !shouldOpen) {
|
|
108
105
|
onClose(event);
|
|
109
|
-
/**
|
|
110
|
-
* On close, we only show children immediately if reduced motion is enabled
|
|
111
|
-
* When disabled, the children will be hidden via the `onTransitionEnd` prop.
|
|
112
|
-
*/
|
|
113
|
-
if (hasReducedMotionEnabled) {
|
|
114
|
-
setIsChildrenVisible(false);
|
|
115
|
-
}
|
|
116
106
|
}
|
|
117
107
|
if (isFunction(onToggleOpen)) {
|
|
118
108
|
onToggleOpen(shouldOpen, event);
|
|
119
|
-
/**
|
|
120
|
-
* On toggle, we forward the show state if
|
|
121
|
-
* * the toggle will open the expansion panel
|
|
122
|
-
* * reduced motion is enabled. When disabled, the children will be hidden via the `onTransitionEnd` prop.
|
|
123
|
-
* */
|
|
124
|
-
if (shouldOpen || hasReducedMotionEnabled) {
|
|
125
|
-
setIsChildrenVisible(shouldOpen);
|
|
126
|
-
}
|
|
127
109
|
}
|
|
128
110
|
};
|
|
129
111
|
|
|
@@ -145,6 +127,9 @@ export const ExpansionPanel: Comp<ExpansionPanelProps, HTMLDivElement> = forward
|
|
|
145
127
|
|
|
146
128
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
147
129
|
|
|
130
|
+
/** Hide the children at the end of the transition */
|
|
131
|
+
const isChildrenVisible = useTransitionVisibility(wrapperRef, !!isOpen, EXPANSION_PANEL_TRANSITION_DURATION);
|
|
132
|
+
|
|
148
133
|
// Switch max height on/off to activate the CSS transition (updates when children changes).
|
|
149
134
|
const [maxHeight, setMaxHeight] = useState('0');
|
|
150
135
|
useEffect(() => {
|
|
@@ -174,16 +159,7 @@ export const ExpansionPanel: Comp<ExpansionPanelProps, HTMLDivElement> = forward
|
|
|
174
159
|
</header>
|
|
175
160
|
|
|
176
161
|
{(isOpen || isChildrenVisible) && (
|
|
177
|
-
<div
|
|
178
|
-
className={`${CLASSNAME}__wrapper`}
|
|
179
|
-
style={{ maxHeight }}
|
|
180
|
-
// At the end of the closing transition, remove the children from the DOM
|
|
181
|
-
onTransitionEnd={() => {
|
|
182
|
-
if (!isOpen) {
|
|
183
|
-
setIsChildrenVisible(false);
|
|
184
|
-
}
|
|
185
|
-
}}
|
|
186
|
-
>
|
|
162
|
+
<div className={`${CLASSNAME}__wrapper`} style={{ maxHeight }}>
|
|
187
163
|
<div className={`${CLASSNAME}__container`} ref={wrapperRef}>
|
|
188
164
|
<div className={`${CLASSNAME}__content`}>{content}</div>
|
|
189
165
|
|