@proteos/ui 0.45.0 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +720 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +191 -8
- package/dist/index.d.ts +191 -8
- package/dist/index.js +715 -74
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/attribute-type-icon/attribute-type-icon.tsx +5 -0
- package/src/components/avatar/avatar.stories.tsx +37 -1
- package/src/components/avatar/avatar.test.tsx +42 -0
- package/src/components/avatar/avatar.tsx +39 -4
- package/src/components/avatar-group/avatar-group.test.tsx +19 -0
- package/src/components/avatar-group/avatar-group.tsx +18 -3
- package/src/components/badge/badge.stories.tsx +27 -1
- package/src/components/badge/badge.test.tsx +26 -0
- package/src/components/badge/badge.tsx +48 -4
- package/src/components/badge-multi-select/badge-multi-select.stories.tsx +24 -0
- package/src/components/badge-multi-select/badge-multi-select.tsx +25 -4
- package/src/components/checkbox/checkbox.tsx +8 -1
- package/src/components/color-input/color-input.stories.tsx +72 -0
- package/src/components/color-input/color-input.test.tsx +95 -0
- package/src/components/color-input/color-input.tsx +208 -0
- package/src/components/color-input/index.ts +2 -0
- package/src/components/data-table/data-table.test.tsx +112 -0
- package/src/components/data-table/data-table.tsx +135 -11
- package/src/components/data-table/index.ts +1 -1
- package/src/components/draft-message-composer/draft-message-composer.stories.tsx +1 -1
- package/src/components/icon-picker/icon-picker.stories.tsx +77 -0
- package/src/components/icon-picker/icon-picker.test.tsx +88 -0
- package/src/components/icon-picker/icon-picker.tsx +336 -0
- package/src/components/icon-picker/index.ts +2 -0
- package/src/components/record-filter/chip-value.tsx +10 -3
- package/src/components/record-filter/filter-value-input.tsx +12 -2
- package/src/components/record-filter/operators.ts +6 -6
- package/src/components/record-filter/record-filter.stories.tsx +1 -1
- package/src/components/record-filter/types.ts +4 -0
- package/src/components/table/table.stories.tsx +12 -13
- package/src/components/toast/index.ts +9 -0
- package/src/components/toast/toast.stories.tsx +58 -0
- package/src/components/toast/toast.test.tsx +34 -0
- package/src/components/toast/toast.tsx +121 -0
- package/src/index.ts +3 -0
- package/src/test/setup.ts +30 -0
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { cn, Button, Skeleton } from './chunk-IKAX76MB.js';
|
|
2
2
|
export { Button, Skeleton, buttonStyles, cn, skeletonStyles } from './chunk-IKAX76MB.js';
|
|
3
|
-
import { Paperclip, BookText, Banknote, User, Link2, Braces, Brackets, ToggleLeft, CircleDot, Calendar, Hash, Type, File, FileImage, FileText, FileSpreadsheet, FileArchive, Loader2, X, AudioLines, Video, Mic, AtSign, MessagesSquare, Camera, Send, Linkedin, MessageCircle, Mail, ChevronDown, GripVertical, SendHorizontal, CircleX, Download, ChevronRight as ChevronRight$1, CircleCheck } from 'lucide-react';
|
|
3
|
+
import { icons, Paperclip, BookText, Banknote, UsersRound, User, Link2, Braces, Brackets, ToggleLeft, CircleDot, Calendar, Hash, Type, File, FileImage, FileText, FileSpreadsheet, FileArchive, Loader2, X, Shapes, Search, AudioLines, Video, Mic, AtSign, MessagesSquare, Camera, Send, Linkedin, MessageCircle, Mail, Pipette, ChevronDown, GripVertical, SendHorizontal, CircleX, Download, ChevronRight as ChevronRight$1, CircleCheck, CircleAlert, Info } from 'lucide-react';
|
|
4
4
|
import { tv } from 'tailwind-variants';
|
|
5
|
-
import { Tabs as Tabs$1, TabPanel, Tab, TabList, MenuTrigger as MenuTrigger$1, SubmenuTrigger as SubmenuTrigger$1, DialogTrigger, Popover as Popover$1, Dialog, DropZone, Text, FileTrigger, Heading, Label, ListBox, ListBoxItem, Breadcrumbs as Breadcrumbs$1, Breadcrumb, Link, Button as Button$1, Checkbox as Checkbox$1, CheckboxGroup as CheckboxGroup$1, FieldError,
|
|
5
|
+
import { Tabs as Tabs$1, TabPanel, Tab, TabList, MenuTrigger as MenuTrigger$1, SubmenuTrigger as SubmenuTrigger$1, DialogTrigger, Popover as Popover$1, Dialog, DropZone, Text, FileTrigger, Heading, Label, Input as Input$1, ListBox, ListBoxItem, Breadcrumbs as Breadcrumbs$1, Breadcrumb, Link, Button as Button$1, Checkbox as Checkbox$1, CheckboxGroup as CheckboxGroup$1, FieldError, TextField, ComboBox, ComboBoxStateContext, Select as Select$1, DatePicker as DatePicker$1, Group, DateInput, DateSegment, SelectValue, ModalOverlay, Modal as Modal$1, Menu as Menu$1, MenuItem as MenuItem$1, Disclosure, DisclosurePanel, ProgressBar as ProgressBar$1, RadioGroup as RadioGroup$1, Radio as Radio$1, Separator as Separator$1, Switch as Switch$1, TextArea, TimeField as TimeField$1, UNSTABLE_ToastQueue, UNSTABLE_ToastRegion, UNSTABLE_Toast, UNSTABLE_ToastContent, TooltipTrigger as TooltipTrigger$1, Tooltip as Tooltip$1, Calendar as Calendar$1, CalendarGrid, CalendarGridHeader, CalendarHeaderCell, CalendarGridBody, CalendarCell, DatePickerStateContext } from 'react-aria-components';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
|
-
import { lazy, createContext, useState, useRef, useEffect, useContext, useSyncExternalStore,
|
|
7
|
+
import { lazy, createContext, useState, useRef, useMemo, useEffect, useContext, useSyncExternalStore, useLayoutEffect, useCallback, Suspense, useId, Fragment as Fragment$1 } from 'react';
|
|
8
8
|
import { formatAmount, parseAmount } from '@proteos/sdk';
|
|
9
9
|
import { draggable, dropTargetForElements, monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
10
10
|
import { extractClosestEdge, attachClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
@@ -355,6 +355,7 @@ var AttributeType = {
|
|
|
355
355
|
Object: "object",
|
|
356
356
|
Relation: "relation",
|
|
357
357
|
User: "user",
|
|
358
|
+
Principal: "principal",
|
|
358
359
|
Currency: "currency",
|
|
359
360
|
KnowledgeText: "knowledge-text",
|
|
360
361
|
File: "file"
|
|
@@ -371,6 +372,7 @@ var ATTRIBUTE_TYPE_ICONS = {
|
|
|
371
372
|
[AttributeType.Object]: Braces,
|
|
372
373
|
[AttributeType.Relation]: Link2,
|
|
373
374
|
[AttributeType.User]: User,
|
|
375
|
+
[AttributeType.Principal]: UsersRound,
|
|
374
376
|
[AttributeType.Currency]: Banknote,
|
|
375
377
|
[AttributeType.KnowledgeText]: BookText,
|
|
376
378
|
[AttributeType.File]: Paperclip
|
|
@@ -397,7 +399,7 @@ function AttributeTypeIcon({
|
|
|
397
399
|
}
|
|
398
400
|
var avatarStyles = tv({
|
|
399
401
|
base: [
|
|
400
|
-
"inline-grid place-items-center shrink-0 select-none",
|
|
402
|
+
"inline-grid place-items-center shrink-0 select-none overflow-hidden",
|
|
401
403
|
"rounded-full border",
|
|
402
404
|
"font-mono font-medium tracking-[-0.005em]"
|
|
403
405
|
],
|
|
@@ -405,7 +407,8 @@ var avatarStyles = tv({
|
|
|
405
407
|
size: {
|
|
406
408
|
sm: "size-[22px] text-[10px]",
|
|
407
409
|
md: "size-7 text-[12px]",
|
|
408
|
-
lg: "size-9 text-[13px]"
|
|
410
|
+
lg: "size-9 text-[13px]",
|
|
411
|
+
xl: "size-[120px] text-[34px]"
|
|
409
412
|
},
|
|
410
413
|
tone: {
|
|
411
414
|
paper: "bg-surface-3 text-ink border-rule",
|
|
@@ -417,8 +420,27 @@ var avatarStyles = tv({
|
|
|
417
420
|
},
|
|
418
421
|
defaultVariants: { size: "md", tone: "paper" }
|
|
419
422
|
});
|
|
420
|
-
function Avatar({
|
|
421
|
-
|
|
423
|
+
function Avatar({
|
|
424
|
+
size,
|
|
425
|
+
tone,
|
|
426
|
+
initials,
|
|
427
|
+
src,
|
|
428
|
+
alt = "",
|
|
429
|
+
className,
|
|
430
|
+
children,
|
|
431
|
+
...props
|
|
432
|
+
}) {
|
|
433
|
+
const [failedSrc, setFailedSrc] = useState(null);
|
|
434
|
+
const showsImage = Boolean(src) && failedSrc !== src;
|
|
435
|
+
return /* @__PURE__ */ jsx("span", { ...props, className: cn(avatarStyles({ size, tone }), className), children: showsImage ? /* @__PURE__ */ jsx(
|
|
436
|
+
"img",
|
|
437
|
+
{
|
|
438
|
+
src: src ?? void 0,
|
|
439
|
+
alt,
|
|
440
|
+
className: "size-full object-cover",
|
|
441
|
+
onError: () => setFailedSrc(src ?? null)
|
|
442
|
+
}
|
|
443
|
+
) : children ?? initials });
|
|
422
444
|
}
|
|
423
445
|
var avatarGroupStyles = tv({
|
|
424
446
|
base: "flex items-center",
|
|
@@ -431,53 +453,29 @@ var avatarGroupStyles = tv({
|
|
|
431
453
|
},
|
|
432
454
|
defaultVariants: { size: "md" }
|
|
433
455
|
});
|
|
434
|
-
function AvatarGroup({
|
|
456
|
+
function AvatarGroup({
|
|
457
|
+
avatars,
|
|
458
|
+
max = 3,
|
|
459
|
+
size = "md",
|
|
460
|
+
className,
|
|
461
|
+
...props
|
|
462
|
+
}) {
|
|
435
463
|
const shown = avatars.slice(0, max);
|
|
436
464
|
const overflow = avatars.length - shown.length;
|
|
437
465
|
return /* @__PURE__ */ jsxs("span", { ...props, className: cn(avatarGroupStyles({ size }), className), children: [
|
|
438
|
-
shown.map((avatar, index) => /* @__PURE__ */ jsx("span", { className: "rounded-full ring-[1.5px] ring-surface", children: /* @__PURE__ */ jsx(
|
|
466
|
+
shown.map((avatar, index) => /* @__PURE__ */ jsx("span", { className: "rounded-full ring-[1.5px] ring-surface", children: /* @__PURE__ */ jsx(
|
|
467
|
+
Avatar,
|
|
468
|
+
{
|
|
469
|
+
size,
|
|
470
|
+
tone: avatar.tone ?? "paper",
|
|
471
|
+
initials: avatar.initials,
|
|
472
|
+
src: avatar.src ?? null,
|
|
473
|
+
alt: avatar.alt ?? ""
|
|
474
|
+
}
|
|
475
|
+
) }, avatar.key ?? index)),
|
|
439
476
|
overflow > 0 && /* @__PURE__ */ jsx("span", { className: "rounded-full ring-[1.5px] ring-surface", children: /* @__PURE__ */ jsx(Avatar, { size, tone: "paper", initials: `+${overflow}` }) })
|
|
440
477
|
] });
|
|
441
478
|
}
|
|
442
|
-
var badgeStyles = tv({
|
|
443
|
-
base: [
|
|
444
|
-
"inline-flex items-center gap-1.5",
|
|
445
|
-
"font-mono text-[11.5px] tracking-[-0.005em]",
|
|
446
|
-
"px-2.5 py-0.5 rounded-pill border",
|
|
447
|
-
// Leading dot
|
|
448
|
-
'before:content-[""] before:block before:size-1.5 before:rounded-full'
|
|
449
|
-
],
|
|
450
|
-
variants: {
|
|
451
|
-
variant: {
|
|
452
|
-
default: "border-rule bg-surface text-ink-3 before:bg-ink-4",
|
|
453
|
-
neutral: "border-rule bg-surface-3 text-ink-2 before:bg-ink-3",
|
|
454
|
-
active: [
|
|
455
|
-
"text-accent-ink before:bg-accent",
|
|
456
|
-
"border-[color-mix(in_oklab,var(--color-accent)_35%,var(--color-rule))]",
|
|
457
|
-
"bg-[color-mix(in_oklab,var(--color-accent)_14%,var(--color-surface))]"
|
|
458
|
-
],
|
|
459
|
-
success: [
|
|
460
|
-
"text-success before:bg-success",
|
|
461
|
-
"border-[color-mix(in_oklab,var(--color-success)_35%,var(--color-rule))]",
|
|
462
|
-
"bg-[color-mix(in_oklab,var(--color-success)_12%,var(--color-surface))]"
|
|
463
|
-
],
|
|
464
|
-
warning: [
|
|
465
|
-
"text-warning before:bg-warning",
|
|
466
|
-
"border-[color-mix(in_oklab,var(--color-warning)_35%,var(--color-rule))]",
|
|
467
|
-
"bg-[color-mix(in_oklab,var(--color-warning)_14%,var(--color-surface))]"
|
|
468
|
-
],
|
|
469
|
-
danger: [
|
|
470
|
-
"text-danger before:bg-danger",
|
|
471
|
-
"border-[color-mix(in_oklab,var(--color-danger)_40%,var(--color-rule))]",
|
|
472
|
-
"bg-[color-mix(in_oklab,var(--color-danger)_12%,var(--color-surface))]"
|
|
473
|
-
]
|
|
474
|
-
}
|
|
475
|
-
},
|
|
476
|
-
defaultVariants: { variant: "default" }
|
|
477
|
-
});
|
|
478
|
-
function Badge({ variant, className, ...props }) {
|
|
479
|
-
return /* @__PURE__ */ jsx("span", { ...props, className: cn(badgeStyles({ variant }), className) });
|
|
480
|
-
}
|
|
481
479
|
var fieldControlStyles = tv({
|
|
482
480
|
slots: {
|
|
483
481
|
box: [
|
|
@@ -570,6 +568,318 @@ function FieldCaret() {
|
|
|
570
568
|
}
|
|
571
569
|
) });
|
|
572
570
|
}
|
|
571
|
+
var ICON_NAMES = Object.keys(icons);
|
|
572
|
+
var BY_NORMALIZED = new Map(
|
|
573
|
+
ICON_NAMES.map((name) => [normalize(name), name])
|
|
574
|
+
);
|
|
575
|
+
function normalize(name) {
|
|
576
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
577
|
+
}
|
|
578
|
+
function resolveLucideIcon(name) {
|
|
579
|
+
const canonical = resolveLucideIconName(name);
|
|
580
|
+
return canonical ? icons[canonical] : null;
|
|
581
|
+
}
|
|
582
|
+
function resolveLucideIconName(name) {
|
|
583
|
+
if (!name) return null;
|
|
584
|
+
return BY_NORMALIZED.get(normalize(name)) ?? null;
|
|
585
|
+
}
|
|
586
|
+
var GRID_PAGE = 120;
|
|
587
|
+
var COMPACT_SIZE = {
|
|
588
|
+
sm: "size-8",
|
|
589
|
+
md: "size-[42px]"
|
|
590
|
+
};
|
|
591
|
+
function IconPicker({
|
|
592
|
+
label,
|
|
593
|
+
description,
|
|
594
|
+
errorMessage,
|
|
595
|
+
placeholder = "Choose an icon\u2026",
|
|
596
|
+
value,
|
|
597
|
+
onChange,
|
|
598
|
+
isDisabled = false,
|
|
599
|
+
isInvalid = false,
|
|
600
|
+
allowClear = true,
|
|
601
|
+
size = "md",
|
|
602
|
+
appearance,
|
|
603
|
+
compact = false,
|
|
604
|
+
"aria-label": ariaLabel,
|
|
605
|
+
className
|
|
606
|
+
}) {
|
|
607
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
608
|
+
const [query, setQuery] = useState("");
|
|
609
|
+
const [limit, setLimit] = useState(GRID_PAGE);
|
|
610
|
+
const triggerRef = useRef(null);
|
|
611
|
+
const styles3 = fieldControlStyles({ size, invalid: isInvalid, appearance });
|
|
612
|
+
const selectedName = resolveLucideIconName(value);
|
|
613
|
+
const SelectedIcon = selectedName ? icons[selectedName] : null;
|
|
614
|
+
const matches2 = useMemo(() => {
|
|
615
|
+
const q = normalize(query);
|
|
616
|
+
return q ? ICON_NAMES.filter((name) => normalize(name).includes(q)) : ICON_NAMES;
|
|
617
|
+
}, [query]);
|
|
618
|
+
const visible = matches2.slice(0, limit);
|
|
619
|
+
const hiddenCount = matches2.length - visible.length;
|
|
620
|
+
const open = (next) => {
|
|
621
|
+
setIsOpen(next);
|
|
622
|
+
if (!next) {
|
|
623
|
+
setQuery("");
|
|
624
|
+
setLimit(GRID_PAGE);
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
const search = (next) => {
|
|
628
|
+
setQuery(next);
|
|
629
|
+
setLimit(GRID_PAGE);
|
|
630
|
+
};
|
|
631
|
+
const onGridScroll = (element) => {
|
|
632
|
+
if (hiddenCount === 0) return;
|
|
633
|
+
const remaining = element.scrollHeight - element.scrollTop - element.clientHeight;
|
|
634
|
+
if (remaining < 120) setLimit((current) => current + GRID_PAGE);
|
|
635
|
+
};
|
|
636
|
+
const pick = (name) => {
|
|
637
|
+
onChange(name);
|
|
638
|
+
open(false);
|
|
639
|
+
triggerRef.current?.focus();
|
|
640
|
+
};
|
|
641
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("grid grid-cols-1 gap-1.5", className), children: [
|
|
642
|
+
label ? /* @__PURE__ */ jsx(Label, { className: fieldLabelStyles, children: label }) : null,
|
|
643
|
+
compact ? /* @__PURE__ */ jsx(
|
|
644
|
+
"button",
|
|
645
|
+
{
|
|
646
|
+
ref: triggerRef,
|
|
647
|
+
type: "button",
|
|
648
|
+
"aria-haspopup": "dialog",
|
|
649
|
+
"aria-expanded": isOpen,
|
|
650
|
+
"aria-label": ariaLabel ?? (typeof label === "string" ? label : "Icon"),
|
|
651
|
+
title: selectedName ?? placeholder,
|
|
652
|
+
disabled: isDisabled,
|
|
653
|
+
onClick: () => open(!isOpen),
|
|
654
|
+
"data-invalid": isInvalid || void 0,
|
|
655
|
+
className: cn(
|
|
656
|
+
styles3.box(),
|
|
657
|
+
"flex shrink-0 items-center justify-center cursor-pointer",
|
|
658
|
+
appearance === "cell" ? "size-[29px]" : COMPACT_SIZE[size],
|
|
659
|
+
"disabled:cursor-not-allowed disabled:opacity-45"
|
|
660
|
+
),
|
|
661
|
+
children: SelectedIcon ? /* @__PURE__ */ jsx(SelectedIcon, { "aria-hidden": true, className: "size-4 text-ink-2" }) : /* @__PURE__ */ jsx(Shapes, { "aria-hidden": true, className: "size-4 text-ink-4" })
|
|
662
|
+
}
|
|
663
|
+
) : /* @__PURE__ */ jsxs(
|
|
664
|
+
"button",
|
|
665
|
+
{
|
|
666
|
+
ref: triggerRef,
|
|
667
|
+
type: "button",
|
|
668
|
+
"aria-haspopup": "dialog",
|
|
669
|
+
"aria-expanded": isOpen,
|
|
670
|
+
"aria-label": ariaLabel ?? (typeof label === "string" ? label : "Icon"),
|
|
671
|
+
disabled: isDisabled,
|
|
672
|
+
onClick: () => open(!isOpen),
|
|
673
|
+
"data-invalid": isInvalid || void 0,
|
|
674
|
+
className: cn(
|
|
675
|
+
// box carries no padding by contract — content is what gives a
|
|
676
|
+
// single-element control its interior (padding, font, text-size).
|
|
677
|
+
styles3.box(),
|
|
678
|
+
styles3.content(),
|
|
679
|
+
"flex w-full items-center gap-2 text-left cursor-pointer",
|
|
680
|
+
"disabled:cursor-not-allowed disabled:opacity-45"
|
|
681
|
+
),
|
|
682
|
+
children: [
|
|
683
|
+
SelectedIcon ? /* @__PURE__ */ jsx(SelectedIcon, { "aria-hidden": true, className: "size-4 shrink-0 text-ink-2" }) : null,
|
|
684
|
+
/* @__PURE__ */ jsx("span", { className: cn("min-w-0 flex-1 truncate", selectedName ? "text-ink" : "text-ink-4"), children: selectedName ?? placeholder }),
|
|
685
|
+
/* @__PURE__ */ jsx(FieldCaret, {})
|
|
686
|
+
]
|
|
687
|
+
}
|
|
688
|
+
),
|
|
689
|
+
description ? /* @__PURE__ */ jsx("p", { className: fieldHintStyles, children: description }) : null,
|
|
690
|
+
errorMessage && appearance !== "cell" ? /* @__PURE__ */ jsx("p", { className: fieldErrorStyles, children: errorMessage }) : null,
|
|
691
|
+
/* @__PURE__ */ jsxs(
|
|
692
|
+
Popover$1,
|
|
693
|
+
{
|
|
694
|
+
isOpen,
|
|
695
|
+
onOpenChange: open,
|
|
696
|
+
triggerRef,
|
|
697
|
+
offset: 6,
|
|
698
|
+
placement: "bottom start",
|
|
699
|
+
className: cn(
|
|
700
|
+
"w-[316px] rounded-md border border-rule bg-surface p-2",
|
|
701
|
+
"shadow-[var(--shadow-raised)]",
|
|
702
|
+
"entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1",
|
|
703
|
+
"exiting:animate-out exiting:fade-out-0 exiting:slide-out-to-top-1"
|
|
704
|
+
),
|
|
705
|
+
children: [
|
|
706
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 pb-2", children: [
|
|
707
|
+
/* @__PURE__ */ jsxs(
|
|
708
|
+
"div",
|
|
709
|
+
{
|
|
710
|
+
className: cn(
|
|
711
|
+
fieldControlStyles({ size: "sm" }).box(),
|
|
712
|
+
"flex min-w-0 flex-1 items-center gap-1.5 px-2.5 py-1.5",
|
|
713
|
+
"focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]"
|
|
714
|
+
),
|
|
715
|
+
children: [
|
|
716
|
+
/* @__PURE__ */ jsx(Search, { "aria-hidden": true, className: "size-3.5 shrink-0 text-ink-4" }),
|
|
717
|
+
/* @__PURE__ */ jsx(
|
|
718
|
+
Input$1,
|
|
719
|
+
{
|
|
720
|
+
autoFocus: true,
|
|
721
|
+
"aria-label": "Search icons",
|
|
722
|
+
value: query,
|
|
723
|
+
onChange: (event) => search(event.target.value),
|
|
724
|
+
placeholder: "Search icons\u2026",
|
|
725
|
+
className: cn(
|
|
726
|
+
"min-w-0 flex-1 bg-transparent font-sans outline-none",
|
|
727
|
+
"text-ink placeholder:text-ink-4",
|
|
728
|
+
fieldTextStyles.sm
|
|
729
|
+
)
|
|
730
|
+
}
|
|
731
|
+
)
|
|
732
|
+
]
|
|
733
|
+
}
|
|
734
|
+
),
|
|
735
|
+
allowClear && selectedName ? /* @__PURE__ */ jsxs(
|
|
736
|
+
"button",
|
|
737
|
+
{
|
|
738
|
+
type: "button",
|
|
739
|
+
onClick: () => pick(null),
|
|
740
|
+
className: cn(
|
|
741
|
+
"flex shrink-0 items-center gap-1 rounded-[6px] px-2 py-1.5 cursor-pointer",
|
|
742
|
+
"font-sans text-[12px] text-ink-3 transition-colors",
|
|
743
|
+
"hover:bg-surface-2 hover:text-ink",
|
|
744
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-accent)]"
|
|
745
|
+
),
|
|
746
|
+
children: [
|
|
747
|
+
/* @__PURE__ */ jsx(X, { "aria-hidden": true, className: "size-3" }),
|
|
748
|
+
"Clear"
|
|
749
|
+
]
|
|
750
|
+
}
|
|
751
|
+
) : null
|
|
752
|
+
] }),
|
|
753
|
+
/* @__PURE__ */ jsx(
|
|
754
|
+
"div",
|
|
755
|
+
{
|
|
756
|
+
className: "max-h-64 overflow-y-auto",
|
|
757
|
+
onScroll: (event) => onGridScroll(event.currentTarget),
|
|
758
|
+
children: /* @__PURE__ */ jsx(
|
|
759
|
+
ListBox,
|
|
760
|
+
{
|
|
761
|
+
"aria-label": "Icons",
|
|
762
|
+
layout: "grid",
|
|
763
|
+
selectionMode: "single",
|
|
764
|
+
selectedKeys: selectedName ? /* @__PURE__ */ new Set([selectedName]) : /* @__PURE__ */ new Set(),
|
|
765
|
+
onSelectionChange: (keys) => {
|
|
766
|
+
if (keys === "all") return;
|
|
767
|
+
const next = [...keys][0];
|
|
768
|
+
if (next !== void 0) pick(next);
|
|
769
|
+
},
|
|
770
|
+
className: "grid grid-cols-8 gap-0.5 outline-none",
|
|
771
|
+
renderEmptyState: () => /* @__PURE__ */ jsx("div", { className: cn("col-span-8 px-2 py-3 text-center", fieldHintStyles), children: "No icons match" }),
|
|
772
|
+
children: visible.map((name) => {
|
|
773
|
+
const Icon = icons[name];
|
|
774
|
+
return /* @__PURE__ */ jsx(
|
|
775
|
+
ListBoxItem,
|
|
776
|
+
{
|
|
777
|
+
id: name,
|
|
778
|
+
textValue: name,
|
|
779
|
+
"aria-label": name,
|
|
780
|
+
className: cn(
|
|
781
|
+
"flex size-[34px] items-center justify-center rounded-[6px]",
|
|
782
|
+
"cursor-pointer outline-none",
|
|
783
|
+
"data-[hovered]:bg-surface-2 data-[focused]:bg-surface-2",
|
|
784
|
+
"data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--color-accent)]",
|
|
785
|
+
"data-[selected]:bg-[color-mix(in_oklab,var(--color-accent)_12%,var(--color-surface))]",
|
|
786
|
+
"data-[selected]:text-accent text-ink-2"
|
|
787
|
+
),
|
|
788
|
+
children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, className: "size-4" })
|
|
789
|
+
},
|
|
790
|
+
name
|
|
791
|
+
);
|
|
792
|
+
})
|
|
793
|
+
}
|
|
794
|
+
)
|
|
795
|
+
}
|
|
796
|
+
),
|
|
797
|
+
hiddenCount > 0 ? /* @__PURE__ */ jsxs("p", { className: cn("px-1 pt-2", fieldHintStyles), children: [
|
|
798
|
+
hiddenCount.toLocaleString(),
|
|
799
|
+
" more \u2014 keep scrolling, or search."
|
|
800
|
+
] }) : null
|
|
801
|
+
]
|
|
802
|
+
}
|
|
803
|
+
)
|
|
804
|
+
] });
|
|
805
|
+
}
|
|
806
|
+
var badgeStyles = tv({
|
|
807
|
+
base: [
|
|
808
|
+
"inline-flex items-center gap-1.5",
|
|
809
|
+
"font-mono text-[11.5px] tracking-[-0.005em]",
|
|
810
|
+
"px-2.5 py-0.5 rounded-pill border",
|
|
811
|
+
// Leading dot
|
|
812
|
+
'before:content-[""] before:block before:size-1.5 before:rounded-full'
|
|
813
|
+
],
|
|
814
|
+
variants: {
|
|
815
|
+
variant: {
|
|
816
|
+
default: "border-rule bg-surface text-ink-3 before:bg-ink-4",
|
|
817
|
+
neutral: "border-rule bg-surface-3 text-ink-2 before:bg-ink-3",
|
|
818
|
+
active: [
|
|
819
|
+
"text-accent-ink before:bg-accent",
|
|
820
|
+
"border-[color-mix(in_oklab,var(--color-accent)_35%,var(--color-rule))]",
|
|
821
|
+
"bg-[color-mix(in_oklab,var(--color-accent)_14%,var(--color-surface))]"
|
|
822
|
+
],
|
|
823
|
+
success: [
|
|
824
|
+
"text-success before:bg-success",
|
|
825
|
+
"border-[color-mix(in_oklab,var(--color-success)_35%,var(--color-rule))]",
|
|
826
|
+
"bg-[color-mix(in_oklab,var(--color-success)_12%,var(--color-surface))]"
|
|
827
|
+
],
|
|
828
|
+
warning: [
|
|
829
|
+
"text-warning before:bg-warning",
|
|
830
|
+
"border-[color-mix(in_oklab,var(--color-warning)_35%,var(--color-rule))]",
|
|
831
|
+
"bg-[color-mix(in_oklab,var(--color-warning)_14%,var(--color-surface))]"
|
|
832
|
+
],
|
|
833
|
+
danger: [
|
|
834
|
+
"text-danger before:bg-danger",
|
|
835
|
+
"border-[color-mix(in_oklab,var(--color-danger)_40%,var(--color-rule))]",
|
|
836
|
+
"bg-[color-mix(in_oklab,var(--color-danger)_12%,var(--color-surface))]"
|
|
837
|
+
],
|
|
838
|
+
// Driven by the `--badge-color` custom property (set from the `color`
|
|
839
|
+
// prop). Chrome only — text stays ink so contrast never depends on the
|
|
840
|
+
// picked color.
|
|
841
|
+
custom: [
|
|
842
|
+
"text-ink-2 before:bg-[var(--badge-color)]",
|
|
843
|
+
"border-[color-mix(in_oklab,var(--badge-color)_35%,var(--color-rule))]",
|
|
844
|
+
"bg-[color-mix(in_oklab,var(--badge-color)_12%,var(--color-surface))]"
|
|
845
|
+
]
|
|
846
|
+
}
|
|
847
|
+
},
|
|
848
|
+
defaultVariants: { variant: "default" }
|
|
849
|
+
});
|
|
850
|
+
var ICON_TONE = {
|
|
851
|
+
default: "text-ink-4",
|
|
852
|
+
neutral: "text-ink-3",
|
|
853
|
+
active: "text-accent",
|
|
854
|
+
success: "text-success",
|
|
855
|
+
warning: "text-warning",
|
|
856
|
+
danger: "text-danger",
|
|
857
|
+
custom: "text-[var(--badge-color)]"
|
|
858
|
+
};
|
|
859
|
+
function Badge({ variant, color, icon, className, style, children, ...props }) {
|
|
860
|
+
const Icon = icon ? resolveLucideIcon(icon) : null;
|
|
861
|
+
const register2 = color ? "custom" : variant ?? "default";
|
|
862
|
+
const mergedStyle = color ? { ...style, "--badge-color": color } : style;
|
|
863
|
+
return /* @__PURE__ */ jsxs(
|
|
864
|
+
"span",
|
|
865
|
+
{
|
|
866
|
+
...props,
|
|
867
|
+
style: mergedStyle,
|
|
868
|
+
className: cn(badgeStyles({ variant: register2 }), Icon ? "before:hidden" : null, className),
|
|
869
|
+
children: [
|
|
870
|
+
Icon ? /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, className: cn("size-3 shrink-0", ICON_TONE[register2]) }) : null,
|
|
871
|
+
children
|
|
872
|
+
]
|
|
873
|
+
}
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
function badgeChrome(option) {
|
|
877
|
+
return {
|
|
878
|
+
...option.variant ? { variant: option.variant } : {},
|
|
879
|
+
...option.color ? { color: option.color } : {},
|
|
880
|
+
...option.icon ? { icon: option.icon } : {}
|
|
881
|
+
};
|
|
882
|
+
}
|
|
573
883
|
function BadgeMultiSelect({
|
|
574
884
|
label,
|
|
575
885
|
description,
|
|
@@ -642,7 +952,7 @@ function BadgeMultiSelect({
|
|
|
642
952
|
) : selectedOptions.map((o) => /* @__PURE__ */ jsx(
|
|
643
953
|
RemovableBadge,
|
|
644
954
|
{
|
|
645
|
-
|
|
955
|
+
...badgeChrome(o),
|
|
646
956
|
onRemove: () => remove(o.id),
|
|
647
957
|
isDisabled,
|
|
648
958
|
children: o.label
|
|
@@ -700,7 +1010,7 @@ function BadgeMultiSelect({
|
|
|
700
1010
|
"data-[selected]:bg-surface-3",
|
|
701
1011
|
"data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed"
|
|
702
1012
|
),
|
|
703
|
-
children: /* @__PURE__ */ jsx(Badge, {
|
|
1013
|
+
children: /* @__PURE__ */ jsx(Badge, { ...badgeChrome(option), children: option.label })
|
|
704
1014
|
},
|
|
705
1015
|
option.id
|
|
706
1016
|
))
|
|
@@ -713,10 +1023,12 @@ function BadgeMultiSelect({
|
|
|
713
1023
|
function RemovableBadge({
|
|
714
1024
|
children,
|
|
715
1025
|
variant,
|
|
1026
|
+
color,
|
|
1027
|
+
icon,
|
|
716
1028
|
onRemove,
|
|
717
1029
|
isDisabled
|
|
718
1030
|
}) {
|
|
719
|
-
return /* @__PURE__ */ jsxs(Badge, { variant, children: [
|
|
1031
|
+
return /* @__PURE__ */ jsxs(Badge, { ...badgeChrome({ variant, color, icon }), children: [
|
|
720
1032
|
/* @__PURE__ */ jsx("span", { children }),
|
|
721
1033
|
/* @__PURE__ */ jsx(
|
|
722
1034
|
"button",
|
|
@@ -952,7 +1264,14 @@ function Checkbox({ children, className, ...props }) {
|
|
|
952
1264
|
{
|
|
953
1265
|
...props,
|
|
954
1266
|
className: (renderProps) => cn(
|
|
955
|
-
|
|
1267
|
+
// `relative` so RAC's visually-hidden <input> — which is absolutely
|
|
1268
|
+
// positioned and is the element that actually receives focus — is
|
|
1269
|
+
// laid out against THIS checkbox. Without a positioned ancestor here
|
|
1270
|
+
// it resolves against a far-away container, ends up outside any
|
|
1271
|
+
// scroll clipping, and focusing it makes the browser scroll a
|
|
1272
|
+
// container the user cannot scroll back (the roles permission
|
|
1273
|
+
// matrix, where toggling a row threw the page off-screen).
|
|
1274
|
+
"group relative inline-flex items-center gap-2.5 cursor-pointer",
|
|
956
1275
|
"font-sans text-[14px] text-ink-2 select-none",
|
|
957
1276
|
"data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed",
|
|
958
1277
|
typeof className === "function" ? className(renderProps) : className
|
|
@@ -1026,6 +1345,146 @@ function CheckboxGroup({
|
|
|
1026
1345
|
}
|
|
1027
1346
|
);
|
|
1028
1347
|
}
|
|
1348
|
+
var HEX6 = /^#?([0-9a-f]{6})$/i;
|
|
1349
|
+
var HEX3 = /^#?([0-9a-f]{3})$/i;
|
|
1350
|
+
function normalizeHexColor(text) {
|
|
1351
|
+
const raw = (text ?? "").trim();
|
|
1352
|
+
if (raw === "") return null;
|
|
1353
|
+
const six = HEX6.exec(raw);
|
|
1354
|
+
if (six?.[1]) return `#${six[1].toLowerCase()}`;
|
|
1355
|
+
const three = HEX3.exec(raw);
|
|
1356
|
+
if (three?.[1]) {
|
|
1357
|
+
const [r, g, b] = three[1].toLowerCase();
|
|
1358
|
+
return `#${r}${r}${g}${g}${b}${b}`;
|
|
1359
|
+
}
|
|
1360
|
+
return null;
|
|
1361
|
+
}
|
|
1362
|
+
function ColorInput({
|
|
1363
|
+
label,
|
|
1364
|
+
description,
|
|
1365
|
+
errorMessage,
|
|
1366
|
+
placeholder = "#5b8def",
|
|
1367
|
+
value,
|
|
1368
|
+
onChange,
|
|
1369
|
+
isDisabled = false,
|
|
1370
|
+
isInvalid = false,
|
|
1371
|
+
size = "md",
|
|
1372
|
+
appearance,
|
|
1373
|
+
"aria-label": ariaLabel,
|
|
1374
|
+
className
|
|
1375
|
+
}) {
|
|
1376
|
+
const committed = normalizeHexColor(value);
|
|
1377
|
+
const [draft, setDraft] = useState(committed ?? "");
|
|
1378
|
+
const nativeRef = useRef(null);
|
|
1379
|
+
useEffect(() => {
|
|
1380
|
+
setDraft((current) => normalizeHexColor(current) === committed ? current : committed ?? "");
|
|
1381
|
+
}, [committed]);
|
|
1382
|
+
const isDraftInvalid = draft.trim() !== "" && normalizeHexColor(draft) === null;
|
|
1383
|
+
const invalid = isInvalid || isDraftInvalid;
|
|
1384
|
+
const styles3 = fieldControlStyles({ size, invalid, appearance });
|
|
1385
|
+
const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
|
|
1386
|
+
const edit = (next) => {
|
|
1387
|
+
setDraft(next);
|
|
1388
|
+
if (next.trim() === "") {
|
|
1389
|
+
if (committed !== null) onChange(null);
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
if (!HEX6.test(next.trim())) return;
|
|
1393
|
+
const hex = normalizeHexColor(next);
|
|
1394
|
+
if (hex !== null && hex !== committed) onChange(hex);
|
|
1395
|
+
};
|
|
1396
|
+
const settle = () => {
|
|
1397
|
+
const hex = normalizeHexColor(draft);
|
|
1398
|
+
if (hex === null) return;
|
|
1399
|
+
setDraft(hex);
|
|
1400
|
+
if (hex !== committed) onChange(hex);
|
|
1401
|
+
};
|
|
1402
|
+
const pick = (next) => {
|
|
1403
|
+
const hex = normalizeHexColor(next);
|
|
1404
|
+
if (hex === null) return;
|
|
1405
|
+
setDraft(hex);
|
|
1406
|
+
if (hex !== committed) onChange(hex);
|
|
1407
|
+
};
|
|
1408
|
+
return /* @__PURE__ */ jsxs(
|
|
1409
|
+
TextField,
|
|
1410
|
+
{
|
|
1411
|
+
value: draft,
|
|
1412
|
+
onChange: edit,
|
|
1413
|
+
isDisabled,
|
|
1414
|
+
isInvalid: invalid,
|
|
1415
|
+
onBlur: settle,
|
|
1416
|
+
...ariaLabel ? { "aria-label": ariaLabel } : {},
|
|
1417
|
+
className: cn("grid grid-cols-1 gap-1.5", className),
|
|
1418
|
+
children: [
|
|
1419
|
+
label ? /* @__PURE__ */ jsx(Label, { className: fieldLabelStyles, children: label }) : null,
|
|
1420
|
+
/* @__PURE__ */ jsxs(
|
|
1421
|
+
"div",
|
|
1422
|
+
{
|
|
1423
|
+
"data-disabled": isDisabled || void 0,
|
|
1424
|
+
className: cn(
|
|
1425
|
+
styles3.box(),
|
|
1426
|
+
"flex items-center gap-2",
|
|
1427
|
+
size === "sm" ? "pl-2" : "pl-2.5",
|
|
1428
|
+
focusWithin
|
|
1429
|
+
),
|
|
1430
|
+
children: [
|
|
1431
|
+
/* @__PURE__ */ jsxs(
|
|
1432
|
+
"button",
|
|
1433
|
+
{
|
|
1434
|
+
type: "button",
|
|
1435
|
+
"aria-label": "Pick color",
|
|
1436
|
+
disabled: isDisabled,
|
|
1437
|
+
onClick: () => nativeRef.current?.click(),
|
|
1438
|
+
className: cn(
|
|
1439
|
+
"relative flex shrink-0 items-center justify-center rounded-sm border border-rule",
|
|
1440
|
+
"cursor-pointer outline-none",
|
|
1441
|
+
"focus-visible:ring-2 focus-visible:ring-[var(--color-accent)]",
|
|
1442
|
+
"disabled:cursor-not-allowed",
|
|
1443
|
+
size === "sm" ? "size-4" : "size-5",
|
|
1444
|
+
committed ? null : "text-ink-4"
|
|
1445
|
+
),
|
|
1446
|
+
style: committed ? { backgroundColor: committed } : void 0,
|
|
1447
|
+
children: [
|
|
1448
|
+
committed ? null : /* @__PURE__ */ jsx(Pipette, { "aria-hidden": true, className: "size-2.5" }),
|
|
1449
|
+
/* @__PURE__ */ jsx(
|
|
1450
|
+
"input",
|
|
1451
|
+
{
|
|
1452
|
+
ref: nativeRef,
|
|
1453
|
+
type: "color",
|
|
1454
|
+
tabIndex: -1,
|
|
1455
|
+
"aria-hidden": true,
|
|
1456
|
+
disabled: isDisabled,
|
|
1457
|
+
value: committed ?? "#000000",
|
|
1458
|
+
onChange: (event) => pick(event.target.value),
|
|
1459
|
+
className: "pointer-events-none absolute inset-0 size-full opacity-0"
|
|
1460
|
+
}
|
|
1461
|
+
)
|
|
1462
|
+
]
|
|
1463
|
+
}
|
|
1464
|
+
),
|
|
1465
|
+
/* @__PURE__ */ jsx(
|
|
1466
|
+
Input$1,
|
|
1467
|
+
{
|
|
1468
|
+
placeholder,
|
|
1469
|
+
spellCheck: false,
|
|
1470
|
+
autoComplete: "off",
|
|
1471
|
+
className: cn(
|
|
1472
|
+
styles3.content(),
|
|
1473
|
+
"min-w-0 flex-1 bg-transparent font-mono outline-none",
|
|
1474
|
+
"pl-0",
|
|
1475
|
+
fieldTextStyles[size]
|
|
1476
|
+
)
|
|
1477
|
+
}
|
|
1478
|
+
)
|
|
1479
|
+
]
|
|
1480
|
+
}
|
|
1481
|
+
),
|
|
1482
|
+
description ? /* @__PURE__ */ jsx(Text, { slot: "description", className: fieldHintStyles, children: description }) : null,
|
|
1483
|
+
errorMessage && appearance !== "cell" ? /* @__PURE__ */ jsx(FieldError, { className: fieldErrorStyles, children: errorMessage }) : null
|
|
1484
|
+
]
|
|
1485
|
+
}
|
|
1486
|
+
);
|
|
1487
|
+
}
|
|
1029
1488
|
function Combobox({
|
|
1030
1489
|
label,
|
|
1031
1490
|
description,
|
|
@@ -2161,6 +2620,7 @@ function useInfiniteScrollSentinel({
|
|
|
2161
2620
|
return ref;
|
|
2162
2621
|
}
|
|
2163
2622
|
var DEFAULT_ROW_HEIGHT = 32;
|
|
2623
|
+
var SELECTION_COLUMN_ID = "__select__";
|
|
2164
2624
|
function DataTable({
|
|
2165
2625
|
query,
|
|
2166
2626
|
columns,
|
|
@@ -2185,6 +2645,9 @@ function DataTable({
|
|
|
2185
2645
|
extraRows,
|
|
2186
2646
|
bodyBefore,
|
|
2187
2647
|
bodyAfter,
|
|
2648
|
+
selectionMode = "none",
|
|
2649
|
+
selectedIds,
|
|
2650
|
+
onSelectionChange,
|
|
2188
2651
|
columnBorders = false
|
|
2189
2652
|
}) {
|
|
2190
2653
|
const rows = useMemo(() => {
|
|
@@ -2195,19 +2658,112 @@ function DataTable({
|
|
|
2195
2658
|
if (startExtras.length === 0 && endExtras.length === 0) return dataRows;
|
|
2196
2659
|
return [...startExtras, ...dataRows, ...endExtras];
|
|
2197
2660
|
}, [query.data, extraRows]);
|
|
2661
|
+
const resolveRowId = useMemo(
|
|
2662
|
+
() => getRowId ?? ((row, index) => {
|
|
2663
|
+
const r = row;
|
|
2664
|
+
if (typeof r.id === "string" || typeof r.id === "number") return String(r.id);
|
|
2665
|
+
if (typeof r.slug === "string") return r.slug;
|
|
2666
|
+
return String(index);
|
|
2667
|
+
}),
|
|
2668
|
+
[getRowId]
|
|
2669
|
+
);
|
|
2670
|
+
const selectionEnabled = selectionMode === "multiple";
|
|
2671
|
+
const selected = useMemo(() => selectedIds ?? /* @__PURE__ */ new Set(), [selectedIds]);
|
|
2672
|
+
const loadedIds = useMemo(
|
|
2673
|
+
() => selectionEnabled ? rows.map((row, index) => resolveRowId(row, index)) : [],
|
|
2674
|
+
[selectionEnabled, rows, resolveRowId]
|
|
2675
|
+
);
|
|
2676
|
+
const lastToggledIndexRef = useRef(null);
|
|
2677
|
+
const toggleRow = (id, index, isRange) => {
|
|
2678
|
+
if (!onSelectionChange) return;
|
|
2679
|
+
const next = new Set(selected);
|
|
2680
|
+
const anchor = lastToggledIndexRef.current;
|
|
2681
|
+
if (isRange && anchor !== null) {
|
|
2682
|
+
const [from, to] = anchor <= index ? [anchor, index] : [index, anchor];
|
|
2683
|
+
for (let i = from; i <= to; i += 1) {
|
|
2684
|
+
const rangeId = loadedIds[i];
|
|
2685
|
+
if (rangeId !== void 0) next.add(rangeId);
|
|
2686
|
+
}
|
|
2687
|
+
} else if (next.has(id)) {
|
|
2688
|
+
next.delete(id);
|
|
2689
|
+
} else {
|
|
2690
|
+
next.add(id);
|
|
2691
|
+
}
|
|
2692
|
+
lastToggledIndexRef.current = index;
|
|
2693
|
+
onSelectionChange(next);
|
|
2694
|
+
};
|
|
2695
|
+
const loadedSelectedCount = loadedIds.reduce((count, id) => count + (selected.has(id) ? 1 : 0), 0);
|
|
2696
|
+
const allLoadedSelected = loadedIds.length > 0 && loadedSelectedCount === loadedIds.length;
|
|
2697
|
+
const toggleAllLoaded = () => {
|
|
2698
|
+
if (!onSelectionChange) return;
|
|
2699
|
+
const next = new Set(selected);
|
|
2700
|
+
if (allLoadedSelected) {
|
|
2701
|
+
for (const id of loadedIds) next.delete(id);
|
|
2702
|
+
} else {
|
|
2703
|
+
for (const id of loadedIds) next.add(id);
|
|
2704
|
+
}
|
|
2705
|
+
lastToggledIndexRef.current = null;
|
|
2706
|
+
onSelectionChange(next);
|
|
2707
|
+
};
|
|
2708
|
+
const rangeModifierRef = useRef(false);
|
|
2709
|
+
const selectionColumn = useMemo(
|
|
2710
|
+
() => ({
|
|
2711
|
+
id: SELECTION_COLUMN_ID,
|
|
2712
|
+
size: 36,
|
|
2713
|
+
enableSorting: false,
|
|
2714
|
+
meta: { align: "center", sticky: "left", cellClassName: "px-0 justify-center" },
|
|
2715
|
+
header: () => /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center w-full", children: /* @__PURE__ */ jsx(
|
|
2716
|
+
Checkbox,
|
|
2717
|
+
{
|
|
2718
|
+
"aria-label": allLoadedSelected ? "Deselect all rows" : "Select all rows",
|
|
2719
|
+
isSelected: allLoadedSelected,
|
|
2720
|
+
isIndeterminate: loadedSelectedCount > 0 && !allLoadedSelected,
|
|
2721
|
+
isDisabled: loadedIds.length === 0,
|
|
2722
|
+
onChange: toggleAllLoaded
|
|
2723
|
+
}
|
|
2724
|
+
) }),
|
|
2725
|
+
cell: ({ row }) => (
|
|
2726
|
+
// Stop the click here: selecting a row must never also open it.
|
|
2727
|
+
/* @__PURE__ */ jsx(
|
|
2728
|
+
"span",
|
|
2729
|
+
{
|
|
2730
|
+
className: "inline-flex items-center justify-center w-full",
|
|
2731
|
+
onClick: (event) => event.stopPropagation(),
|
|
2732
|
+
onKeyDown: (event) => {
|
|
2733
|
+
event.stopPropagation();
|
|
2734
|
+
rangeModifierRef.current = event.shiftKey;
|
|
2735
|
+
},
|
|
2736
|
+
onPointerDownCapture: (event) => {
|
|
2737
|
+
rangeModifierRef.current = event.shiftKey;
|
|
2738
|
+
},
|
|
2739
|
+
role: "presentation",
|
|
2740
|
+
children: /* @__PURE__ */ jsx(
|
|
2741
|
+
Checkbox,
|
|
2742
|
+
{
|
|
2743
|
+
"aria-label": `Select row ${row.index + 1}`,
|
|
2744
|
+
isSelected: selected.has(row.id),
|
|
2745
|
+
onChange: () => toggleRow(row.id, row.index, rangeModifierRef.current)
|
|
2746
|
+
}
|
|
2747
|
+
)
|
|
2748
|
+
}
|
|
2749
|
+
)
|
|
2750
|
+
)
|
|
2751
|
+
}),
|
|
2752
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: handlers read the latest selection via closure recreated on these inputs
|
|
2753
|
+
[selected, loadedIds, allLoadedSelected, loadedSelectedCount]
|
|
2754
|
+
);
|
|
2755
|
+
const tableColumns = useMemo(
|
|
2756
|
+
() => selectionEnabled ? [selectionColumn, ...columns] : columns,
|
|
2757
|
+
[selectionEnabled, selectionColumn, columns]
|
|
2758
|
+
);
|
|
2198
2759
|
const table = useReactTable({
|
|
2199
2760
|
data: rows,
|
|
2200
|
-
columns,
|
|
2761
|
+
columns: tableColumns,
|
|
2201
2762
|
state: { sorting: sorting ?? [] },
|
|
2202
2763
|
...onSortingChange ? { onSortingChange } : {},
|
|
2203
2764
|
manualSorting: true,
|
|
2204
2765
|
getCoreRowModel: getCoreRowModel(),
|
|
2205
|
-
getRowId:
|
|
2206
|
-
const r = row;
|
|
2207
|
-
if (typeof r.id === "string" || typeof r.id === "number") return String(r.id);
|
|
2208
|
-
if (typeof r.slug === "string") return r.slug;
|
|
2209
|
-
return String(index);
|
|
2210
|
-
}
|
|
2766
|
+
getRowId: (row, index) => resolveRowId(row, index)
|
|
2211
2767
|
});
|
|
2212
2768
|
const tableRows = table.getRowModel().rows;
|
|
2213
2769
|
const tableRowCount = tableRows.length;
|
|
@@ -2239,8 +2795,8 @@ function DataTable({
|
|
|
2239
2795
|
enabled: !!query.hasNextPage
|
|
2240
2796
|
});
|
|
2241
2797
|
const totalColumnWidth = useMemo(
|
|
2242
|
-
() =>
|
|
2243
|
-
[
|
|
2798
|
+
() => tableColumns.reduce((sum, c) => sum + (c.size ?? 140), 0),
|
|
2799
|
+
[tableColumns]
|
|
2244
2800
|
);
|
|
2245
2801
|
const columnsRef = useRef(columns);
|
|
2246
2802
|
columnsRef.current = columns;
|
|
@@ -4876,25 +5432,25 @@ var OPERATORS = [
|
|
|
4876
5432
|
id: "eq",
|
|
4877
5433
|
label: "is",
|
|
4878
5434
|
arity: 1,
|
|
4879
|
-
types: ["string", "number", "integer", "currency", "datetime", "enum", "boolean", "relation", "user"]
|
|
5435
|
+
types: ["string", "number", "integer", "currency", "datetime", "enum", "boolean", "relation", "user", "principal"]
|
|
4880
5436
|
},
|
|
4881
5437
|
{
|
|
4882
5438
|
id: "ne",
|
|
4883
5439
|
label: "is not",
|
|
4884
5440
|
arity: 1,
|
|
4885
|
-
types: ["string", "number", "integer", "currency", "datetime", "enum", "boolean", "relation", "user"]
|
|
5441
|
+
types: ["string", "number", "integer", "currency", "datetime", "enum", "boolean", "relation", "user", "principal"]
|
|
4886
5442
|
},
|
|
4887
5443
|
{
|
|
4888
5444
|
id: "in",
|
|
4889
5445
|
label: "is any of",
|
|
4890
5446
|
arity: "n",
|
|
4891
|
-
types: ["string", "number", "integer", "currency", "enum", "relation", "user"]
|
|
5447
|
+
types: ["string", "number", "integer", "currency", "enum", "relation", "user", "principal"]
|
|
4892
5448
|
},
|
|
4893
5449
|
{
|
|
4894
5450
|
id: "not_in",
|
|
4895
5451
|
label: "is none of",
|
|
4896
5452
|
arity: "n",
|
|
4897
|
-
types: ["string", "number", "integer", "currency", "enum", "relation", "user"]
|
|
5453
|
+
types: ["string", "number", "integer", "currency", "enum", "relation", "user", "principal"]
|
|
4898
5454
|
},
|
|
4899
5455
|
{ id: "contains", label: "contains", arity: 1, types: ["string", "array"] },
|
|
4900
5456
|
{ id: "starts_with", label: "starts with", arity: 1, types: ["string"] },
|
|
@@ -4907,13 +5463,13 @@ var OPERATORS = [
|
|
|
4907
5463
|
id: "empty",
|
|
4908
5464
|
label: "is empty",
|
|
4909
5465
|
arity: 0,
|
|
4910
|
-
types: ["string", "number", "integer", "currency", "datetime", "enum", "boolean", "array", "relation", "user", "file"]
|
|
5466
|
+
types: ["string", "number", "integer", "currency", "datetime", "enum", "boolean", "array", "relation", "user", "principal", "file"]
|
|
4911
5467
|
},
|
|
4912
5468
|
{
|
|
4913
5469
|
id: "not_empty",
|
|
4914
5470
|
label: "is not empty",
|
|
4915
5471
|
arity: 0,
|
|
4916
|
-
types: ["string", "number", "integer", "currency", "datetime", "enum", "boolean", "array", "relation", "user", "file"]
|
|
5472
|
+
types: ["string", "number", "integer", "currency", "datetime", "enum", "boolean", "array", "relation", "user", "principal", "file"]
|
|
4917
5473
|
}
|
|
4918
5474
|
];
|
|
4919
5475
|
var OP_LABEL_OVERRIDES = {
|
|
@@ -5001,9 +5557,16 @@ function ChipItem({
|
|
|
5001
5557
|
if (custom !== void 0) return /* @__PURE__ */ jsx(Fragment, { children: custom });
|
|
5002
5558
|
}
|
|
5003
5559
|
if (field.type === "enum") {
|
|
5004
|
-
const
|
|
5005
|
-
|
|
5006
|
-
|
|
5560
|
+
const option = field.options?.find((o) => o.value === value);
|
|
5561
|
+
return /* @__PURE__ */ jsx(
|
|
5562
|
+
Badge,
|
|
5563
|
+
{
|
|
5564
|
+
variant: option?.variant,
|
|
5565
|
+
...option?.color ? { color: option.color } : {},
|
|
5566
|
+
...option?.icon ? { icon: option.icon } : {},
|
|
5567
|
+
children: option?.label ?? value
|
|
5568
|
+
}
|
|
5569
|
+
);
|
|
5007
5570
|
}
|
|
5008
5571
|
return /* @__PURE__ */ jsx("span", { className: cn("font-mono text-[12px] text-ink max-w-[10rem] truncate"), children: formatValue(field, operator, value) });
|
|
5009
5572
|
}
|
|
@@ -5384,8 +5947,16 @@ function EnumSingleValue({
|
|
|
5384
5947
|
selectedKey: value === "" ? null : value,
|
|
5385
5948
|
onSelectionChange: (next) => onChange(next == null ? "" : String(next)),
|
|
5386
5949
|
renderItem: (o) => {
|
|
5387
|
-
const
|
|
5388
|
-
return /* @__PURE__ */ jsx(
|
|
5950
|
+
const option = field.options?.find((x) => x.value === o.id);
|
|
5951
|
+
return /* @__PURE__ */ jsx(
|
|
5952
|
+
Badge,
|
|
5953
|
+
{
|
|
5954
|
+
variant: option?.variant,
|
|
5955
|
+
...option?.color ? { color: option.color } : {},
|
|
5956
|
+
...option?.icon ? { icon: option.icon } : {},
|
|
5957
|
+
children: o.label
|
|
5958
|
+
}
|
|
5959
|
+
);
|
|
5389
5960
|
},
|
|
5390
5961
|
...isDisabled !== void 0 ? { isDisabled } : {},
|
|
5391
5962
|
...autoFocus ? { autoFocus: true } : {},
|
|
@@ -5404,7 +5975,9 @@ function EnumMultiValue({
|
|
|
5404
5975
|
const options = (field.options ?? []).map((o) => ({
|
|
5405
5976
|
id: o.value,
|
|
5406
5977
|
label: o.label,
|
|
5407
|
-
...o.variant ? { variant: o.variant } : {}
|
|
5978
|
+
...o.variant ? { variant: o.variant } : {},
|
|
5979
|
+
...o.color ? { color: o.color } : {},
|
|
5980
|
+
...o.icon ? { icon: o.icon } : {}
|
|
5408
5981
|
}));
|
|
5409
5982
|
return /* @__PURE__ */ jsx(
|
|
5410
5983
|
BadgeMultiSelect,
|
|
@@ -7038,6 +7611,74 @@ function TimeField({
|
|
|
7038
7611
|
}
|
|
7039
7612
|
);
|
|
7040
7613
|
}
|
|
7614
|
+
function createToastQueue(options = {}) {
|
|
7615
|
+
return new UNSTABLE_ToastQueue({ maxVisibleToasts: options.maxVisibleToasts ?? 3 });
|
|
7616
|
+
}
|
|
7617
|
+
var toastStyles = tv({
|
|
7618
|
+
slots: {
|
|
7619
|
+
root: [
|
|
7620
|
+
"flex items-start gap-3 w-[360px] max-w-[calc(100vw-32px)]",
|
|
7621
|
+
"rounded-lg border border-rule bg-surface shadow-float",
|
|
7622
|
+
"px-3.5 py-3 outline-none",
|
|
7623
|
+
"focus-visible:shadow-focus",
|
|
7624
|
+
"entering:animate-in entering:fade-in-0 entering:slide-in-from-bottom-2 entering:duration-200",
|
|
7625
|
+
"exiting:animate-out exiting:fade-out-0 exiting:duration-150"
|
|
7626
|
+
],
|
|
7627
|
+
icon: "size-4 shrink-0 mt-0.5",
|
|
7628
|
+
title: "font-sans text-[13px] font-medium leading-[1.4] text-ink",
|
|
7629
|
+
description: "font-sans text-[12.5px] leading-[1.5] text-ink-3 break-words"
|
|
7630
|
+
},
|
|
7631
|
+
variants: {
|
|
7632
|
+
variant: {
|
|
7633
|
+
info: { icon: "text-ink-3" },
|
|
7634
|
+
success: { icon: "text-success" },
|
|
7635
|
+
danger: { icon: "text-danger" }
|
|
7636
|
+
}
|
|
7637
|
+
},
|
|
7638
|
+
defaultVariants: { variant: "info" }
|
|
7639
|
+
});
|
|
7640
|
+
var VARIANT_ICON = {
|
|
7641
|
+
info: Info,
|
|
7642
|
+
success: CircleCheck,
|
|
7643
|
+
danger: CircleAlert
|
|
7644
|
+
};
|
|
7645
|
+
function ToastRegion({ queue, className }) {
|
|
7646
|
+
return /* @__PURE__ */ jsx(
|
|
7647
|
+
UNSTABLE_ToastRegion,
|
|
7648
|
+
{
|
|
7649
|
+
queue,
|
|
7650
|
+
className: cn(
|
|
7651
|
+
"fixed bottom-4 right-4 z-[1300] flex flex-col-reverse gap-2 outline-none",
|
|
7652
|
+
className
|
|
7653
|
+
),
|
|
7654
|
+
children: ({ toast }) => {
|
|
7655
|
+
const variant = toast.content.variant ?? "info";
|
|
7656
|
+
const Icon = VARIANT_ICON[variant];
|
|
7657
|
+
const { root, icon, title, description } = toastStyles({ variant });
|
|
7658
|
+
return /* @__PURE__ */ jsxs(UNSTABLE_Toast, { toast, className: root(), children: [
|
|
7659
|
+
/* @__PURE__ */ jsx(Icon, { className: icon(), "aria-hidden": true }),
|
|
7660
|
+
/* @__PURE__ */ jsxs(UNSTABLE_ToastContent, { className: "flex flex-col gap-0.5 flex-1 min-w-0", children: [
|
|
7661
|
+
/* @__PURE__ */ jsx(Text, { slot: "title", className: title(), children: toast.content.title }),
|
|
7662
|
+
toast.content.description ? /* @__PURE__ */ jsx(Text, { slot: "description", className: description(), children: toast.content.description }) : null
|
|
7663
|
+
] }),
|
|
7664
|
+
/* @__PURE__ */ jsx(
|
|
7665
|
+
Button$1,
|
|
7666
|
+
{
|
|
7667
|
+
slot: "close",
|
|
7668
|
+
"aria-label": "Dismiss",
|
|
7669
|
+
className: cn(
|
|
7670
|
+
"shrink-0 inline-flex items-center justify-center size-6 rounded-md",
|
|
7671
|
+
"text-ink-4 hover:text-ink hover:bg-surface-2 cursor-pointer outline-none",
|
|
7672
|
+
"focus-visible:shadow-focus"
|
|
7673
|
+
),
|
|
7674
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
|
|
7675
|
+
}
|
|
7676
|
+
)
|
|
7677
|
+
] });
|
|
7678
|
+
}
|
|
7679
|
+
}
|
|
7680
|
+
);
|
|
7681
|
+
}
|
|
7041
7682
|
function TooltipTrigger({
|
|
7042
7683
|
delay = 500,
|
|
7043
7684
|
closeDelay = 0,
|
|
@@ -7064,6 +7705,6 @@ function Tooltip({ className, offset = 6, ...props }) {
|
|
|
7064
7705
|
);
|
|
7065
7706
|
}
|
|
7066
7707
|
|
|
7067
|
-
export { ATTRIBUTE_TYPES, ATTRIBUTE_TYPE_ICONS, AttachmentChip, AttributePicker, AttributeType, AttributeTypeIcon, Avatar, AvatarGroup, Badge, BadgeMultiSelect, BooleanCell, Breadcrumbs, COLUMN_DRAG_KIND, Card, CardBody, CardContent, CardEyebrow, CardFeatureTitle, CardFooter, CardHeader, CardTitle, ChannelIcon, Checkbox, CheckboxGroup, ChipValue, Combobox, Command, CommandHint, CurrencyInput, DRAFT_OUTCOME_LABEL, DataTable, DataTableEmpty, DataTableError, DataTableSkeleton, DateCell, DatePicker, DateTimeCell, DateTimePicker, DraftMessageCard, DraftMessageComposer, DraftMessageReview, EmptyState, ErrorAnimation, FieldCaret, FileField, FileViewer, FileViewerFallbackCard, FilterRow, FilterValueInput, ImageAttachment, ImageLightbox, Input, Kbd, LinkCell, MAX_COMPOSER_ATTACHMENT_BYTES, Menu, MenuItem, MenuPopover, MenuTrigger, MessageComposer, Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle, MultiSelect, NavGroup, NavItem, NavSection, OPERATORS, OperatorPicker, PROTECTED_COMBOS, Popover, PopoverContent, PopoverPanelBody, PopoverPanelFooter, PopoverPanelHeader, PressableCard, ProgressBar, Radio, RadioGroup, RecipientSelect, RecordFilterBuilderPanel, RecordFilterButton, RecordFilterChips, RecordFilterEditor, RenderChipItemProvider, RenderValueInputProvider, SegmentedControl, Select, Separator, SubmenuTrigger, SuccessAnimation, Switch, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TableHeaderSpacer, TableRow, TableScroller, Tabs, TagInput, Textarea, TimeField, Tooltip, TooltipTrigger, TruncateCell, __resetDraftMessageActions, __resetDraftMessageOutcomes, addLeaf as addFilterLeaf, addPendingLeaf, addSubgroup, arityOf, attachmentChipStyles, avatarGroupStyles, avatarStyles, badgeStyles, cardStyles2 as cardStyles, channelIcon, countLeaves, createDraftMessageClient, defaultValueFor, draftMessageCardStyles, draftMessageComposerStyles, draftOutcomeFor, emptyStateStyles, fieldControlStyles, fieldErrorStyles, fieldHintStyles, fieldLabelStyles, fileViewerFallbackCardStyles, fileViewerStyles, formatFileSize, formatValue, iconForContentType, imageAttachmentStyles, imageLightboxStyles, isColumnDragData, isDraftReviewOutcome, isEditableTarget, isPreviewableImageName, makeActionsColumn, messageComposerStyles, navItemStyles, operatorById, operatorsForType, parseCombo, progressBarStyles, publishDraftMessageOutcome, rebaseRowOnFieldChange, rebaseRowOnOperatorChange, registerDraftMessageActions, removeLeaf, removeSubgroup, replaceLeaf, segmentedControlStyles, setJoiner, subscribeDraftMessageOutcome, tableCellStyles, tableHeaderCellStyles, tabsStyles, terminalKindFor, updateLeaf, updateSubgroup, useAttributeTypeIcon, useCommand, useDiscoveryActive, useDraftMessageActions, useDraftMessageOutcome, useEscapeKey, useInfiniteScrollSentinel, useRenderChipItem, useRenderValueInput, useShowDetails, viewerKindForContentType, wrapLeafInGroup };
|
|
7708
|
+
export { ATTRIBUTE_TYPES, ATTRIBUTE_TYPE_ICONS, AttachmentChip, AttributePicker, AttributeType, AttributeTypeIcon, Avatar, AvatarGroup, Badge, BadgeMultiSelect, BooleanCell, Breadcrumbs, COLUMN_DRAG_KIND, Card, CardBody, CardContent, CardEyebrow, CardFeatureTitle, CardFooter, CardHeader, CardTitle, ChannelIcon, Checkbox, CheckboxGroup, ChipValue, ColorInput, Combobox, Command, CommandHint, CurrencyInput, DRAFT_OUTCOME_LABEL, DataTable, DataTableEmpty, DataTableError, DataTableSkeleton, DateCell, DatePicker, DateTimeCell, DateTimePicker, DraftMessageCard, DraftMessageComposer, DraftMessageReview, EmptyState, ErrorAnimation, FieldCaret, FileField, FileViewer, FileViewerFallbackCard, FilterRow, FilterValueInput, IconPicker, ImageAttachment, ImageLightbox, Input, Kbd, LinkCell, MAX_COMPOSER_ATTACHMENT_BYTES, Menu, MenuItem, MenuPopover, MenuTrigger, MessageComposer, Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle, MultiSelect, NavGroup, NavItem, NavSection, OPERATORS, OperatorPicker, PROTECTED_COMBOS, Popover, PopoverContent, PopoverPanelBody, PopoverPanelFooter, PopoverPanelHeader, PressableCard, ProgressBar, Radio, RadioGroup, RecipientSelect, RecordFilterBuilderPanel, RecordFilterButton, RecordFilterChips, RecordFilterEditor, RenderChipItemProvider, RenderValueInputProvider, SELECTION_COLUMN_ID, SegmentedControl, Select, Separator, SubmenuTrigger, SuccessAnimation, Switch, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TableHeaderSpacer, TableRow, TableScroller, Tabs, TagInput, Textarea, TimeField, ToastRegion, Tooltip, TooltipTrigger, TruncateCell, __resetDraftMessageActions, __resetDraftMessageOutcomes, addLeaf as addFilterLeaf, addPendingLeaf, addSubgroup, arityOf, attachmentChipStyles, avatarGroupStyles, avatarStyles, badgeStyles, cardStyles2 as cardStyles, channelIcon, countLeaves, createDraftMessageClient, createToastQueue, defaultValueFor, draftMessageCardStyles, draftMessageComposerStyles, draftOutcomeFor, emptyStateStyles, fieldControlStyles, fieldErrorStyles, fieldHintStyles, fieldLabelStyles, fileViewerFallbackCardStyles, fileViewerStyles, formatFileSize, formatValue, iconForContentType, imageAttachmentStyles, imageLightboxStyles, isColumnDragData, isDraftReviewOutcome, isEditableTarget, isPreviewableImageName, makeActionsColumn, messageComposerStyles, navItemStyles, normalizeHexColor, operatorById, operatorsForType, parseCombo, progressBarStyles, publishDraftMessageOutcome, rebaseRowOnFieldChange, rebaseRowOnOperatorChange, registerDraftMessageActions, removeLeaf, removeSubgroup, replaceLeaf, resolveLucideIcon, resolveLucideIconName, segmentedControlStyles, setJoiner, subscribeDraftMessageOutcome, tableCellStyles, tableHeaderCellStyles, tabsStyles, terminalKindFor, toastStyles, updateLeaf, updateSubgroup, useAttributeTypeIcon, useCommand, useDiscoveryActive, useDraftMessageActions, useDraftMessageOutcome, useEscapeKey, useInfiniteScrollSentinel, useRenderChipItem, useRenderValueInput, useShowDetails, viewerKindForContentType, wrapLeafInGroup };
|
|
7068
7709
|
//# sourceMappingURL=index.js.map
|
|
7069
7710
|
//# sourceMappingURL=index.js.map
|