@nextlyhq/ui 0.0.2-alpha.60 → 0.0.2-alpha.64
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/README.md +35 -8
- package/dist/index.cjs +475 -221
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +301 -23
- package/dist/index.d.ts +301 -23
- package/dist/index.mjs +479 -221
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.scoped.css +1 -1
- package/dist/tailwind-preset.cjs.map +1 -1
- package/dist/tailwind-preset.mjs.map +1 -1
- package/dist/theme.css +132 -0
- package/package.json +6 -5
package/dist/index.mjs
CHANGED
|
@@ -998,15 +998,23 @@ var tabsListVariants = cva8(
|
|
|
998
998
|
defaultVariants: { variant: "default" }
|
|
999
999
|
}
|
|
1000
1000
|
);
|
|
1001
|
-
var TabsList = forwardRef15(({ className, variant, ...props }, ref) =>
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1001
|
+
var TabsList = forwardRef15(({ className, variant, scrollable = false, ...props }, ref) => {
|
|
1002
|
+
const list = /* @__PURE__ */ jsx20(
|
|
1003
|
+
List,
|
|
1004
|
+
{
|
|
1005
|
+
ref,
|
|
1006
|
+
"data-slot": "tabs-list",
|
|
1007
|
+
className: cn(
|
|
1008
|
+
tabsListVariants({ variant }),
|
|
1009
|
+
scrollable && "w-max min-w-full",
|
|
1010
|
+
className
|
|
1011
|
+
),
|
|
1012
|
+
...props
|
|
1013
|
+
}
|
|
1014
|
+
);
|
|
1015
|
+
if (!scrollable) return list;
|
|
1016
|
+
return /* @__PURE__ */ jsx20("div", { "data-slot": "tabs-list-scroller", className: "w-full overflow-x-auto", children: list });
|
|
1017
|
+
});
|
|
1010
1018
|
TabsList.displayName = List.displayName;
|
|
1011
1019
|
var TABS_TRIGGER_SIZES = {
|
|
1012
1020
|
default: "text-sm",
|
|
@@ -1657,6 +1665,7 @@ var SheetPortal = DialogPrimitive2.Portal;
|
|
|
1657
1665
|
var SheetOverlay = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
|
|
1658
1666
|
DialogPrimitive2.Overlay,
|
|
1659
1667
|
{
|
|
1668
|
+
"data-slot": "sheet-overlay",
|
|
1660
1669
|
className: cn(
|
|
1661
1670
|
// A modal scrim, from the `--nx-overlay` token rather than a surface
|
|
1662
1671
|
// token. A black wash is the point — painting it from `background` would
|
|
@@ -1756,7 +1765,11 @@ SheetDescription.displayName = DialogPrimitive2.Description.displayName;
|
|
|
1756
1765
|
|
|
1757
1766
|
// src/components/command.tsx
|
|
1758
1767
|
import * as DialogPrimitive3 from "@radix-ui/react-dialog";
|
|
1759
|
-
import {
|
|
1768
|
+
import {
|
|
1769
|
+
Command as CommandPrimitive,
|
|
1770
|
+
defaultFilter,
|
|
1771
|
+
useCommandState as useCommandStatePrimitive
|
|
1772
|
+
} from "cmdk";
|
|
1760
1773
|
import { Search } from "lucide-react";
|
|
1761
1774
|
import { forwardRef as forwardRef22 } from "react";
|
|
1762
1775
|
import { jsx as jsx27, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
@@ -1983,6 +1996,7 @@ var CommandShortcut = forwardRef22(
|
|
|
1983
1996
|
);
|
|
1984
1997
|
CommandShortcut.displayName = "CommandShortcut";
|
|
1985
1998
|
var commandDefaultFilter = defaultFilter;
|
|
1999
|
+
var useCommandHighlight = () => useCommandStatePrimitive((state) => state.value);
|
|
1986
2000
|
|
|
1987
2001
|
// src/components/spinner.tsx
|
|
1988
2002
|
import { cva as cva12 } from "class-variance-authority";
|
|
@@ -2257,7 +2271,7 @@ TableSkeleton.displayName = "TableSkeleton";
|
|
|
2257
2271
|
|
|
2258
2272
|
// src/components/color-picker.tsx
|
|
2259
2273
|
import { Pipette } from "lucide-react";
|
|
2260
|
-
import * as
|
|
2274
|
+
import * as React10 from "react";
|
|
2261
2275
|
|
|
2262
2276
|
// src/lib/color/convert.ts
|
|
2263
2277
|
var clamp01 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
|
|
@@ -2362,6 +2376,10 @@ function hueSliderValue(hue, max) {
|
|
|
2362
2376
|
return step > max ? max : step;
|
|
2363
2377
|
}
|
|
2364
2378
|
|
|
2379
|
+
// src/lib/isomorphic-layout-effect.ts
|
|
2380
|
+
import * as React9 from "react";
|
|
2381
|
+
var useIsomorphicLayoutEffect = typeof document === "undefined" ? React9.useEffect : React9.useLayoutEffect;
|
|
2382
|
+
|
|
2365
2383
|
// src/components/color-picker.tsx
|
|
2366
2384
|
import { Fragment as Fragment2, jsx as jsx34, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2367
2385
|
function toHsva(hex) {
|
|
@@ -2383,6 +2401,9 @@ var CHECKERBOARD = "repeating-conic-gradient(#c8c8c8 0% 25%, #ffffff 0% 50%)";
|
|
|
2383
2401
|
function eyeDropperSupported() {
|
|
2384
2402
|
return typeof window !== "undefined" && "EyeDropper" in window;
|
|
2385
2403
|
}
|
|
2404
|
+
function isNode(value) {
|
|
2405
|
+
return value !== null && typeof value.nodeType === "number";
|
|
2406
|
+
}
|
|
2386
2407
|
function ColorPicker({
|
|
2387
2408
|
color,
|
|
2388
2409
|
onColorChange,
|
|
@@ -2392,20 +2413,100 @@ function ColorPicker({
|
|
|
2392
2413
|
showAlpha = false,
|
|
2393
2414
|
className
|
|
2394
2415
|
}) {
|
|
2395
|
-
const fieldId =
|
|
2396
|
-
const
|
|
2397
|
-
const
|
|
2398
|
-
const
|
|
2416
|
+
const fieldId = React10.useId();
|
|
2417
|
+
const rootRef = React10.useRef(null);
|
|
2418
|
+
const insidePress = React10.useRef(false);
|
|
2419
|
+
const owedFinish = React10.useRef(false);
|
|
2420
|
+
const pendingTap = React10.useRef(null);
|
|
2421
|
+
const latestCommit = React10.useRef(() => void 0);
|
|
2422
|
+
const surfaceRef = React10.useRef(null);
|
|
2423
|
+
const [hsva, setHsva] = React10.useState(() => toHsva(color));
|
|
2424
|
+
const [draftHex, setDraftHex] = React10.useState(null);
|
|
2425
|
+
const draftRef = React10.useRef(null);
|
|
2399
2426
|
const rendered = toHexString(hsva, showAlpha);
|
|
2400
|
-
|
|
2427
|
+
useIsomorphicLayoutEffect(() => {
|
|
2401
2428
|
const incoming = parseHex(color);
|
|
2402
2429
|
if (incoming && toHex(incoming, showAlpha ? incoming.alpha : 1) !== rendered) {
|
|
2430
|
+
dropDraft();
|
|
2403
2431
|
setHsva((prev) => hsvaFrom(incoming, incoming.alpha, prev.h));
|
|
2404
2432
|
}
|
|
2405
2433
|
}, [color, rendered, showAlpha]);
|
|
2434
|
+
const dropDraft = () => {
|
|
2435
|
+
owedFinish.current = false;
|
|
2436
|
+
draftRef.current = null;
|
|
2437
|
+
setDraftHex(null);
|
|
2438
|
+
};
|
|
2439
|
+
const commitDraft = () => {
|
|
2440
|
+
owedFinish.current = false;
|
|
2441
|
+
const text = draftRef.current;
|
|
2442
|
+
draftRef.current = null;
|
|
2443
|
+
if (text === null) return;
|
|
2444
|
+
setDraftHex(null);
|
|
2445
|
+
const parsed = parseHex(text);
|
|
2446
|
+
if (!parsed) return;
|
|
2447
|
+
setHsva((prev) => hsvaFrom(parsed, parsed.alpha, prev.h));
|
|
2448
|
+
onColorChange(toHex(parsed, showAlpha ? parsed.alpha : 1));
|
|
2449
|
+
};
|
|
2450
|
+
useIsomorphicLayoutEffect(() => {
|
|
2451
|
+
const root = rootRef.current;
|
|
2452
|
+
if (root === null) return;
|
|
2453
|
+
latestCommit.current = commitDraft;
|
|
2454
|
+
const onPointerDown = (event) => {
|
|
2455
|
+
pendingTap.current?.();
|
|
2456
|
+
pendingTap.current = null;
|
|
2457
|
+
const path = typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
2458
|
+
const inside = path.includes(root) || isNode(event.target) && root.contains(event.target);
|
|
2459
|
+
insidePress.current = true;
|
|
2460
|
+
if (inside) return;
|
|
2461
|
+
const pointerType = event.pointerType;
|
|
2462
|
+
if (pointerType === "touch") {
|
|
2463
|
+
const onClick = () => {
|
|
2464
|
+
owner.removeEventListener("click", onClick, true);
|
|
2465
|
+
pendingTap.current = null;
|
|
2466
|
+
latestCommit.current();
|
|
2467
|
+
};
|
|
2468
|
+
owner.addEventListener("click", onClick, true);
|
|
2469
|
+
pendingTap.current = () => {
|
|
2470
|
+
owner.removeEventListener("click", onClick, true);
|
|
2471
|
+
};
|
|
2472
|
+
return;
|
|
2473
|
+
}
|
|
2474
|
+
commitDraft();
|
|
2475
|
+
};
|
|
2476
|
+
const owner = root.ownerDocument;
|
|
2477
|
+
const onPointerCancel = () => {
|
|
2478
|
+
insidePress.current = false;
|
|
2479
|
+
pendingTap.current?.();
|
|
2480
|
+
pendingTap.current = null;
|
|
2481
|
+
};
|
|
2482
|
+
const onPointerUp = () => {
|
|
2483
|
+
insidePress.current = false;
|
|
2484
|
+
};
|
|
2485
|
+
const onClickResolve = () => {
|
|
2486
|
+
if (!owedFinish.current) return;
|
|
2487
|
+
latestCommit.current();
|
|
2488
|
+
};
|
|
2489
|
+
owner.addEventListener("pointerdown", onPointerDown, true);
|
|
2490
|
+
owner.addEventListener("pointercancel", onPointerCancel, true);
|
|
2491
|
+
owner.addEventListener("pointerup", onPointerUp, true);
|
|
2492
|
+
owner.addEventListener("click", onClickResolve, false);
|
|
2493
|
+
return () => {
|
|
2494
|
+
owner.removeEventListener("pointerdown", onPointerDown, true);
|
|
2495
|
+
owner.removeEventListener("pointercancel", onPointerCancel, true);
|
|
2496
|
+
owner.removeEventListener("pointerup", onPointerUp, true);
|
|
2497
|
+
owner.removeEventListener("click", onClickResolve, false);
|
|
2498
|
+
};
|
|
2499
|
+
});
|
|
2500
|
+
useIsomorphicLayoutEffect(
|
|
2501
|
+
() => () => {
|
|
2502
|
+
pendingTap.current?.();
|
|
2503
|
+
pendingTap.current = null;
|
|
2504
|
+
},
|
|
2505
|
+
[]
|
|
2506
|
+
);
|
|
2406
2507
|
const commit = (next) => {
|
|
2407
2508
|
setHsva(next);
|
|
2408
|
-
|
|
2509
|
+
dropDraft();
|
|
2409
2510
|
onColorChange(toHexString(next, showAlpha));
|
|
2410
2511
|
};
|
|
2411
2512
|
const trackPointer = (event) => {
|
|
@@ -2435,8 +2536,8 @@ function ColorPicker({
|
|
|
2435
2536
|
event.preventDefault();
|
|
2436
2537
|
nudge(move[0], move[1]);
|
|
2437
2538
|
};
|
|
2438
|
-
const [canPickFromScreen, setCanPickFromScreen] =
|
|
2439
|
-
|
|
2539
|
+
const [canPickFromScreen, setCanPickFromScreen] = React10.useState(false);
|
|
2540
|
+
React10.useEffect(() => {
|
|
2440
2541
|
setCanPickFromScreen(eyeDropperSupported());
|
|
2441
2542
|
}, []);
|
|
2442
2543
|
const handle = surfacePointFor(hsva.s, hsva.v);
|
|
@@ -2444,163 +2545,187 @@ function ColorPicker({
|
|
|
2444
2545
|
const pickFromScreen = async () => {
|
|
2445
2546
|
const ctor = window.EyeDropper;
|
|
2446
2547
|
if (!ctor) return;
|
|
2548
|
+
const owed = owedFinish.current;
|
|
2549
|
+
owedFinish.current = false;
|
|
2447
2550
|
let sampled;
|
|
2448
2551
|
try {
|
|
2449
2552
|
sampled = (await new ctor().open()).sRGBHex;
|
|
2450
2553
|
} catch {
|
|
2554
|
+
if (owed) commitDraft();
|
|
2451
2555
|
return;
|
|
2452
2556
|
}
|
|
2453
2557
|
const parsed = parseHex(sampled);
|
|
2454
2558
|
if (parsed) commit(hsvaFrom(parsed, hsva.a, hsva.h));
|
|
2455
2559
|
};
|
|
2456
|
-
return /* @__PURE__ */ jsxs13(
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
// viewer, so the reverse order lets the opaque white end of the
|
|
2469
|
-
// saturation ramp cover the black end of the value ramp: the
|
|
2470
|
-
// bottom-left corner displays white while selecting black.
|
|
2471
|
-
backgroundImage: "linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, transparent)"
|
|
2472
|
-
},
|
|
2473
|
-
onKeyDown: handleSurfaceKey,
|
|
2474
|
-
onPointerDown: (event) => {
|
|
2475
|
-
event.currentTarget.setPointerCapture(event.pointerId);
|
|
2476
|
-
trackPointer(event);
|
|
2477
|
-
},
|
|
2478
|
-
onPointerMove: (event) => {
|
|
2479
|
-
if (event.buttons === 1) trackPointer(event);
|
|
2480
|
-
},
|
|
2481
|
-
children: /* @__PURE__ */ jsx34(
|
|
2482
|
-
"span",
|
|
2483
|
-
{
|
|
2484
|
-
"aria-hidden": "true",
|
|
2485
|
-
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",
|
|
2486
|
-
style: { left: `${handle.x * 100}%`, top: `${handle.y * 100}%` }
|
|
2487
|
-
}
|
|
2488
|
-
)
|
|
2489
|
-
}
|
|
2490
|
-
),
|
|
2491
|
-
/* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-hue`, children: "Hue" }),
|
|
2492
|
-
/* @__PURE__ */ jsx34(
|
|
2493
|
-
"input",
|
|
2494
|
-
{
|
|
2495
|
-
id: `${fieldId}-hue`,
|
|
2496
|
-
type: "range",
|
|
2497
|
-
min: 0,
|
|
2498
|
-
max: HUE_MAX,
|
|
2499
|
-
step: 1,
|
|
2500
|
-
value: hueSliderValue(hsva.h, HUE_MAX),
|
|
2501
|
-
onChange: (event) => commit({ ...hsva, h: hueAt(+event.target.value / (HUE_MAX + 1)) }),
|
|
2502
|
-
className: SLIDER,
|
|
2503
|
-
style: {
|
|
2504
|
-
backgroundImage: "linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00)"
|
|
2560
|
+
return /* @__PURE__ */ jsxs13(
|
|
2561
|
+
"div",
|
|
2562
|
+
{
|
|
2563
|
+
ref: rootRef,
|
|
2564
|
+
className: cn("w-64 space-y-3", className),
|
|
2565
|
+
onBlur: (event) => {
|
|
2566
|
+
const next = event.relatedTarget;
|
|
2567
|
+
const root = rootRef.current;
|
|
2568
|
+
if (root !== null && isNode(next) && root.contains(next)) return;
|
|
2569
|
+
if (next === null && insidePress.current) {
|
|
2570
|
+
owedFinish.current = true;
|
|
2571
|
+
return;
|
|
2505
2572
|
}
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2573
|
+
commitDraft();
|
|
2574
|
+
},
|
|
2575
|
+
children: [
|
|
2576
|
+
/* @__PURE__ */ jsx34(
|
|
2577
|
+
"div",
|
|
2578
|
+
{
|
|
2579
|
+
ref: surfaceRef,
|
|
2580
|
+
role: "application",
|
|
2581
|
+
tabIndex: 0,
|
|
2582
|
+
"aria-label": `Saturation and brightness: ${Math.round(hsva.s * 100)}% saturation, ${Math.round(hsva.v * 100)}% brightness. Arrow keys adjust.`,
|
|
2583
|
+
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",
|
|
2584
|
+
style: {
|
|
2585
|
+
backgroundColor: hueOnly,
|
|
2586
|
+
// Value on TOP of saturation. CSS paints the first layer nearest the
|
|
2587
|
+
// viewer, so the reverse order lets the opaque white end of the
|
|
2588
|
+
// saturation ramp cover the black end of the value ramp: the
|
|
2589
|
+
// bottom-left corner displays white while selecting black.
|
|
2590
|
+
backgroundImage: "linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, transparent)"
|
|
2591
|
+
},
|
|
2592
|
+
onKeyDown: handleSurfaceKey,
|
|
2593
|
+
onPointerDown: (event) => {
|
|
2594
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
2595
|
+
trackPointer(event);
|
|
2596
|
+
},
|
|
2597
|
+
onPointerMove: (event) => {
|
|
2598
|
+
if (event.buttons === 1) trackPointer(event);
|
|
2599
|
+
},
|
|
2600
|
+
children: /* @__PURE__ */ jsx34(
|
|
2601
|
+
"span",
|
|
2602
|
+
{
|
|
2603
|
+
"aria-hidden": "true",
|
|
2604
|
+
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",
|
|
2605
|
+
style: { left: `${handle.x * 100}%`, top: `${handle.y * 100}%` }
|
|
2606
|
+
}
|
|
2607
|
+
)
|
|
2528
2608
|
}
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
if (parsed) {
|
|
2545
|
-
setHsva(hsvaFrom(parsed, parsed.alpha, hsva.h));
|
|
2546
|
-
onColorChange(toHex(parsed, showAlpha ? parsed.alpha : 1));
|
|
2609
|
+
),
|
|
2610
|
+
/* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-hue`, children: "Hue" }),
|
|
2611
|
+
/* @__PURE__ */ jsx34(
|
|
2612
|
+
"input",
|
|
2613
|
+
{
|
|
2614
|
+
id: `${fieldId}-hue`,
|
|
2615
|
+
type: "range",
|
|
2616
|
+
min: 0,
|
|
2617
|
+
max: HUE_MAX,
|
|
2618
|
+
step: 1,
|
|
2619
|
+
value: hueSliderValue(hsva.h, HUE_MAX),
|
|
2620
|
+
onChange: (event) => commit({ ...hsva, h: hueAt(+event.target.value / (HUE_MAX + 1)) }),
|
|
2621
|
+
className: SLIDER,
|
|
2622
|
+
style: {
|
|
2623
|
+
backgroundImage: "linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00)"
|
|
2547
2624
|
}
|
|
2548
|
-
},
|
|
2549
|
-
onBlur: () => setDraftHex(null)
|
|
2550
|
-
}
|
|
2551
|
-
),
|
|
2552
|
-
canPickFromScreen && /* @__PURE__ */ jsx34(
|
|
2553
|
-
Button,
|
|
2554
|
-
{
|
|
2555
|
-
type: "button",
|
|
2556
|
-
variant: "outline",
|
|
2557
|
-
size: "icon",
|
|
2558
|
-
"aria-label": "Pick a colour from the screen",
|
|
2559
|
-
onClick: () => void pickFromScreen(),
|
|
2560
|
-
children: /* @__PURE__ */ jsx34(Pipette, { className: "size-4" })
|
|
2561
|
-
}
|
|
2562
|
-
)
|
|
2563
|
-
] }),
|
|
2564
|
-
swatches.length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
|
|
2565
|
-
/* @__PURE__ */ jsx34("p", { className: "text-muted-foreground mb-1 text-xs", children: "Presets" }),
|
|
2566
|
-
/* @__PURE__ */ jsx34("div", { className: "flex flex-wrap gap-1", children: swatches.map((swatch) => /* @__PURE__ */ jsx34(
|
|
2567
|
-
"button",
|
|
2568
|
-
{
|
|
2569
|
-
type: "button",
|
|
2570
|
-
title: swatch.label,
|
|
2571
|
-
"aria-label": swatch.label,
|
|
2572
|
-
className: "size-6 rounded border shadow-sm",
|
|
2573
|
-
style: { backgroundColor: swatch.color },
|
|
2574
|
-
onClick: () => onSwatchSelect?.(swatch)
|
|
2575
|
-
},
|
|
2576
|
-
swatch.id
|
|
2577
|
-
)) })
|
|
2578
|
-
] }),
|
|
2579
|
-
recentColors.length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
|
|
2580
|
-
/* @__PURE__ */ jsx34("p", { className: "text-muted-foreground mb-1 text-xs", children: "Recent" }),
|
|
2581
|
-
/* @__PURE__ */ jsx34("div", { className: "flex flex-wrap gap-1", children: recentColors.map((recent) => /* @__PURE__ */ jsx34(
|
|
2582
|
-
"button",
|
|
2583
|
-
{
|
|
2584
|
-
type: "button",
|
|
2585
|
-
title: recent,
|
|
2586
|
-
"aria-label": recent,
|
|
2587
|
-
className: "size-6 rounded border shadow-sm",
|
|
2588
|
-
style: { backgroundColor: recent },
|
|
2589
|
-
onClick: () => {
|
|
2590
|
-
const parsed = parseHex(recent);
|
|
2591
|
-
if (parsed) commit(hsvaFrom(parsed, parsed.alpha, hsva.h));
|
|
2592
2625
|
}
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2626
|
+
),
|
|
2627
|
+
showAlpha && /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
2628
|
+
/* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-alpha`, children: "Opacity" }),
|
|
2629
|
+
/* @__PURE__ */ jsx34(
|
|
2630
|
+
"input",
|
|
2631
|
+
{
|
|
2632
|
+
id: `${fieldId}-alpha`,
|
|
2633
|
+
type: "range",
|
|
2634
|
+
min: 0,
|
|
2635
|
+
max: 100,
|
|
2636
|
+
step: 1,
|
|
2637
|
+
value: Math.round(hsva.a * 100),
|
|
2638
|
+
onChange: (event) => commit({ ...hsva, a: +event.target.value / 100 }),
|
|
2639
|
+
className: SLIDER,
|
|
2640
|
+
style: {
|
|
2641
|
+
// The ramp runs to the colour being edited, over a chequerboard,
|
|
2642
|
+
// so the track shows what the slider actually controls. Without
|
|
2643
|
+
// any background this rendered as a blank 12px strip whose only
|
|
2644
|
+
// label was screen-reader-only.
|
|
2645
|
+
backgroundImage: `linear-gradient(to right, transparent, ${toHexString({ ...hsva, a: 1 }, false)}), ${CHECKERBOARD}`,
|
|
2646
|
+
backgroundSize: "100% 100%, 8px 8px"
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
)
|
|
2650
|
+
] }),
|
|
2651
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
|
|
2652
|
+
/* @__PURE__ */ jsx34("label", { className: "sr-only", htmlFor: `${fieldId}-hex`, children: "Hex colour" }),
|
|
2653
|
+
/* @__PURE__ */ jsx34(
|
|
2654
|
+
Input,
|
|
2655
|
+
{
|
|
2656
|
+
id: `${fieldId}-hex`,
|
|
2657
|
+
className: "font-mono",
|
|
2658
|
+
value: draftHex ?? rendered,
|
|
2659
|
+
onChange: (event) => {
|
|
2660
|
+
draftRef.current = event.target.value;
|
|
2661
|
+
setDraftHex(event.target.value);
|
|
2662
|
+
},
|
|
2663
|
+
onKeyDown: (event) => {
|
|
2664
|
+
if (event.key !== "Enter") return;
|
|
2665
|
+
if (event.nativeEvent.isComposing || event.keyCode === 229) return;
|
|
2666
|
+
event.preventDefault();
|
|
2667
|
+
commitDraft();
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
),
|
|
2671
|
+
canPickFromScreen && /* @__PURE__ */ jsx34(
|
|
2672
|
+
Button,
|
|
2673
|
+
{
|
|
2674
|
+
type: "button",
|
|
2675
|
+
variant: "outline",
|
|
2676
|
+
size: "icon",
|
|
2677
|
+
"aria-label": "Pick a colour from the screen",
|
|
2678
|
+
onClick: () => void pickFromScreen(),
|
|
2679
|
+
children: /* @__PURE__ */ jsx34(Pipette, { className: "size-4" })
|
|
2680
|
+
}
|
|
2681
|
+
)
|
|
2682
|
+
] }),
|
|
2683
|
+
swatches.length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
|
|
2684
|
+
/* @__PURE__ */ jsx34("p", { className: "text-muted-foreground mb-1 text-xs", children: "Presets" }),
|
|
2685
|
+
/* @__PURE__ */ jsx34("div", { className: "flex flex-wrap gap-1", children: swatches.map((swatch) => /* @__PURE__ */ jsx34(
|
|
2686
|
+
"button",
|
|
2687
|
+
{
|
|
2688
|
+
type: "button",
|
|
2689
|
+
title: swatch.label,
|
|
2690
|
+
"aria-label": swatch.label,
|
|
2691
|
+
className: "size-6 rounded border shadow-sm",
|
|
2692
|
+
style: { backgroundColor: swatch.color },
|
|
2693
|
+
onClick: () => {
|
|
2694
|
+
if (onSwatchSelect === void 0) return;
|
|
2695
|
+
dropDraft();
|
|
2696
|
+
onSwatchSelect(swatch);
|
|
2697
|
+
}
|
|
2698
|
+
},
|
|
2699
|
+
swatch.id
|
|
2700
|
+
)) })
|
|
2701
|
+
] }),
|
|
2702
|
+
recentColors.length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
|
|
2703
|
+
/* @__PURE__ */ jsx34("p", { className: "text-muted-foreground mb-1 text-xs", children: "Recent" }),
|
|
2704
|
+
/* @__PURE__ */ jsx34("div", { className: "flex flex-wrap gap-1", children: recentColors.map((recent) => /* @__PURE__ */ jsx34(
|
|
2705
|
+
"button",
|
|
2706
|
+
{
|
|
2707
|
+
type: "button",
|
|
2708
|
+
title: recent,
|
|
2709
|
+
"aria-label": recent,
|
|
2710
|
+
className: "size-6 rounded border shadow-sm",
|
|
2711
|
+
style: { backgroundColor: recent },
|
|
2712
|
+
onClick: () => {
|
|
2713
|
+
const parsed = parseHex(recent);
|
|
2714
|
+
if (parsed) commit(hsvaFrom(parsed, parsed.alpha, hsva.h));
|
|
2715
|
+
}
|
|
2716
|
+
},
|
|
2717
|
+
recent
|
|
2718
|
+
)) })
|
|
2719
|
+
] })
|
|
2720
|
+
]
|
|
2721
|
+
}
|
|
2722
|
+
);
|
|
2598
2723
|
}
|
|
2599
2724
|
|
|
2600
2725
|
// src/components/context-menu.tsx
|
|
2601
2726
|
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
|
|
2602
2727
|
import { Check as Check4, ChevronRight as ChevronRight2, Circle as Circle2 } from "lucide-react";
|
|
2603
|
-
import * as
|
|
2728
|
+
import * as React11 from "react";
|
|
2604
2729
|
import { jsx as jsx35, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2605
2730
|
var menuItemBase2 = "cursor-pointer transition-colors data-[highlighted]:bg-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
|
|
2606
2731
|
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]";
|
|
@@ -2609,7 +2734,7 @@ var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
|
|
|
2609
2734
|
var ContextMenuGroup = ContextMenuPrimitive.Group;
|
|
2610
2735
|
var ContextMenuSub = ContextMenuPrimitive.Sub;
|
|
2611
2736
|
var ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
|
|
2612
|
-
var ContextMenuSubTrigger =
|
|
2737
|
+
var ContextMenuSubTrigger = React11.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs14(
|
|
2613
2738
|
ContextMenuPrimitive.SubTrigger,
|
|
2614
2739
|
{
|
|
2615
2740
|
ref,
|
|
@@ -2627,7 +2752,7 @@ var ContextMenuSubTrigger = React10.forwardRef(({ className, inset, children, ..
|
|
|
2627
2752
|
}
|
|
2628
2753
|
));
|
|
2629
2754
|
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
|
|
2630
|
-
var ContextMenuSubContent =
|
|
2755
|
+
var ContextMenuSubContent = React11.forwardRef(({ className, ...props }, ref) => {
|
|
2631
2756
|
const portalContainer = usePortalContainer();
|
|
2632
2757
|
return /* @__PURE__ */ jsx35(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx35(
|
|
2633
2758
|
ContextMenuPrimitive.SubContent,
|
|
@@ -2639,7 +2764,7 @@ var ContextMenuSubContent = React10.forwardRef(({ className, ...props }, ref) =>
|
|
|
2639
2764
|
) });
|
|
2640
2765
|
});
|
|
2641
2766
|
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
|
2642
|
-
var ContextMenuContent =
|
|
2767
|
+
var ContextMenuContent = React11.forwardRef(({ className, ...props }, ref) => {
|
|
2643
2768
|
const portalContainer = usePortalContainer();
|
|
2644
2769
|
return /* @__PURE__ */ jsx35(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx35(
|
|
2645
2770
|
ContextMenuPrimitive.Content,
|
|
@@ -2651,7 +2776,7 @@ var ContextMenuContent = React10.forwardRef(({ className, ...props }, ref) => {
|
|
|
2651
2776
|
) });
|
|
2652
2777
|
});
|
|
2653
2778
|
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
|
2654
|
-
var ContextMenuItem =
|
|
2779
|
+
var ContextMenuItem = React11.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx35(
|
|
2655
2780
|
ContextMenuPrimitive.Item,
|
|
2656
2781
|
{
|
|
2657
2782
|
ref,
|
|
@@ -2665,7 +2790,7 @@ var ContextMenuItem = React10.forwardRef(({ className, inset, ...props }, ref) =
|
|
|
2665
2790
|
}
|
|
2666
2791
|
));
|
|
2667
2792
|
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
|
|
2668
|
-
var ContextMenuCheckboxItem =
|
|
2793
|
+
var ContextMenuCheckboxItem = React11.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs14(
|
|
2669
2794
|
ContextMenuPrimitive.CheckboxItem,
|
|
2670
2795
|
{
|
|
2671
2796
|
ref,
|
|
@@ -2683,7 +2808,7 @@ var ContextMenuCheckboxItem = React10.forwardRef(({ className, children, checked
|
|
|
2683
2808
|
}
|
|
2684
2809
|
));
|
|
2685
2810
|
ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
|
|
2686
|
-
var ContextMenuRadioItem =
|
|
2811
|
+
var ContextMenuRadioItem = React11.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs14(
|
|
2687
2812
|
ContextMenuPrimitive.RadioItem,
|
|
2688
2813
|
{
|
|
2689
2814
|
ref,
|
|
@@ -2700,7 +2825,7 @@ var ContextMenuRadioItem = React10.forwardRef(({ className, children, ...props }
|
|
|
2700
2825
|
}
|
|
2701
2826
|
));
|
|
2702
2827
|
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
|
|
2703
|
-
var ContextMenuLabel =
|
|
2828
|
+
var ContextMenuLabel = React11.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx35(
|
|
2704
2829
|
ContextMenuPrimitive.Label,
|
|
2705
2830
|
{
|
|
2706
2831
|
ref,
|
|
@@ -2713,7 +2838,7 @@ var ContextMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref)
|
|
|
2713
2838
|
}
|
|
2714
2839
|
));
|
|
2715
2840
|
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
|
|
2716
|
-
var ContextMenuSeparator =
|
|
2841
|
+
var ContextMenuSeparator = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx35(
|
|
2717
2842
|
ContextMenuPrimitive.Separator,
|
|
2718
2843
|
{
|
|
2719
2844
|
ref,
|
|
@@ -2786,7 +2911,7 @@ var ResizableHandle = ({
|
|
|
2786
2911
|
// src/components/tree-view.tsx
|
|
2787
2912
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
2788
2913
|
import { ChevronRight as ChevronRight3 } from "lucide-react";
|
|
2789
|
-
import * as
|
|
2914
|
+
import * as React12 from "react";
|
|
2790
2915
|
import { jsx as jsx37, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2791
2916
|
var ROW_HEIGHT = 28;
|
|
2792
2917
|
var INDENT_PER_LEVEL = 12;
|
|
@@ -2828,19 +2953,28 @@ function flatten(nodes, expanded) {
|
|
|
2828
2953
|
return rows;
|
|
2829
2954
|
}
|
|
2830
2955
|
function useControllable(controlled, fallback) {
|
|
2831
|
-
const [uncontrolled, setUncontrolled] =
|
|
2956
|
+
const [uncontrolled, setUncontrolled] = React12.useState(fallback);
|
|
2832
2957
|
return [
|
|
2833
2958
|
controlled === void 0 ? uncontrolled : controlled,
|
|
2834
2959
|
setUncontrolled
|
|
2835
2960
|
];
|
|
2836
2961
|
}
|
|
2837
|
-
|
|
2962
|
+
function treeSelectionMode(modifiers) {
|
|
2963
|
+
if (modifiers.shiftKey) return "extend";
|
|
2964
|
+
if (modifiers.metaKey || modifiers.ctrlKey) return "toggle";
|
|
2965
|
+
return "replace";
|
|
2966
|
+
}
|
|
2967
|
+
function isRowSelected(id, primary, selectedIds) {
|
|
2968
|
+
return selectedIds === void 0 ? primary === id : selectedIds.includes(id);
|
|
2969
|
+
}
|
|
2970
|
+
var TreeView = React12.forwardRef(
|
|
2838
2971
|
({
|
|
2839
2972
|
nodes,
|
|
2840
2973
|
expandedIds,
|
|
2841
2974
|
defaultExpandedIds,
|
|
2842
2975
|
onExpandedChange,
|
|
2843
2976
|
selectedId,
|
|
2977
|
+
selectedIds,
|
|
2844
2978
|
defaultSelectedId,
|
|
2845
2979
|
onSelectedChange,
|
|
2846
2980
|
className,
|
|
@@ -2849,8 +2983,8 @@ var TreeView = React11.forwardRef(
|
|
|
2849
2983
|
"aria-describedby": ariaDescribedBy,
|
|
2850
2984
|
...props
|
|
2851
2985
|
}, forwardedRef) => {
|
|
2852
|
-
const scrollRef =
|
|
2853
|
-
const attachScroll =
|
|
2986
|
+
const scrollRef = React12.useRef(null);
|
|
2987
|
+
const attachScroll = React12.useCallback(
|
|
2854
2988
|
(node) => {
|
|
2855
2989
|
scrollRef.current = node;
|
|
2856
2990
|
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
@@ -2864,7 +2998,7 @@ var TreeView = React11.forwardRef(
|
|
|
2864
2998
|
expandedIds === void 0 ? void 0 : [...expandedIds],
|
|
2865
2999
|
[...defaultExpandedIds ?? []]
|
|
2866
3000
|
);
|
|
2867
|
-
const expanded =
|
|
3001
|
+
const expanded = React12.useMemo(
|
|
2868
3002
|
() => new Set(expandedIds ?? expandedState),
|
|
2869
3003
|
[expandedIds, expandedState]
|
|
2870
3004
|
);
|
|
@@ -2872,11 +3006,11 @@ var TreeView = React11.forwardRef(
|
|
|
2872
3006
|
selectedId === void 0 ? void 0 : selectedId,
|
|
2873
3007
|
defaultSelectedId ?? null
|
|
2874
3008
|
);
|
|
2875
|
-
const rows =
|
|
3009
|
+
const rows = React12.useMemo(
|
|
2876
3010
|
() => flatten(nodes, expanded),
|
|
2877
3011
|
[nodes, expanded]
|
|
2878
3012
|
);
|
|
2879
|
-
const [activeId, setActiveId] =
|
|
3013
|
+
const [activeId, setActiveId] = React12.useState(null);
|
|
2880
3014
|
const activeIndex = Math.max(
|
|
2881
3015
|
0,
|
|
2882
3016
|
rows.findIndex((row) => row.node.id === (activeId ?? selected))
|
|
@@ -2898,9 +3032,9 @@ var TreeView = React11.forwardRef(
|
|
|
2898
3032
|
else next.delete(id);
|
|
2899
3033
|
commitExpanded(next);
|
|
2900
3034
|
};
|
|
2901
|
-
const choose = (id) => {
|
|
3035
|
+
const choose = (id, mode = "replace") => {
|
|
2902
3036
|
if (selectedId === void 0) setSelected(id);
|
|
2903
|
-
onSelectedChange?.(id);
|
|
3037
|
+
onSelectedChange?.(id, mode);
|
|
2904
3038
|
};
|
|
2905
3039
|
const focusRow = (index) => {
|
|
2906
3040
|
const row = rows[index];
|
|
@@ -2920,11 +3054,12 @@ var TreeView = React11.forwardRef(
|
|
|
2920
3054
|
}
|
|
2921
3055
|
return from;
|
|
2922
3056
|
};
|
|
2923
|
-
const typeahead =
|
|
3057
|
+
const typeahead = React12.useRef({ query: "", at: 0 });
|
|
2924
3058
|
const onKeyDown = (event) => {
|
|
2925
3059
|
const index = activeIndex;
|
|
2926
3060
|
const row = rows[index];
|
|
2927
3061
|
if (row === void 0) return;
|
|
3062
|
+
if (event.altKey) return;
|
|
2928
3063
|
switch (event.key) {
|
|
2929
3064
|
case "ArrowDown":
|
|
2930
3065
|
event.preventDefault();
|
|
@@ -2979,7 +3114,9 @@ var TreeView = React11.forwardRef(
|
|
|
2979
3114
|
case "Enter":
|
|
2980
3115
|
case " ":
|
|
2981
3116
|
event.preventDefault();
|
|
2982
|
-
if (row.node.disabled !== true)
|
|
3117
|
+
if (row.node.disabled !== true) {
|
|
3118
|
+
choose(row.node.id, treeSelectionMode(event));
|
|
3119
|
+
}
|
|
2983
3120
|
return;
|
|
2984
3121
|
case "*": {
|
|
2985
3122
|
event.preventDefault();
|
|
@@ -3027,6 +3164,7 @@ var TreeView = React11.forwardRef(
|
|
|
3027
3164
|
"div",
|
|
3028
3165
|
{
|
|
3029
3166
|
role: "tree",
|
|
3167
|
+
"aria-multiselectable": selectedIds === void 0 ? void 0 : true,
|
|
3030
3168
|
"aria-label": ariaLabel,
|
|
3031
3169
|
"aria-labelledby": ariaLabelledBy,
|
|
3032
3170
|
"aria-describedby": ariaDescribedBy,
|
|
@@ -3035,7 +3173,12 @@ var TreeView = React11.forwardRef(
|
|
|
3035
3173
|
children: virtualItems.map((item) => {
|
|
3036
3174
|
const row = rows[item.index];
|
|
3037
3175
|
if (row === void 0) return null;
|
|
3038
|
-
const isSelected =
|
|
3176
|
+
const isSelected = isRowSelected(
|
|
3177
|
+
row.node.id,
|
|
3178
|
+
selected,
|
|
3179
|
+
selectedIds
|
|
3180
|
+
);
|
|
3181
|
+
const isPrimary = selected === row.node.id;
|
|
3039
3182
|
return /* @__PURE__ */ jsxs16(
|
|
3040
3183
|
"div",
|
|
3041
3184
|
{
|
|
@@ -3049,16 +3192,21 @@ var TreeView = React11.forwardRef(
|
|
|
3049
3192
|
"aria-disabled": row.node.disabled === true ? true : void 0,
|
|
3050
3193
|
tabIndex: item.index === tabStopIndex ? 0 : -1,
|
|
3051
3194
|
onFocus: () => setActiveId(row.node.id),
|
|
3052
|
-
onClick: () => {
|
|
3195
|
+
onClick: (event) => {
|
|
3053
3196
|
if (row.node.disabled === true) return;
|
|
3054
3197
|
setActiveId(row.node.id);
|
|
3055
|
-
choose(row.node.id);
|
|
3198
|
+
choose(row.node.id, treeSelectionMode(event));
|
|
3056
3199
|
},
|
|
3057
3200
|
className: cn(
|
|
3058
3201
|
"absolute left-0 flex w-full select-none items-center gap-1 rounded-sm pr-2 text-sm outline-none",
|
|
3059
3202
|
"focus-visible:ring-1 focus-visible:ring-ring",
|
|
3060
3203
|
row.node.disabled === true ? "pointer-events-none opacity-50" : "cursor-pointer",
|
|
3061
|
-
isSelected ? "bg-muted text-foreground" : "hover:bg-muted/50"
|
|
3204
|
+
isSelected ? "bg-muted text-foreground" : "hover:bg-muted/50",
|
|
3205
|
+
// WEIGHT, not a second colour. Every row here is selected and
|
|
3206
|
+
// an action applies to all of them; what a reader needs is
|
|
3207
|
+
// which one the detail panel describes, and a second colour
|
|
3208
|
+
// would have to mean a second kind of selected.
|
|
3209
|
+
isSelected && isPrimary && "font-medium"
|
|
3062
3210
|
),
|
|
3063
3211
|
style: {
|
|
3064
3212
|
height: item.size,
|
|
@@ -3104,7 +3252,7 @@ TreeView.displayName = "TreeView";
|
|
|
3104
3252
|
|
|
3105
3253
|
// src/components/slider.tsx
|
|
3106
3254
|
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
3107
|
-
import * as
|
|
3255
|
+
import * as React13 from "react";
|
|
3108
3256
|
|
|
3109
3257
|
// src/lib/dev-warn.ts
|
|
3110
3258
|
var emitted = /* @__PURE__ */ new Set();
|
|
@@ -3130,7 +3278,7 @@ function thumbCount(value, defaultValue) {
|
|
|
3130
3278
|
function hasAccessibleName(value) {
|
|
3131
3279
|
return value !== void 0 && value.trim() !== "";
|
|
3132
3280
|
}
|
|
3133
|
-
var Slider =
|
|
3281
|
+
var Slider = React13.forwardRef(
|
|
3134
3282
|
({
|
|
3135
3283
|
className,
|
|
3136
3284
|
value,
|
|
@@ -3141,7 +3289,7 @@ var Slider = React12.forwardRef(
|
|
|
3141
3289
|
"aria-labelledby": ariaLabelledBy,
|
|
3142
3290
|
...props
|
|
3143
3291
|
}, ref) => {
|
|
3144
|
-
const initialUncontrolledCount =
|
|
3292
|
+
const initialUncontrolledCount = React13.useRef(
|
|
3145
3293
|
thumbCount(void 0, defaultValue)
|
|
3146
3294
|
).current;
|
|
3147
3295
|
const count = value?.length ?? initialUncontrolledCount;
|
|
@@ -3255,7 +3403,7 @@ var Slider = React12.forwardRef(
|
|
|
3255
3403
|
Slider.displayName = SliderPrimitive.Root.displayName;
|
|
3256
3404
|
|
|
3257
3405
|
// src/lib/shortcuts/react.tsx
|
|
3258
|
-
import * as
|
|
3406
|
+
import * as React14 from "react";
|
|
3259
3407
|
|
|
3260
3408
|
// src/lib/shortcuts/key-spec.ts
|
|
3261
3409
|
function normalizeKey(key) {
|
|
@@ -3784,9 +3932,8 @@ var FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
|
3784
3932
|
|
|
3785
3933
|
// src/lib/shortcuts/react.tsx
|
|
3786
3934
|
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
3787
|
-
var ShortcutContext =
|
|
3935
|
+
var ShortcutContext = React14.createContext(null);
|
|
3788
3936
|
var ownersByTarget = /* @__PURE__ */ new WeakMap();
|
|
3789
|
-
var useIsomorphicLayoutEffect = typeof document === "undefined" ? React13.useEffect : React13.useLayoutEffect;
|
|
3790
3937
|
function optionsFingerprint(options) {
|
|
3791
3938
|
return [
|
|
3792
3939
|
options.isApple ?? "auto",
|
|
@@ -3799,13 +3946,13 @@ function ShortcutProvider({
|
|
|
3799
3946
|
target,
|
|
3800
3947
|
...managerOptions
|
|
3801
3948
|
}) {
|
|
3802
|
-
const parent =
|
|
3949
|
+
const parent = React14.useContext(ShortcutContext);
|
|
3803
3950
|
const resolvedTarget = target === null ? null : target ?? (typeof document === "undefined" ? null : document);
|
|
3804
3951
|
const nestedOnSameTarget = parent !== null && parent.target === resolvedTarget;
|
|
3805
|
-
const optionsRef =
|
|
3806
|
-
const ownManagers =
|
|
3807
|
-
const ownDetached =
|
|
3808
|
-
const detached =
|
|
3952
|
+
const optionsRef = React14.useRef(managerOptions);
|
|
3953
|
+
const ownManagers = React14.useRef(/* @__PURE__ */ new WeakMap());
|
|
3954
|
+
const ownDetached = React14.useRef(null);
|
|
3955
|
+
const detached = React14.useMemo(() => {
|
|
3809
3956
|
if (resolvedTarget === null) {
|
|
3810
3957
|
ownDetached.current ??= createShortcutManager(optionsRef.current);
|
|
3811
3958
|
return ownDetached.current;
|
|
@@ -3861,7 +4008,7 @@ function ShortcutProvider({
|
|
|
3861
4008
|
};
|
|
3862
4009
|
}, [resolvedTarget, manager]);
|
|
3863
4010
|
const depth = nestedOnSameTarget && parent ? parent.depth : 0;
|
|
3864
|
-
const value =
|
|
4011
|
+
const value = React14.useMemo(
|
|
3865
4012
|
() => ({ manager, depth, target: resolvedTarget, options: fingerprint }),
|
|
3866
4013
|
[manager, depth, resolvedTarget, fingerprint]
|
|
3867
4014
|
);
|
|
@@ -3870,11 +4017,11 @@ function ShortcutProvider({
|
|
|
3870
4017
|
function ShortcutScope({
|
|
3871
4018
|
children
|
|
3872
4019
|
}) {
|
|
3873
|
-
const parent =
|
|
4020
|
+
const parent = React14.useContext(ShortcutContext);
|
|
3874
4021
|
if (!parent) {
|
|
3875
4022
|
throw new Error("ShortcutScope must be rendered inside a ShortcutProvider");
|
|
3876
4023
|
}
|
|
3877
|
-
const value =
|
|
4024
|
+
const value = React14.useMemo(
|
|
3878
4025
|
() => ({
|
|
3879
4026
|
manager: parent.manager,
|
|
3880
4027
|
depth: parent.depth + 1,
|
|
@@ -3888,13 +4035,13 @@ function ShortcutScope({
|
|
|
3888
4035
|
return /* @__PURE__ */ jsx39(ShortcutContext.Provider, { value, children });
|
|
3889
4036
|
}
|
|
3890
4037
|
function useShortcuts(bindings, options) {
|
|
3891
|
-
const context =
|
|
4038
|
+
const context = React14.useContext(ShortcutContext);
|
|
3892
4039
|
if (!context) {
|
|
3893
4040
|
throw new Error("useShortcuts must be called inside a ShortcutProvider");
|
|
3894
4041
|
}
|
|
3895
4042
|
const { manager, depth } = context;
|
|
3896
|
-
const registration =
|
|
3897
|
-
const latest =
|
|
4043
|
+
const registration = React14.useRef(null);
|
|
4044
|
+
const latest = React14.useRef({ bindings, options });
|
|
3898
4045
|
useIsomorphicLayoutEffect(() => {
|
|
3899
4046
|
registration.current = manager.register([], {
|
|
3900
4047
|
name: latest.current.options.name,
|
|
@@ -3917,7 +4064,7 @@ function useShortcuts(bindings, options) {
|
|
|
3917
4064
|
});
|
|
3918
4065
|
}
|
|
3919
4066
|
function useShortcutManager() {
|
|
3920
|
-
const context =
|
|
4067
|
+
const context = React14.useContext(ShortcutContext);
|
|
3921
4068
|
if (!context) {
|
|
3922
4069
|
throw new Error(
|
|
3923
4070
|
"useShortcutManager must be called inside a ShortcutProvider"
|
|
@@ -3927,7 +4074,7 @@ function useShortcutManager() {
|
|
|
3927
4074
|
}
|
|
3928
4075
|
function useActiveShortcuts() {
|
|
3929
4076
|
const manager = useShortcutManager();
|
|
3930
|
-
return
|
|
4077
|
+
return React14.useSyncExternalStore(
|
|
3931
4078
|
manager.subscribe,
|
|
3932
4079
|
manager.activeBindings,
|
|
3933
4080
|
manager.activeBindings
|
|
@@ -4054,29 +4201,12 @@ function FormSection({
|
|
|
4054
4201
|
),
|
|
4055
4202
|
description ? /* @__PURE__ */ jsx41("p", { className: "text-sm text-muted-foreground", children: description }) : null
|
|
4056
4203
|
] }),
|
|
4057
|
-
/* @__PURE__ */ jsx41(Card, { className: "overflow-hidden", children: /* @__PURE__ */ jsx41("div", { className: "divide-y divide-foreground/10 px-6", children }) })
|
|
4204
|
+
/* @__PURE__ */ jsx41(Card, { className: "overflow-hidden", children: /* @__PURE__ */ jsx41("div", { className: "nx-form-section-rows divide-y divide-foreground/10 px-6", children }) })
|
|
4058
4205
|
] });
|
|
4059
4206
|
}
|
|
4060
4207
|
|
|
4061
|
-
// src/components/form-
|
|
4062
|
-
import { cva as cva14 } from "class-variance-authority";
|
|
4208
|
+
// src/components/form-actions.tsx
|
|
4063
4209
|
import { jsx as jsx42, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
4064
|
-
var measure = cva14("mx-auto w-full px-6 py-8", {
|
|
4065
|
-
variants: {
|
|
4066
|
-
width: {
|
|
4067
|
-
form: "max-w-[56rem]",
|
|
4068
|
-
wide: "max-w-[72rem]"
|
|
4069
|
-
}
|
|
4070
|
-
},
|
|
4071
|
-
defaultVariants: { width: "form" }
|
|
4072
|
-
});
|
|
4073
|
-
function FormLayout({
|
|
4074
|
-
width = "form",
|
|
4075
|
-
className,
|
|
4076
|
-
children
|
|
4077
|
-
}) {
|
|
4078
|
-
return /* @__PURE__ */ jsx42("div", { className: cn(measure({ width }), className), children });
|
|
4079
|
-
}
|
|
4080
4210
|
function FormActions({ dirty, className, children }) {
|
|
4081
4211
|
return /* @__PURE__ */ jsxs20(
|
|
4082
4212
|
"div",
|
|
@@ -4099,6 +4229,127 @@ function FormActions({ dirty, className, children }) {
|
|
|
4099
4229
|
}
|
|
4100
4230
|
);
|
|
4101
4231
|
}
|
|
4232
|
+
|
|
4233
|
+
// src/components/page-shell.tsx
|
|
4234
|
+
import {
|
|
4235
|
+
createContext as createContext5,
|
|
4236
|
+
forwardRef as forwardRef28,
|
|
4237
|
+
useCallback as useCallback2,
|
|
4238
|
+
useContext as useContext5,
|
|
4239
|
+
useEffect as useEffect4,
|
|
4240
|
+
useRef as useRef5
|
|
4241
|
+
} from "react";
|
|
4242
|
+
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
4243
|
+
function hasBareTextChild(shell) {
|
|
4244
|
+
return Array.from(shell.childNodes).some(
|
|
4245
|
+
(node) => node.nodeType === Node.TEXT_NODE && node.textContent?.trim() !== ""
|
|
4246
|
+
);
|
|
4247
|
+
}
|
|
4248
|
+
var InsideShell = createContext5(false);
|
|
4249
|
+
function hasDisplayContentsChild(shell) {
|
|
4250
|
+
return Array.from(shell.children).some(
|
|
4251
|
+
(child) => getComputedStyle(child).display === "contents"
|
|
4252
|
+
);
|
|
4253
|
+
}
|
|
4254
|
+
var SHELL_MEASURE = {
|
|
4255
|
+
form: "var(--nx-measure-form)",
|
|
4256
|
+
wide: "var(--nx-measure-wide)",
|
|
4257
|
+
full: "100%"
|
|
4258
|
+
};
|
|
4259
|
+
var PageShell = forwardRef28(
|
|
4260
|
+
({ width = "form", className, children, style, ...props }, ref) => {
|
|
4261
|
+
const shellRef = useRef5(null);
|
|
4262
|
+
const attachRef = useCallback2(
|
|
4263
|
+
(node) => {
|
|
4264
|
+
shellRef.current = node;
|
|
4265
|
+
if (typeof ref === "function") return ref(node);
|
|
4266
|
+
if (ref) ref.current = node;
|
|
4267
|
+
},
|
|
4268
|
+
[ref]
|
|
4269
|
+
);
|
|
4270
|
+
const nested = useContext5(InsideShell);
|
|
4271
|
+
useEffect4(() => {
|
|
4272
|
+
if (!isDevelopmentRuntime()) return;
|
|
4273
|
+
const shell = shellRef.current;
|
|
4274
|
+
if (!shell) return;
|
|
4275
|
+
devWarnOnce(
|
|
4276
|
+
!nested,
|
|
4277
|
+
"PageShell: an ancestor already renders a PageShell. The two grids each add a pair of gutter tracks, so this page's content is inset twice. Remove this shell, or move the outer one."
|
|
4278
|
+
);
|
|
4279
|
+
const check = () => {
|
|
4280
|
+
devWarnOnce(
|
|
4281
|
+
!hasBareTextChild(shell),
|
|
4282
|
+
"PageShell: a direct child renders as bare text. CSS Grid wraps it in an anonymous grid item, which no selector can reach, so it is placed in the gutter rather than the content column and sits outside the page's measure. Wrap it in an element \u2014 a `<p>`, or the section it belongs to."
|
|
4283
|
+
);
|
|
4284
|
+
devWarnOnce(
|
|
4285
|
+
!hasDisplayContentsChild(shell),
|
|
4286
|
+
"PageShell: a direct child has `display: contents`, so it generates no grid item and the content-column rule has nothing to apply to. Its own children are promoted into this grid, match no selector, and are placed from the gutter onward. Give the child a box, or move `display: contents` inside it."
|
|
4287
|
+
);
|
|
4288
|
+
};
|
|
4289
|
+
check();
|
|
4290
|
+
const observer = new MutationObserver(check);
|
|
4291
|
+
observer.observe(shell, { childList: true });
|
|
4292
|
+
return () => {
|
|
4293
|
+
observer.disconnect();
|
|
4294
|
+
};
|
|
4295
|
+
});
|
|
4296
|
+
const shellStyle = {
|
|
4297
|
+
...style,
|
|
4298
|
+
"--nx-shell-measure": SHELL_MEASURE[width]
|
|
4299
|
+
};
|
|
4300
|
+
return /* @__PURE__ */ jsx43(InsideShell.Provider, { value: true, children: /* @__PURE__ */ jsx43(
|
|
4301
|
+
"div",
|
|
4302
|
+
{
|
|
4303
|
+
ref: attachRef,
|
|
4304
|
+
"data-slot": "page-shell",
|
|
4305
|
+
style: shellStyle,
|
|
4306
|
+
className: cn("nx-page-shell py-8", className),
|
|
4307
|
+
...props,
|
|
4308
|
+
children
|
|
4309
|
+
}
|
|
4310
|
+
) });
|
|
4311
|
+
}
|
|
4312
|
+
);
|
|
4313
|
+
PageShell.displayName = "PageShell";
|
|
4314
|
+
var Bleed = forwardRef28(
|
|
4315
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx43(
|
|
4316
|
+
"div",
|
|
4317
|
+
{
|
|
4318
|
+
ref,
|
|
4319
|
+
"data-slot": "bleed",
|
|
4320
|
+
className: cn("nx-bleed", className),
|
|
4321
|
+
...props,
|
|
4322
|
+
children
|
|
4323
|
+
}
|
|
4324
|
+
)
|
|
4325
|
+
);
|
|
4326
|
+
Bleed.displayName = "Bleed";
|
|
4327
|
+
|
|
4328
|
+
// src/components/page-header.tsx
|
|
4329
|
+
import { forwardRef as forwardRef29 } from "react";
|
|
4330
|
+
import { jsx as jsx44, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4331
|
+
var PageHeader = forwardRef29(
|
|
4332
|
+
({ title, description, breadcrumbs, actions, className, ...props }, ref) => /* @__PURE__ */ jsxs21(
|
|
4333
|
+
"header",
|
|
4334
|
+
{
|
|
4335
|
+
ref,
|
|
4336
|
+
"data-slot": "page-header",
|
|
4337
|
+
className: cn("mb-8", className),
|
|
4338
|
+
...props,
|
|
4339
|
+
children: [
|
|
4340
|
+
breadcrumbs ? /* @__PURE__ */ jsx44("div", { className: "mb-6", children: breadcrumbs }) : null,
|
|
4341
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex flex-col justify-between gap-4 sm:flex-row sm:items-center", children: [
|
|
4342
|
+
/* @__PURE__ */ jsxs21("div", { className: "space-y-1", children: [
|
|
4343
|
+
/* @__PURE__ */ jsx44("h1", { className: "text-xl font-semibold tracking-tight", children: title }),
|
|
4344
|
+
description ? /* @__PURE__ */ jsx44("p", { className: "mt-1 text-sm font-normal text-muted-foreground", children: description }) : null
|
|
4345
|
+
] }),
|
|
4346
|
+
actions ? /* @__PURE__ */ jsx44("div", { className: "flex items-center gap-3", children: actions }) : null
|
|
4347
|
+
] })
|
|
4348
|
+
]
|
|
4349
|
+
}
|
|
4350
|
+
)
|
|
4351
|
+
);
|
|
4352
|
+
PageHeader.displayName = "PageHeader";
|
|
4102
4353
|
export {
|
|
4103
4354
|
Accordion,
|
|
4104
4355
|
AccordionContent,
|
|
@@ -4122,6 +4373,7 @@ export {
|
|
|
4122
4373
|
AvatarFallback,
|
|
4123
4374
|
AvatarImage,
|
|
4124
4375
|
Badge,
|
|
4376
|
+
Bleed,
|
|
4125
4377
|
Button,
|
|
4126
4378
|
Card,
|
|
4127
4379
|
CardAction,
|
|
@@ -4186,11 +4438,12 @@ export {
|
|
|
4186
4438
|
FieldShell,
|
|
4187
4439
|
FormActions,
|
|
4188
4440
|
FormLabelWithTooltip,
|
|
4189
|
-
FormLayout,
|
|
4190
4441
|
FormSection,
|
|
4191
4442
|
Grid,
|
|
4192
4443
|
Input,
|
|
4193
4444
|
Label,
|
|
4445
|
+
PageHeader,
|
|
4446
|
+
PageShell,
|
|
4194
4447
|
Popover,
|
|
4195
4448
|
PopoverAnchor,
|
|
4196
4449
|
PopoverContent,
|
|
@@ -4202,6 +4455,7 @@ export {
|
|
|
4202
4455
|
ResizableHandle,
|
|
4203
4456
|
ResizablePanel,
|
|
4204
4457
|
ResizablePanelGroup,
|
|
4458
|
+
SHELL_MEASURE,
|
|
4205
4459
|
Select,
|
|
4206
4460
|
SelectContent,
|
|
4207
4461
|
SelectGroup,
|
|
@@ -4260,8 +4514,10 @@ export {
|
|
|
4260
4514
|
badgeVariants,
|
|
4261
4515
|
buttonVariants,
|
|
4262
4516
|
cardVariants,
|
|
4517
|
+
chordMatches,
|
|
4263
4518
|
commandDefaultFilter,
|
|
4264
4519
|
createShortcutManager,
|
|
4520
|
+
detectApplePlatform,
|
|
4265
4521
|
dialogContentVariants,
|
|
4266
4522
|
inputVariants,
|
|
4267
4523
|
parseKeys,
|
|
@@ -4271,6 +4527,8 @@ export {
|
|
|
4271
4527
|
spinnerVariants,
|
|
4272
4528
|
toast,
|
|
4273
4529
|
useActiveShortcuts,
|
|
4530
|
+
useCommandHighlight,
|
|
4531
|
+
useIsomorphicLayoutEffect,
|
|
4274
4532
|
usePortalContainer,
|
|
4275
4533
|
useShortcutManager,
|
|
4276
4534
|
useShortcuts
|