@spear-ai/spectral 1.16.9 → 1.17.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.
- package/dist/AlertDialog.d.ts +59 -0
- package/dist/AlertDialog.d.ts.map +1 -0
- package/dist/AlertDialog.js +97 -0
- package/dist/AlertDialog.js.map +1 -0
- package/dist/Button.d.ts +2 -2
- package/dist/Button.d.ts.map +1 -1
- package/dist/Button.js +20 -21
- package/dist/Button.js.map +1 -1
- package/dist/Icons/LoaderIcon.d.ts.map +1 -1
- package/dist/Icons/LoaderIcon.js +1 -1
- package/dist/Icons/LoaderIcon.js.map +1 -1
- package/dist/RadialMenu.d.ts +46 -0
- package/dist/RadialMenu.d.ts.map +1 -0
- package/dist/RadialMenu.js +331 -0
- package/dist/RadialMenu.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +5 -3
- package/dist/styles/horizon/colors.css +34 -26
- package/dist/styles/spectral.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { ChevronDownIcon } from "./Icons/ChevronDownIcon.js";
|
|
3
|
+
import { cn } from "./utils/twUtils.js";
|
|
4
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "./Tooltip.js";
|
|
5
|
+
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { createPortal } from "react-dom";
|
|
8
|
+
|
|
9
|
+
//#region src/components/RadialMenu/RadialMenu.tsx
|
|
10
|
+
const BOUNCE_EASE = "motion-safe:ease-[cubic-bezier(0.34,1.56,0.64,1)]";
|
|
11
|
+
const LABEL_SHADOW = "[text-shadow:0_0_5px_var(--color-text-inverted),0_0_5px_var(--color-text-inverted),0_0_10px_var(--color-text-inverted),0_0_10px_var(--color-text-inverted),0_0_16px_var(--color-text-inverted),0_0_16px_var(--color-text-inverted),0_0_22px_var(--color-text-inverted)]";
|
|
12
|
+
const CLOSE_MS = 260;
|
|
13
|
+
const LEVEL_MS = 200;
|
|
14
|
+
const LABEL_OFFSET = 30;
|
|
15
|
+
const PRIMARY_RADIUS = 70;
|
|
16
|
+
const SUB_RADIUS = 96;
|
|
17
|
+
const ITEM_REACH = 44;
|
|
18
|
+
const VIEWPORT_MARGIN = 16;
|
|
19
|
+
const clamp = (value, min, max) => min > max ? (min + max) / 2 : Math.min(Math.max(value, min), max);
|
|
20
|
+
const runAfterPaint = (callback) => {
|
|
21
|
+
let inner = 0;
|
|
22
|
+
const outer = requestAnimationFrame(() => {
|
|
23
|
+
inner = requestAnimationFrame(callback);
|
|
24
|
+
});
|
|
25
|
+
return () => {
|
|
26
|
+
cancelAnimationFrame(outer);
|
|
27
|
+
cancelAnimationFrame(inner);
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
const positionForIndex = (index, count, radius) => {
|
|
31
|
+
const angle = -Math.PI / 2 + index * 2 * Math.PI / count;
|
|
32
|
+
return {
|
|
33
|
+
x: Math.cos(angle) * radius,
|
|
34
|
+
y: Math.sin(angle) * radius
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
const SUB_ARC_CENTER = -Math.PI / 2;
|
|
38
|
+
const SUB_ARC_SPAN = Math.PI * .7;
|
|
39
|
+
const positionOnArc = (index, count, radius) => {
|
|
40
|
+
const angle = count <= 1 ? SUB_ARC_CENTER : SUB_ARC_CENTER - SUB_ARC_SPAN / 2 + index / (count - 1) * SUB_ARC_SPAN;
|
|
41
|
+
return {
|
|
42
|
+
x: Math.cos(angle) * radius,
|
|
43
|
+
y: Math.sin(angle) * radius
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
const RadialMenu = ({ ariaLabel, backLabel = "Back", className, dataTestId, items, onClose, position, ref }) => {
|
|
47
|
+
const resolvedTestId = dataTestId ?? "spectral-radial-menu";
|
|
48
|
+
const containerRef = useRef(null);
|
|
49
|
+
const levelTimersRef = useRef([]);
|
|
50
|
+
const [activeSubmenuId, setActiveSubmenuId] = useState(null);
|
|
51
|
+
const [highlightIndex, setHighlightIndex] = useState(-1);
|
|
52
|
+
const [renderCenter, setRenderCenter] = useState(position);
|
|
53
|
+
const [expanded, setExpanded] = useState(false);
|
|
54
|
+
const [spreadOrigin, setSpreadOrigin] = useState({
|
|
55
|
+
x: 0,
|
|
56
|
+
y: 0
|
|
57
|
+
});
|
|
58
|
+
const [backSkin, setBackSkin] = useState(null);
|
|
59
|
+
const [returningId, setReturningId] = useState(null);
|
|
60
|
+
const clearLevelTimers = useCallback(() => {
|
|
61
|
+
levelTimersRef.current.forEach((id) => clearTimeout(id));
|
|
62
|
+
levelTimersRef.current = [];
|
|
63
|
+
}, []);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
clearLevelTimers();
|
|
66
|
+
if (position !== null) {
|
|
67
|
+
setRenderCenter(position);
|
|
68
|
+
setActiveSubmenuId(null);
|
|
69
|
+
setHighlightIndex(-1);
|
|
70
|
+
setSpreadOrigin({
|
|
71
|
+
x: 0,
|
|
72
|
+
y: 0
|
|
73
|
+
});
|
|
74
|
+
setBackSkin(null);
|
|
75
|
+
setReturningId(null);
|
|
76
|
+
setExpanded(false);
|
|
77
|
+
return runAfterPaint(() => {
|
|
78
|
+
setExpanded(true);
|
|
79
|
+
containerRef.current?.focus();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
setExpanded(false);
|
|
83
|
+
setSpreadOrigin({
|
|
84
|
+
x: 0,
|
|
85
|
+
y: 0
|
|
86
|
+
});
|
|
87
|
+
const timer = setTimeout(() => {
|
|
88
|
+
setRenderCenter(null);
|
|
89
|
+
setBackSkin(null);
|
|
90
|
+
}, CLOSE_MS);
|
|
91
|
+
return () => {
|
|
92
|
+
clearTimeout(timer);
|
|
93
|
+
};
|
|
94
|
+
}, [clearLevelTimers, position]);
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
if (position === null) return () => {};
|
|
97
|
+
window.addEventListener("scroll", onClose, true);
|
|
98
|
+
window.addEventListener("resize", onClose);
|
|
99
|
+
return () => {
|
|
100
|
+
window.removeEventListener("scroll", onClose, true);
|
|
101
|
+
window.removeEventListener("resize", onClose);
|
|
102
|
+
};
|
|
103
|
+
}, [position, onClose]);
|
|
104
|
+
const renderCenterRef = useRef(renderCenter);
|
|
105
|
+
renderCenterRef.current = renderCenter;
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
if (renderCenterRef.current === null) return () => {};
|
|
108
|
+
return runAfterPaint(() => {
|
|
109
|
+
setExpanded(true);
|
|
110
|
+
});
|
|
111
|
+
}, [activeSubmenuId]);
|
|
112
|
+
useEffect(() => clearLevelTimers, [clearLevelTimers]);
|
|
113
|
+
const activeItems = useMemo(() => {
|
|
114
|
+
if (activeSubmenuId === null) return items;
|
|
115
|
+
return items.find((item) => item.id === activeSubmenuId)?.items ?? items;
|
|
116
|
+
}, [activeSubmenuId, items]);
|
|
117
|
+
const activate = useCallback((item) => {
|
|
118
|
+
if (item.disabled === true) return;
|
|
119
|
+
if (item.items && item.items.length > 0) {
|
|
120
|
+
clearLevelTimers();
|
|
121
|
+
const offset = positionForIndex(items.findIndex((candidate) => candidate.id === item.id), items.length, PRIMARY_RADIUS);
|
|
122
|
+
setSpreadOrigin(offset);
|
|
123
|
+
setReturningId(null);
|
|
124
|
+
setBackSkin({
|
|
125
|
+
item: {
|
|
126
|
+
...item,
|
|
127
|
+
description: void 0,
|
|
128
|
+
icon: /* @__PURE__ */ jsx(ChevronDownIcon, {
|
|
129
|
+
className: "rotate-90",
|
|
130
|
+
size: 20
|
|
131
|
+
}),
|
|
132
|
+
id: `${item.id}__back`,
|
|
133
|
+
items: void 0,
|
|
134
|
+
label: backLabel
|
|
135
|
+
},
|
|
136
|
+
offset
|
|
137
|
+
});
|
|
138
|
+
setActiveSubmenuId(item.id);
|
|
139
|
+
setHighlightIndex(-1);
|
|
140
|
+
setExpanded(false);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
item.onSelect?.();
|
|
144
|
+
onClose();
|
|
145
|
+
}, [
|
|
146
|
+
backLabel,
|
|
147
|
+
clearLevelTimers,
|
|
148
|
+
items,
|
|
149
|
+
onClose
|
|
150
|
+
]);
|
|
151
|
+
const goBack = useCallback(() => {
|
|
152
|
+
const returningSubmenuId = activeSubmenuId;
|
|
153
|
+
const index = items.findIndex((candidate) => candidate.id === returningSubmenuId);
|
|
154
|
+
setSpreadOrigin(index >= 0 ? positionForIndex(index, items.length, PRIMARY_RADIUS) : {
|
|
155
|
+
x: 0,
|
|
156
|
+
y: 0
|
|
157
|
+
});
|
|
158
|
+
setExpanded(false);
|
|
159
|
+
setHighlightIndex(-1);
|
|
160
|
+
clearLevelTimers();
|
|
161
|
+
levelTimersRef.current = [window.setTimeout(() => {
|
|
162
|
+
if (renderCenterRef.current === null) return;
|
|
163
|
+
setActiveSubmenuId(null);
|
|
164
|
+
setBackSkin(null);
|
|
165
|
+
setReturningId(returningSubmenuId);
|
|
166
|
+
}, LEVEL_MS), window.setTimeout(() => {
|
|
167
|
+
if (renderCenterRef.current !== null) setReturningId(null);
|
|
168
|
+
}, LEVEL_MS + 350)];
|
|
169
|
+
}, [
|
|
170
|
+
activeSubmenuId,
|
|
171
|
+
clearLevelTimers,
|
|
172
|
+
items
|
|
173
|
+
]);
|
|
174
|
+
const handleKeyDown = useCallback((event) => {
|
|
175
|
+
const count = activeItems.length;
|
|
176
|
+
if (count === 0) return;
|
|
177
|
+
switch (event.key) {
|
|
178
|
+
case "ArrowRight":
|
|
179
|
+
case "ArrowDown":
|
|
180
|
+
event.preventDefault();
|
|
181
|
+
setHighlightIndex((index) => index < 0 ? 0 : (index + 1) % count);
|
|
182
|
+
break;
|
|
183
|
+
case "ArrowLeft":
|
|
184
|
+
case "ArrowUp":
|
|
185
|
+
event.preventDefault();
|
|
186
|
+
setHighlightIndex((index) => index < 0 ? count - 1 : (index - 1 + count) % count);
|
|
187
|
+
break;
|
|
188
|
+
case "Enter":
|
|
189
|
+
case " ": {
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
const item = activeItems[highlightIndex];
|
|
192
|
+
if (item) activate(item);
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
case "Escape":
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
if (activeSubmenuId === null) onClose();
|
|
198
|
+
else goBack();
|
|
199
|
+
break;
|
|
200
|
+
case "Tab":
|
|
201
|
+
event.preventDefault();
|
|
202
|
+
break;
|
|
203
|
+
default: break;
|
|
204
|
+
}
|
|
205
|
+
}, [
|
|
206
|
+
activate,
|
|
207
|
+
activeItems,
|
|
208
|
+
activeSubmenuId,
|
|
209
|
+
goBack,
|
|
210
|
+
highlightIndex,
|
|
211
|
+
onClose
|
|
212
|
+
]);
|
|
213
|
+
if (renderCenter === null || typeof document === "undefined") return null;
|
|
214
|
+
const inSubmenu = activeSubmenuId !== null;
|
|
215
|
+
const parentIndex = inSubmenu ? items.findIndex((item) => item.id === activeSubmenuId) : -1;
|
|
216
|
+
const base = (parentIndex >= 0 ? items[parentIndex] ?? null : null) === null ? {
|
|
217
|
+
x: 0,
|
|
218
|
+
y: 0
|
|
219
|
+
} : positionForIndex(parentIndex, items.length, PRIMARY_RADIUS);
|
|
220
|
+
const ringRadius = inSubmenu ? SUB_RADIUS : PRIMARY_RADIUS;
|
|
221
|
+
const reach = (inSubmenu ? PRIMARY_RADIUS + SUB_RADIUS : PRIMARY_RADIUS) + ITEM_REACH;
|
|
222
|
+
const cx = clamp(renderCenter.x, reach + VIEWPORT_MARGIN, window.innerWidth - reach - VIEWPORT_MARGIN);
|
|
223
|
+
const cy = clamp(renderCenter.y, reach + VIEWPORT_MARGIN, window.innerHeight - reach - VIEWPORT_MARGIN);
|
|
224
|
+
const renderSpoke = (options) => {
|
|
225
|
+
const { delay = 0, isActive = false, isHighlighted = false, item, nonInteractive = false, onClick, opacity, testId, x, y } = options;
|
|
226
|
+
const hasSubmenu = Boolean(item.items && item.items.length > 0);
|
|
227
|
+
const circle = /* @__PURE__ */ jsxs("button", {
|
|
228
|
+
"aria-disabled": item.disabled,
|
|
229
|
+
"aria-haspopup": hasSubmenu ? "menu" : void 0,
|
|
230
|
+
"aria-label": item.label,
|
|
231
|
+
className: cn("size-12 absolute flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full", "border border-border-primary bg-popover-bg text-popover-text shadow-elevation-3", "hover:scale-110 hover:cursor-pointer hover:border-toggle-border hover:bg-level-three", "motion-safe:transition-[left,top,opacity,transform] motion-safe:duration-300", BOUNCE_EASE, (isHighlighted || isActive) && "border-toggle-border bg-level-three", isHighlighted && "scale-110", item.destructive === true && "text-danger-300", item.disabled === true && "pointer-events-none hover:scale-100", nonInteractive && "pointer-events-none"),
|
|
232
|
+
"data-testid": testId,
|
|
233
|
+
disabled: item.disabled,
|
|
234
|
+
onClick,
|
|
235
|
+
role: "menuitem",
|
|
236
|
+
style: {
|
|
237
|
+
left: x,
|
|
238
|
+
opacity,
|
|
239
|
+
top: y,
|
|
240
|
+
transitionDelay: `${delay}ms`
|
|
241
|
+
},
|
|
242
|
+
type: "button",
|
|
243
|
+
children: [item.icon, hasSubmenu && /* @__PURE__ */ jsx("span", {
|
|
244
|
+
"aria-hidden": true,
|
|
245
|
+
className: "size-4 -right-0.5 -top-0.5 font-semibold absolute flex items-center justify-center rounded-full border border-border-primary bg-level-four text-[9px] leading-none text-text-primary tabular-nums",
|
|
246
|
+
"data-testid": `${testId}-submenu-count`,
|
|
247
|
+
children: item.items?.length
|
|
248
|
+
})]
|
|
249
|
+
});
|
|
250
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [item.description ? /* @__PURE__ */ jsxs(Tooltip, {
|
|
251
|
+
delayDuration: 400,
|
|
252
|
+
children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
253
|
+
asChild: true,
|
|
254
|
+
children: circle
|
|
255
|
+
}), /* @__PURE__ */ jsx(TooltipContent, { children: item.description })]
|
|
256
|
+
}) : circle, /* @__PURE__ */ jsx("span", {
|
|
257
|
+
"aria-hidden": true,
|
|
258
|
+
className: cn("w-20 font-medium leading-tight pointer-events-none absolute -translate-x-1/2 text-center text-[10px]", LABEL_SHADOW, "motion-safe:transition-[left,top,opacity] motion-safe:duration-300", BOUNCE_EASE, item.destructive === true ? "text-danger-300" : "text-text-primary"),
|
|
259
|
+
"data-testid": `${testId}-label`,
|
|
260
|
+
style: {
|
|
261
|
+
left: x,
|
|
262
|
+
opacity,
|
|
263
|
+
top: y + LABEL_OFFSET,
|
|
264
|
+
transitionDelay: `${delay}ms`
|
|
265
|
+
},
|
|
266
|
+
children: item.label
|
|
267
|
+
})] }, item.id);
|
|
268
|
+
};
|
|
269
|
+
return createPortal(/* @__PURE__ */ jsx("div", {
|
|
270
|
+
className: "inset-0 fixed z-50 motion-safe:duration-150 motion-safe:animate-in motion-safe:fade-in-0",
|
|
271
|
+
"data-testid": resolvedTestId,
|
|
272
|
+
onContextMenu: (event) => {
|
|
273
|
+
event.preventDefault();
|
|
274
|
+
},
|
|
275
|
+
onPointerDown: (event) => {
|
|
276
|
+
if (event.target === event.currentTarget) onClose();
|
|
277
|
+
},
|
|
278
|
+
ref,
|
|
279
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
280
|
+
"aria-label": ariaLabel,
|
|
281
|
+
className: cn("focus-visible:ring-ring absolute origin-center focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none", className),
|
|
282
|
+
"data-testid": `${resolvedTestId}-menu`,
|
|
283
|
+
onKeyDown: handleKeyDown,
|
|
284
|
+
ref: containerRef,
|
|
285
|
+
role: "menu",
|
|
286
|
+
style: {
|
|
287
|
+
left: cx,
|
|
288
|
+
top: cy
|
|
289
|
+
},
|
|
290
|
+
tabIndex: -1,
|
|
291
|
+
children: [
|
|
292
|
+
!inSubmenu && /* @__PURE__ */ jsx("span", {
|
|
293
|
+
"aria-hidden": true,
|
|
294
|
+
className: "size-1.5 absolute -translate-x-1/2 -translate-y-1/2 rounded-full bg-text-secondary opacity-60",
|
|
295
|
+
"data-testid": `${resolvedTestId}-center`
|
|
296
|
+
}),
|
|
297
|
+
backSkin !== null && renderSpoke({
|
|
298
|
+
isActive: true,
|
|
299
|
+
item: backSkin.item,
|
|
300
|
+
nonInteractive: !inSubmenu,
|
|
301
|
+
onClick: goBack,
|
|
302
|
+
opacity: inSubmenu ? 1 : 0,
|
|
303
|
+
testId: `${resolvedTestId}-back`,
|
|
304
|
+
x: backSkin.offset.x,
|
|
305
|
+
y: backSkin.offset.y
|
|
306
|
+
}),
|
|
307
|
+
activeItems.map((item, index) => {
|
|
308
|
+
const offset = inSubmenu ? positionOnArc(index, activeItems.length, ringRadius) : positionForIndex(index, activeItems.length, ringRadius);
|
|
309
|
+
const settled = expanded || item.id === returningId;
|
|
310
|
+
return renderSpoke({
|
|
311
|
+
delay: item.id === returningId ? 0 : expanded ? index * 25 : 0,
|
|
312
|
+
isHighlighted: index === highlightIndex,
|
|
313
|
+
item,
|
|
314
|
+
onClick: () => {
|
|
315
|
+
activate(item);
|
|
316
|
+
},
|
|
317
|
+
opacity: settled ? item.disabled === true ? .4 : 1 : 0,
|
|
318
|
+
testId: `${resolvedTestId}-item`,
|
|
319
|
+
x: settled ? base.x + offset.x : spreadOrigin.x,
|
|
320
|
+
y: settled ? base.y + offset.y : spreadOrigin.y
|
|
321
|
+
});
|
|
322
|
+
})
|
|
323
|
+
]
|
|
324
|
+
})
|
|
325
|
+
}), document.body);
|
|
326
|
+
};
|
|
327
|
+
RadialMenu.displayName = "RadialMenu";
|
|
328
|
+
|
|
329
|
+
//#endregion
|
|
330
|
+
export { RadialMenu };
|
|
331
|
+
//# sourceMappingURL=RadialMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RadialMenu.js","names":[],"sources":["../src/components/RadialMenu/RadialMenu.tsx"],"sourcesContent":["import { ChevronDownIcon } from '@components/Icons'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@components/Tooltip/Tooltip'\nimport { cn } from '@utils/twUtils'\nimport { Fragment, useCallback, useEffect, useMemo, useRef, useState, type ReactNode, type Ref } from 'react'\nimport { createPortal } from 'react-dom'\n\nexport interface RadialMenuItem {\n /** Optional longer description shown in a tooltip on hover, since labels are kept short. */\n description?: string\n destructive?: boolean\n disabled?: boolean\n icon: ReactNode\n id: string\n items?: RadialMenuItem[]\n label: string\n onSelect?: () => void\n}\n\nexport interface RadialMenuProps {\n ariaLabel: string\n backLabel?: string\n className?: string\n dataTestId?: string\n items: RadialMenuItem[]\n onClose: () => void\n position: { x: number; y: number } | null\n}\n\nconst BOUNCE_EASE = 'motion-safe:ease-[cubic-bezier(0.34,1.56,0.64,1)]'\n// Stacked soft shadows form a dense-but-soft halo so labels stay legible over any background.\nconst LABEL_SHADOW =\n '[text-shadow:0_0_5px_var(--color-text-inverted),0_0_5px_var(--color-text-inverted),0_0_10px_var(--color-text-inverted),0_0_10px_var(--color-text-inverted),0_0_16px_var(--color-text-inverted),0_0_16px_var(--color-text-inverted),0_0_22px_var(--color-text-inverted)]'\nconst CLOSE_MS = 260\nconst LEVEL_MS = 200\nconst LABEL_OFFSET = 30\nconst PRIMARY_RADIUS = 70\nconst SUB_RADIUS = 96\nconst ITEM_REACH = 44\nconst VIEWPORT_MARGIN = 16\n\n// When the menu is larger than the viewport (min > max), center it; otherwise clamp normally.\nconst clamp = (value: number, min: number, max: number) => (min > max ? (min + max) / 2 : Math.min(Math.max(value, min), max))\n\n// Double rAF so the collapsed \"from\" state paints before the transition target is applied.\nconst runAfterPaint = (callback: () => void) => {\n let inner = 0\n const outer = requestAnimationFrame(() => {\n inner = requestAnimationFrame(callback)\n })\n return () => {\n cancelAnimationFrame(outer)\n cancelAnimationFrame(inner)\n }\n}\n\nconst positionForIndex = (index: number, count: number, radius: number) => {\n const angle = -Math.PI / 2 + (index * 2 * Math.PI) / count\n return { x: Math.cos(angle) * radius, y: Math.sin(angle) * radius }\n}\n\n// Fanned across an arc centered straight up, so a sub-ring arches above its parent.\nconst SUB_ARC_CENTER = -Math.PI / 2\nconst SUB_ARC_SPAN = Math.PI * 0.7\nconst positionOnArc = (index: number, count: number, radius: number) => {\n const angle = count <= 1 ? SUB_ARC_CENTER : SUB_ARC_CENTER - SUB_ARC_SPAN / 2 + (index / (count - 1)) * SUB_ARC_SPAN\n return { x: Math.cos(angle) * radius, y: Math.sin(angle) * radius }\n}\n\nexport const RadialMenu = ({ ariaLabel, backLabel = 'Back', className, dataTestId, items, onClose, position, ref }: RadialMenuProps & { ref?: Ref<HTMLDivElement> }) => {\n const resolvedTestId = dataTestId ?? 'spectral-radial-menu'\n const containerRef = useRef<HTMLDivElement>(null)\n const levelTimersRef = useRef<number[]>([])\n const [activeSubmenuId, setActiveSubmenuId] = useState<string | null>(null)\n const [highlightIndex, setHighlightIndex] = useState(-1)\n // Items animate between `spreadOrigin` (collapsed) and `base + ring offset` (expanded).\n const [renderCenter, setRenderCenter] = useState(position)\n const [expanded, setExpanded] = useState(false)\n const [spreadOrigin, setSpreadOrigin] = useState<{ x: number; y: number }>({ x: 0, y: 0 })\n // Parent re-skinned as a back control, kept mounted so it swaps cleanly with the real item.\n const [backSkin, setBackSkin] = useState<{ item: RadialMenuItem; offset: { x: number; y: number } } | null>(null)\n // The returned item appears instantly at its spot (swapping in for the chevron) rather than fading.\n const [returningId, setReturningId] = useState<string | null>(null)\n\n const clearLevelTimers = useCallback(() => {\n levelTimersRef.current.forEach((id) => clearTimeout(id))\n levelTimersRef.current = []\n }, [])\n\n useEffect(() => {\n // Cancel any in-flight level-change timers so a stale callback can't mutate a new cycle.\n clearLevelTimers()\n if (position !== null) {\n setRenderCenter(position)\n setActiveSubmenuId(null)\n setHighlightIndex(-1)\n setSpreadOrigin({ x: 0, y: 0 })\n setBackSkin(null)\n setReturningId(null)\n setExpanded(false)\n return runAfterPaint(() => {\n setExpanded(true)\n containerRef.current?.focus()\n })\n }\n setExpanded(false)\n // Collapse to the center, not the lingering sub-ring origin, so close mirrors open.\n setSpreadOrigin({ x: 0, y: 0 })\n const timer = setTimeout(() => {\n setRenderCenter(null)\n setBackSkin(null)\n }, CLOSE_MS)\n return () => {\n clearTimeout(timer)\n }\n }, [clearLevelTimers, position])\n\n useEffect(() => {\n if (position === null) {\n return () => {}\n }\n window.addEventListener('scroll', onClose, true)\n window.addEventListener('resize', onClose)\n return () => {\n window.removeEventListener('scroll', onClose, true)\n window.removeEventListener('resize', onClose)\n }\n }, [position, onClose])\n\n const renderCenterRef = useRef(renderCenter)\n renderCenterRef.current = renderCenter\n useEffect(() => {\n if (renderCenterRef.current === null) {\n return () => {}\n }\n return runAfterPaint(() => {\n setExpanded(true)\n })\n }, [activeSubmenuId])\n\n useEffect(() => clearLevelTimers, [clearLevelTimers])\n\n const activeItems = useMemo(() => {\n if (activeSubmenuId === null) return items\n return items.find((item) => item.id === activeSubmenuId)?.items ?? items\n }, [activeSubmenuId, items])\n\n const activate = useCallback(\n (item: RadialMenuItem) => {\n if (item.disabled === true) return\n if (item.items && item.items.length > 0) {\n clearLevelTimers()\n const index = items.findIndex((candidate) => candidate.id === item.id)\n const offset = positionForIndex(index, items.length, PRIMARY_RADIUS)\n setSpreadOrigin(offset)\n setReturningId(null)\n setBackSkin({\n item: {\n ...item,\n description: undefined,\n icon: (\n <ChevronDownIcon\n className='rotate-90'\n size={20}\n />\n ),\n id: `${item.id}__back`,\n items: undefined,\n label: backLabel,\n },\n offset,\n })\n setActiveSubmenuId(item.id)\n setHighlightIndex(-1)\n setExpanded(false)\n return\n }\n item.onSelect?.()\n onClose()\n },\n [backLabel, clearLevelTimers, items, onClose],\n )\n\n const goBack = useCallback(() => {\n const returningSubmenuId = activeSubmenuId\n const index = items.findIndex((candidate) => candidate.id === returningSubmenuId)\n setSpreadOrigin(index >= 0 ? positionForIndex(index, items.length, PRIMARY_RADIUS) : { x: 0, y: 0 })\n setExpanded(false)\n setHighlightIndex(-1)\n clearLevelTimers()\n levelTimersRef.current = [\n window.setTimeout(() => {\n if (renderCenterRef.current === null) return\n setActiveSubmenuId(null)\n setBackSkin(null)\n setReturningId(returningSubmenuId)\n }, LEVEL_MS),\n window.setTimeout(() => {\n if (renderCenterRef.current !== null) {\n setReturningId(null)\n }\n }, LEVEL_MS + 350),\n ]\n }, [activeSubmenuId, clearLevelTimers, items])\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n const count = activeItems.length\n if (count === 0) return\n\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowDown': {\n event.preventDefault()\n setHighlightIndex((index) => (index < 0 ? 0 : (index + 1) % count))\n break\n }\n case 'ArrowLeft':\n case 'ArrowUp': {\n event.preventDefault()\n setHighlightIndex((index) => (index < 0 ? count - 1 : (index - 1 + count) % count))\n break\n }\n case 'Enter':\n case ' ': {\n event.preventDefault()\n const item = activeItems[highlightIndex]\n if (item) activate(item)\n break\n }\n case 'Escape': {\n event.preventDefault()\n if (activeSubmenuId === null) {\n onClose()\n } else {\n goBack()\n }\n break\n }\n case 'Tab': {\n event.preventDefault()\n break\n }\n default: {\n break\n }\n }\n },\n [activate, activeItems, activeSubmenuId, goBack, highlightIndex, onClose],\n )\n\n if (renderCenter === null || typeof document === 'undefined') {\n return null\n }\n\n const inSubmenu = activeSubmenuId !== null\n const parentIndex = inSubmenu ? items.findIndex((item) => item.id === activeSubmenuId) : -1\n const parentItem = parentIndex >= 0 ? (items[parentIndex] ?? null) : null\n const base = parentItem === null ? { x: 0, y: 0 } : positionForIndex(parentIndex, items.length, PRIMARY_RADIUS)\n const ringRadius = inSubmenu ? SUB_RADIUS : PRIMARY_RADIUS\n\n const reach = (inSubmenu ? PRIMARY_RADIUS + SUB_RADIUS : PRIMARY_RADIUS) + ITEM_REACH\n const cx = clamp(renderCenter.x, reach + VIEWPORT_MARGIN, window.innerWidth - reach - VIEWPORT_MARGIN)\n const cy = clamp(renderCenter.y, reach + VIEWPORT_MARGIN, window.innerHeight - reach - VIEWPORT_MARGIN)\n\n const renderSpoke = (options: { delay?: number; isActive?: boolean; isHighlighted?: boolean; item: RadialMenuItem; nonInteractive?: boolean; onClick: () => void; opacity: number; testId: string; x: number; y: number }) => {\n const { delay = 0, isActive = false, isHighlighted = false, item, nonInteractive = false, onClick, opacity, testId, x, y } = options\n const hasSubmenu = Boolean(item.items && item.items.length > 0)\n const circle = (\n <button\n aria-disabled={item.disabled}\n aria-haspopup={hasSubmenu ? 'menu' : undefined}\n aria-label={item.label}\n className={cn(\n 'size-12 absolute flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full',\n 'border border-border-primary bg-popover-bg text-popover-text shadow-elevation-3',\n 'hover:scale-110 hover:cursor-pointer hover:border-toggle-border hover:bg-level-three',\n 'motion-safe:transition-[left,top,opacity,transform] motion-safe:duration-300',\n BOUNCE_EASE,\n (isHighlighted || isActive) && 'border-toggle-border bg-level-three',\n isHighlighted && 'scale-110',\n item.destructive === true && 'text-danger-300',\n item.disabled === true && 'pointer-events-none hover:scale-100',\n nonInteractive && 'pointer-events-none',\n )}\n data-testid={testId}\n disabled={item.disabled}\n onClick={onClick}\n role='menuitem'\n style={{ left: x, opacity, top: y, transitionDelay: `${delay}ms` }}\n type='button'\n >\n {item.icon}\n {hasSubmenu && (\n <span\n aria-hidden\n className='size-4 -right-0.5 -top-0.5 font-semibold absolute flex items-center justify-center rounded-full border border-border-primary bg-level-four text-[9px] leading-none text-text-primary tabular-nums'\n data-testid={`${testId}-submenu-count`}\n >\n {item.items?.length}\n </span>\n )}\n </button>\n )\n return (\n <Fragment key={item.id}>\n {item.description ? (\n <Tooltip delayDuration={400}>\n <TooltipTrigger asChild>{circle}</TooltipTrigger>\n <TooltipContent>{item.description}</TooltipContent>\n </Tooltip>\n ) : (\n circle\n )}\n <span\n aria-hidden\n className={cn(\n 'w-20 font-medium leading-tight pointer-events-none absolute -translate-x-1/2 text-center text-[10px]',\n LABEL_SHADOW,\n 'motion-safe:transition-[left,top,opacity] motion-safe:duration-300',\n BOUNCE_EASE,\n item.destructive === true ? 'text-danger-300' : 'text-text-primary',\n )}\n data-testid={`${testId}-label`}\n style={{ left: x, opacity, top: y + LABEL_OFFSET, transitionDelay: `${delay}ms` }}\n >\n {item.label}\n </span>\n </Fragment>\n )\n }\n\n return createPortal(\n <div\n className='inset-0 fixed z-50 motion-safe:duration-150 motion-safe:animate-in motion-safe:fade-in-0'\n data-testid={resolvedTestId}\n onContextMenu={(event) => {\n event.preventDefault()\n }}\n onPointerDown={(event) => {\n if (event.target === event.currentTarget) {\n onClose()\n }\n }}\n ref={ref}\n >\n <div\n aria-label={ariaLabel}\n className={cn('focus-visible:ring-ring absolute origin-center focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none', className)}\n data-testid={`${resolvedTestId}-menu`}\n onKeyDown={handleKeyDown}\n ref={containerRef}\n role='menu'\n style={{ left: cx, top: cy }}\n tabIndex={-1}\n >\n {!inSubmenu && (\n <span\n aria-hidden\n className='size-1.5 absolute -translate-x-1/2 -translate-y-1/2 rounded-full bg-text-secondary opacity-60'\n data-testid={`${resolvedTestId}-center`}\n />\n )}\n {backSkin !== null &&\n renderSpoke({\n isActive: true,\n item: backSkin.item,\n nonInteractive: !inSubmenu,\n onClick: goBack,\n opacity: inSubmenu ? 1 : 0,\n testId: `${resolvedTestId}-back`,\n x: backSkin.offset.x,\n y: backSkin.offset.y,\n })}\n {activeItems.map((item, index) => {\n const offset = inSubmenu ? positionOnArc(index, activeItems.length, ringRadius) : positionForIndex(index, activeItems.length, ringRadius)\n const settled = expanded || item.id === returningId\n return renderSpoke({\n delay: item.id === returningId ? 0 : expanded ? index * 25 : 0,\n isHighlighted: index === highlightIndex,\n item,\n onClick: () => {\n activate(item)\n },\n opacity: settled ? (item.disabled === true ? 0.4 : 1) : 0,\n testId: `${resolvedTestId}-item`,\n x: settled ? base.x + offset.x : spreadOrigin.x,\n y: settled ? base.y + offset.y : spreadOrigin.y,\n })\n })}\n </div>\n </div>,\n document.body,\n )\n}\n\nRadialMenu.displayName = 'RadialMenu'\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { Accordion, AccordionProps } from "./Accordion.js";
|
|
3
3
|
import { Alert, AlertProps } from "./Alert.js";
|
|
4
|
+
import { AlertDialog, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPopup, AlertDialogPopupProps, AlertDialogProps, AlertDialogTitle, AlertDialogTrigger, AlertDialogTriggerProps } from "./AlertDialog.js";
|
|
4
5
|
import { Avatar, AvatarProps } from "./Avatar.js";
|
|
5
6
|
import { Badge, BadgeProps } from "./Badge.js";
|
|
6
7
|
import { Button, ButtonProps } from "./Button.js";
|
|
@@ -110,6 +111,7 @@ import { Kbd, KbdGroup, KbdGroupProps, KbdProps, KbdSymbol } from "./Kbd.js";
|
|
|
110
111
|
import { Label, LabelProps } from "./Label.js";
|
|
111
112
|
import { MultiSelect, MultiSelectProps } from "./MultiSelect.js";
|
|
112
113
|
import { Popover, PopoverAnchor, PopoverContent, PopoverContentProps, PopoverTrigger } from "./Popover.js";
|
|
114
|
+
import { RadialMenu, RadialMenuItem, RadialMenuProps } from "./RadialMenu.js";
|
|
113
115
|
import { RadioButton, RadioButtonProps } from "./RadioButton.js";
|
|
114
116
|
import { RadioButtonGroup, RadioButtonGroupItem, RadioButtonGroupItemProps, RadioButtonGroupProps } from "./RadioButtonGroup.js";
|
|
115
117
|
import { RadioGroup, RadioGroupItem, RadioGroupItemProps, RadioGroupProps } from "./RadioGroup.js";
|
|
@@ -132,4 +134,4 @@ import { useControllableState } from "./hooks/useControllableState.js";
|
|
|
132
134
|
import { useUncontrolledState } from "./hooks/useUncontrolledState.js";
|
|
133
135
|
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea } from "./primitives/input-group.js";
|
|
134
136
|
import { cn } from "./utils/twUtils.js";
|
|
135
|
-
export { Accordion, type AccordionProps, AdjustmentsIcon, Alert, type AlertProps, AnalyzeIcon, AnnotationsIcon, ApprovedIcon, ArrowDownIcon, ArrowUpIcon, Avatar, type AvatarProps, Badge, type BadgeProps, BoxToolIcon, Button, ButtonGroup, ButtonGroupItem, type ButtonGroupProps, ButtonGroupSeparator, ButtonIcon, type ButtonIconProps, ButtonIconSlideout, type ButtonIconSlideoutProps, type ButtonProps, CalendarIcon, CheckCircleIcon, CheckSquareIcon, Checkbox, type CheckboxProps, CheckmarkIcon, ChevronDownIcon, ChevronUpIcon, ClockIcon, CloseCircleIcon, CloseIcon, Combobox, type ComboboxOption, type ComboboxProps, ControlGroupSelect, type ControlGroupSelectCaptionLayout, type ControlGroupSelectProps, Crosshairs2Icon, CrosshairsIcon, DashboardIcon, DataCard, type DataCardProps, DatabaseIcon, DateTimePicker, type DateTimePickerProps, DeleteIcon, Dialog, Drawer, type DrawerProps, DurationIcon, EditIcon, EmailIcon, EraserIcon, ErrorIcon, ErrorMessage, EyeClosedIcon, EyeClosedIcon2, EyeOpenIcon, FileDownloadIcon, type FormFieldMessageValue, GoToFirstIcon, GoToLastIcon, HarmonicCursorsIcon, HoverCard, HoverCardContent, type HoverCardProps, HoverCardTrigger, IconBase, InfoIcon, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputNumeric, type InputNumericProps, InputOTP, type InputOTPBaseProps, type InputOTPProps, type InputProps, InputSearch, type InputSearchOption, type InputSearchProps, Kbd, KbdGroup, type KbdGroupProps, type KbdProps, type KbdSymbol, KeyboardIcon, Label, LabelIcon, type LabelProps, LassoIcon, LineToolIcon, LinkIcon, LiveViewIcon, LoaderIcon, LocationIcon, LogoutIcon, MaximizeIcon, MeasureIcon, MenuDotsIcon, MenuIcon, MessagesIcon, MetadataIcon, MinimizeIcon, MinusIcon, MultiSelect, type MultiSelectProps, OntologyIcon, PanelIconClose, PanelIconOpen, PauseIcon, PlayIcon, PlusIcon, PolygonIcon, Popover, PopoverAnchor, PopoverContent, type PopoverContentProps, PopoverTrigger, PrinterIcon, ProgressCheckIcon, RadioButton, RadioButtonGroup, RadioButtonGroupItem, type RadioButtonGroupItemProps, type RadioButtonGroupProps, type RadioButtonProps, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, ResetIcon, ReviewedIcon, ScissorsIcon, SearchIcon, Select, type SelectExtendedProps, type SelectProps, Separator, type SeparatorProps, SettingsIcon, Skeleton, Slider, type SliderProps, SortAscendingIcon, SortAtoZIcon, SortDescendingIcon, SortZtoAIcon, SparklesIcon, SpectralProvider, type SpectralProviderProps, StackIcon, StarIcon, SvgIdContext, Switch, type SwitchProps, SyncIcon, SyncOffIcon, Tabs, type TabsProps, Textarea, type TextareaProps, Toast, type ToastProps, Toggle, ToggleGroup, ToggleGroupItem, type ToggleGroupItemProps, type ToggleGroupProps, ToggleGroupSplitMenuItem, type ToggleGroupSplitMenuItemProps, type ToggleProps, Tooltip, TooltipContent, TooltipTrigger, TrashIcon, Tray, type TrayBaseProps, type TrayBodyProps, type TrayContentProps, UndoIcon, UnlinkIcon, UploadIcon, User2Icon, UserIcon, WarningIcon, WarningMessage, ZoomAllIcon, ZoomXIcon, ZoomYIcon, cn, toast, useAccordionAutoScroll, useControllableState, useUncontrolledState };
|
|
137
|
+
export { Accordion, type AccordionProps, AdjustmentsIcon, Alert, AlertDialog, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPopup, type AlertDialogPopupProps, type AlertDialogProps, AlertDialogTitle, AlertDialogTrigger, type AlertDialogTriggerProps, type AlertProps, AnalyzeIcon, AnnotationsIcon, ApprovedIcon, ArrowDownIcon, ArrowUpIcon, Avatar, type AvatarProps, Badge, type BadgeProps, BoxToolIcon, Button, ButtonGroup, ButtonGroupItem, type ButtonGroupProps, ButtonGroupSeparator, ButtonIcon, type ButtonIconProps, ButtonIconSlideout, type ButtonIconSlideoutProps, type ButtonProps, CalendarIcon, CheckCircleIcon, CheckSquareIcon, Checkbox, type CheckboxProps, CheckmarkIcon, ChevronDownIcon, ChevronUpIcon, ClockIcon, CloseCircleIcon, CloseIcon, Combobox, type ComboboxOption, type ComboboxProps, ControlGroupSelect, type ControlGroupSelectCaptionLayout, type ControlGroupSelectProps, Crosshairs2Icon, CrosshairsIcon, DashboardIcon, DataCard, type DataCardProps, DatabaseIcon, DateTimePicker, type DateTimePickerProps, DeleteIcon, Dialog, Drawer, type DrawerProps, DurationIcon, EditIcon, EmailIcon, EraserIcon, ErrorIcon, ErrorMessage, EyeClosedIcon, EyeClosedIcon2, EyeOpenIcon, FileDownloadIcon, type FormFieldMessageValue, GoToFirstIcon, GoToLastIcon, HarmonicCursorsIcon, HoverCard, HoverCardContent, type HoverCardProps, HoverCardTrigger, IconBase, InfoIcon, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputNumeric, type InputNumericProps, InputOTP, type InputOTPBaseProps, type InputOTPProps, type InputProps, InputSearch, type InputSearchOption, type InputSearchProps, Kbd, KbdGroup, type KbdGroupProps, type KbdProps, type KbdSymbol, KeyboardIcon, Label, LabelIcon, type LabelProps, LassoIcon, LineToolIcon, LinkIcon, LiveViewIcon, LoaderIcon, LocationIcon, LogoutIcon, MaximizeIcon, MeasureIcon, MenuDotsIcon, MenuIcon, MessagesIcon, MetadataIcon, MinimizeIcon, MinusIcon, MultiSelect, type MultiSelectProps, OntologyIcon, PanelIconClose, PanelIconOpen, PauseIcon, PlayIcon, PlusIcon, PolygonIcon, Popover, PopoverAnchor, PopoverContent, type PopoverContentProps, PopoverTrigger, PrinterIcon, ProgressCheckIcon, RadialMenu, type RadialMenuItem, type RadialMenuProps, RadioButton, RadioButtonGroup, RadioButtonGroupItem, type RadioButtonGroupItemProps, type RadioButtonGroupProps, type RadioButtonProps, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, ResetIcon, ReviewedIcon, ScissorsIcon, SearchIcon, Select, type SelectExtendedProps, type SelectProps, Separator, type SeparatorProps, SettingsIcon, Skeleton, Slider, type SliderProps, SortAscendingIcon, SortAtoZIcon, SortDescendingIcon, SortZtoAIcon, SparklesIcon, SpectralProvider, type SpectralProviderProps, StackIcon, StarIcon, SvgIdContext, Switch, type SwitchProps, SyncIcon, SyncOffIcon, Tabs, type TabsProps, Textarea, type TextareaProps, Toast, type ToastProps, Toggle, ToggleGroup, ToggleGroupItem, type ToggleGroupItemProps, type ToggleGroupProps, ToggleGroupSplitMenuItem, type ToggleGroupSplitMenuItemProps, type ToggleProps, Tooltip, TooltipContent, TooltipTrigger, TrashIcon, Tray, type TrayBaseProps, type TrayBodyProps, type TrayContentProps, UndoIcon, UnlinkIcon, UploadIcon, User2Icon, UserIcon, WarningIcon, WarningMessage, ZoomAllIcon, ZoomXIcon, ZoomYIcon, cn, toast, useAccordionAutoScroll, useControllableState, useUncontrolledState };
|
package/dist/index.js
CHANGED
|
@@ -88,9 +88,10 @@ import { useAccordionAutoScroll } from "./hooks/useAccordionAutoScroll.js";
|
|
|
88
88
|
import { cn } from "./utils/twUtils.js";
|
|
89
89
|
import { Accordion } from "./Accordion.js";
|
|
90
90
|
import { Alert } from "./Alert.js";
|
|
91
|
+
import { Button } from "./Button.js";
|
|
92
|
+
import { AlertDialog, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPopup, AlertDialogTitle, AlertDialogTrigger } from "./AlertDialog.js";
|
|
91
93
|
import { Avatar } from "./Avatar.js";
|
|
92
94
|
import { Badge } from "./Badge.js";
|
|
93
|
-
import { Button } from "./Button.js";
|
|
94
95
|
import { Separator } from "./Separator.js";
|
|
95
96
|
import { ButtonGroup, ButtonGroupItem, ButtonGroupSeparator } from "./ButtonGroup.js";
|
|
96
97
|
import { ButtonIcon } from "./ButtonIcon.js";
|
|
@@ -116,6 +117,8 @@ import { InputOTP } from "./InputOTP.js";
|
|
|
116
117
|
import { InputSearch } from "./InputSearch.js";
|
|
117
118
|
import { Kbd, KbdGroup } from "./Kbd.js";
|
|
118
119
|
import { MultiSelect } from "./MultiSelect.js";
|
|
120
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "./Tooltip.js";
|
|
121
|
+
import { RadialMenu } from "./RadialMenu.js";
|
|
119
122
|
import { RadioButtonGroup, RadioButtonGroupItem } from "./RadioButtonGroup.js";
|
|
120
123
|
import { RadioButton } from "./RadioButton.js";
|
|
121
124
|
import { RadioGroup, RadioGroupItem } from "./RadioGroup.js";
|
|
@@ -130,7 +133,6 @@ import { Toggle } from "./Toggle.js";
|
|
|
130
133
|
import { ToggleGroupItem } from "./ToggleGroup/ToggleGroupItem.js";
|
|
131
134
|
import { ToggleGroupSplitMenuItem } from "./ToggleGroup/ToggleGroupSplitMenuItem.js";
|
|
132
135
|
import { ToggleGroup } from "./ToggleGroup.js";
|
|
133
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from "./Tooltip.js";
|
|
134
136
|
import { Tray } from "./Tray.js";
|
|
135
137
|
|
|
136
|
-
export { Accordion, AdjustmentsIcon, Alert, AnalyzeIcon, AnnotationsIcon, ApprovedIcon, ArrowDownIcon, ArrowUpIcon, Avatar, Badge, BoxToolIcon, Button, ButtonGroup, ButtonGroupItem, ButtonGroupSeparator, ButtonIcon, ButtonIconSlideout, CalendarIcon, CheckCircleIcon, CheckSquareIcon, Checkbox, CheckmarkIcon, ChevronDownIcon, ChevronUpIcon, ClockIcon, CloseCircleIcon, CloseIcon, Combobox, ControlGroupSelect, Crosshairs2Icon, CrosshairsIcon, DashboardIcon, DataCard, DatabaseIcon, DateTimePicker, DeleteIcon, Dialog, Drawer, DurationIcon, EditIcon, EmailIcon, EraserIcon, ErrorIcon, ErrorMessage, EyeClosedIcon, EyeClosedIcon2, EyeOpenIcon, FileDownloadIcon, GoToFirstIcon, GoToLastIcon, HarmonicCursorsIcon, HoverCard, HoverCardContent, HoverCardTrigger, IconBase, InfoIcon, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputNumeric, InputOTP, InputSearch, Kbd, KbdGroup, KeyboardIcon, Label, LabelIcon, LassoIcon, LineToolIcon, LinkIcon, LiveViewIcon, LoaderIcon, LocationIcon, LogoutIcon, MaximizeIcon, MeasureIcon, MenuDotsIcon, MenuIcon, MessagesIcon, MetadataIcon, MinimizeIcon, MinusIcon, MultiSelect, OntologyIcon, PanelIconClose, PanelIconOpen, PauseIcon, PlayIcon, PlusIcon, PolygonIcon, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PrinterIcon, ProgressCheckIcon, RadioButton, RadioButtonGroup, RadioButtonGroupItem, RadioGroup, RadioGroupItem, ResetIcon, ReviewedIcon, ScissorsIcon, SearchIcon, Select, Separator, SettingsIcon, Skeleton, Slider, SortAscendingIcon, SortAtoZIcon, SortDescendingIcon, SortZtoAIcon, SparklesIcon, SpectralProvider, StackIcon, StarIcon, SvgIdContext, Switch, SyncIcon, SyncOffIcon, Tabs, Textarea, Toast, Toggle, ToggleGroup, ToggleGroupItem, ToggleGroupSplitMenuItem, Tooltip, TooltipContent, TooltipTrigger, TrashIcon, Tray, UndoIcon, UnlinkIcon, UploadIcon, User2Icon, UserIcon, WarningIcon, WarningMessage, ZoomAllIcon, ZoomXIcon, ZoomYIcon, cn, toast, useAccordionAutoScroll, useControllableState, useUncontrolledState };
|
|
138
|
+
export { Accordion, AdjustmentsIcon, Alert, AlertDialog, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPopup, AlertDialogTitle, AlertDialogTrigger, AnalyzeIcon, AnnotationsIcon, ApprovedIcon, ArrowDownIcon, ArrowUpIcon, Avatar, Badge, BoxToolIcon, Button, ButtonGroup, ButtonGroupItem, ButtonGroupSeparator, ButtonIcon, ButtonIconSlideout, CalendarIcon, CheckCircleIcon, CheckSquareIcon, Checkbox, CheckmarkIcon, ChevronDownIcon, ChevronUpIcon, ClockIcon, CloseCircleIcon, CloseIcon, Combobox, ControlGroupSelect, Crosshairs2Icon, CrosshairsIcon, DashboardIcon, DataCard, DatabaseIcon, DateTimePicker, DeleteIcon, Dialog, Drawer, DurationIcon, EditIcon, EmailIcon, EraserIcon, ErrorIcon, ErrorMessage, EyeClosedIcon, EyeClosedIcon2, EyeOpenIcon, FileDownloadIcon, GoToFirstIcon, GoToLastIcon, HarmonicCursorsIcon, HoverCard, HoverCardContent, HoverCardTrigger, IconBase, InfoIcon, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputNumeric, InputOTP, InputSearch, Kbd, KbdGroup, KeyboardIcon, Label, LabelIcon, LassoIcon, LineToolIcon, LinkIcon, LiveViewIcon, LoaderIcon, LocationIcon, LogoutIcon, MaximizeIcon, MeasureIcon, MenuDotsIcon, MenuIcon, MessagesIcon, MetadataIcon, MinimizeIcon, MinusIcon, MultiSelect, OntologyIcon, PanelIconClose, PanelIconOpen, PauseIcon, PlayIcon, PlusIcon, PolygonIcon, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PrinterIcon, ProgressCheckIcon, RadialMenu, RadioButton, RadioButtonGroup, RadioButtonGroupItem, RadioGroup, RadioGroupItem, ResetIcon, ReviewedIcon, ScissorsIcon, SearchIcon, Select, Separator, SettingsIcon, Skeleton, Slider, SortAscendingIcon, SortAtoZIcon, SortDescendingIcon, SortZtoAIcon, SparklesIcon, SpectralProvider, StackIcon, StarIcon, SvgIdContext, Switch, SyncIcon, SyncOffIcon, Tabs, Textarea, Toast, Toggle, ToggleGroup, ToggleGroupItem, ToggleGroupSplitMenuItem, Tooltip, TooltipContent, TooltipTrigger, TrashIcon, Tray, UndoIcon, UnlinkIcon, UploadIcon, User2Icon, UserIcon, WarningIcon, WarningMessage, ZoomAllIcon, ZoomXIcon, ZoomYIcon, cn, toast, useAccordionAutoScroll, useControllableState, useUncontrolledState };
|
|
@@ -73,41 +73,49 @@
|
|
|
73
73
|
--color-badge-destructive-bg: var(--horizon-color-danger-400);
|
|
74
74
|
--color-badge-destructive-border: var(--horizon-color-danger-400);
|
|
75
75
|
|
|
76
|
-
--color-button-primary-bg: var(--horizon-color-accent);
|
|
77
|
-
--color-button-primary-bg--hover: var(--horizon-color-
|
|
78
|
-
--color-button-primary-bg--disabled: var(--horizon-color-
|
|
79
|
-
--color-button-primary-
|
|
80
|
-
--color-button-primary-border
|
|
76
|
+
--color-button-primary-bg: oklch(from var(--horizon-color-accent) l c h / 0.2);
|
|
77
|
+
--color-button-primary-bg--hover: oklch(from var(--horizon-color-accent) l c h / 0.4);
|
|
78
|
+
--color-button-primary-bg--disabled: oklch(from var(--horizon-color-level-four) l c h / 0.3);
|
|
79
|
+
--color-button-primary-bg--loading: oklch(from var(--horizon-color-level-four) l c h / 0.3);
|
|
80
|
+
--color-button-primary-border: oklch(from var(--horizon-color-accent) l c h / 0.8);
|
|
81
81
|
--color-button-primary-border--disabled: var(--horizon-color-neutral-500);
|
|
82
|
-
--color-button-primary-
|
|
82
|
+
--color-button-primary-border--loading: var(--horizon-color-neutral-500);
|
|
83
|
+
--color-button-primary-text: var(--horizon-color-accent);
|
|
83
84
|
--color-button-primary-text--hover: var(--horizon-color-accent);
|
|
84
|
-
--color-button-primary-text--disabled: var(--horizon-color-neutral-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
--color-button-secondary-bg
|
|
88
|
-
--color-button-secondary-bg--
|
|
85
|
+
--color-button-primary-text--disabled: var(--horizon-color-neutral-400);
|
|
86
|
+
--color-button-primary-text--loading: var(--horizon-color-neutral-400);
|
|
87
|
+
|
|
88
|
+
--color-button-secondary-bg: var(--horizon-color-transparent);
|
|
89
|
+
--color-button-secondary-bg--hover: oklch(from var(--horizon-color-neutral-50) l c h / 0.2);
|
|
90
|
+
--color-button-secondary-bg--disabled: oklch(from var(--horizon-color-level-four) l c h / 0.3);
|
|
91
|
+
--color-button-secondary-bg--loading: var(--horizon-color-transparent);
|
|
92
|
+
--color-button-secondary-border: var(--horizon-color-neutral-50);
|
|
93
|
+
--color-button-secondary-border--hover: var(--horizon-color-neutral-50);
|
|
94
|
+
--color-button-secondary-border--disabled: var(--horizon-color-neutral-600);
|
|
95
|
+
--color-button-secondary-border--loading: var(--horizon-color-neutral-600);
|
|
89
96
|
--color-button-secondary-text: var(--horizon-color-neutral-50);
|
|
90
|
-
--color-button-secondary-text--hover: var(--horizon-color-
|
|
91
|
-
--color-button-secondary-text--disabled: var(--horizon-color-neutral-
|
|
92
|
-
--color-button-secondary-
|
|
93
|
-
--color-button-secondary-border--disabled: var(--horizon-color-neutral-500);
|
|
94
|
-
|
|
95
|
-
--color-button-outline-bg: var(--horizon-color-transparent);
|
|
96
|
-
--color-button-outline-bg--hover: var(--horizon-color-level-two);
|
|
97
|
-
--color-button-outline-text: var(--horizon-color-neutral-50);
|
|
98
|
-
--color-button-outline-text--hover: var(--horizon-color-accent);
|
|
99
|
-
--color-button-outline-text--disabled: var(--horizon-color-neutral-400);
|
|
100
|
-
--color-button-outline-border: var(--horizon-color-accent);
|
|
101
|
-
--color-button-outline-border--disabled: var(--horizon-color-neutral-400);
|
|
97
|
+
--color-button-secondary-text--hover: var(--horizon-color-neutral-50);
|
|
98
|
+
--color-button-secondary-text--disabled: var(--horizon-color-neutral-400);
|
|
99
|
+
--color-button-secondary-text--loading: var(--horizon-color-neutral-400);
|
|
102
100
|
|
|
103
101
|
--color-button-ghost-bg: var(--horizon-color-transparent);
|
|
104
102
|
--color-button-ghost-bg--hover: var(--horizon-color-level-two);
|
|
105
103
|
--color-button-ghost-text: var(--horizon-color-neutral-50);
|
|
106
104
|
--color-button-ghost-text--hover: var(--horizon-color-accent);
|
|
107
105
|
--color-button-ghost-text--disabled: var(--horizon-color-neutral-400);
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
--color-button-
|
|
106
|
+
--color-button-ghost-text--loading: var(--horizon-color-neutral-400);
|
|
107
|
+
|
|
108
|
+
--color-button-destructive-bg: oklch(from var(--horizon-color-danger-400) l c h / 0.15);
|
|
109
|
+
--color-button-destructive-bg--hover: oklch(from var(--horizon-color-danger-400) l c h / 0.3);
|
|
110
|
+
--color-button-destructive-bg--disabled: oklch(from var(--horizon-color-level-four) l c h / 0.15);
|
|
111
|
+
--color-button-destructive-bg--loading: oklch(from var(--horizon-color-level-four) l c h / 0.15);
|
|
112
|
+
--color-button-destructive-border: oklch(from var(--horizon-color-danger-400) l c h / 0.6);
|
|
113
|
+
--color-button-destructive-border--disabled: oklch(from var(--horizon-color-danger-400) l c h / 0.6);
|
|
114
|
+
--color-button-destructive-border--loading: oklch(from var(--horizon-color-danger-400) l c h / 0.6);
|
|
115
|
+
--color-button-destructive-text: var(--horizon-color-danger-400);
|
|
116
|
+
--color-button-destructive-text--hover: var(--horizon-color-danger-400);
|
|
117
|
+
--color-button-destructive-text--disabled: oklch(from var(--horizon-color-danger-400) l c h / 0.6);
|
|
118
|
+
--color-button-destructive-text--loading: oklch(from var(--horizon-color-danger-400) l c h / 0.6);
|
|
111
119
|
|
|
112
120
|
--color-checkbox-border: var(--horizon-color-neutral-100);
|
|
113
121
|
--color-checkbox-border--focus: var(--horizon-color-accent);
|