Skip to content

Commit 7e2c6a1

Browse files
authored
Merge pull request #836 from szhsin/feat/rsc
feat: react server component
2 parents 219b440 + 9bd4275 commit 7e2c6a1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+659
-460
lines changed

dist/cjs/components/Accordion.cjs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
3+
var React = require('react');
4+
var useAccordionProvider = require('../hooks/useAccordionProvider.cjs');
5+
var ControlledAccordion = require('./ControlledAccordion.cjs');
6+
var jsxRuntime = require('react/jsx-runtime');
7+
8+
const Accordion = /*#__PURE__*/React.forwardRef(({
9+
allowMultiple,
10+
initialEntered,
11+
mountOnEnter,
12+
unmountOnExit,
13+
transition,
14+
transitionTimeout,
15+
onStateChange,
16+
...rest
17+
}, ref) => {
18+
const providerValue = useAccordionProvider.useAccordionProvider({
19+
allowMultiple,
20+
initialEntered,
21+
mountOnEnter,
22+
unmountOnExit,
23+
transition,
24+
transitionTimeout,
25+
onStateChange
26+
});
27+
return /*#__PURE__*/jsxRuntime.jsx(ControlledAccordion.ControlledAccordion, {
28+
...rest,
29+
ref: ref,
30+
providerValue: providerValue
31+
});
32+
});
33+
Accordion.displayName = 'Accordion';
34+
35+
exports.Accordion = Accordion;
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
'use strict';
2+
3+
var React = require('react');
4+
var constants = require('../utils/constants.cjs');
5+
var bem = require('../utils/bem.cjs');
6+
var mergeProps = require('../utils/mergeProps.cjs');
7+
var useAccordionItem = require('../hooks/useAccordionItem.cjs');
8+
var useHeightTransition = require('../hooks/useHeightTransition.cjs');
9+
var useMergeRef = require('../hooks/useMergeRef.cjs');
10+
var withAccordionItem = require('./withAccordionItem.cjs');
11+
var jsxRuntime = require('react/jsx-runtime');
12+
13+
const getRenderNode = (nodeOrFunc, props) => typeof nodeOrFunc === 'function' ? nodeOrFunc(props) : nodeOrFunc;
14+
const WrappedItem = /*#__PURE__*/React.memo(({
15+
forwardedRef,
16+
itemRef,
17+
state,
18+
toggle,
19+
className,
20+
disabled,
21+
header,
22+
headingTag: Heading = 'h3',
23+
headingProps,
24+
buttonProps,
25+
contentProps,
26+
panelProps,
27+
children,
28+
...rest
29+
}) => {
30+
const itemState = {
31+
state,
32+
toggle,
33+
disabled
34+
};
35+
const {
36+
buttonProps: _buttonProps,
37+
panelProps: _panelProps
38+
} = useAccordionItem.useAccordionItem(itemState);
39+
const [transitionStyle, _panelRef] = useHeightTransition.useHeightTransition(state);
40+
const panelRef = useMergeRef.useMergeRef(panelProps?.ref, _panelRef);
41+
const {
42+
status,
43+
isMounted,
44+
isEnter
45+
} = state;
46+
return /*#__PURE__*/jsxRuntime.jsxs("div", {
47+
...rest,
48+
ref: useMergeRef.useMergeRef(forwardedRef, itemRef),
49+
className: bem.bem(constants.ACCORDION_BLOCK, 'item', {
50+
status,
51+
expanded: isEnter
52+
})(className, state),
53+
children: [/*#__PURE__*/jsxRuntime.jsx(Heading, {
54+
...headingProps,
55+
style: {
56+
margin: 0,
57+
...headingProps?.style
58+
},
59+
className: bem.bem(constants.ACCORDION_BLOCK, 'item-heading')(headingProps?.className, state),
60+
children: /*#__PURE__*/jsxRuntime.jsx("button", {
61+
...mergeProps.mergeProps(_buttonProps, buttonProps),
62+
type: "button",
63+
className: bem.bem(constants.ACCORDION_BLOCK, 'item-btn')(buttonProps?.className, state),
64+
children: getRenderNode(header, itemState)
65+
})
66+
}), isMounted && /*#__PURE__*/jsxRuntime.jsx("div", {
67+
...contentProps,
68+
style: {
69+
display: status === 'exited' ? 'none' : undefined,
70+
...transitionStyle,
71+
...contentProps?.style
72+
},
73+
className: bem.bem(constants.ACCORDION_BLOCK, 'item-content')(contentProps?.className, state),
74+
children: /*#__PURE__*/jsxRuntime.jsx("div", {
75+
...mergeProps.mergeProps(_panelProps, panelProps),
76+
ref: panelRef,
77+
className: bem.bem(constants.ACCORDION_BLOCK, 'item-panel')(panelProps?.className, state),
78+
children: getRenderNode(children, itemState)
79+
})
80+
})]
81+
});
82+
});
83+
WrappedItem.displayName = 'AccordionItem';
84+
const AccordionItem = /*#__PURE__*/withAccordionItem.withAccordionItem(WrappedItem);
85+
86+
exports.AccordionItem = AccordionItem;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
var constants = require('../utils/constants.cjs');
4+
var jsxRuntime = require('react/jsx-runtime');
5+
6+
const AccordionProvider = props => /*#__PURE__*/jsxRuntime.jsx(constants.AccordionContext.Provider, {
7+
...props
8+
});
9+
10+
exports.AccordionProvider = AccordionProvider;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict';
2+
3+
var React = require('react');
4+
var constants = require('../utils/constants.cjs');
5+
var bem = require('../utils/bem.cjs');
6+
var mergeProps = require('../utils/mergeProps.cjs');
7+
var AccordionProvider = require('./AccordionProvider.cjs');
8+
var useAccordion = require('../hooks/useAccordion.cjs');
9+
var jsxRuntime = require('react/jsx-runtime');
10+
11+
const ControlledAccordion = /*#__PURE__*/React.forwardRef(({
12+
providerValue,
13+
className,
14+
...rest
15+
}, ref) => {
16+
const {
17+
accordionProps
18+
} = useAccordion.useAccordion();
19+
return /*#__PURE__*/jsxRuntime.jsx(AccordionProvider.AccordionProvider, {
20+
value: providerValue,
21+
children: /*#__PURE__*/jsxRuntime.jsx("div", {
22+
...mergeProps.mergeProps(accordionProps, rest),
23+
ref: ref,
24+
className: bem.bem(constants.ACCORDION_BLOCK)(className)
25+
})
26+
});
27+
});
28+
ControlledAccordion.displayName = 'ControlledAccordion';
29+
30+
exports.ControlledAccordion = ControlledAccordion;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
var React = require('react');
4+
var useAccordionItemEffect = require('../hooks/useAccordionItemEffect.cjs');
5+
var jsxRuntime = require('react/jsx-runtime');
6+
7+
const withAccordionItem = WrappedItem => {
8+
const WithAccordionItem = /*#__PURE__*/React.forwardRef(({
9+
itemKey,
10+
initialEntered,
11+
...rest
12+
}, ref) => /*#__PURE__*/jsxRuntime.jsx(WrappedItem, {
13+
forwardedRef: ref,
14+
...rest,
15+
...useAccordionItemEffect.useAccordionItemEffect({
16+
itemKey,
17+
initialEntered,
18+
disabled: rest.disabled
19+
})
20+
}));
21+
WithAccordionItem.displayName = 'WithAccordionItem';
22+
return WithAccordionItem;
23+
};
24+
25+
exports.withAccordionItem = withAccordionItem;

dist/cjs/hooks/useAccordion.cjs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
var constants = require('../utils/constants.cjs');
4+
5+
const getAccordion = node => {
6+
do {
7+
node = node.parentElement;
8+
} while (node && !node.hasAttribute(constants.ACCORDION_ATTR));
9+
return node;
10+
};
11+
const getNextIndex = (moveUp, current, length) => moveUp ? current > 0 ? current - 1 : length - 1 : (current + 1) % length;
12+
const moveFocus = (moveUp, e) => {
13+
const {
14+
activeElement
15+
} = document;
16+
if (!activeElement || !activeElement.hasAttribute(constants.ACCORDION_BTN_ATTR) || getAccordion(activeElement) !== e.currentTarget) return;
17+
const nodes = e.currentTarget.querySelectorAll(`[${constants.ACCORDION_BTN_ATTR}]`);
18+
const {
19+
length
20+
} = nodes;
21+
for (let i = 0; i < length; i++) {
22+
if (nodes[i] === activeElement) {
23+
let next = getNextIndex(moveUp, i, length);
24+
while (getAccordion(nodes[i]) !== getAccordion(nodes[next])) next = getNextIndex(moveUp, next, length);
25+
if (i !== next) {
26+
e.preventDefault();
27+
nodes[next].focus();
28+
}
29+
break;
30+
}
31+
}
32+
};
33+
const useAccordion = () => {
34+
const accordionProps = {
35+
[constants.ACCORDION_ATTR]: '',
36+
onKeyDown: e => e.key === 'ArrowUp' ? moveFocus(true, e) : e.key === 'ArrowDown' && moveFocus(false, e)
37+
};
38+
return {
39+
accordionProps
40+
};
41+
};
42+
43+
exports.useAccordion = useAccordion;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
var React = require('react');
4+
var constants = require('../utils/constants.cjs');
5+
6+
const getItemState = (providerValue, key, itemInitialEntered) => {
7+
const {
8+
stateMap,
9+
mountOnEnter,
10+
initialEntered
11+
} = providerValue;
12+
const _initialEntered = itemInitialEntered != null ? itemInitialEntered : initialEntered;
13+
return stateMap.get(key) || {
14+
status: _initialEntered ? 'entered' : mountOnEnter ? 'unmounted' : 'exited',
15+
isMounted: !mountOnEnter,
16+
isEnter: _initialEntered,
17+
isResolved: true
18+
};
19+
};
20+
const useAccordionContext = () => {
21+
const context = React.useContext(constants.AccordionContext);
22+
if (process.env.NODE_ENV !== 'production' && !context.stateMap) {
23+
throw new Error('[React-Accordion] Cannot find a <AccordionProvider/> above this AccordionItem.');
24+
}
25+
return context;
26+
};
27+
28+
exports.getItemState = getItemState;
29+
exports.useAccordionContext = useAccordionContext;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
3+
var constants = require('../utils/constants.cjs');
4+
var useId = require('./useId.cjs');
5+
6+
const useAccordionItem = ({
7+
state,
8+
toggle,
9+
disabled
10+
}) => {
11+
const buttonId = useId.useId();
12+
const panelId = buttonId && buttonId + '-';
13+
const buttonProps = {
14+
id: buttonId,
15+
'aria-controls': panelId,
16+
'aria-expanded': state.isEnter,
17+
onClick: toggle
18+
};
19+
disabled ? buttonProps.disabled = true : buttonProps[constants.ACCORDION_BTN_ATTR] = '';
20+
const panelProps = {
21+
id: panelId,
22+
'aria-labelledby': buttonId,
23+
role: 'region'
24+
};
25+
return {
26+
buttonProps,
27+
panelProps
28+
};
29+
};
30+
31+
exports.useAccordionItem = useAccordionItem;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
3+
var React = require('react');
4+
var useAccordionContext = require('./useAccordionContext.cjs');
5+
6+
const useAccordionItemEffect = ({
7+
itemKey,
8+
initialEntered,
9+
disabled
10+
} = {}) => {
11+
const itemRef = React.useRef(null);
12+
const context = useAccordionContext.useAccordionContext();
13+
const key = itemKey != null ? itemKey : itemRef.current;
14+
const state = useAccordionContext.getItemState(context, key, initialEntered);
15+
const {
16+
setItem,
17+
deleteItem,
18+
toggle
19+
} = context;
20+
React.useEffect(() => {
21+
if (disabled) return;
22+
const key = itemKey != null ? itemKey : itemRef.current;
23+
setItem(key, {
24+
initialEntered
25+
});
26+
return () => void deleteItem(key);
27+
}, [setItem, deleteItem, itemKey, initialEntered, disabled]);
28+
return {
29+
itemRef,
30+
state,
31+
toggle: React.useCallback(toEnter => toggle(key, toEnter), [toggle, key])
32+
};
33+
};
34+
35+
exports.useAccordionItemEffect = useAccordionItemEffect;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
3+
var reactTransitionState = require('react-transition-state');
4+
5+
const getTransition = (transition, name) => transition === true || !!(transition && transition[name]);
6+
const useAccordionProvider = ({
7+
transition,
8+
transitionTimeout,
9+
...rest
10+
} = {}) => {
11+
const transitionMap = reactTransitionState.useTransitionMap({
12+
timeout: transitionTimeout,
13+
enter: getTransition(transition, 'enter'),
14+
exit: getTransition(transition, 'exit'),
15+
preEnter: getTransition(transition, 'preEnter'),
16+
preExit: getTransition(transition, 'preExit'),
17+
...rest
18+
});
19+
return {
20+
mountOnEnter: !!rest.mountOnEnter,
21+
initialEntered: !!rest.initialEntered,
22+
...transitionMap
23+
};
24+
};
25+
26+
exports.useAccordionProvider = useAccordionProvider;

0 commit comments

Comments
 (0)