@justanarthur/modo-ui 0.0.0-stage → 0.2.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 (171) 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 +31 -0
  10. package/dist/components/badge/index.d.ts +59 -0
  11. package/dist/components/badge/index.js +16 -0
  12. package/dist/components/button/index.d.ts +59 -0
  13. package/dist/components/button/index.js +14 -0
  14. package/dist/components/card/index.d.ts +141 -0
  15. package/dist/components/card/index.js +42 -0
  16. package/dist/components/inputs/checkbox-group/index.d.ts +50 -0
  17. package/dist/components/inputs/checkbox-group/index.js +21 -0
  18. package/dist/components/inputs/color-picker/index.d.ts +137 -0
  19. package/dist/components/inputs/color-picker/index.js +35 -0
  20. package/dist/components/inputs/combobox/index.d.ts +161 -0
  21. package/dist/components/inputs/combobox/index.js +38 -0
  22. package/dist/components/inputs/date-time/calendar/index.d.ts +45 -0
  23. package/dist/components/inputs/date-time/calendar/index.js +18 -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 +32 -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 +31 -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 +31 -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 +30 -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 +31 -0
  34. package/dist/components/inputs/input/index.d.ts +84 -0
  35. package/dist/components/inputs/input/index.js +19 -0
  36. package/dist/components/inputs/input-copy/index.d.ts +44 -0
  37. package/dist/components/inputs/input-copy/index.js +16 -0
  38. package/dist/components/inputs/input-message/index.d.ts +125 -0
  39. package/dist/components/inputs/input-message/index.js +25 -0
  40. package/dist/components/inputs/radio-group/index.d.ts +58 -0
  41. package/dist/components/inputs/radio-group/index.js +20 -0
  42. package/dist/components/inputs/search/index.d.ts +83 -0
  43. package/dist/components/inputs/search/index.js +25 -0
  44. package/dist/components/inputs/select/index.d.ts +105 -0
  45. package/dist/components/inputs/select/index.js +34 -0
  46. package/dist/components/inputs/slider/index.d.ts +108 -0
  47. package/dist/components/inputs/slider/index.js +14 -0
  48. package/dist/components/inputs/switch/index.d.ts +43 -0
  49. package/dist/components/inputs/switch/index.js +14 -0
  50. package/dist/components/navigation/accordion/index.d.ts +117 -0
  51. package/dist/components/navigation/accordion/index.js +28 -0
  52. package/dist/components/navigation/sidebar/index.d.ts +388 -0
  53. package/dist/components/navigation/sidebar/index.js +99 -0
  54. package/dist/components/navigation/tabs/index.d.ts +70 -0
  55. package/dist/components/navigation/tabs/index.js +23 -0
  56. package/dist/components/navigation/tabs-subtle/index.d.ts +73 -0
  57. package/dist/components/navigation/tabs-subtle/index.js +21 -0
  58. package/dist/components/overlays/alert-dialog/index.d.ts +67 -0
  59. package/dist/components/overlays/alert-dialog/index.js +22 -0
  60. package/dist/components/overlays/command/index.d.ts +121 -0
  61. package/dist/components/overlays/command/index.js +36 -0
  62. package/dist/components/overlays/context-menu/index.d.ts +97 -0
  63. package/dist/components/overlays/context-menu/index.js +29 -0
  64. package/dist/components/overlays/dialog/index.d.ts +130 -0
  65. package/dist/components/overlays/dialog/index.js +37 -0
  66. package/dist/components/overlays/dropdown/index.d.ts +222 -0
  67. package/dist/components/overlays/dropdown/index.js +44 -0
  68. package/dist/components/overlays/popover/index.d.ts +87 -0
  69. package/dist/components/overlays/popover/index.js +26 -0
  70. package/dist/components/overlays/preview-card/index.d.ts +75 -0
  71. package/dist/components/overlays/preview-card/index.js +19 -0
  72. package/dist/components/overlays/sheet/index.d.ts +67 -0
  73. package/dist/components/overlays/sheet/index.js +24 -0
  74. package/dist/components/overlays/toast/index.d.ts +107 -0
  75. package/dist/components/overlays/toast/index.js +21 -0
  76. package/dist/components/overlays/tooltip/index.d.ts +75 -0
  77. package/dist/components/overlays/tooltip/index.js +17 -0
  78. package/dist/components/table/index.d.ts +44 -0
  79. package/dist/components/table/index.js +26 -0
  80. package/dist/components/thinking-indicator/index.d.ts +32 -0
  81. package/dist/components/thinking-indicator/index.js +13 -0
  82. package/dist/index.d.ts +3926 -0
  83. package/dist/index.js +511 -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 +11 -0
  88. package/dist/primitives/craft/index.d.ts +31 -0
  89. package/dist/primitives/craft/index.js +11 -0
  90. package/dist/primitives/fluid-hover/index.d.ts +233 -0
  91. package/dist/primitives/fluid-hover/index.js +25 -0
  92. package/dist/primitives/morph/index.d.ts +127 -0
  93. package/dist/primitives/morph/index.js +19 -0
  94. package/dist/primitives/motion/index.d.ts +115 -0
  95. package/dist/primitives/motion/index.js +19 -0
  96. package/dist/primitives/scroll-area/index.d.ts +41 -0
  97. package/dist/primitives/scroll-area/index.js +12 -0
  98. package/dist/primitives/sizes/index.d.ts +128 -0
  99. package/dist/primitives/sizes/index.js +21 -0
  100. package/dist/primitives/surface/index.d.ts +69 -0
  101. package/dist/primitives/surface/index.js +17 -0
  102. package/dist/shared/components-0ke6xada.js +123 -0
  103. package/dist/shared/components-0q0sqfh4.js +146 -0
  104. package/dist/shared/components-0sn7ypjw.js +61 -0
  105. package/dist/shared/components-1j9791sn.js +345 -0
  106. package/dist/shared/components-1rfwbyyc.js +361 -0
  107. package/dist/shared/components-1v7rxytx.js +30 -0
  108. package/dist/shared/components-1xekx2hx.js +215 -0
  109. package/dist/shared/components-39jq9va1.js +86 -0
  110. package/dist/shared/components-3gae8nta.js +719 -0
  111. package/dist/shared/components-3k8xpnpq.js +1759 -0
  112. package/dist/shared/components-3ky44908.js +9 -0
  113. package/dist/shared/components-3mkepka5.js +111 -0
  114. package/dist/shared/components-3wk0w46f.js +667 -0
  115. package/dist/shared/components-4cnjmgex.js +124 -0
  116. package/dist/shared/components-59efxjd9.js +298 -0
  117. package/dist/shared/components-5xc2j8jz.js +159 -0
  118. package/dist/shared/components-62ybc7t2.js +496 -0
  119. package/dist/shared/components-66mv71kx.js +262 -0
  120. package/dist/shared/components-7ans7ce5.js +120 -0
  121. package/dist/shared/components-7btqt08d.js +270 -0
  122. package/dist/shared/components-7r3etddy.js +171 -0
  123. package/dist/shared/components-7x9kawxv.js +152 -0
  124. package/dist/shared/components-8fpr3s4p.js +292 -0
  125. package/dist/shared/components-9jvzzvt1.js +198 -0
  126. package/dist/shared/components-apdwtweq.js +484 -0
  127. package/dist/shared/components-asr5pg50.js +191 -0
  128. package/dist/shared/components-b2wyq2cq.js +232 -0
  129. package/dist/shared/components-c6s6b43g.js +15 -0
  130. package/dist/shared/components-ca2c898n.js +1828 -0
  131. package/dist/shared/components-cbxjn9p8.js +141 -0
  132. package/dist/shared/components-chacnk61.js +216 -0
  133. package/dist/shared/components-cv16mryv.js +62 -0
  134. package/dist/shared/components-ez65vtbq.js +110 -0
  135. package/dist/shared/components-ezxhrmer.js +17 -0
  136. package/dist/shared/components-gc5vtq2f.js +149 -0
  137. package/dist/shared/components-gf5s6ap9.js +42 -0
  138. package/dist/shared/components-gvr9w41t.js +193 -0
  139. package/dist/shared/components-h2dpcwgc.js +137 -0
  140. package/dist/shared/components-hawvy2qz.js +105 -0
  141. package/dist/shared/components-hqeq3w9q.js +375 -0
  142. package/dist/shared/components-jjw69c4c.js +28 -0
  143. package/dist/shared/components-jwst3vtj.js +346 -0
  144. package/dist/shared/components-kvr7f9hy.js +45 -0
  145. package/dist/shared/components-men63rwj.js +9 -0
  146. package/dist/shared/components-mhd39z7x.js +22 -0
  147. package/dist/shared/components-n7mjr357.js +26 -0
  148. package/dist/shared/components-ng72k97e.js +128 -0
  149. package/dist/shared/components-nh8tma1n.js +986 -0
  150. package/dist/shared/components-njzgqdwy.js +445 -0
  151. package/dist/shared/components-ny774h8p.js +293 -0
  152. package/dist/shared/components-q4daerx0.js +58 -0
  153. package/dist/shared/components-q5xj5c16.js +79 -0
  154. package/dist/shared/components-rr7a6ja9.js +160 -0
  155. package/dist/shared/components-s2bz1xpk.js +63 -0
  156. package/dist/shared/components-tqvarbfv.js +288 -0
  157. package/dist/shared/components-v6xp325t.js +304 -0
  158. package/dist/shared/components-v7wtz8hk.js +144 -0
  159. package/dist/shared/components-vc7vq5nz.js +32 -0
  160. package/dist/shared/components-vfbhxf5r.js +58 -0
  161. package/dist/shared/components-vynjtrk6.js +19 -0
  162. package/dist/shared/components-wvp1m52g.js +1200 -0
  163. package/dist/shared/components-yh3kwdhr.js +981 -0
  164. package/dist/shared/components-ytb2tefr.js +291 -0
  165. package/dist/shared/components-zfnmn5d4.js +220 -0
  166. package/dist/shared/components-zrkzcayz.js +141 -0
  167. package/dist/shared/components-zx6b6yby.js +42 -0
  168. package/dist/styles.css +1949 -0
  169. package/dist/tailwind.css +219 -0
  170. package/dist/tokens.css +345 -0
  171. package/package.json +103 -4
@@ -0,0 +1,124 @@
1
+ import {
2
+ defaultLocale,
3
+ parseMonthText,
4
+ fieldLabel,
5
+ dividedColumns,
6
+ ScrollColumn
7
+ } from "./components-9jvzzvt1.js";
8
+ import {
9
+ cn2
10
+ } from "./components-ezxhrmer.js";
11
+ import {
12
+ useControllableState
13
+ } from "./components-n7mjr357.js";
14
+ import {
15
+ PickerShell,
16
+ PickerInput
17
+ } from "./components-7btqt08d.js";
18
+
19
+ // components/inputs/date-time/month-picker/index.tsx
20
+ import { addYears, endOfYear, format, startOfMonth, startOfYear } from "date-fns";
21
+ import { useMemo, useRef } from "react";
22
+ import { jsx, jsxs } from "react/jsx-runtime";
23
+ function MonthPicker2({
24
+ value: valueProp,
25
+ defaultValue = null,
26
+ onValueChange,
27
+ locale = defaultLocale,
28
+ placeholder,
29
+ startMonth,
30
+ endMonth,
31
+ disabled,
32
+ invalid,
33
+ size,
34
+ open: openProp,
35
+ defaultOpen = false,
36
+ onOpenChange,
37
+ id,
38
+ from,
39
+ effect,
40
+ hideSource,
41
+ tier,
42
+ className
43
+ }) {
44
+ const [value, setValue] = useControllableState(valueProp, defaultValue, onValueChange);
45
+ const [open, setOpen] = useControllableState(openProp, defaultOpen, onOpenChange);
46
+ const input = useRef(null);
47
+ const today = useMemo(() => new Date, []);
48
+ const start = startOfMonth(startMonth ?? startOfYear(addYears(today, -100)));
49
+ const end = startOfMonth(endMonth ?? endOfYear(addYears(today, 50)));
50
+ const year = value?.getFullYear() ?? today.getFullYear();
51
+ const formatted = value ? format(value, "LLLL y", { locale }) : "";
52
+ const pick = (date) => setValue(startOfMonth(date < start ? start : date > end ? end : date));
53
+ const readMonth = (text) => {
54
+ if (!text.trim()) {
55
+ setValue(null);
56
+ return true;
57
+ }
58
+ const read = parseMonthText(text, locale);
59
+ if (!read || read < start || read > end)
60
+ return false;
61
+ setValue(startOfMonth(read));
62
+ return true;
63
+ };
64
+ const months = useMemo(() => Array.from({ length: 12 }, (_, m) => ({
65
+ value: m,
66
+ label: format(new Date(2000, m, 1), "LLLL", { locale }),
67
+ disabled: new Date(year, m, 1) < start || new Date(year, m, 1) > end
68
+ })), [locale, year, start.getTime(), end.getTime()]);
69
+ const years = useMemo(() => Array.from({ length: end.getFullYear() - start.getFullYear() + 1 }, (_, i) => ({
70
+ value: start.getFullYear() + i,
71
+ label: String(start.getFullYear() + i)
72
+ })), [start.getFullYear(), end.getFullYear()]);
73
+ return /* @__PURE__ */ jsx(PickerShell, {
74
+ open,
75
+ onOpenChange: setOpen,
76
+ size,
77
+ invalid,
78
+ disabled,
79
+ icon: "calendar",
80
+ display: formatted,
81
+ placeholder,
82
+ header: /* @__PURE__ */ jsx(PickerInput, {
83
+ ref: input,
84
+ "aria-label": placeholder ?? "Month",
85
+ placeholder,
86
+ formatted,
87
+ onText: readMonth,
88
+ onEnter: () => setOpen(false),
89
+ className: "flex-1"
90
+ }),
91
+ initialFocus: input,
92
+ popupClassName: "w-[max(var(--anchor-width,0px),14rem)]",
93
+ id,
94
+ from,
95
+ effect,
96
+ hideSource,
97
+ tier,
98
+ className,
99
+ children: /* @__PURE__ */ jsxs("div", {
100
+ className: cn2(dividedColumns, "h-56"),
101
+ children: [
102
+ /* @__PURE__ */ jsx(ScrollColumn, {
103
+ label: fieldLabel(locale, "month"),
104
+ options: months,
105
+ value: value?.getMonth() ?? null,
106
+ follow: value?.getMonth() ?? today.getMonth(),
107
+ onValueChange: (m) => pick(new Date(year, m, 1)),
108
+ className: "min-w-0 flex-1"
109
+ }),
110
+ /* @__PURE__ */ jsx(ScrollColumn, {
111
+ label: fieldLabel(locale, "year"),
112
+ options: years,
113
+ value: value?.getFullYear() ?? null,
114
+ follow: year,
115
+ onValueChange: (y) => pick(new Date(y, value?.getMonth() ?? today.getMonth(), 1)),
116
+ className: "min-w-0 flex-1"
117
+ })
118
+ ]
119
+ })
120
+ });
121
+ }
122
+ var month_picker_default = MonthPicker2;
123
+
124
+ export { MonthPicker2, month_picker_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 distance = Math.hypot(point.x - (left + width / 2), point.y - (top + height / 2));
38
+ if (distance < closestDistance) {
39
+ closestDistance = distance;
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 useFluidHover2(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 element of itemsRef.current.values()) {
227
+ if (element.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 useRegisterFluidHoverItem2(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 { useFluidHover2, useRegisterFluidHoverItem2 };
@@ -0,0 +1,159 @@
1
+ import {
2
+ useReduceMotion
3
+ } from "./components-men63rwj.js";
4
+ import {
5
+ GOO_BLUR_RATIO
6
+ } from "./components-hqeq3w9q.js";
7
+ import {
8
+ union,
9
+ GooLayer
10
+ } from "./components-chacnk61.js";
11
+ import {
12
+ spring2
13
+ } from "./components-1v7rxytx.js";
14
+
15
+ // lib/use-merge-split.tsx
16
+ import { AnimatePresence, motion } from "motion/react";
17
+ import { useEffect, useLayoutEffect, useRef, useState } from "react";
18
+ import { jsx } from "react/jsx-runtime";
19
+ var mergeSpring = spring2.moderate;
20
+ var settleMs = mergeSpring.duration * 1000 + 80;
21
+ var SEED = 0.5;
22
+ function useSelectionRuns(checkedIndices) {
23
+ const prevGroupMap = useRef(new Map);
24
+ const groupIdCounter = useRef(0);
25
+ const runs = [];
26
+ const sorted = [...checkedIndices].sort((a, b) => a - b);
27
+ for (const idx of sorted) {
28
+ const last = runs[runs.length - 1];
29
+ if (last && idx === last.end + 1)
30
+ last.end = idx;
31
+ else
32
+ runs.push({ start: idx, end: idx });
33
+ }
34
+ const usedIds = new Set;
35
+ const nextGroupMap = new Map;
36
+ const result = runs.map((run) => {
37
+ let stableId = null;
38
+ for (let i = run.start;i <= run.end; i++) {
39
+ const prevId = prevGroupMap.current.get(i);
40
+ if (prevId !== undefined && !usedIds.has(prevId)) {
41
+ stableId = prevId;
42
+ break;
43
+ }
44
+ }
45
+ const id = stableId ?? ++groupIdCounter.current;
46
+ usedIds.add(id);
47
+ for (let i = run.start;i <= run.end; i++)
48
+ nextGroupMap.set(i, id);
49
+ return { ...run, id };
50
+ });
51
+ prevGroupMap.current = nextGroupMap;
52
+ return result;
53
+ }
54
+ function useMergeSplitBlocks(runs, itemRects, R) {
55
+ const blocks = [];
56
+ for (const run of runs) {
57
+ const first = itemRects[run.start];
58
+ const last = itemRects[run.end];
59
+ if (!first || !last)
60
+ continue;
61
+ const left = Math.min(first.left, last.left);
62
+ const width = Math.max(first.width, last.width);
63
+ for (let i = run.start;i <= run.end; i++) {
64
+ const row = itemRects[i];
65
+ if (!row)
66
+ continue;
67
+ const next = i < run.end ? itemRects[i + 1] : undefined;
68
+ const bottom = next?.top ?? row.top + row.height;
69
+ const top = i === run.start ? R : 0;
70
+ const end = i === run.end ? R : 0;
71
+ blocks.push({
72
+ key: `sel-${i}`,
73
+ top: row.top,
74
+ left,
75
+ width,
76
+ height: bottom - row.top,
77
+ radii: [top, top, end, end],
78
+ instant: false
79
+ });
80
+ }
81
+ }
82
+ return blocks;
83
+ }
84
+ var corners = ([tl, tr, br, bl]) => ({
85
+ borderTopLeftRadius: tl,
86
+ borderTopRightRadius: tr,
87
+ borderBottomRightRadius: br,
88
+ borderBottomLeftRadius: bl
89
+ });
90
+ var rest = (b) => ({
91
+ top: b.top,
92
+ left: b.left,
93
+ width: b.width,
94
+ height: b.height,
95
+ opacity: 1,
96
+ ...corners(b.radii)
97
+ });
98
+ var seed = (b) => ({
99
+ top: b.top + b.height / 2,
100
+ left: b.left + b.width * (1 - SEED) / 2,
101
+ width: b.width * SEED,
102
+ height: 0,
103
+ ...corners(b.radii)
104
+ });
105
+ var variants = (b) => ({
106
+ rest: rest(b),
107
+ enter: (mode) => mode === "goo" ? seed(b) : { ...rest(b), opacity: 0 },
108
+ leave: (mode) => mode === "goo" ? { ...seed(b), transition: mergeSpring.exit } : { opacity: 0, transition: mode === "fade" ? mergeSpring.exit : { duration: 0 } }
109
+ });
110
+ function SelectionBackgrounds({ blocks }) {
111
+ const reduced = useReduceMotion();
112
+ const mode = blocks.some((b) => b.instant) ? "snap" : reduced ? "fade" : "goo";
113
+ const rows = blocks.map((b) => b.key).join("|");
114
+ const [melting, setMelting] = useState(false);
115
+ const shown = useRef(rows);
116
+ const timer = useRef();
117
+ const covered = useRef(null);
118
+ const radius = useRef(0);
119
+ useLayoutEffect(() => {
120
+ if (rows === shown.current)
121
+ return;
122
+ shown.current = rows;
123
+ if (mode !== "goo")
124
+ return;
125
+ setMelting(true);
126
+ clearTimeout(timer.current);
127
+ timer.current = setTimeout(() => setMelting(false), settleMs);
128
+ }, [rows, mode]);
129
+ useEffect(() => () => clearTimeout(timer.current), []);
130
+ const box = blocks.reduce(union, null);
131
+ const changing = melting || rows !== shown.current;
132
+ if (!changing)
133
+ covered.current = box;
134
+ else if (box)
135
+ covered.current = union(covered.current, box);
136
+ radius.current = Math.max(changing ? radius.current : 0, ...blocks.flatMap((b) => b.radii));
137
+ return /* @__PURE__ */ jsx(GooLayer, {
138
+ active: melting,
139
+ blur: radius.current * GOO_BLUR_RATIO,
140
+ box: covered.current,
141
+ fill: "bg-active",
142
+ children: /* @__PURE__ */ jsx(AnimatePresence, {
143
+ initial: false,
144
+ custom: mode,
145
+ children: blocks.map((b) => /* @__PURE__ */ jsx(motion.div, {
146
+ "aria-hidden": true,
147
+ className: "pointer-events-none absolute bg-active",
148
+ custom: mode,
149
+ variants: variants(b),
150
+ initial: mode === "snap" ? false : "enter",
151
+ animate: "rest",
152
+ exit: "leave",
153
+ transition: mode === "snap" ? { duration: 0 } : { ...mergeSpring, opacity: { duration: spring2.fast.duration } }
154
+ }, b.key))
155
+ })
156
+ });
157
+ }
158
+
159
+ export { useSelectionRuns, useMergeSplitBlocks, SelectionBackgrounds };