@lovett/ui 0.0.10 → 0.0.11
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.d.ts +666 -13
- package/dist/index.js +1835 -344
- package/dist/index.js.map +1 -1
- package/dist/styles.css +16 -2
- package/dist/theme-v2.css +228 -0
- package/dist/tokens.css +9 -0
- package/package.json +1 -1
- package/src/__tests__/anchor.test.tsx +422 -0
- package/src/__tests__/combobox.test.tsx +677 -0
- package/src/__tests__/dropdown-menu.test.tsx +418 -0
- package/src/__tests__/helpers/geometry.ts +58 -0
- package/src/__tests__/layer-stack.test.tsx +228 -0
- package/src/__tests__/popover.test.tsx +460 -0
- package/src/__tests__/select.test.tsx +543 -0
- package/src/__tests__/tooltip.test.tsx +355 -0
- package/src/calculator-shell-v2.tsx +19 -39
- package/src/combobox.tsx +796 -0
- package/src/dropdown-menu.tsx +142 -152
- package/src/index.ts +106 -0
- package/src/lib/anchor.ts +427 -0
- package/src/lib/focus.ts +32 -0
- package/src/lib/layer-stack.ts +188 -0
- package/src/lib/refs.ts +31 -0
- package/src/metric-card.tsx +57 -22
- package/src/modal.tsx +31 -48
- package/src/popover.tsx +407 -0
- package/src/select.tsx +646 -0
- package/src/stat-row.tsx +108 -70
- package/src/styles.css +16 -2
- package/src/tokens.css +9 -0
- package/src/tooltip.tsx +297 -0
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React2, { forwardRef, Children, isValidElement, useState, createContext, useContext, useId, useRef, useEffect,
|
|
1
|
+
import React2, { forwardRef, Children, isValidElement, useState, createContext, useContext, useId, useRef, useEffect, cloneElement, useMemo, useCallback, useLayoutEffect, memo, Fragment as Fragment$1 } from 'react';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { twMerge } from 'tailwind-merge';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
|
-
import { Minus, Check, EyeOff, Eye,
|
|
5
|
+
import { Minus, Check, ChevronDown, X, Loader2, EyeOff, Eye, Search, Play, VolumeX, Volume2, Pencil, House, GripVertical, ChevronUp, ChevronsUpDown, ChevronLeft, ChevronRight, SlidersHorizontal, Copy, Plus, FolderClosed, FolderPlus, Folder, Paperclip, Upload, Image, Code, Table as Table$1, FileText, FileType, AlertCircle, RotateCcw, Link2, ArrowRight, MoreHorizontal, ThumbsUp as ThumbsUp$1, MessageCircle, Share2, Lock, Info, ExternalLink } from 'lucide-react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
import { Link } from 'react-router-dom';
|
|
8
8
|
import { toast, Toaster as Toaster$1 } from 'sonner';
|
|
@@ -17,7 +17,7 @@ import css from 'react-syntax-highlighter/dist/esm/languages/prism/css';
|
|
|
17
17
|
import diff from 'react-syntax-highlighter/dist/esm/languages/prism/diff';
|
|
18
18
|
import javascript from 'react-syntax-highlighter/dist/esm/languages/prism/javascript';
|
|
19
19
|
import json from 'react-syntax-highlighter/dist/esm/languages/prism/json';
|
|
20
|
-
import
|
|
20
|
+
import jsx70 from 'react-syntax-highlighter/dist/esm/languages/prism/jsx';
|
|
21
21
|
import markdown from 'react-syntax-highlighter/dist/esm/languages/prism/markdown';
|
|
22
22
|
import markup from 'react-syntax-highlighter/dist/esm/languages/prism/markup';
|
|
23
23
|
import python from 'react-syntax-highlighter/dist/esm/languages/prism/python';
|
|
@@ -481,7 +481,8 @@ var Textarea = forwardRef(function Textarea2({ error, shellClassName, className,
|
|
|
481
481
|
}
|
|
482
482
|
);
|
|
483
483
|
});
|
|
484
|
-
|
|
484
|
+
|
|
485
|
+
// src/lib/focus.ts
|
|
485
486
|
var FOCUSABLE_SELECTOR = [
|
|
486
487
|
"a[href]",
|
|
487
488
|
"area[href]",
|
|
@@ -494,11 +495,90 @@ var FOCUSABLE_SELECTOR = [
|
|
|
494
495
|
'[contenteditable="true"]',
|
|
495
496
|
"[tabindex]"
|
|
496
497
|
].join(",");
|
|
497
|
-
function tabbablesWithin(
|
|
498
|
-
return Array.from(
|
|
498
|
+
function tabbablesWithin(root) {
|
|
499
|
+
return Array.from(root.querySelectorAll(FOCUSABLE_SELECTOR)).filter(
|
|
499
500
|
(el) => el.tabIndex >= 0 && !el.hasAttribute("inert") && el.getAttribute("aria-hidden") !== "true" && !el.closest("[hidden]")
|
|
500
501
|
);
|
|
501
502
|
}
|
|
503
|
+
var stack = [];
|
|
504
|
+
var listening = false;
|
|
505
|
+
function onDocumentKeyDown(event) {
|
|
506
|
+
if (event.key !== "Escape") return;
|
|
507
|
+
const top = stack[stack.length - 1];
|
|
508
|
+
if (!top) return;
|
|
509
|
+
event.stopPropagation();
|
|
510
|
+
top.onEscape(event);
|
|
511
|
+
}
|
|
512
|
+
function pushLayer(record) {
|
|
513
|
+
stack.push(record);
|
|
514
|
+
if (!listening) {
|
|
515
|
+
document.addEventListener("keydown", onDocumentKeyDown);
|
|
516
|
+
listening = true;
|
|
517
|
+
}
|
|
518
|
+
return () => {
|
|
519
|
+
const at = stack.lastIndexOf(record);
|
|
520
|
+
if (at !== -1) stack.splice(at, 1);
|
|
521
|
+
if (stack.length === 0 && listening) {
|
|
522
|
+
document.removeEventListener("keydown", onDocumentKeyDown);
|
|
523
|
+
listening = false;
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
function useLayer(options) {
|
|
528
|
+
const { enabled, kind, elementRef, onEscape } = options;
|
|
529
|
+
const onEscapeRef = useRef(onEscape);
|
|
530
|
+
useEffect(() => {
|
|
531
|
+
onEscapeRef.current = onEscape;
|
|
532
|
+
});
|
|
533
|
+
const recordRef = useRef(null);
|
|
534
|
+
useEffect(() => {
|
|
535
|
+
if (!enabled) return;
|
|
536
|
+
const record = {
|
|
537
|
+
kind,
|
|
538
|
+
element: () => elementRef?.current ?? null,
|
|
539
|
+
onEscape: (event) => onEscapeRef.current(event)
|
|
540
|
+
};
|
|
541
|
+
recordRef.current = record;
|
|
542
|
+
const pop = pushLayer(record);
|
|
543
|
+
return () => {
|
|
544
|
+
pop();
|
|
545
|
+
if (recordRef.current === record) recordRef.current = null;
|
|
546
|
+
};
|
|
547
|
+
}, [enabled, kind, elementRef]);
|
|
548
|
+
return useMemo(
|
|
549
|
+
() => ({
|
|
550
|
+
isTop: () => {
|
|
551
|
+
const record = recordRef.current;
|
|
552
|
+
return record !== null && stack[stack.length - 1] === record;
|
|
553
|
+
},
|
|
554
|
+
isTopOfKind: () => {
|
|
555
|
+
const record = recordRef.current;
|
|
556
|
+
if (!record) return false;
|
|
557
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
558
|
+
const layer = stack[i];
|
|
559
|
+
if (layer === record) return true;
|
|
560
|
+
if (layer?.kind === record.kind) return false;
|
|
561
|
+
}
|
|
562
|
+
return false;
|
|
563
|
+
},
|
|
564
|
+
containsInLayerAbove: (node) => {
|
|
565
|
+
const record = recordRef.current;
|
|
566
|
+
if (!record) return false;
|
|
567
|
+
const at = stack.indexOf(record);
|
|
568
|
+
if (at === -1) return false;
|
|
569
|
+
for (let i = at + 1; i < stack.length; i++) {
|
|
570
|
+
if (stack[i]?.element()?.contains(node)) return true;
|
|
571
|
+
}
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
}),
|
|
575
|
+
[]
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
function useEscapeKey(onEscape, options = {}) {
|
|
579
|
+
const { enabled = true, kind = "popover" } = options;
|
|
580
|
+
return useLayer({ enabled, kind, onEscape });
|
|
581
|
+
}
|
|
502
582
|
function Modal({ isOpen, onClose, title, children, className, ariaLabel }) {
|
|
503
583
|
const panelRef = useRef(null);
|
|
504
584
|
const titleId = useId();
|
|
@@ -507,26 +587,25 @@ function Modal({ isOpen, onClose, title, children, className, ariaLabel }) {
|
|
|
507
587
|
const panel = panelRef.current;
|
|
508
588
|
if (!panel) return;
|
|
509
589
|
const previous = document.activeElement instanceof HTMLElement && document.activeElement !== document.body ? document.activeElement : null;
|
|
510
|
-
openPanels.push(panel);
|
|
511
590
|
const initial = panel.querySelector("[data-autofocus]");
|
|
512
591
|
(initial ?? panel).focus();
|
|
513
592
|
return () => {
|
|
514
|
-
const at = openPanels.indexOf(panel);
|
|
515
|
-
if (at !== -1) openPanels.splice(at, 1);
|
|
516
593
|
if (previous && previous.isConnected) previous.focus();
|
|
517
594
|
};
|
|
518
595
|
}, [isOpen]);
|
|
596
|
+
const layer = useLayer({
|
|
597
|
+
enabled: isOpen,
|
|
598
|
+
kind: "modal",
|
|
599
|
+
elementRef: panelRef,
|
|
600
|
+
onEscape: () => onClose()
|
|
601
|
+
});
|
|
519
602
|
useEffect(() => {
|
|
520
603
|
if (!isOpen) return;
|
|
521
604
|
const panel = panelRef.current;
|
|
522
605
|
if (!panel) return;
|
|
523
606
|
const handleKeyDown = (e) => {
|
|
524
|
-
if (openPanels[openPanels.length - 1] !== panel) return;
|
|
525
|
-
if (e.key === "Escape") {
|
|
526
|
-
onClose();
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
607
|
if (e.key !== "Tab") return;
|
|
608
|
+
if (!layer.isTopOfKind()) return;
|
|
530
609
|
const active = document.activeElement;
|
|
531
610
|
if (!(active instanceof HTMLElement) || !panel.contains(active)) return;
|
|
532
611
|
const tabbables = tabbablesWithin(panel);
|
|
@@ -554,7 +633,7 @@ function Modal({ isOpen, onClose, title, children, className, ariaLabel }) {
|
|
|
554
633
|
};
|
|
555
634
|
document.addEventListener("keydown", handleKeyDown);
|
|
556
635
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
557
|
-
}, [isOpen,
|
|
636
|
+
}, [isOpen, layer]);
|
|
558
637
|
if (!isOpen) return null;
|
|
559
638
|
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
|
|
560
639
|
/* @__PURE__ */ jsx(
|
|
@@ -2596,6 +2675,16 @@ function OptionTileGroup(props) {
|
|
|
2596
2675
|
}
|
|
2597
2676
|
);
|
|
2598
2677
|
}
|
|
2678
|
+
|
|
2679
|
+
// src/lib/clipboard.ts
|
|
2680
|
+
async function copyText(value, label) {
|
|
2681
|
+
try {
|
|
2682
|
+
await navigator.clipboard.writeText(value);
|
|
2683
|
+
toast.success(label ? `Copied ${label}` : `Copied ${value}`);
|
|
2684
|
+
} catch {
|
|
2685
|
+
toast.error("Copy failed");
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2599
2688
|
var TONE_COLOR = {
|
|
2600
2689
|
neutral: "rgb(var(--foreground))",
|
|
2601
2690
|
accent: "rgb(var(--accent))",
|
|
@@ -2610,7 +2699,9 @@ function MetricCard({
|
|
|
2610
2699
|
tone = "neutral",
|
|
2611
2700
|
icon,
|
|
2612
2701
|
labelPosition = "bottom",
|
|
2613
|
-
className
|
|
2702
|
+
className,
|
|
2703
|
+
copyable = false,
|
|
2704
|
+
copyValue
|
|
2614
2705
|
}) {
|
|
2615
2706
|
const labelEl = labelPosition === "top" ? /* @__PURE__ */ jsx(
|
|
2616
2707
|
"div",
|
|
@@ -2638,24 +2729,40 @@ function MetricCard({
|
|
|
2638
2729
|
}
|
|
2639
2730
|
)
|
|
2640
2731
|
] });
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2732
|
+
const body = labelPosition === "top" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2733
|
+
labelEl,
|
|
2734
|
+
valueEl
|
|
2735
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2736
|
+
valueEl,
|
|
2737
|
+
labelEl
|
|
2738
|
+
] });
|
|
2739
|
+
const surfaceClass = className ?? "flex flex-col gap-1 px-4 py-3 border";
|
|
2740
|
+
const surfaceStyle = {
|
|
2741
|
+
background: "rgb(var(--surface-overlay-soft))",
|
|
2742
|
+
borderColor: "rgb(var(--border))",
|
|
2743
|
+
borderRadius: "var(--radius-lg)"
|
|
2744
|
+
};
|
|
2745
|
+
const text = copyValue ?? (typeof value === "string" ? value : void 0);
|
|
2746
|
+
if (copyable && text !== void 0) {
|
|
2747
|
+
return /* @__PURE__ */ jsx(
|
|
2748
|
+
"button",
|
|
2749
|
+
{
|
|
2750
|
+
type: "button",
|
|
2751
|
+
onClick: () => void copyText(text, label),
|
|
2752
|
+
title: `Copy ${label}`,
|
|
2753
|
+
"aria-label": `Copy ${label}: ${text}`,
|
|
2754
|
+
className: cn(
|
|
2755
|
+
surfaceClass,
|
|
2756
|
+
"text-left cursor-pointer transition-[border-color,box-shadow]",
|
|
2757
|
+
"hover:border-[rgb(var(--border-strong))] hover:[box-shadow:var(--shadow-sm)]",
|
|
2758
|
+
"focus-visible:outline-none focus-visible:[box-shadow:var(--ring-focus)]"
|
|
2759
|
+
),
|
|
2760
|
+
style: surfaceStyle,
|
|
2761
|
+
children: body
|
|
2762
|
+
}
|
|
2763
|
+
);
|
|
2764
|
+
}
|
|
2765
|
+
return /* @__PURE__ */ jsx("div", { className: surfaceClass, style: surfaceStyle, children: body });
|
|
2659
2766
|
}
|
|
2660
2767
|
function ProgressBar({ label, percent, status, height = 8 }) {
|
|
2661
2768
|
const determinate = typeof percent === "number";
|
|
@@ -2911,16 +3018,6 @@ function TokenBadge({
|
|
|
2911
3018
|
}
|
|
2912
3019
|
);
|
|
2913
3020
|
}
|
|
2914
|
-
|
|
2915
|
-
// src/lib/clipboard.ts
|
|
2916
|
-
async function copyText(value, label) {
|
|
2917
|
-
try {
|
|
2918
|
-
await navigator.clipboard.writeText(value);
|
|
2919
|
-
toast.success(label ? `Copied ${label}` : `Copied ${value}`);
|
|
2920
|
-
} catch {
|
|
2921
|
-
toast.error("Copy failed");
|
|
2922
|
-
}
|
|
2923
|
-
}
|
|
2924
3021
|
var ValueChip = forwardRef(
|
|
2925
3022
|
function ValueChip2({ children, copyValue, copyLabel, size = "md", fill, className, ...rest }, ref) {
|
|
2926
3023
|
const shared = cn(
|
|
@@ -3610,6 +3707,403 @@ var Checkbox = forwardRef(
|
|
|
3610
3707
|
);
|
|
3611
3708
|
}
|
|
3612
3709
|
);
|
|
3710
|
+
|
|
3711
|
+
// src/lib/refs.ts
|
|
3712
|
+
function assignRef(ref, node) {
|
|
3713
|
+
if (!ref) return;
|
|
3714
|
+
if (typeof ref === "function") {
|
|
3715
|
+
ref(node);
|
|
3716
|
+
return;
|
|
3717
|
+
}
|
|
3718
|
+
ref.current = node;
|
|
3719
|
+
}
|
|
3720
|
+
function composeRefs(...refs) {
|
|
3721
|
+
return (node) => {
|
|
3722
|
+
for (const ref of refs) assignRef(ref, node);
|
|
3723
|
+
};
|
|
3724
|
+
}
|
|
3725
|
+
var OPPOSITE = {
|
|
3726
|
+
top: "bottom",
|
|
3727
|
+
bottom: "top",
|
|
3728
|
+
left: "right",
|
|
3729
|
+
right: "left"
|
|
3730
|
+
};
|
|
3731
|
+
function isVertical(side) {
|
|
3732
|
+
return side === "top" || side === "bottom";
|
|
3733
|
+
}
|
|
3734
|
+
function clampNumber(value, min, max) {
|
|
3735
|
+
return Math.max(min, Math.min(value, max));
|
|
3736
|
+
}
|
|
3737
|
+
function computeAnchoredPosition(anchor, floating, viewport, options = {}) {
|
|
3738
|
+
const {
|
|
3739
|
+
side: preferred = "bottom",
|
|
3740
|
+
align = "start",
|
|
3741
|
+
offset = 6,
|
|
3742
|
+
alignOffset = 0,
|
|
3743
|
+
flip = true,
|
|
3744
|
+
clampToViewport = true,
|
|
3745
|
+
gutter = 8
|
|
3746
|
+
} = options;
|
|
3747
|
+
const anchorRight = anchor.left + anchor.width;
|
|
3748
|
+
const anchorBottom = anchor.top + anchor.height;
|
|
3749
|
+
const room = {
|
|
3750
|
+
top: anchor.top - gutter,
|
|
3751
|
+
bottom: viewport.height - anchorBottom - gutter,
|
|
3752
|
+
left: anchor.left - gutter,
|
|
3753
|
+
right: viewport.width - anchorRight - gutter
|
|
3754
|
+
};
|
|
3755
|
+
const needed = (side2) => (isVertical(side2) ? floating.height : floating.width) + offset;
|
|
3756
|
+
let side = preferred;
|
|
3757
|
+
if (flip && room[preferred] < needed(preferred)) {
|
|
3758
|
+
const opposite = OPPOSITE[preferred];
|
|
3759
|
+
if (room[opposite] >= needed(opposite) || room[opposite] > room[preferred]) {
|
|
3760
|
+
side = opposite;
|
|
3761
|
+
}
|
|
3762
|
+
}
|
|
3763
|
+
let left;
|
|
3764
|
+
let top;
|
|
3765
|
+
if (isVertical(side)) {
|
|
3766
|
+
top = side === "bottom" ? anchorBottom + offset : anchor.top - floating.height - offset;
|
|
3767
|
+
switch (align) {
|
|
3768
|
+
case "start":
|
|
3769
|
+
left = anchor.left + alignOffset;
|
|
3770
|
+
break;
|
|
3771
|
+
case "center":
|
|
3772
|
+
left = anchor.left + anchor.width / 2 - floating.width / 2 + alignOffset;
|
|
3773
|
+
break;
|
|
3774
|
+
case "end":
|
|
3775
|
+
left = anchorRight - floating.width - alignOffset;
|
|
3776
|
+
break;
|
|
3777
|
+
}
|
|
3778
|
+
} else {
|
|
3779
|
+
left = side === "right" ? anchorRight + offset : anchor.left - floating.width - offset;
|
|
3780
|
+
switch (align) {
|
|
3781
|
+
case "start":
|
|
3782
|
+
top = anchor.top + alignOffset;
|
|
3783
|
+
break;
|
|
3784
|
+
case "center":
|
|
3785
|
+
top = anchor.top + anchor.height / 2 - floating.height / 2 + alignOffset;
|
|
3786
|
+
break;
|
|
3787
|
+
case "end":
|
|
3788
|
+
top = anchorBottom - floating.height - alignOffset;
|
|
3789
|
+
break;
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3792
|
+
if (clampToViewport) {
|
|
3793
|
+
left = clampNumber(left, gutter, viewport.width - floating.width - gutter);
|
|
3794
|
+
top = clampNumber(top, gutter, viewport.height - floating.height - gutter);
|
|
3795
|
+
}
|
|
3796
|
+
return {
|
|
3797
|
+
left: Math.round(left),
|
|
3798
|
+
top: Math.round(top),
|
|
3799
|
+
placement: { side, align }
|
|
3800
|
+
};
|
|
3801
|
+
}
|
|
3802
|
+
var PARKED_STYLE = {
|
|
3803
|
+
position: "fixed",
|
|
3804
|
+
// Parked far off-screen, not at (0, 0): if a renderer paints the
|
|
3805
|
+
// unpositioned frame despite `visibility: hidden`, nothing flashes at the
|
|
3806
|
+
// viewport's top-left corner.
|
|
3807
|
+
left: -99999,
|
|
3808
|
+
top: -99999,
|
|
3809
|
+
visibility: "hidden",
|
|
3810
|
+
opacity: 0,
|
|
3811
|
+
pointerEvents: "none"
|
|
3812
|
+
};
|
|
3813
|
+
function viewportSize() {
|
|
3814
|
+
const root = document.documentElement;
|
|
3815
|
+
return {
|
|
3816
|
+
width: root.clientWidth || window.innerWidth,
|
|
3817
|
+
height: root.clientHeight || window.innerHeight
|
|
3818
|
+
};
|
|
3819
|
+
}
|
|
3820
|
+
function samePosition(a, b) {
|
|
3821
|
+
return a !== null && a.left === b.left && a.top === b.top && a.placement.side === b.placement.side && a.placement.align === b.placement.align;
|
|
3822
|
+
}
|
|
3823
|
+
function useAnchoredPosition(options) {
|
|
3824
|
+
const {
|
|
3825
|
+
anchorRef,
|
|
3826
|
+
anchorRect = null,
|
|
3827
|
+
enabled = true,
|
|
3828
|
+
side = "bottom",
|
|
3829
|
+
align = "start",
|
|
3830
|
+
offset = 6,
|
|
3831
|
+
alignOffset = 0,
|
|
3832
|
+
flip = true,
|
|
3833
|
+
clampToViewport = true,
|
|
3834
|
+
gutter = 8
|
|
3835
|
+
} = options;
|
|
3836
|
+
const floatingRef = useRef(null);
|
|
3837
|
+
const [floating, setFloating] = useState(null);
|
|
3838
|
+
const ref = useCallback((node) => {
|
|
3839
|
+
floatingRef.current = node;
|
|
3840
|
+
setFloating(node);
|
|
3841
|
+
}, []);
|
|
3842
|
+
const [position, setPosition] = useState(null);
|
|
3843
|
+
const anchorRectRef = useRef(anchorRect);
|
|
3844
|
+
useLayoutEffect(() => {
|
|
3845
|
+
anchorRectRef.current = anchorRect;
|
|
3846
|
+
});
|
|
3847
|
+
const rectKey = anchorRect ? `${anchorRect.left}|${anchorRect.top}|${anchorRect.width}|${anchorRect.height}` : "";
|
|
3848
|
+
const measure = useCallback(() => {
|
|
3849
|
+
const node = floatingRef.current;
|
|
3850
|
+
if (!node) return;
|
|
3851
|
+
const rect = anchorRectRef.current ?? anchorRef?.current?.getBoundingClientRect() ?? null;
|
|
3852
|
+
if (!rect) return;
|
|
3853
|
+
const next = computeAnchoredPosition(
|
|
3854
|
+
rect,
|
|
3855
|
+
{ width: node.offsetWidth, height: node.offsetHeight },
|
|
3856
|
+
viewportSize(),
|
|
3857
|
+
{ side, align, offset, alignOffset, flip, clampToViewport, gutter }
|
|
3858
|
+
);
|
|
3859
|
+
setPosition((prev) => samePosition(prev, next) ? prev : next);
|
|
3860
|
+
}, [anchorRef, side, align, offset, alignOffset, flip, clampToViewport, gutter]);
|
|
3861
|
+
useLayoutEffect(() => {
|
|
3862
|
+
if (!enabled || !floating) {
|
|
3863
|
+
setPosition((prev) => prev === null ? prev : null);
|
|
3864
|
+
return;
|
|
3865
|
+
}
|
|
3866
|
+
measure();
|
|
3867
|
+
window.addEventListener("resize", measure);
|
|
3868
|
+
window.addEventListener("scroll", measure, true);
|
|
3869
|
+
let observer = null;
|
|
3870
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
3871
|
+
observer = new ResizeObserver(() => measure());
|
|
3872
|
+
observer.observe(floating);
|
|
3873
|
+
const anchorEl = anchorRef?.current;
|
|
3874
|
+
if (anchorEl) observer.observe(anchorEl);
|
|
3875
|
+
}
|
|
3876
|
+
return () => {
|
|
3877
|
+
window.removeEventListener("resize", measure);
|
|
3878
|
+
window.removeEventListener("scroll", measure, true);
|
|
3879
|
+
observer?.disconnect();
|
|
3880
|
+
};
|
|
3881
|
+
}, [enabled, floating, measure, anchorRef, rectKey]);
|
|
3882
|
+
const positioned = position !== null;
|
|
3883
|
+
const style = positioned ? { position: "fixed", left: position.left, top: position.top } : PARKED_STYLE;
|
|
3884
|
+
return {
|
|
3885
|
+
ref,
|
|
3886
|
+
floatingRef,
|
|
3887
|
+
style,
|
|
3888
|
+
placement: position?.placement ?? null,
|
|
3889
|
+
positioned,
|
|
3890
|
+
update: measure
|
|
3891
|
+
};
|
|
3892
|
+
}
|
|
3893
|
+
function useOutsideClick(targets, onOutside, options = {}) {
|
|
3894
|
+
const { enabled = true, layer } = options;
|
|
3895
|
+
const targetsRef = useRef(targets);
|
|
3896
|
+
const handlerRef = useRef(onOutside);
|
|
3897
|
+
useEffect(() => {
|
|
3898
|
+
targetsRef.current = targets;
|
|
3899
|
+
handlerRef.current = onOutside;
|
|
3900
|
+
});
|
|
3901
|
+
useEffect(() => {
|
|
3902
|
+
if (!enabled) return;
|
|
3903
|
+
const onPointerDown = (event) => {
|
|
3904
|
+
const target = event.target;
|
|
3905
|
+
if (!(target instanceof Node)) return;
|
|
3906
|
+
for (const candidate of targetsRef.current) {
|
|
3907
|
+
const el = candidate instanceof Node ? candidate : candidate?.current;
|
|
3908
|
+
if (el?.contains(target)) return;
|
|
3909
|
+
}
|
|
3910
|
+
if (layer?.containsInLayerAbove(target)) return;
|
|
3911
|
+
handlerRef.current(event);
|
|
3912
|
+
};
|
|
3913
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
3914
|
+
return () => document.removeEventListener("pointerdown", onPointerDown);
|
|
3915
|
+
}, [enabled, layer]);
|
|
3916
|
+
}
|
|
3917
|
+
var POPOVER_SURFACE_STYLE = {
|
|
3918
|
+
background: "rgb(var(--popover))",
|
|
3919
|
+
color: "rgb(var(--popover-foreground))",
|
|
3920
|
+
border: "1px solid rgb(var(--border))",
|
|
3921
|
+
boxShadow: "var(--shadow-lg)"
|
|
3922
|
+
};
|
|
3923
|
+
var PopoverCtx = createContext(null);
|
|
3924
|
+
function usePopoverCtx(consumer) {
|
|
3925
|
+
const ctx = useContext(PopoverCtx);
|
|
3926
|
+
if (!ctx) {
|
|
3927
|
+
throw new Error(
|
|
3928
|
+
`${consumer} must be rendered inside <Popover>. Wrap your trigger + content with the Popover root component.`
|
|
3929
|
+
);
|
|
3930
|
+
}
|
|
3931
|
+
return ctx;
|
|
3932
|
+
}
|
|
3933
|
+
function PopoverRoot({
|
|
3934
|
+
open: controlledOpen,
|
|
3935
|
+
defaultOpen,
|
|
3936
|
+
onOpenChange,
|
|
3937
|
+
anchorRect = null,
|
|
3938
|
+
children
|
|
3939
|
+
}) {
|
|
3940
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(Boolean(defaultOpen));
|
|
3941
|
+
const isControlled = controlledOpen !== void 0;
|
|
3942
|
+
const open = isControlled ? Boolean(controlledOpen) : uncontrolledOpen;
|
|
3943
|
+
const triggerRef = useRef(null);
|
|
3944
|
+
const interactedOutsideRef = useRef(false);
|
|
3945
|
+
const generatedId = useId();
|
|
3946
|
+
const contentId = `popover-${generatedId.replace(/:/g, "")}`;
|
|
3947
|
+
const setOpen = useCallback(
|
|
3948
|
+
(next) => {
|
|
3949
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
3950
|
+
onOpenChange?.(next);
|
|
3951
|
+
},
|
|
3952
|
+
[isControlled, onOpenChange]
|
|
3953
|
+
);
|
|
3954
|
+
const value = useMemo(
|
|
3955
|
+
() => ({ open, setOpen, triggerRef, contentId, anchorRect, interactedOutsideRef }),
|
|
3956
|
+
[open, setOpen, contentId, anchorRect]
|
|
3957
|
+
);
|
|
3958
|
+
return /* @__PURE__ */ jsx(PopoverCtx.Provider, { value, children });
|
|
3959
|
+
}
|
|
3960
|
+
var PopoverTrigger = forwardRef(
|
|
3961
|
+
function PopoverTrigger2({ asChild, onClick, children, ...rest }, forwardedRef) {
|
|
3962
|
+
const { open, setOpen, triggerRef, contentId } = usePopoverCtx("Popover.Trigger");
|
|
3963
|
+
const ariaProps = {
|
|
3964
|
+
"aria-haspopup": "dialog",
|
|
3965
|
+
"aria-expanded": open,
|
|
3966
|
+
"aria-controls": open ? contentId : void 0,
|
|
3967
|
+
"data-state": open ? "open" : "closed"
|
|
3968
|
+
};
|
|
3969
|
+
if (asChild) {
|
|
3970
|
+
if (!isValidElement(children)) {
|
|
3971
|
+
throw new Error("Popover.Trigger with `asChild` expects exactly one element child.");
|
|
3972
|
+
}
|
|
3973
|
+
const child = children;
|
|
3974
|
+
const childOnClick = child.props.onClick;
|
|
3975
|
+
return cloneElement(child, {
|
|
3976
|
+
...rest,
|
|
3977
|
+
...ariaProps,
|
|
3978
|
+
ref: composeRefs(child.props.ref, forwardedRef, triggerRef),
|
|
3979
|
+
onClick: (event) => {
|
|
3980
|
+
childOnClick?.(event);
|
|
3981
|
+
onClick?.(event);
|
|
3982
|
+
if (!event.defaultPrevented) setOpen(!open);
|
|
3983
|
+
}
|
|
3984
|
+
});
|
|
3985
|
+
}
|
|
3986
|
+
return /* @__PURE__ */ jsx(
|
|
3987
|
+
"button",
|
|
3988
|
+
{
|
|
3989
|
+
ref: composeRefs(forwardedRef, triggerRef),
|
|
3990
|
+
type: "button",
|
|
3991
|
+
...ariaProps,
|
|
3992
|
+
onClick: (event) => {
|
|
3993
|
+
onClick?.(event);
|
|
3994
|
+
if (!event.defaultPrevented) setOpen(!open);
|
|
3995
|
+
},
|
|
3996
|
+
...rest,
|
|
3997
|
+
children
|
|
3998
|
+
}
|
|
3999
|
+
);
|
|
4000
|
+
}
|
|
4001
|
+
);
|
|
4002
|
+
var PopoverContent = forwardRef(
|
|
4003
|
+
function PopoverContent2({
|
|
4004
|
+
children,
|
|
4005
|
+
side = "bottom",
|
|
4006
|
+
align = "start",
|
|
4007
|
+
offset = 6,
|
|
4008
|
+
alignOffset = 0,
|
|
4009
|
+
flip = true,
|
|
4010
|
+
clampToViewport = true,
|
|
4011
|
+
role = "dialog",
|
|
4012
|
+
unstyled,
|
|
4013
|
+
className,
|
|
4014
|
+
style,
|
|
4015
|
+
...rest
|
|
4016
|
+
}, forwardedRef) {
|
|
4017
|
+
const { open, setOpen, triggerRef, contentId, anchorRect, interactedOutsideRef } = usePopoverCtx("Popover.Content");
|
|
4018
|
+
const contentRef = useRef(null);
|
|
4019
|
+
const {
|
|
4020
|
+
ref: positionRef,
|
|
4021
|
+
style: positionStyle,
|
|
4022
|
+
placement,
|
|
4023
|
+
positioned
|
|
4024
|
+
} = useAnchoredPosition({
|
|
4025
|
+
anchorRef: triggerRef,
|
|
4026
|
+
anchorRect,
|
|
4027
|
+
side,
|
|
4028
|
+
align,
|
|
4029
|
+
offset,
|
|
4030
|
+
alignOffset,
|
|
4031
|
+
flip,
|
|
4032
|
+
clampToViewport,
|
|
4033
|
+
enabled: open
|
|
4034
|
+
});
|
|
4035
|
+
const layer = useLayer({
|
|
4036
|
+
enabled: open,
|
|
4037
|
+
kind: "popover",
|
|
4038
|
+
elementRef: contentRef,
|
|
4039
|
+
onEscape: () => setOpen(false)
|
|
4040
|
+
});
|
|
4041
|
+
useOutsideClick(
|
|
4042
|
+
[triggerRef, contentRef],
|
|
4043
|
+
() => {
|
|
4044
|
+
interactedOutsideRef.current = true;
|
|
4045
|
+
setOpen(false);
|
|
4046
|
+
},
|
|
4047
|
+
{ enabled: open, layer }
|
|
4048
|
+
);
|
|
4049
|
+
useEffect(() => {
|
|
4050
|
+
if (!open || !positioned) return;
|
|
4051
|
+
const node = contentRef.current;
|
|
4052
|
+
if (!node) return;
|
|
4053
|
+
interactedOutsideRef.current = false;
|
|
4054
|
+
const trigger = triggerRef.current;
|
|
4055
|
+
const previous = document.activeElement instanceof HTMLElement && document.activeElement !== document.body ? document.activeElement : null;
|
|
4056
|
+
const initial = node.querySelector("[data-autofocus]") ?? tabbablesWithin(node)[0] ?? node;
|
|
4057
|
+
initial.focus();
|
|
4058
|
+
return () => {
|
|
4059
|
+
if (interactedOutsideRef.current) return;
|
|
4060
|
+
const active = document.activeElement;
|
|
4061
|
+
if (active !== null && active !== document.body && !node.contains(active)) return;
|
|
4062
|
+
const target = trigger ?? previous;
|
|
4063
|
+
if (target?.isConnected) target.focus();
|
|
4064
|
+
};
|
|
4065
|
+
}, [open, positioned, triggerRef, interactedOutsideRef]);
|
|
4066
|
+
const ref = useMemo(
|
|
4067
|
+
() => composeRefs(forwardedRef, contentRef, positionRef),
|
|
4068
|
+
[forwardedRef, positionRef]
|
|
4069
|
+
);
|
|
4070
|
+
if (!open || typeof document === "undefined") return null;
|
|
4071
|
+
return createPortal(
|
|
4072
|
+
/* @__PURE__ */ jsx(
|
|
4073
|
+
"div",
|
|
4074
|
+
{
|
|
4075
|
+
ref,
|
|
4076
|
+
id: contentId,
|
|
4077
|
+
role: role === "none" ? void 0 : role,
|
|
4078
|
+
tabIndex: -1,
|
|
4079
|
+
"data-slot": "popover-content",
|
|
4080
|
+
"data-state": "open",
|
|
4081
|
+
"data-side": placement?.side,
|
|
4082
|
+
"data-align": placement?.align,
|
|
4083
|
+
"data-positioned": positioned ? "true" : "false",
|
|
4084
|
+
className: cn(
|
|
4085
|
+
"fixed z-[100] outline-none",
|
|
4086
|
+
!unstyled && "rounded-[var(--radius-lg)] p-3",
|
|
4087
|
+
positioned && "ds-enter-pop",
|
|
4088
|
+
className
|
|
4089
|
+
),
|
|
4090
|
+
style: {
|
|
4091
|
+
...positionStyle,
|
|
4092
|
+
...unstyled ? void 0 : POPOVER_SURFACE_STYLE,
|
|
4093
|
+
...style
|
|
4094
|
+
},
|
|
4095
|
+
...rest,
|
|
4096
|
+
children
|
|
4097
|
+
}
|
|
4098
|
+
),
|
|
4099
|
+
document.body
|
|
4100
|
+
);
|
|
4101
|
+
}
|
|
4102
|
+
);
|
|
4103
|
+
var Popover = Object.assign(PopoverRoot, {
|
|
4104
|
+
Trigger: PopoverTrigger,
|
|
4105
|
+
Content: PopoverContent
|
|
4106
|
+
});
|
|
3613
4107
|
var DropdownMenuCtx = createContext(null);
|
|
3614
4108
|
function useDropdownMenuCtx(consumer) {
|
|
3615
4109
|
const ctx = useContext(DropdownMenuCtx);
|
|
@@ -3647,22 +4141,21 @@ function DropdownMenu({
|
|
|
3647
4141
|
);
|
|
3648
4142
|
return /* @__PURE__ */ jsx(DropdownMenuCtx.Provider, { value, children });
|
|
3649
4143
|
}
|
|
3650
|
-
|
|
3651
|
-
unstyled,
|
|
3652
|
-
className,
|
|
3653
|
-
onClick,
|
|
3654
|
-
children,
|
|
3655
|
-
...rest
|
|
3656
|
-
}) {
|
|
4144
|
+
var DropdownMenuTrigger = forwardRef(function DropdownMenuTrigger2({ unstyled, className, onClick, children, ...rest }, forwardedRef) {
|
|
3657
4145
|
const { open, setOpen, triggerRef, contentId } = useDropdownMenuCtx("DropdownMenuTrigger");
|
|
4146
|
+
const ref = useMemo(
|
|
4147
|
+
() => composeRefs(forwardedRef, triggerRef),
|
|
4148
|
+
[forwardedRef, triggerRef]
|
|
4149
|
+
);
|
|
3658
4150
|
return /* @__PURE__ */ jsx(
|
|
3659
4151
|
"button",
|
|
3660
4152
|
{
|
|
3661
|
-
ref
|
|
4153
|
+
ref,
|
|
3662
4154
|
type: "button",
|
|
3663
4155
|
"aria-haspopup": "menu",
|
|
3664
4156
|
"aria-expanded": open,
|
|
3665
4157
|
"aria-controls": open ? contentId : void 0,
|
|
4158
|
+
"data-state": open ? "open" : "closed",
|
|
3666
4159
|
className: cn(
|
|
3667
4160
|
!unstyled && "btn btn-secondary",
|
|
3668
4161
|
className
|
|
@@ -3675,8 +4168,8 @@ function DropdownMenuTrigger({
|
|
|
3675
4168
|
children
|
|
3676
4169
|
}
|
|
3677
4170
|
);
|
|
3678
|
-
}
|
|
3679
|
-
|
|
4171
|
+
});
|
|
4172
|
+
var DropdownMenuContent = forwardRef(function DropdownMenuContent2({
|
|
3680
4173
|
children,
|
|
3681
4174
|
align = "start",
|
|
3682
4175
|
alignOffset = 0,
|
|
@@ -3685,100 +4178,62 @@ function DropdownMenuContent({
|
|
|
3685
4178
|
className,
|
|
3686
4179
|
style,
|
|
3687
4180
|
...rest
|
|
3688
|
-
}) {
|
|
4181
|
+
}, forwardedRef) {
|
|
3689
4182
|
const { open, setOpen, triggerRef, contentId } = useDropdownMenuCtx("DropdownMenuContent");
|
|
3690
4183
|
const contentRef = useRef(null);
|
|
3691
|
-
const
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
let top = side === "bottom" ? triggerRect.bottom + sideOffset : triggerRect.top - contentRect.height - sideOffset;
|
|
3710
|
-
const gutter = 8;
|
|
3711
|
-
const maxLeft = window.innerWidth - contentRect.width - gutter;
|
|
3712
|
-
const maxTop = window.innerHeight - contentRect.height - gutter;
|
|
3713
|
-
left = Math.max(gutter, Math.min(left, maxLeft));
|
|
3714
|
-
top = Math.max(gutter, Math.min(top, maxTop));
|
|
3715
|
-
setPosition({ left, top });
|
|
3716
|
-
};
|
|
3717
|
-
measure();
|
|
3718
|
-
window.addEventListener("resize", measure);
|
|
3719
|
-
window.addEventListener("scroll", measure, true);
|
|
3720
|
-
return () => {
|
|
3721
|
-
window.removeEventListener("resize", measure);
|
|
3722
|
-
window.removeEventListener("scroll", measure, true);
|
|
3723
|
-
};
|
|
3724
|
-
}, [open, align, alignOffset, side, sideOffset, triggerRef]);
|
|
3725
|
-
useEffect(() => {
|
|
3726
|
-
if (!open) return;
|
|
3727
|
-
const onPointerDown = (event) => {
|
|
3728
|
-
const target = event.target;
|
|
3729
|
-
if (!target) return;
|
|
3730
|
-
if (contentRef.current?.contains(target)) return;
|
|
3731
|
-
if (triggerRef.current?.contains(target)) return;
|
|
4184
|
+
const {
|
|
4185
|
+
ref: positionRef,
|
|
4186
|
+
style: positionStyle,
|
|
4187
|
+
placement,
|
|
4188
|
+
positioned
|
|
4189
|
+
} = useAnchoredPosition({
|
|
4190
|
+
anchorRef: triggerRef,
|
|
4191
|
+
side,
|
|
4192
|
+
align,
|
|
4193
|
+
offset: sideOffset,
|
|
4194
|
+
alignOffset,
|
|
4195
|
+
enabled: open
|
|
4196
|
+
});
|
|
4197
|
+
const layer = useLayer({
|
|
4198
|
+
enabled: open,
|
|
4199
|
+
kind: "popover",
|
|
4200
|
+
elementRef: contentRef,
|
|
4201
|
+
onEscape: () => {
|
|
3732
4202
|
setOpen(false);
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
document.removeEventListener("pointerdown", onPointerDown);
|
|
3745
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
3746
|
-
};
|
|
3747
|
-
}, [open, setOpen, triggerRef]);
|
|
4203
|
+
triggerRef.current?.focus();
|
|
4204
|
+
}
|
|
4205
|
+
});
|
|
4206
|
+
useOutsideClick([triggerRef, contentRef], () => setOpen(false), {
|
|
4207
|
+
enabled: open,
|
|
4208
|
+
layer
|
|
4209
|
+
});
|
|
4210
|
+
const ref = useMemo(
|
|
4211
|
+
() => composeRefs(forwardedRef, contentRef, positionRef),
|
|
4212
|
+
[forwardedRef, positionRef]
|
|
4213
|
+
);
|
|
3748
4214
|
if (!open || typeof document === "undefined") return null;
|
|
3749
|
-
const isPositioned = position !== null;
|
|
3750
4215
|
return createPortal(
|
|
3751
4216
|
/* @__PURE__ */ jsx(
|
|
3752
4217
|
"div",
|
|
3753
4218
|
{
|
|
3754
|
-
ref
|
|
4219
|
+
ref,
|
|
3755
4220
|
id: contentId,
|
|
3756
4221
|
role: "menu",
|
|
3757
4222
|
"data-slot": "dropdown-menu-content",
|
|
3758
4223
|
"data-state": "open",
|
|
3759
|
-
"data-
|
|
4224
|
+
"data-side": placement?.side,
|
|
4225
|
+
"data-align": placement?.align,
|
|
4226
|
+
"data-positioned": positioned ? "true" : "false",
|
|
3760
4227
|
className: cn(
|
|
3761
4228
|
"fixed z-[100] min-w-48 max-w-[min(28rem,calc(100vw-16px))]",
|
|
3762
4229
|
"p-1.5 overflow-y-auto",
|
|
3763
4230
|
"rounded-[var(--radius-lg)]",
|
|
3764
|
-
|
|
4231
|
+
positioned && "ds-enter-pop",
|
|
3765
4232
|
className
|
|
3766
4233
|
),
|
|
3767
4234
|
style: {
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
// visibility:hidden during a same-frame double-render. If the
|
|
3771
|
-
// first paint slips through, it's at (-99999, -99999), not at
|
|
3772
|
-
// viewport (0, 0) where a left-edge flash would be visible.
|
|
3773
|
-
left: position?.left ?? -99999,
|
|
3774
|
-
top: position?.top ?? -99999,
|
|
3775
|
-
opacity: isPositioned ? void 0 : 0,
|
|
3776
|
-
pointerEvents: isPositioned ? void 0 : "none",
|
|
3777
|
-
visibility: isPositioned ? "visible" : "hidden",
|
|
3778
|
-
background: "rgb(var(--popover))",
|
|
3779
|
-
color: "rgb(var(--popover-foreground))",
|
|
3780
|
-
border: "1px solid rgb(var(--border))",
|
|
3781
|
-
boxShadow: "var(--shadow-lg, 0 10px 32px rgba(0,0,0,0.18))",
|
|
4235
|
+
...positionStyle,
|
|
4236
|
+
...POPOVER_SURFACE_STYLE,
|
|
3782
4237
|
...style
|
|
3783
4238
|
},
|
|
3784
4239
|
...rest,
|
|
@@ -3787,19 +4242,13 @@ function DropdownMenuContent({
|
|
|
3787
4242
|
),
|
|
3788
4243
|
document.body
|
|
3789
4244
|
);
|
|
3790
|
-
}
|
|
3791
|
-
|
|
3792
|
-
variant = "default",
|
|
3793
|
-
inset,
|
|
3794
|
-
className,
|
|
3795
|
-
onClick,
|
|
3796
|
-
children,
|
|
3797
|
-
...rest
|
|
3798
|
-
}) {
|
|
4245
|
+
});
|
|
4246
|
+
var DropdownMenuItem = forwardRef(function DropdownMenuItem2({ variant = "default", inset, className, onClick, children, ...rest }, forwardedRef) {
|
|
3799
4247
|
const { setOpen } = useDropdownMenuCtx("DropdownMenuItem");
|
|
3800
4248
|
return /* @__PURE__ */ jsx(
|
|
3801
4249
|
"button",
|
|
3802
4250
|
{
|
|
4251
|
+
ref: forwardedRef,
|
|
3803
4252
|
role: "menuitem",
|
|
3804
4253
|
type: "button",
|
|
3805
4254
|
"data-slot": "dropdown-menu-item",
|
|
@@ -3824,19 +4273,12 @@ function DropdownMenuItem({
|
|
|
3824
4273
|
children
|
|
3825
4274
|
}
|
|
3826
4275
|
);
|
|
3827
|
-
}
|
|
3828
|
-
|
|
3829
|
-
checked,
|
|
3830
|
-
onCheckedChange,
|
|
3831
|
-
className,
|
|
3832
|
-
children,
|
|
3833
|
-
onClick,
|
|
3834
|
-
disabled,
|
|
3835
|
-
...rest
|
|
3836
|
-
}) {
|
|
4276
|
+
});
|
|
4277
|
+
var DropdownMenuCheckboxItem = forwardRef(function DropdownMenuCheckboxItem2({ checked, onCheckedChange, className, children, onClick, disabled, ...rest }, forwardedRef) {
|
|
3837
4278
|
return /* @__PURE__ */ jsxs(
|
|
3838
4279
|
"button",
|
|
3839
4280
|
{
|
|
4281
|
+
ref: forwardedRef,
|
|
3840
4282
|
role: "menuitemcheckbox",
|
|
3841
4283
|
type: "button",
|
|
3842
4284
|
"data-slot": "dropdown-menu-checkbox-item",
|
|
@@ -3870,7 +4312,7 @@ function DropdownMenuCheckboxItem({
|
|
|
3870
4312
|
]
|
|
3871
4313
|
}
|
|
3872
4314
|
);
|
|
3873
|
-
}
|
|
4315
|
+
});
|
|
3874
4316
|
function DropdownMenuSeparator({
|
|
3875
4317
|
className,
|
|
3876
4318
|
...rest
|
|
@@ -5515,113 +5957,1169 @@ function DataGrid({
|
|
|
5515
5957
|
sort: sort ?? null,
|
|
5516
5958
|
onSortChange
|
|
5517
5959
|
}
|
|
5518
|
-
) })
|
|
5960
|
+
) })
|
|
5961
|
+
]
|
|
5962
|
+
}
|
|
5963
|
+
),
|
|
5964
|
+
renderDrawerPanel ? renderDrawerPanel(drawerPanelProps) : /* @__PURE__ */ jsx(
|
|
5965
|
+
DrawerPanel,
|
|
5966
|
+
{
|
|
5967
|
+
isOpen: drawerIsOpen,
|
|
5968
|
+
onClose: closeDrawer,
|
|
5969
|
+
drawerRow,
|
|
5970
|
+
drawerColumn,
|
|
5971
|
+
drawerCellValue,
|
|
5972
|
+
getRowLabel,
|
|
5973
|
+
isEditableColumn,
|
|
5974
|
+
isEmptyValue,
|
|
5975
|
+
modal: drawerModal,
|
|
5976
|
+
size: drawerSize ?? void 0
|
|
5977
|
+
}
|
|
5978
|
+
)
|
|
5979
|
+
] });
|
|
5980
|
+
}
|
|
5981
|
+
function DataGridToolbar({
|
|
5982
|
+
search,
|
|
5983
|
+
children,
|
|
5984
|
+
className
|
|
5985
|
+
}) {
|
|
5986
|
+
return /* @__PURE__ */ jsxs(
|
|
5987
|
+
"div",
|
|
5988
|
+
{
|
|
5989
|
+
className: cn(
|
|
5990
|
+
"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
|
|
5991
|
+
className
|
|
5992
|
+
),
|
|
5993
|
+
children: [
|
|
5994
|
+
search ? /* @__PURE__ */ jsx("div", { className: "w-full sm:max-w-sm", children: search }) : /* @__PURE__ */ jsx("span", {}),
|
|
5995
|
+
children ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 sm:justify-end", children }) : null
|
|
5996
|
+
]
|
|
5997
|
+
}
|
|
5998
|
+
);
|
|
5999
|
+
}
|
|
6000
|
+
function DataGridColumnOptionsMenu({
|
|
6001
|
+
showSummaries,
|
|
6002
|
+
onShowSummariesChange,
|
|
6003
|
+
visibleColumns,
|
|
6004
|
+
visibleColumnIds,
|
|
6005
|
+
hiddenColumns,
|
|
6006
|
+
toggleColumnVisibility,
|
|
6007
|
+
optionsSensors,
|
|
6008
|
+
onOptionColumnDragEnd,
|
|
6009
|
+
optionsDndContextId,
|
|
6010
|
+
triggerLabel = "Options"
|
|
6011
|
+
}) {
|
|
6012
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
6013
|
+
/* @__PURE__ */ jsxs(DropdownMenuTrigger, { "aria-label": "Open table options", children: [
|
|
6014
|
+
/* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-4 w-4" }),
|
|
6015
|
+
/* @__PURE__ */ jsx("span", { children: triggerLabel })
|
|
6016
|
+
] }),
|
|
6017
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [
|
|
6018
|
+
/* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Options" }) }),
|
|
6019
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
6020
|
+
/* @__PURE__ */ jsx(
|
|
6021
|
+
DropdownMenuCheckboxItem,
|
|
6022
|
+
{
|
|
6023
|
+
checked: showSummaries,
|
|
6024
|
+
onCheckedChange: (checked) => onShowSummariesChange(checked === true),
|
|
6025
|
+
children: "Show summary row"
|
|
6026
|
+
}
|
|
6027
|
+
),
|
|
6028
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
6029
|
+
/* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Columns" }) }),
|
|
6030
|
+
/* @__PURE__ */ jsx(
|
|
6031
|
+
DndContext,
|
|
6032
|
+
{
|
|
6033
|
+
id: optionsDndContextId,
|
|
6034
|
+
sensors: optionsSensors,
|
|
6035
|
+
collisionDetection: closestCenter,
|
|
6036
|
+
onDragEnd: onOptionColumnDragEnd,
|
|
6037
|
+
children: /* @__PURE__ */ jsx(
|
|
6038
|
+
SortableContext,
|
|
6039
|
+
{
|
|
6040
|
+
items: visibleColumns.map((column) => column.id),
|
|
6041
|
+
strategy: verticalListSortingStrategy,
|
|
6042
|
+
children: visibleColumns.map((column) => /* @__PURE__ */ jsx(
|
|
6043
|
+
SortableColumnOptionItem,
|
|
6044
|
+
{
|
|
6045
|
+
column,
|
|
6046
|
+
checked: true,
|
|
6047
|
+
disabled: visibleColumnIds.length === 1,
|
|
6048
|
+
onCheckedChange: (checked) => toggleColumnVisibility(column.id, checked)
|
|
6049
|
+
},
|
|
6050
|
+
column.id
|
|
6051
|
+
))
|
|
6052
|
+
}
|
|
6053
|
+
)
|
|
6054
|
+
}
|
|
6055
|
+
),
|
|
6056
|
+
hiddenColumns.length > 0 ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}) : null,
|
|
6057
|
+
hiddenColumns.map((column) => /* @__PURE__ */ jsx(
|
|
6058
|
+
DropdownMenuCheckboxItem,
|
|
6059
|
+
{
|
|
6060
|
+
checked: false,
|
|
6061
|
+
onCheckedChange: (checked) => toggleColumnVisibility(column.id, checked === true),
|
|
6062
|
+
children: column.label
|
|
6063
|
+
},
|
|
6064
|
+
column.id
|
|
6065
|
+
))
|
|
6066
|
+
] })
|
|
6067
|
+
] });
|
|
6068
|
+
}
|
|
6069
|
+
var SHELL_SIZE_CLASS = {
|
|
6070
|
+
sm: "size-sm",
|
|
6071
|
+
md: ""
|
|
6072
|
+
};
|
|
6073
|
+
var VALUE_SIZE_CLASS = {
|
|
6074
|
+
sm: "gap-2 pl-2.5 text-[12.5px]",
|
|
6075
|
+
md: "gap-2 pl-3 text-[13.5px]"
|
|
6076
|
+
};
|
|
6077
|
+
var LISTBOX_CLASS = "fixed z-[100] max-h-[min(60vh,20rem)] overflow-y-auto rounded-[var(--radius-lg)] p-1.5 outline-none";
|
|
6078
|
+
var TYPEAHEAD_RESET_MS = 500;
|
|
6079
|
+
function isPrintableKey(event) {
|
|
6080
|
+
return event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;
|
|
6081
|
+
}
|
|
6082
|
+
function sanitizeId(id) {
|
|
6083
|
+
return id.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
6084
|
+
}
|
|
6085
|
+
function ListboxOption({
|
|
6086
|
+
id,
|
|
6087
|
+
label,
|
|
6088
|
+
description,
|
|
6089
|
+
icon,
|
|
6090
|
+
count,
|
|
6091
|
+
selected,
|
|
6092
|
+
highlighted,
|
|
6093
|
+
disabled,
|
|
6094
|
+
onSelect,
|
|
6095
|
+
onHighlight,
|
|
6096
|
+
children
|
|
6097
|
+
}) {
|
|
6098
|
+
return /* @__PURE__ */ jsxs(
|
|
6099
|
+
"button",
|
|
6100
|
+
{
|
|
6101
|
+
type: "button",
|
|
6102
|
+
role: "option",
|
|
6103
|
+
id,
|
|
6104
|
+
"aria-selected": selected,
|
|
6105
|
+
"aria-disabled": disabled ? true : void 0,
|
|
6106
|
+
tabIndex: -1,
|
|
6107
|
+
"data-slot": "listbox-option",
|
|
6108
|
+
"data-highlighted": highlighted ? "" : void 0,
|
|
6109
|
+
"data-selected": selected ? "" : void 0,
|
|
6110
|
+
"data-disabled": disabled ? "" : void 0,
|
|
6111
|
+
className: cn(
|
|
6112
|
+
"flex w-full cursor-default items-center gap-2.5 text-left",
|
|
6113
|
+
"rounded-[var(--radius-md)] px-2.5 py-2 text-[13px] font-medium",
|
|
6114
|
+
"outline-none transition-colors",
|
|
6115
|
+
"aria-disabled:pointer-events-none aria-disabled:opacity-50"
|
|
6116
|
+
),
|
|
6117
|
+
style: {
|
|
6118
|
+
background: highlighted ? "rgb(var(--surface-overlay))" : "transparent",
|
|
6119
|
+
color: "rgb(var(--foreground))"
|
|
6120
|
+
},
|
|
6121
|
+
onClick: () => {
|
|
6122
|
+
if (!disabled) onSelect();
|
|
6123
|
+
},
|
|
6124
|
+
onPointerMove: () => {
|
|
6125
|
+
if (!disabled && !highlighted) onHighlight();
|
|
6126
|
+
},
|
|
6127
|
+
children: [
|
|
6128
|
+
children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6129
|
+
icon ? /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0 items-center", children: icon }) : null,
|
|
6130
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
6131
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate", children: label }),
|
|
6132
|
+
description ? /* @__PURE__ */ jsx(
|
|
6133
|
+
"span",
|
|
6134
|
+
{
|
|
6135
|
+
className: "block truncate text-[11.5px] font-normal",
|
|
6136
|
+
style: { color: "rgb(var(--text-tertiary))" },
|
|
6137
|
+
children: description
|
|
6138
|
+
}
|
|
6139
|
+
) : null
|
|
6140
|
+
] }),
|
|
6141
|
+
typeof count === "number" ? /* @__PURE__ */ jsx(
|
|
6142
|
+
"span",
|
|
6143
|
+
{
|
|
6144
|
+
className: "shrink-0 text-[11px] font-medium tabular-nums",
|
|
6145
|
+
style: { color: "rgb(var(--text-muted))" },
|
|
6146
|
+
children: count.toLocaleString()
|
|
6147
|
+
}
|
|
6148
|
+
) : null
|
|
6149
|
+
] }),
|
|
6150
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center", "aria-hidden": "true", children: selected ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5", style: { color: "rgb(var(--accent))" } }) : null })
|
|
6151
|
+
]
|
|
6152
|
+
}
|
|
6153
|
+
);
|
|
6154
|
+
}
|
|
6155
|
+
var SelectImpl = forwardRef(function Select({
|
|
6156
|
+
options,
|
|
6157
|
+
value: valueProp,
|
|
6158
|
+
defaultValue = null,
|
|
6159
|
+
onValueChange,
|
|
6160
|
+
placeholder = "Select\u2026",
|
|
6161
|
+
size = "md",
|
|
6162
|
+
error,
|
|
6163
|
+
open: openProp,
|
|
6164
|
+
defaultOpen,
|
|
6165
|
+
onOpenChange,
|
|
6166
|
+
side = "bottom",
|
|
6167
|
+
align = "start",
|
|
6168
|
+
listboxClassName,
|
|
6169
|
+
id,
|
|
6170
|
+
className,
|
|
6171
|
+
style,
|
|
6172
|
+
disabled,
|
|
6173
|
+
onClick,
|
|
6174
|
+
onKeyDown,
|
|
6175
|
+
"aria-label": ariaLabel,
|
|
6176
|
+
"aria-labelledby": ariaLabelledby,
|
|
6177
|
+
...rest
|
|
6178
|
+
}, forwardedRef) {
|
|
6179
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
6180
|
+
const isControlledValue = valueProp !== void 0;
|
|
6181
|
+
const value = isControlledValue ? valueProp : uncontrolledValue;
|
|
6182
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(Boolean(defaultOpen));
|
|
6183
|
+
const isControlledOpen = openProp !== void 0;
|
|
6184
|
+
const open = isControlledOpen ? Boolean(openProp) : uncontrolledOpen;
|
|
6185
|
+
const setOpen = useCallback(
|
|
6186
|
+
(next) => {
|
|
6187
|
+
if (!isControlledOpen) setUncontrolledOpen(next);
|
|
6188
|
+
onOpenChange?.(next);
|
|
6189
|
+
},
|
|
6190
|
+
[isControlledOpen, onOpenChange]
|
|
6191
|
+
);
|
|
6192
|
+
const triggerRef = useRef(null);
|
|
6193
|
+
const listboxRef = useRef(null);
|
|
6194
|
+
const baseId = sanitizeId(useId());
|
|
6195
|
+
const triggerId = id ?? `select-${baseId}`;
|
|
6196
|
+
const listboxId = `select-listbox-${baseId}`;
|
|
6197
|
+
const optionId = (index) => `${listboxId}-opt-${index}`;
|
|
6198
|
+
const selectedIndex = useMemo(
|
|
6199
|
+
() => options.findIndex((option) => option.value === value),
|
|
6200
|
+
[options, value]
|
|
6201
|
+
);
|
|
6202
|
+
const selected = selectedIndex >= 0 ? options[selectedIndex] : void 0;
|
|
6203
|
+
const firstEnabled = options.findIndex((option) => !option.disabled);
|
|
6204
|
+
let lastEnabled = -1;
|
|
6205
|
+
for (let i = options.length - 1; i >= 0; i--) {
|
|
6206
|
+
if (!options[i]?.disabled) {
|
|
6207
|
+
lastEnabled = i;
|
|
6208
|
+
break;
|
|
6209
|
+
}
|
|
6210
|
+
}
|
|
6211
|
+
const [highlight, setHighlight] = useState(null);
|
|
6212
|
+
const activeIndex = highlight !== null && highlight < options.length ? highlight : selectedIndex >= 0 ? selectedIndex : firstEnabled;
|
|
6213
|
+
const openList = useCallback(
|
|
6214
|
+
(initial) => {
|
|
6215
|
+
setHighlight(initial);
|
|
6216
|
+
setOpen(true);
|
|
6217
|
+
},
|
|
6218
|
+
[setOpen]
|
|
6219
|
+
);
|
|
6220
|
+
const closeList = useCallback(() => {
|
|
6221
|
+
setOpen(false);
|
|
6222
|
+
setHighlight(null);
|
|
6223
|
+
}, [setOpen]);
|
|
6224
|
+
const commit = (index) => {
|
|
6225
|
+
const option = options[index];
|
|
6226
|
+
if (!option || option.disabled) return;
|
|
6227
|
+
if (option.value !== value) {
|
|
6228
|
+
if (!isControlledValue) setUncontrolledValue(option.value);
|
|
6229
|
+
onValueChange?.(option.value);
|
|
6230
|
+
}
|
|
6231
|
+
closeList();
|
|
6232
|
+
triggerRef.current?.focus();
|
|
6233
|
+
};
|
|
6234
|
+
const step = (from, direction) => {
|
|
6235
|
+
for (let i = from + direction; i >= 0 && i < options.length; i += direction) {
|
|
6236
|
+
if (!options[i]?.disabled) return i;
|
|
6237
|
+
}
|
|
6238
|
+
return from;
|
|
6239
|
+
};
|
|
6240
|
+
const typeaheadRef = useRef({ text: "", timer: null });
|
|
6241
|
+
useEffect(() => {
|
|
6242
|
+
const state = typeaheadRef.current;
|
|
6243
|
+
return () => {
|
|
6244
|
+
if (state.timer !== null) window.clearTimeout(state.timer);
|
|
6245
|
+
};
|
|
6246
|
+
}, []);
|
|
6247
|
+
const typeahead = (char, from) => {
|
|
6248
|
+
const state = typeaheadRef.current;
|
|
6249
|
+
if (state.timer !== null) window.clearTimeout(state.timer);
|
|
6250
|
+
state.text += char.toLowerCase();
|
|
6251
|
+
state.timer = window.setTimeout(() => {
|
|
6252
|
+
state.text = "";
|
|
6253
|
+
state.timer = null;
|
|
6254
|
+
}, TYPEAHEAD_RESET_MS);
|
|
6255
|
+
const typed = state.text;
|
|
6256
|
+
const first = typed.charAt(0);
|
|
6257
|
+
const repeated = typed.length > 1 && typed.split("").every((c) => c === first);
|
|
6258
|
+
const needle = repeated ? first : typed;
|
|
6259
|
+
const count = options.length;
|
|
6260
|
+
if (count === 0) return null;
|
|
6261
|
+
const startAt = needle.length === 1 ? from + 1 : Math.max(from, 0);
|
|
6262
|
+
for (let k = 0; k < count; k++) {
|
|
6263
|
+
const i = (startAt + k) % count;
|
|
6264
|
+
const option = options[i];
|
|
6265
|
+
if (option && !option.disabled && option.label.toLowerCase().startsWith(needle)) return i;
|
|
6266
|
+
}
|
|
6267
|
+
return null;
|
|
6268
|
+
};
|
|
6269
|
+
const handleKeyDown = (event) => {
|
|
6270
|
+
onKeyDown?.(event);
|
|
6271
|
+
if (event.defaultPrevented) return;
|
|
6272
|
+
const { key } = event;
|
|
6273
|
+
if (!open) {
|
|
6274
|
+
if (key === "ArrowDown" || key === "ArrowUp" || key === "Enter" || key === " ") {
|
|
6275
|
+
event.preventDefault();
|
|
6276
|
+
openList(null);
|
|
6277
|
+
return;
|
|
6278
|
+
}
|
|
6279
|
+
if (key === "Home" || key === "End") {
|
|
6280
|
+
event.preventDefault();
|
|
6281
|
+
openList(key === "Home" ? firstEnabled : lastEnabled);
|
|
6282
|
+
return;
|
|
6283
|
+
}
|
|
6284
|
+
if (isPrintableKey(event)) {
|
|
6285
|
+
event.preventDefault();
|
|
6286
|
+
openList(typeahead(key, selectedIndex));
|
|
6287
|
+
}
|
|
6288
|
+
return;
|
|
6289
|
+
}
|
|
6290
|
+
switch (key) {
|
|
6291
|
+
case "ArrowDown":
|
|
6292
|
+
event.preventDefault();
|
|
6293
|
+
setHighlight(step(activeIndex, 1));
|
|
6294
|
+
return;
|
|
6295
|
+
case "ArrowUp":
|
|
6296
|
+
event.preventDefault();
|
|
6297
|
+
setHighlight(step(activeIndex, -1));
|
|
6298
|
+
return;
|
|
6299
|
+
case "Home":
|
|
6300
|
+
event.preventDefault();
|
|
6301
|
+
setHighlight(firstEnabled);
|
|
6302
|
+
return;
|
|
6303
|
+
case "End":
|
|
6304
|
+
event.preventDefault();
|
|
6305
|
+
setHighlight(lastEnabled);
|
|
6306
|
+
return;
|
|
6307
|
+
case "Enter":
|
|
6308
|
+
case " ":
|
|
6309
|
+
event.preventDefault();
|
|
6310
|
+
commit(activeIndex);
|
|
6311
|
+
return;
|
|
6312
|
+
case "Tab":
|
|
6313
|
+
closeList();
|
|
6314
|
+
return;
|
|
6315
|
+
case "Escape":
|
|
6316
|
+
return;
|
|
6317
|
+
default:
|
|
6318
|
+
if (isPrintableKey(event)) {
|
|
6319
|
+
event.preventDefault();
|
|
6320
|
+
const match = typeahead(key, activeIndex);
|
|
6321
|
+
if (match !== null) setHighlight(match);
|
|
6322
|
+
}
|
|
6323
|
+
}
|
|
6324
|
+
};
|
|
6325
|
+
const {
|
|
6326
|
+
ref: positionRef,
|
|
6327
|
+
style: positionStyle,
|
|
6328
|
+
placement,
|
|
6329
|
+
positioned
|
|
6330
|
+
} = useAnchoredPosition({
|
|
6331
|
+
anchorRef: triggerRef,
|
|
6332
|
+
side,
|
|
6333
|
+
align,
|
|
6334
|
+
enabled: open
|
|
6335
|
+
});
|
|
6336
|
+
const layer = useLayer({
|
|
6337
|
+
enabled: open,
|
|
6338
|
+
kind: "popover",
|
|
6339
|
+
elementRef: listboxRef,
|
|
6340
|
+
onEscape: () => {
|
|
6341
|
+
closeList();
|
|
6342
|
+
triggerRef.current?.focus();
|
|
6343
|
+
}
|
|
6344
|
+
});
|
|
6345
|
+
useOutsideClick([triggerRef, listboxRef], closeList, { enabled: open, layer });
|
|
6346
|
+
const [triggerWidth, setTriggerWidth] = useState(null);
|
|
6347
|
+
useLayoutEffect(() => {
|
|
6348
|
+
if (!open) return;
|
|
6349
|
+
setTriggerWidth(triggerRef.current?.offsetWidth ?? null);
|
|
6350
|
+
}, [open]);
|
|
6351
|
+
useEffect(() => {
|
|
6352
|
+
if (!open) return;
|
|
6353
|
+
listboxRef.current?.querySelector("[data-highlighted]")?.scrollIntoView({ block: "nearest" });
|
|
6354
|
+
}, [open, activeIndex]);
|
|
6355
|
+
const triggerRefs = useMemo(
|
|
6356
|
+
() => composeRefs(forwardedRef, triggerRef),
|
|
6357
|
+
[forwardedRef]
|
|
6358
|
+
);
|
|
6359
|
+
const listboxRefs = useMemo(
|
|
6360
|
+
() => composeRefs(listboxRef, positionRef),
|
|
6361
|
+
[positionRef]
|
|
6362
|
+
);
|
|
6363
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6364
|
+
/* @__PURE__ */ jsxs(
|
|
6365
|
+
"button",
|
|
6366
|
+
{
|
|
6367
|
+
ref: triggerRefs,
|
|
6368
|
+
id: triggerId,
|
|
6369
|
+
type: "button",
|
|
6370
|
+
role: "combobox",
|
|
6371
|
+
"aria-haspopup": "listbox",
|
|
6372
|
+
"aria-expanded": open,
|
|
6373
|
+
"aria-controls": open ? listboxId : void 0,
|
|
6374
|
+
"aria-activedescendant": open && activeIndex >= 0 ? optionId(activeIndex) : void 0,
|
|
6375
|
+
"aria-label": ariaLabel,
|
|
6376
|
+
"aria-labelledby": ariaLabelledby,
|
|
6377
|
+
"aria-invalid": error ? true : void 0,
|
|
6378
|
+
disabled,
|
|
6379
|
+
"data-slot": "select-trigger",
|
|
6380
|
+
"data-state": open ? "open" : "closed",
|
|
6381
|
+
"data-size": size,
|
|
6382
|
+
"data-placeholder": selected ? void 0 : "",
|
|
6383
|
+
className: cn(
|
|
6384
|
+
"input-shell appearance-none p-0 text-left",
|
|
6385
|
+
SHELL_SIZE_CLASS[size],
|
|
6386
|
+
error && "is-error",
|
|
6387
|
+
disabled && "is-disabled",
|
|
6388
|
+
className
|
|
6389
|
+
),
|
|
6390
|
+
style: { alignItems: "center", ...style },
|
|
6391
|
+
onClick: (event) => {
|
|
6392
|
+
onClick?.(event);
|
|
6393
|
+
if (event.defaultPrevented) return;
|
|
6394
|
+
if (open) closeList();
|
|
6395
|
+
else openList(null);
|
|
6396
|
+
},
|
|
6397
|
+
onKeyDown: handleKeyDown,
|
|
6398
|
+
...rest,
|
|
6399
|
+
children: [
|
|
6400
|
+
/* @__PURE__ */ jsxs(
|
|
6401
|
+
"span",
|
|
6402
|
+
{
|
|
6403
|
+
"data-slot": "select-value",
|
|
6404
|
+
className: cn(
|
|
6405
|
+
"flex min-w-0 flex-1 items-center font-medium leading-[1.4]",
|
|
6406
|
+
VALUE_SIZE_CLASS[size]
|
|
6407
|
+
),
|
|
6408
|
+
children: [
|
|
6409
|
+
selected?.icon ? /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0 items-center", children: selected.icon }) : null,
|
|
6410
|
+
/* @__PURE__ */ jsx(
|
|
6411
|
+
"span",
|
|
6412
|
+
{
|
|
6413
|
+
className: "truncate",
|
|
6414
|
+
style: {
|
|
6415
|
+
color: selected ? "rgb(var(--foreground))" : "rgb(var(--text-tertiary))"
|
|
6416
|
+
},
|
|
6417
|
+
children: selected ? selected.label : placeholder
|
|
6418
|
+
}
|
|
6419
|
+
)
|
|
6420
|
+
]
|
|
6421
|
+
}
|
|
6422
|
+
),
|
|
6423
|
+
/* @__PURE__ */ jsx("span", { className: "affix", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
|
|
6424
|
+
ChevronDown,
|
|
6425
|
+
{
|
|
6426
|
+
className: cn(
|
|
6427
|
+
"h-4 w-4 transition-transform duration-[var(--dur-fast)] ease-[var(--ease-out)] motion-reduce:transition-none",
|
|
6428
|
+
open && "rotate-180"
|
|
6429
|
+
)
|
|
6430
|
+
}
|
|
6431
|
+
) })
|
|
6432
|
+
]
|
|
6433
|
+
}
|
|
6434
|
+
),
|
|
6435
|
+
open && typeof document !== "undefined" ? createPortal(
|
|
6436
|
+
/* @__PURE__ */ jsx(
|
|
6437
|
+
"div",
|
|
6438
|
+
{
|
|
6439
|
+
ref: listboxRefs,
|
|
6440
|
+
id: listboxId,
|
|
6441
|
+
role: "listbox",
|
|
6442
|
+
"aria-label": ariaLabelledby ? void 0 : ariaLabel,
|
|
6443
|
+
"aria-labelledby": ariaLabelledby ?? (ariaLabel ? void 0 : triggerId),
|
|
6444
|
+
tabIndex: -1,
|
|
6445
|
+
"data-slot": "select-listbox",
|
|
6446
|
+
"data-state": "open",
|
|
6447
|
+
"data-side": placement?.side,
|
|
6448
|
+
"data-align": placement?.align,
|
|
6449
|
+
"data-positioned": positioned ? "true" : "false",
|
|
6450
|
+
className: cn(LISTBOX_CLASS, positioned && "ds-enter-pop", listboxClassName),
|
|
6451
|
+
style: {
|
|
6452
|
+
...positionStyle,
|
|
6453
|
+
...POPOVER_SURFACE_STYLE,
|
|
6454
|
+
...triggerWidth ? { minWidth: triggerWidth } : void 0
|
|
6455
|
+
},
|
|
6456
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
6457
|
+
children: options.length === 0 ? /* @__PURE__ */ jsx(
|
|
6458
|
+
"div",
|
|
6459
|
+
{
|
|
6460
|
+
"data-slot": "select-empty",
|
|
6461
|
+
className: "px-2.5 py-2 text-[12.5px]",
|
|
6462
|
+
style: { color: "rgb(var(--text-tertiary))" },
|
|
6463
|
+
children: "No options"
|
|
6464
|
+
}
|
|
6465
|
+
) : options.map((option, index) => /* @__PURE__ */ jsx(
|
|
6466
|
+
ListboxOption,
|
|
6467
|
+
{
|
|
6468
|
+
id: optionId(index),
|
|
6469
|
+
label: option.label,
|
|
6470
|
+
description: option.description,
|
|
6471
|
+
icon: option.icon,
|
|
6472
|
+
selected: option.value === value,
|
|
6473
|
+
highlighted: index === activeIndex,
|
|
6474
|
+
disabled: option.disabled,
|
|
6475
|
+
onSelect: () => commit(index),
|
|
6476
|
+
onHighlight: () => setHighlight(index)
|
|
6477
|
+
},
|
|
6478
|
+
option.value
|
|
6479
|
+
))
|
|
6480
|
+
}
|
|
6481
|
+
),
|
|
6482
|
+
document.body
|
|
6483
|
+
) : null
|
|
6484
|
+
] });
|
|
6485
|
+
});
|
|
6486
|
+
var Select2 = SelectImpl;
|
|
6487
|
+
var SHELL_SIZE_CLASS2 = {
|
|
6488
|
+
sm: "size-sm",
|
|
6489
|
+
md: ""
|
|
6490
|
+
};
|
|
6491
|
+
var MULTI_SHELL_STYLE = {
|
|
6492
|
+
sm: {
|
|
6493
|
+
height: "auto",
|
|
6494
|
+
minHeight: "var(--ctrl-sm)",
|
|
6495
|
+
alignItems: "center",
|
|
6496
|
+
flexWrap: "wrap",
|
|
6497
|
+
gap: "var(--space-1)",
|
|
6498
|
+
paddingTop: "var(--space-1)",
|
|
6499
|
+
paddingBottom: "var(--space-1)"
|
|
6500
|
+
},
|
|
6501
|
+
md: {
|
|
6502
|
+
height: "auto",
|
|
6503
|
+
minHeight: "var(--ctrl-md)",
|
|
6504
|
+
alignItems: "center",
|
|
6505
|
+
flexWrap: "wrap",
|
|
6506
|
+
gap: "var(--space-1)",
|
|
6507
|
+
paddingTop: "var(--space-1)",
|
|
6508
|
+
paddingBottom: "var(--space-1)"
|
|
6509
|
+
}
|
|
6510
|
+
};
|
|
6511
|
+
var MULTI_INPUT_STYLE = { minWidth: "6rem" };
|
|
6512
|
+
function defaultFilter(option, query) {
|
|
6513
|
+
const needle = query.toLowerCase();
|
|
6514
|
+
return option.label.toLowerCase().includes(needle) || (option.description?.toLowerCase().includes(needle) ?? false);
|
|
6515
|
+
}
|
|
6516
|
+
function sanitizeId2(id) {
|
|
6517
|
+
return id.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
6518
|
+
}
|
|
6519
|
+
var ComboboxImpl = forwardRef(function Combobox(props, forwardedRef) {
|
|
6520
|
+
const {
|
|
6521
|
+
options,
|
|
6522
|
+
groups,
|
|
6523
|
+
loading,
|
|
6524
|
+
placeholder,
|
|
6525
|
+
size = "md",
|
|
6526
|
+
disabled,
|
|
6527
|
+
error,
|
|
6528
|
+
inputValue: inputValueProp,
|
|
6529
|
+
defaultInputValue = "",
|
|
6530
|
+
onInputValueChange,
|
|
6531
|
+
shouldFilter = true,
|
|
6532
|
+
filter,
|
|
6533
|
+
emptyMessage = "No results",
|
|
6534
|
+
loadingMessage = "Loading\u2026",
|
|
6535
|
+
renderOption,
|
|
6536
|
+
open: openProp,
|
|
6537
|
+
onOpenChange,
|
|
6538
|
+
side = "bottom",
|
|
6539
|
+
align = "start",
|
|
6540
|
+
id,
|
|
6541
|
+
autoFocus,
|
|
6542
|
+
"aria-label": ariaLabel,
|
|
6543
|
+
"aria-labelledby": ariaLabelledby,
|
|
6544
|
+
className,
|
|
6545
|
+
listboxClassName
|
|
6546
|
+
} = props;
|
|
6547
|
+
const isMultiple = props.multiple === true;
|
|
6548
|
+
const [uncontrolledSelection, setUncontrolledSelection] = useState(() => {
|
|
6549
|
+
if (props.multiple === true) return [...props.defaultValue ?? []];
|
|
6550
|
+
return props.defaultValue == null ? [] : [props.defaultValue];
|
|
6551
|
+
});
|
|
6552
|
+
const isControlledValue = props.value !== void 0;
|
|
6553
|
+
const selection = props.value === void 0 ? uncontrolledSelection : props.multiple === true ? props.value : props.value === null ? [] : [props.value];
|
|
6554
|
+
const emit = (next) => {
|
|
6555
|
+
if (!isControlledValue) setUncontrolledSelection(next);
|
|
6556
|
+
if (props.multiple === true) props.onValueChange?.(next);
|
|
6557
|
+
else props.onValueChange?.(next[0] ?? null);
|
|
6558
|
+
};
|
|
6559
|
+
const [uncontrolledInput, setUncontrolledInput] = useState(defaultInputValue);
|
|
6560
|
+
const inputValue = inputValueProp ?? uncontrolledInput;
|
|
6561
|
+
const setInputValue = (next) => {
|
|
6562
|
+
if (inputValueProp === void 0) setUncontrolledInput(next);
|
|
6563
|
+
onInputValueChange?.(next);
|
|
6564
|
+
};
|
|
6565
|
+
const [dirty, setDirty] = useState(false);
|
|
6566
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
|
|
6567
|
+
const isControlledOpen = openProp !== void 0;
|
|
6568
|
+
const open = isControlledOpen ? Boolean(openProp) : uncontrolledOpen;
|
|
6569
|
+
const setOpen = useCallback(
|
|
6570
|
+
(next) => {
|
|
6571
|
+
if (!isControlledOpen) setUncontrolledOpen(next);
|
|
6572
|
+
onOpenChange?.(next);
|
|
6573
|
+
},
|
|
6574
|
+
[isControlledOpen, onOpenChange]
|
|
6575
|
+
);
|
|
6576
|
+
const openRef = useRef(open);
|
|
6577
|
+
useLayoutEffect(() => {
|
|
6578
|
+
openRef.current = open;
|
|
6579
|
+
});
|
|
6580
|
+
const shellRef = useRef(null);
|
|
6581
|
+
const inputRef = useRef(null);
|
|
6582
|
+
const listboxRef = useRef(null);
|
|
6583
|
+
const baseId = sanitizeId2(useId());
|
|
6584
|
+
const inputId = id ?? `combobox-${baseId}`;
|
|
6585
|
+
const listboxId = `combobox-listbox-${baseId}`;
|
|
6586
|
+
const optionId = (index) => `${listboxId}-opt-${index}`;
|
|
6587
|
+
const byValue = useMemo(() => {
|
|
6588
|
+
const map = /* @__PURE__ */ new Map();
|
|
6589
|
+
for (const option of options) map.set(option.value, option);
|
|
6590
|
+
return map;
|
|
6591
|
+
}, [options]);
|
|
6592
|
+
const selectedSingle = isMultiple ? void 0 : byValue.get(selection[0] ?? "");
|
|
6593
|
+
const filterQuery = dirty ? inputValue.trim() : "";
|
|
6594
|
+
const { sections, flat } = useMemo(() => {
|
|
6595
|
+
const matches = filter ?? defaultFilter;
|
|
6596
|
+
const visible = shouldFilter && filterQuery ? options.filter((option) => matches(option, filterQuery)) : options;
|
|
6597
|
+
const byGroup = /* @__PURE__ */ new Map();
|
|
6598
|
+
for (const option of visible) {
|
|
6599
|
+
const key = option.group ?? null;
|
|
6600
|
+
const list = byGroup.get(key) ?? [];
|
|
6601
|
+
list.push(option);
|
|
6602
|
+
byGroup.set(key, list);
|
|
6603
|
+
}
|
|
6604
|
+
const order = [{ key: null, label: null }];
|
|
6605
|
+
if (groups) {
|
|
6606
|
+
for (const group of groups) order.push({ key: group.id, label: group.label });
|
|
6607
|
+
for (const key of byGroup.keys()) {
|
|
6608
|
+
if (key !== null && !groups.some((group) => group.id === key)) {
|
|
6609
|
+
order.push({ key, label: key });
|
|
6610
|
+
}
|
|
6611
|
+
}
|
|
6612
|
+
} else {
|
|
6613
|
+
for (const key of byGroup.keys()) if (key !== null) order.push({ key, label: key });
|
|
6614
|
+
}
|
|
6615
|
+
const flatList = [];
|
|
6616
|
+
const sectionList = [];
|
|
6617
|
+
for (const { key, label } of order) {
|
|
6618
|
+
const members = byGroup.get(key);
|
|
6619
|
+
if (!members || members.length === 0) continue;
|
|
6620
|
+
sectionList.push({
|
|
6621
|
+
key: key ?? "__ungrouped",
|
|
6622
|
+
label,
|
|
6623
|
+
items: members.map((option) => ({ option, index: flatList.push(option) - 1 }))
|
|
6624
|
+
});
|
|
6625
|
+
}
|
|
6626
|
+
return { sections: sectionList, flat: flatList };
|
|
6627
|
+
}, [options, groups, filter, shouldFilter, filterQuery]);
|
|
6628
|
+
const firstEnabled = flat.findIndex((option) => !option.disabled);
|
|
6629
|
+
const selectedFlatIndex = !isMultiple && !dirty && selectedSingle ? flat.findIndex((option) => option.value === selectedSingle.value) : -1;
|
|
6630
|
+
const [highlight, setHighlight] = useState(null);
|
|
6631
|
+
const activeIndex = highlight !== null && highlight < flat.length ? highlight : selectedFlatIndex >= 0 ? selectedFlatIndex : firstEnabled;
|
|
6632
|
+
const step = (from, direction) => {
|
|
6633
|
+
for (let i = from + direction; i >= 0 && i < flat.length; i += direction) {
|
|
6634
|
+
if (!flat[i]?.disabled) return i;
|
|
6635
|
+
}
|
|
6636
|
+
return from;
|
|
6637
|
+
};
|
|
6638
|
+
const openList = () => {
|
|
6639
|
+
if (openRef.current) return;
|
|
6640
|
+
setHighlight(null);
|
|
6641
|
+
setOpen(true);
|
|
6642
|
+
};
|
|
6643
|
+
const closeList = (clearIfEmpty) => {
|
|
6644
|
+
if (!openRef.current) return;
|
|
6645
|
+
openRef.current = false;
|
|
6646
|
+
if (!isMultiple && clearIfEmpty && dirty && inputValue.trim() === "" && selection.length > 0) {
|
|
6647
|
+
emit([]);
|
|
6648
|
+
}
|
|
6649
|
+
if (isMultiple && inputValue !== "") setInputValue("");
|
|
6650
|
+
setDirty(false);
|
|
6651
|
+
setHighlight(null);
|
|
6652
|
+
setOpen(false);
|
|
6653
|
+
};
|
|
6654
|
+
const choose = (index) => {
|
|
6655
|
+
const option = flat[index];
|
|
6656
|
+
if (!option || option.disabled) return;
|
|
6657
|
+
if (isMultiple) {
|
|
6658
|
+
const has = selection.includes(option.value);
|
|
6659
|
+
emit(has ? selection.filter((value) => value !== option.value) : [...selection, option.value]);
|
|
6660
|
+
} else {
|
|
6661
|
+
if (selection[0] !== option.value) emit([option.value]);
|
|
6662
|
+
closeList(false);
|
|
6663
|
+
}
|
|
6664
|
+
inputRef.current?.focus();
|
|
6665
|
+
};
|
|
6666
|
+
const removeChip = (value) => {
|
|
6667
|
+
emit(selection.filter((candidate) => candidate !== value));
|
|
6668
|
+
inputRef.current?.focus();
|
|
6669
|
+
};
|
|
6670
|
+
const text = isMultiple || dirty ? inputValue : selectedSingle?.label ?? "";
|
|
6671
|
+
const handleChange = (next) => {
|
|
6672
|
+
setInputValue(next);
|
|
6673
|
+
setDirty(true);
|
|
6674
|
+
setHighlight(null);
|
|
6675
|
+
if (!openRef.current) setOpen(true);
|
|
6676
|
+
};
|
|
6677
|
+
const handleKeyDown = (event) => {
|
|
6678
|
+
switch (event.key) {
|
|
6679
|
+
case "ArrowDown":
|
|
6680
|
+
event.preventDefault();
|
|
6681
|
+
if (!open) openList();
|
|
6682
|
+
else setHighlight(step(activeIndex, 1));
|
|
6683
|
+
return;
|
|
6684
|
+
case "ArrowUp":
|
|
6685
|
+
event.preventDefault();
|
|
6686
|
+
if (!open) openList();
|
|
6687
|
+
else setHighlight(step(activeIndex, -1));
|
|
6688
|
+
return;
|
|
6689
|
+
case "Enter":
|
|
6690
|
+
if (open) {
|
|
6691
|
+
event.preventDefault();
|
|
6692
|
+
if (activeIndex >= 0) choose(activeIndex);
|
|
6693
|
+
}
|
|
6694
|
+
return;
|
|
6695
|
+
case "Backspace":
|
|
6696
|
+
if (isMultiple && text === "" && selection.length > 0) {
|
|
6697
|
+
event.preventDefault();
|
|
6698
|
+
emit(selection.slice(0, -1));
|
|
6699
|
+
}
|
|
6700
|
+
return;
|
|
6701
|
+
case "Tab":
|
|
6702
|
+
if (open) closeList(true);
|
|
6703
|
+
return;
|
|
6704
|
+
default:
|
|
6705
|
+
return;
|
|
6706
|
+
}
|
|
6707
|
+
};
|
|
6708
|
+
const handleBlur = (event) => {
|
|
6709
|
+
if (event.relatedTarget instanceof Node && shellRef.current?.contains(event.relatedTarget)) {
|
|
6710
|
+
return;
|
|
6711
|
+
}
|
|
6712
|
+
closeList(true);
|
|
6713
|
+
};
|
|
6714
|
+
const {
|
|
6715
|
+
ref: positionRef,
|
|
6716
|
+
style: positionStyle,
|
|
6717
|
+
placement,
|
|
6718
|
+
positioned
|
|
6719
|
+
} = useAnchoredPosition({
|
|
6720
|
+
anchorRef: shellRef,
|
|
6721
|
+
side,
|
|
6722
|
+
align,
|
|
6723
|
+
enabled: open
|
|
6724
|
+
});
|
|
6725
|
+
const layer = useLayer({
|
|
6726
|
+
enabled: open,
|
|
6727
|
+
kind: "popover",
|
|
6728
|
+
elementRef: listboxRef,
|
|
6729
|
+
onEscape: () => closeList(false)
|
|
6730
|
+
});
|
|
6731
|
+
useOutsideClick([shellRef, listboxRef], () => closeList(true), { enabled: open, layer });
|
|
6732
|
+
const [shellWidth, setShellWidth] = useState(null);
|
|
6733
|
+
useLayoutEffect(() => {
|
|
6734
|
+
if (!open) return;
|
|
6735
|
+
setShellWidth(shellRef.current?.offsetWidth ?? null);
|
|
6736
|
+
}, [open]);
|
|
6737
|
+
useEffect(() => {
|
|
6738
|
+
if (!open) return;
|
|
6739
|
+
listboxRef.current?.querySelector("[data-highlighted]")?.scrollIntoView({ block: "nearest" });
|
|
6740
|
+
}, [open, activeIndex]);
|
|
6741
|
+
useEffect(() => {
|
|
6742
|
+
if (!autoFocus) return;
|
|
6743
|
+
const node = inputRef.current;
|
|
6744
|
+
if (!node) return;
|
|
6745
|
+
if (node.closest('[data-positioned="false"]')) return;
|
|
6746
|
+
node.focus();
|
|
6747
|
+
}, []);
|
|
6748
|
+
const inputRefs = useMemo(
|
|
6749
|
+
() => composeRefs(forwardedRef, inputRef),
|
|
6750
|
+
[forwardedRef]
|
|
6751
|
+
);
|
|
6752
|
+
const listboxRefs = useMemo(
|
|
6753
|
+
() => composeRefs(listboxRef, positionRef),
|
|
6754
|
+
[positionRef]
|
|
6755
|
+
);
|
|
6756
|
+
const chips = isMultiple ? selection : [];
|
|
6757
|
+
const hasChips = chips.length > 0;
|
|
6758
|
+
const shellStyle = isMultiple ? hasChips ? { ...MULTI_SHELL_STYLE[size], paddingLeft: "var(--space-2)" } : MULTI_SHELL_STYLE[size] : void 0;
|
|
6759
|
+
const renderItem = ({ option, index }) => {
|
|
6760
|
+
const selected = selection.includes(option.value);
|
|
6761
|
+
const highlighted = index === activeIndex;
|
|
6762
|
+
return /* @__PURE__ */ jsx(
|
|
6763
|
+
ListboxOption,
|
|
6764
|
+
{
|
|
6765
|
+
id: optionId(index),
|
|
6766
|
+
label: option.label,
|
|
6767
|
+
description: option.description,
|
|
6768
|
+
icon: option.icon,
|
|
6769
|
+
count: option.count,
|
|
6770
|
+
selected,
|
|
6771
|
+
highlighted,
|
|
6772
|
+
disabled: option.disabled,
|
|
6773
|
+
onSelect: () => choose(index),
|
|
6774
|
+
onHighlight: () => setHighlight(index),
|
|
6775
|
+
children: renderOption ? renderOption(option, { selected, highlighted, query: filterQuery }) : void 0
|
|
6776
|
+
},
|
|
6777
|
+
option.value
|
|
6778
|
+
);
|
|
6779
|
+
};
|
|
6780
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6781
|
+
/* @__PURE__ */ jsxs(
|
|
6782
|
+
"div",
|
|
6783
|
+
{
|
|
6784
|
+
ref: shellRef,
|
|
6785
|
+
"data-slot": "combobox",
|
|
6786
|
+
"data-state": open ? "open" : "closed",
|
|
6787
|
+
"data-size": size,
|
|
6788
|
+
className: cn(
|
|
6789
|
+
"input-shell has-trailing",
|
|
6790
|
+
SHELL_SIZE_CLASS2[size],
|
|
6791
|
+
hasChips && "has-leading",
|
|
6792
|
+
error && "is-error",
|
|
6793
|
+
disabled && "is-disabled",
|
|
6794
|
+
className
|
|
6795
|
+
),
|
|
6796
|
+
style: shellStyle,
|
|
6797
|
+
children: [
|
|
6798
|
+
chips.map((value) => {
|
|
6799
|
+
const label = byValue.get(value)?.label ?? value;
|
|
6800
|
+
return /* @__PURE__ */ jsxs(
|
|
6801
|
+
"span",
|
|
6802
|
+
{
|
|
6803
|
+
"data-slot": "combobox-chip",
|
|
6804
|
+
className: "inline-flex items-center gap-1 rounded-[var(--radius-xs)] py-0.5 pl-2 pr-1 text-[12px] font-medium",
|
|
6805
|
+
style: {
|
|
6806
|
+
background: "rgb(var(--surface-overlay))",
|
|
6807
|
+
color: "rgb(var(--foreground))"
|
|
6808
|
+
},
|
|
6809
|
+
children: [
|
|
6810
|
+
/* @__PURE__ */ jsx("span", { className: "max-w-[12rem] truncate", children: label }),
|
|
6811
|
+
/* @__PURE__ */ jsx(
|
|
6812
|
+
"button",
|
|
6813
|
+
{
|
|
6814
|
+
type: "button",
|
|
6815
|
+
"aria-label": `Remove ${label}`,
|
|
6816
|
+
disabled,
|
|
6817
|
+
onClick: () => removeChip(value),
|
|
6818
|
+
className: "inline-flex h-4 w-4 items-center justify-center rounded-[var(--radius-xs)] transition-colors hover:bg-[rgb(var(--surface-overlay-strong))]",
|
|
6819
|
+
style: { color: "rgb(var(--text-muted))" },
|
|
6820
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3", "aria-hidden": "true" })
|
|
6821
|
+
}
|
|
6822
|
+
)
|
|
6823
|
+
]
|
|
6824
|
+
},
|
|
6825
|
+
value
|
|
6826
|
+
);
|
|
6827
|
+
}),
|
|
6828
|
+
/* @__PURE__ */ jsx(
|
|
6829
|
+
"input",
|
|
6830
|
+
{
|
|
6831
|
+
ref: inputRefs,
|
|
6832
|
+
id: inputId,
|
|
6833
|
+
type: "text",
|
|
6834
|
+
role: "combobox",
|
|
6835
|
+
"aria-haspopup": "listbox",
|
|
6836
|
+
"aria-expanded": open,
|
|
6837
|
+
"aria-controls": open ? listboxId : void 0,
|
|
6838
|
+
"aria-autocomplete": "list",
|
|
6839
|
+
"aria-activedescendant": open && activeIndex >= 0 ? optionId(activeIndex) : void 0,
|
|
6840
|
+
"aria-label": ariaLabel,
|
|
6841
|
+
"aria-labelledby": ariaLabelledby,
|
|
6842
|
+
"aria-invalid": error ? true : void 0,
|
|
6843
|
+
autoComplete: "off",
|
|
6844
|
+
spellCheck: false,
|
|
6845
|
+
disabled,
|
|
6846
|
+
placeholder: hasChips ? "" : placeholder,
|
|
6847
|
+
value: text,
|
|
6848
|
+
"data-slot": "combobox-input",
|
|
6849
|
+
"data-autofocus": autoFocus ? "" : void 0,
|
|
6850
|
+
style: isMultiple ? MULTI_INPUT_STYLE : void 0,
|
|
6851
|
+
onChange: (event) => handleChange(event.target.value),
|
|
6852
|
+
onKeyDown: handleKeyDown,
|
|
6853
|
+
onClick: openList,
|
|
6854
|
+
onFocus: (event) => event.currentTarget.select(),
|
|
6855
|
+
onBlur: handleBlur
|
|
6856
|
+
}
|
|
6857
|
+
),
|
|
6858
|
+
loading ? /* @__PURE__ */ jsx("span", { className: "affix", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin motion-reduce:animate-none" }) }) : null,
|
|
6859
|
+
/* @__PURE__ */ jsx(
|
|
6860
|
+
"button",
|
|
6861
|
+
{
|
|
6862
|
+
type: "button",
|
|
6863
|
+
tabIndex: -1,
|
|
6864
|
+
"aria-label": open ? "Close options" : "Open options",
|
|
6865
|
+
disabled,
|
|
6866
|
+
className: "affix action",
|
|
6867
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
6868
|
+
onClick: () => {
|
|
6869
|
+
if (open) closeList(false);
|
|
6870
|
+
else openList();
|
|
6871
|
+
inputRef.current?.focus();
|
|
6872
|
+
},
|
|
6873
|
+
children: /* @__PURE__ */ jsx(
|
|
6874
|
+
ChevronDown,
|
|
6875
|
+
{
|
|
6876
|
+
className: cn(
|
|
6877
|
+
"h-4 w-4 transition-transform duration-[var(--dur-fast)] ease-[var(--ease-out)] motion-reduce:transition-none",
|
|
6878
|
+
open && "rotate-180"
|
|
6879
|
+
),
|
|
6880
|
+
"aria-hidden": "true"
|
|
6881
|
+
}
|
|
6882
|
+
)
|
|
6883
|
+
}
|
|
6884
|
+
)
|
|
5519
6885
|
]
|
|
5520
6886
|
}
|
|
5521
6887
|
),
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
6888
|
+
open && typeof document !== "undefined" ? createPortal(
|
|
6889
|
+
/* @__PURE__ */ jsx(
|
|
6890
|
+
"div",
|
|
6891
|
+
{
|
|
6892
|
+
ref: listboxRefs,
|
|
6893
|
+
id: listboxId,
|
|
6894
|
+
role: "listbox",
|
|
6895
|
+
"aria-multiselectable": isMultiple || void 0,
|
|
6896
|
+
"aria-busy": loading || void 0,
|
|
6897
|
+
"aria-label": ariaLabelledby ? void 0 : ariaLabel,
|
|
6898
|
+
"aria-labelledby": ariaLabelledby,
|
|
6899
|
+
tabIndex: -1,
|
|
6900
|
+
"data-slot": "combobox-listbox",
|
|
6901
|
+
"data-state": "open",
|
|
6902
|
+
"data-side": placement?.side,
|
|
6903
|
+
"data-align": placement?.align,
|
|
6904
|
+
"data-positioned": positioned ? "true" : "false",
|
|
6905
|
+
className: cn(LISTBOX_CLASS, positioned && "ds-enter-pop", listboxClassName),
|
|
6906
|
+
style: {
|
|
6907
|
+
...positionStyle,
|
|
6908
|
+
...POPOVER_SURFACE_STYLE,
|
|
6909
|
+
...shellWidth ? { minWidth: shellWidth } : void 0
|
|
6910
|
+
},
|
|
6911
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
6912
|
+
children: flat.length === 0 ? /* @__PURE__ */ jsx(
|
|
6913
|
+
"div",
|
|
6914
|
+
{
|
|
6915
|
+
"data-slot": "combobox-empty",
|
|
6916
|
+
className: "px-2.5 py-2 text-[12.5px]",
|
|
6917
|
+
style: { color: "rgb(var(--text-tertiary))" },
|
|
6918
|
+
children: loading ? loadingMessage : emptyMessage
|
|
6919
|
+
}
|
|
6920
|
+
) : sections.map(
|
|
6921
|
+
(section) => section.label === null ? section.items.map(renderItem) : /* @__PURE__ */ jsxs(
|
|
6922
|
+
"div",
|
|
6923
|
+
{
|
|
6924
|
+
role: "group",
|
|
6925
|
+
"aria-labelledby": `${listboxId}-group-${sanitizeId2(section.key)}`,
|
|
6926
|
+
"data-slot": "combobox-group",
|
|
6927
|
+
children: [
|
|
6928
|
+
/* @__PURE__ */ jsx(
|
|
6929
|
+
"div",
|
|
6930
|
+
{
|
|
6931
|
+
id: `${listboxId}-group-${sanitizeId2(section.key)}`,
|
|
6932
|
+
"data-slot": "combobox-group-label",
|
|
6933
|
+
className: "px-2.5 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-[0.4px]",
|
|
6934
|
+
style: { color: "rgb(var(--text-muted))" },
|
|
6935
|
+
children: section.label
|
|
6936
|
+
}
|
|
6937
|
+
),
|
|
6938
|
+
section.items.map(renderItem)
|
|
6939
|
+
]
|
|
6940
|
+
},
|
|
6941
|
+
section.key
|
|
6942
|
+
)
|
|
6943
|
+
)
|
|
6944
|
+
}
|
|
6945
|
+
),
|
|
6946
|
+
document.body
|
|
6947
|
+
) : null
|
|
5537
6948
|
] });
|
|
5538
|
-
}
|
|
5539
|
-
|
|
5540
|
-
|
|
6949
|
+
});
|
|
6950
|
+
var Combobox2 = ComboboxImpl;
|
|
6951
|
+
var TOOLTIP_SURFACE_STYLE = {
|
|
6952
|
+
background: "rgb(var(--popover))",
|
|
6953
|
+
color: "rgb(var(--popover-foreground))",
|
|
6954
|
+
border: "1px solid rgb(var(--border))",
|
|
6955
|
+
boxShadow: "var(--shadow-md)",
|
|
6956
|
+
borderRadius: "var(--radius-sm)",
|
|
6957
|
+
padding: "var(--space-1) var(--space-2)"
|
|
6958
|
+
};
|
|
6959
|
+
function Tooltip({
|
|
6960
|
+
content,
|
|
5541
6961
|
children,
|
|
6962
|
+
side = "top",
|
|
6963
|
+
align = "center",
|
|
6964
|
+
offset = 6,
|
|
6965
|
+
openDelay = 300,
|
|
6966
|
+
closeDelay = 0,
|
|
6967
|
+
open: openProp,
|
|
6968
|
+
defaultOpen,
|
|
6969
|
+
onOpenChange,
|
|
5542
6970
|
className
|
|
5543
6971
|
}) {
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
)
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
6972
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(Boolean(defaultOpen));
|
|
6973
|
+
const isControlled = openProp !== void 0;
|
|
6974
|
+
const open = isControlled ? Boolean(openProp) : uncontrolledOpen;
|
|
6975
|
+
const setOpen = useCallback(
|
|
6976
|
+
(next) => {
|
|
6977
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
6978
|
+
onOpenChange?.(next);
|
|
6979
|
+
},
|
|
6980
|
+
[isControlled, onOpenChange]
|
|
6981
|
+
);
|
|
6982
|
+
const triggerRef = useRef(null);
|
|
6983
|
+
const tipRef = useRef(null);
|
|
6984
|
+
const timerRef = useRef(null);
|
|
6985
|
+
const pointerDownRef = useRef(false);
|
|
6986
|
+
const pressEndListenerRef = useRef(null);
|
|
6987
|
+
const clearPressEndListener = useCallback(() => {
|
|
6988
|
+
const listener = pressEndListenerRef.current;
|
|
6989
|
+
if (listener === null) return;
|
|
6990
|
+
pressEndListenerRef.current = null;
|
|
6991
|
+
document.removeEventListener("pointerup", listener);
|
|
6992
|
+
document.removeEventListener("pointercancel", listener);
|
|
6993
|
+
}, []);
|
|
6994
|
+
useEffect(() => clearPressEndListener, [clearPressEndListener]);
|
|
6995
|
+
const tipId = `tooltip-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
6996
|
+
const clearTimer = useCallback(() => {
|
|
6997
|
+
if (timerRef.current !== null) {
|
|
6998
|
+
window.clearTimeout(timerRef.current);
|
|
6999
|
+
timerRef.current = null;
|
|
5555
7000
|
}
|
|
7001
|
+
}, []);
|
|
7002
|
+
useEffect(() => clearTimer, [clearTimer]);
|
|
7003
|
+
const scheduleOpen = useCallback(
|
|
7004
|
+
(delay) => {
|
|
7005
|
+
clearTimer();
|
|
7006
|
+
if (delay <= 0) {
|
|
7007
|
+
setOpen(true);
|
|
7008
|
+
return;
|
|
7009
|
+
}
|
|
7010
|
+
timerRef.current = window.setTimeout(() => {
|
|
7011
|
+
timerRef.current = null;
|
|
7012
|
+
setOpen(true);
|
|
7013
|
+
}, delay);
|
|
7014
|
+
},
|
|
7015
|
+
[clearTimer, setOpen]
|
|
5556
7016
|
);
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
7017
|
+
const scheduleClose = useCallback(
|
|
7018
|
+
(delay) => {
|
|
7019
|
+
clearTimer();
|
|
7020
|
+
if (delay <= 0) {
|
|
7021
|
+
setOpen(false);
|
|
7022
|
+
return;
|
|
7023
|
+
}
|
|
7024
|
+
timerRef.current = window.setTimeout(() => {
|
|
7025
|
+
timerRef.current = null;
|
|
7026
|
+
setOpen(false);
|
|
7027
|
+
}, delay);
|
|
7028
|
+
},
|
|
7029
|
+
[clearTimer, setOpen]
|
|
7030
|
+
);
|
|
7031
|
+
const {
|
|
7032
|
+
ref: positionRef,
|
|
7033
|
+
style: positionStyle,
|
|
7034
|
+
placement,
|
|
7035
|
+
positioned
|
|
7036
|
+
} = useAnchoredPosition({
|
|
7037
|
+
anchorRef: triggerRef,
|
|
7038
|
+
side,
|
|
7039
|
+
align,
|
|
7040
|
+
offset,
|
|
7041
|
+
enabled: open
|
|
7042
|
+
});
|
|
7043
|
+
useLayer({
|
|
7044
|
+
enabled: open,
|
|
7045
|
+
kind: "popover",
|
|
7046
|
+
elementRef: tipRef,
|
|
7047
|
+
onEscape: () => {
|
|
7048
|
+
clearTimer();
|
|
7049
|
+
setOpen(false);
|
|
7050
|
+
}
|
|
7051
|
+
});
|
|
7052
|
+
const tipRefs = useMemo(
|
|
7053
|
+
() => composeRefs(tipRef, positionRef),
|
|
7054
|
+
[positionRef]
|
|
7055
|
+
);
|
|
7056
|
+
if (!isValidElement(children)) {
|
|
7057
|
+
throw new Error("Tooltip expects exactly one element child to use as its trigger.");
|
|
7058
|
+
}
|
|
7059
|
+
if (content === null || content === void 0 || content === false) return children;
|
|
7060
|
+
const childProps = children.props;
|
|
7061
|
+
const describedBy = open ? [childProps["aria-describedby"], tipId].filter(Boolean).join(" ") : childProps["aria-describedby"];
|
|
7062
|
+
const trigger = cloneElement(children, {
|
|
7063
|
+
ref: composeRefs(childProps.ref, triggerRef),
|
|
7064
|
+
"aria-describedby": describedBy,
|
|
7065
|
+
onPointerEnter: (event) => {
|
|
7066
|
+
childProps.onPointerEnter?.(event);
|
|
7067
|
+
if (event.pointerType === "touch") return;
|
|
7068
|
+
scheduleOpen(openDelay);
|
|
7069
|
+
},
|
|
7070
|
+
onPointerLeave: (event) => {
|
|
7071
|
+
childProps.onPointerLeave?.(event);
|
|
7072
|
+
scheduleClose(closeDelay);
|
|
7073
|
+
},
|
|
7074
|
+
onPointerDown: (event) => {
|
|
7075
|
+
childProps.onPointerDown?.(event);
|
|
7076
|
+
pointerDownRef.current = true;
|
|
7077
|
+
clearPressEndListener();
|
|
7078
|
+
const onPressEnd = () => {
|
|
7079
|
+
pointerDownRef.current = false;
|
|
7080
|
+
clearPressEndListener();
|
|
7081
|
+
};
|
|
7082
|
+
pressEndListenerRef.current = onPressEnd;
|
|
7083
|
+
document.addEventListener("pointerup", onPressEnd);
|
|
7084
|
+
document.addEventListener("pointercancel", onPressEnd);
|
|
7085
|
+
clearTimer();
|
|
7086
|
+
setOpen(false);
|
|
7087
|
+
},
|
|
7088
|
+
onFocus: (event) => {
|
|
7089
|
+
childProps.onFocus?.(event);
|
|
7090
|
+
if (pointerDownRef.current) return;
|
|
7091
|
+
scheduleOpen(0);
|
|
7092
|
+
},
|
|
7093
|
+
onBlur: (event) => {
|
|
7094
|
+
childProps.onBlur?.(event);
|
|
7095
|
+
scheduleClose(0);
|
|
7096
|
+
}
|
|
7097
|
+
});
|
|
7098
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7099
|
+
trigger,
|
|
7100
|
+
open && typeof document !== "undefined" ? createPortal(
|
|
5588
7101
|
/* @__PURE__ */ jsx(
|
|
5589
|
-
|
|
7102
|
+
"div",
|
|
5590
7103
|
{
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
onCheckedChange: (checked) => toggleColumnVisibility(column.id, checked)
|
|
5607
|
-
},
|
|
5608
|
-
column.id
|
|
5609
|
-
))
|
|
5610
|
-
}
|
|
5611
|
-
)
|
|
7104
|
+
ref: tipRefs,
|
|
7105
|
+
id: tipId,
|
|
7106
|
+
role: "tooltip",
|
|
7107
|
+
"data-slot": "tooltip",
|
|
7108
|
+
"data-state": "open",
|
|
7109
|
+
"data-side": placement?.side,
|
|
7110
|
+
"data-align": placement?.align,
|
|
7111
|
+
"data-positioned": positioned ? "true" : "false",
|
|
7112
|
+
className: cn(
|
|
7113
|
+
"pointer-events-none fixed z-[110] max-w-xs text-xs font-medium leading-snug",
|
|
7114
|
+
positioned && "ds-enter-pop",
|
|
7115
|
+
className
|
|
7116
|
+
),
|
|
7117
|
+
style: { ...positionStyle, ...TOOLTIP_SURFACE_STYLE },
|
|
7118
|
+
children: content
|
|
5612
7119
|
}
|
|
5613
7120
|
),
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
DropdownMenuCheckboxItem,
|
|
5617
|
-
{
|
|
5618
|
-
checked: false,
|
|
5619
|
-
onCheckedChange: (checked) => toggleColumnVisibility(column.id, checked === true),
|
|
5620
|
-
children: column.label
|
|
5621
|
-
},
|
|
5622
|
-
column.id
|
|
5623
|
-
))
|
|
5624
|
-
] })
|
|
7121
|
+
document.body
|
|
7122
|
+
) : null
|
|
5625
7123
|
] });
|
|
5626
7124
|
}
|
|
5627
7125
|
var VARIANT_CLASS2 = {
|
|
@@ -8445,7 +9943,7 @@ var LANGUAGES = {
|
|
|
8445
9943
|
javascript,
|
|
8446
9944
|
js: javascript,
|
|
8447
9945
|
json,
|
|
8448
|
-
jsx:
|
|
9946
|
+
jsx: jsx70,
|
|
8449
9947
|
markdown,
|
|
8450
9948
|
md: markdown,
|
|
8451
9949
|
html: markup,
|
|
@@ -9194,26 +10692,6 @@ function HeaderTitle({ title }) {
|
|
|
9194
10692
|
/* @__PURE__ */ jsx("span", { style: accent, children: last })
|
|
9195
10693
|
] });
|
|
9196
10694
|
}
|
|
9197
|
-
function BenchmarkPlaceholder() {
|
|
9198
|
-
return /* @__PURE__ */ jsxs(
|
|
9199
|
-
"div",
|
|
9200
|
-
{
|
|
9201
|
-
className: "flex items-center",
|
|
9202
|
-
style: {
|
|
9203
|
-
gap: 10,
|
|
9204
|
-
padding: "12px 16px",
|
|
9205
|
-
borderRadius: "var(--radius-lg)",
|
|
9206
|
-
background: "rgb(var(--muted))",
|
|
9207
|
-
border: "1px dashed rgb(var(--border))",
|
|
9208
|
-
color: "rgb(var(--text-muted))"
|
|
9209
|
-
},
|
|
9210
|
-
children: [
|
|
9211
|
-
/* @__PURE__ */ jsx(BarChart3, { size: 15 }),
|
|
9212
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: 12, fontWeight: 500 }, children: "Benchmark unavailable in manual mode" })
|
|
9213
|
-
]
|
|
9214
|
-
}
|
|
9215
|
-
);
|
|
9216
|
-
}
|
|
9217
10695
|
function AssumptionsPopover({ children }) {
|
|
9218
10696
|
const [open, setOpen] = useState(false);
|
|
9219
10697
|
return /* @__PURE__ */ jsxs(
|
|
@@ -9307,10 +10785,9 @@ function CalculatorShellV2({
|
|
|
9307
10785
|
const header = /* @__PURE__ */ jsxs(
|
|
9308
10786
|
"header",
|
|
9309
10787
|
{
|
|
9310
|
-
className: "flex items-center",
|
|
10788
|
+
className: "flex items-center px-4 py-4 sm:px-6 sm:py-5",
|
|
9311
10789
|
style: {
|
|
9312
10790
|
gap: 16,
|
|
9313
|
-
padding: "20px 24px",
|
|
9314
10791
|
background: "rgb(var(--brand-ink))",
|
|
9315
10792
|
borderRadius: isOpen ? "var(--radius-xl)" : 0
|
|
9316
10793
|
},
|
|
@@ -9334,7 +10811,8 @@ function CalculatorShellV2({
|
|
|
9334
10811
|
/* @__PURE__ */ jsx(
|
|
9335
10812
|
"div",
|
|
9336
10813
|
{
|
|
9337
|
-
className: "font-semibold uppercase",
|
|
10814
|
+
className: "font-semibold uppercase truncate",
|
|
10815
|
+
title: eyebrow,
|
|
9338
10816
|
style: {
|
|
9339
10817
|
fontFamily: "var(--font-mono)",
|
|
9340
10818
|
fontSize: 11,
|
|
@@ -9364,10 +10842,9 @@ function CalculatorShellV2({
|
|
|
9364
10842
|
const footer = /* @__PURE__ */ jsxs(
|
|
9365
10843
|
"footer",
|
|
9366
10844
|
{
|
|
9367
|
-
className: "flex items-center",
|
|
10845
|
+
className: "flex flex-wrap items-center px-4 py-4 sm:px-6",
|
|
9368
10846
|
style: {
|
|
9369
10847
|
gap: 12,
|
|
9370
|
-
padding: "16px 24px",
|
|
9371
10848
|
borderTop: isOpen ? "none" : "1px solid rgb(var(--border))",
|
|
9372
10849
|
marginTop: isOpen ? 4 : 0,
|
|
9373
10850
|
background: isOpen ? "transparent" : "rgb(var(--bg-card))"
|
|
@@ -9414,7 +10891,7 @@ function CalculatorShellV2({
|
|
|
9414
10891
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9415
10892
|
inputs,
|
|
9416
10893
|
result,
|
|
9417
|
-
benchmarkSlot
|
|
10894
|
+
benchmarkSlot
|
|
9418
10895
|
] });
|
|
9419
10896
|
return /* @__PURE__ */ jsx(
|
|
9420
10897
|
"div",
|
|
@@ -9448,8 +10925,8 @@ function CalculatorShellV2({
|
|
|
9448
10925
|
/* @__PURE__ */ jsx(
|
|
9449
10926
|
"div",
|
|
9450
10927
|
{
|
|
9451
|
-
className: "flex flex-col",
|
|
9452
|
-
style: {
|
|
10928
|
+
className: "flex flex-col p-4 sm:p-6",
|
|
10929
|
+
style: { gap: "var(--space-4)" },
|
|
9453
10930
|
children: body
|
|
9454
10931
|
}
|
|
9455
10932
|
),
|
|
@@ -9460,90 +10937,104 @@ function CalculatorShellV2({
|
|
|
9460
10937
|
}
|
|
9461
10938
|
);
|
|
9462
10939
|
}
|
|
9463
|
-
function StatRow({ steps, className }) {
|
|
9464
|
-
return /* @__PURE__ */ jsx(
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
|
|
9478
|
-
|
|
9479
|
-
|
|
9480
|
-
|
|
9481
|
-
|
|
9482
|
-
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
10940
|
+
function StatRow({ steps, copyable = false, className }) {
|
|
10941
|
+
return /* @__PURE__ */ jsx(
|
|
10942
|
+
"div",
|
|
10943
|
+
{
|
|
10944
|
+
className: cn("grid grid-cols-2 gap-2 sm:flex sm:items-stretch sm:gap-0", className),
|
|
10945
|
+
children: steps.map((s, i) => {
|
|
10946
|
+
const panelStyle = {
|
|
10947
|
+
background: "rgb(var(--bg-card))",
|
|
10948
|
+
borderRadius: 10,
|
|
10949
|
+
padding: "12px 10px",
|
|
10950
|
+
minHeight: 46
|
|
10951
|
+
};
|
|
10952
|
+
const figure = /* @__PURE__ */ jsx(
|
|
10953
|
+
"span",
|
|
10954
|
+
{
|
|
10955
|
+
className: "font-extrabold tabular-nums",
|
|
10956
|
+
style: {
|
|
10957
|
+
fontSize: 22,
|
|
10958
|
+
letterSpacing: "-0.025em",
|
|
10959
|
+
lineHeight: 1,
|
|
10960
|
+
color: s.pivotal ? "rgb(var(--accent))" : "rgb(var(--foreground))"
|
|
10961
|
+
},
|
|
10962
|
+
children: s.value
|
|
10963
|
+
}
|
|
10964
|
+
);
|
|
10965
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
10966
|
+
i > 0 && /* @__PURE__ */ jsx(
|
|
10967
|
+
"div",
|
|
10968
|
+
{
|
|
10969
|
+
className: "hidden sm:flex items-center shrink-0",
|
|
10970
|
+
style: { padding: "0 2px", color: "rgb(var(--text-muted))" },
|
|
10971
|
+
"aria-hidden": "true",
|
|
10972
|
+
children: /* @__PURE__ */ jsx(ArrowRight, { size: 14, strokeWidth: 2.2 })
|
|
10973
|
+
}
|
|
10974
|
+
),
|
|
9486
10975
|
/* @__PURE__ */ jsxs(
|
|
9487
10976
|
"div",
|
|
9488
10977
|
{
|
|
9489
|
-
|
|
10978
|
+
"data-pivotal": s.pivotal ? "true" : void 0,
|
|
9490
10979
|
style: {
|
|
9491
|
-
|
|
9492
|
-
|
|
9493
|
-
|
|
9494
|
-
|
|
10980
|
+
flex: 1,
|
|
10981
|
+
minWidth: 0,
|
|
10982
|
+
borderRadius: "var(--radius-lg)",
|
|
10983
|
+
padding: 5,
|
|
10984
|
+
background: s.pivotal ? "rgb(var(--accent))" : "rgb(var(--brand-ink))"
|
|
9495
10985
|
},
|
|
9496
10986
|
children: [
|
|
9497
|
-
/* @__PURE__ */
|
|
9498
|
-
|
|
9499
|
-
"span",
|
|
10987
|
+
/* @__PURE__ */ jsxs(
|
|
10988
|
+
"div",
|
|
9500
10989
|
{
|
|
9501
|
-
className: "
|
|
9502
|
-
title: s.label,
|
|
10990
|
+
className: "flex items-center",
|
|
9503
10991
|
style: {
|
|
9504
|
-
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
textOverflow: "ellipsis",
|
|
9509
|
-
minWidth: 0,
|
|
9510
|
-
flex: 1
|
|
10992
|
+
gap: 5,
|
|
10993
|
+
padding: "4px 7px 6px",
|
|
10994
|
+
color: "rgb(255 255 255 / 0.7)",
|
|
10995
|
+
minWidth: 0
|
|
9511
10996
|
},
|
|
9512
|
-
children:
|
|
10997
|
+
children: [
|
|
10998
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: s.icon }),
|
|
10999
|
+
/* @__PURE__ */ jsx(
|
|
11000
|
+
"span",
|
|
11001
|
+
{
|
|
11002
|
+
className: "font-bold uppercase",
|
|
11003
|
+
title: s.label,
|
|
11004
|
+
style: {
|
|
11005
|
+
fontSize: "9.5px",
|
|
11006
|
+
letterSpacing: "0.05em",
|
|
11007
|
+
whiteSpace: "nowrap",
|
|
11008
|
+
overflow: "hidden",
|
|
11009
|
+
textOverflow: "ellipsis",
|
|
11010
|
+
minWidth: 0,
|
|
11011
|
+
flex: 1
|
|
11012
|
+
},
|
|
11013
|
+
children: s.label
|
|
11014
|
+
}
|
|
11015
|
+
)
|
|
11016
|
+
]
|
|
9513
11017
|
}
|
|
9514
|
-
)
|
|
11018
|
+
),
|
|
11019
|
+
copyable ? /* @__PURE__ */ jsx(
|
|
11020
|
+
"button",
|
|
11021
|
+
{
|
|
11022
|
+
type: "button",
|
|
11023
|
+
onClick: () => void copyText(s.copyValue ?? s.value, s.label),
|
|
11024
|
+
title: `Copy ${s.label}`,
|
|
11025
|
+
"aria-label": `Copy ${s.label}: ${s.value}`,
|
|
11026
|
+
className: "grid w-full place-items-center text-center cursor-pointer transition-[box-shadow,transform] hover:-translate-y-px hover:[box-shadow:var(--shadow-sm)] focus-visible:outline-none focus-visible:[box-shadow:var(--ring-focus)]",
|
|
11027
|
+
style: { ...panelStyle, border: "none" },
|
|
11028
|
+
children: figure
|
|
11029
|
+
}
|
|
11030
|
+
) : /* @__PURE__ */ jsx("div", { className: "grid place-items-center text-center", style: panelStyle, children: figure })
|
|
9515
11031
|
]
|
|
9516
11032
|
}
|
|
9517
|
-
),
|
|
9518
|
-
/* @__PURE__ */ jsx(
|
|
9519
|
-
"div",
|
|
9520
|
-
{
|
|
9521
|
-
className: "grid place-items-center text-center",
|
|
9522
|
-
style: {
|
|
9523
|
-
background: "rgb(var(--bg-card))",
|
|
9524
|
-
borderRadius: 10,
|
|
9525
|
-
padding: "12px 10px",
|
|
9526
|
-
minHeight: 46
|
|
9527
|
-
},
|
|
9528
|
-
children: /* @__PURE__ */ jsx(
|
|
9529
|
-
"span",
|
|
9530
|
-
{
|
|
9531
|
-
className: "font-extrabold tabular-nums",
|
|
9532
|
-
style: {
|
|
9533
|
-
fontSize: 22,
|
|
9534
|
-
letterSpacing: "-0.025em",
|
|
9535
|
-
lineHeight: 1,
|
|
9536
|
-
color: s.pivotal ? "rgb(var(--accent))" : "rgb(var(--foreground))"
|
|
9537
|
-
},
|
|
9538
|
-
children: s.value
|
|
9539
|
-
}
|
|
9540
|
-
)
|
|
9541
|
-
}
|
|
9542
11033
|
)
|
|
9543
|
-
]
|
|
9544
|
-
}
|
|
9545
|
-
|
|
9546
|
-
|
|
11034
|
+
] }, i);
|
|
11035
|
+
})
|
|
11036
|
+
}
|
|
11037
|
+
);
|
|
9547
11038
|
}
|
|
9548
11039
|
function Slider({
|
|
9549
11040
|
value,
|
|
@@ -14645,6 +16136,6 @@ var PLACEMENT_CONFIGS = [
|
|
|
14645
16136
|
}
|
|
14646
16137
|
];
|
|
14647
16138
|
|
|
14648
|
-
export { AccordionCompound as Accordion, AllocationSparkbar, AppScroll, BRAND_ICONS, Badge, BrandFacebook, BrandIcon, BrandInstagram, BrandLinkedIn, BrandLogoTile, BrandMessenger, BrandMeta, BrandNextdoor, BrandPinterest, BrandSnapchat, BrandTikTok, BulkActionBar, Button, ButtonGroup, CalculatorShell, CalculatorShellV2, card_default as Card, Checkbox, ChipNav, Choropleth, CodeBlock, CollapsibleCard, CompletionRing, CopyField, DataGrid, DataGridColumnOptionsMenu, DataGridDragOverlay, DataGridDropIndicator, DataGridToolbar, DetailSection, DeviceFrame, DragHandle, DropdownButton, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, EmptyPlaceholder, EmptyState, FOLDER_COLOR_KEYS, FileDropZone, FilePreviewGrid, FilePreviewItem, FileThumbnail, FileUploadButton, FilterBar, FilterDropdown, FloatingDrawer, FloatingStatusBar, FolderCard, FolderTreePicker, FrameStack, HEADER_HEIGHT, HeroFormCardCompound as HeroFormCard, HomeCrumbLink, IconTile, IdentityLabel, IdentityValue, Input, Kbd, ListItem, MarkdownCode, MarkdownRenderer, MenuButton, MetaCell, meta_previews_exports as MetaPreviews, MetricCard, MicrosoftLogo, modal_default as Modal, OptionTile, OptionTileGroup, PLACEMENT_CONFIGS, PageHeaderHost, PageHeaderSlotProvider, PageHero, page_shell_default as PageShell, Pagination, PillButton, profile_section_default as ProfileSection, ProgressBar, Radio, RadioGroup, RangeSlider, ResizableHandle, ResizablePane, SECTION_SCROLL_OFFSET, SearchBar, SectionLabel, SegmentedPill, Shell2 as Shell, ShellStat, Slider, SortableItem, SortableList, SortableTable, StatRow, StatsGrid, StepLoader, Tabs, TagChipInput, TagRow, TextInput, Textarea, TextareaInput, Toaster, TokenBadge, ValueChip, bestTextOn, cn, contrastRatio, copyText, folderColorVar, formatCurrency, formatNumber, formatPercent, formatRatio, hasBrandIcon, hexToRgbTuple, hslString, relativeLuminance, rgbCss, rgbString, useBreadcrumbHome, useFileUpload, wcagBadges };
|
|
16139
|
+
export { AccordionCompound as Accordion, AllocationSparkbar, AppScroll, BRAND_ICONS, Badge, BrandFacebook, BrandIcon, BrandInstagram, BrandLinkedIn, BrandLogoTile, BrandMessenger, BrandMeta, BrandNextdoor, BrandPinterest, BrandSnapchat, BrandTikTok, BulkActionBar, Button, ButtonGroup, CalculatorShell, CalculatorShellV2, card_default as Card, Checkbox, ChipNav, Choropleth, CodeBlock, CollapsibleCard, Combobox2 as Combobox, CompletionRing, CopyField, DataGrid, DataGridColumnOptionsMenu, DataGridDragOverlay, DataGridDropIndicator, DataGridToolbar, DetailSection, DeviceFrame, DragHandle, DropdownButton, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, EmptyPlaceholder, EmptyState, FOLDER_COLOR_KEYS, FileDropZone, FilePreviewGrid, FilePreviewItem, FileThumbnail, FileUploadButton, FilterBar, FilterDropdown, FloatingDrawer, FloatingStatusBar, FolderCard, FolderTreePicker, FrameStack, HEADER_HEIGHT, HeroFormCardCompound as HeroFormCard, HomeCrumbLink, IconTile, IdentityLabel, IdentityValue, Input, Kbd, LISTBOX_CLASS, ListItem, ListboxOption, MarkdownCode, MarkdownRenderer, MenuButton, MetaCell, meta_previews_exports as MetaPreviews, MetricCard, MicrosoftLogo, modal_default as Modal, OptionTile, OptionTileGroup, PLACEMENT_CONFIGS, POPOVER_SURFACE_STYLE, PageHeaderHost, PageHeaderSlotProvider, PageHero, page_shell_default as PageShell, Pagination, PillButton, Popover, profile_section_default as ProfileSection, ProgressBar, Radio, RadioGroup, RangeSlider, ResizableHandle, ResizablePane, SECTION_SCROLL_OFFSET, SearchBar, SectionLabel, SegmentedPill, Select2 as Select, Shell2 as Shell, ShellStat, Slider, SortableItem, SortableList, SortableTable, StatRow, StatsGrid, StepLoader, Tabs, TagChipInput, TagRow, TextInput, Textarea, TextareaInput, Toaster, TokenBadge, Tooltip, ValueChip, bestTextOn, cn, computeAnchoredPosition, contrastRatio, copyText, folderColorVar, formatCurrency, formatNumber, formatPercent, formatRatio, hasBrandIcon, hexToRgbTuple, hslString, relativeLuminance, rgbCss, rgbString, useAnchoredPosition, useBreadcrumbHome, useEscapeKey, useFileUpload, useLayer, useOutsideClick, wcagBadges };
|
|
14649
16140
|
//# sourceMappingURL=index.js.map
|
|
14650
16141
|
//# sourceMappingURL=index.js.map
|