@zayne-labs/ui-react 0.11.0 → 0.11.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.
package/css/animation.css CHANGED
@@ -7,6 +7,8 @@
7
7
 
8
8
  --animate-files-in: files-in 0.3s ease-out forwards;
9
9
 
10
+ --animate-progress-out: progress-out 0.3s ease-out forwards;
11
+
10
12
  @keyframes shake {
11
13
  0%,
12
14
  100% {
@@ -58,4 +60,15 @@
58
60
  transform: translateY(0);
59
61
  }
60
62
  }
63
+
64
+ @keyframes progress-out {
65
+ from {
66
+ opacity: 1;
67
+ transform: translateY(0);
68
+ }
69
+ to {
70
+ opacity: 0;
71
+ transform: translateY(-6px);
72
+ }
73
+ }
61
74
  }
@@ -4,4 +4,4 @@ const cnMerge = (...classNames) => twMerge(classNames);
4
4
  //#endregion
5
5
  export { cnMerge as t };
6
6
 
7
- //# sourceMappingURL=cn-Bbh2G587.js.map
7
+ //# sourceMappingURL=cn-jNZfGhrk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cn-Bbh2G587.js","names":[],"sources":["../../src/lib/utils/cn.ts"],"sourcesContent":["import { twMerge } from \"tailwind-merge\";\n\nexport const cnMerge: typeof twMerge = (...classNames) => twMerge(classNames);\n"],"mappings":";;AAEA,MAAa,WAA2B,GAAG,eAAe,QAAQ,WAAW"}
1
+ {"version":3,"file":"cn-jNZfGhrk.js","names":[],"sources":["../../src/lib/utils/cn.ts"],"sourcesContent":["import { twMerge } from \"tailwind-merge\";\n\nexport const cnMerge: typeof twMerge = (...classNames) => twMerge(classNames);\n"],"mappings":";;AAEA,MAAa,WAA2B,GAAG,eAAe,QAAQ,WAAW"}
@@ -1,5 +1,5 @@
1
- import { o as ErrorBoundaryProps } from "../../index-BUIvQ2wP.js";
2
- import { n as SuspenseWithBoundaryProps } from "../../index-ClV6w6nv.js";
1
+ import { o as ErrorBoundaryProps } from "../../index-Dbt-nJhQ.js";
2
+ import { n as SuspenseWithBoundaryProps } from "../../index-Ce3J0_vR.js";
3
3
  import { GetSlotComponentProps } from "@zayne-labs/toolkit-react/utils";
4
4
  import * as react from "react";
5
5
  import * as react_jsx_runtime0 from "react/jsx-runtime";
@@ -1,2 +1,2 @@
1
- import { a as ErrorBoundary, i as useErrorBoundaryContext, n as useErrorBoundary, o as ErrorBoundaryProps, r as ErrorBoundaryContextType, s as ErrorFallbackProps, t as UseErrorBoundaryReturn } from "../../index-BUIvQ2wP.js";
1
+ import { a as ErrorBoundary, i as useErrorBoundaryContext, n as useErrorBoundary, o as ErrorBoundaryProps, r as ErrorBoundaryContextType, s as ErrorFallbackProps, t as UseErrorBoundaryReturn } from "../../index-Dbt-nJhQ.js";
2
2
  export { ErrorBoundary, ErrorBoundaryContextType, ErrorBoundaryProps, ErrorFallbackProps, UseErrorBoundaryReturn, useErrorBoundary, useErrorBoundaryContext };
@@ -16,7 +16,7 @@ declare function For<const TArray extends ArrayOrNumber>(props: ForProps<TArray>
16
16
  type ForWithWrapperProps<TArray extends ArrayOrNumber, TElement extends React.ElementType = "ul"> = PolymorphicPropsStrict<TElement, ForProps<TArray>> & {
17
17
  displayFallBackWhenEmpty?: boolean;
18
18
  };
19
- declare function ForWithWrapper<const TArray extends ArrayOrNumber, TElement extends React.ElementType = "ul">(props: ForWithWrapperProps<TArray, TElement>): string | number | bigint | boolean | react_jsx_runtime0.JSX.Element | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | null;
19
+ declare function ForWithWrapper<const TArray extends ArrayOrNumber, TElement extends React.ElementType = "ul">(props: ForWithWrapperProps<TArray, TElement>): string | number | bigint | boolean | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | react_jsx_runtime0.JSX.Element | null;
20
20
  //#endregion
21
21
  //#region src/components/common/for/getElementList.d.ts
22
22
  type GetElementListResult<TVariant extends "base" | "withWrapper"> = TVariant extends "base" ? [typeof For] : [typeof ForWithWrapper];
@@ -10,21 +10,21 @@ type UsePresenceOptions = {
10
10
  */
11
11
  variant?: "animation" | "transition";
12
12
  };
13
+ type PresencePropGetters = {
14
+ getPresenceProps: (innerProps: InferProps<HTMLElement>) => InferProps<HTMLElement>;
15
+ };
13
16
  type UsePresenceResult = {
14
- isPresent: boolean;
15
- isPresentOrIsTransitionComplete: boolean;
16
- propGetters: {
17
- getPresenceProps: (innerProps: InferProps<HTMLElement>) => InferProps<HTMLElement>;
18
- };
17
+ isMounted: boolean;
18
+ isTransitionComplete: boolean;
19
+ propGetters: PresencePropGetters;
19
20
  ref: React.Ref<HTMLElement>;
20
- shouldStartTransition: boolean;
21
21
  };
22
22
  //#endregion
23
23
  //#region src/components/common/presence/presence.d.ts
24
24
  type RefProp = {
25
25
  ref?: React.Ref<HTMLElement>;
26
26
  };
27
- type RenderPropContext = Omit<UsePresenceResult, "propGetters" | "ref">;
27
+ type RenderPropContext = Omit<UsePresenceResult, "propGetters" | "ref"> & Pick<UsePresenceOptions, "present">;
28
28
  type PresenceProps = UsePresenceOptions & {
29
29
  children?: React.ReactElement<RefProp> | ((props: RenderPropContext) => React.ReactElement<RefProp>);
30
30
  className?: string;
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import { t as Presence } from "../../presence-CWOGx-be.js";
2
+ import { t as Presence } from "../../presence-CHd9s3IS.js";
3
3
  export { Presence };
@@ -1,2 +1,2 @@
1
- import { n as SuspenseWithBoundaryProps, t as SuspenseWithBoundary } from "../../index-ClV6w6nv.js";
1
+ import { n as SuspenseWithBoundaryProps, t as SuspenseWithBoundary } from "../../index-Ce3J0_vR.js";
2
2
  export { SuspenseWithBoundary, SuspenseWithBoundaryProps };
@@ -1,36 +1,3 @@
1
1
  "use client";
2
- import { t as __exportAll } from "../../chunk-pbuEa-1d.js";
3
- import { getRegularChildren, getSingleSlot } from "@zayne-labs/toolkit-react/utils";
4
- import { isFunction } from "@zayne-labs/toolkit-type-helpers";
5
- //#region src/components/common/switch/switch.tsx
6
- const defaultValueSymbol = Symbol("default-value");
7
- function SwitchRoot(props) {
8
- const { children, value = defaultValueSymbol } = props;
9
- const defaultCase = getSingleSlot(children, SwitchDefault, {
10
- errorMessage: "Only one <Switch.Default> component is allowed",
11
- throwOnMultipleSlotMatch: true
12
- });
13
- return getRegularChildren(children, SwitchDefault).find((child) => {
14
- if (value === defaultValueSymbol) return Boolean(child.props.when);
15
- return child.props.when === value;
16
- }) ?? defaultCase;
17
- }
18
- function SwitchMatch(props) {
19
- const { children, when } = props;
20
- return isFunction(children) ? children(when) : children;
21
- }
22
- function SwitchDefault({ children }) {
23
- return children;
24
- }
25
- SwitchDefault.slotSymbol = Symbol("switch-default");
26
- //#endregion
27
- //#region src/components/common/switch/switch-parts.ts
28
- var switch_parts_exports = /* @__PURE__ */ __exportAll({
29
- Default: () => SwitchDefault,
30
- Match: () => SwitchMatch,
31
- Root: () => SwitchRoot
32
- });
33
- //#endregion
2
+ import { i as SwitchRoot, n as SwitchDefault, r as SwitchMatch, t as switch_parts_exports } from "../../switch-Dwy5Gzsb.js";
34
3
  export { switch_parts_exports as Switch, SwitchDefault, SwitchMatch, SwitchRoot };
35
-
36
- //# sourceMappingURL=index.js.map
@@ -25,16 +25,12 @@ function Teleport(props) {
25
25
  return;
26
26
  }
27
27
  const tempWrapper = document.createElement("div");
28
- tempWrapper.id = TELEPORT_KEY;
28
+ tempWrapper.dataset.id = TELEPORT_KEY;
29
29
  tempWrapper.style.display = "contents";
30
30
  destination?.insertAdjacentElement(insertPosition, tempWrapper);
31
- const timeoutId = setTimeout(() => {
32
- tempWrapper.replaceWith(...tempWrapper.children);
33
- }, 0);
34
31
  stableUpdatePortalContainer(tempWrapper);
35
32
  return () => {
36
33
  tempWrapper.remove();
37
- clearTimeout(timeoutId);
38
34
  };
39
35
  }, [
40
36
  to,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/common/teleport/teleport.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallbackRef } from \"@zayne-labs/toolkit-react\";\nimport { isString, type AnyString } from \"@zayne-labs/toolkit-type-helpers\";\nimport { useLayoutEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { ClientGate } from \"../client-gate\";\n\ntype ValidHtmlTags = keyof HTMLElementTagNameMap;\n\nexport type TeleportProps = {\n\tchildren: React.ReactNode;\n\tinsertPosition?: InsertPosition;\n\tto: AnyString | HTMLElement | React.RefObject<HTMLElement> | ValidHtmlTags | null;\n};\n\nconst TELEPORT_KEY = \"teleport-wrapper\";\n\nconst getDestination = (to: NonNullable<TeleportProps[\"to\"]>) => {\n\tif (isString(to)) {\n\t\treturn document.querySelector<HTMLElement>(to);\n\t}\n\n\tif (to instanceof HTMLElement) {\n\t\treturn to;\n\t}\n\n\treturn to.current;\n};\n\nfunction Teleport(props: TeleportProps) {\n\tconst { children, insertPosition, to } = props;\n\n\tconst [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);\n\n\tconst stableUpdatePortalContainer = useCallbackRef((destination: HTMLElement | null) => {\n\t\t// eslint-disable-next-line react-x/set-state-in-effect -- Ignore\n\t\tsetPortalContainer(destination);\n\t});\n\n\tuseLayoutEffect(() => {\n\t\tif (!to) return;\n\n\t\tconst destination = getDestination(to);\n\n\t\tif (!insertPosition) {\n\t\t\tdestination && stableUpdatePortalContainer(destination);\n\t\t\treturn;\n\t\t}\n\n\t\tconst tempWrapper = document.createElement(\"div\");\n\t\ttempWrapper.id = TELEPORT_KEY;\n\t\ttempWrapper.style.display = \"contents\";\n\n\t\tdestination?.insertAdjacentElement(insertPosition, tempWrapper);\n\n\t\tconst timeoutId = setTimeout(() => {\n\t\t\ttempWrapper.replaceWith(...tempWrapper.children);\n\t\t}, 0);\n\n\t\tstableUpdatePortalContainer(tempWrapper);\n\n\t\treturn () => {\n\t\t\ttempWrapper.remove();\n\t\t\tclearTimeout(timeoutId);\n\t\t};\n\t}, [to, insertPosition, stableUpdatePortalContainer]);\n\n\treturn (\n\t\t<ClientGate>\n\t\t\t{() => portalContainer && createPortal(children, portalContainer, TELEPORT_KEY)}\n\t\t</ClientGate>\n\t);\n}\n\nexport { Teleport };\n"],"mappings":";;;;;;;AAgBA,MAAM,eAAe;AAErB,MAAM,kBAAkB,OAAyC;AAChE,KAAI,SAAS,GAAG,CACf,QAAO,SAAS,cAA2B,GAAG;AAG/C,KAAI,cAAc,YACjB,QAAO;AAGR,QAAO,GAAG;;AAGX,SAAS,SAAS,OAAsB;CACvC,MAAM,EAAE,UAAU,gBAAgB,OAAO;CAEzC,MAAM,CAAC,iBAAiB,sBAAsB,SAA6B,KAAK;CAEhF,MAAM,8BAA8B,gBAAgB,gBAAoC;AAEvF,qBAAmB,YAAY;GAC9B;AAEF,uBAAsB;AACrB,MAAI,CAAC,GAAI;EAET,MAAM,cAAc,eAAe,GAAG;AAEtC,MAAI,CAAC,gBAAgB;AACpB,kBAAe,4BAA4B,YAAY;AACvD;;EAGD,MAAM,cAAc,SAAS,cAAc,MAAM;AACjD,cAAY,KAAK;AACjB,cAAY,MAAM,UAAU;AAE5B,eAAa,sBAAsB,gBAAgB,YAAY;EAE/D,MAAM,YAAY,iBAAiB;AAClC,eAAY,YAAY,GAAG,YAAY,SAAS;KAC9C,EAAE;AAEL,8BAA4B,YAAY;AAExC,eAAa;AACZ,eAAY,QAAQ;AACpB,gBAAa,UAAU;;IAEtB;EAAC;EAAI;EAAgB;EAA4B,CAAC;AAErD,QACC,oBAAC,YAAD,EAAA,gBACQ,mBAAmB,aAAa,UAAU,iBAAiB,aAAa,EACnE,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/common/teleport/teleport.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallbackRef } from \"@zayne-labs/toolkit-react\";\nimport { isString, type AnyString } from \"@zayne-labs/toolkit-type-helpers\";\nimport { useLayoutEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { ClientGate } from \"../client-gate\";\n\ntype ValidHtmlTags = keyof HTMLElementTagNameMap;\n\nexport type TeleportProps = {\n\tchildren: React.ReactNode;\n\tinsertPosition?: InsertPosition;\n\tto: AnyString | HTMLElement | React.RefObject<HTMLElement> | ValidHtmlTags | null;\n};\n\nconst TELEPORT_KEY = \"teleport-wrapper\";\n\nconst getDestination = (to: NonNullable<TeleportProps[\"to\"]>) => {\n\tif (isString(to)) {\n\t\treturn document.querySelector<HTMLElement>(to);\n\t}\n\n\tif (to instanceof HTMLElement) {\n\t\treturn to;\n\t}\n\n\treturn to.current;\n};\n\nfunction Teleport(props: TeleportProps) {\n\tconst { children, insertPosition, to } = props;\n\n\tconst [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);\n\n\tconst stableUpdatePortalContainer = useCallbackRef((destination: HTMLElement | null) => {\n\t\t// eslint-disable-next-line react-x/set-state-in-effect -- Ignore\n\t\tsetPortalContainer(destination);\n\t});\n\n\tuseLayoutEffect(() => {\n\t\tif (!to) return;\n\n\t\tconst destination = getDestination(to);\n\n\t\tif (!insertPosition) {\n\t\t\tdestination && stableUpdatePortalContainer(destination);\n\t\t\treturn;\n\t\t}\n\n\t\tconst tempWrapper = document.createElement(\"div\");\n\t\ttempWrapper.dataset.id = TELEPORT_KEY;\n\t\ttempWrapper.style.display = \"contents\";\n\n\t\tdestination?.insertAdjacentElement(insertPosition, tempWrapper);\n\n\t\t// const timeoutId = setTimeout(() => {\n\t\t// \ttempWrapper.replaceWith(...tempWrapper.children);\n\t\t// }, 0);\n\n\t\tstableUpdatePortalContainer(tempWrapper);\n\n\t\treturn () => {\n\t\t\ttempWrapper.remove();\n\t\t};\n\t}, [to, insertPosition, stableUpdatePortalContainer]);\n\n\treturn (\n\t\t<ClientGate>\n\t\t\t{() => portalContainer && createPortal(children, portalContainer, TELEPORT_KEY)}\n\t\t</ClientGate>\n\t);\n}\n\nexport { Teleport };\n"],"mappings":";;;;;;;AAgBA,MAAM,eAAe;AAErB,MAAM,kBAAkB,OAAyC;AAChE,KAAI,SAAS,GAAG,CACf,QAAO,SAAS,cAA2B,GAAG;AAG/C,KAAI,cAAc,YACjB,QAAO;AAGR,QAAO,GAAG;;AAGX,SAAS,SAAS,OAAsB;CACvC,MAAM,EAAE,UAAU,gBAAgB,OAAO;CAEzC,MAAM,CAAC,iBAAiB,sBAAsB,SAA6B,KAAK;CAEhF,MAAM,8BAA8B,gBAAgB,gBAAoC;AAEvF,qBAAmB,YAAY;GAC9B;AAEF,uBAAsB;AACrB,MAAI,CAAC,GAAI;EAET,MAAM,cAAc,eAAe,GAAG;AAEtC,MAAI,CAAC,gBAAgB;AACpB,kBAAe,4BAA4B,YAAY;AACvD;;EAGD,MAAM,cAAc,SAAS,cAAc,MAAM;AACjD,cAAY,QAAQ,KAAK;AACzB,cAAY,MAAM,UAAU;AAE5B,eAAa,sBAAsB,gBAAgB,YAAY;AAM/D,8BAA4B,YAAY;AAExC,eAAa;AACZ,eAAY,QAAQ;;IAEnB;EAAC;EAAI;EAAgB;EAA4B,CAAC;AAErD,QACC,oBAAC,YAAD,EAAA,gBACQ,mBAAmB,aAAa,UAAU,iBAAiB,aAAa,EACnE,CAAA"}
@@ -1,4 +1,4 @@
1
- import { o as ErrorBoundaryProps } from "./index-BUIvQ2wP.js";
1
+ import { o as ErrorBoundaryProps } from "./index-Dbt-nJhQ.js";
2
2
  import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/components/common/suspense-with-boundary/suspense-with-boundary.d.ts
@@ -10,4 +10,4 @@ type SuspenseWithBoundaryProps = {
10
10
  declare function SuspenseWithBoundary(props: SuspenseWithBoundaryProps): react_jsx_runtime0.JSX.Element;
11
11
  //#endregion
12
12
  export { SuspenseWithBoundaryProps as n, SuspenseWithBoundary as t };
13
- //# sourceMappingURL=index-ClV6w6nv.d.ts.map
13
+ //# sourceMappingURL=index-Ce3J0_vR.d.ts.map
@@ -71,4 +71,4 @@ type UseErrorBoundaryReturn = {
71
71
  };
72
72
  //#endregion
73
73
  export { ErrorBoundary as a, useErrorBoundaryContext as i, useErrorBoundary as n, ErrorBoundaryProps as o, ErrorBoundaryContextType as r, ErrorFallbackProps as s, UseErrorBoundaryReturn as t };
74
- //# sourceMappingURL=index-BUIvQ2wP.d.ts.map
74
+ //# sourceMappingURL=index-Dbt-nJhQ.d.ts.map
@@ -0,0 +1,225 @@
1
+ import { n as SlotRoot } from "./slot-DuwoiC2C.js";
2
+ import { isFunction } from "@zayne-labs/toolkit-type-helpers";
3
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
4
+ import { useCallbackRef, useComposeRefs, useToggle } from "@zayne-labs/toolkit-react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ import { on } from "@zayne-labs/toolkit-core";
7
+ //#region src/components/common/presence/use-presence.ts
8
+ const useStateMachine = (config) => {
9
+ const reducer = (prevState, event) => {
10
+ return config.states[prevState][event] ?? prevState;
11
+ };
12
+ return useReducer(reducer, config.initial);
13
+ };
14
+ const getAnimationName = (styles) => styles?.animationName ?? "none";
15
+ /**
16
+ * React hook that provides the ability to animate the mount/unmount of a component.
17
+ * @see https://github.com/radix-ui/primitives/blob/main/packages/react/presence/src/presence.tsx
18
+ */
19
+ const usePresence = (options) => {
20
+ const { onExitComplete, present: presentProp, variant = "animation" } = options;
21
+ const stableOnExitComplete = useCallbackRef(onExitComplete);
22
+ const [node, setNode] = useState(null);
23
+ const [isTransitionComplete, toggleIsTransitionComplete] = useToggle(false);
24
+ const stylesRef = useRef(null);
25
+ const prevNodeStateRef = useRef({
26
+ prevAnimationName: "none",
27
+ prevPresent: presentProp
28
+ });
29
+ const [mountState, send] = useStateMachine({
30
+ initial: presentProp ? "mounted" : "unmounted",
31
+ states: {
32
+ mounted: {
33
+ ANIMATION_OUT: "unmountSuspended",
34
+ UNMOUNT: "unmounted"
35
+ },
36
+ unmounted: { MOUNT: "mounted" },
37
+ unmountSuspended: {
38
+ ANIMATION_END: "unmounted",
39
+ MOUNT: "mounted"
40
+ }
41
+ }
42
+ });
43
+ useEffect(() => {
44
+ const currentAnimationName = getAnimationName(stylesRef.current);
45
+ prevNodeStateRef.current.prevAnimationName = mountState === "mounted" ? currentAnimationName : "none";
46
+ }, [mountState]);
47
+ useLayoutEffect(() => {
48
+ const styles = stylesRef.current;
49
+ const wasPresent = prevNodeStateRef.current.prevPresent;
50
+ if (!(wasPresent !== presentProp)) return;
51
+ const prevAnimationName = prevNodeStateRef.current.prevAnimationName;
52
+ const currentAnimationName = getAnimationName(styles);
53
+ switch (true) {
54
+ case presentProp:
55
+ send("MOUNT");
56
+ if (variant === "transition") requestAnimationFrame(() => toggleIsTransitionComplete(true));
57
+ break;
58
+ case Boolean(node):
59
+ if (variant === "animation") {
60
+ /**
61
+ * When `present` changes to `false`, we check changes to animation-name to
62
+ * determine whether an animation has started. We chose this approach (reading
63
+ * computed styles) because there is no `animationrun` event (like the `transitionrun` event) and `animationstart`
64
+ * fires after `animation-delay` has expired which would be too late.
65
+ */
66
+ const isAnimationStarted = currentAnimationName !== "none" && styles?.display !== "none" && prevAnimationName !== currentAnimationName;
67
+ send(wasPresent && isAnimationStarted ? "ANIMATION_OUT" : "UNMOUNT");
68
+ }
69
+ break;
70
+ default:
71
+ send("UNMOUNT");
72
+ break;
73
+ }
74
+ prevNodeStateRef.current.prevPresent = presentProp;
75
+ }, [
76
+ presentProp,
77
+ node,
78
+ send,
79
+ variant,
80
+ toggleIsTransitionComplete
81
+ ]);
82
+ useLayoutEffect(() => {
83
+ if (!node) {
84
+ send("ANIMATION_END");
85
+ return;
86
+ }
87
+ const setupAnimationListeners = () => {
88
+ let timeoutId;
89
+ const ownerWindow = node.ownerDocument.defaultView ?? globalThis;
90
+ const handleAnimationStart = (event) => {
91
+ if (!(event.target === node)) return;
92
+ prevNodeStateRef.current.prevAnimationName = getAnimationName(stylesRef.current);
93
+ };
94
+ /**
95
+ * @description Triggering an ANIMATION_OUT during an ANIMATION_IN will fire an `animationcancel`
96
+ * event for ANIMATION_IN after we have entered `unmountSuspended` state. So, we
97
+ * make sure we only trigger ANIMATION_END for the currently active animation.
98
+ */
99
+ const handleAnimationEnd = (event) => {
100
+ const isCurrentAnimation = getAnimationName(stylesRef.current).includes(CSS.escape(event.animationName));
101
+ if (!(event.target === node && isCurrentAnimation)) return;
102
+ send("ANIMATION_END");
103
+ if (!prevNodeStateRef.current.prevPresent) {
104
+ const currentFillMode = node.style.animationFillMode;
105
+ node.style.animationFillMode = "forwards";
106
+ timeoutId = ownerWindow.setTimeout(() => {
107
+ if (node.style.animationFillMode === "forwards") node.style.animationFillMode = currentFillMode;
108
+ });
109
+ }
110
+ };
111
+ const onAnimationStartCleanup = on(node, "animationstart", handleAnimationStart);
112
+ const onAnimationEndCleanup = on(node, "animationend", handleAnimationEnd);
113
+ const onAnimationCancelCleanup = on(node, "animationcancel", handleAnimationEnd);
114
+ const cleanup = () => {
115
+ ownerWindow.clearTimeout(timeoutId);
116
+ onAnimationStartCleanup();
117
+ onAnimationEndCleanup();
118
+ onAnimationCancelCleanup();
119
+ };
120
+ return cleanup;
121
+ };
122
+ const setupTransitionListeners = () => {
123
+ const handleTransitionRun = (event) => {
124
+ if (!(event.target === node)) return;
125
+ send("ANIMATION_OUT");
126
+ };
127
+ const handleTransitionEnd = (event) => {
128
+ if (!(event.target === node && !prevNodeStateRef.current.prevPresent)) return;
129
+ send("ANIMATION_END");
130
+ };
131
+ const onTransitionRunCleanup = on(node, "transitionrun", handleTransitionRun);
132
+ const onTransitionEndCleanup = on(node, "transitionend", handleTransitionEnd);
133
+ const onTransitionCancelCleanup = on(node, "transitioncancel", handleTransitionEnd);
134
+ const cleanup = () => {
135
+ onTransitionRunCleanup();
136
+ onTransitionEndCleanup();
137
+ onTransitionCancelCleanup();
138
+ };
139
+ return cleanup;
140
+ };
141
+ switch (variant) {
142
+ case "animation": return setupAnimationListeners();
143
+ case "transition": return setupTransitionListeners();
144
+ default: throw new Error(`Invalid variant: ${variant}`);
145
+ }
146
+ }, [
147
+ node,
148
+ send,
149
+ variant
150
+ ]);
151
+ useEffect(() => {
152
+ if (!presentProp && mountState === "unmounted") {
153
+ toggleIsTransitionComplete(false);
154
+ stableOnExitComplete?.();
155
+ }
156
+ }, [
157
+ mountState,
158
+ presentProp,
159
+ stableOnExitComplete,
160
+ toggleIsTransitionComplete
161
+ ]);
162
+ const ref = useCallbackRef((refNode) => {
163
+ setNode(refNode);
164
+ if (refNode) stylesRef.current = getComputedStyle(refNode);
165
+ });
166
+ const isMounted = ["mounted", "unmountSuspended"].includes(mountState);
167
+ const transitionPhase = presentProp && isTransitionComplete ? "enter" : "exit";
168
+ const animationPhase = presentProp ? "enter" : "exit";
169
+ const getPresenceProps = useCallback((innerProps) => {
170
+ return {
171
+ "data-animation-phase": animationPhase,
172
+ "data-mounted": isMounted,
173
+ "data-present": presentProp,
174
+ "data-transition-phase": transitionPhase,
175
+ "data-variant": variant,
176
+ ...innerProps,
177
+ className: innerProps.className
178
+ };
179
+ }, [
180
+ animationPhase,
181
+ isMounted,
182
+ presentProp,
183
+ transitionPhase,
184
+ variant
185
+ ]);
186
+ const propGetters = useMemo(() => ({ getPresenceProps }), [getPresenceProps]);
187
+ return useMemo(() => ({
188
+ isMounted,
189
+ isTransitionComplete,
190
+ propGetters,
191
+ ref
192
+ }), [
193
+ isMounted,
194
+ isTransitionComplete,
195
+ propGetters,
196
+ ref
197
+ ]);
198
+ };
199
+ //#endregion
200
+ //#region src/components/common/presence/presence.tsx
201
+ function Presence(props) {
202
+ const { children, className, forceMount = false, onExitComplete, present, variant } = props;
203
+ const { isMounted, isTransitionComplete, propGetters, ref: presenceRef } = usePresence({
204
+ onExitComplete,
205
+ present,
206
+ variant
207
+ });
208
+ const context = {
209
+ isMounted,
210
+ isTransitionComplete,
211
+ present
212
+ };
213
+ const resolvedChild = isFunction(children) ? children(context) : children;
214
+ const ref = useComposeRefs(presenceRef, resolvedChild?.props.ref ?? resolvedChild.ref);
215
+ if (!(forceMount || (variant === "transition" ? isMounted || isTransitionComplete : isMounted))) return null;
216
+ return /* @__PURE__ */ jsx(SlotRoot, {
217
+ ref,
218
+ ...propGetters.getPresenceProps({ className }),
219
+ children: resolvedChild
220
+ });
221
+ }
222
+ //#endregion
223
+ export { Presence as t };
224
+
225
+ //# sourceMappingURL=presence-CHd9s3IS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence-CHd9s3IS.js","names":["Slot.Root"],"sources":["../../src/components/common/presence/use-presence.ts","../../src/components/common/presence/presence.tsx"],"sourcesContent":["import { on } from \"@zayne-labs/toolkit-core\";\nimport { useCallbackRef, useToggle } from \"@zayne-labs/toolkit-react\";\nimport type { InferProps } from \"@zayne-labs/toolkit-react/utils\";\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from \"react\";\n\ntype StateMachineConfig<TState extends string, TEvent extends string> = {\n\tinitial: TState;\n\tstates: Record<TState, Partial<Record<TEvent, TState>>>;\n};\n\nconst useStateMachine = <TState extends string, TEvent extends string>(\n\tconfig: StateMachineConfig<TState, TEvent>\n) => {\n\tconst reducer = (prevState: TState, event: TEvent): TState => {\n\t\tconst newState = config.states[prevState][event] ?? prevState;\n\n\t\treturn newState;\n\t};\n\n\treturn useReducer(reducer, config.initial);\n};\n\nconst getAnimationName = (styles: CSSStyleDeclaration | null) => styles?.animationName ?? \"none\";\n\nexport type UsePresenceOptions = {\n\tonExitComplete?: () => void;\n\tpresent: boolean;\n\t/**\n\t * @default \"animation\"\n\t */\n\tvariant?: \"animation\" | \"transition\";\n};\n\nexport type PresencePropGetters = {\n\tgetPresenceProps: (innerProps: InferProps<HTMLElement>) => InferProps<HTMLElement>;\n};\n\nexport type UsePresenceResult = {\n\tisMounted: boolean;\n\tisTransitionComplete: boolean;\n\tpropGetters: PresencePropGetters;\n\tref: React.Ref<HTMLElement>;\n};\n\n/**\n * React hook that provides the ability to animate the mount/unmount of a component.\n * @see https://github.com/radix-ui/primitives/blob/main/packages/react/presence/src/presence.tsx\n */\n\nconst usePresence = (options: UsePresenceOptions): UsePresenceResult => {\n\tconst { onExitComplete, present: presentProp, variant = \"animation\" } = options;\n\n\tconst stableOnExitComplete = useCallbackRef(onExitComplete);\n\n\tconst [node, setNode] = useState<HTMLElement | null>(null);\n\n\tconst [isTransitionComplete, toggleIsTransitionComplete] = useToggle(false);\n\n\tconst stylesRef = useRef<CSSStyleDeclaration | null>(null);\n\n\tconst prevNodeStateRef = useRef<{\n\t\tprevAnimationName: string;\n\t\tprevPresent: boolean;\n\t}>({\n\t\tprevAnimationName: \"none\",\n\t\tprevPresent: presentProp,\n\t});\n\n\tconst initialState = presentProp ? \"mounted\" : \"unmounted\";\n\n\tconst [mountState, send] = useStateMachine({\n\t\tinitial: initialState,\n\t\tstates: {\n\t\t\tmounted: {\n\t\t\t\tANIMATION_OUT: \"unmountSuspended\",\n\t\t\t\tUNMOUNT: \"unmounted\",\n\t\t\t},\n\t\t\tunmounted: {\n\t\t\t\tMOUNT: \"mounted\",\n\t\t\t},\n\t\t\tunmountSuspended: {\n\t\t\t\tANIMATION_END: \"unmounted\",\n\t\t\t\tMOUNT: \"mounted\",\n\t\t\t},\n\t\t},\n\t});\n\n\tuseEffect(() => {\n\t\tconst currentAnimationName = getAnimationName(stylesRef.current);\n\n\t\tprevNodeStateRef.current.prevAnimationName =\n\t\t\tmountState === \"mounted\" ? currentAnimationName : \"none\";\n\t}, [mountState]);\n\n\tuseLayoutEffect(() => {\n\t\tconst styles = stylesRef.current;\n\t\tconst wasPresent = prevNodeStateRef.current.prevPresent;\n\t\tconst hasPresentChanged = wasPresent !== presentProp;\n\n\t\tif (!hasPresentChanged) return;\n\n\t\tconst prevAnimationName = prevNodeStateRef.current.prevAnimationName;\n\t\tconst currentAnimationName = getAnimationName(styles);\n\n\t\tswitch (true) {\n\t\t\tcase presentProp: {\n\t\t\t\tsend(\"MOUNT\");\n\n\t\t\t\tif (variant === \"transition\") {\n\t\t\t\t\trequestAnimationFrame(() => toggleIsTransitionComplete(true));\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase Boolean(node): {\n\t\t\t\tif (variant === \"animation\") {\n\t\t\t\t\tconst hasAnimation = currentAnimationName !== \"none\" && styles?.display !== \"none\";\n\n\t\t\t\t\t/**\n\t\t\t\t\t * When `present` changes to `false`, we check changes to animation-name to\n\t\t\t\t\t * determine whether an animation has started. We chose this approach (reading\n\t\t\t\t\t * computed styles) because there is no `animationrun` event (like the `transitionrun` event) and `animationstart`\n\t\t\t\t\t * fires after `animation-delay` has expired which would be too late.\n\t\t\t\t\t */\n\n\t\t\t\t\tconst isAnimationStarted = hasAnimation && prevAnimationName !== currentAnimationName;\n\n\t\t\t\t\tconst isAnimatingOut = wasPresent && isAnimationStarted;\n\n\t\t\t\t\tsend(isAnimatingOut ? \"ANIMATION_OUT\" : \"UNMOUNT\");\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tsend(\"UNMOUNT\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tprevNodeStateRef.current.prevPresent = presentProp;\n\t}, [presentProp, node, send, variant, toggleIsTransitionComplete]);\n\n\tuseLayoutEffect(() => {\n\t\tif (!node) {\n\t\t\t// Transition to the unmounted state if the node is removed prematurely.\n\t\t\t// We avoid doing so during cleanup as the node may change but still exist.\n\t\t\tsend(\"ANIMATION_END\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst setupAnimationListeners = () => {\n\t\t\tlet timeoutId: number;\n\n\t\t\tconst ownerWindow = node.ownerDocument.defaultView ?? globalThis;\n\n\t\t\tconst handleAnimationStart = (event: AnimationEvent) => {\n\t\t\t\tconst isTargetAnimatingNode = event.target === node;\n\n\t\t\t\tif (!isTargetAnimatingNode) return;\n\n\t\t\t\tprevNodeStateRef.current.prevAnimationName = getAnimationName(stylesRef.current);\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * @description Triggering an ANIMATION_OUT during an ANIMATION_IN will fire an `animationcancel`\n\t\t\t * event for ANIMATION_IN after we have entered `unmountSuspended` state. So, we\n\t\t\t * make sure we only trigger ANIMATION_END for the currently active animation.\n\t\t\t */\n\t\t\tconst handleAnimationEnd = (event: AnimationEvent) => {\n\t\t\t\tconst currentAnimationName = getAnimationName(stylesRef.current);\n\n\t\t\t\t// The event.animationName is unescaped for CSS syntax, so we need to escape it to compare with the animationName computed from the style.\n\t\t\t\tconst isCurrentAnimation = currentAnimationName.includes(CSS.escape(event.animationName));\n\n\t\t\t\tconst isTargetAnimatingNode = event.target === node && isCurrentAnimation;\n\n\t\t\t\tif (!isTargetAnimatingNode) return;\n\n\t\t\t\t// With React 18 concurrency this update is applied a frame after the\n\t\t\t\t// animation ends, creating a flash of visible content. By setting the\n\t\t\t\t// animation fill mode to \"forwards\", we force the node to keep the\n\t\t\t\t// styles of the last keyframe, removing the flash.\n\n\t\t\t\t// Previously we flushed the update via ReactDom.flushSync, but with\n\t\t\t\t// exit animations this resulted in the node being removed from the\n\t\t\t\t// DOM before the synthetic animationEnd event was dispatched, meaning\n\t\t\t\t// user-provided event handlers would not be called.\n\t\t\t\t// https://github.com/radix-ui/primitives/pull/1849\n\t\t\t\tsend(\"ANIMATION_END\");\n\n\t\t\t\tif (!prevNodeStateRef.current.prevPresent) {\n\t\t\t\t\tconst currentFillMode = node.style.animationFillMode;\n\t\t\t\t\tnode.style.animationFillMode = \"forwards\";\n\n\t\t\t\t\t// Reset the style after the node had time to unmount (for cases\n\t\t\t\t\t// where the component chooses not to unmount). Doing this any\n\t\t\t\t\t// sooner than `setTimeout` (e.g. with `requestAnimationFrame`)\n\t\t\t\t\t// still causes a flash.\n\t\t\t\t\ttimeoutId = ownerWindow.setTimeout(() => {\n\t\t\t\t\t\tif (node.style.animationFillMode === \"forwards\") {\n\t\t\t\t\t\t\tnode.style.animationFillMode = currentFillMode;\n\t\t\t\t\t\t}\n\t\t\t\t\t}) as never;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst onAnimationStartCleanup = on(node, \"animationstart\", handleAnimationStart);\n\t\t\tconst onAnimationEndCleanup = on(node, \"animationend\", handleAnimationEnd);\n\t\t\tconst onAnimationCancelCleanup = on(node, \"animationcancel\", handleAnimationEnd);\n\n\t\t\tconst cleanup = () => {\n\t\t\t\townerWindow.clearTimeout(timeoutId);\n\t\t\t\tonAnimationStartCleanup();\n\t\t\t\tonAnimationEndCleanup();\n\t\t\t\tonAnimationCancelCleanup();\n\t\t\t};\n\n\t\t\treturn cleanup;\n\t\t};\n\n\t\tconst setupTransitionListeners = () => {\n\t\t\tconst handleTransitionRun = (event: TransitionEvent) => {\n\t\t\t\tconst isTargetTransitioningNode = event.target === node;\n\n\t\t\t\tif (!isTargetTransitioningNode) return;\n\n\t\t\t\tsend(\"ANIMATION_OUT\");\n\t\t\t};\n\n\t\t\tconst handleTransitionEnd = (event: TransitionEvent) => {\n\t\t\t\tconst isTargetTransitioningNode =\n\t\t\t\t\tevent.target === node && !prevNodeStateRef.current.prevPresent;\n\n\t\t\t\tif (!isTargetTransitioningNode) return;\n\n\t\t\t\tsend(\"ANIMATION_END\");\n\t\t\t};\n\n\t\t\tconst onTransitionRunCleanup = on(node, \"transitionrun\", handleTransitionRun);\n\t\t\tconst onTransitionEndCleanup = on(node, \"transitionend\", handleTransitionEnd);\n\t\t\tconst onTransitionCancelCleanup = on(node, \"transitioncancel\", handleTransitionEnd);\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tonTransitionRunCleanup();\n\t\t\t\tonTransitionEndCleanup();\n\t\t\t\tonTransitionCancelCleanup();\n\t\t\t};\n\n\t\t\treturn cleanup;\n\t\t};\n\n\t\tswitch (variant) {\n\t\t\tcase \"animation\": {\n\t\t\t\tconst cleanup = setupAnimationListeners();\n\n\t\t\t\treturn cleanup;\n\t\t\t}\n\n\t\t\tcase \"transition\": {\n\t\t\t\tconst cleanup = setupTransitionListeners();\n\n\t\t\t\treturn cleanup;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tvariant satisfies never;\n\t\t\t\tthrow new Error(`Invalid variant: ${variant}`);\n\t\t\t}\n\t\t}\n\t}, [node, send, variant]);\n\n\tuseEffect(() => {\n\t\tconst isExitCompleted = !presentProp && mountState === \"unmounted\";\n\n\t\tif (isExitCompleted) {\n\t\t\ttoggleIsTransitionComplete(false);\n\t\t\tstableOnExitComplete?.();\n\t\t}\n\t}, [mountState, presentProp, stableOnExitComplete, toggleIsTransitionComplete]);\n\n\tconst ref = useCallbackRef((refNode: HTMLElement | null) => {\n\t\tsetNode(refNode);\n\n\t\tif (refNode) {\n\t\t\tstylesRef.current = getComputedStyle(refNode);\n\t\t}\n\t});\n\n\tconst MOUNTED_STATES = [\"mounted\", \"unmountSuspended\"] satisfies Array<typeof mountState>;\n\tconst isMounted = MOUNTED_STATES.includes(mountState);\n\tconst transitionPhase = presentProp && isTransitionComplete ? \"enter\" : \"exit\";\n\tconst animationPhase = presentProp ? \"enter\" : \"exit\";\n\n\tconst getPresenceProps: PresencePropGetters[\"getPresenceProps\"] = useCallback(\n\t\t(innerProps) => {\n\t\t\treturn {\n\t\t\t\t\"data-animation-phase\": animationPhase,\n\t\t\t\t\"data-mounted\": isMounted,\n\t\t\t\t\"data-present\": presentProp,\n\t\t\t\t\"data-transition-phase\": transitionPhase,\n\t\t\t\t\"data-variant\": variant,\n\t\t\t\t...innerProps,\n\t\t\t\tclassName: innerProps.className,\n\t\t\t};\n\t\t},\n\t\t[animationPhase, isMounted, presentProp, transitionPhase, variant]\n\t);\n\n\tconst propGetters = useMemo(\n\t\t() => ({\n\t\t\tgetPresenceProps,\n\t\t}),\n\t\t[getPresenceProps]\n\t);\n\n\tconst result = useMemo<UsePresenceResult>(\n\t\t() =>\n\t\t\t({\n\t\t\t\tisMounted,\n\t\t\t\tisTransitionComplete,\n\t\t\t\tpropGetters,\n\t\t\t\tref,\n\t\t\t}) satisfies UsePresenceResult,\n\t\t[isMounted, isTransitionComplete, propGetters, ref]\n\t);\n\n\treturn result;\n};\n\nexport { usePresence };\n","\"use client\";\n\nimport { useComposeRefs } from \"@zayne-labs/toolkit-react\";\nimport { isFunction, type UnknownObject } from \"@zayne-labs/toolkit-type-helpers\";\nimport { Slot } from \"../slot\";\nimport { usePresence, type UsePresenceOptions, type UsePresenceResult } from \"./use-presence\";\n\ntype RefProp = { ref?: React.Ref<HTMLElement> };\n\ntype RenderPropContext = Omit<UsePresenceResult, \"propGetters\" | \"ref\">\n\t& Pick<UsePresenceOptions, \"present\">;\n\nexport type PresenceProps = UsePresenceOptions & {\n\tchildren?: React.ReactElement<RefProp> | ((props: RenderPropContext) => React.ReactElement<RefProp>);\n\tclassName?: string;\n\tforceMount?: boolean;\n};\n\nfunction Presence(props: PresenceProps) {\n\tconst { children, className, forceMount = false, onExitComplete, present, variant } = props;\n\n\tconst {\n\t\tisMounted,\n\t\tisTransitionComplete,\n\t\tpropGetters,\n\t\tref: presenceRef,\n\t} = usePresence({ onExitComplete, present, variant });\n\n\tconst context = {\n\t\tisMounted,\n\t\tisTransitionComplete,\n\t\tpresent,\n\t} satisfies RenderPropContext;\n\n\tconst resolvedChild = isFunction(children) ? children(context) : children;\n\n\tconst childRef = (resolvedChild?.props.ref\n\t\t?? (resolvedChild as unknown as UnknownObject).ref) as React.Ref<HTMLElement>;\n\n\tconst ref = useComposeRefs(presenceRef, childRef);\n\n\tconst shouldRender =\n\t\tforceMount || (variant === \"transition\" ? isMounted || isTransitionComplete : isMounted);\n\n\tif (!shouldRender) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<Slot.Root ref={ref} {...propGetters.getPresenceProps({ className })}>\n\t\t\t{resolvedChild}\n\t\t</Slot.Root>\n\t);\n}\n\nexport { Presence };\n"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { t as __exportAll } from "./chunk-pbuEa-1d.js";
2
+ import { getRegularChildren, getSingleSlot } from "@zayne-labs/toolkit-react/utils";
3
+ import { isFunction } from "@zayne-labs/toolkit-type-helpers";
4
+ //#region src/components/common/switch/switch.tsx
5
+ const defaultValueSymbol = Symbol("default-value");
6
+ function SwitchRoot(props) {
7
+ const { children, value = defaultValueSymbol } = props;
8
+ const defaultCase = getSingleSlot(children, SwitchDefault, {
9
+ errorMessage: "Only one <Switch.Default> component is allowed",
10
+ throwOnMultipleSlotMatch: true
11
+ });
12
+ return getRegularChildren(children, SwitchDefault).find((child) => {
13
+ if (value === defaultValueSymbol) return Boolean(child.props.when);
14
+ return child.props.when === value;
15
+ }) ?? defaultCase;
16
+ }
17
+ function SwitchMatch(props) {
18
+ const { children, when } = props;
19
+ return isFunction(children) ? children(when) : children;
20
+ }
21
+ function SwitchDefault({ children }) {
22
+ return children;
23
+ }
24
+ SwitchDefault.slotSymbol = Symbol("switch-default");
25
+ //#endregion
26
+ //#region src/components/common/switch/switch-parts.ts
27
+ var switch_parts_exports = /* @__PURE__ */ __exportAll({
28
+ Default: () => SwitchDefault,
29
+ Match: () => SwitchMatch,
30
+ Root: () => SwitchRoot
31
+ });
32
+ //#endregion
33
+ export { SwitchRoot as i, SwitchDefault as n, SwitchMatch as r, switch_parts_exports as t };
34
+
35
+ //# sourceMappingURL=switch-Dwy5Gzsb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switch-Dwy5Gzsb.js","names":[],"sources":["../../src/components/common/switch/switch.tsx","../../src/components/common/switch/switch-parts.ts"],"sourcesContent":["\"use client\";\n\nimport { getRegularChildren, getSingleSlot } from \"@zayne-labs/toolkit-react/utils\";\nimport { isFunction } from \"@zayne-labs/toolkit-type-helpers\";\n\ntype ValidSwitchComponentType = React.ReactElement<SwitchMatchProps<unknown>>;\n\nexport type SwitchRootProps<TValue> = {\n\tchildren: ValidSwitchComponentType | ValidSwitchComponentType[];\n\tvalue?: TValue;\n};\n\nconst defaultValueSymbol = Symbol(\"default-value\");\n\n// TODO - Add a factory to make this 'when' and 'value' type-safe later following the link below\n// LINK - https://tkdodo.eu/blog/building-type-safe-compound-components#component-factory-pattern\nexport function SwitchRoot<TValue>(props: SwitchRootProps<TValue>) {\n\tconst { children, value = defaultValueSymbol } = props;\n\n\tconst defaultCase = getSingleSlot(children, SwitchDefault, {\n\t\terrorMessage: \"Only one <Switch.Default> component is allowed\",\n\t\tthrowOnMultipleSlotMatch: true,\n\t});\n\n\tconst childrenCasesArray = getRegularChildren(children, SwitchDefault) as ValidSwitchComponentType[];\n\n\tconst matchedCase = childrenCasesArray.find((child) => {\n\t\t// == If value is defaultValueSymbol, match the cases in order like switch(true)\n\t\tif (value === defaultValueSymbol) {\n\t\t\treturn Boolean(child.props.when);\n\t\t}\n\n\t\t// == Otherwise, match the cases like switch(value)\n\t\treturn child.props.when === value;\n\t});\n\n\treturn matchedCase ?? defaultCase;\n}\n\nexport type SwitchMatchProps<TWhen> = {\n\tchildren: React.ReactNode | ((value: TWhen) => React.ReactNode);\n\twhen: false | TWhen | null | undefined;\n};\n\nexport function SwitchMatch<TWhen>(props: SwitchMatchProps<TWhen>) {\n\tconst { children, when } = props;\n\n\tconst resolvedChildren = isFunction(children) ? children(when as TWhen) : children;\n\n\treturn resolvedChildren;\n}\n\nexport function SwitchDefault({ children }: { children: React.ReactNode }) {\n\treturn children;\n}\nSwitchDefault.slotSymbol = Symbol(\"switch-default\");\n","export { SwitchDefault as Default, SwitchMatch as Match, SwitchRoot as Root } from \"./switch\";\n"],"mappings":";;;;AAYA,MAAM,qBAAqB,OAAO,gBAAgB;AAIlD,SAAgB,WAAmB,OAAgC;CAClE,MAAM,EAAE,UAAU,QAAQ,uBAAuB;CAEjD,MAAM,cAAc,cAAc,UAAU,eAAe;EAC1D,cAAc;EACd,0BAA0B;EAC1B,CAAC;AAcF,QAZ2B,mBAAmB,UAAU,cAAc,CAE/B,MAAM,UAAU;AAEtD,MAAI,UAAU,mBACb,QAAO,QAAQ,MAAM,MAAM,KAAK;AAIjC,SAAO,MAAM,MAAM,SAAS;GAC3B,IAEoB;;AAQvB,SAAgB,YAAmB,OAAgC;CAClE,MAAM,EAAE,UAAU,SAAS;AAI3B,QAFyB,WAAW,SAAS,GAAG,SAAS,KAAc,GAAG;;AAK3E,SAAgB,cAAc,EAAE,YAA2C;AAC1E,QAAO;;AAER,cAAc,aAAa,OAAO,iBAAiB"}
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "../../chunk-pbuEa-1d.js";
2
2
  import { n as SlotRoot } from "../../slot-DuwoiC2C.js";
3
- import { t as cnMerge } from "../../cn-Bbh2G587.js";
3
+ import { t as cnMerge } from "../../cn-jNZfGhrk.js";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/components/ui/card/card.tsx
6
6
  function CardRoot(props) {
@@ -2,7 +2,7 @@
2
2
  import { t as __exportAll } from "../../chunk-pbuEa-1d.js";
3
3
  import { n as For } from "../../for-DGTMIS0w.js";
4
4
  import { i as ShowRoot, n as ShowContent, r as ShowFallback } from "../../show-BzfAw7y3.js";
5
- import { t as cnMerge } from "../../cn-Bbh2G587.js";
5
+ import { t as cnMerge } from "../../cn-jNZfGhrk.js";
6
6
  import { isFunction } from "@zayne-labs/toolkit-type-helpers";
7
7
  import { useMemo, useState } from "react";
8
8
  import { useAnimationInterval, useCallbackRef, useStore } from "@zayne-labs/toolkit-react";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { t as __exportAll } from "../../chunk-pbuEa-1d.js";
3
3
  import { n as SlotRoot } from "../../slot-DuwoiC2C.js";
4
- import { t as cnMerge } from "../../cn-Bbh2G587.js";
4
+ import { t as cnMerge } from "../../cn-jNZfGhrk.js";
5
5
  import { composeRefs, composeTwoEventHandlers } from "@zayne-labs/toolkit-react/utils";
6
6
  import { isFunction, isNumber } from "@zayne-labs/toolkit-type-helpers";
7
7
  import { useCallback, useEffect, useMemo, useRef } from "react";
@@ -352,19 +352,29 @@ type DropZoneFileItemDeleteProps = {
352
352
  asChild?: boolean;
353
353
  } & PartInputProps["fileItemDelete"];
354
354
  declare function DropZoneFileItemDelete(props: DropZoneFileItemDeleteProps): react_jsx_runtime0.JSX.Element;
355
+ type StrictExtract<TUnion, TPick extends TUnion> = Extract<TUnion, TPick>;
355
356
  type DropZoneFileItemProgressProps = {
356
357
  asChild?: boolean;
357
- classNames?: {
358
- circular?: {
359
- root?: string;
360
- svgCircleOne?: string;
361
- svgCircleTwo?: string;
362
- svgRoot?: string;
363
- };
364
- };
365
358
  forceMount?: boolean;
366
359
  size?: number;
367
- } & PartInputProps["fileItemProgress"];
360
+ } & PartInputProps["fileItemProgress"] & ({
361
+ classNames?: {
362
+ svgCircleOne?: string;
363
+ svgCircleTwo?: string;
364
+ svgRoot?: string;
365
+ };
366
+ variant: StrictExtract<PartInputProps["fileItemProgress"]["variant"], "circular">;
367
+ } | {
368
+ classNames?: {
369
+ track?: string;
370
+ };
371
+ variant: StrictExtract<PartInputProps["fileItemProgress"]["variant"], "fill">;
372
+ } | {
373
+ classNames?: {
374
+ track?: string;
375
+ };
376
+ variant?: StrictExtract<PartInputProps["fileItemProgress"]["variant"], "linear">;
377
+ });
368
378
  declare function DropZoneFileItemProgress<TElement extends React.ElementType = "span">(props: PolymorphicPropsStrict<TElement, DropZoneFileItemProgressProps>): react_jsx_runtime0.JSX.Element | null;
369
379
  type NodeCtx<TElement extends React.ElementType> = {
370
380
  getProps: (innerProps: Partial<InferProps<TElement>>) => InferProps<TElement>;