@justanarthur/modo-ui 0.0.0-stage → 0.1.0

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.
Files changed (172) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSE.beui +21 -0
  3. package/LICENSE.fluid-functionalism +21 -0
  4. package/LICENSE.motion-primitives +21 -0
  5. package/LICENSE.sileo +21 -0
  6. package/README.md +608 -2
  7. package/dist/base.css +994 -0
  8. package/dist/blocks/sidebar-app/index.d.ts +34 -0
  9. package/dist/blocks/sidebar-app/index.js +34 -0
  10. package/dist/components/badge/index.d.ts +59 -0
  11. package/dist/components/badge/index.js +18 -0
  12. package/dist/components/button/index.d.ts +59 -0
  13. package/dist/components/button/index.js +16 -0
  14. package/dist/components/card/index.d.ts +141 -0
  15. package/dist/components/card/index.js +44 -0
  16. package/dist/components/inputs/checkbox-group/index.d.ts +50 -0
  17. package/dist/components/inputs/checkbox-group/index.js +23 -0
  18. package/dist/components/inputs/color-picker/index.d.ts +137 -0
  19. package/dist/components/inputs/color-picker/index.js +37 -0
  20. package/dist/components/inputs/combobox/index.d.ts +161 -0
  21. package/dist/components/inputs/combobox/index.js +41 -0
  22. package/dist/components/inputs/date-time/calendar/index.d.ts +45 -0
  23. package/dist/components/inputs/date-time/calendar/index.js +20 -0
  24. package/dist/components/inputs/date-time/date-picker/index.d.ts +82 -0
  25. package/dist/components/inputs/date-time/date-picker/index.js +34 -0
  26. package/dist/components/inputs/date-time/date-range-picker/index.d.ts +64 -0
  27. package/dist/components/inputs/date-time/date-range-picker/index.js +33 -0
  28. package/dist/components/inputs/date-time/duration-picker/index.d.ts +57 -0
  29. package/dist/components/inputs/date-time/duration-picker/index.js +33 -0
  30. package/dist/components/inputs/date-time/month-picker/index.d.ts +57 -0
  31. package/dist/components/inputs/date-time/month-picker/index.js +32 -0
  32. package/dist/components/inputs/date-time/time-picker/index.d.ts +59 -0
  33. package/dist/components/inputs/date-time/time-picker/index.js +33 -0
  34. package/dist/components/inputs/input/index.d.ts +84 -0
  35. package/dist/components/inputs/input/index.js +20 -0
  36. package/dist/components/inputs/input-copy/index.d.ts +44 -0
  37. package/dist/components/inputs/input-copy/index.js +18 -0
  38. package/dist/components/inputs/input-message/index.d.ts +125 -0
  39. package/dist/components/inputs/input-message/index.js +27 -0
  40. package/dist/components/inputs/radio-group/index.d.ts +58 -0
  41. package/dist/components/inputs/radio-group/index.js +22 -0
  42. package/dist/components/inputs/search/index.d.ts +83 -0
  43. package/dist/components/inputs/search/index.js +28 -0
  44. package/dist/components/inputs/select/index.d.ts +105 -0
  45. package/dist/components/inputs/select/index.js +37 -0
  46. package/dist/components/inputs/slider/index.d.ts +108 -0
  47. package/dist/components/inputs/slider/index.js +16 -0
  48. package/dist/components/inputs/switch/index.d.ts +43 -0
  49. package/dist/components/inputs/switch/index.js +16 -0
  50. package/dist/components/navigation/accordion/index.d.ts +117 -0
  51. package/dist/components/navigation/accordion/index.js +30 -0
  52. package/dist/components/navigation/sidebar/index.d.ts +388 -0
  53. package/dist/components/navigation/sidebar/index.js +101 -0
  54. package/dist/components/navigation/tabs/index.d.ts +70 -0
  55. package/dist/components/navigation/tabs/index.js +25 -0
  56. package/dist/components/navigation/tabs-subtle/index.d.ts +73 -0
  57. package/dist/components/navigation/tabs-subtle/index.js +23 -0
  58. package/dist/components/overlays/alert-dialog/index.d.ts +67 -0
  59. package/dist/components/overlays/alert-dialog/index.js +24 -0
  60. package/dist/components/overlays/command/index.d.ts +121 -0
  61. package/dist/components/overlays/command/index.js +39 -0
  62. package/dist/components/overlays/context-menu/index.d.ts +97 -0
  63. package/dist/components/overlays/context-menu/index.js +32 -0
  64. package/dist/components/overlays/dialog/index.d.ts +130 -0
  65. package/dist/components/overlays/dialog/index.js +39 -0
  66. package/dist/components/overlays/dropdown/index.d.ts +222 -0
  67. package/dist/components/overlays/dropdown/index.js +47 -0
  68. package/dist/components/overlays/popover/index.d.ts +87 -0
  69. package/dist/components/overlays/popover/index.js +28 -0
  70. package/dist/components/overlays/preview-card/index.d.ts +75 -0
  71. package/dist/components/overlays/preview-card/index.js +21 -0
  72. package/dist/components/overlays/sheet/index.d.ts +67 -0
  73. package/dist/components/overlays/sheet/index.js +26 -0
  74. package/dist/components/overlays/toast/index.d.ts +107 -0
  75. package/dist/components/overlays/toast/index.js +23 -0
  76. package/dist/components/overlays/tooltip/index.d.ts +75 -0
  77. package/dist/components/overlays/tooltip/index.js +19 -0
  78. package/dist/components/table/index.d.ts +44 -0
  79. package/dist/components/table/index.js +28 -0
  80. package/dist/components/thinking-indicator/index.d.ts +32 -0
  81. package/dist/components/thinking-indicator/index.js +15 -0
  82. package/dist/index.d.ts +3926 -0
  83. package/dist/index.js +513 -0
  84. package/dist/preset.d.ts +104 -0
  85. package/dist/preset.js +124 -0
  86. package/dist/primitives/code/index.d.ts +23 -0
  87. package/dist/primitives/code/index.js +12 -0
  88. package/dist/primitives/craft/index.d.ts +31 -0
  89. package/dist/primitives/craft/index.js +13 -0
  90. package/dist/primitives/fluid-hover/index.d.ts +233 -0
  91. package/dist/primitives/fluid-hover/index.js +27 -0
  92. package/dist/primitives/morph/index.d.ts +127 -0
  93. package/dist/primitives/morph/index.js +21 -0
  94. package/dist/primitives/motion/index.d.ts +115 -0
  95. package/dist/primitives/motion/index.js +20 -0
  96. package/dist/primitives/scroll-area/index.d.ts +41 -0
  97. package/dist/primitives/scroll-area/index.js +13 -0
  98. package/dist/primitives/sizes/index.d.ts +128 -0
  99. package/dist/primitives/sizes/index.js +22 -0
  100. package/dist/primitives/surface/index.d.ts +69 -0
  101. package/dist/primitives/surface/index.js +18 -0
  102. package/dist/shared/components-0f0as45n.js +17 -0
  103. package/dist/shared/components-40j34hdb.js +986 -0
  104. package/dist/shared/components-4hh0gm0v.js +292 -0
  105. package/dist/shared/components-4xxddc44.js +15 -0
  106. package/dist/shared/components-4xxtggzp.js +110 -0
  107. package/dist/shared/components-54nf2x99.js +293 -0
  108. package/dist/shared/components-5pkcfprd.js +232 -0
  109. package/dist/shared/components-5vxtcp88.js +9 -0
  110. package/dist/shared/components-5zry9te1.js +152 -0
  111. package/dist/shared/components-61ckf42z.js +220 -0
  112. package/dist/shared/components-6hzwfmfd.js +58 -0
  113. package/dist/shared/components-6phwsry6.js +361 -0
  114. package/dist/shared/components-6t6nr33r.js +86 -0
  115. package/dist/shared/components-6y1th6k4.js +111 -0
  116. package/dist/shared/components-74c20v2f.js +32 -0
  117. package/dist/shared/components-7cqq1sqy.js +193 -0
  118. package/dist/shared/components-7gv95yfy.js +496 -0
  119. package/dist/shared/components-7nww01w4.js +375 -0
  120. package/dist/shared/components-7zp99w5d.js +62 -0
  121. package/dist/shared/components-8hk9ve3r.js +1200 -0
  122. package/dist/shared/components-8hzbsfbd.js +123 -0
  123. package/dist/shared/components-9p8s8n5q.js +171 -0
  124. package/dist/shared/components-aaq3yk4f.js +304 -0
  125. package/dist/shared/components-bf2d9k02.js +484 -0
  126. package/dist/shared/components-bkvb6nem.js +63 -0
  127. package/dist/shared/components-brnzrp2t.js +262 -0
  128. package/dist/shared/components-csxz9f52.js +42 -0
  129. package/dist/shared/components-de8xsm9y.js +22 -0
  130. package/dist/shared/components-dg0w8g5p.js +26 -0
  131. package/dist/shared/components-dphg9gjr.js +42 -0
  132. package/dist/shared/components-e46kf6cp.js +298 -0
  133. package/dist/shared/components-ed7cmssr.js +105 -0
  134. package/dist/shared/components-ess3ch6w.js +137 -0
  135. package/dist/shared/components-gjfrycb5.js +984 -0
  136. package/dist/shared/components-gndm6am4.js +128 -0
  137. package/dist/shared/components-hjkrv00c.js +191 -0
  138. package/dist/shared/components-hzfp4tjb.js +270 -0
  139. package/dist/shared/components-j65qt1mq.js +719 -0
  140. package/dist/shared/components-jw16snbn.js +19 -0
  141. package/dist/shared/components-jxgznftn.js +146 -0
  142. package/dist/shared/components-kf2ehztc.js +216 -0
  143. package/dist/shared/components-kpbcms10.js +9 -0
  144. package/dist/shared/components-m5br529r.js +141 -0
  145. package/dist/shared/components-nn6xezy2.js +1828 -0
  146. package/dist/shared/components-nnnd2xef.js +9 -0
  147. package/dist/shared/components-p2vmyfe1.js +345 -0
  148. package/dist/shared/components-peg09pzs.js +79 -0
  149. package/dist/shared/components-r22vtgqc.js +45 -0
  150. package/dist/shared/components-r2gke5p6.js +1759 -0
  151. package/dist/shared/components-r43mqnd6.js +160 -0
  152. package/dist/shared/components-r4jt6hgd.js +58 -0
  153. package/dist/shared/components-rc63qsy6.js +159 -0
  154. package/dist/shared/components-s3yfvfkr.js +149 -0
  155. package/dist/shared/components-s5pkbjx1.js +445 -0
  156. package/dist/shared/components-tad5h7ta.js +346 -0
  157. package/dist/shared/components-taxmgbnh.js +120 -0
  158. package/dist/shared/components-tm88ghva.js +215 -0
  159. package/dist/shared/components-v7es8aan.js +144 -0
  160. package/dist/shared/components-vb033rns.js +28 -0
  161. package/dist/shared/components-vc1k7yv2.js +30 -0
  162. package/dist/shared/components-vktws5r6.js +667 -0
  163. package/dist/shared/components-x2xyckd5.js +198 -0
  164. package/dist/shared/components-x3rz4cyn.js +61 -0
  165. package/dist/shared/components-xszag63d.js +141 -0
  166. package/dist/shared/components-y3cqdrgy.js +291 -0
  167. package/dist/shared/components-zvb11ker.js +288 -0
  168. package/dist/shared/components-zx2hr57f.js +124 -0
  169. package/dist/styles.css +1949 -0
  170. package/dist/tailwind.css +219 -0
  171. package/dist/tokens.css +345 -0
  172. package/package.json +102 -3
@@ -0,0 +1,262 @@
1
+ import {
2
+ CommandList,
3
+ CommandListRoot,
4
+ CommandShortcut
5
+ } from "./components-4hh0gm0v.js";
6
+ import {
7
+ useIcon
8
+ } from "./components-m5br529r.js";
9
+ import {
10
+ SURFACE_BG,
11
+ SURFACE_SHADOW,
12
+ SurfaceProvider,
13
+ useSurface
14
+ } from "./components-csxz9f52.js";
15
+ import {
16
+ MorphSurface
17
+ } from "./components-jxgznftn.js";
18
+ import {
19
+ shapeMap,
20
+ useShape
21
+ } from "./components-7zp99w5d.js";
22
+ import {
23
+ useControllableState
24
+ } from "./components-dg0w8g5p.js";
25
+ import {
26
+ useMorph
27
+ } from "./components-7nww01w4.js";
28
+ import {
29
+ useReduceMotion
30
+ } from "./components-nnnd2xef.js";
31
+ import {
32
+ spring
33
+ } from "./components-vc1k7yv2.js";
34
+ import {
35
+ useSize
36
+ } from "./components-x3rz4cyn.js";
37
+ import {
38
+ cn
39
+ } from "./components-0f0as45n.js";
40
+
41
+ // components/inputs/search/index.tsx
42
+ import { Autocomplete } from "@base-ui/react/autocomplete";
43
+ import { motion } from "motion/react";
44
+ import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
45
+ import { flushSync } from "react-dom";
46
+ import { jsx, jsxs } from "react/jsx-runtime";
47
+ var INSET = { default: "pl-2.5", compact: "pl-[7px]" };
48
+ var SQUARE = { default: "w-9", compact: "w-7" };
49
+ var PILL = { default: "min-w-[160px]", compact: "min-w-[128px]" };
50
+ var isEditable = (target) => target instanceof HTMLElement && (target.isContentEditable || target.closest("input, textarea, select") !== null);
51
+ function Search({
52
+ variant = "pill",
53
+ placeholder = "Search",
54
+ items,
55
+ value,
56
+ defaultValue = "",
57
+ onValueChange,
58
+ onSubmit,
59
+ expanded,
60
+ defaultExpanded = false,
61
+ onExpandedChange,
62
+ width = 288,
63
+ align = "start",
64
+ shortcut,
65
+ emptyMessage = "No results found.",
66
+ effect,
67
+ tier = "moderate",
68
+ className
69
+ }) {
70
+ const [query, setQuery] = useControllableState(value, defaultValue, onValueChange);
71
+ const [isExpanded, setExpanded] = useControllableState(expanded, defaultExpanded, onExpandedChange);
72
+ const [suggesting, setSuggesting] = useState(false);
73
+ const [settled, setSettled] = useState(isExpanded);
74
+ const [rest, setRest] = useState(0);
75
+ const reduced = useReduceMotion();
76
+ const shape = useShape();
77
+ const size = useSize();
78
+ const level = Math.min(useSurface() + 2, 8);
79
+ const SearchIcon = useIcon("search");
80
+ const XIcon = useIcon("x");
81
+ const button = useRef(null);
82
+ const field = useRef(null);
83
+ const input = useRef(null);
84
+ const origin = useRef({});
85
+ const suggestions = useMemo(() => items?.map((item) => typeof item === "string" ? { label: item } : item), [items]);
86
+ const open = suggesting && isExpanded && settled;
87
+ const lifted = isExpanded || settled;
88
+ const morph = useMorph(open, origin, { from: field, effect, tier });
89
+ useLayoutEffect(() => {
90
+ const el = button.current;
91
+ if (!el)
92
+ return;
93
+ const observer = new ResizeObserver(() => setRest(el.offsetWidth));
94
+ observer.observe(el);
95
+ return () => observer.disconnect();
96
+ }, []);
97
+ const expand = () => {
98
+ flushSync(() => setExpanded(true));
99
+ input.current?.focus({ preventScroll: true });
100
+ };
101
+ const collapse = (refocus) => {
102
+ flushSync(() => {
103
+ setQuery("");
104
+ setSuggesting(false);
105
+ setExpanded(false);
106
+ });
107
+ if (refocus)
108
+ button.current?.focus();
109
+ };
110
+ useEffect(() => {
111
+ if (!shortcut || isExpanded)
112
+ return;
113
+ const onKey = (event) => {
114
+ if (event.defaultPrevented || event.key !== shortcut || event.metaKey || event.ctrlKey || event.altKey)
115
+ return;
116
+ if (isEditable(event.target))
117
+ return;
118
+ event.preventDefault();
119
+ expand();
120
+ };
121
+ window.addEventListener("keydown", onKey);
122
+ return () => window.removeEventListener("keydown", onKey);
123
+ }, [shortcut, isExpanded]);
124
+ const onKeyDown = (event) => {
125
+ if (event.key !== "Escape" || open)
126
+ return;
127
+ event.stopPropagation();
128
+ if (query)
129
+ setQuery("");
130
+ else
131
+ collapse(true);
132
+ };
133
+ const inputProps = {
134
+ ref: input,
135
+ placeholder,
136
+ "aria-label": placeholder,
137
+ onKeyDown,
138
+ className: cn("h-full min-w-0 flex-1 bg-transparent text-foreground outline-none placeholder:text-muted-foreground [&::-webkit-search-cancel-button]:hidden", size.text)
139
+ };
140
+ const root = /* @__PURE__ */ jsx("search", {
141
+ onBlur: (event) => {
142
+ if (!isExpanded || query || event.currentTarget.contains(event.relatedTarget))
143
+ return;
144
+ collapse(false);
145
+ },
146
+ className: cn("group/search relative inline-flex shrink-0 align-middle", className),
147
+ children: /* @__PURE__ */ jsxs("form", {
148
+ className: "contents",
149
+ onSubmit: (event) => {
150
+ event.preventDefault();
151
+ onSubmit?.(query);
152
+ },
153
+ children: [
154
+ /* @__PURE__ */ jsxs("button", {
155
+ ref: button,
156
+ type: "button",
157
+ "aria-label": placeholder,
158
+ onClick: expand,
159
+ className: cn("relative z-[1] flex items-center outline-none focus-visible:ring-1 focus-visible:ring-focus-ring", size.control, size.gap, size.text, shape.input, variant === "icon" ? cn("cursor-pointer justify-center", SQUARE[size.variant]) : cn("cursor-text pr-2.5", INSET[size.variant], PILL[size.variant]), isExpanded && "invisible"),
160
+ children: [
161
+ /* @__PURE__ */ jsx(SearchIcon, {
162
+ size: size.icon,
163
+ strokeWidth: 1.5,
164
+ className: "shrink-0 text-muted-foreground transition-colors duration-fast group-hover/search:text-foreground"
165
+ }),
166
+ variant === "pill" && /* @__PURE__ */ jsx("span", {
167
+ className: "text-muted-foreground",
168
+ children: placeholder
169
+ }),
170
+ variant === "pill" && shortcut && /* @__PURE__ */ jsx(CommandShortcut, {
171
+ className: "pl-4",
172
+ children: shortcut
173
+ })
174
+ ]
175
+ }),
176
+ rest > 0 && /* @__PURE__ */ jsx(motion.div, {
177
+ ref: field,
178
+ className: cn("absolute top-0 h-full overflow-hidden ring-1 transition-[box-shadow] duration-moderate", align === "end" ? "right-0" : "left-0", shape.input, lifted ? cn("z-10 ring-transparent", SURFACE_BG[level], SURFACE_SHADOW[3]) : "ring-border group-hover/search:bg-muted/50"),
179
+ initial: false,
180
+ animate: { width: isExpanded ? width : rest },
181
+ transition: reduced ? { duration: 0 } : isExpanded ? spring.slow : spring.slow.exit,
182
+ onAnimationComplete: () => setSettled(isExpanded),
183
+ children: lifted && /* @__PURE__ */ jsxs("div", {
184
+ className: cn("flex h-full items-center pr-1.5", size.gap, INSET[size.variant]),
185
+ style: { width },
186
+ children: [
187
+ /* @__PURE__ */ jsx(SearchIcon, {
188
+ size: size.icon,
189
+ strokeWidth: 1.5,
190
+ className: "shrink-0 text-muted-foreground"
191
+ }),
192
+ suggestions ? /* @__PURE__ */ jsx(Autocomplete.Input, {
193
+ ...inputProps
194
+ }) : /* @__PURE__ */ jsx("input", {
195
+ ...inputProps,
196
+ type: "search",
197
+ value: query,
198
+ onChange: (event) => setQuery(event.target.value)
199
+ }),
200
+ query && /* @__PURE__ */ jsx("button", {
201
+ type: "button",
202
+ "aria-label": "Clear",
203
+ onMouseDown: (event) => event.preventDefault(),
204
+ onClick: () => {
205
+ setQuery("");
206
+ input.current?.focus();
207
+ },
208
+ className: "flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground outline-none transition-[color,background-color] duration-fast hover:bg-hover hover:text-foreground active:bg-active focus-visible:ring-1 focus-visible:ring-focus-ring",
209
+ children: /* @__PURE__ */ jsx(XIcon, {
210
+ size: size.icon - 2,
211
+ strokeWidth: 1.5
212
+ })
213
+ })
214
+ ]
215
+ })
216
+ })
217
+ ]
218
+ })
219
+ });
220
+ if (!suggestions)
221
+ return root;
222
+ return /* @__PURE__ */ jsxs(CommandListRoot, {
223
+ items: suggestions,
224
+ value: query,
225
+ onValueChange: setQuery,
226
+ open,
227
+ onOpenChange: setSuggesting,
228
+ children: [
229
+ root,
230
+ /* @__PURE__ */ jsx(Autocomplete.Portal, {
231
+ children: /* @__PURE__ */ jsx(Autocomplete.Positioner, {
232
+ anchor: field,
233
+ side: "bottom",
234
+ align,
235
+ sideOffset: 8,
236
+ className: "z-50 outline-none",
237
+ children: /* @__PURE__ */ jsx(Autocomplete.Popup, {
238
+ ref: morph.popupRef,
239
+ className: "relative outline-none",
240
+ children: /* @__PURE__ */ jsx(SurfaceProvider, {
241
+ value: level,
242
+ children: /* @__PURE__ */ jsx(MorphSurface, {
243
+ morph,
244
+ bg: SURFACE_BG[level],
245
+ shadow: SURFACE_SHADOW[3],
246
+ radius: shapeMap.rounded.container,
247
+ className: "flex max-h-[min(300px,var(--available-height))] w-[var(--anchor-width)] flex-col overflow-hidden",
248
+ children: /* @__PURE__ */ jsx(CommandList, {
249
+ emptyMessage,
250
+ onPick: (item) => onSubmit?.(item.label)
251
+ })
252
+ })
253
+ })
254
+ })
255
+ })
256
+ })
257
+ ]
258
+ });
259
+ }
260
+ var search_default = Search;
261
+
262
+ export { Search, search_default };
@@ -0,0 +1,42 @@
1
+ // lib/surface-classes.ts
2
+ var SURFACE_BG = {
3
+ 1: "bg-surface-1",
4
+ 2: "bg-surface-2",
5
+ 3: "bg-surface-3",
6
+ 4: "bg-surface-4",
7
+ 5: "bg-surface-5",
8
+ 6: "bg-surface-6",
9
+ 7: "bg-surface-7",
10
+ 8: "bg-surface-8"
11
+ };
12
+ var SURFACE_SHADOW = {
13
+ 1: "shadow-surface-1",
14
+ 2: "shadow-surface-2",
15
+ 3: "shadow-surface-3",
16
+ 4: "shadow-surface-4",
17
+ 5: "shadow-surface-5",
18
+ 6: "shadow-surface-6",
19
+ 7: "shadow-surface-7",
20
+ 8: "shadow-surface-8"
21
+ };
22
+ function surfaceClasses(bgLevel, shadowLevel = bgLevel) {
23
+ const bg = Math.round(Math.max(1, Math.min(8, bgLevel)));
24
+ const shadow = Math.round(Math.max(1, Math.min(8, shadowLevel)));
25
+ return `${SURFACE_BG[bg]} ${SURFACE_SHADOW[shadow]}`;
26
+ }
27
+
28
+ // lib/surface-context.tsx
29
+ import { createContext, useContext } from "react";
30
+ import { jsx } from "react/jsx-runtime";
31
+ var SurfaceContext = createContext(1);
32
+ function useSurface() {
33
+ return useContext(SurfaceContext);
34
+ }
35
+ function SurfaceProvider({ value, children }) {
36
+ return /* @__PURE__ */ jsx(SurfaceContext.Provider, {
37
+ value: Math.max(1, Math.min(8, value)),
38
+ children
39
+ });
40
+ }
41
+
42
+ export { SURFACE_BG, SURFACE_SHADOW, surfaceClasses, useSurface, SurfaceProvider };
@@ -0,0 +1,22 @@
1
+ // lib/field-classes.ts
2
+ import { cva } from "class-variance-authority";
3
+ var fieldVariants = cva([
4
+ "group/field ring-1 cursor-text transition-[background-color,box-shadow,opacity] duration-fast",
5
+ "hover:bg-muted/50 hover:ring-border data-[active]:bg-muted/50 data-[active]:ring-border",
6
+ "focus-within:!bg-card focus-within:ring-border",
7
+ "data-[invalid]:!ring-destructive/50 data-[invalid]:hover:bg-destructive-light/60 data-[invalid]:data-[active]:bg-destructive-light/60",
8
+ "data-[disabled]:ring-border data-[disabled]:opacity-50 data-[disabled]:pointer-events-none"
9
+ ], {
10
+ variants: {
11
+ variant: {
12
+ borderless: "bg-transparent ring-transparent",
13
+ bordered: "bg-transparent ring-border"
14
+ }
15
+ },
16
+ defaultVariants: {
17
+ variant: "borderless"
18
+ }
19
+ });
20
+ var fieldIconClasses = "shrink-0 text-muted-foreground transition-[color,stroke-width] duration-fast group-hover/field:text-foreground group-hover/field:stroke-[2] group-data-[active]/field:text-foreground group-data-[active]/field:stroke-[2] group-focus-within/field:text-foreground group-focus-within/field:stroke-[2]";
21
+
22
+ export { fieldVariants, fieldIconClasses };
@@ -0,0 +1,26 @@
1
+ // lib/use-controllable-state.ts
2
+ import { useCallback, useRef, useState } from "react";
3
+ function useControllableState(value, defaultValue, onChange) {
4
+ const [internal, setInternal] = useState(defaultValue);
5
+ const controlled = value !== undefined;
6
+ const current = controlled ? value : internal;
7
+ const currentRef = useRef(current);
8
+ currentRef.current = current;
9
+ const controlledRef = useRef(controlled);
10
+ controlledRef.current = controlled;
11
+ const onChangeRef = useRef(onChange);
12
+ onChangeRef.current = onChange;
13
+ const setValue = useCallback((next) => {
14
+ const prev = currentRef.current;
15
+ const resolved = typeof next === "function" ? next(prev) : next;
16
+ if (Object.is(resolved, prev))
17
+ return;
18
+ currentRef.current = resolved;
19
+ if (!controlledRef.current)
20
+ setInternal(resolved);
21
+ onChangeRef.current?.(resolved);
22
+ }, []);
23
+ return [current, setValue];
24
+ }
25
+
26
+ export { useControllableState };
@@ -0,0 +1,42 @@
1
+ import {
2
+ DialogClose,
3
+ DialogContent,
4
+ DialogDescription,
5
+ DialogFooter,
6
+ DialogHeader,
7
+ DialogState,
8
+ DialogTitle,
9
+ DialogTrigger
10
+ } from "./components-61ckf42z.js";
11
+
12
+ // components/overlays/alert-dialog/index.tsx
13
+ import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
14
+ import { forwardRef } from "react";
15
+ import { jsx } from "react/jsx-runtime";
16
+ var AlertDialogContent = forwardRef(({ showCloseButton = false, ...props }, ref) => /* @__PURE__ */ jsx(DialogContent, {
17
+ ref,
18
+ showCloseButton,
19
+ ...props
20
+ }));
21
+ AlertDialogContent.displayName = "AlertDialogContent";
22
+ function AlertDialog({ children, open, defaultOpen, onOpenChange }) {
23
+ return /* @__PURE__ */ jsx(DialogState, {
24
+ open,
25
+ defaultOpen,
26
+ onOpenChange,
27
+ children: (root) => /* @__PURE__ */ jsx(AlertDialogPrimitive.Root, {
28
+ ...root,
29
+ children
30
+ })
31
+ });
32
+ }
33
+ AlertDialog.Trigger = DialogTrigger;
34
+ AlertDialog.Content = AlertDialogContent;
35
+ AlertDialog.Header = DialogHeader;
36
+ AlertDialog.Footer = DialogFooter;
37
+ AlertDialog.Title = DialogTitle;
38
+ AlertDialog.Description = DialogDescription;
39
+ AlertDialog.Close = DialogClose;
40
+ var alert_dialog_default = AlertDialog;
41
+
42
+ export { AlertDialogContent, AlertDialog, alert_dialog_default };
@@ -0,0 +1,298 @@
1
+ // lib/use-fluid-hover.ts
2
+ import {
3
+ useCallback,
4
+ useEffect,
5
+ useRef,
6
+ useState
7
+ } from "react";
8
+ function pickNearest({
9
+ axis,
10
+ point,
11
+ rects,
12
+ containerRect,
13
+ scroll,
14
+ border,
15
+ layoutSize,
16
+ isDisabled
17
+ }) {
18
+ const scaleX = layoutSize.width > 0 ? containerRect.width / layoutSize.width : 1;
19
+ const scaleY = layoutSize.height > 0 ? containerRect.height / layoutSize.height : 1;
20
+ let closestIndex = null;
21
+ let closestDistance = Infinity;
22
+ let containingIndex = null;
23
+ for (let index = 0;index < rects.length; index++) {
24
+ const r = rects[index];
25
+ if (!r)
26
+ continue;
27
+ if (isDisabled?.(index))
28
+ continue;
29
+ if (axis === "xy") {
30
+ const left = containerRect.left + (border.x + r.left - scroll.x) * scaleX;
31
+ const top = containerRect.top + (border.y + r.top - scroll.y) * scaleY;
32
+ const width = r.width * scaleX;
33
+ const height = r.height * scaleY;
34
+ if (point.x >= left && point.x <= left + width && point.y >= top && point.y <= top + height) {
35
+ containingIndex = index;
36
+ }
37
+ const distance2 = Math.hypot(point.x - (left + width / 2), point.y - (top + height / 2));
38
+ if (distance2 < closestDistance) {
39
+ closestDistance = distance2;
40
+ closestIndex = index;
41
+ }
42
+ continue;
43
+ }
44
+ const horizontal = axis === "x";
45
+ const mousePos = horizontal ? point.x : point.y;
46
+ const scale = horizontal ? scaleX : scaleY;
47
+ const itemStart = (horizontal ? containerRect.left : containerRect.top) + ((horizontal ? border.x : border.y) + (horizontal ? r.left : r.top) - (horizontal ? scroll.x : scroll.y)) * scale;
48
+ const itemSize = (horizontal ? r.width : r.height) * scale;
49
+ if (mousePos >= itemStart && mousePos <= itemStart + itemSize) {
50
+ containingIndex = index;
51
+ }
52
+ const distance = Math.abs(mousePos - (itemStart + itemSize / 2));
53
+ if (distance < closestDistance) {
54
+ closestDistance = distance;
55
+ closestIndex = index;
56
+ }
57
+ }
58
+ return containingIndex ?? closestIndex;
59
+ }
60
+ var ACTIVE_ATTR = "data-fluid-hover-active";
61
+ var ACTIVE_INDEX_ATTR = "data-fluid-hover-active-index";
62
+ var ACTIVATOR_SELECTOR = "a[href], button, [role='menuitem'], [role='menuitemradio'], [role='menuitemcheckbox'], [role='option'], [role='radio'], [role='checkbox'], [role='tab'], [role='link'], [role='button']";
63
+ function resolveActivator(element) {
64
+ if (element.matches(ACTIVATOR_SELECTOR) || element.hasAttribute("tabindex")) {
65
+ return element;
66
+ }
67
+ return element.querySelector(ACTIVATOR_SELECTOR) ?? element;
68
+ }
69
+ var measurementAttempts = 3;
70
+ function useFluidHover(containerRef, options = {}) {
71
+ const { axis = "y", isItemDisabled, gapClick = true } = options;
72
+ const gapClickMaxDistance = typeof gapClick === "object" ? gapClick.maxDistance ?? Infinity : Infinity;
73
+ const itemsRef = useRef(new Map);
74
+ const [activeIndex, setActiveIndex] = useState(null);
75
+ const activeIndexRef = useRef(null);
76
+ activeIndexRef.current = activeIndex;
77
+ useEffect(() => {
78
+ const container = containerRef.current;
79
+ if (activeIndex === null)
80
+ container?.removeAttribute(ACTIVE_INDEX_ATTR);
81
+ else
82
+ container?.setAttribute(ACTIVE_INDEX_ATTR, String(activeIndex));
83
+ const active = activeIndex === null ? undefined : itemsRef.current.get(activeIndex);
84
+ active?.setAttribute(ACTIVE_ATTR, "");
85
+ return () => {
86
+ active?.removeAttribute(ACTIVE_ATTR);
87
+ if (activeIndex !== null)
88
+ itemsRef.current.get(activeIndex)?.removeAttribute(ACTIVE_ATTR);
89
+ };
90
+ }, [activeIndex, containerRef]);
91
+ const [itemRects, setItemRects] = useState([]);
92
+ const [isMeasured, setIsMeasured] = useState(false);
93
+ const itemRectsRef = useRef([]);
94
+ const sessionRef = useRef(0);
95
+ const rafIdRef = useRef(null);
96
+ const remeasureRafIdRef = useRef(null);
97
+ const runMeasurement = useCallback(() => {
98
+ const container = containerRef.current;
99
+ if (!container)
100
+ return false;
101
+ const rects = [];
102
+ let everyItemHasLayout = true;
103
+ itemsRef.current.forEach((element, index) => {
104
+ const hasLayoutBox = element.offsetParent !== null || element.offsetWidth > 0 || element.offsetHeight > 0;
105
+ if (!hasLayoutBox) {
106
+ everyItemHasLayout = false;
107
+ return;
108
+ }
109
+ let top = element.offsetTop;
110
+ let left = element.offsetLeft;
111
+ let ancestor = element.offsetParent;
112
+ while (ancestor && ancestor !== container && container.contains(ancestor)) {
113
+ top += ancestor.offsetTop + ancestor.clientTop;
114
+ left += ancestor.offsetLeft + ancestor.clientLeft;
115
+ ancestor = ancestor.offsetParent;
116
+ }
117
+ rects[index] = {
118
+ top,
119
+ height: element.offsetHeight,
120
+ left,
121
+ width: element.offsetWidth
122
+ };
123
+ });
124
+ if (!everyItemHasLayout)
125
+ return false;
126
+ const prev = itemRectsRef.current;
127
+ let changed = prev.length !== rects.length;
128
+ for (let i = 0;!changed && i < rects.length; i++) {
129
+ const p = prev[i];
130
+ const r = rects[i];
131
+ if (p === r)
132
+ continue;
133
+ changed = !p || !r || p.top !== r.top || p.left !== r.left || p.width !== r.width || p.height !== r.height;
134
+ }
135
+ if (changed) {
136
+ itemRectsRef.current = rects;
137
+ setItemRects(rects);
138
+ }
139
+ return true;
140
+ }, [containerRef]);
141
+ const measureItems = useCallback(() => {
142
+ runMeasurement();
143
+ }, [runMeasurement]);
144
+ const scheduleMeasurement = useCallback((attemptsLeft) => {
145
+ if (remeasureRafIdRef.current !== null) {
146
+ cancelAnimationFrame(remeasureRafIdRef.current);
147
+ }
148
+ remeasureRafIdRef.current = requestAnimationFrame(() => {
149
+ remeasureRafIdRef.current = null;
150
+ if (runMeasurement()) {
151
+ setIsMeasured(true);
152
+ } else if (attemptsLeft > 1) {
153
+ scheduleMeasurement(attemptsLeft - 1);
154
+ }
155
+ });
156
+ }, [runMeasurement]);
157
+ const remeasure = useCallback(() => {
158
+ setIsMeasured(false);
159
+ scheduleMeasurement(measurementAttempts);
160
+ }, [scheduleMeasurement]);
161
+ const itemRoRef = useRef(null);
162
+ const getItemRo = useCallback(() => {
163
+ if (itemRoRef.current === null && typeof ResizeObserver !== "undefined") {
164
+ itemRoRef.current = new ResizeObserver(() => scheduleMeasurement(measurementAttempts));
165
+ }
166
+ return itemRoRef.current;
167
+ }, [scheduleMeasurement]);
168
+ const registerItem = useCallback((index, element) => {
169
+ if (element) {
170
+ itemsRef.current.set(index, element);
171
+ getItemRo()?.observe(element);
172
+ if (index === activeIndexRef.current)
173
+ element.setAttribute(ACTIVE_ATTR, "");
174
+ } else {
175
+ const previous = itemsRef.current.get(index);
176
+ if (previous)
177
+ itemRoRef.current?.unobserve(previous);
178
+ previous?.removeAttribute(ACTIVE_ATTR);
179
+ itemsRef.current.delete(index);
180
+ if (index === activeIndexRef.current) {
181
+ setActiveIndex((current) => current === index && !itemsRef.current.has(index) ? null : current);
182
+ }
183
+ }
184
+ remeasure();
185
+ }, [remeasure, getItemRo]);
186
+ const handleMouseMove = useCallback((e) => {
187
+ const mouseX = e.clientX;
188
+ const mouseY = e.clientY;
189
+ if (rafIdRef.current !== null) {
190
+ cancelAnimationFrame(rafIdRef.current);
191
+ }
192
+ rafIdRef.current = requestAnimationFrame(() => {
193
+ rafIdRef.current = null;
194
+ const container = containerRef.current;
195
+ if (!container)
196
+ return;
197
+ setActiveIndex(pickNearest({
198
+ axis,
199
+ point: { x: mouseX, y: mouseY },
200
+ rects: itemRectsRef.current,
201
+ containerRect: container.getBoundingClientRect(),
202
+ scroll: { x: container.scrollLeft, y: container.scrollTop },
203
+ border: { x: container.clientLeft, y: container.clientTop },
204
+ layoutSize: { width: container.offsetWidth, height: container.offsetHeight },
205
+ isDisabled: isItemDisabled ? (index) => {
206
+ const el = itemsRef.current.get(index);
207
+ return !!el && isItemDisabled(el);
208
+ } : undefined
209
+ }));
210
+ });
211
+ }, [axis, containerRef, isItemDisabled]);
212
+ const handleMouseEnter = useCallback(() => {
213
+ sessionRef.current += 1;
214
+ }, []);
215
+ const handleMouseLeave = useCallback(() => {
216
+ if (rafIdRef.current !== null) {
217
+ cancelAnimationFrame(rafIdRef.current);
218
+ rafIdRef.current = null;
219
+ }
220
+ setActiveIndex(null);
221
+ }, []);
222
+ const handleClick = useCallback((e) => {
223
+ const target = e.target;
224
+ if (!target)
225
+ return;
226
+ for (const element2 of itemsRef.current.values()) {
227
+ if (element2.contains(target))
228
+ return;
229
+ }
230
+ if (!target.isConnected)
231
+ return;
232
+ const control = target.closest?.("input, textarea, select, button, a, summary, [contenteditable], [role='textbox'], [role='searchbox'], [role='button']");
233
+ if (control)
234
+ return;
235
+ if (gapClick === false)
236
+ return;
237
+ const index = activeIndexRef.current;
238
+ if (index === null)
239
+ return;
240
+ const element = itemsRef.current.get(index);
241
+ if (!element || isItemDisabled?.(element))
242
+ return;
243
+ if (gapClickMaxDistance !== Infinity) {
244
+ const r = element.getBoundingClientRect();
245
+ const dx = Math.max(r.left - e.clientX, 0, e.clientX - r.right);
246
+ const dy = Math.max(r.top - e.clientY, 0, e.clientY - r.bottom);
247
+ if (Math.hypot(dx, dy) > gapClickMaxDistance)
248
+ return;
249
+ }
250
+ resolveActivator(element).click();
251
+ }, [isItemDisabled, gapClick, gapClickMaxDistance]);
252
+ useEffect(() => {
253
+ const container = containerRef.current;
254
+ if (!container || typeof ResizeObserver === "undefined")
255
+ return;
256
+ const ro = new ResizeObserver(() => scheduleMeasurement(measurementAttempts));
257
+ ro.observe(container);
258
+ return () => ro.disconnect();
259
+ }, [containerRef, scheduleMeasurement]);
260
+ useEffect(() => {
261
+ return () => {
262
+ if (rafIdRef.current !== null) {
263
+ cancelAnimationFrame(rafIdRef.current);
264
+ }
265
+ if (remeasureRafIdRef.current !== null) {
266
+ cancelAnimationFrame(remeasureRafIdRef.current);
267
+ }
268
+ itemRoRef.current?.disconnect();
269
+ itemRoRef.current = null;
270
+ };
271
+ }, []);
272
+ return {
273
+ activeIndex,
274
+ setActiveIndex,
275
+ itemRects,
276
+ isMeasured,
277
+ sessionRef,
278
+ handlers: {
279
+ onMouseMove: handleMouseMove,
280
+ onMouseEnter: handleMouseEnter,
281
+ onMouseLeave: handleMouseLeave,
282
+ onClick: handleClick
283
+ },
284
+ registerItem,
285
+ remeasure,
286
+ measureItems
287
+ };
288
+ }
289
+ function useRegisterFluidHoverItem(registerItem, index, ref) {
290
+ useEffect(() => {
291
+ if (!registerItem || index === undefined)
292
+ return;
293
+ registerItem(index, ref.current);
294
+ return () => registerItem(index, null);
295
+ }, [index, registerItem, ref]);
296
+ }
297
+
298
+ export { useFluidHover, useRegisterFluidHoverItem };