@xwadex/fesd-next 0.3.21 → 0.3.23

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.
@@ -1,16 +1,11 @@
1
- import { AsPropsTypes } from "../../types/index.js";
1
+ import { CollapseTypes } from "../../hooks/index.js";
2
+ import type { AsPropsTypes } from "../../types/index.js";
2
3
  type PropsTypes<T extends React.ElementType = "div"> = AsPropsTypes<T, {
3
4
  as?: React.ElementType;
4
5
  children?: React.ReactNode;
5
6
  defaultActive?: boolean;
6
7
  active?: boolean;
7
- time?: number;
8
- timingFunction?: string;
9
- isClickExtend?: boolean;
10
- onChange?: (state: boolean) => void;
11
- onExpanded?: (state: boolean) => void;
12
- onClosed?: (state: boolean) => void;
13
- }>;
8
+ } & CollapseTypes>;
14
9
  declare const AccordionsBase: <T extends React.ElementType = "div">(props: PropsTypes<T>) => import("react/jsx-runtime").JSX.Element;
15
10
  declare const Accordions: React.MemoExoticComponent<typeof AccordionsBase>;
16
11
  export default Accordions;
@@ -1,31 +1,49 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useMemo, memo } from "react";
3
+ import { useCallback, useMemo, memo, useEffect } from "react";
4
4
  import { AccordionsContext } from "./accordionsContext";
5
5
  import { useCollapse } from "../../hooks/index.js";
6
6
  const AccordionsBase = (props) => {
7
- const { as, children, defaultActive = false, active, time = 300, timingFunction = "var(--global-animation-timing)", onChange, onExpanded, onClosed, ...othersProps } = props;
7
+ const { as, children, defaultActive = false, active, time, ease, onInit, onChange, onExpand, onClose, ...othersProps } = props;
8
8
  const RootComponent = as || "div";
9
- const { contentRef, setExpand, isExpand } = useCollapse({
10
- defaultActive,
11
- active,
9
+ const isActive = typeof active == "boolean";
10
+ const defaultOpen = isActive ? active : defaultActive;
11
+ const { contentRef, setOpen, open, } = useCollapse({
12
+ defaultOpen,
12
13
  time,
13
- timingFunction,
14
+ ease,
15
+ onInit,
14
16
  onChange,
15
- onExpanded,
16
- onClosed
17
+ onExpand,
18
+ onClose
17
19
  });
20
+ const isExpand = isActive ? active : open;
21
+ const setExpand = useCallback((state) => {
22
+ const nextState = typeof state === "boolean" ? state : !isExpand;
23
+ if (nextState === isExpand)
24
+ return;
25
+ if (!isActive)
26
+ setOpen(nextState);
27
+ setOpen(nextState);
28
+ }, [isExpand, isActive, setOpen]);
29
+ useEffect(() => {
30
+ if ((isActive && active) || defaultActive)
31
+ setOpen(true);
32
+ }, []);
33
+ useEffect(() => {
34
+ setOpen(isExpand);
35
+ }, [isExpand]);
18
36
  const contextValue = useMemo(() => ({
19
37
  contentRef,
20
38
  time,
21
- timingFunction,
39
+ ease,
22
40
  setExpand
23
41
  }), [
24
42
  time,
25
- timingFunction,
43
+ ease,
26
44
  setExpand
27
45
  ]);
28
- return (_jsxs(AccordionsContext, { value: contextValue, children: [JSON.stringify(isExpand), _jsx(RootComponent, { ...othersProps, children: children })] }));
46
+ return (_jsxs(AccordionsContext, { value: contextValue, children: [JSON.stringify(open), _jsx(RootComponent, { ...othersProps, children: children })] }));
29
47
  };
30
48
  const Accordions = memo(AccordionsBase);
31
49
  Accordions.displayName = "Accordions";
@@ -2,15 +2,15 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { memo } from "react";
4
4
  import { useAccordionsContext } from "./accordionsContext";
5
- import styles from "./accordions.module.scss";
6
5
  const AccordionsContentBase = (props) => {
7
6
  const { as, children, className, style, ...othersProps } = props;
8
7
  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: {
8
+ const { contentRef } = useAccordionsContext();
9
+ return (_jsx(RootComponent, { ...othersProps, ref: contentRef, style: {
11
10
  ...style,
12
- transition: time ? time / 1000 + "s" : undefined,
13
- transitionTimingFunction: timingFunction
11
+ overflow: "hidden",
12
+ maxWith: "100%",
13
+ maxHeight: "0"
14
14
  }, children: children }));
15
15
  };
16
16
  const AccordionsContent = memo(AccordionsContentBase);
@@ -1,11 +1,10 @@
1
- type ReturnDatasTypes = {
1
+ export interface ReturnDatasTypes {
2
2
  fetcher: (payload: PayloadTypes) => Promise<any>;
3
3
  cancel: () => void;
4
4
  pending: boolean;
5
- };
6
- interface PayloadTypes {
5
+ }
6
+ export interface PayloadTypes {
7
7
  url: string | URL | globalThis.Request;
8
8
  options?: RequestInit;
9
9
  }
10
10
  export declare function useAsyncFetcher(): ReturnDatasTypes;
11
- export {};
@@ -1,13 +1,14 @@
1
- export declare function useCollapse({ defaultActive, active, time, timingFunction, onChange, onExpanded, onClosed, }: {
2
- defaultActive?: boolean;
3
- active?: boolean;
1
+ export interface CollapseTypes {
2
+ defaultOpen?: boolean;
4
3
  time?: number;
5
- timingFunction?: string;
6
- onChange?: (state: boolean) => void;
7
- onExpanded?: (state: boolean) => void;
8
- onClosed?: (state: boolean) => void;
9
- }): {
4
+ ease?: string;
5
+ onInit?: (isInit: boolean) => void;
6
+ onChange?: (isOpen: boolean) => void;
7
+ onExpand?: (isOpen: boolean) => void;
8
+ onClose?: (isOpen: boolean) => void;
9
+ }
10
+ export declare function useCollapse({ defaultOpen, time, ease, onInit, onChange, onExpand, onClose, }: CollapseTypes): {
10
11
  contentRef: import("react").RefObject<null>;
11
- setExpand: (state?: boolean) => void;
12
- isExpand: boolean;
12
+ setOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
13
+ open: boolean;
13
14
  };
@@ -1,61 +1,55 @@
1
1
  "use client";
2
- import { useCallback, useState, useMemo, useRef, useEffect } from "react";
2
+ import { useCallback, useState, useRef, useEffect } from "react";
3
3
  import { getDomTransTime, sleep } from "../utils/index.js";
4
- export function useCollapse({ defaultActive, active, time = 300, timingFunction = "var(--global-animation-timing)", onChange, onExpanded, onClosed, }) {
4
+ export function useCollapse({ defaultOpen = false, time = 0.3, ease = "Cubic-Bezier(0.05, 0.8, 0.1, 0.95)", onInit, onChange, onExpand, onClose, }) {
5
5
  const contentRef = useRef(null);
6
6
  const isMounted = useRef(false);
7
- const isActive = typeof active == "boolean";
8
- const [open, setOpen] = useState(defaultActive);
7
+ const [open, setOpen] = useState(defaultOpen);
9
8
  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) => {
9
+ const setExpandHeight = useCallback((height) => {
10
+ if (!contentRef.current)
11
+ return;
12
+ const target = contentRef.current;
13
+ const nextHeight = height == "none" ? height : height + "px";
14
+ target.style.maxHeight = nextHeight;
15
+ target.offsetHeight; // hack to force reflow
16
+ }, []);
17
+ const eventCallbacks = useCallback((state) => state
18
+ ? onExpand?.(state)
19
+ : onClose?.(state), [onExpand, onClose]);
20
+ const expandAnimate = useCallback(async (state) => {
15
21
  if (isAnimating || !contentRef?.current)
16
22
  return;
17
23
  setAnimating(true);
18
24
  onChange?.(state);
19
25
  const target = contentRef.current;
20
- target.style.height = target.scrollHeight + "px";
21
- target.offsetHeight;
26
+ setExpandHeight(target.scrollHeight);
22
27
  await sleep(!state ? 0 : getDomTransTime(target));
23
- target.style.height = state ? "auto" : "0";
24
- callbackHandler(state);
28
+ setExpandHeight(state ? "none" : "0");
29
+ eventCallbacks(state);
25
30
  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]);
31
+ }, [isAnimating, onChange, eventCallbacks]);
35
32
  useEffect(() => {
36
- if ((isActive && active) || defaultActive)
37
- animate(true);
33
+ if (!contentRef.current)
34
+ return;
35
+ const target = contentRef.current;
36
+ target.style.transition = time + "s";
37
+ target.style.transitionTimingFunction = ease;
38
+ if (!defaultOpen)
39
+ return;
40
+ setExpandHeight(target.scrollHeight);
38
41
  }, []);
39
42
  useEffect(() => {
40
43
  if (!isMounted.current) {
41
44
  isMounted.current = true;
45
+ onInit?.(true);
42
46
  return;
43
47
  }
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
- ]);
48
+ expandAnimate(open);
49
+ }, [open]);
56
50
  return {
57
51
  contentRef,
58
- setExpand,
59
- isExpand
52
+ setOpen,
53
+ open,
60
54
  };
61
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xwadex/fesd-next",
3
- "version": "0.3.21",
3
+ "version": "0.3.23",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,18 +0,0 @@
1
- .root {
2
- display: flex;
3
- flex-direction: column;
4
- }
5
-
6
- .headers {
7
- font-size: 1.2rem;
8
- font-weight: 600;
9
- }
10
-
11
- .contents {
12
- width: 100%;
13
- height: 0;
14
- overflow: hidden;
15
- &[data-active="true"] {
16
- height: auto;
17
- }
18
- }