@hexdspace/react 0.1.17 → 0.1.19

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/dist/index.d.ts CHANGED
@@ -546,9 +546,11 @@ declare class DialogController {
546
546
  }
547
547
  declare const dialogController: DialogController;
548
548
 
549
- declare const dialogPanelVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
549
+ declare const dialogSurfaceVariants: (props?: ({
550
+ chrome?: "flat" | "glass" | "glow" | "hairline" | null | undefined;
551
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
550
552
  declare function DialogContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
551
- interface DialogProps<TPayload = unknown> extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>, VariantProps<typeof dialogPanelVariants> {
553
+ interface DialogProps<TPayload = unknown> extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>, VariantProps<typeof dialogSurfaceVariants> {
552
554
  id: string;
553
555
  template: DialogTemplate<TPayload>;
554
556
  payload: TPayload;
@@ -565,7 +567,7 @@ interface DialogProps<TPayload = unknown> extends Omit<React.HTMLAttributes<HTML
565
567
  open?: boolean;
566
568
  defaultOpen?: boolean;
567
569
  }
568
- declare function Dialog<TPayload>({ id, template, payload, trigger, modal, dismissible, zIndex, maxWidthPx, onDismiss, onResolve, onOpenChange, showClose, closeLabel, open, defaultOpen, className, style, ...props }: DialogProps<TPayload>): react_jsx_runtime.JSX.Element;
570
+ declare function Dialog<TPayload>({ id, template, payload, trigger, modal, dismissible, zIndex, maxWidthPx, onDismiss, onResolve, onOpenChange, showClose, closeLabel, open, defaultOpen, chrome, className, style, ...props }: DialogProps<TPayload>): react_jsx_runtime.JSX.Element;
569
571
 
570
572
  type ControlLikeProps = {
571
573
  id?: string;
@@ -610,6 +612,7 @@ declare const skeletonVariants: (props?: ({
610
612
  } & class_variance_authority_types.ClassProp) | undefined) => string;
611
613
  interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof skeletonVariants> {
612
614
  animate?: boolean;
615
+ asChild?: boolean;
613
616
  }
614
617
  declare const Skeleton: React.ForwardRefExoticComponent<SkeletonProps & React.RefAttributes<HTMLDivElement>>;
615
618
 
package/dist/index.js CHANGED
@@ -1542,33 +1542,57 @@ Button.displayName = "Button";
1542
1542
 
1543
1543
  // src/ui/components/dialog/Dialog.tsx
1544
1544
  import { cva as cva2 } from "class-variance-authority";
1545
+ import { AnimatePresence, motion } from "motion/react";
1545
1546
  import { XIcon } from "lucide-react";
1546
1547
  import { Dialog as DialogPrimitive } from "radix-ui";
1547
1548
  import * as React2 from "react";
1548
- import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
1549
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
1549
1550
  var dialogPanelVariants = cva2(
1550
1551
  cn(
1551
1552
  "fixed left-1/2 top-1/2",
1552
1553
  "-translate-x-1/2 -translate-y-1/2",
1553
1554
  "w-[min(92vw,var(--dialog-width))]",
1554
- "pointer-events-auto",
1555
- "data-[state=open]:transition-opacity duration-[var(--motion-med)]",
1556
- "data-[state=closed]:animate-[dialog-fade-out_var(--motion-med)]",
1557
- "data-[state=closed]:pointer-events-none"
1555
+ "pointer-events-auto"
1558
1556
  )
1559
1557
  );
1560
- var dialogOverlayClass = cn(
1561
- "fixed inset-0 bg-[color:var(--overlay)]",
1562
- "data-[state=closed]:animate-[dialog-overlay-out_var(--motion-med)_cubic-bezier(0.2,0,0.2,1)]",
1563
- "data-[state=closed]:pointer-events-none"
1564
- );
1558
+ var dialogOverlayClass = cn("fixed inset-0 bg-[color:var(--overlay)]");
1559
+ var dialogSurfaceVariants = cva2("dialog-surface relative overflow-hidden", {
1560
+ variants: {
1561
+ chrome: {
1562
+ flat: "shell",
1563
+ glass: cn(
1564
+ "border border-[color:color-mix(in_oklab,var(--border),transparent_50%)]",
1565
+ "bg-[color:color-mix(in_oklab,var(--surface-1),transparent_25%)]",
1566
+ "backdrop-blur-[6px]",
1567
+ "rounded-[var(--radius-shell)]",
1568
+ "shadow-[0_18px_40px_rgba(0,0,0,0.18)]"
1569
+ ),
1570
+ glow: cn(
1571
+ "rounded-[var(--radius-shell)]",
1572
+ "border border-[color:color-mix(in_oklab,var(--border),transparent_60%)]",
1573
+ "bg-[color:var(--surface-1)]",
1574
+ "shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_55%),0_16px_36px_color-mix(in_oklab,var(--border),transparent_70%)]"
1575
+ ),
1576
+ hairline: cn(
1577
+ "rounded-[var(--radius-shell)]",
1578
+ "border border-[color:color-mix(in_oklab,var(--border),transparent_70%)]",
1579
+ "bg-transparent",
1580
+ "shadow-none"
1581
+ )
1582
+ }
1583
+ },
1584
+ defaultVariants: {
1585
+ chrome: "flat"
1586
+ }
1587
+ });
1565
1588
  function DialogContent({ className, ...props }) {
1566
1589
  return /* @__PURE__ */ jsx7("div", { className: cn("DialogContent p-6", className), ...props });
1567
1590
  }
1568
1591
  function AutoHeight({
1569
1592
  children,
1570
1593
  onReady,
1571
- resetKey
1594
+ resetKey,
1595
+ durationSeconds
1572
1596
  }) {
1573
1597
  const ref = React2.useRef(null);
1574
1598
  const [height, setHeight] = React2.useState("auto");
@@ -1609,11 +1633,12 @@ function AutoHeight({
1609
1633
  };
1610
1634
  }, [onReady]);
1611
1635
  return /* @__PURE__ */ jsx7(
1612
- "div",
1636
+ motion.div,
1613
1637
  {
1614
- className: cn("transition-[height] duration-(--motion-med) ease motion-reduce:transition-none"),
1638
+ animate: { height: height === "auto" ? "auto" : height },
1639
+ initial: false,
1640
+ transition: { duration: durationSeconds, ease: "easeOut" },
1615
1641
  style: {
1616
- height: height === "auto" ? "auto" : height,
1617
1642
  maxHeight: "calc(100vh - 4rem)",
1618
1643
  overflow: "auto",
1619
1644
  willChange: "height"
@@ -1622,6 +1647,28 @@ function AutoHeight({
1622
1647
  }
1623
1648
  );
1624
1649
  }
1650
+ function parseCssTimeSeconds(value) {
1651
+ if (!value) return null;
1652
+ if (value.endsWith("ms")) {
1653
+ const numeric = Number.parseFloat(value);
1654
+ return Number.isFinite(numeric) ? numeric / 1e3 : null;
1655
+ }
1656
+ if (value.endsWith("s")) {
1657
+ const numeric = Number.parseFloat(value);
1658
+ return Number.isFinite(numeric) ? numeric : null;
1659
+ }
1660
+ return null;
1661
+ }
1662
+ function useMotionDuration(varName, fallbackSeconds) {
1663
+ const [duration, setDuration] = React2.useState(fallbackSeconds);
1664
+ React2.useLayoutEffect(() => {
1665
+ if (typeof window === "undefined") return;
1666
+ const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
1667
+ const parsed = parseCssTimeSeconds(value);
1668
+ if (parsed !== null) setDuration(parsed);
1669
+ }, [varName]);
1670
+ return duration;
1671
+ }
1625
1672
  function Dialog({
1626
1673
  id,
1627
1674
  template,
@@ -1638,6 +1685,7 @@ function Dialog({
1638
1685
  closeLabel = "Close dialog",
1639
1686
  open: open2,
1640
1687
  defaultOpen,
1688
+ chrome,
1641
1689
  className,
1642
1690
  style,
1643
1691
  ...props
@@ -1652,6 +1700,7 @@ function Dialog({
1652
1700
  const [surfaceReady, setSurfaceReady] = React2.useState(false);
1653
1701
  const [overlayReady, setOverlayReady] = React2.useState(false);
1654
1702
  const Template = template;
1703
+ const motionDuration = useMotionDuration("--motion-fast", 0.16);
1655
1704
  const handleOpenChange = (nextOpen) => {
1656
1705
  if (!isControlled) setUncontrolledOpen(nextOpen);
1657
1706
  onOpenChange?.(nextOpen);
@@ -1681,10 +1730,6 @@ function Dialog({
1681
1730
  setOverlayReady(false);
1682
1731
  return;
1683
1732
  }
1684
- if (!isOpen && wasOpen) {
1685
- setSurfaceReady(false);
1686
- setOverlayReady(false);
1687
- }
1688
1733
  }, [isOpen]);
1689
1734
  const handleAutoHeightReady = React2.useCallback(() => {
1690
1735
  if (!isOpen) return;
@@ -1693,35 +1738,38 @@ function Dialog({
1693
1738
  setOverlayReady(true);
1694
1739
  });
1695
1740
  }, [isOpen]);
1696
- const overlayClassName = cn(
1697
- "DialogOverlay",
1698
- dialogOverlayClass,
1699
- isOpen && !overlayReady ? "opacity-0" : null,
1700
- overlayReady ? "animate-[dialog-overlay-in_var(--motion-med)_cubic-bezier(0.2,0,0.2,1)] [animation-fill-mode:both]" : null
1701
- );
1702
- const surfaceClassName = cn(
1703
- "dialog-surface relative shell overflow-hidden",
1704
- isOpen && !surfaceReady ? "opacity-0 translate-y-5" : null,
1705
- surfaceReady ? "animate-[dialog-surface-in_var(--motion-med)_cubic-bezier(0.16,1,0.3,1)] [animation-fill-mode:both]" : null
1706
- );
1741
+ const overlayClassName = cn("DialogOverlay", dialogOverlayClass);
1742
+ const surfaceClassName = cn(dialogSurfaceVariants({ chrome }));
1707
1743
  return /* @__PURE__ */ jsxs3(DialogPrimitive.Root, { open: open2, defaultOpen, onOpenChange: handleOpenChange, modal, children: [
1708
1744
  trigger ? /* @__PURE__ */ jsx7(DialogPrimitive.Trigger, { asChild: true, children: trigger }) : null,
1709
- /* @__PURE__ */ jsxs3(DialogPrimitive.Portal, { children: [
1710
- modal ? /* @__PURE__ */ jsx7(DialogPrimitive.Overlay, { className: overlayClassName, style: { zIndex: zIndex - 1 } }) : null,
1745
+ /* @__PURE__ */ jsx7(DialogPrimitive.Portal, { forceMount: true, children: /* @__PURE__ */ jsx7(AnimatePresence, { children: isOpen ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
1746
+ modal ? /* @__PURE__ */ jsx7(DialogPrimitive.Overlay, { forceMount: true, asChild: true, children: /* @__PURE__ */ jsx7(
1747
+ motion.div,
1748
+ {
1749
+ className: overlayClassName,
1750
+ style: { zIndex: zIndex - 1 },
1751
+ variants: {
1752
+ open: {
1753
+ opacity: 1,
1754
+ pointerEvents: "auto",
1755
+ transition: { duration: motionDuration, ease: "easeOut" }
1756
+ },
1757
+ closed: {
1758
+ opacity: 0,
1759
+ pointerEvents: "none",
1760
+ transition: { duration: motionDuration, ease: "easeOut" }
1761
+ }
1762
+ },
1763
+ initial: "closed",
1764
+ animate: overlayReady ? "open" : "closed",
1765
+ exit: "closed"
1766
+ }
1767
+ ) }) : null,
1711
1768
  /* @__PURE__ */ jsx7(
1712
1769
  DialogPrimitive.Content,
1713
1770
  {
1714
- className: cn(
1715
- "DialogContent",
1716
- dialogPanelVariants(),
1717
- "data-[state=closed]:[&_.dialog-surface]:animate-[dialog-surface-out_var(--motion-med)_cubic-bezier(0.4,0,1,1)]",
1718
- className
1719
- ),
1720
- style: {
1721
- ...style,
1722
- zIndex,
1723
- "--dialog-width": `${maxWidthPx}px`
1724
- },
1771
+ forceMount: true,
1772
+ asChild: true,
1725
1773
  onInteractOutside: (event) => {
1726
1774
  if (!dismissible) event.preventDefault();
1727
1775
  },
@@ -1729,22 +1777,85 @@ function Dialog({
1729
1777
  if (!dismissible) event.preventDefault();
1730
1778
  },
1731
1779
  ...props,
1732
- children: /* @__PURE__ */ jsxs3("div", { className: surfaceClassName, children: [
1733
- showClose ? /* @__PURE__ */ jsx7(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx7(
1734
- Button,
1735
- {
1736
- variant: "ghost",
1737
- size: "icon",
1738
- leftIcon: /* @__PURE__ */ jsx7(XIcon, { className: "w-5 h-5" }),
1739
- className: "absolute right-2 top-2 z-10 rounded-full",
1740
- "aria-label": closeLabel
1741
- }
1742
- ) }) : null,
1743
- /* @__PURE__ */ jsx7(AutoHeight, { onReady: handleAutoHeightReady, resetKey: contentCycle, children: /* @__PURE__ */ jsx7(Template, { id: id ?? fallbackId, payload, onResolve: handleResolve }) })
1744
- ] })
1780
+ children: /* @__PURE__ */ jsx7(
1781
+ motion.div,
1782
+ {
1783
+ className: cn("DialogContent", dialogPanelVariants(), className),
1784
+ style: {
1785
+ ...style,
1786
+ zIndex,
1787
+ "--dialog-width": `${maxWidthPx}px`
1788
+ },
1789
+ variants: {
1790
+ open: {
1791
+ opacity: 1,
1792
+ pointerEvents: "auto",
1793
+ transition: { duration: motionDuration, ease: "easeOut" }
1794
+ },
1795
+ closed: {
1796
+ opacity: 0,
1797
+ pointerEvents: "none",
1798
+ transition: { duration: motionDuration, ease: "easeIn" }
1799
+ }
1800
+ },
1801
+ initial: "open",
1802
+ animate: "open",
1803
+ exit: "closed",
1804
+ children: /* @__PURE__ */ jsxs3(
1805
+ motion.div,
1806
+ {
1807
+ className: surfaceClassName,
1808
+ style: { willChange: "transform" },
1809
+ variants: {
1810
+ open: {
1811
+ opacity: 1,
1812
+ y: 0,
1813
+ transition: { duration: motionDuration, ease: "easeOut" }
1814
+ },
1815
+ closed: {
1816
+ opacity: 0,
1817
+ y: 20,
1818
+ transition: { duration: motionDuration, ease: "easeIn" }
1819
+ }
1820
+ },
1821
+ initial: "closed",
1822
+ animate: surfaceReady ? "open" : "closed",
1823
+ exit: "closed",
1824
+ children: [
1825
+ showClose ? /* @__PURE__ */ jsx7(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx7(
1826
+ Button,
1827
+ {
1828
+ variant: "ghost",
1829
+ size: "icon",
1830
+ leftIcon: /* @__PURE__ */ jsx7(XIcon, { className: "w-5 h-5" }),
1831
+ className: "absolute right-2 top-2 z-10 rounded-full",
1832
+ "aria-label": closeLabel
1833
+ }
1834
+ ) }) : null,
1835
+ /* @__PURE__ */ jsx7(
1836
+ AutoHeight,
1837
+ {
1838
+ onReady: handleAutoHeightReady,
1839
+ resetKey: contentCycle,
1840
+ durationSeconds: motionDuration,
1841
+ children: /* @__PURE__ */ jsx7(
1842
+ Template,
1843
+ {
1844
+ id: id ?? fallbackId,
1845
+ payload,
1846
+ onResolve: handleResolve
1847
+ }
1848
+ )
1849
+ }
1850
+ )
1851
+ ]
1852
+ }
1853
+ )
1854
+ }
1855
+ )
1745
1856
  }
1746
1857
  )
1747
- ] })
1858
+ ] }) : null }) })
1748
1859
  ] });
1749
1860
  }
1750
1861
 
@@ -1752,7 +1863,7 @@ function Dialog({
1752
1863
  import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1753
1864
  var ConfirmDialog = (props) => {
1754
1865
  const p = props.payload ?? { title: "Are you sure?" };
1755
- const confirmVariant = p.variant ?? (p.danger ? "danger" : "secondary");
1866
+ const confirmVariant = p.variant ?? (p.danger ? "danger" : "success");
1756
1867
  return /* @__PURE__ */ jsxs4(DialogContent, { children: [
1757
1868
  /* @__PURE__ */ jsx8(DialogPrimitive2.Title, { className: "text-lg font-semibold", children: p.title }),
1758
1869
  p.children && p.children,
@@ -1957,7 +2068,7 @@ var closeTop = new CloseTopUseCase(registry);
1957
2068
  var dialogController = new DialogController(registry, open, resolve, dismiss, closeTop);
1958
2069
 
1959
2070
  // src/feature/dialog/infra/web/react/DialogHost.tsx
1960
- import { Fragment as Fragment2, jsx as jsx11 } from "react/jsx-runtime";
2071
+ import { Fragment as Fragment3, jsx as jsx11 } from "react/jsx-runtime";
1961
2072
  var DialogHost = () => {
1962
2073
  const [state, setState] = React3.useState(dialogController.handleGetRegistry().getState());
1963
2074
  const [closingIds, setClosingIds] = React3.useState(() => /* @__PURE__ */ new Set());
@@ -1999,7 +2110,7 @@ var DialogHost = () => {
1999
2110
  },
2000
2111
  [closeDelayMs, closingIds]
2001
2112
  );
2002
- return /* @__PURE__ */ jsx11(Fragment2, { children: state.stack.map((dialog, index) => {
2113
+ return /* @__PURE__ */ jsx11(Fragment3, { children: state.stack.map((dialog, index) => {
2003
2114
  const template = getDialogTemplate(dialog.templateKey);
2004
2115
  if (!template) {
2005
2116
  console.error(`Missing dialog template: ${dialog.templateKey}`);
@@ -2220,6 +2331,7 @@ Input.displayName = "Input";
2220
2331
 
2221
2332
  // src/ui/components/Skeleton.tsx
2222
2333
  import { cva as cva4 } from "class-variance-authority";
2334
+ import { Slot as Slot2 } from "radix-ui";
2223
2335
  import * as React7 from "react";
2224
2336
  import { jsx as jsx15 } from "react/jsx-runtime";
2225
2337
  var skeletonBase = cn(
@@ -2232,7 +2344,7 @@ var shimmerEffect = cn(
2232
2344
  "before:content-[''] before:absolute before:inset-0",
2233
2345
  "before:bg-[linear-gradient(110deg,transparent_0%,color-mix(in_oklab,var(--skeleton-shimmer),transparent_100%)_25%,color-mix(in_oklab,var(--skeleton-shimmer),transparent_55%)_50%,color-mix(in_oklab,var(--skeleton-shimmer),transparent_100%)_75%,transparent_100%)]",
2234
2346
  "before:[background-size:200%_100%]",
2235
- "before:animate-[skeleton-shimmer_1.6s_linear_infinite] motion-reduce:before:animate-none"
2347
+ "before:animate-[skeleton-shimmer_1.6s_linear_infinite]"
2236
2348
  );
2237
2349
  var skeletonVariants = cva4(skeletonBase, {
2238
2350
  variants: {
@@ -2255,7 +2367,7 @@ var skeletonVariants = cva4(skeletonBase, {
2255
2367
  fullWidth: { true: "w-full", false: "w-auto" },
2256
2368
  animation: {
2257
2369
  none: "",
2258
- pulse: "animate-pulse motion-reduce:animate-none",
2370
+ pulse: "animate-pulse",
2259
2371
  shimmer: shimmerEffect
2260
2372
  },
2261
2373
  preset: {
@@ -2276,10 +2388,11 @@ var skeletonVariants = cva4(skeletonBase, {
2276
2388
  }
2277
2389
  });
2278
2390
  var Skeleton = React7.forwardRef(
2279
- ({ variant, size, radius, fullWidth, animation, preset, animate, className, ...props }, ref) => {
2391
+ ({ variant, size, radius, fullWidth, animation, preset, animate, asChild, className, children, ...props }, ref) => {
2280
2392
  const resolvedAnimation = animation ?? (animate === false ? "none" : animate ? "pulse" : void 0);
2393
+ const Component = asChild ? Slot2.Root : "div";
2281
2394
  return /* @__PURE__ */ jsx15(
2282
- "div",
2395
+ Component,
2283
2396
  {
2284
2397
  ref,
2285
2398
  className: cn(
@@ -2293,7 +2406,9 @@ var Skeleton = React7.forwardRef(
2293
2406
  }),
2294
2407
  className
2295
2408
  ),
2296
- ...props
2409
+ "aria-hidden": props["aria-hidden"] ?? true,
2410
+ ...props,
2411
+ children: asChild ? /* @__PURE__ */ jsx15(Slot2.Slottable, { children }) : children
2297
2412
  }
2298
2413
  );
2299
2414
  }
@@ -2439,8 +2554,7 @@ var tooltipContentBase = cn(
2439
2554
  "data-[side=right]:[--tooltip-x:-4px] data-[side=right]:[--tooltip-y:0px]",
2440
2555
  "data-[state=delayed-open]:animate-[tooltip-in_140ms_ease-out]",
2441
2556
  "data-[state=instant-open]:animate-[tooltip-in_140ms_ease-out]",
2442
- "data-[state=closed]:animate-[tooltip-out_120ms_ease-in]",
2443
- "motion-reduce:animate-none"
2557
+ "data-[state=closed]:animate-[tooltip-out_120ms_ease-in]"
2444
2558
  );
2445
2559
  function Tooltip({
2446
2560
  children,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexdspace/react",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,6 +29,7 @@
29
29
  "dependencies": {
30
30
  "class-variance-authority": "^0.7.1",
31
31
  "clsx": "^2.1.1",
32
+ "motion": "^12.23.26",
32
33
  "tailwind-merge": "^3.4.0",
33
34
  "uuid": "^13.0.0",
34
35
  "@hexdspace/util": "0.0.25"
@@ -37,7 +38,7 @@
37
38
  "@tanstack/react-query": "^5.90.11",
38
39
  "lucide-react": "^0.555.0",
39
40
  "radix-ui": "^1.4.3",
40
- "react": "^19.2.3",
41
+ "react": "^20.2.3",
41
42
  "react-dom": "^19.2.3",
42
43
  "react-router-dom": "^7.10.1",
43
44
  "react-toastify": "^11.0.5"