@mantine/hooks 9.6.0 → 9.6.2

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.
@@ -12,6 +12,9 @@ function getAutoHeightDuration(height) {
12
12
  function getElementHeight(elementRef) {
13
13
  return elementRef.current ? elementRef.current.scrollHeight : "auto";
14
14
  }
15
+ function isMeasured(size) {
16
+ return typeof size === "number" && size > 0;
17
+ }
15
18
  function useCollapse({ transitionDuration, transitionTimingFunction = "ease", onTransitionEnd, onTransitionStart, expanded, keepMounted }) {
16
19
  const collapsedStyles = {
17
20
  height: 0,
@@ -19,6 +22,7 @@ function useCollapse({ transitionDuration, transitionTimingFunction = "ease", on
19
22
  ...keepMounted ? {} : { display: "none" }
20
23
  };
21
24
  const onTransitionStartEvent = (0, react.useEffectEvent)(() => onTransitionStart?.());
25
+ const onTransitionEndEvent = (0, react.useEffectEvent)(() => onTransitionEnd?.());
22
26
  const elementRef = (0, react.useRef)(null);
23
27
  const [styles, setStylesRaw] = (0, react.useState)(expanded ? {} : collapsedStyles);
24
28
  const [state, setState] = (0, react.useState)(expanded ? "entered" : "exited");
@@ -35,9 +39,14 @@ function useCollapse({ transitionDuration, transitionTimingFunction = "ease", on
35
39
  const duration = transitionDuration ?? getAutoHeightDuration(height);
36
40
  return { transition: `height ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}` };
37
41
  };
42
+ const transitionRef = (0, react.useRef)(0);
38
43
  require_use_did_update.useDidUpdate(() => {
44
+ transitionRef.current += 1;
45
+ const transitionId = transitionRef.current;
46
+ const isCurrentTransition = () => transitionRef.current === transitionId;
39
47
  if (transitionDuration !== 0) onTransitionStartEvent();
40
48
  if (expanded) window.requestAnimationFrame(() => {
49
+ if (!isCurrentTransition() || !elementRef.current) return;
41
50
  (0, react_dom.flushSync)(() => setState("entering"));
42
51
  mergeStyles({
43
52
  willChange: "height",
@@ -45,7 +54,14 @@ function useCollapse({ transitionDuration, transitionTimingFunction = "ease", on
45
54
  overflow: "hidden"
46
55
  });
47
56
  window.requestAnimationFrame(() => {
57
+ if (!isCurrentTransition() || !elementRef.current) return;
48
58
  const height = getElementHeight(elementRef);
59
+ if (!isMeasured(height)) {
60
+ setStyles({});
61
+ setState("entered");
62
+ onTransitionEndEvent();
63
+ return;
64
+ }
49
65
  mergeStyles({
50
66
  ...getTransitionStyles(height),
51
67
  height
@@ -53,17 +69,27 @@ function useCollapse({ transitionDuration, transitionTimingFunction = "ease", on
53
69
  });
54
70
  });
55
71
  else window.requestAnimationFrame(() => {
72
+ if (!isCurrentTransition() || !elementRef.current) return;
56
73
  (0, react_dom.flushSync)(() => setState("exiting"));
57
74
  const height = getElementHeight(elementRef);
75
+ if (!isMeasured(height)) {
76
+ setStyles(collapsedStyles);
77
+ setState("exited");
78
+ onTransitionEndEvent();
79
+ return;
80
+ }
58
81
  mergeStyles({
59
82
  ...getTransitionStyles(height),
60
83
  willChange: "height",
61
84
  height
62
85
  });
63
- window.requestAnimationFrame(() => mergeStyles({
64
- height: 0,
65
- overflow: "hidden"
66
- }));
86
+ window.requestAnimationFrame(() => {
87
+ if (!isCurrentTransition() || !elementRef.current) return;
88
+ mergeStyles({
89
+ height: 0,
90
+ overflow: "hidden"
91
+ });
92
+ });
67
93
  });
68
94
  }, [expanded]);
69
95
  const handleTransitionEnd = (event) => {
@@ -73,11 +99,11 @@ function useCollapse({ transitionDuration, transitionTimingFunction = "ease", on
73
99
  if (height === styles.height) setStyles({});
74
100
  else mergeStyles({ height });
75
101
  setState("entered");
76
- onTransitionEnd?.();
102
+ onTransitionEndEvent();
77
103
  } else if (styles.height === 0) {
78
104
  setStyles(collapsedStyles);
79
105
  setState("exited");
80
- onTransitionEnd?.();
106
+ onTransitionEndEvent();
81
107
  }
82
108
  };
83
109
  return {
@@ -97,6 +123,7 @@ function useCollapse({ transitionDuration, transitionTimingFunction = "ease", on
97
123
  }
98
124
  //#endregion
99
125
  exports.getElementHeight = getElementHeight;
126
+ exports.isMeasured = isMeasured;
100
127
  exports.useCollapse = useCollapse;
101
128
 
102
129
  //# sourceMappingURL=use-collapse.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-collapse.cjs","names":["useEffectEvent","useRef","useState","mergeRefs"],"sources":["../../src/use-collapse/use-collapse.ts"],"sourcesContent":["import React, { CSSProperties, useEffectEvent, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\nimport { mergeRefs } from '../use-merged-ref/use-merged-ref';\n\nfunction getAutoHeightDuration(height: number | string) {\n if (!height || typeof height === 'string') {\n return 0;\n }\n const constant = height / 36;\n return Math.round((4 + 15 * constant ** 0.25 + constant / 5) * 10);\n}\n\nexport function getElementHeight(elementRef: React.RefObject<HTMLElement | null>) {\n return elementRef.current ? elementRef.current.scrollHeight : 'auto';\n}\n\nexport interface UseCollapseInput {\n /** Expanded state */\n expanded: boolean;\n\n /** Transition duration in milliseconds, by default calculated based on content height */\n transitionDuration?: number;\n\n /** Transition timing function, `ease` by default */\n transitionTimingFunction?: string;\n\n /** Called when transition ends */\n onTransitionEnd?: () => void;\n\n /** Called when transition starts */\n onTransitionStart?: () => void;\n\n /** If true, collapsed content is kept in the DOM and hidden with `display: none` styles */\n keepMounted?: boolean;\n}\n\ninterface GetCollapsePropsInput {\n style?: CSSProperties;\n ref?: React.Ref<HTMLDivElement>;\n}\n\ninterface GetCollapsePropsReturnValue {\n 'aria-hidden': boolean;\n inert: boolean;\n ref: React.RefCallback<HTMLDivElement>;\n onTransitionEnd: (event: React.TransitionEvent<Element>) => void;\n style: React.CSSProperties;\n}\n\nexport type UseCollapseState = 'entering' | 'entered' | 'exiting' | 'exited';\n\nexport interface UseCollapseReturnValue {\n /** Current transition state */\n state: UseCollapseState;\n\n /** Props to pass down to the collapsible element */\n getCollapseProps: (input?: GetCollapsePropsInput) => GetCollapsePropsReturnValue;\n}\n\nexport function useCollapse({\n transitionDuration,\n transitionTimingFunction = 'ease',\n onTransitionEnd,\n onTransitionStart,\n expanded,\n keepMounted,\n}: UseCollapseInput): UseCollapseReturnValue {\n const collapsedStyles = {\n height: 0,\n overflow: 'hidden',\n ...(keepMounted ? {} : { display: 'none' }),\n };\n\n const onTransitionStartEvent = useEffectEvent(() => onTransitionStart?.());\n\n const elementRef = useRef<HTMLElement>(null);\n const [styles, setStylesRaw] = useState<CSSProperties>(expanded ? {} : collapsedStyles);\n const [state, setState] = useState<UseCollapseState>(expanded ? 'entered' : 'exited');\n const setStyles = (newStyles: React.SetStateAction<CSSProperties>) => {\n flushSync(() => setStylesRaw(newStyles));\n };\n\n const mergeStyles = (newStyles: CSSProperties) => {\n setStyles((oldStyles) => ({ ...oldStyles, ...newStyles }));\n };\n\n const getTransitionStyles = (height: number | string) => {\n const duration = transitionDuration ?? getAutoHeightDuration(height);\n return {\n transition: `height ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}`,\n };\n };\n\n useDidUpdate(() => {\n const shouldTransition = transitionDuration !== 0;\n\n if (shouldTransition) {\n onTransitionStartEvent();\n }\n\n if (expanded) {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('entering'));\n mergeStyles({ willChange: 'height', display: 'block', overflow: 'hidden' });\n window.requestAnimationFrame(() => {\n const height = getElementHeight(elementRef);\n mergeStyles({ ...getTransitionStyles(height), height });\n });\n });\n } else {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('exiting'));\n const height = getElementHeight(elementRef);\n mergeStyles({ ...getTransitionStyles(height), willChange: 'height', height });\n window.requestAnimationFrame(() => mergeStyles({ height: 0, overflow: 'hidden' }));\n });\n }\n }, [expanded]);\n\n const handleTransitionEnd = (event: React.TransitionEvent): void => {\n if (event.target !== elementRef.current || event.propertyName !== 'height') {\n return;\n }\n\n if (expanded) {\n const height = getElementHeight(elementRef);\n\n if (height === styles.height) {\n setStyles({});\n } else {\n mergeStyles({ height });\n }\n\n setState('entered');\n onTransitionEnd?.();\n } else if (styles.height === 0) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEnd?.();\n }\n };\n\n return {\n state,\n getCollapseProps: (input) => ({\n 'aria-hidden': !expanded,\n inert: !expanded,\n ref: mergeRefs(elementRef, input?.ref),\n onTransitionEnd: handleTransitionEnd,\n style: { boxSizing: 'border-box', ...input?.style, ...styles },\n }),\n };\n}\n\nexport namespace useCollapse {\n export type Input = UseCollapseInput;\n export type ReturnValue = UseCollapseReturnValue;\n export type State = UseCollapseState;\n}\n"],"mappings":";;;;;;AAKA,SAAS,sBAAsB,QAAyB;CACtD,IAAI,CAAC,UAAU,OAAO,WAAW,UAC/B,OAAO;CAET,MAAM,WAAW,SAAS;CAC1B,OAAO,KAAK,OAAO,IAAI,KAAK,YAAY,MAAO,WAAW,KAAK,EAAE;AACnE;AAEA,SAAgB,iBAAiB,YAAiD;CAChF,OAAO,WAAW,UAAU,WAAW,QAAQ,eAAe;AAChE;AA6CA,SAAgB,YAAY,EAC1B,oBACA,2BAA2B,QAC3B,iBACA,mBACA,UACA,eAC2C;CAC3C,MAAM,kBAAkB;EACtB,QAAQ;EACR,UAAU;EACV,GAAI,cAAc,CAAC,IAAI,EAAE,SAAS,OAAO;CAC3C;CAEA,MAAM,0BAAA,GAAyBA,MAAAA,eAAAA,OAAqB,oBAAoB,CAAC;CAEzE,MAAM,cAAA,GAAaC,MAAAA,OAAAA,CAAoB,IAAI;CAC3C,MAAM,CAAC,QAAQ,iBAAA,GAAgBC,MAAAA,SAAAA,CAAwB,WAAW,CAAC,IAAI,eAAe;CACtF,MAAM,CAAC,OAAO,aAAA,GAAYA,MAAAA,SAAAA,CAA2B,WAAW,YAAY,QAAQ;CACpF,MAAM,aAAa,cAAmD;EACpE,CAAA,GAAA,UAAA,UAAA,OAAgB,aAAa,SAAS,CAAC;CACzC;CAEA,MAAM,eAAe,cAA6B;EAChD,WAAW,eAAe;GAAE,GAAG;GAAW,GAAG;EAAU,EAAE;CAC3D;CAEA,MAAM,uBAAuB,WAA4B;EACvD,MAAM,WAAW,sBAAsB,sBAAsB,MAAM;EACnE,OAAO,EACL,YAAY,UAAU,SAAS,KAAK,yBAAyB,YAAY,SAAS,KAAK,2BACzF;CACF;CAEA,uBAAA,mBAAmB;EAGjB,IAFyB,uBAAuB,GAG9C,uBAAuB;EAGzB,IAAI,UACF,OAAO,4BAA4B;GACjC,CAAA,GAAA,UAAA,UAAA,OAAgB,SAAS,UAAU,CAAC;GACpC,YAAY;IAAE,YAAY;IAAU,SAAS;IAAS,UAAU;GAAS,CAAC;GAC1E,OAAO,4BAA4B;IACjC,MAAM,SAAS,iBAAiB,UAAU;IAC1C,YAAY;KAAE,GAAG,oBAAoB,MAAM;KAAG;IAAO,CAAC;GACxD,CAAC;EACH,CAAC;OAED,OAAO,4BAA4B;GACjC,CAAA,GAAA,UAAA,UAAA,OAAgB,SAAS,SAAS,CAAC;GACnC,MAAM,SAAS,iBAAiB,UAAU;GAC1C,YAAY;IAAE,GAAG,oBAAoB,MAAM;IAAG,YAAY;IAAU;GAAO,CAAC;GAC5E,OAAO,4BAA4B,YAAY;IAAE,QAAQ;IAAG,UAAU;GAAS,CAAC,CAAC;EACnF,CAAC;CAEL,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,uBAAuB,UAAuC;EAClE,IAAI,MAAM,WAAW,WAAW,WAAW,MAAM,iBAAiB,UAChE;EAGF,IAAI,UAAU;GACZ,MAAM,SAAS,iBAAiB,UAAU;GAE1C,IAAI,WAAW,OAAO,QACpB,UAAU,CAAC,CAAC;QAEZ,YAAY,EAAE,OAAO,CAAC;GAGxB,SAAS,SAAS;GAClB,kBAAkB;EACpB,OAAO,IAAI,OAAO,WAAW,GAAG;GAC9B,UAAU,eAAe;GACzB,SAAS,QAAQ;GACjB,kBAAkB;EACpB;CACF;CAEA,OAAO;EACL;EACA,mBAAmB,WAAW;GAC5B,eAAe,CAAC;GAChB,OAAO,CAAC;GACR,KAAKC,uBAAAA,UAAU,YAAY,OAAO,GAAG;GACrC,iBAAiB;GACjB,OAAO;IAAE,WAAW;IAAc,GAAG,OAAO;IAAO,GAAG;GAAO;EAC/D;CACF;AACF"}
1
+ {"version":3,"file":"use-collapse.cjs","names":["useEffectEvent","useRef","useState","mergeRefs"],"sources":["../../src/use-collapse/use-collapse.ts"],"sourcesContent":["import React, { CSSProperties, useEffectEvent, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\nimport { mergeRefs } from '../use-merged-ref/use-merged-ref';\n\nfunction getAutoHeightDuration(height: number | string) {\n if (!height || typeof height === 'string') {\n return 0;\n }\n const constant = height / 36;\n return Math.round((4 + 15 * constant ** 0.25 + constant / 5) * 10);\n}\n\nexport function getElementHeight(elementRef: React.RefObject<HTMLElement | null>) {\n return elementRef.current ? elementRef.current.scrollHeight : 'auto';\n}\n\nexport function isMeasured(size: number | string): size is number {\n return typeof size === 'number' && size > 0;\n}\n\nexport interface UseCollapseInput {\n /** Expanded state */\n expanded: boolean;\n\n /** Transition duration in milliseconds, by default calculated based on content height */\n transitionDuration?: number;\n\n /** Transition timing function, `ease` by default */\n transitionTimingFunction?: string;\n\n /** Called when transition ends */\n onTransitionEnd?: () => void;\n\n /** Called when transition starts */\n onTransitionStart?: () => void;\n\n /** If true, collapsed content is kept in the DOM and hidden with `display: none` styles */\n keepMounted?: boolean;\n}\n\ninterface GetCollapsePropsInput {\n style?: CSSProperties;\n ref?: React.Ref<HTMLDivElement>;\n}\n\ninterface GetCollapsePropsReturnValue {\n 'aria-hidden': boolean;\n inert: boolean;\n ref: React.RefCallback<HTMLDivElement>;\n onTransitionEnd: (event: React.TransitionEvent<Element>) => void;\n style: React.CSSProperties;\n}\n\nexport type UseCollapseState = 'entering' | 'entered' | 'exiting' | 'exited';\n\nexport interface UseCollapseReturnValue {\n /** Current transition state */\n state: UseCollapseState;\n\n /** Props to pass down to the collapsible element */\n getCollapseProps: (input?: GetCollapsePropsInput) => GetCollapsePropsReturnValue;\n}\n\nexport function useCollapse({\n transitionDuration,\n transitionTimingFunction = 'ease',\n onTransitionEnd,\n onTransitionStart,\n expanded,\n keepMounted,\n}: UseCollapseInput): UseCollapseReturnValue {\n const collapsedStyles = {\n height: 0,\n overflow: 'hidden',\n ...(keepMounted ? {} : { display: 'none' }),\n };\n\n const onTransitionStartEvent = useEffectEvent(() => onTransitionStart?.());\n const onTransitionEndEvent = useEffectEvent(() => onTransitionEnd?.());\n\n const elementRef = useRef<HTMLElement>(null);\n const [styles, setStylesRaw] = useState<CSSProperties>(expanded ? {} : collapsedStyles);\n const [state, setState] = useState<UseCollapseState>(expanded ? 'entered' : 'exited');\n const setStyles = (newStyles: React.SetStateAction<CSSProperties>) => {\n flushSync(() => setStylesRaw(newStyles));\n };\n\n const mergeStyles = (newStyles: CSSProperties) => {\n setStyles((oldStyles) => ({ ...oldStyles, ...newStyles }));\n };\n\n const getTransitionStyles = (height: number | string) => {\n const duration = transitionDuration ?? getAutoHeightDuration(height);\n return {\n transition: `height ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}`,\n };\n };\n\n const transitionRef = useRef(0);\n\n useDidUpdate(() => {\n transitionRef.current += 1;\n const transitionId = transitionRef.current;\n const isCurrentTransition = () => transitionRef.current === transitionId;\n const shouldTransition = transitionDuration !== 0;\n\n if (shouldTransition) {\n onTransitionStartEvent();\n }\n\n if (expanded) {\n window.requestAnimationFrame(() => {\n if (!isCurrentTransition() || !elementRef.current) {\n return;\n }\n\n flushSync(() => setState('entering'));\n mergeStyles({ willChange: 'height', display: 'block', overflow: 'hidden' });\n window.requestAnimationFrame(() => {\n if (!isCurrentTransition() || !elementRef.current) {\n return;\n }\n\n const height = getElementHeight(elementRef);\n\n if (!isMeasured(height)) {\n setStyles({});\n setState('entered');\n onTransitionEndEvent();\n return;\n }\n\n mergeStyles({ ...getTransitionStyles(height), height });\n });\n });\n } else {\n window.requestAnimationFrame(() => {\n if (!isCurrentTransition() || !elementRef.current) {\n return;\n }\n\n flushSync(() => setState('exiting'));\n const height = getElementHeight(elementRef);\n\n if (!isMeasured(height)) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEndEvent();\n return;\n }\n\n mergeStyles({ ...getTransitionStyles(height), willChange: 'height', height });\n window.requestAnimationFrame(() => {\n if (!isCurrentTransition() || !elementRef.current) {\n return;\n }\n\n mergeStyles({ height: 0, overflow: 'hidden' });\n });\n });\n }\n }, [expanded]);\n\n const handleTransitionEnd = (event: React.TransitionEvent): void => {\n if (event.target !== elementRef.current || event.propertyName !== 'height') {\n return;\n }\n\n if (expanded) {\n const height = getElementHeight(elementRef);\n\n if (height === styles.height) {\n setStyles({});\n } else {\n mergeStyles({ height });\n }\n\n setState('entered');\n onTransitionEndEvent();\n } else if (styles.height === 0) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEndEvent();\n }\n };\n\n return {\n state,\n getCollapseProps: (input) => ({\n 'aria-hidden': !expanded,\n inert: !expanded,\n ref: mergeRefs(elementRef, input?.ref),\n onTransitionEnd: handleTransitionEnd,\n style: { boxSizing: 'border-box', ...input?.style, ...styles },\n }),\n };\n}\n\nexport namespace useCollapse {\n export type Input = UseCollapseInput;\n export type ReturnValue = UseCollapseReturnValue;\n export type State = UseCollapseState;\n}\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  const require_use_did_update = require("../use-did-update/use-did-update.cjs");
3
3
  const require_use_merged_ref = require("../use-merged-ref/use-merged-ref.cjs");
4
+ const require_use_collapse = require("./use-collapse.cjs");
4
5
  let react = require("react");
5
6
  let react_dom = require("react-dom");
6
7
  //#region packages/@mantine/hooks/src/use-collapse/use-horizontal-collapse.ts
@@ -19,6 +20,7 @@ function useHorizontalCollapse({ transitionDuration, transitionTimingFunction =
19
20
  ...keepMounted ? {} : { display: "none" }
20
21
  };
21
22
  const onTransitionStartEvent = (0, react.useEffectEvent)(() => onTransitionStart?.());
23
+ const onTransitionEndEvent = (0, react.useEffectEvent)(() => onTransitionEnd?.());
22
24
  const elementRef = (0, react.useRef)(null);
23
25
  const [styles, setStylesRaw] = (0, react.useState)(expanded ? {} : collapsedStyles);
24
26
  const [state, setState] = (0, react.useState)(expanded ? "entered" : "exited");
@@ -35,9 +37,14 @@ function useHorizontalCollapse({ transitionDuration, transitionTimingFunction =
35
37
  const duration = transitionDuration ?? getAutoWidthDuration(width);
36
38
  return { transition: `width ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}` };
37
39
  };
40
+ const transitionRef = (0, react.useRef)(0);
38
41
  require_use_did_update.useDidUpdate(() => {
42
+ transitionRef.current += 1;
43
+ const transitionId = transitionRef.current;
44
+ const isCurrentTransition = () => transitionRef.current === transitionId;
39
45
  if (transitionDuration !== 0) onTransitionStartEvent();
40
46
  if (expanded) window.requestAnimationFrame(() => {
47
+ if (!isCurrentTransition() || !elementRef.current) return;
41
48
  (0, react_dom.flushSync)(() => setState("entering"));
42
49
  mergeStyles({
43
50
  willChange: "width",
@@ -45,7 +52,14 @@ function useHorizontalCollapse({ transitionDuration, transitionTimingFunction =
45
52
  overflow: "hidden"
46
53
  });
47
54
  window.requestAnimationFrame(() => {
55
+ if (!isCurrentTransition() || !elementRef.current) return;
48
56
  const width = getElementWidth(elementRef);
57
+ if (!require_use_collapse.isMeasured(width)) {
58
+ setStyles({});
59
+ setState("entered");
60
+ onTransitionEndEvent();
61
+ return;
62
+ }
49
63
  mergeStyles({
50
64
  ...getTransitionStyles(width),
51
65
  width
@@ -53,17 +67,27 @@ function useHorizontalCollapse({ transitionDuration, transitionTimingFunction =
53
67
  });
54
68
  });
55
69
  else window.requestAnimationFrame(() => {
70
+ if (!isCurrentTransition() || !elementRef.current) return;
56
71
  (0, react_dom.flushSync)(() => setState("exiting"));
57
72
  const width = getElementWidth(elementRef);
73
+ if (!require_use_collapse.isMeasured(width)) {
74
+ setStyles(collapsedStyles);
75
+ setState("exited");
76
+ onTransitionEndEvent();
77
+ return;
78
+ }
58
79
  mergeStyles({
59
80
  ...getTransitionStyles(width),
60
81
  willChange: "width",
61
82
  width
62
83
  });
63
- window.requestAnimationFrame(() => mergeStyles({
64
- width: 0,
65
- overflow: "hidden"
66
- }));
84
+ window.requestAnimationFrame(() => {
85
+ if (!isCurrentTransition() || !elementRef.current) return;
86
+ mergeStyles({
87
+ width: 0,
88
+ overflow: "hidden"
89
+ });
90
+ });
67
91
  });
68
92
  }, [expanded]);
69
93
  const handleTransitionEnd = (event) => {
@@ -73,11 +97,11 @@ function useHorizontalCollapse({ transitionDuration, transitionTimingFunction =
73
97
  if (width === styles.width) setStyles({});
74
98
  else mergeStyles({ width });
75
99
  setState("entered");
76
- onTransitionEnd?.();
100
+ onTransitionEndEvent();
77
101
  } else if (styles.width === 0) {
78
102
  setStyles(collapsedStyles);
79
103
  setState("exited");
80
- onTransitionEnd?.();
104
+ onTransitionEndEvent();
81
105
  }
82
106
  };
83
107
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"use-horizontal-collapse.cjs","names":["useEffectEvent","useRef","useState","mergeRefs"],"sources":["../../src/use-collapse/use-horizontal-collapse.ts"],"sourcesContent":["import React, { CSSProperties, useEffectEvent, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\nimport { mergeRefs } from '../use-merged-ref/use-merged-ref';\n\nfunction getAutoWidthDuration(width: number | string) {\n if (!width || typeof width === 'string') {\n return 0;\n }\n const constant = width / 36;\n return Math.round((4 + 15 * constant ** 0.25 + constant / 5) * 10);\n}\n\nexport function getElementWidth(elementRef: React.RefObject<HTMLElement | null>) {\n return elementRef.current ? elementRef.current.scrollWidth : 'auto';\n}\n\nexport interface UseHorizontalCollapseInput {\n /** Expanded state */\n expanded: boolean;\n\n /** Transition duration in milliseconds, by default calculated based on content width */\n transitionDuration?: number;\n\n /** Transition timing function, `ease` by default */\n transitionTimingFunction?: string;\n\n /** Called when transition ends */\n onTransitionEnd?: () => void;\n\n /** Called when transition starts */\n onTransitionStart?: () => void;\n\n /** If true, collapsed content is kept in the DOM and hidden with `display: none` styles */\n keepMounted?: boolean;\n}\n\ninterface GetHorizontalCollapsePropsInput {\n style?: CSSProperties;\n ref?: React.Ref<HTMLDivElement>;\n}\n\ninterface GetHorizontalCollapsePropsReturnValue {\n 'aria-hidden': boolean;\n inert: boolean;\n ref: React.RefCallback<HTMLDivElement>;\n onTransitionEnd: (event: React.TransitionEvent<Element>) => void;\n style: React.CSSProperties;\n}\n\nexport type UseHorizontalCollapseState = 'entering' | 'entered' | 'exiting' | 'exited';\n\nexport interface UseHorizontalCollapseReturnValue {\n /** Current transition state */\n state: UseHorizontalCollapseState;\n\n /** Props to pass down to the collapsible element */\n getCollapseProps: (\n input?: GetHorizontalCollapsePropsInput\n ) => GetHorizontalCollapsePropsReturnValue;\n}\n\nexport function useHorizontalCollapse({\n transitionDuration,\n transitionTimingFunction = 'ease',\n onTransitionEnd,\n onTransitionStart,\n expanded,\n keepMounted,\n}: UseHorizontalCollapseInput): UseHorizontalCollapseReturnValue {\n const collapsedStyles = {\n width: 0,\n overflow: 'hidden',\n ...(keepMounted ? {} : { display: 'none' }),\n };\n\n const onTransitionStartEvent = useEffectEvent(() => onTransitionStart?.());\n\n const elementRef = useRef<HTMLElement>(null);\n const [styles, setStylesRaw] = useState<CSSProperties>(expanded ? {} : collapsedStyles);\n const [state, setState] = useState<UseHorizontalCollapseState>(expanded ? 'entered' : 'exited');\n const setStyles = (newStyles: React.SetStateAction<CSSProperties>) => {\n flushSync(() => setStylesRaw(newStyles));\n };\n\n const mergeStyles = (newStyles: CSSProperties) => {\n setStyles((oldStyles) => ({ ...oldStyles, ...newStyles }));\n };\n\n const getTransitionStyles = (width: number | string) => {\n const duration = transitionDuration ?? getAutoWidthDuration(width);\n return {\n transition: `width ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}`,\n };\n };\n\n useDidUpdate(() => {\n const shouldTransition = transitionDuration !== 0;\n\n if (shouldTransition) {\n onTransitionStartEvent();\n }\n\n if (expanded) {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('entering'));\n mergeStyles({ willChange: 'width', display: 'block', overflow: 'hidden' });\n window.requestAnimationFrame(() => {\n const width = getElementWidth(elementRef);\n mergeStyles({ ...getTransitionStyles(width), width });\n });\n });\n } else {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('exiting'));\n const width = getElementWidth(elementRef);\n mergeStyles({ ...getTransitionStyles(width), willChange: 'width', width });\n window.requestAnimationFrame(() => mergeStyles({ width: 0, overflow: 'hidden' }));\n });\n }\n }, [expanded]);\n\n const handleTransitionEnd = (event: React.TransitionEvent): void => {\n if (event.target !== elementRef.current || event.propertyName !== 'width') {\n return;\n }\n\n if (expanded) {\n const width = getElementWidth(elementRef);\n\n if (width === styles.width) {\n setStyles({});\n } else {\n mergeStyles({ width });\n }\n\n setState('entered');\n onTransitionEnd?.();\n } else if (styles.width === 0) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEnd?.();\n }\n };\n\n return {\n state,\n getCollapseProps: (input) => ({\n 'aria-hidden': !expanded,\n inert: !expanded,\n ref: mergeRefs(elementRef, input?.ref),\n onTransitionEnd: handleTransitionEnd,\n style: { boxSizing: 'border-box', ...input?.style, ...styles },\n }),\n };\n}\n\nexport namespace useHorizontalCollapse {\n export type Input = UseHorizontalCollapseInput;\n export type ReturnValue = UseHorizontalCollapseReturnValue;\n export type State = UseHorizontalCollapseState;\n}\n"],"mappings":";;;;;;AAKA,SAAS,qBAAqB,OAAwB;CACpD,IAAI,CAAC,SAAS,OAAO,UAAU,UAC7B,OAAO;CAET,MAAM,WAAW,QAAQ;CACzB,OAAO,KAAK,OAAO,IAAI,KAAK,YAAY,MAAO,WAAW,KAAK,EAAE;AACnE;AAEA,SAAgB,gBAAgB,YAAiD;CAC/E,OAAO,WAAW,UAAU,WAAW,QAAQ,cAAc;AAC/D;AA+CA,SAAgB,sBAAsB,EACpC,oBACA,2BAA2B,QAC3B,iBACA,mBACA,UACA,eAC+D;CAC/D,MAAM,kBAAkB;EACtB,OAAO;EACP,UAAU;EACV,GAAI,cAAc,CAAC,IAAI,EAAE,SAAS,OAAO;CAC3C;CAEA,MAAM,0BAAA,GAAyBA,MAAAA,eAAAA,OAAqB,oBAAoB,CAAC;CAEzE,MAAM,cAAA,GAAaC,MAAAA,OAAAA,CAAoB,IAAI;CAC3C,MAAM,CAAC,QAAQ,iBAAA,GAAgBC,MAAAA,SAAAA,CAAwB,WAAW,CAAC,IAAI,eAAe;CACtF,MAAM,CAAC,OAAO,aAAA,GAAYA,MAAAA,SAAAA,CAAqC,WAAW,YAAY,QAAQ;CAC9F,MAAM,aAAa,cAAmD;EACpE,CAAA,GAAA,UAAA,UAAA,OAAgB,aAAa,SAAS,CAAC;CACzC;CAEA,MAAM,eAAe,cAA6B;EAChD,WAAW,eAAe;GAAE,GAAG;GAAW,GAAG;EAAU,EAAE;CAC3D;CAEA,MAAM,uBAAuB,UAA2B;EACtD,MAAM,WAAW,sBAAsB,qBAAqB,KAAK;EACjE,OAAO,EACL,YAAY,SAAS,SAAS,KAAK,yBAAyB,YAAY,SAAS,KAAK,2BACxF;CACF;CAEA,uBAAA,mBAAmB;EAGjB,IAFyB,uBAAuB,GAG9C,uBAAuB;EAGzB,IAAI,UACF,OAAO,4BAA4B;GACjC,CAAA,GAAA,UAAA,UAAA,OAAgB,SAAS,UAAU,CAAC;GACpC,YAAY;IAAE,YAAY;IAAS,SAAS;IAAS,UAAU;GAAS,CAAC;GACzE,OAAO,4BAA4B;IACjC,MAAM,QAAQ,gBAAgB,UAAU;IACxC,YAAY;KAAE,GAAG,oBAAoB,KAAK;KAAG;IAAM,CAAC;GACtD,CAAC;EACH,CAAC;OAED,OAAO,4BAA4B;GACjC,CAAA,GAAA,UAAA,UAAA,OAAgB,SAAS,SAAS,CAAC;GACnC,MAAM,QAAQ,gBAAgB,UAAU;GACxC,YAAY;IAAE,GAAG,oBAAoB,KAAK;IAAG,YAAY;IAAS;GAAM,CAAC;GACzE,OAAO,4BAA4B,YAAY;IAAE,OAAO;IAAG,UAAU;GAAS,CAAC,CAAC;EAClF,CAAC;CAEL,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,uBAAuB,UAAuC;EAClE,IAAI,MAAM,WAAW,WAAW,WAAW,MAAM,iBAAiB,SAChE;EAGF,IAAI,UAAU;GACZ,MAAM,QAAQ,gBAAgB,UAAU;GAExC,IAAI,UAAU,OAAO,OACnB,UAAU,CAAC,CAAC;QAEZ,YAAY,EAAE,MAAM,CAAC;GAGvB,SAAS,SAAS;GAClB,kBAAkB;EACpB,OAAO,IAAI,OAAO,UAAU,GAAG;GAC7B,UAAU,eAAe;GACzB,SAAS,QAAQ;GACjB,kBAAkB;EACpB;CACF;CAEA,OAAO;EACL;EACA,mBAAmB,WAAW;GAC5B,eAAe,CAAC;GAChB,OAAO,CAAC;GACR,KAAKC,uBAAAA,UAAU,YAAY,OAAO,GAAG;GACrC,iBAAiB;GACjB,OAAO;IAAE,WAAW;IAAc,GAAG,OAAO;IAAO,GAAG;GAAO;EAC/D;CACF;AACF"}
1
+ {"version":3,"file":"use-horizontal-collapse.cjs","names":["useEffectEvent","useRef","useState","isMeasured","mergeRefs"],"sources":["../../src/use-collapse/use-horizontal-collapse.ts"],"sourcesContent":["import React, { CSSProperties, useEffectEvent, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\nimport { mergeRefs } from '../use-merged-ref/use-merged-ref';\nimport { isMeasured } from './use-collapse';\n\nfunction getAutoWidthDuration(width: number | string) {\n if (!width || typeof width === 'string') {\n return 0;\n }\n const constant = width / 36;\n return Math.round((4 + 15 * constant ** 0.25 + constant / 5) * 10);\n}\n\nexport function getElementWidth(elementRef: React.RefObject<HTMLElement | null>) {\n return elementRef.current ? elementRef.current.scrollWidth : 'auto';\n}\n\nexport interface UseHorizontalCollapseInput {\n /** Expanded state */\n expanded: boolean;\n\n /** Transition duration in milliseconds, by default calculated based on content width */\n transitionDuration?: number;\n\n /** Transition timing function, `ease` by default */\n transitionTimingFunction?: string;\n\n /** Called when transition ends */\n onTransitionEnd?: () => void;\n\n /** Called when transition starts */\n onTransitionStart?: () => void;\n\n /** If true, collapsed content is kept in the DOM and hidden with `display: none` styles */\n keepMounted?: boolean;\n}\n\ninterface GetHorizontalCollapsePropsInput {\n style?: CSSProperties;\n ref?: React.Ref<HTMLDivElement>;\n}\n\ninterface GetHorizontalCollapsePropsReturnValue {\n 'aria-hidden': boolean;\n inert: boolean;\n ref: React.RefCallback<HTMLDivElement>;\n onTransitionEnd: (event: React.TransitionEvent<Element>) => void;\n style: React.CSSProperties;\n}\n\nexport type UseHorizontalCollapseState = 'entering' | 'entered' | 'exiting' | 'exited';\n\nexport interface UseHorizontalCollapseReturnValue {\n /** Current transition state */\n state: UseHorizontalCollapseState;\n\n /** Props to pass down to the collapsible element */\n getCollapseProps: (\n input?: GetHorizontalCollapsePropsInput\n ) => GetHorizontalCollapsePropsReturnValue;\n}\n\nexport function useHorizontalCollapse({\n transitionDuration,\n transitionTimingFunction = 'ease',\n onTransitionEnd,\n onTransitionStart,\n expanded,\n keepMounted,\n}: UseHorizontalCollapseInput): UseHorizontalCollapseReturnValue {\n const collapsedStyles = {\n width: 0,\n overflow: 'hidden',\n ...(keepMounted ? {} : { display: 'none' }),\n };\n\n const onTransitionStartEvent = useEffectEvent(() => onTransitionStart?.());\n const onTransitionEndEvent = useEffectEvent(() => onTransitionEnd?.());\n\n const elementRef = useRef<HTMLElement>(null);\n const [styles, setStylesRaw] = useState<CSSProperties>(expanded ? {} : collapsedStyles);\n const [state, setState] = useState<UseHorizontalCollapseState>(expanded ? 'entered' : 'exited');\n const setStyles = (newStyles: React.SetStateAction<CSSProperties>) => {\n flushSync(() => setStylesRaw(newStyles));\n };\n\n const mergeStyles = (newStyles: CSSProperties) => {\n setStyles((oldStyles) => ({ ...oldStyles, ...newStyles }));\n };\n\n const getTransitionStyles = (width: number | string) => {\n const duration = transitionDuration ?? getAutoWidthDuration(width);\n return {\n transition: `width ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}`,\n };\n };\n\n const transitionRef = useRef(0);\n\n useDidUpdate(() => {\n transitionRef.current += 1;\n const transitionId = transitionRef.current;\n const isCurrentTransition = () => transitionRef.current === transitionId;\n const shouldTransition = transitionDuration !== 0;\n\n if (shouldTransition) {\n onTransitionStartEvent();\n }\n\n if (expanded) {\n window.requestAnimationFrame(() => {\n if (!isCurrentTransition() || !elementRef.current) {\n return;\n }\n\n flushSync(() => setState('entering'));\n mergeStyles({ willChange: 'width', display: 'block', overflow: 'hidden' });\n window.requestAnimationFrame(() => {\n if (!isCurrentTransition() || !elementRef.current) {\n return;\n }\n\n const width = getElementWidth(elementRef);\n\n if (!isMeasured(width)) {\n setStyles({});\n setState('entered');\n onTransitionEndEvent();\n return;\n }\n\n mergeStyles({ ...getTransitionStyles(width), width });\n });\n });\n } else {\n window.requestAnimationFrame(() => {\n if (!isCurrentTransition() || !elementRef.current) {\n return;\n }\n\n flushSync(() => setState('exiting'));\n const width = getElementWidth(elementRef);\n\n if (!isMeasured(width)) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEndEvent();\n return;\n }\n\n mergeStyles({ ...getTransitionStyles(width), willChange: 'width', width });\n window.requestAnimationFrame(() => {\n if (!isCurrentTransition() || !elementRef.current) {\n return;\n }\n\n mergeStyles({ width: 0, overflow: 'hidden' });\n });\n });\n }\n }, [expanded]);\n\n const handleTransitionEnd = (event: React.TransitionEvent): void => {\n if (event.target !== elementRef.current || event.propertyName !== 'width') {\n return;\n }\n\n if (expanded) {\n const width = getElementWidth(elementRef);\n\n if (width === styles.width) {\n setStyles({});\n } else {\n mergeStyles({ width });\n }\n\n setState('entered');\n onTransitionEndEvent();\n } else if (styles.width === 0) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEndEvent();\n }\n };\n\n return {\n state,\n getCollapseProps: (input) => ({\n 'aria-hidden': !expanded,\n inert: !expanded,\n ref: mergeRefs(elementRef, input?.ref),\n onTransitionEnd: handleTransitionEnd,\n style: { boxSizing: 'border-box', ...input?.style, ...styles },\n }),\n };\n}\n\nexport namespace useHorizontalCollapse {\n export type Input = UseHorizontalCollapseInput;\n export type ReturnValue = UseHorizontalCollapseReturnValue;\n export type State = UseHorizontalCollapseState;\n}\n"],"mappings":"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"}
@@ -1,14 +1,26 @@
1
1
  "use client";
2
2
  let react = require("react");
3
3
  //#region packages/@mantine/hooks/src/use-did-update/use-did-update.ts
4
+ function dependenciesChanged(previous, next) {
5
+ return previous.length !== next.length || next.some((dep, index) => !Object.is(dep, previous[index]));
6
+ }
4
7
  function useDidUpdate(fn, dependencies) {
5
8
  const mounted = (0, react.useRef)(false);
6
- (0, react.useEffect)(() => () => {
7
- mounted.current = false;
8
- }, []);
9
+ const previousRender = (0, react.useRef)(null);
10
+ const previousDependencies = (0, react.useRef)(void 0);
11
+ const render = {};
9
12
  (0, react.useEffect)(() => {
10
- if (mounted.current) return fn();
11
- mounted.current = true;
13
+ const isSameRender = previousRender.current === render;
14
+ const previous = previousDependencies.current;
15
+ previousRender.current = render;
16
+ previousDependencies.current = dependencies;
17
+ if (!mounted.current) {
18
+ mounted.current = true;
19
+ return;
20
+ }
21
+ if (isSameRender) return;
22
+ if (dependencies && previous && !dependenciesChanged(previous, dependencies)) return;
23
+ return fn();
12
24
  }, dependencies);
13
25
  }
14
26
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"use-did-update.cjs","names":["useRef"],"sources":["../../src/use-did-update/use-did-update.ts"],"sourcesContent":["import { DependencyList, EffectCallback, useEffect, useRef } from 'react';\n\nexport function useDidUpdate(fn: EffectCallback, dependencies?: DependencyList) {\n const mounted = useRef(false);\n\n useEffect(\n () => () => {\n mounted.current = false;\n },\n []\n );\n\n useEffect(() => {\n if (mounted.current) {\n return fn();\n }\n\n mounted.current = true;\n return undefined;\n }, dependencies);\n}\n"],"mappings":";;;AAEA,SAAgB,aAAa,IAAoB,cAA+B;CAC9E,MAAM,WAAA,GAAUA,MAAAA,OAAAA,CAAO,KAAK;CAE5B,CAAA,GAAA,MAAA,UAAA,aACc;EACV,QAAQ,UAAU;CACpB,GACA,CAAC,CACH;CAEA,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,QAAQ,SACV,OAAO,GAAG;EAGZ,QAAQ,UAAU;CAEpB,GAAG,YAAY;AACjB"}
1
+ {"version":3,"file":"use-did-update.cjs","names":["useRef"],"sources":["../../src/use-did-update/use-did-update.ts"],"sourcesContent":["import { DependencyList, EffectCallback, useEffect, useRef } from 'react';\n\nfunction dependenciesChanged(previous: DependencyList, next: DependencyList) {\n return (\n previous.length !== next.length || next.some((dep, index) => !Object.is(dep, previous[index]))\n );\n}\n\nexport function useDidUpdate(fn: EffectCallback, dependencies?: DependencyList) {\n const mounted = useRef(false);\n const previousRender = useRef<object>(null);\n const previousDependencies = useRef<DependencyList | undefined>(undefined);\n const render = {};\n\n useEffect(() => {\n const isSameRender = previousRender.current === render;\n const previous = previousDependencies.current;\n\n previousRender.current = render;\n previousDependencies.current = dependencies;\n\n if (!mounted.current) {\n mounted.current = true;\n return undefined;\n }\n\n if (isSameRender) {\n return undefined;\n }\n\n if (dependencies && previous && !dependenciesChanged(previous, dependencies)) {\n return undefined;\n }\n\n return fn();\n }, dependencies);\n}\n"],"mappings":";;;AAEA,SAAS,oBAAoB,UAA0B,MAAsB;CAC3E,OACE,SAAS,WAAW,KAAK,UAAU,KAAK,MAAM,KAAK,UAAU,CAAC,OAAO,GAAG,KAAK,SAAS,MAAM,CAAC;AAEjG;AAEA,SAAgB,aAAa,IAAoB,cAA+B;CAC9E,MAAM,WAAA,GAAUA,MAAAA,OAAAA,CAAO,KAAK;CAC5B,MAAM,kBAAA,GAAiBA,MAAAA,OAAAA,CAAe,IAAI;CAC1C,MAAM,wBAAA,GAAuBA,MAAAA,OAAAA,CAAmC,KAAA,CAAS;CACzE,MAAM,SAAS,CAAC;CAEhB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,eAAe,eAAe,YAAY;EAChD,MAAM,WAAW,qBAAqB;EAEtC,eAAe,UAAU;EACzB,qBAAqB,UAAU;EAE/B,IAAI,CAAC,QAAQ,SAAS;GACpB,QAAQ,UAAU;GAClB;EACF;EAEA,IAAI,cACF;EAGF,IAAI,gBAAgB,YAAY,CAAC,oBAAoB,UAAU,YAAY,GACzE;EAGF,OAAO,GAAG;CACZ,GAAG,YAAY;AACjB"}
@@ -1,15 +1,16 @@
1
1
  "use client";
2
+ const require_use_callback_ref = require("../utils/use-callback-ref/use-callback-ref.cjs");
2
3
  let react = require("react");
3
4
  //#region packages/@mantine/hooks/src/use-interval/use-interval.ts
4
5
  function useInterval(fn, interval, { autoInvoke = false } = {}) {
5
6
  const [active, setActive] = (0, react.useState)(false);
6
7
  const intervalRef = (0, react.useRef)(null);
7
- const fnRef = (0, react.useRef)(null);
8
+ const handleCallback = require_use_callback_ref.useCallbackRef(fn);
8
9
  const intervalValueRef = (0, react.useRef)(interval);
9
10
  intervalValueRef.current = interval;
10
11
  const start = (0, react.useCallback)(() => {
11
12
  setActive((old) => {
12
- if (!old && !intervalRef.current) intervalRef.current = window.setInterval(fnRef.current, intervalValueRef.current);
13
+ if (!old && !intervalRef.current) intervalRef.current = window.setInterval(handleCallback, intervalValueRef.current);
13
14
  return true;
14
15
  });
15
16
  }, []);
@@ -25,19 +26,14 @@ function useInterval(fn, interval, { autoInvoke = false } = {}) {
25
26
  intervalRef.current = null;
26
27
  return false;
27
28
  }
28
- if (!intervalRef.current) intervalRef.current = window.setInterval(fnRef.current, intervalValueRef.current);
29
+ if (!intervalRef.current) intervalRef.current = window.setInterval(handleCallback, intervalValueRef.current);
29
30
  return true;
30
31
  });
31
32
  }, []);
32
33
  (0, react.useEffect)(() => {
33
- fnRef.current = fn;
34
34
  active && start();
35
35
  return stop;
36
- }, [
37
- fn,
38
- active,
39
- interval
40
- ]);
36
+ }, [active, interval]);
41
37
  (0, react.useEffect)(() => {
42
38
  if (autoInvoke) start();
43
39
  }, []);
@@ -1 +1 @@
1
- {"version":3,"file":"use-interval.cjs","names":["useState","useRef","useCallback"],"sources":["../../src/use-interval/use-interval.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseIntervalOptions {\n /** If set, the interval will start automatically when the component is mounted, `false` by default */\n autoInvoke?: boolean;\n}\n\nexport interface UseIntervalReturnValue {\n /** Starts the interval */\n start: () => void;\n\n /** Stops the interval */\n stop: () => void;\n\n /** Toggles the interval */\n toggle: () => void;\n\n /** Indicates if the interval is active */\n active: boolean;\n}\n\nexport function useInterval(\n fn: () => void,\n interval: number,\n { autoInvoke = false }: UseIntervalOptions = {}\n): UseIntervalReturnValue {\n const [active, setActive] = useState(false);\n const intervalRef = useRef<number | null>(null);\n const fnRef = useRef<() => void>(null);\n const intervalValueRef = useRef(interval);\n intervalValueRef.current = interval;\n\n const start = useCallback(() => {\n setActive((old) => {\n if (!old && !intervalRef.current) {\n intervalRef.current = window.setInterval(fnRef.current!, intervalValueRef.current);\n }\n return true;\n });\n }, []);\n\n const stop = useCallback(() => {\n setActive(false);\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current);\n }\n intervalRef.current = null;\n }, []);\n\n const toggle = useCallback(() => {\n setActive((current) => {\n if (current) {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current);\n }\n intervalRef.current = null;\n return false;\n }\n if (!intervalRef.current) {\n intervalRef.current = window.setInterval(fnRef.current!, intervalValueRef.current);\n }\n return true;\n });\n }, []);\n\n useEffect(() => {\n fnRef.current = fn;\n active && start();\n return stop;\n }, [fn, active, interval]);\n\n useEffect(() => {\n if (autoInvoke) {\n start();\n }\n }, []);\n\n return { start, stop, toggle, active };\n}\n\nexport namespace useInterval {\n export type Options = UseIntervalOptions;\n export type ReturnValue = UseIntervalReturnValue;\n}\n"],"mappings":";;;AAqBA,SAAgB,YACd,IACA,UACA,EAAE,aAAa,UAA8B,CAAC,GACtB;CACxB,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAS,KAAK;CAC1C,MAAM,eAAA,GAAcC,MAAAA,OAAAA,CAAsB,IAAI;CAC9C,MAAM,SAAA,GAAQA,MAAAA,OAAAA,CAAmB,IAAI;CACrC,MAAM,oBAAA,GAAmBA,MAAAA,OAAAA,CAAO,QAAQ;CACxC,iBAAiB,UAAU;CAE3B,MAAM,SAAA,GAAQC,MAAAA,YAAAA,OAAkB;EAC9B,WAAW,QAAQ;GACjB,IAAI,CAAC,OAAO,CAAC,YAAY,SACvB,YAAY,UAAU,OAAO,YAAY,MAAM,SAAU,iBAAiB,OAAO;GAEnF,OAAO;EACT,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,MAAM,QAAA,GAAOA,MAAAA,YAAAA,OAAkB;EAC7B,UAAU,KAAK;EACf,IAAI,YAAY,SACd,OAAO,cAAc,YAAY,OAAO;EAE1C,YAAY,UAAU;CACxB,GAAG,CAAC,CAAC;CAEL,MAAM,UAAA,GAASA,MAAAA,YAAAA,OAAkB;EAC/B,WAAW,YAAY;GACrB,IAAI,SAAS;IACX,IAAI,YAAY,SACd,OAAO,cAAc,YAAY,OAAO;IAE1C,YAAY,UAAU;IACtB,OAAO;GACT;GACA,IAAI,CAAC,YAAY,SACf,YAAY,UAAU,OAAO,YAAY,MAAM,SAAU,iBAAiB,OAAO;GAEnF,OAAO;EACT,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,UAAU;EAChB,UAAU,MAAM;EAChB,OAAO;CACT,GAAG;EAAC;EAAI;EAAQ;CAAQ,CAAC;CAEzB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,YACF,MAAM;CAEV,GAAG,CAAC,CAAC;CAEL,OAAO;EAAE;EAAO;EAAM;EAAQ;CAAO;AACvC"}
1
+ {"version":3,"file":"use-interval.cjs","names":["useState","useRef","useCallbackRef","useCallback"],"sources":["../../src/use-interval/use-interval.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useCallbackRef } from '../utils';\n\nexport interface UseIntervalOptions {\n /** If set, the interval will start automatically when the component is mounted, `false` by default */\n autoInvoke?: boolean;\n}\n\nexport interface UseIntervalReturnValue {\n /** Starts the interval */\n start: () => void;\n\n /** Stops the interval */\n stop: () => void;\n\n /** Toggles the interval */\n toggle: () => void;\n\n /** Indicates if the interval is active */\n active: boolean;\n}\n\nexport function useInterval(\n fn: () => void,\n interval: number,\n { autoInvoke = false }: UseIntervalOptions = {}\n): UseIntervalReturnValue {\n const [active, setActive] = useState(false);\n const intervalRef = useRef<number | null>(null);\n const handleCallback = useCallbackRef(fn);\n const intervalValueRef = useRef(interval);\n intervalValueRef.current = interval;\n\n const start = useCallback(() => {\n setActive((old) => {\n if (!old && !intervalRef.current) {\n intervalRef.current = window.setInterval(handleCallback, intervalValueRef.current);\n }\n return true;\n });\n }, []);\n\n const stop = useCallback(() => {\n setActive(false);\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current);\n }\n intervalRef.current = null;\n }, []);\n\n const toggle = useCallback(() => {\n setActive((current) => {\n if (current) {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current);\n }\n intervalRef.current = null;\n return false;\n }\n if (!intervalRef.current) {\n intervalRef.current = window.setInterval(handleCallback, intervalValueRef.current);\n }\n return true;\n });\n }, []);\n\n useEffect(() => {\n active && start();\n return stop;\n }, [active, interval]);\n\n useEffect(() => {\n if (autoInvoke) {\n start();\n }\n }, []);\n\n return { start, stop, toggle, active };\n}\n\nexport namespace useInterval {\n export type Options = UseIntervalOptions;\n export type ReturnValue = UseIntervalReturnValue;\n}\n"],"mappings":";;;;AAsBA,SAAgB,YACd,IACA,UACA,EAAE,aAAa,UAA8B,CAAC,GACtB;CACxB,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAS,KAAK;CAC1C,MAAM,eAAA,GAAcC,MAAAA,OAAAA,CAAsB,IAAI;CAC9C,MAAM,iBAAiBC,yBAAAA,eAAe,EAAE;CACxC,MAAM,oBAAA,GAAmBD,MAAAA,OAAAA,CAAO,QAAQ;CACxC,iBAAiB,UAAU;CAE3B,MAAM,SAAA,GAAQE,MAAAA,YAAAA,OAAkB;EAC9B,WAAW,QAAQ;GACjB,IAAI,CAAC,OAAO,CAAC,YAAY,SACvB,YAAY,UAAU,OAAO,YAAY,gBAAgB,iBAAiB,OAAO;GAEnF,OAAO;EACT,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,MAAM,QAAA,GAAOA,MAAAA,YAAAA,OAAkB;EAC7B,UAAU,KAAK;EACf,IAAI,YAAY,SACd,OAAO,cAAc,YAAY,OAAO;EAE1C,YAAY,UAAU;CACxB,GAAG,CAAC,CAAC;CAEL,MAAM,UAAA,GAASA,MAAAA,YAAAA,OAAkB;EAC/B,WAAW,YAAY;GACrB,IAAI,SAAS;IACX,IAAI,YAAY,SACd,OAAO,cAAc,YAAY,OAAO;IAE1C,YAAY,UAAU;IACtB,OAAO;GACT;GACA,IAAI,CAAC,YAAY,SACf,YAAY,UAAU,OAAO,YAAY,gBAAgB,iBAAiB,OAAO;GAEnF,OAAO;EACT,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,UAAU,MAAM;EAChB,OAAO;CACT,GAAG,CAAC,QAAQ,QAAQ,CAAC;CAErB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,YACF,MAAM;CAEV,GAAG,CAAC,CAAC;CAEL,OAAO;EAAE;EAAO;EAAM;EAAQ;CAAO;AACvC"}
@@ -244,9 +244,11 @@ function useMask(options) {
244
244
  const initializeInputValue = (0, react.useCallback)((node) => {
245
245
  const opts = optionsRef.current;
246
246
  if (!node.value) return false;
247
+ const isOwnValue = node.value === displayValueRef.current;
248
+ const parse = (slots, slotCharOption) => isOwnValue ? applyMaskToRaw(rawValueRef.current, slots, slotCharOption) : processInput(node.value, slots, slotCharOption);
247
249
  const { slots: initialSlots, slotChar: initialSlotChar } = getResolvedOptions(opts, "");
248
- const { slots: resolvedSlots, slotChar } = getResolvedOptions(opts, extractRaw(processInput(node.value, initialSlots, initialSlotChar), initialSlots));
249
- const reprocessed = processInput(node.value, resolvedSlots, slotChar);
250
+ const { slots: resolvedSlots, slotChar } = getResolvedOptions(opts, extractRaw(parse(initialSlots, initialSlotChar), initialSlots));
251
+ const reprocessed = parse(resolvedSlots, slotChar);
250
252
  const newRaw = extractRaw(reprocessed, resolvedSlots);
251
253
  const showSlots = opts.alwaysShowMask || isFocusedRef.current;
252
254
  const showOnFocus = opts.showMaskOnFocus !== false;