@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.
@@ -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
- onChanged?: (state: boolean) => void;
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 { useCallback, useState, useMemo, memo } from "react";
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)", isClickExtend = true, onChanged, onExpanded, onClosed, ...othersProps } = props;
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 [expand, setExpand] = useState(defaultActive);
9
- const [isWorking, setWorking] = useState(false);
10
- const setExtandHandler = useCallback((state) => {
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
- active,
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
- active,
34
- isClickExtend,
35
- expand,
36
- isWorking,
37
- setExtandHandler,
38
- onChanged,
39
- onExpanded,
40
- onClosed
26
+ setExpand
41
27
  ]);
42
- return (_jsx(AccordionsContext, { value: contextValue, children: _jsx(RootComponent, { ...othersProps, children: children }) }));
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
- active?: boolean;
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, active, children, ...othersProps } = props;
6
+ const { as, clickActive, children, ...othersProps } = props;
7
7
  const RootComponent = as || "div";
8
- const { setExtandHandler } = useAccordionsContext();
9
- return (_jsx(RootComponent, { ...othersProps, onClick: () => setExtandHandler(active), children: children }));
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, useCallback, useEffect, useRef, useState } from "react";
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, expand, active, isWorking, setWorking, onChanged, onExpanded, onClosed, } = useAccordionsContext();
11
- const menuRef = useRef(null);
12
- const [open, setOpen] = useState(expand);
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
- }, "data-active": open, children: children }));
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
- active?: boolean;
5
- isClickExtend?: boolean;
6
- expand: boolean;
7
- setExtandHandler: (state?: boolean) => void;
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 { setExtandHandler } = useAccordionsContext();
9
- return (_jsx(RootComponent, { ...othersProps, onClick: setExtandHandler, children: children }));
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";
@@ -3,3 +3,4 @@ export * from "./useDebounceValue";
3
3
  export * from "./useCookies";
4
4
  export * from "./useDragResize";
5
5
  export * from "./useAsyncFetcher";
6
+ export * from "./useCollapse";
@@ -3,3 +3,4 @@ export * from "./useDebounceValue";
3
3
  export * from "./useCookies";
4
4
  export * from "./useDragResize";
5
5
  export * from "./useAsyncFetcher";
6
+ export * from "./useCollapse";
@@ -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
+ }
@@ -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 transNumber = (time) => {
41
- if (time.endsWith("ms"))
42
- return parseFloat(time);
43
- if (time.endsWith("s"))
44
- return parseFloat(time) * 1000;
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(',').map(transNumber);
48
- const delays = computedStyle.transitionDelay.split(',').map(transNumber);
49
- return Math.max(...durations.map((d, i) => d + (delays[i] || 0)));
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.19",
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
  }