@hexdspace/react 0.1.15 → 0.1.17

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.
@@ -181,18 +181,22 @@
181
181
 
182
182
  @keyframes dialog-surface-in {
183
183
  from {
184
+ opacity: 0;
184
185
  transform: translateY(1.25rem);
185
186
  }
186
187
  to {
188
+ opacity: 1;
187
189
  transform: translateY(0);
188
190
  }
189
191
  }
190
192
 
191
193
  @keyframes dialog-surface-out {
192
194
  from {
195
+ opacity: 1;
193
196
  transform: translateY(0);
194
197
  }
195
198
  to {
199
+ opacity: 0;
196
200
  transform: translateY(1.25rem);
197
201
  }
198
202
  }
package/dist/index.js CHANGED
@@ -1552,30 +1552,34 @@ var dialogPanelVariants = cva2(
1552
1552
  "-translate-x-1/2 -translate-y-1/2",
1553
1553
  "w-[min(92vw,var(--dialog-width))]",
1554
1554
  "pointer-events-auto",
1555
- "data-[state=open]:animate-[dialog-fade-in_var(--motion-med)_cubic-bezier(0.2,0,0.2,1)]",
1556
- "data-[state=closed]:animate-[dialog-fade-out_var(--motion-med)_cubic-bezier(0.2,0,0.2,1)]",
1557
- "motion-reduce:animate-none",
1555
+ "data-[state=open]:transition-opacity duration-[var(--motion-med)]",
1556
+ "data-[state=closed]:animate-[dialog-fade-out_var(--motion-med)]",
1558
1557
  "data-[state=closed]:pointer-events-none"
1559
1558
  )
1560
1559
  );
1561
1560
  var dialogOverlayClass = cn(
1562
1561
  "fixed inset-0 bg-[color:var(--overlay)]",
1563
- "data-[state=open]:animate-[dialog-overlay-in_var(--motion-med)_cubic-bezier(0.2,0,0.2,1)]",
1564
1562
  "data-[state=closed]:animate-[dialog-overlay-out_var(--motion-med)_cubic-bezier(0.2,0,0.2,1)]",
1565
- "motion-reduce:animate-none",
1566
1563
  "data-[state=closed]:pointer-events-none"
1567
1564
  );
1568
1565
  function DialogContent({ className, ...props }) {
1569
1566
  return /* @__PURE__ */ jsx7("div", { className: cn("DialogContent p-6", className), ...props });
1570
1567
  }
1571
- function AutoHeight({ children, freeze = false }) {
1568
+ function AutoHeight({
1569
+ children,
1570
+ onReady,
1571
+ resetKey
1572
+ }) {
1572
1573
  const ref = React2.useRef(null);
1573
1574
  const [height, setHeight] = React2.useState("auto");
1575
+ const readyRef = React2.useRef(false);
1576
+ const resetKeyRef = React2.useRef(resetKey);
1574
1577
  React2.useEffect(() => {
1575
- if (freeze) {
1576
- setHeight("auto");
1577
- return;
1578
- }
1578
+ if (resetKeyRef.current === resetKey) return;
1579
+ resetKeyRef.current = resetKey;
1580
+ readyRef.current = false;
1581
+ });
1582
+ React2.useLayoutEffect(() => {
1579
1583
  const el = ref.current;
1580
1584
  if (!el) return;
1581
1585
  const dpr = Math.max(1, Math.round(window.devicePixelRatio || 1));
@@ -1590,6 +1594,12 @@ function AutoHeight({ children, freeze = false }) {
1590
1594
  if (prevNum < 0 || Math.abs(snapped - prevNum) >= 2) return snapped;
1591
1595
  return prev;
1592
1596
  });
1597
+ if (!readyRef.current) {
1598
+ readyRef.current = true;
1599
+ requestAnimationFrame(() => {
1600
+ onReady?.();
1601
+ });
1602
+ }
1593
1603
  });
1594
1604
  });
1595
1605
  ro.observe(el);
@@ -1597,15 +1607,17 @@ function AutoHeight({ children, freeze = false }) {
1597
1607
  ro.disconnect();
1598
1608
  cancelAnimationFrame(raf);
1599
1609
  };
1600
- }, [freeze]);
1610
+ }, [onReady]);
1601
1611
  return /* @__PURE__ */ jsx7(
1602
1612
  "div",
1603
1613
  {
1604
- className: cn(
1605
- "transition-[height] duration-(--motion-med) ease motion-reduce:transition-none",
1606
- freeze && "transition-none"
1607
- ),
1608
- style: { height: height === "auto" ? "auto" : height, overflow: "hidden", willChange: "height" },
1614
+ className: cn("transition-[height] duration-(--motion-med) ease motion-reduce:transition-none"),
1615
+ style: {
1616
+ height: height === "auto" ? "auto" : height,
1617
+ maxHeight: "calc(100vh - 4rem)",
1618
+ overflow: "auto",
1619
+ willChange: "height"
1620
+ },
1609
1621
  children: /* @__PURE__ */ jsx7("div", { ref, style: { boxSizing: "border-box" }, children })
1610
1622
  }
1611
1623
  );
@@ -1632,19 +1644,16 @@ function Dialog({
1632
1644
  }) {
1633
1645
  const fallbackId = React2.useId();
1634
1646
  const resolvedRef = React2.useRef(false);
1635
- const [isAnimating, setIsAnimating] = React2.useState(false);
1636
- const animationTimer = React2.useRef(null);
1637
- const motionMs = useMotionDurationMs("--motion-med", 160);
1647
+ const isControlled = open2 !== void 0;
1648
+ const [uncontrolledOpen, setUncontrolledOpen] = React2.useState(defaultOpen ?? false);
1649
+ const isOpen = isControlled ? open2 : uncontrolledOpen;
1650
+ const prevOpenRef = React2.useRef(false);
1651
+ const [contentCycle, setContentCycle] = React2.useState(0);
1652
+ const [surfaceReady, setSurfaceReady] = React2.useState(false);
1653
+ const [overlayReady, setOverlayReady] = React2.useState(false);
1638
1654
  const Template = template;
1639
1655
  const handleOpenChange = (nextOpen) => {
1640
- if (typeof window !== "undefined") {
1641
- if (animationTimer.current) window.clearTimeout(animationTimer.current);
1642
- setIsAnimating(true);
1643
- animationTimer.current = window.setTimeout(() => {
1644
- setIsAnimating(false);
1645
- animationTimer.current = null;
1646
- }, motionMs);
1647
- }
1656
+ if (!isControlled) setUncontrolledOpen(nextOpen);
1648
1657
  onOpenChange?.(nextOpen);
1649
1658
  if (nextOpen) {
1650
1659
  resolvedRef.current = false;
@@ -1663,28 +1672,51 @@ function Dialog({
1663
1672
  },
1664
1673
  [onResolve]
1665
1674
  );
1675
+ React2.useEffect(() => {
1676
+ const wasOpen = prevOpenRef.current;
1677
+ prevOpenRef.current = Boolean(isOpen);
1678
+ if (isOpen && !wasOpen) {
1679
+ setContentCycle((value) => value + 1);
1680
+ setSurfaceReady(false);
1681
+ setOverlayReady(false);
1682
+ return;
1683
+ }
1684
+ if (!isOpen && wasOpen) {
1685
+ setSurfaceReady(false);
1686
+ setOverlayReady(false);
1687
+ }
1688
+ }, [isOpen]);
1689
+ const handleAutoHeightReady = React2.useCallback(() => {
1690
+ if (!isOpen) return;
1691
+ requestAnimationFrame(() => {
1692
+ setSurfaceReady(true);
1693
+ setOverlayReady(true);
1694
+ });
1695
+ }, [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
+ );
1666
1707
  return /* @__PURE__ */ jsxs3(DialogPrimitive.Root, { open: open2, defaultOpen, onOpenChange: handleOpenChange, modal, children: [
1667
1708
  trigger ? /* @__PURE__ */ jsx7(DialogPrimitive.Trigger, { asChild: true, children: trigger }) : null,
1668
1709
  /* @__PURE__ */ jsxs3(DialogPrimitive.Portal, { children: [
1669
- modal ? /* @__PURE__ */ jsx7(
1670
- DialogPrimitive.Overlay,
1671
- {
1672
- className: cn("DialogOverlay", dialogOverlayClass),
1673
- style: { zIndex: zIndex - 1 }
1674
- }
1675
- ) : null,
1710
+ modal ? /* @__PURE__ */ jsx7(DialogPrimitive.Overlay, { className: overlayClassName, style: { zIndex: zIndex - 1 } }) : null,
1676
1711
  /* @__PURE__ */ jsx7(
1677
1712
  DialogPrimitive.Content,
1678
1713
  {
1679
1714
  className: cn(
1680
1715
  "DialogContent",
1681
1716
  dialogPanelVariants(),
1682
- "data-[state=open]:[&_.dialog-surface]:animate-[dialog-surface-in_var(--motion-med)_cubic-bezier(0.16,1,0.3,1)]",
1683
1717
  "data-[state=closed]:[&_.dialog-surface]:animate-[dialog-surface-out_var(--motion-med)_cubic-bezier(0.4,0,1,1)]",
1684
- "motion-reduce:[&_.dialog-surface]:animate-none",
1685
1718
  className
1686
1719
  ),
1687
- "aria-describedby": void 0,
1688
1720
  style: {
1689
1721
  ...style,
1690
1722
  zIndex,
@@ -1697,7 +1729,7 @@ function Dialog({
1697
1729
  if (!dismissible) event.preventDefault();
1698
1730
  },
1699
1731
  ...props,
1700
- children: /* @__PURE__ */ jsxs3("div", { className: "dialog-surface relative shell overflow-hidden", children: [
1732
+ children: /* @__PURE__ */ jsxs3("div", { className: surfaceClassName, children: [
1701
1733
  showClose ? /* @__PURE__ */ jsx7(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx7(
1702
1734
  Button,
1703
1735
  {
@@ -1708,32 +1740,13 @@ function Dialog({
1708
1740
  "aria-label": closeLabel
1709
1741
  }
1710
1742
  ) }) : null,
1711
- /* @__PURE__ */ jsx7(AutoHeight, { freeze: isAnimating, children: /* @__PURE__ */ jsx7(Template, { id: id ?? fallbackId, payload, onResolve: handleResolve }) })
1743
+ /* @__PURE__ */ jsx7(AutoHeight, { onReady: handleAutoHeightReady, resetKey: contentCycle, children: /* @__PURE__ */ jsx7(Template, { id: id ?? fallbackId, payload, onResolve: handleResolve }) })
1712
1744
  ] })
1713
1745
  }
1714
1746
  )
1715
1747
  ] })
1716
1748
  ] });
1717
1749
  }
1718
- function useMotionDurationMs(token, fallback) {
1719
- const [ms, setMs] = React2.useState(fallback);
1720
- React2.useEffect(() => {
1721
- if (typeof window === "undefined") return;
1722
- const raw = getComputedStyle(document.documentElement).getPropertyValue(token).trim();
1723
- const parsed = parseDurationMs(raw);
1724
- if (parsed !== null) setMs(parsed);
1725
- }, [token]);
1726
- return ms;
1727
- }
1728
- function parseDurationMs(value) {
1729
- if (!value) return null;
1730
- const trimmed = value.trim();
1731
- const numeric = Number(trimmed.replace(/ms|s/g, ""));
1732
- if (Number.isNaN(numeric)) return null;
1733
- if (trimmed.endsWith("ms")) return numeric;
1734
- if (trimmed.endsWith("s")) return numeric * 1e3;
1735
- return numeric;
1736
- }
1737
1750
 
1738
1751
  // src/ui/components/dialog/dialog-variant/ConfirmDialog.tsx
1739
1752
  import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -1954,7 +1967,7 @@ var DialogHost = () => {
1954
1967
  React3.useEffect(() => {
1955
1968
  if (typeof window === "undefined") return;
1956
1969
  const raw = getComputedStyle(document.documentElement).getPropertyValue("--motion-fast").trim();
1957
- const parsed = parseDurationMs2(raw);
1970
+ const parsed = parseDurationMs(raw);
1958
1971
  if (parsed) setCloseDelayMs(parsed);
1959
1972
  }, []);
1960
1973
  React3.useEffect(() => {
@@ -2010,7 +2023,7 @@ var DialogHost = () => {
2010
2023
  );
2011
2024
  }) });
2012
2025
  };
2013
- function parseDurationMs2(value) {
2026
+ function parseDurationMs(value) {
2014
2027
  if (!value) return null;
2015
2028
  const trimmed = value.trim();
2016
2029
  const asNumber = Number(trimmed.replace(/ms|s/g, ""));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexdspace/react",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",