@xwadex/fesd-next 0.3.20 → 0.3.22

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.
@@ -5,9 +5,9 @@ type PropsTypes<T extends React.ElementType = "div"> = AsPropsTypes<T, {
5
5
  defaultActive?: boolean;
6
6
  active?: boolean;
7
7
  time?: number;
8
- timingFunction?: number[];
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,31 +1,29 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { useState, useMemo, memo } from "react";
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, duration = 0.3, ease = [0.05, 0.8, 0.1, 0.95], 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 contextValue = useMemo(() => ({
10
- duration,
11
- ease,
9
+ const { contentRef, setExpand, isExpand } = useCollapse({
10
+ defaultActive,
12
11
  active,
13
- isClickExtend,
14
- expand,
15
- setExpand,
16
- onChanged,
12
+ time,
13
+ timingFunction,
14
+ onChange,
17
15
  onExpanded,
18
16
  onClosed
17
+ });
18
+ const contextValue = useMemo(() => ({
19
+ contentRef,
20
+ time,
21
+ timingFunction,
22
+ setExpand
19
23
  }), [
20
- duration,
21
- ease,
22
- active,
23
- isClickExtend,
24
- expand,
25
- setExpand,
26
- onChanged,
27
- onExpanded,
28
- onClosed
24
+ time,
25
+ timingFunction,
26
+ setExpand
29
27
  ]);
30
28
  return (_jsx(AccordionsContext, { value: contextValue, children: _jsx(RootComponent, { ...othersProps, children: children }) }));
31
29
  };
@@ -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
- clickActive?: "open" | "close";
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;
@@ -6,13 +6,7 @@ const AccordionsButtonBase = (props) => {
6
6
  const { as, clickActive, children, ...othersProps } = props;
7
7
  const RootComponent = as || "div";
8
8
  const { setExpand } = useAccordionsContext();
9
- return (_jsx(RootComponent, { ...othersProps, onClick: () => setExpand(prev => {
10
- if (clickActive == "open")
11
- return true;
12
- if (clickActive == "close")
13
- return false;
14
- return !prev;
15
- }), children: children }));
9
+ return (_jsx(RootComponent, { ...othersProps, onClick: () => setExpand(clickActive), children: children }));
16
10
  };
17
11
  const AccordionsButton = memo(AccordionsButtonBase);
18
12
  AccordionsButton.displayName = "AccordionsButton";
@@ -1,29 +1,17 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { AnimatePresence, motion } from "motion/react";
4
- import { memo, useEffect } from "react";
3
+ import { memo } from "react";
5
4
  import { useAccordionsContext } from "./accordionsContext";
5
+ import styles from "./accordions.module.scss";
6
6
  const AccordionsContentBase = (props) => {
7
7
  const { as, children, className, style, ...othersProps } = props;
8
- const RootComponent = motion.create(as || "div");
9
- const { duration, ease, expand, setExpand, onChanged, onExpanded, onClosed, active } = useAccordionsContext();
10
- useEffect(() => {
11
- if (typeof active !== "boolean")
12
- return;
13
- setExpand(active);
14
- }, [active]);
15
- return (_jsx(AnimatePresence, { initial: false, children: (expand) && _jsx(RootComponent, { ...othersProps, initial: "collapsed", animate: "open", exit: "collapsed", custom: expand, variants: {
16
- open: { height: 'auto', opacity: 1 },
17
- collapsed: { height: 0, opacity: 0 },
18
- }, transition: { duration, ease }, onAnimationStart: (variants) => {
19
- onChanged?.(variants == "open" ? true : false);
20
- }, onAnimationComplete: (variants) => {
21
- const isExpand = variants == "open" ? true : false;
22
- if (!isExpand)
23
- onClosed?.(false);
24
- if (isExpand)
25
- onExpanded?.(true);
26
- }, children: children }) }));
8
+ const RootComponent = as || "div";
9
+ const { contentRef, time, timingFunction, } = useAccordionsContext();
10
+ return (_jsx(RootComponent, { ...othersProps, ref: contentRef, className: className ? styles.contents + " " + className : styles.contents, style: {
11
+ ...style,
12
+ transition: time ? time / 1000 + "s" : undefined,
13
+ transitionTimingFunction: timingFunction
14
+ }, children: children }));
27
15
  };
28
16
  const AccordionsContent = memo(AccordionsContentBase);
29
17
  AccordionsContent.displayName = "AccordionsContent";
@@ -1,15 +1,15 @@
1
1
  export interface AccordionsContextType {
2
- duration?: number;
3
- ease?: number[];
4
- active?: boolean;
5
- isClickExtend?: boolean;
6
- expand: boolean;
7
- setExpand: React.Dispatch<React.SetStateAction<boolean>>;
8
- onChanged?: (state: boolean) => void;
9
- onExpanded?: (state: boolean) => void;
10
- onClosed?: (state: boolean) => void;
2
+ time?: number;
3
+ timingFunction?: string;
4
+ contentRef: React.RefObject<null>;
5
+ defaultActive?: boolean;
6
+ isActive?: boolean;
7
+ setExpand: (state?: boolean) => void;
11
8
  }
12
9
  export declare const AccordionsContext: import("react").Context<AccordionsContextType | undefined> & {
13
10
  displayName: string;
14
11
  };
15
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
+ };
@@ -6,7 +6,7 @@ const AccordionsHeaderBase = (props) => {
6
6
  const { as, children, ...othersProps } = props;
7
7
  const RootComponent = as || "div";
8
8
  const { setExpand } = useAccordionsContext();
9
- return (_jsx(RootComponent, { ...othersProps, onClick: () => setExpand(prev => !prev), children: children }));
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xwadex/fesd-next",
3
- "version": "0.3.20",
3
+ "version": "0.3.22",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",