@nextlyhq/ui 0.0.2-alpha.56 → 0.0.2-alpha.57

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/index.mjs CHANGED
@@ -2111,7 +2111,7 @@ var TableSkeleton = ({
2111
2111
  ] })
2112
2112
  ] }) : /* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-[60%] max-w-[120px]" }) }, colIdx)) }, rowIdx)) })
2113
2113
  ] }) }),
2114
- !hideFooter && /* @__PURE__ */ jsx33("div", { className: "table-footer border-t border-border", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between px-2 py-4 p-4", children: [
2114
+ !hideFooter && /* @__PURE__ */ jsx33("div", { className: "table-footer border-t border-border", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between px-2 py-4", children: [
2115
2115
  /* @__PURE__ */ jsx33("div", { className: "flex items-center gap-2 text-sm", children: /* @__PURE__ */ jsx33(GrayBar, { className: "h-4 w-[120px]" }) }),
2116
2116
  /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-6", children: [
2117
2117
  /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
@@ -2136,11 +2136,353 @@ var TableSkeleton = ({
2136
2136
  };
2137
2137
  TableSkeleton.displayName = "TableSkeleton";
2138
2138
 
2139
+ // src/components/color-picker.tsx
2140
+ import { Pipette } from "lucide-react";
2141
+ import * as React9 from "react";
2142
+
2143
+ // src/lib/color/convert.ts
2144
+ var clamp01 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
2145
+ function normalizeHue(hue) {
2146
+ if (!Number.isFinite(hue)) return 0;
2147
+ const wrapped = hue % 360;
2148
+ return wrapped < 0 ? wrapped + 360 : wrapped;
2149
+ }
2150
+ function hsvToRgb({ h, s, v }) {
2151
+ const hue = normalizeHue(h);
2152
+ const sat = clamp01(s);
2153
+ const val = clamp01(v);
2154
+ const sector = hue / 60;
2155
+ const chroma = val * sat;
2156
+ const x = chroma * (1 - Math.abs(sector % 2 - 1));
2157
+ const base = val - chroma;
2158
+ let rgb;
2159
+ if (sector < 1) rgb = [chroma, x, 0];
2160
+ else if (sector < 2) rgb = [x, chroma, 0];
2161
+ else if (sector < 3) rgb = [0, chroma, x];
2162
+ else if (sector < 4) rgb = [0, x, chroma];
2163
+ else if (sector < 5) rgb = [x, 0, chroma];
2164
+ else rgb = [chroma, 0, x];
2165
+ return { r: rgb[0] + base, g: rgb[1] + base, b: rgb[2] + base };
2166
+ }
2167
+ function rgbToHsv({ r, g, b }) {
2168
+ const red = clamp01(r);
2169
+ const green = clamp01(g);
2170
+ const blue = clamp01(b);
2171
+ const max = Math.max(red, green, blue);
2172
+ const min = Math.min(red, green, blue);
2173
+ const chroma = max - min;
2174
+ let hue = 0;
2175
+ if (chroma !== 0) {
2176
+ if (max === red) hue = (green - blue) / chroma % 6;
2177
+ else if (max === green) hue = (blue - red) / chroma + 2;
2178
+ else hue = (red - green) / chroma + 4;
2179
+ hue *= 60;
2180
+ }
2181
+ return {
2182
+ h: normalizeHue(hue),
2183
+ s: max === 0 ? 0 : chroma / max,
2184
+ v: max
2185
+ };
2186
+ }
2187
+
2188
+ // src/lib/color/hex.ts
2189
+ var HEX = /^#?(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
2190
+ var clamp012 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
2191
+ function pair(channel) {
2192
+ const value = Number.isFinite(channel) ? clamp012(channel) : 0;
2193
+ return Math.round(value * 255).toString(16).padStart(2, "0");
2194
+ }
2195
+ function parseHex(input) {
2196
+ const text = input.trim();
2197
+ if (!HEX.test(text)) return null;
2198
+ const digits = text.replace("#", "");
2199
+ const short = digits.length < 6;
2200
+ const size = short ? 1 : 2;
2201
+ const channel = (index) => {
2202
+ const slice = digits.slice(index * size, index * size + size);
2203
+ return parseInt(short ? slice + slice : slice, 16) / 255;
2204
+ };
2205
+ const hasAlpha = digits.length === 4 || digits.length === 8;
2206
+ return {
2207
+ r: channel(0),
2208
+ g: channel(1),
2209
+ b: channel(2),
2210
+ alpha: hasAlpha ? channel(3) : 1
2211
+ };
2212
+ }
2213
+ function toHex(color, alpha = 1) {
2214
+ const opacity = Number.isFinite(alpha) ? clamp012(alpha) : 1;
2215
+ const opaque = `#${pair(color.r)}${pair(color.g)}${pair(color.b)}`;
2216
+ return opacity === 1 ? opaque : `${opaque}${pair(opacity)}`;
2217
+ }
2218
+
2219
+ // src/lib/color/picker-geometry.ts
2220
+ var clamp013 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
2221
+ function pointOnSurface(clientX, clientY, rect) {
2222
+ return {
2223
+ x: rect.width === 0 ? 0 : clamp013((clientX - rect.left) / rect.width),
2224
+ y: rect.height === 0 ? 0 : clamp013((clientY - rect.top) / rect.height)
2225
+ };
2226
+ }
2227
+ function saturationValueAt(point) {
2228
+ return { s: clamp013(point.x), v: 1 - clamp013(point.y) };
2229
+ }
2230
+ function surfacePointFor(s, v) {
2231
+ return { x: clamp013(s), y: 1 - clamp013(v) };
2232
+ }
2233
+ function hueAt(fraction) {
2234
+ const hue = clamp013(fraction) * 360;
2235
+ return hue >= 360 ? 0 : hue;
2236
+ }
2237
+ function huePosition(hue) {
2238
+ const wrapped = (hue % 360 + 360) % 360;
2239
+ return wrapped / 360;
2240
+ }
2241
+ function hueSliderValue(hue, max) {
2242
+ const step = Math.round(huePosition(hue) * (max + 1));
2243
+ return step > max ? max : step;
2244
+ }
2245
+
2246
+ // src/components/color-picker.tsx
2247
+ import { Fragment as Fragment2, jsx as jsx34, jsxs as jsxs13 } from "react/jsx-runtime";
2248
+ function toHsva(hex) {
2249
+ const parsed = parseHex(hex);
2250
+ if (!parsed) return { h: 0, s: 0, v: 0, a: 1 };
2251
+ const { r, g, b, alpha } = parsed;
2252
+ return { ...rgbToHsv({ r, g, b }), a: alpha };
2253
+ }
2254
+ function toHexString(hsva, withAlpha) {
2255
+ return toHex(hsvToRgb(hsva), withAlpha ? hsva.a : 1);
2256
+ }
2257
+ var HUE_MAX = 359;
2258
+ function hsvaFrom(color, alpha, currentHue) {
2259
+ const hsv = rgbToHsv(color);
2260
+ return { ...hsv, h: hsv.s === 0 ? currentHue : hsv.h, a: alpha };
2261
+ }
2262
+ var SLIDER = "h-3 w-full cursor-pointer appearance-none rounded-full";
2263
+ var CHECKERBOARD = "repeating-conic-gradient(#c8c8c8 0% 25%, #ffffff 0% 50%)";
2264
+ function eyeDropperSupported() {
2265
+ return typeof window !== "undefined" && "EyeDropper" in window;
2266
+ }
2267
+ function ColorPicker({
2268
+ color,
2269
+ onColorChange,
2270
+ swatches = [],
2271
+ onSwatchSelect,
2272
+ recentColors = [],
2273
+ showAlpha = false,
2274
+ className
2275
+ }) {
2276
+ const fieldId = React9.useId();
2277
+ const surfaceRef = React9.useRef(null);
2278
+ const [hsva, setHsva] = React9.useState(() => toHsva(color));
2279
+ const [draftHex, setDraftHex] = React9.useState(null);
2280
+ const rendered = toHexString(hsva, showAlpha);
2281
+ React9.useEffect(() => {
2282
+ const incoming = parseHex(color);
2283
+ if (incoming && toHex(incoming, showAlpha ? incoming.alpha : 1) !== rendered) {
2284
+ setHsva((prev) => hsvaFrom(incoming, incoming.alpha, prev.h));
2285
+ }
2286
+ }, [color, rendered, showAlpha]);
2287
+ const commit = (next) => {
2288
+ setHsva(next);
2289
+ setDraftHex(null);
2290
+ onColorChange(toHexString(next, showAlpha));
2291
+ };
2292
+ const trackPointer = (event) => {
2293
+ const rect = surfaceRef.current?.getBoundingClientRect();
2294
+ if (!rect) return;
2295
+ const { s, v } = saturationValueAt(
2296
+ pointOnSurface(event.clientX, event.clientY, rect)
2297
+ );
2298
+ commit({ ...hsva, s, v });
2299
+ };
2300
+ const nudge = (ds, dv) => {
2301
+ const { s, v } = saturationValueAt(
2302
+ surfacePointFor(hsva.s + ds, hsva.v + dv)
2303
+ );
2304
+ commit({ ...hsva, s, v });
2305
+ };
2306
+ const handleSurfaceKey = (event) => {
2307
+ const step = event.shiftKey ? 0.1 : 0.01;
2308
+ const moves = {
2309
+ ArrowLeft: [-step, 0],
2310
+ ArrowRight: [step, 0],
2311
+ ArrowUp: [0, step],
2312
+ ArrowDown: [0, -step]
2313
+ };
2314
+ const move = moves[event.key];
2315
+ if (!move) return;
2316
+ event.preventDefault();
2317
+ nudge(move[0], move[1]);
2318
+ };
2319
+ const [canPickFromScreen, setCanPickFromScreen] = React9.useState(false);
2320
+ React9.useEffect(() => {
2321
+ setCanPickFromScreen(eyeDropperSupported());
2322
+ }, []);
2323
+ const handle = surfacePointFor(hsva.s, hsva.v);
2324
+ const hueOnly = toHex(hsvToRgb({ h: hsva.h, s: 1, v: 1 }));
2325
+ const pickFromScreen = async () => {
2326
+ const ctor = window.EyeDropper;
2327
+ if (!ctor) return;
2328
+ let sampled;
2329
+ try {
2330
+ sampled = (await new ctor().open()).sRGBHex;
2331
+ } catch {
2332
+ return;
2333
+ }
2334
+ const parsed = parseHex(sampled);
2335
+ if (parsed) commit(hsvaFrom(parsed, hsva.a, hsva.h));
2336
+ };
2337
+ return /* @__PURE__ */ jsxs13("div", { className: cn("w-64 space-y-3", className), children: [
2338
+ /* @__PURE__ */ jsx34(
2339
+ "div",
2340
+ {
2341
+ ref: surfaceRef,
2342
+ role: "application",
2343
+ tabIndex: 0,
2344
+ "aria-label": `Saturation and brightness: ${Math.round(hsva.s * 100)}% saturation, ${Math.round(hsva.v * 100)}% brightness. Arrow keys adjust.`,
2345
+ className: "ring-offset-background focus-visible:ring-ring relative h-40 w-full cursor-crosshair touch-none rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none",
2346
+ style: {
2347
+ backgroundColor: hueOnly,
2348
+ // Value on TOP of saturation. CSS paints the first layer nearest the
2349
+ // viewer, so the reverse order lets the opaque white end of the
2350
+ // saturation ramp cover the black end of the value ramp: the
2351
+ // bottom-left corner displays white while selecting black.
2352
+ backgroundImage: "linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, transparent)"
2353
+ },
2354
+ onKeyDown: handleSurfaceKey,
2355
+ onPointerDown: (event) => {
2356
+ event.currentTarget.setPointerCapture(event.pointerId);
2357
+ trackPointer(event);
2358
+ },
2359
+ onPointerMove: (event) => {
2360
+ if (event.buttons === 1) trackPointer(event);
2361
+ },
2362
+ children: /* @__PURE__ */ jsx34(
2363
+ "span",
2364
+ {
2365
+ "aria-hidden": "true",
2366
+ className: "pointer-events-none absolute size-3 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-sm ring-1 ring-black/60",
2367
+ style: { left: `${handle.x * 100}%`, top: `${handle.y * 100}%` }
2368
+ }
2369
+ )
2370
+ }
2371
+ ),
2372
+ /* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-hue`, children: "Hue" }),
2373
+ /* @__PURE__ */ jsx34(
2374
+ "input",
2375
+ {
2376
+ id: `${fieldId}-hue`,
2377
+ type: "range",
2378
+ min: 0,
2379
+ max: HUE_MAX,
2380
+ step: 1,
2381
+ value: hueSliderValue(hsva.h, HUE_MAX),
2382
+ onChange: (event) => commit({ ...hsva, h: hueAt(+event.target.value / (HUE_MAX + 1)) }),
2383
+ className: SLIDER,
2384
+ style: {
2385
+ backgroundImage: "linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00)"
2386
+ }
2387
+ }
2388
+ ),
2389
+ showAlpha && /* @__PURE__ */ jsxs13(Fragment2, { children: [
2390
+ /* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-alpha`, children: "Opacity" }),
2391
+ /* @__PURE__ */ jsx34(
2392
+ "input",
2393
+ {
2394
+ id: `${fieldId}-alpha`,
2395
+ type: "range",
2396
+ min: 0,
2397
+ max: 100,
2398
+ step: 1,
2399
+ value: Math.round(hsva.a * 100),
2400
+ onChange: (event) => commit({ ...hsva, a: +event.target.value / 100 }),
2401
+ className: SLIDER,
2402
+ style: {
2403
+ // The ramp runs to the colour being edited, over a chequerboard,
2404
+ // so the track shows what the slider actually controls. Without
2405
+ // any background this rendered as a blank 12px strip whose only
2406
+ // label was screen-reader-only.
2407
+ backgroundImage: `linear-gradient(to right, transparent, ${toHexString({ ...hsva, a: 1 }, false)}), ${CHECKERBOARD}`,
2408
+ backgroundSize: "100% 100%, 8px 8px"
2409
+ }
2410
+ }
2411
+ )
2412
+ ] }),
2413
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
2414
+ /* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-hex`, children: "Hex colour" }),
2415
+ /* @__PURE__ */ jsx34(
2416
+ Input,
2417
+ {
2418
+ id: `${fieldId}-hex`,
2419
+ className: "font-mono",
2420
+ value: draftHex ?? rendered,
2421
+ onChange: (event) => {
2422
+ const text = event.target.value;
2423
+ setDraftHex(text);
2424
+ const parsed = parseHex(text);
2425
+ if (parsed) {
2426
+ setHsva(hsvaFrom(parsed, parsed.alpha, hsva.h));
2427
+ onColorChange(toHex(parsed, showAlpha ? parsed.alpha : 1));
2428
+ }
2429
+ },
2430
+ onBlur: () => setDraftHex(null)
2431
+ }
2432
+ ),
2433
+ canPickFromScreen && /* @__PURE__ */ jsx34(
2434
+ Button,
2435
+ {
2436
+ type: "button",
2437
+ variant: "outline",
2438
+ size: "icon",
2439
+ "aria-label": "Pick a colour from the screen",
2440
+ onClick: () => void pickFromScreen(),
2441
+ children: /* @__PURE__ */ jsx34(Pipette, { className: "size-4" })
2442
+ }
2443
+ )
2444
+ ] }),
2445
+ swatches.length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
2446
+ /* @__PURE__ */ jsx34("p", { className: "text-muted-foreground mb-1 text-xs", children: "Presets" }),
2447
+ /* @__PURE__ */ jsx34("div", { className: "flex flex-wrap gap-1", children: swatches.map((swatch) => /* @__PURE__ */ jsx34(
2448
+ "button",
2449
+ {
2450
+ type: "button",
2451
+ title: swatch.label,
2452
+ "aria-label": swatch.label,
2453
+ className: "size-6 rounded border shadow-sm",
2454
+ style: { backgroundColor: swatch.color },
2455
+ onClick: () => onSwatchSelect?.(swatch)
2456
+ },
2457
+ swatch.id
2458
+ )) })
2459
+ ] }),
2460
+ recentColors.length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
2461
+ /* @__PURE__ */ jsx34("p", { className: "text-muted-foreground mb-1 text-xs", children: "Recent" }),
2462
+ /* @__PURE__ */ jsx34("div", { className: "flex flex-wrap gap-1", children: recentColors.map((recent) => /* @__PURE__ */ jsx34(
2463
+ "button",
2464
+ {
2465
+ type: "button",
2466
+ title: recent,
2467
+ "aria-label": recent,
2468
+ className: "size-6 rounded border shadow-sm",
2469
+ style: { backgroundColor: recent },
2470
+ onClick: () => {
2471
+ const parsed = parseHex(recent);
2472
+ if (parsed) commit(hsvaFrom(parsed, parsed.alpha, hsva.h));
2473
+ }
2474
+ },
2475
+ recent
2476
+ )) })
2477
+ ] })
2478
+ ] });
2479
+ }
2480
+
2139
2481
  // src/components/context-menu.tsx
2140
2482
  import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
2141
2483
  import { Check as Check4, ChevronRight as ChevronRight2, Circle as Circle2 } from "lucide-react";
2142
- import * as React9 from "react";
2143
- import { jsx as jsx34, jsxs as jsxs13 } from "react/jsx-runtime";
2484
+ import * as React10 from "react";
2485
+ import { jsx as jsx35, jsxs as jsxs14 } from "react/jsx-runtime";
2144
2486
  var menuItemBase2 = "cursor-pointer transition-colors data-[highlighted]:bg-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
2145
2487
  var menuSurface = "z-50 max-h-[var(--radix-context-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 origin-[--radix-context-menu-content-transform-origin]";
2146
2488
  var ContextMenu = ContextMenuPrimitive.Root;
@@ -2148,7 +2490,7 @@ var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
2148
2490
  var ContextMenuGroup = ContextMenuPrimitive.Group;
2149
2491
  var ContextMenuSub = ContextMenuPrimitive.Sub;
2150
2492
  var ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
2151
- var ContextMenuSubTrigger = React9.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs13(
2493
+ var ContextMenuSubTrigger = React10.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs14(
2152
2494
  ContextMenuPrimitive.SubTrigger,
2153
2495
  {
2154
2496
  ref,
@@ -2161,14 +2503,14 @@ var ContextMenuSubTrigger = React9.forwardRef(({ className, inset, children, ...
2161
2503
  ...props,
2162
2504
  children: [
2163
2505
  children,
2164
- /* @__PURE__ */ jsx34(ChevronRight2, { className: "ml-auto" })
2506
+ /* @__PURE__ */ jsx35(ChevronRight2, { className: "ml-auto" })
2165
2507
  ]
2166
2508
  }
2167
2509
  ));
2168
2510
  ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
2169
- var ContextMenuSubContent = React9.forwardRef(({ className, ...props }, ref) => {
2511
+ var ContextMenuSubContent = React10.forwardRef(({ className, ...props }, ref) => {
2170
2512
  const portalContainer = usePortalContainer();
2171
- return /* @__PURE__ */ jsx34(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx34(
2513
+ return /* @__PURE__ */ jsx35(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx35(
2172
2514
  ContextMenuPrimitive.SubContent,
2173
2515
  {
2174
2516
  ref,
@@ -2178,9 +2520,9 @@ var ContextMenuSubContent = React9.forwardRef(({ className, ...props }, ref) =>
2178
2520
  ) });
2179
2521
  });
2180
2522
  ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
2181
- var ContextMenuContent = React9.forwardRef(({ className, ...props }, ref) => {
2523
+ var ContextMenuContent = React10.forwardRef(({ className, ...props }, ref) => {
2182
2524
  const portalContainer = usePortalContainer();
2183
- return /* @__PURE__ */ jsx34(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx34(
2525
+ return /* @__PURE__ */ jsx35(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx35(
2184
2526
  ContextMenuPrimitive.Content,
2185
2527
  {
2186
2528
  ref,
@@ -2190,7 +2532,7 @@ var ContextMenuContent = React9.forwardRef(({ className, ...props }, ref) => {
2190
2532
  ) });
2191
2533
  });
2192
2534
  ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
2193
- var ContextMenuItem = React9.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx34(
2535
+ var ContextMenuItem = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx35(
2194
2536
  ContextMenuPrimitive.Item,
2195
2537
  {
2196
2538
  ref,
@@ -2204,7 +2546,7 @@ var ContextMenuItem = React9.forwardRef(({ className, inset, ...props }, ref) =>
2204
2546
  }
2205
2547
  ));
2206
2548
  ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
2207
- var ContextMenuCheckboxItem = React9.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs13(
2549
+ var ContextMenuCheckboxItem = React10.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs14(
2208
2550
  ContextMenuPrimitive.CheckboxItem,
2209
2551
  {
2210
2552
  ref,
@@ -2216,13 +2558,13 @@ var ContextMenuCheckboxItem = React9.forwardRef(({ className, children, checked,
2216
2558
  checked,
2217
2559
  ...props,
2218
2560
  children: [
2219
- /* @__PURE__ */ jsx34("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx34(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx34(Check4, { className: "h-4 w-4" }) }) }),
2561
+ /* @__PURE__ */ jsx35("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx35(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx35(Check4, { className: "h-4 w-4" }) }) }),
2220
2562
  children
2221
2563
  ]
2222
2564
  }
2223
2565
  ));
2224
2566
  ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
2225
- var ContextMenuRadioItem = React9.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs13(
2567
+ var ContextMenuRadioItem = React10.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs14(
2226
2568
  ContextMenuPrimitive.RadioItem,
2227
2569
  {
2228
2570
  ref,
@@ -2233,13 +2575,13 @@ var ContextMenuRadioItem = React9.forwardRef(({ className, children, ...props },
2233
2575
  ),
2234
2576
  ...props,
2235
2577
  children: [
2236
- /* @__PURE__ */ jsx34("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx34(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx34(Circle2, { className: "h-2 w-2 fill-current" }) }) }),
2578
+ /* @__PURE__ */ jsx35("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx35(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx35(Circle2, { className: "h-2 w-2 fill-current" }) }) }),
2237
2579
  children
2238
2580
  ]
2239
2581
  }
2240
2582
  ));
2241
2583
  ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
2242
- var ContextMenuLabel = React9.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx34(
2584
+ var ContextMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx35(
2243
2585
  ContextMenuPrimitive.Label,
2244
2586
  {
2245
2587
  ref,
@@ -2252,7 +2594,7 @@ var ContextMenuLabel = React9.forwardRef(({ className, inset, ...props }, ref) =
2252
2594
  }
2253
2595
  ));
2254
2596
  ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
2255
- var ContextMenuSeparator = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx34(
2597
+ var ContextMenuSeparator = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx35(
2256
2598
  ContextMenuPrimitive.Separator,
2257
2599
  {
2258
2600
  ref,
@@ -2264,7 +2606,7 @@ ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
2264
2606
  var ContextMenuShortcut = ({
2265
2607
  className,
2266
2608
  ...props
2267
- }) => /* @__PURE__ */ jsx34(
2609
+ }) => /* @__PURE__ */ jsx35(
2268
2610
  "span",
2269
2611
  {
2270
2612
  className: cn(
@@ -2279,11 +2621,11 @@ ContextMenuShortcut.displayName = "ContextMenuShortcut";
2279
2621
  // src/components/resizable.tsx
2280
2622
  import { GripVertical } from "lucide-react";
2281
2623
  import * as ResizablePrimitive from "react-resizable-panels";
2282
- import { jsx as jsx35, jsxs as jsxs14 } from "react/jsx-runtime";
2624
+ import { jsx as jsx36, jsxs as jsxs15 } from "react/jsx-runtime";
2283
2625
  var ResizablePanelGroup = ({
2284
2626
  className,
2285
2627
  ...props
2286
- }) => /* @__PURE__ */ jsx35(
2628
+ }) => /* @__PURE__ */ jsx36(
2287
2629
  ResizablePrimitive.Group,
2288
2630
  {
2289
2631
  className: cn("h-full w-full", className),
@@ -2296,7 +2638,7 @@ var ResizableHandle = ({
2296
2638
  className,
2297
2639
  children,
2298
2640
  ...props
2299
- }) => /* @__PURE__ */ jsxs14(
2641
+ }) => /* @__PURE__ */ jsxs15(
2300
2642
  ResizablePrimitive.Separator,
2301
2643
  {
2302
2644
  className: cn(
@@ -2316,7 +2658,7 @@ var ResizableHandle = ({
2316
2658
  ),
2317
2659
  ...props,
2318
2660
  children: [
2319
- withGrip ? /* @__PURE__ */ jsx35("div", { className: "z-10 flex h-4 w-3 items-center justify-center rounded-sm border border-border bg-border", children: /* @__PURE__ */ jsx35(GripVertical, { className: "h-2.5 w-2.5 text-muted-foreground" }) }) : null,
2661
+ withGrip ? /* @__PURE__ */ jsx36("div", { className: "z-10 flex h-4 w-3 items-center justify-center rounded-sm border border-border bg-border", children: /* @__PURE__ */ jsx36(GripVertical, { className: "h-2.5 w-2.5 text-muted-foreground" }) }) : null,
2320
2662
  children
2321
2663
  ]
2322
2664
  }
@@ -2325,8 +2667,8 @@ var ResizableHandle = ({
2325
2667
  // src/components/tree-view.tsx
2326
2668
  import { useVirtualizer } from "@tanstack/react-virtual";
2327
2669
  import { ChevronRight as ChevronRight3 } from "lucide-react";
2328
- import * as React10 from "react";
2329
- import { jsx as jsx36, jsxs as jsxs15 } from "react/jsx-runtime";
2670
+ import * as React11 from "react";
2671
+ import { jsx as jsx37, jsxs as jsxs16 } from "react/jsx-runtime";
2330
2672
  var ROW_HEIGHT = 28;
2331
2673
  var INDENT_PER_LEVEL = 12;
2332
2674
  function textOf(node) {
@@ -2367,13 +2709,13 @@ function flatten(nodes, expanded) {
2367
2709
  return rows;
2368
2710
  }
2369
2711
  function useControllable(controlled, fallback) {
2370
- const [uncontrolled, setUncontrolled] = React10.useState(fallback);
2712
+ const [uncontrolled, setUncontrolled] = React11.useState(fallback);
2371
2713
  return [
2372
2714
  controlled === void 0 ? uncontrolled : controlled,
2373
2715
  setUncontrolled
2374
2716
  ];
2375
2717
  }
2376
- var TreeView = React10.forwardRef(
2718
+ var TreeView = React11.forwardRef(
2377
2719
  ({
2378
2720
  nodes,
2379
2721
  expandedIds,
@@ -2388,8 +2730,8 @@ var TreeView = React10.forwardRef(
2388
2730
  "aria-describedby": ariaDescribedBy,
2389
2731
  ...props
2390
2732
  }, forwardedRef) => {
2391
- const scrollRef = React10.useRef(null);
2392
- const attachScroll = React10.useCallback(
2733
+ const scrollRef = React11.useRef(null);
2734
+ const attachScroll = React11.useCallback(
2393
2735
  (node) => {
2394
2736
  scrollRef.current = node;
2395
2737
  if (typeof forwardedRef === "function") forwardedRef(node);
@@ -2403,7 +2745,7 @@ var TreeView = React10.forwardRef(
2403
2745
  expandedIds === void 0 ? void 0 : [...expandedIds],
2404
2746
  [...defaultExpandedIds ?? []]
2405
2747
  );
2406
- const expanded = React10.useMemo(
2748
+ const expanded = React11.useMemo(
2407
2749
  () => new Set(expandedIds ?? expandedState),
2408
2750
  [expandedIds, expandedState]
2409
2751
  );
@@ -2411,11 +2753,11 @@ var TreeView = React10.forwardRef(
2411
2753
  selectedId === void 0 ? void 0 : selectedId,
2412
2754
  defaultSelectedId ?? null
2413
2755
  );
2414
- const rows = React10.useMemo(
2756
+ const rows = React11.useMemo(
2415
2757
  () => flatten(nodes, expanded),
2416
2758
  [nodes, expanded]
2417
2759
  );
2418
- const [activeId, setActiveId] = React10.useState(null);
2760
+ const [activeId, setActiveId] = React11.useState(null);
2419
2761
  const activeIndex = Math.max(
2420
2762
  0,
2421
2763
  rows.findIndex((row) => row.node.id === (activeId ?? selected))
@@ -2459,7 +2801,7 @@ var TreeView = React10.forwardRef(
2459
2801
  }
2460
2802
  return from;
2461
2803
  };
2462
- const typeahead = React10.useRef({ query: "", at: 0 });
2804
+ const typeahead = React11.useRef({ query: "", at: 0 });
2463
2805
  const onKeyDown = (event) => {
2464
2806
  const index = activeIndex;
2465
2807
  const row = rows[index];
@@ -2556,13 +2898,13 @@ var TreeView = React10.forwardRef(
2556
2898
  const virtualItems = virtualizer.getVirtualItems();
2557
2899
  const usable = (index) => rows[index]?.node.disabled !== true;
2558
2900
  const tabStopIndex = virtualItems.some((item) => item.index === activeIndex) && usable(activeIndex) ? activeIndex : virtualItems.find((item) => usable(item.index))?.index ?? -1;
2559
- return /* @__PURE__ */ jsx36(
2901
+ return /* @__PURE__ */ jsx37(
2560
2902
  "div",
2561
2903
  {
2562
2904
  ref: attachScroll,
2563
2905
  className: cn("overflow-auto", className),
2564
2906
  ...props,
2565
- children: /* @__PURE__ */ jsx36(
2907
+ children: /* @__PURE__ */ jsx37(
2566
2908
  "div",
2567
2909
  {
2568
2910
  role: "tree",
@@ -2575,7 +2917,7 @@ var TreeView = React10.forwardRef(
2575
2917
  const row = rows[item.index];
2576
2918
  if (row === void 0) return null;
2577
2919
  const isSelected = selected === row.node.id;
2578
- return /* @__PURE__ */ jsxs15(
2920
+ return /* @__PURE__ */ jsxs16(
2579
2921
  "div",
2580
2922
  {
2581
2923
  "data-tree-index": item.index,
@@ -2605,7 +2947,7 @@ var TreeView = React10.forwardRef(
2605
2947
  paddingLeft: 4 + row.level * INDENT_PER_LEVEL
2606
2948
  },
2607
2949
  children: [
2608
- /* @__PURE__ */ jsx36(
2950
+ /* @__PURE__ */ jsx37(
2609
2951
  "span",
2610
2952
  {
2611
2953
  "aria-hidden": "true",
@@ -2615,7 +2957,7 @@ var TreeView = React10.forwardRef(
2615
2957
  event.stopPropagation();
2616
2958
  setExpansion(row.node.id, !expanded.has(row.node.id));
2617
2959
  },
2618
- children: row.hasChildren ? /* @__PURE__ */ jsx36(
2960
+ children: row.hasChildren ? /* @__PURE__ */ jsx37(
2619
2961
  ChevronRight3,
2620
2962
  {
2621
2963
  className: cn(
@@ -2626,8 +2968,8 @@ var TreeView = React10.forwardRef(
2626
2968
  ) : null
2627
2969
  }
2628
2970
  ),
2629
- row.node.icon !== void 0 ? /* @__PURE__ */ jsx36("span", { className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground", children: row.node.icon }) : null,
2630
- /* @__PURE__ */ jsx36("span", { className: "truncate", children: row.node.label })
2971
+ row.node.icon !== void 0 ? /* @__PURE__ */ jsx37("span", { className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground", children: row.node.icon }) : null,
2972
+ /* @__PURE__ */ jsx37("span", { className: "truncate", children: row.node.label })
2631
2973
  ]
2632
2974
  },
2633
2975
  row.node.id
@@ -2643,7 +2985,7 @@ TreeView.displayName = "TreeView";
2643
2985
 
2644
2986
  // src/components/slider.tsx
2645
2987
  import * as SliderPrimitive from "@radix-ui/react-slider";
2646
- import * as React11 from "react";
2988
+ import * as React12 from "react";
2647
2989
 
2648
2990
  // src/lib/dev-warn.ts
2649
2991
  var emitted = /* @__PURE__ */ new Set();
@@ -2662,14 +3004,14 @@ function devWarnOnce(condition, message) {
2662
3004
  }
2663
3005
 
2664
3006
  // src/components/slider.tsx
2665
- import { jsx as jsx37, jsxs as jsxs16 } from "react/jsx-runtime";
3007
+ import { jsx as jsx38, jsxs as jsxs17 } from "react/jsx-runtime";
2666
3008
  function thumbCount(value, defaultValue) {
2667
3009
  return Math.max(1, value?.length ?? defaultValue?.length ?? 1);
2668
3010
  }
2669
3011
  function hasAccessibleName(value) {
2670
3012
  return value !== void 0 && value.trim() !== "";
2671
3013
  }
2672
- var Slider = React11.forwardRef(
3014
+ var Slider = React12.forwardRef(
2673
3015
  ({
2674
3016
  className,
2675
3017
  value,
@@ -2680,7 +3022,7 @@ var Slider = React11.forwardRef(
2680
3022
  "aria-labelledby": ariaLabelledBy,
2681
3023
  ...props
2682
3024
  }, ref) => {
2683
- const initialUncontrolledCount = React11.useRef(
3025
+ const initialUncontrolledCount = React12.useRef(
2684
3026
  thumbCount(void 0, defaultValue)
2685
3027
  ).current;
2686
3028
  const count = value?.length ?? initialUncontrolledCount;
@@ -2725,7 +3067,7 @@ var Slider = React11.forwardRef(
2725
3067
  // `aria-label`/`aria-labelledby` are destructured out above rather than
2726
3068
  // spread here: left on the root they would be a second, roleless copy
2727
3069
  // of a name only the thumb is read for.
2728
- /* @__PURE__ */ jsxs16(
3070
+ /* @__PURE__ */ jsxs17(
2729
3071
  SliderPrimitive.Root,
2730
3072
  {
2731
3073
  ref,
@@ -2753,14 +3095,14 @@ var Slider = React11.forwardRef(
2753
3095
  defaultValue: isEmptyDefault ? void 0 : defaultValue,
2754
3096
  ...props,
2755
3097
  children: [
2756
- /* @__PURE__ */ jsx37(
3098
+ /* @__PURE__ */ jsx38(
2757
3099
  SliderPrimitive.Track,
2758
3100
  {
2759
3101
  className: cn(
2760
3102
  "bg-secondary relative grow overflow-hidden rounded-full",
2761
3103
  isVertical ? "h-full w-1.5" : "h-1.5 w-full"
2762
3104
  ),
2763
- children: /* @__PURE__ */ jsx37(
3105
+ children: /* @__PURE__ */ jsx38(
2764
3106
  SliderPrimitive.Range,
2765
3107
  {
2766
3108
  className: cn(
@@ -2771,7 +3113,7 @@ var Slider = React11.forwardRef(
2771
3113
  )
2772
3114
  }
2773
3115
  ),
2774
- Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx37(
3116
+ Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx38(
2775
3117
  SliderPrimitive.Thumb,
2776
3118
  {
2777
3119
  ...ariaFor(i),
@@ -2794,7 +3136,7 @@ var Slider = React11.forwardRef(
2794
3136
  Slider.displayName = SliderPrimitive.Root.displayName;
2795
3137
 
2796
3138
  // src/lib/shortcuts/react.tsx
2797
- import * as React12 from "react";
3139
+ import * as React13 from "react";
2798
3140
 
2799
3141
  // src/lib/shortcuts/key-spec.ts
2800
3142
  function normalizeKey(key) {
@@ -3128,6 +3470,7 @@ function createShortcutManager(options = {}) {
3128
3470
  }
3129
3471
  }
3130
3472
  function handle(event) {
3473
+ if (typeof event.key !== "string") return false;
3131
3474
  if (event.defaultPrevented) {
3132
3475
  abandonSequence();
3133
3476
  return true;
@@ -3321,10 +3664,10 @@ var FIELD_KEYS = /* @__PURE__ */ new Set([
3321
3664
  ]);
3322
3665
 
3323
3666
  // src/lib/shortcuts/react.tsx
3324
- import { jsx as jsx38 } from "react/jsx-runtime";
3325
- var ShortcutContext = React12.createContext(null);
3667
+ import { jsx as jsx39 } from "react/jsx-runtime";
3668
+ var ShortcutContext = React13.createContext(null);
3326
3669
  var ownersByTarget = /* @__PURE__ */ new WeakMap();
3327
- var useIsomorphicLayoutEffect = typeof document === "undefined" ? React12.useEffect : React12.useLayoutEffect;
3670
+ var useIsomorphicLayoutEffect = typeof document === "undefined" ? React13.useEffect : React13.useLayoutEffect;
3328
3671
  function optionsFingerprint(options) {
3329
3672
  return [
3330
3673
  options.isApple ?? "auto",
@@ -3337,13 +3680,13 @@ function ShortcutProvider({
3337
3680
  target,
3338
3681
  ...managerOptions
3339
3682
  }) {
3340
- const parent = React12.useContext(ShortcutContext);
3683
+ const parent = React13.useContext(ShortcutContext);
3341
3684
  const resolvedTarget = target === null ? null : target ?? (typeof document === "undefined" ? null : document);
3342
3685
  const nestedOnSameTarget = parent !== null && parent.target === resolvedTarget;
3343
- const optionsRef = React12.useRef(managerOptions);
3344
- const ownManagers = React12.useRef(/* @__PURE__ */ new WeakMap());
3345
- const ownDetached = React12.useRef(null);
3346
- const detached = React12.useMemo(() => {
3686
+ const optionsRef = React13.useRef(managerOptions);
3687
+ const ownManagers = React13.useRef(/* @__PURE__ */ new WeakMap());
3688
+ const ownDetached = React13.useRef(null);
3689
+ const detached = React13.useMemo(() => {
3347
3690
  if (resolvedTarget === null) {
3348
3691
  ownDetached.current ??= createShortcutManager(optionsRef.current);
3349
3692
  return ownDetached.current;
@@ -3399,20 +3742,20 @@ function ShortcutProvider({
3399
3742
  };
3400
3743
  }, [resolvedTarget, manager]);
3401
3744
  const depth = nestedOnSameTarget && parent ? parent.depth : 0;
3402
- const value = React12.useMemo(
3745
+ const value = React13.useMemo(
3403
3746
  () => ({ manager, depth, target: resolvedTarget, options: fingerprint }),
3404
3747
  [manager, depth, resolvedTarget, fingerprint]
3405
3748
  );
3406
- return /* @__PURE__ */ jsx38(ShortcutContext.Provider, { value, children });
3749
+ return /* @__PURE__ */ jsx39(ShortcutContext.Provider, { value, children });
3407
3750
  }
3408
3751
  function ShortcutScope({
3409
3752
  children
3410
3753
  }) {
3411
- const parent = React12.useContext(ShortcutContext);
3754
+ const parent = React13.useContext(ShortcutContext);
3412
3755
  if (!parent) {
3413
3756
  throw new Error("ShortcutScope must be rendered inside a ShortcutProvider");
3414
3757
  }
3415
- const value = React12.useMemo(
3758
+ const value = React13.useMemo(
3416
3759
  () => ({
3417
3760
  manager: parent.manager,
3418
3761
  depth: parent.depth + 1,
@@ -3423,16 +3766,16 @@ function ShortcutScope({
3423
3766
  }),
3424
3767
  [parent.manager, parent.depth, parent.target, parent.options]
3425
3768
  );
3426
- return /* @__PURE__ */ jsx38(ShortcutContext.Provider, { value, children });
3769
+ return /* @__PURE__ */ jsx39(ShortcutContext.Provider, { value, children });
3427
3770
  }
3428
3771
  function useShortcuts(bindings, options) {
3429
- const context = React12.useContext(ShortcutContext);
3772
+ const context = React13.useContext(ShortcutContext);
3430
3773
  if (!context) {
3431
3774
  throw new Error("useShortcuts must be called inside a ShortcutProvider");
3432
3775
  }
3433
3776
  const { manager, depth } = context;
3434
- const registration = React12.useRef(null);
3435
- const latest = React12.useRef({ bindings, options });
3777
+ const registration = React13.useRef(null);
3778
+ const latest = React13.useRef({ bindings, options });
3436
3779
  useIsomorphicLayoutEffect(() => {
3437
3780
  registration.current = manager.register([], {
3438
3781
  name: latest.current.options.name,
@@ -3454,7 +3797,7 @@ function useShortcuts(bindings, options) {
3454
3797
  });
3455
3798
  }
3456
3799
  function useShortcutManager() {
3457
- const context = React12.useContext(ShortcutContext);
3800
+ const context = React13.useContext(ShortcutContext);
3458
3801
  if (!context) {
3459
3802
  throw new Error(
3460
3803
  "useShortcutManager must be called inside a ShortcutProvider"
@@ -3464,7 +3807,7 @@ function useShortcutManager() {
3464
3807
  }
3465
3808
  function useActiveShortcuts() {
3466
3809
  const manager = useShortcutManager();
3467
- return React12.useSyncExternalStore(
3810
+ return React13.useSyncExternalStore(
3468
3811
  manager.subscribe,
3469
3812
  manager.activeBindings,
3470
3813
  manager.activeBindings
@@ -3505,6 +3848,7 @@ export {
3505
3848
  Collapsible,
3506
3849
  CollapsibleContent2 as CollapsibleContent,
3507
3850
  CollapsibleTrigger2 as CollapsibleTrigger,
3851
+ ColorPicker,
3508
3852
  Command,
3509
3853
  CommandDialog,
3510
3854
  CommandEmpty,