@xwadex/fesd-next 0.3.19 → 0.3.21
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/dist/components/accordions/accordions.d.ts +1 -1
- package/dist/components/accordions/accordions.js +16 -30
- package/dist/components/accordions/accordionsButton.d.ts +1 -1
- package/dist/components/accordions/accordionsButton.js +3 -3
- package/dist/components/accordions/accordionsContent.js +6 -32
- package/dist/components/accordions/accordionsContext.d.ts +7 -9
- package/dist/components/accordions/accordionsContext.js +4 -0
- package/dist/components/accordions/accordionsHeader.js +2 -2
- package/dist/components/accordions/index.d.ts +1 -0
- package/dist/components/accordions/index.js +1 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useCollapse.d.ts +13 -0
- package/dist/hooks/useCollapse.js +61 -0
- package/dist/utils/index.js +23 -8
- package/package.json +3 -2
|
@@ -7,7 +7,7 @@ type PropsTypes<T extends React.ElementType = "div"> = AsPropsTypes<T, {
|
|
|
7
7
|
time?: number;
|
|
8
8
|
timingFunction?: string;
|
|
9
9
|
isClickExtend?: boolean;
|
|
10
|
-
|
|
10
|
+
onChange?: (state: boolean) => void;
|
|
11
11
|
onExpanded?: (state: boolean) => void;
|
|
12
12
|
onClosed?: (state: boolean) => void;
|
|
13
13
|
}>;
|
|
@@ -1,45 +1,31 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo, memo } from "react";
|
|
4
4
|
import { AccordionsContext } from "./accordionsContext";
|
|
5
|
+
import { useCollapse } from "../../hooks/index.js";
|
|
5
6
|
const AccordionsBase = (props) => {
|
|
6
|
-
const { as, children, defaultActive = false, active, time = 300, timingFunction = "var(--global-animation-timing)",
|
|
7
|
+
const { as, children, defaultActive = false, active, time = 300, timingFunction = "var(--global-animation-timing)", onChange, onExpanded, onClosed, ...othersProps } = props;
|
|
7
8
|
const RootComponent = as || "div";
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (isWorking || !isClickExtend)
|
|
12
|
-
return;
|
|
13
|
-
if (typeof state !== "boolean")
|
|
14
|
-
setExpand(prev => !prev);
|
|
15
|
-
else
|
|
16
|
-
setExpand(state);
|
|
17
|
-
}, [isWorking, isClickExtend]);
|
|
18
|
-
const contextValue = useMemo(() => ({
|
|
9
|
+
const { contentRef, setExpand, isExpand } = useCollapse({
|
|
10
|
+
defaultActive,
|
|
11
|
+
active,
|
|
19
12
|
time,
|
|
20
13
|
timingFunction,
|
|
21
|
-
|
|
22
|
-
isClickExtend,
|
|
23
|
-
expand,
|
|
24
|
-
setExtandHandler,
|
|
25
|
-
isWorking,
|
|
26
|
-
setWorking,
|
|
27
|
-
onChanged,
|
|
14
|
+
onChange,
|
|
28
15
|
onExpanded,
|
|
29
16
|
onClosed
|
|
17
|
+
});
|
|
18
|
+
const contextValue = useMemo(() => ({
|
|
19
|
+
contentRef,
|
|
20
|
+
time,
|
|
21
|
+
timingFunction,
|
|
22
|
+
setExpand
|
|
30
23
|
}), [
|
|
31
24
|
time,
|
|
32
25
|
timingFunction,
|
|
33
|
-
|
|
34
|
-
isClickExtend,
|
|
35
|
-
expand,
|
|
36
|
-
isWorking,
|
|
37
|
-
setExtandHandler,
|
|
38
|
-
onChanged,
|
|
39
|
-
onExpanded,
|
|
40
|
-
onClosed
|
|
26
|
+
setExpand
|
|
41
27
|
]);
|
|
42
|
-
return (
|
|
28
|
+
return (_jsxs(AccordionsContext, { value: contextValue, children: [JSON.stringify(isExpand), _jsx(RootComponent, { ...othersProps, children: children })] }));
|
|
43
29
|
};
|
|
44
30
|
const Accordions = memo(AccordionsBase);
|
|
45
31
|
Accordions.displayName = "Accordions";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AsPropsTypes } from "../../types/index.js";
|
|
2
2
|
type PropsTypes<T extends React.ElementType = "div"> = AsPropsTypes<T, {
|
|
3
3
|
as?: React.ElementType;
|
|
4
|
-
|
|
4
|
+
clickActive?: boolean;
|
|
5
5
|
children?: React.ReactNode;
|
|
6
6
|
}>;
|
|
7
7
|
declare const AccordionsButtonBase: <T extends React.ElementType = "div">(props: PropsTypes<T>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,10 +3,10 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { memo } from "react";
|
|
4
4
|
import { useAccordionsContext } from "./accordionsContext";
|
|
5
5
|
const AccordionsButtonBase = (props) => {
|
|
6
|
-
const { as,
|
|
6
|
+
const { as, clickActive, children, ...othersProps } = props;
|
|
7
7
|
const RootComponent = as || "div";
|
|
8
|
-
const {
|
|
9
|
-
return (_jsx(RootComponent, { ...othersProps, onClick: () =>
|
|
8
|
+
const { setExpand } = useAccordionsContext();
|
|
9
|
+
return (_jsx(RootComponent, { ...othersProps, onClick: () => setExpand(clickActive), children: children }));
|
|
10
10
|
};
|
|
11
11
|
const AccordionsButton = memo(AccordionsButtonBase);
|
|
12
12
|
AccordionsButton.displayName = "AccordionsButton";
|
|
@@ -1,43 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { memo
|
|
3
|
+
import { memo } from "react";
|
|
4
4
|
import { useAccordionsContext } from "./accordionsContext";
|
|
5
|
-
import { getDomTransTime, sleep } from "../../utils/index.js";
|
|
6
5
|
import styles from "./accordions.module.scss";
|
|
7
6
|
const AccordionsContentBase = (props) => {
|
|
8
|
-
const { as, children, ...othersProps } = props;
|
|
7
|
+
const { as, children, className, style, ...othersProps } = props;
|
|
9
8
|
const RootComponent = as || "div";
|
|
10
|
-
const { time, timingFunction,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const callbackHandler = useCallback((state) => state
|
|
14
|
-
? onExpanded?.(state)
|
|
15
|
-
: onClosed?.(state), [onExpanded, onClosed]);
|
|
16
|
-
const setOpenHandler = useCallback(async (state) => {
|
|
17
|
-
if (expand == open || isWorking || !menuRef?.current)
|
|
18
|
-
return;
|
|
19
|
-
setWorking(true);
|
|
20
|
-
const target = menuRef.current;
|
|
21
|
-
target.style.height = target.scrollHeight + "px";
|
|
22
|
-
await sleep(!state ? 0 : getDomTransTime(target));
|
|
23
|
-
target.style.height = "";
|
|
24
|
-
setOpen(state);
|
|
25
|
-
setWorking(false);
|
|
26
|
-
onChanged?.(state);
|
|
27
|
-
callbackHandler(state);
|
|
28
|
-
}, [expand, isWorking, onChanged]);
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
setOpenHandler(expand);
|
|
31
|
-
}, [expand]);
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
if (typeof active !== "boolean")
|
|
34
|
-
return;
|
|
35
|
-
setOpenHandler(active);
|
|
36
|
-
}, [active]);
|
|
37
|
-
return (_jsx(RootComponent, { ...othersProps, ref: menuRef, className: styles.contents, style: {
|
|
9
|
+
const { contentRef, time, timingFunction, } = useAccordionsContext();
|
|
10
|
+
return (_jsx(RootComponent, { ...othersProps, ref: contentRef, className: className ? styles.contents + " " + className : styles.contents, style: {
|
|
11
|
+
...style,
|
|
38
12
|
transition: time ? time / 1000 + "s" : undefined,
|
|
39
13
|
transitionTimingFunction: timingFunction
|
|
40
|
-
},
|
|
14
|
+
}, children: children }));
|
|
41
15
|
};
|
|
42
16
|
const AccordionsContent = memo(AccordionsContentBase);
|
|
43
17
|
AccordionsContent.displayName = "AccordionsContent";
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
export interface AccordionsContextType {
|
|
2
2
|
time?: number;
|
|
3
3
|
timingFunction?: string;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
isWorking: boolean;
|
|
9
|
-
setWorking: React.Dispatch<React.SetStateAction<boolean>>;
|
|
10
|
-
onChanged?: (state: boolean) => void;
|
|
11
|
-
onExpanded?: (state: boolean) => void;
|
|
12
|
-
onClosed?: (state: boolean) => void;
|
|
4
|
+
contentRef: React.RefObject<null>;
|
|
5
|
+
defaultActive?: boolean;
|
|
6
|
+
isActive?: boolean;
|
|
7
|
+
setExpand: (state?: boolean) => void;
|
|
13
8
|
}
|
|
14
9
|
export declare const AccordionsContext: import("react").Context<AccordionsContextType | undefined> & {
|
|
15
10
|
displayName: string;
|
|
16
11
|
};
|
|
17
12
|
export declare const useAccordionsContext: () => AccordionsContextType;
|
|
13
|
+
export declare const useAccordionsExpand: () => {
|
|
14
|
+
setAccordionsExpand: (state?: boolean) => void;
|
|
15
|
+
};
|
|
@@ -7,3 +7,7 @@ export const useAccordionsContext = () => {
|
|
|
7
7
|
return context;
|
|
8
8
|
throw new Error("AccordionsContext is not defined!!");
|
|
9
9
|
};
|
|
10
|
+
export const useAccordionsExpand = () => {
|
|
11
|
+
const { setExpand } = useAccordionsContext();
|
|
12
|
+
return { setAccordionsExpand: setExpand };
|
|
13
|
+
};
|
|
@@ -5,8 +5,8 @@ import { useAccordionsContext } from "./accordionsContext";
|
|
|
5
5
|
const AccordionsHeaderBase = (props) => {
|
|
6
6
|
const { as, children, ...othersProps } = props;
|
|
7
7
|
const RootComponent = as || "div";
|
|
8
|
-
const {
|
|
9
|
-
return (_jsx(RootComponent, { ...othersProps, onClick:
|
|
8
|
+
const { setExpand } = useAccordionsContext();
|
|
9
|
+
return (_jsx(RootComponent, { ...othersProps, onClick: setExpand, children: children }));
|
|
10
10
|
};
|
|
11
11
|
const AccordionsHeader = memo(AccordionsHeaderBase);
|
|
12
12
|
AccordionsHeader.displayName = "AccordionsHeader";
|
|
@@ -2,3 +2,4 @@ export { default as Accordions } from "./accordions";
|
|
|
2
2
|
export { default as AccordionsContent } from "./accordionsContent";
|
|
3
3
|
export { default as AccordionsHeader } from "./accordionsHeader";
|
|
4
4
|
export { default as AccordionsButton } from "./accordionsButton";
|
|
5
|
+
export * from "./accordionsContext";
|
|
@@ -2,4 +2,5 @@ export { default as Accordions } from "./accordions";
|
|
|
2
2
|
export { default as AccordionsContent } from "./accordionsContent";
|
|
3
3
|
export { default as AccordionsHeader } from "./accordionsHeader";
|
|
4
4
|
export { default as AccordionsButton } from "./accordionsButton";
|
|
5
|
+
export * from "./accordionsContext";
|
|
5
6
|
// export { default as Accordions } from "./accordions";
|
package/dist/hooks/index.d.ts
CHANGED
package/dist/hooks/index.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function useCollapse({ defaultActive, active, time, timingFunction, onChange, onExpanded, onClosed, }: {
|
|
2
|
+
defaultActive?: boolean;
|
|
3
|
+
active?: boolean;
|
|
4
|
+
time?: number;
|
|
5
|
+
timingFunction?: string;
|
|
6
|
+
onChange?: (state: boolean) => void;
|
|
7
|
+
onExpanded?: (state: boolean) => void;
|
|
8
|
+
onClosed?: (state: boolean) => void;
|
|
9
|
+
}): {
|
|
10
|
+
contentRef: import("react").RefObject<null>;
|
|
11
|
+
setExpand: (state?: boolean) => void;
|
|
12
|
+
isExpand: boolean;
|
|
13
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useState, useMemo, useRef, useEffect } from "react";
|
|
3
|
+
import { getDomTransTime, sleep } from "../utils/index.js";
|
|
4
|
+
export function useCollapse({ defaultActive, active, time = 300, timingFunction = "var(--global-animation-timing)", onChange, onExpanded, onClosed, }) {
|
|
5
|
+
const contentRef = useRef(null);
|
|
6
|
+
const isMounted = useRef(false);
|
|
7
|
+
const isActive = typeof active == "boolean";
|
|
8
|
+
const [open, setOpen] = useState(defaultActive);
|
|
9
|
+
const [isAnimating, setAnimating] = useState(false);
|
|
10
|
+
const isExpand = isActive ? active : open;
|
|
11
|
+
const callbackHandler = useCallback((state) => state
|
|
12
|
+
? onExpanded?.(state)
|
|
13
|
+
: onClosed?.(state), [onExpanded, onClosed]);
|
|
14
|
+
const animate = useCallback(async (state) => {
|
|
15
|
+
if (isAnimating || !contentRef?.current)
|
|
16
|
+
return;
|
|
17
|
+
setAnimating(true);
|
|
18
|
+
onChange?.(state);
|
|
19
|
+
const target = contentRef.current;
|
|
20
|
+
target.style.height = target.scrollHeight + "px";
|
|
21
|
+
target.offsetHeight;
|
|
22
|
+
await sleep(!state ? 0 : getDomTransTime(target));
|
|
23
|
+
target.style.height = state ? "auto" : "0";
|
|
24
|
+
callbackHandler(state);
|
|
25
|
+
setAnimating(false);
|
|
26
|
+
}, [contentRef, isAnimating]);
|
|
27
|
+
const setExpand = useCallback((state) => {
|
|
28
|
+
const nextState = typeof state === "boolean" ? state : !isExpand;
|
|
29
|
+
if (nextState === isExpand)
|
|
30
|
+
return;
|
|
31
|
+
if (!isActive)
|
|
32
|
+
setOpen(nextState);
|
|
33
|
+
animate(nextState);
|
|
34
|
+
}, [isExpand, isActive, animate]);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if ((isActive && active) || defaultActive)
|
|
37
|
+
animate(true);
|
|
38
|
+
}, []);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (!isMounted.current) {
|
|
41
|
+
isMounted.current = true;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
animate(isExpand);
|
|
45
|
+
}, [isExpand]);
|
|
46
|
+
const contextValue = useMemo(() => ({
|
|
47
|
+
contentRef,
|
|
48
|
+
time,
|
|
49
|
+
timingFunction,
|
|
50
|
+
setExpand
|
|
51
|
+
}), [
|
|
52
|
+
time,
|
|
53
|
+
timingFunction,
|
|
54
|
+
setExpand
|
|
55
|
+
]);
|
|
56
|
+
return {
|
|
57
|
+
contentRef,
|
|
58
|
+
setExpand,
|
|
59
|
+
isExpand
|
|
60
|
+
};
|
|
61
|
+
}
|
package/dist/utils/index.js
CHANGED
|
@@ -35,18 +35,33 @@ export const getSearchParams = (searchParams) => {
|
|
|
35
35
|
searchParams.forEach((value, key) => { params[key] = value; });
|
|
36
36
|
return params;
|
|
37
37
|
};
|
|
38
|
+
// export const getDomTransTime = (target: HTMLElement): number => {
|
|
39
|
+
// const computedStyle = window.getComputedStyle(target)
|
|
40
|
+
// const transNumber = (time: string) => {
|
|
41
|
+
// if (time.endsWith("ms")) return parseFloat(time)
|
|
42
|
+
// if (time.endsWith("s")) return parseFloat(time) * 1000
|
|
43
|
+
// return 0
|
|
44
|
+
// }
|
|
45
|
+
// const durations = computedStyle.transitionDuration.split(',').map(transNumber)
|
|
46
|
+
// const delays = computedStyle.transitionDelay.split(',').map(transNumber)
|
|
47
|
+
// return Math.max(...durations.map((d, i) => d + (delays[i] || 0)))
|
|
48
|
+
// }
|
|
38
49
|
export const getDomTransTime = (target) => {
|
|
50
|
+
if (!target)
|
|
51
|
+
return 0;
|
|
39
52
|
const computedStyle = window.getComputedStyle(target);
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
const parseTime = (timeStr) => {
|
|
54
|
+
timeStr = timeStr.trim();
|
|
55
|
+
if (timeStr.endsWith("ms"))
|
|
56
|
+
return parseFloat(timeStr);
|
|
57
|
+
if (timeStr.endsWith("s"))
|
|
58
|
+
return parseFloat(timeStr) * 1000;
|
|
45
59
|
return 0;
|
|
46
60
|
};
|
|
47
|
-
const durations = computedStyle.transitionDuration.split(
|
|
48
|
-
const delays = computedStyle.transitionDelay.split(
|
|
49
|
-
|
|
61
|
+
const durations = computedStyle.transitionDuration.split(",").map(parseTime);
|
|
62
|
+
const delays = computedStyle.transitionDelay.split(",").map(parseTime);
|
|
63
|
+
const maxLength = Math.max(durations.length, delays.length);
|
|
64
|
+
return Math.max(...Array.from({ length: maxLength }, (_, i) => (durations[i] || 0) + (delays[i] || 0)));
|
|
50
65
|
};
|
|
51
66
|
export const getURLSearchParams = (searchParams) => {
|
|
52
67
|
const params = {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xwadex/fesd-next",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.21",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"react-dom": ">=18",
|
|
40
40
|
"next": ">=15.3.3",
|
|
41
41
|
"tua-body-scroll-lock": ">=1.5.3",
|
|
42
|
-
"react-sortablejs": ">=6.1.4"
|
|
42
|
+
"react-sortablejs": ">=6.1.4",
|
|
43
|
+
"motion": ">12.18.1"
|
|
43
44
|
}
|
|
44
45
|
}
|