@lumx/react 3.13.3-alpha.1 → 3.13.3-alpha.3

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/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.13.3-alpha.1",
10
- "@lumx/icons": "^3.13.3-alpha.1",
9
+ "@lumx/core": "^3.13.3-alpha.3",
10
+ "@lumx/icons": "^3.13.3-alpha.3",
11
11
  "@popperjs/core": "^2.5.4",
12
12
  "body-scroll-lock": "^3.1.5",
13
13
  "classnames": "^2.3.2",
@@ -110,5 +110,5 @@
110
110
  "build:storybook": "storybook build"
111
111
  },
112
112
  "sideEffects": false,
113
- "version": "3.13.3-alpha.1"
113
+ "version": "3.13.3-alpha.3"
114
114
  }
@@ -1,9 +1,18 @@
1
1
  /* eslint-disable react-hooks/rules-of-hooks */
2
2
  import React from 'react';
3
3
 
4
- import { ExpansionPanel, FlexBox } from '@lumx/react';
4
+ import { ExpansionPanel, ExpansionPanelProps, Text } from '@lumx/react';
5
5
  import { withNestedProps } from '@lumx/react/stories/decorators/withNestedProps';
6
6
 
7
+ function useBaseProps({
8
+ toggleButtonProps = { label: 'Toggle' },
9
+ isOpen: initiallyOpen,
10
+ ...args
11
+ }: Partial<ExpansionPanelProps>) {
12
+ const [isOpen, setOpen] = React.useState(initiallyOpen);
13
+ return { isOpen, toggleButtonProps, onToggleOpen: setOpen, ...args };
14
+ }
15
+
7
16
  export default {
8
17
  title: 'LumX components/expansion-panel/ExpansionPanel',
9
18
  component: ExpansionPanel,
@@ -13,11 +22,8 @@ export default {
13
22
  label: 'Label',
14
23
  },
15
24
  decorators: [withNestedProps()],
16
- render({ toggleButtonProps, ...args }: any) {
17
- const [isOpen, setOpen] = React.useState(args.isOpen);
18
- return (
19
- <ExpansionPanel isOpen={isOpen} toggleButtonProps={toggleButtonProps} onToggleOpen={setOpen} {...args} />
20
- );
25
+ render(args: ExpansionPanelProps) {
26
+ return <ExpansionPanel {...useBaseProps(args)} />;
21
27
  },
22
28
  };
23
29
 
@@ -40,19 +46,34 @@ export const HasHeaderDivider = {
40
46
  },
41
47
  };
42
48
 
43
- /** Test resizable content work */
44
- export const ResizingContent = {
45
- args: {
46
- hasBackground: true,
47
- children: (
48
- <FlexBox
49
- style={{ resize: 'both', overflow: 'hidden' }}
50
- hAlign="center"
51
- vAlign="center"
52
- className="lumx-spacing-padding-huge"
53
- >
54
- Content
55
- </FlexBox>
56
- ),
49
+ /** Nested expansion panels */
50
+ export const Nested = {
51
+ args: {},
52
+ render(args: ExpansionPanelProps) {
53
+ return (
54
+ <ExpansionPanel {...useBaseProps(args)}>
55
+ <ExpansionPanel
56
+ label="Child 1"
57
+ hasBackground
58
+ className="lumx-spacing-margin-left-huge lumx-spacing-margin-bottom-big"
59
+ {...useBaseProps(args)}
60
+ >
61
+ <Text as="p" typography="body1" color="dark-L2" className="lumx-spacing-padding-big">
62
+ content child 1
63
+ </Text>
64
+ </ExpansionPanel>
65
+
66
+ <ExpansionPanel
67
+ label="Child 2"
68
+ hasBackground
69
+ className="lumx-spacing-margin-left-huge lumx-spacing-margin-bottom-big"
70
+ {...useBaseProps(args)}
71
+ >
72
+ <Text as="p" typography="body1" color="dark-L2" className="lumx-spacing-padding-big">
73
+ content child 2
74
+ </Text>
75
+ </ExpansionPanel>
76
+ </ExpansionPanel>
77
+ );
57
78
  },
58
79
  };
@@ -1,21 +1,18 @@
1
- import React, { Children, PropsWithChildren, ReactNode, useEffect, useRef, useState } from 'react';
1
+ import React, { Children, PropsWithChildren, ReactNode, useRef } from 'react';
2
2
 
3
3
  import classNames from 'classnames';
4
4
 
5
5
  import { mdiChevronDown, mdiChevronUp } from '@lumx/icons';
6
6
 
7
- import get from 'lodash/get';
8
7
  import isEmpty from 'lodash/isEmpty';
9
- import isFunction from 'lodash/isFunction';
10
8
 
11
9
  import { ColorPalette, DragHandle, Emphasis, IconButton, IconButtonProps, Theme } from '@lumx/react';
12
10
  import { GenericProps, HasTheme, isComponent } from '@lumx/react/utils/type';
13
11
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
14
12
  import { partitionMulti } from '@lumx/react/utils/partitionMulti';
15
- import { useTransitionVisibility } from '@lumx/react/hooks/useTransitionVisibility';
16
- import { EXPANSION_PANEL_TRANSITION_DURATION } from '@lumx/core/js/constants';
17
13
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
18
14
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
15
+ import { IS_BROWSER } from '@lumx/react/constants';
19
16
 
20
17
  /**
21
18
  * Defines the props of the component.
@@ -101,13 +98,13 @@ export const ExpansionPanel = forwardRef<ExpansionPanelProps, HTMLDivElement>((p
101
98
  const toggleOpen = (event: React.MouseEvent) => {
102
99
  const shouldOpen = !isOpen;
103
100
 
104
- if (isFunction(onOpen) && shouldOpen) {
101
+ if (onOpen && shouldOpen) {
105
102
  onOpen(event);
106
103
  }
107
- if (isFunction(onClose) && !shouldOpen) {
104
+ if (onClose && !shouldOpen) {
108
105
  onClose(event);
109
106
  }
110
- if (isFunction(onToggleOpen)) {
107
+ if (onToggleOpen) {
111
108
  onToggleOpen(shouldOpen, event);
112
109
  }
113
110
  };
@@ -130,18 +127,31 @@ export const ExpansionPanel = forwardRef<ExpansionPanelProps, HTMLDivElement>((p
130
127
 
131
128
  const wrapperRef = useRef<HTMLDivElement>(null);
132
129
 
133
- /** Hide the children at the end of the transition */
134
- const isChildrenVisible = useTransitionVisibility(wrapperRef, !!isOpen, EXPANSION_PANEL_TRANSITION_DURATION);
130
+ // Children visible while the open/close transition is running
131
+ const [isChildrenVisible, setChildrenVisible] = React.useState(isOpen);
135
132
 
136
- // Switch max height on/off to activate the CSS transition (updates when children changes).
137
- const [maxHeight, setMaxHeight] = useState<string | undefined>('0');
138
- useEffect(() => {
139
- const height = isOpen ? get(wrapperRef.current, 'offsetHeight', 0) : 0;
140
- setMaxHeight(`${height}px`);
133
+ const isOpenRef = React.useRef(isOpen);
134
+ React.useEffect(() => {
135
+ if (isOpen) {
136
+ setChildrenVisible(true);
137
+ } else if (!IS_BROWSER) {
138
+ // Outside a browser we can't wait for the transition
139
+ setChildrenVisible(false);
140
+ }
141
+ isOpenRef.current = isOpen;
141
142
  }, [isOpen]);
142
143
 
143
- const onTransitionEnd = React.useCallback(() => {
144
- setMaxHeight(undefined);
144
+ // Change children visibility on transition end
145
+ React.useEffect(() => {
146
+ const { current: wrapper } = wrapperRef;
147
+ if (!IS_BROWSER || !wrapper) {
148
+ return undefined;
149
+ }
150
+ const onTransitionEnd = () => {
151
+ setChildrenVisible(isOpenRef.current);
152
+ };
153
+ wrapper.addEventListener('transitionend', onTransitionEnd);
154
+ return () => wrapper.removeEventListener('transitionend', onTransitionEnd);
145
155
  }, []);
146
156
 
147
157
  return (
@@ -165,15 +175,15 @@ export const ExpansionPanel = forwardRef<ExpansionPanelProps, HTMLDivElement>((p
165
175
  </div>
166
176
  </header>
167
177
 
168
- {(isOpen || isChildrenVisible) && (
169
- <div className={`${CLASSNAME}__wrapper`} style={{ maxHeight }} onTransitionEnd={onTransitionEnd}>
170
- <div className={`${CLASSNAME}__container`} ref={wrapperRef}>
178
+ <div className={`${CLASSNAME}__wrapper`} ref={wrapperRef}>
179
+ {(isOpen || isChildrenVisible) && (
180
+ <div className={`${CLASSNAME}__container`}>
171
181
  <div className={`${CLASSNAME}__content`}>{content}</div>
172
182
 
173
183
  {footer && <div className={`${CLASSNAME}__footer`}>{footer}</div>}
174
184
  </div>
175
- </div>
176
- )}
185
+ )}
186
+ </div>
177
187
  </section>
178
188
  );
179
189
  });