@hexdspace/react 0.1.21 → 0.1.22

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.
@@ -121,28 +121,6 @@
121
121
  }
122
122
  }
123
123
 
124
- @keyframes tooltip-in {
125
- 0% {
126
- opacity: 0;
127
- transform: translate(var(--tooltip-x, 0px), var(--tooltip-y, 4px)) scale(0.98);
128
- }
129
- 100% {
130
- opacity: 1;
131
- transform: translate(0, 0) scale(1);
132
- }
133
- }
134
-
135
- @keyframes tooltip-out {
136
- 0% {
137
- opacity: 1;
138
- transform: translate(0, 0) scale(1);
139
- }
140
- 100% {
141
- opacity: 0;
142
- transform: translate(var(--tooltip-x, 0px), var(--tooltip-y, 4px)) scale(0.98);
143
- }
144
- }
145
-
146
124
  :root .prose code {
147
125
  background: rgba(0, 0, 0, 0.08);
148
126
  padding: 3px 3px 0;
package/dist/index.js CHANGED
@@ -1545,7 +1545,34 @@ import { cva as cva2 } from "class-variance-authority";
1545
1545
  import { AnimatePresence, motion } from "motion/react";
1546
1546
  import { XIcon } from "lucide-react";
1547
1547
  import { Dialog as DialogPrimitive } from "radix-ui";
1548
+ import * as React3 from "react";
1549
+
1550
+ // src/ui/utils/motion.ts
1548
1551
  import * as React2 from "react";
1552
+ function parseCssTimeSeconds(value) {
1553
+ if (!value) return null;
1554
+ if (value.endsWith("ms")) {
1555
+ const numeric = Number.parseFloat(value);
1556
+ return Number.isFinite(numeric) ? numeric / 1e3 : null;
1557
+ }
1558
+ if (value.endsWith("s")) {
1559
+ const numeric = Number.parseFloat(value);
1560
+ return Number.isFinite(numeric) ? numeric : null;
1561
+ }
1562
+ return null;
1563
+ }
1564
+ function useMotionDuration(varName, fallbackSeconds) {
1565
+ const [duration, setDuration] = React2.useState(fallbackSeconds);
1566
+ React2.useLayoutEffect(() => {
1567
+ if (typeof window === "undefined") return;
1568
+ const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
1569
+ const parsed = parseCssTimeSeconds(value);
1570
+ if (parsed !== null) setDuration(parsed);
1571
+ }, [varName]);
1572
+ return duration;
1573
+ }
1574
+
1575
+ // src/ui/components/dialog/Dialog.tsx
1549
1576
  import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
1550
1577
  var dialogPanelVariants = cva2(
1551
1578
  cn(
@@ -1594,16 +1621,16 @@ function AutoHeight({
1594
1621
  resetKey,
1595
1622
  durationSeconds
1596
1623
  }) {
1597
- const ref = React2.useRef(null);
1598
- const [height, setHeight] = React2.useState("auto");
1599
- const readyRef = React2.useRef(false);
1600
- const resetKeyRef = React2.useRef(resetKey);
1601
- React2.useEffect(() => {
1624
+ const ref = React3.useRef(null);
1625
+ const [height, setHeight] = React3.useState("auto");
1626
+ const readyRef = React3.useRef(false);
1627
+ const resetKeyRef = React3.useRef(resetKey);
1628
+ React3.useEffect(() => {
1602
1629
  if (resetKeyRef.current === resetKey) return;
1603
1630
  resetKeyRef.current = resetKey;
1604
1631
  readyRef.current = false;
1605
1632
  });
1606
- React2.useLayoutEffect(() => {
1633
+ React3.useLayoutEffect(() => {
1607
1634
  const el = ref.current;
1608
1635
  if (!el) return;
1609
1636
  const dpr = Math.max(1, Math.round(window.devicePixelRatio || 1));
@@ -1646,28 +1673,6 @@ function AutoHeight({
1646
1673
  }
1647
1674
  );
1648
1675
  }
1649
- function parseCssTimeSeconds(value) {
1650
- if (!value) return null;
1651
- if (value.endsWith("ms")) {
1652
- const numeric = Number.parseFloat(value);
1653
- return Number.isFinite(numeric) ? numeric / 1e3 : null;
1654
- }
1655
- if (value.endsWith("s")) {
1656
- const numeric = Number.parseFloat(value);
1657
- return Number.isFinite(numeric) ? numeric : null;
1658
- }
1659
- return null;
1660
- }
1661
- function useMotionDuration(varName, fallbackSeconds) {
1662
- const [duration, setDuration] = React2.useState(fallbackSeconds);
1663
- React2.useLayoutEffect(() => {
1664
- if (typeof window === "undefined") return;
1665
- const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
1666
- const parsed = parseCssTimeSeconds(value);
1667
- if (parsed !== null) setDuration(parsed);
1668
- }, [varName]);
1669
- return duration;
1670
- }
1671
1676
  function Dialog({
1672
1677
  id,
1673
1678
  template,
@@ -1689,13 +1694,13 @@ function Dialog({
1689
1694
  style,
1690
1695
  ...props
1691
1696
  }) {
1692
- const fallbackId = React2.useId();
1693
- const resolvedRef = React2.useRef(false);
1697
+ const fallbackId = React3.useId();
1698
+ const resolvedRef = React3.useRef(false);
1694
1699
  const isControlled = open2 !== void 0;
1695
- const [uncontrolledOpen, setUncontrolledOpen] = React2.useState(defaultOpen ?? false);
1700
+ const [uncontrolledOpen, setUncontrolledOpen] = React3.useState(defaultOpen ?? false);
1696
1701
  const isOpen = isControlled ? open2 : uncontrolledOpen;
1697
- const [surfaceReady, setSurfaceReady] = React2.useState(false);
1698
- const [overlayReady, setOverlayReady] = React2.useState(false);
1702
+ const [surfaceReady, setSurfaceReady] = React3.useState(false);
1703
+ const [overlayReady, setOverlayReady] = React3.useState(false);
1699
1704
  const Template = template;
1700
1705
  const motionDuration = useMotionDuration("--motion-med", 0.16);
1701
1706
  const handleOpenChange = (nextOpen) => {
@@ -1711,14 +1716,14 @@ function Dialog({
1711
1716
  }
1712
1717
  onDismiss?.();
1713
1718
  };
1714
- const handleResolve = React2.useCallback(
1719
+ const handleResolve = React3.useCallback(
1715
1720
  (result) => {
1716
1721
  resolvedRef.current = true;
1717
1722
  onResolve?.(result);
1718
1723
  },
1719
1724
  [onResolve]
1720
1725
  );
1721
- const handleAutoHeightReady = React2.useCallback(() => {
1726
+ const handleAutoHeightReady = React3.useCallback(() => {
1722
1727
  if (!isOpen) return;
1723
1728
  requestAnimationFrame(() => {
1724
1729
  setSurfaceReady(true);
@@ -1727,6 +1732,7 @@ function Dialog({
1727
1732
  }, [isOpen]);
1728
1733
  const overlayClassName = cn(dialogOverlayClass);
1729
1734
  const surfaceClassName = cn(dialogSurfaceVariants({ chrome }));
1735
+ const panelRef = React3.useRef(null);
1730
1736
  return /* @__PURE__ */ jsxs3(DialogPrimitive.Root, { open: open2, defaultOpen, onOpenChange: handleOpenChange, modal, children: [
1731
1737
  trigger ? /* @__PURE__ */ jsx7(DialogPrimitive.Trigger, { asChild: true, children: trigger }) : null,
1732
1738
  /* @__PURE__ */ jsx7(DialogPrimitive.Portal, { forceMount: true, children: /* @__PURE__ */ jsx7(AnimatePresence, { children: isOpen ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
@@ -1749,6 +1755,10 @@ function Dialog({
1749
1755
  {
1750
1756
  forceMount: true,
1751
1757
  asChild: true,
1758
+ onOpenAutoFocus: (event) => {
1759
+ event.preventDefault();
1760
+ panelRef.current?.focus();
1761
+ },
1752
1762
  onInteractOutside: (event) => {
1753
1763
  if (!dismissible) event.preventDefault();
1754
1764
  },
@@ -1760,6 +1770,8 @@ function Dialog({
1760
1770
  motion.div,
1761
1771
  {
1762
1772
  className: cn(dialogPanelVariants(), className),
1773
+ ref: panelRef,
1774
+ tabIndex: -1,
1763
1775
  style: {
1764
1776
  ...style,
1765
1777
  zIndex,
@@ -1881,7 +1893,7 @@ function registerDefaultDialogs() {
1881
1893
  var DefaultDialogTemplateKeys = ["custom", "confirm", "info"];
1882
1894
 
1883
1895
  // src/feature/dialog/infra/web/react/DialogHost.tsx
1884
- import * as React3 from "react";
1896
+ import * as React4 from "react";
1885
1897
 
1886
1898
  // src/feature/dialog/application/use-case/close-top-dialog-use-case.ts
1887
1899
  var CloseTopUseCase = class {
@@ -2032,18 +2044,18 @@ var dialogController = new DialogController(registry, open, resolve, dismiss, cl
2032
2044
  // src/feature/dialog/infra/web/react/DialogHost.tsx
2033
2045
  import { Fragment as Fragment3, jsx as jsx11 } from "react/jsx-runtime";
2034
2046
  var DialogHost = () => {
2035
- const [state, setState] = React3.useState(dialogController.handleGetRegistry().getState());
2036
- const [closingIds, setClosingIds] = React3.useState(() => /* @__PURE__ */ new Set());
2037
- const closeTimers = React3.useRef(/* @__PURE__ */ new Map());
2038
- const [closeDelayMs, setCloseDelayMs] = React3.useState(160);
2039
- React3.useEffect(() => dialogController.handleGetRegistry().subscribe(setState), []);
2040
- React3.useEffect(() => {
2047
+ const [state, setState] = React4.useState(dialogController.handleGetRegistry().getState());
2048
+ const [closingIds, setClosingIds] = React4.useState(() => /* @__PURE__ */ new Set());
2049
+ const closeTimers = React4.useRef(/* @__PURE__ */ new Map());
2050
+ const [closeDelayMs, setCloseDelayMs] = React4.useState(160);
2051
+ React4.useEffect(() => dialogController.handleGetRegistry().subscribe(setState), []);
2052
+ React4.useEffect(() => {
2041
2053
  if (typeof window === "undefined") return;
2042
2054
  const raw = getComputedStyle(document.documentElement).getPropertyValue("--motion-fast").trim();
2043
2055
  const parsed = parseDurationMs(raw);
2044
2056
  if (parsed) setCloseDelayMs(parsed);
2045
2057
  }, []);
2046
- React3.useEffect(() => {
2058
+ React4.useEffect(() => {
2047
2059
  return () => {
2048
2060
  for (const timer of closeTimers.current.values()) {
2049
2061
  window.clearTimeout(timer);
@@ -2051,7 +2063,7 @@ var DialogHost = () => {
2051
2063
  closeTimers.current.clear();
2052
2064
  };
2053
2065
  }, []);
2054
- const scheduleClose = React3.useCallback(
2066
+ const scheduleClose = React4.useCallback(
2055
2067
  (id, action, result) => {
2056
2068
  if (closingIds.has(id)) return;
2057
2069
  setClosingIds((prev) => new Set(prev).add(id));
@@ -2122,12 +2134,12 @@ function useDialog() {
2122
2134
  }
2123
2135
 
2124
2136
  // src/ui/components/Field.tsx
2125
- import * as React5 from "react";
2137
+ import * as React6 from "react";
2126
2138
 
2127
2139
  // src/ui/components/Label.tsx
2128
- import * as React4 from "react";
2140
+ import * as React5 from "react";
2129
2141
  import { jsx as jsx12 } from "react/jsx-runtime";
2130
- var Label = React4.forwardRef(
2142
+ var Label = React5.forwardRef(
2131
2143
  ({ className, htmlFor, children, ...props }, ref) => /* @__PURE__ */ jsx12(
2132
2144
  "label",
2133
2145
  {
@@ -2144,7 +2156,7 @@ Label.displayName = "Label";
2144
2156
  // src/ui/components/Field.tsx
2145
2157
  import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
2146
2158
  function Field({ label, hint, error, required, disabled, id, children, className, ...props }) {
2147
- const reactId = React5.useId();
2159
+ const reactId = React6.useId();
2148
2160
  const controlId = id ?? `field-${reactId}`;
2149
2161
  const hintId = hint ? `${controlId}-hint` : void 0;
2150
2162
  const errorId = error ? `${controlId}-error` : void 0;
@@ -2154,7 +2166,7 @@ function Field({ label, hint, error, required, disabled, id, children, className
2154
2166
  const ariaDescribedBy = describedByParts.length ? describedByParts.join(" ") : void 0;
2155
2167
  const resolvedDisabled = disabled ?? children.props.disabled;
2156
2168
  const resolvedRequired = required ?? children.props.required;
2157
- const control = React5.cloneElement(children, {
2169
+ const control = React6.cloneElement(children, {
2158
2170
  id: controlId,
2159
2171
  disabled: resolvedDisabled,
2160
2172
  required: resolvedRequired,
@@ -2177,7 +2189,7 @@ function Field({ label, hint, error, required, disabled, id, children, className
2177
2189
 
2178
2190
  // src/ui/components/Input.tsx
2179
2191
  import { cva as cva3 } from "class-variance-authority";
2180
- import * as React6 from "react";
2192
+ import * as React7 from "react";
2181
2193
  import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
2182
2194
  var controlShellBase = cn(
2183
2195
  "relative inline-flex items-center gap-2",
@@ -2233,7 +2245,7 @@ var slotBase = cn(
2233
2245
  "data-[disabled]:text-[color:var(--disabled-fg)]"
2234
2246
  );
2235
2247
  var slotReserve = "min-w-[var(--input-slot-size)]";
2236
- var Input = React6.forwardRef(
2248
+ var Input = React7.forwardRef(
2237
2249
  ({
2238
2250
  variant,
2239
2251
  size,
@@ -2294,7 +2306,7 @@ Input.displayName = "Input";
2294
2306
  // src/ui/components/Skeleton.tsx
2295
2307
  import { cva as cva4 } from "class-variance-authority";
2296
2308
  import { Slot as Slot2 } from "radix-ui";
2297
- import * as React7 from "react";
2309
+ import * as React8 from "react";
2298
2310
  import { jsx as jsx15 } from "react/jsx-runtime";
2299
2311
  var skeletonBase = cn(
2300
2312
  "relative isolate inline-flex overflow-hidden",
@@ -2349,7 +2361,7 @@ var skeletonVariants = cva4(skeletonBase, {
2349
2361
  preset: "none"
2350
2362
  }
2351
2363
  });
2352
- var Skeleton = React7.forwardRef(
2364
+ var Skeleton = React8.forwardRef(
2353
2365
  ({ variant, size, radius, fullWidth, animation, preset, animate, asChild, className, children, ...props }, ref) => {
2354
2366
  const resolvedAnimation = animation ?? (animate === false ? "none" : animate ? "pulse" : void 0);
2355
2367
  const Component = asChild ? Slot2.Root : "div";
@@ -2379,7 +2391,7 @@ Skeleton.displayName = "Skeleton";
2379
2391
 
2380
2392
  // src/ui/components/Textarea.tsx
2381
2393
  import { cva as cva5 } from "class-variance-authority";
2382
- import * as React8 from "react";
2394
+ import * as React9 from "react";
2383
2395
  import { jsx as jsx16 } from "react/jsx-runtime";
2384
2396
  var controlShellBase2 = cn(
2385
2397
  "relative inline-flex w-full",
@@ -2442,7 +2454,7 @@ function mergeRefs(...refs) {
2442
2454
  }
2443
2455
  };
2444
2456
  }
2445
- var Textarea = React8.forwardRef(
2457
+ var Textarea = React9.forwardRef(
2446
2458
  ({
2447
2459
  variant,
2448
2460
  size,
@@ -2459,8 +2471,8 @@ var Textarea = React8.forwardRef(
2459
2471
  ...props
2460
2472
  }, ref) => {
2461
2473
  const isDisabled = Boolean(disabled);
2462
- const innerRef = React8.useRef(null);
2463
- const resize = React8.useCallback(() => {
2474
+ const innerRef = React9.useRef(null);
2475
+ const resize = React9.useCallback(() => {
2464
2476
  if (!autoResize) return;
2465
2477
  const el = innerRef.current;
2466
2478
  if (!el) return;
@@ -2472,7 +2484,7 @@ var Textarea = React8.forwardRef(
2472
2484
  resize();
2473
2485
  onInput?.(e);
2474
2486
  };
2475
- React8.useLayoutEffect(() => {
2487
+ React9.useLayoutEffect(() => {
2476
2488
  resize();
2477
2489
  }, [resize, value]);
2478
2490
  return /* @__PURE__ */ jsx16(
@@ -2505,7 +2517,9 @@ var Textarea = React8.forwardRef(
2505
2517
  Textarea.displayName = "Textarea";
2506
2518
 
2507
2519
  // src/ui/components/Tooltip.tsx
2520
+ import { AnimatePresence as AnimatePresence2, motion as motion2 } from "motion/react";
2508
2521
  import { Tooltip as TooltipPrimitive } from "radix-ui";
2522
+ import * as React10 from "react";
2509
2523
  import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
2510
2524
  var tooltipContentBase = cn(
2511
2525
  "panel shadow-none px-4 py-2.5 text-xs z-5000 select-none",
@@ -2513,10 +2527,7 @@ var tooltipContentBase = cn(
2513
2527
  "[--tooltip-x:0px] [--tooltip-y:4px]",
2514
2528
  "data-[side=bottom]:[--tooltip-y:-4px]",
2515
2529
  "data-[side=left]:[--tooltip-x:4px] data-[side=left]:[--tooltip-y:0px]",
2516
- "data-[side=right]:[--tooltip-x:-4px] data-[side=right]:[--tooltip-y:0px]",
2517
- "data-[state=delayed-open]:animate-[tooltip-in_140ms_ease-out]",
2518
- "data-[state=instant-open]:animate-[tooltip-in_140ms_ease-out]",
2519
- "data-[state=closed]:animate-[tooltip-out_120ms_ease-in]"
2530
+ "data-[side=right]:[--tooltip-x:-4px] data-[side=right]:[--tooltip-y:0px]"
2520
2531
  );
2521
2532
  function Tooltip({
2522
2533
  children,
@@ -2527,27 +2538,51 @@ function Tooltip({
2527
2538
  maxWidthPx = 240,
2528
2539
  preserveWhitespace = false
2529
2540
  }) {
2530
- return /* @__PURE__ */ jsx17(TooltipPrimitive.Provider, { delayDuration: delayMs, children: /* @__PURE__ */ jsxs9(TooltipPrimitive.Root, { children: [
2541
+ const [open2, setOpen] = React10.useState(false);
2542
+ const motionDuration = useMotionDuration("--motion-fast", 0.14);
2543
+ return /* @__PURE__ */ jsx17(TooltipPrimitive.Provider, { delayDuration: delayMs, children: /* @__PURE__ */ jsxs9(TooltipPrimitive.Root, { onOpenChange: setOpen, children: [
2531
2544
  /* @__PURE__ */ jsx17(TooltipPrimitive.Trigger, { asChild: true, children }),
2532
- /* @__PURE__ */ jsx17(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs9(
2545
+ /* @__PURE__ */ jsx17(TooltipPrimitive.Portal, { forceMount: true, children: /* @__PURE__ */ jsx17(AnimatePresence2, { children: open2 ? /* @__PURE__ */ jsx17(
2533
2546
  TooltipPrimitive.Content,
2534
2547
  {
2548
+ asChild: true,
2549
+ forceMount: true,
2535
2550
  side,
2536
2551
  sideOffset,
2537
- className: tooltipContentBase,
2538
- style: {
2539
- width: "max-content",
2540
- maxWidth: `min(${maxWidthPx}px, 90vw)`,
2541
- whiteSpace: preserveWhitespace ? "pre-line" : "normal",
2542
- overflowWrap: "break-word",
2543
- hyphens: "auto"
2544
- },
2545
- children: [
2546
- content,
2547
- /* @__PURE__ */ jsx17(TooltipPrimitive.Arrow, { style: { fill: "var(--surface-2)" } })
2548
- ]
2552
+ children: /* @__PURE__ */ jsxs9(
2553
+ motion2.div,
2554
+ {
2555
+ className: tooltipContentBase,
2556
+ initial: {
2557
+ opacity: 0,
2558
+ scale: 0.98,
2559
+ x: "var(--tooltip-x)",
2560
+ y: "var(--tooltip-y)"
2561
+ },
2562
+ animate: { opacity: 1, scale: 1, x: 0, y: 0 },
2563
+ exit: {
2564
+ opacity: 0,
2565
+ scale: 0.98,
2566
+ x: "var(--tooltip-x)",
2567
+ y: "var(--tooltip-y)",
2568
+ transition: { duration: motionDuration, ease: "easeIn" }
2569
+ },
2570
+ transition: { duration: motionDuration, ease: "easeOut" },
2571
+ style: {
2572
+ width: "max-content",
2573
+ maxWidth: `min(${maxWidthPx}px, 90vw)`,
2574
+ whiteSpace: preserveWhitespace ? "pre-line" : "normal",
2575
+ overflowWrap: "break-word",
2576
+ hyphens: "auto"
2577
+ },
2578
+ children: [
2579
+ content,
2580
+ /* @__PURE__ */ jsx17(TooltipPrimitive.Arrow, { style: { fill: "var(--surface-2)" } })
2581
+ ]
2582
+ }
2583
+ )
2549
2584
  }
2550
- ) })
2585
+ ) : null }) })
2551
2586
  ] }) });
2552
2587
  }
2553
2588
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexdspace/react",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",