pixelize-design-library 2.4.2-beta.34 → 2.4.2-beta.35

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.
Files changed (84) hide show
  1. package/dist/Components/AppSwitcher/AppSwitcher.js +10 -4
  2. package/dist/Components/ButtonGroupIcon/ButtonGroupIcon.js +1 -3
  3. package/dist/Components/Common/fieldStyles.js +1 -1
  4. package/dist/Components/CopyButton/CopyButton.js +7 -6
  5. package/dist/Components/DatePicker/CalendarPanel.js +8 -5
  6. package/dist/Components/DatePicker/RangeDatePicker.js +27 -3
  7. package/dist/Components/DatePicker/SingleDatePicker.js +48 -14
  8. package/dist/Components/DatePicker/TimeOnlyPicker.js +7 -1
  9. package/dist/Components/DatePicker/TimePicker.js +3 -3
  10. package/dist/Components/DatePicker/TimePickerInput.js +1 -1
  11. package/dist/Components/Dropdown/DropDown.js +19 -6
  12. package/dist/Components/EmptyState/EmptyState.js +1 -1
  13. package/dist/Components/FileUpload/FileUpload.js +2 -2
  14. package/dist/Components/FilterSidebar/FilterSidebar.js +5 -5
  15. package/dist/Components/FilterSidebar/filterHoverStyle.d.ts +2 -1
  16. package/dist/Components/FilterSidebar/filterHoverStyle.js +3 -4
  17. package/dist/Components/Input/TextInput.styles.js +2 -2
  18. package/dist/Components/InputTextArea/InputTextArea.style.js +2 -2
  19. package/dist/Components/MoreItems/MoreItems.js +3 -1
  20. package/dist/Components/MultiSelect/MultiSelect.js +2 -2
  21. package/dist/Components/NavigationBar/NavigationBar.js +6 -7
  22. package/dist/Components/NumberInput/NumberInput.styles.js +2 -2
  23. package/dist/Components/OrgSwitcher/OrgSwitcher.js +14 -10
  24. package/dist/Components/PdfViewer/PdfViewer.js +4 -4
  25. package/dist/Components/RolesPermission/RolesPermission.js +4 -3
  26. package/dist/Components/SearchSelect/SearchSelect.js +46 -41
  27. package/dist/Components/Select/Select.styles.js +1 -1
  28. package/dist/Components/SelectSearch/SelectSearch.js +35 -17
  29. package/dist/Components/SelectV2/SelectV2.js +3 -0
  30. package/dist/Components/Table/TableProps.d.ts +2 -0
  31. package/dist/Components/Table/components/TableBody.js +7 -10
  32. package/dist/Components/Table/filters/CompactSelect.js +29 -8
  33. package/dist/Components/Table/settings/ManageColumns.js +5 -3
  34. package/dist/Components/Table/settings/TableSettings.js +4 -2
  35. package/dist/Components/Trail/EditableCell.js +1 -1
  36. package/dist/Components/UserDetails/DeactivateConfirmModal.js +1 -1
  37. package/dist/Components/UserDetails/UserDetails.js +5 -3
  38. package/dist/Hooks/exclusiveOverlay.d.ts +4 -0
  39. package/dist/Hooks/exclusiveOverlay.js +22 -0
  40. package/dist/Hooks/useExclusiveOverlay.d.ts +5 -0
  41. package/dist/Hooks/useExclusiveOverlay.js +24 -0
  42. package/dist/Theme/chakra/Menu.styles.js +4 -2
  43. package/dist/Utils/table.d.ts +3 -0
  44. package/dist/Utils/table.js +44 -1
  45. package/dist/esm/Components/AppSwitcher/AppSwitcher.js +11 -5
  46. package/dist/esm/Components/ButtonGroupIcon/ButtonGroupIcon.js +1 -3
  47. package/dist/esm/Components/Common/fieldStyles.js +1 -1
  48. package/dist/esm/Components/CopyButton/CopyButton.js +7 -6
  49. package/dist/esm/Components/DatePicker/CalendarPanel.js +9 -6
  50. package/dist/esm/Components/DatePicker/RangeDatePicker.js +28 -4
  51. package/dist/esm/Components/DatePicker/SingleDatePicker.js +49 -15
  52. package/dist/esm/Components/DatePicker/TimeOnlyPicker.js +7 -1
  53. package/dist/esm/Components/DatePicker/TimePicker.js +3 -3
  54. package/dist/esm/Components/DatePicker/TimePickerInput.js +1 -1
  55. package/dist/esm/Components/Dropdown/DropDown.js +20 -7
  56. package/dist/esm/Components/EmptyState/EmptyState.js +1 -1
  57. package/dist/esm/Components/FileUpload/FileUpload.js +2 -2
  58. package/dist/esm/Components/FilterSidebar/FilterSidebar.js +5 -5
  59. package/dist/esm/Components/FilterSidebar/filterHoverStyle.js +3 -4
  60. package/dist/esm/Components/Input/TextInput.styles.js +2 -2
  61. package/dist/esm/Components/InputTextArea/InputTextArea.style.js +2 -2
  62. package/dist/esm/Components/MoreItems/MoreItems.js +3 -1
  63. package/dist/esm/Components/MultiSelect/MultiSelect.js +2 -2
  64. package/dist/esm/Components/NavigationBar/NavigationBar.js +6 -7
  65. package/dist/esm/Components/NumberInput/NumberInput.styles.js +2 -2
  66. package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +14 -10
  67. package/dist/esm/Components/PdfViewer/PdfViewer.js +4 -4
  68. package/dist/esm/Components/RolesPermission/RolesPermission.js +4 -3
  69. package/dist/esm/Components/SearchSelect/SearchSelect.js +46 -41
  70. package/dist/esm/Components/Select/Select.styles.js +1 -1
  71. package/dist/esm/Components/SelectSearch/SelectSearch.js +35 -17
  72. package/dist/esm/Components/SelectV2/SelectV2.js +3 -0
  73. package/dist/esm/Components/Table/components/TableBody.js +7 -10
  74. package/dist/esm/Components/Table/filters/CompactSelect.js +29 -8
  75. package/dist/esm/Components/Table/settings/ManageColumns.js +5 -3
  76. package/dist/esm/Components/Table/settings/TableSettings.js +5 -3
  77. package/dist/esm/Components/Trail/EditableCell.js +1 -1
  78. package/dist/esm/Components/UserDetails/DeactivateConfirmModal.js +1 -1
  79. package/dist/esm/Components/UserDetails/UserDetails.js +5 -3
  80. package/dist/esm/Hooks/exclusiveOverlay.js +16 -0
  81. package/dist/esm/Hooks/useExclusiveOverlay.js +20 -0
  82. package/dist/esm/Theme/chakra/Menu.styles.js +4 -2
  83. package/dist/esm/Utils/table.js +45 -3
  84. package/package.json +1 -1
@@ -6,7 +6,8 @@ import { TextLabel } from "../Common/FormLabel.js";
6
6
  import Tag from "../Tag/Tag.js";
7
7
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
8
8
  import { placeholderInk } from "../../Theme/tokens/builders/placeholderInk.js";
9
- import { resolveHoverTint } from "../../Theme/tokens/builders/outlineRung.js";
9
+ import { listRowBackgrounds } from "../../Theme/tokens/builders/rowStates.js";
10
+ import { useExclusiveOverlay } from "../../Hooks/useExclusiveOverlay.js";
10
11
  import ErrorMessage from "../Common/ErrorMessage.js";
11
12
  import HelperText from "../Common/HelperText.js";
12
13
  import ToolTip from "../ToolTip/ToolTip.js";
@@ -51,15 +52,11 @@ const SearchSelect = ({ id, label, options, onSelect, onSearch, isOptionLoading
51
52
  width: 0,
52
53
  });
53
54
  const theme = useCustomTheme();
54
- const customSelectActiveTint = useMemo(() => resolveHoverTint(theme.colors.primary[500], theme.colors.background[400]), [theme.colors.primary, theme.colors.background]);
55
- const dropdownActiveTint = useMemo(() => resolveHoverTint(theme.colors.primary[500], theme.colors.background[50]), [theme.colors.primary, theme.colors.background]);
56
- const dropdownHoverTint = useMemo(() => resolveHoverTint(theme.colors.gray[50], theme.colors.background[50]), [theme.colors.gray, theme.colors.background]);
57
- // `searchselect-dropdown-portal` is also the DOM id an existing outside-click check and
58
- // several tests look up directly — kept as a literal constant, not derived from `baseId`,
59
- // so those keep working unchanged.
55
+ const rowBackgrounds = useMemo(() => listRowBackgrounds(theme.colors), [theme.colors]);
60
56
  const generatedId = useId();
61
57
  const baseId = id || generatedId;
62
- const listboxId = "searchselect-dropdown-portal";
58
+ const listboxId = `${baseId}-listbox`;
59
+ const insideSelectPortalId = `${baseId}-inside-select`;
63
60
  const getOptionId = (index) => `${baseId}-option-${index}`;
64
61
  const [activeIndex, setActiveIndex] = useState(-1);
65
62
  const pendingFocusRestoreRef = useRef(false);
@@ -69,12 +66,15 @@ const SearchSelect = ({ id, label, options, onSelect, onSearch, isOptionLoading
69
66
  // just "Input is mounted now": falling back to render-condition guessing there would put
70
67
  // aria-activedescendant on an unfocused Input while the still-focused toggle button gets none.
71
68
  const [focusedTrigger, setFocusedTrigger] = useState(null);
69
+ const closeMenus = useCallback(() => {
70
+ setIsOpen(false);
71
+ setCustomSelectOpen(false);
72
+ }, []);
73
+ const requestExclusiveOpen = useExclusiveOverlay(isOpen || customSelectOpen, closeMenus);
72
74
  useOutsideClick({
73
75
  ref: containerRef,
74
76
  handler: (e) => {
75
- // The options dropdown is portaled to <body>, so a click on it is "outside"
76
- // the container — ignore those so selecting an option doesn't close first.
77
- const dropdown = document.getElementById(listboxId);
77
+ const dropdown = dropdownMenuRef.current;
78
78
  if (dropdown && dropdown.contains(e.target))
79
79
  return;
80
80
  setIsOpen(false);
@@ -181,6 +181,7 @@ const SearchSelect = ({ id, label, options, onSelect, onSearch, isOptionLoading
181
181
  // Opens only — matches SelectV2's convention of a first ArrowDown/Enter/Space that opens with
182
182
  // nothing highlighted yet, and a second keypress that moves onto the first/last option.
183
183
  const openMenu = () => {
184
+ requestExclusiveOpen();
184
185
  setCustomSelectOpen(false);
185
186
  setIsOpen(true);
186
187
  };
@@ -325,7 +326,7 @@ const SearchSelect = ({ id, label, options, onSelect, onSearch, isOptionLoading
325
326
  useOutsideClick({
326
327
  ref: customSelectRef,
327
328
  handler: (e) => {
328
- const dropdown = document.getElementById("custom-select-portal");
329
+ const dropdown = insideSelectMenuRef.current;
329
330
  if (dropdown && dropdown.contains(e.target))
330
331
  return;
331
332
  setCustomSelectOpen(false);
@@ -441,38 +442,39 @@ const SearchSelect = ({ id, label, options, onSelect, onSearch, isOptionLoading
441
442
  ? theme.colors.semanticText.error
442
443
  : focused
443
444
  ? theme.colors.primary[500]
444
- : theme.colors.boxborder[500], borderRadius: "lg", bg: theme.colors.gray[50], boxShadow: focused
445
+ : theme.colors.boxborder[500], borderRadius: "lg", bg: theme.colors.background[50], boxShadow: focused
445
446
  ? error
446
447
  ? `0 0 0 0.125rem ${theme.colors.boxShadow.error}`
447
448
  : `0 0 0 0.125rem ${theme.colors.boxShadow.primary}`
448
449
  : error
449
450
  ? `0 0 0 0.125rem ${theme.colors.boxShadow.error}`
450
- : "none", transition: "box-shadow 0.2s, border-color 0.2s", onKeyDown: handleControlKeyDown, onFocus: () => setFocused(true), onBlur: () => setFocused(false), onClick: () => {
451
- setCustomSelectOpen(false);
452
- setIsOpen(true);
453
- }, children: [insideSelect && (() => {
451
+ : "none", transition: "box-shadow 0.2s, border-color 0.2s", onKeyDown: handleControlKeyDown, onFocus: () => setFocused(true), onBlur: () => setFocused(false), onClick: () => openMenu(), children: [insideSelect && (() => {
454
452
  var _a, _b, _c, _d, _e;
455
453
  const insideLabel = (_a = insideSelect.value) === null || _a === void 0 ? void 0 : _a.label;
456
454
  const insidePlaceholder = (_b = insideSelect.placeholder) !== null && _b !== void 0 ? _b : "Select";
457
455
  return (_jsxs(Box, { position: "relative", ref: customSelectRef, flexShrink: 0, ml: s.insideSelectMarginLeft, h: "-webkit-fill-available", borderRight: "0.063rem solid", borderColor: theme.colors.boxborder[200], bg: customSelectOpen
458
- ? customSelectActiveTint
456
+ ? rowBackgrounds.active
459
457
  : theme.colors.background[400], borderLeftRadius: "md", borderRightRadius: 0, transition: "background 0.15s ease, box-shadow 0.15s ease", boxShadow: customSelectOpen
460
458
  ? `inset 0 0 0 0.063rem ${theme.colors.primary[500]}`
461
459
  : "none", onClick: (e) => {
462
460
  e.stopPropagation();
463
461
  setIsOpen(false);
464
- setCustomSelectOpen((prev) => !prev);
465
- }, children: [_jsxs(Box, { minW: "4.5rem", cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 1, width: insideSelect.width, height: insideSelectBoxHeight, pl: "0.5rem", pr: "0.375rem", children: [insideLabel ? (_jsx(SelectTruncatedLabel, { label: insideLabel, maxWidth: insideSelect.width || "6rem", fontSize: s.fieldFontSize })) : (_jsx(Text, { fontSize: s.fieldFontSize, fontWeight: 500, color: placeholderInk(theme.colors), isTruncated: true, maxW: insideSelect.width || "6rem", children: insidePlaceholder })), _jsx(Box, { as: "span", display: "inline-flex", flexShrink: 0, color: customSelectOpen ? theme.colors.accentText : theme.colors.textMuted, transition: "transform 0.2s ease, color 0.15s ease", transform: customSelectOpen ? "rotate(180deg)" : "rotate(0deg)", children: _jsx(ChevronDown, { size: s.chevronSize }) })] }), customSelectOpen && (_jsx(Portal, { children: _jsx(Box, { ref: setInsideSelectMenuRef, id: "custom-select-portal", position: "fixed", top: `${customSelectPos.top}px`, left: `${customSelectPos.left}px`, zIndex: 1510, bg: theme.colors.background[50], border: "0.063rem solid", borderColor: theme.colors.boxborder[200], borderRadius: "lg", boxShadow: (_d = (_c = theme.shadows) === null || _c === void 0 ? void 0 : _c.md) !== null && _d !== void 0 ? _d : "md", minW: `${customSelectPos.width}px`, maxW: "20rem", py: 1, overflow: "hidden", children: (_e = insideSelect.option) === null || _e === void 0 ? void 0 : _e.map((item) => {
462
+ if (customSelectOpen) {
463
+ setCustomSelectOpen(false);
464
+ }
465
+ else {
466
+ requestExclusiveOpen();
467
+ setCustomSelectOpen(true);
468
+ }
469
+ }, children: [_jsxs(Box, { minW: "4.5rem", cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 1, width: insideSelect.width, height: insideSelectBoxHeight, pl: "0.5rem", pr: "0.375rem", children: [insideLabel ? (_jsx(SelectTruncatedLabel, { label: insideLabel, maxWidth: insideSelect.width || "6rem", fontSize: s.fieldFontSize })) : (_jsx(Text, { fontSize: s.fieldFontSize, fontWeight: 500, color: placeholderInk(theme.colors), isTruncated: true, maxW: insideSelect.width || "6rem", children: insidePlaceholder })), _jsx(Box, { as: "span", display: "inline-flex", flexShrink: 0, color: customSelectOpen ? theme.colors.accentText : theme.colors.textMuted, transition: "transform 0.2s ease, color 0.15s ease", transform: customSelectOpen ? "rotate(180deg)" : "rotate(0deg)", children: _jsx(ChevronDown, { size: s.chevronSize }) })] }), customSelectOpen && (_jsx(Portal, { children: _jsx(Box, { ref: setInsideSelectMenuRef, id: insideSelectPortalId, position: "fixed", top: `${customSelectPos.top}px`, left: `${customSelectPos.left}px`, zIndex: 1510, bg: theme.colors.background[50], border: "0.063rem solid", borderColor: theme.colors.boxborder[200], borderRadius: "lg", boxShadow: (_d = (_c = theme.shadows) === null || _c === void 0 ? void 0 : _c.md) !== null && _d !== void 0 ? _d : "md", minW: `${customSelectPos.width}px`, maxW: "20rem", py: 1, overflow: "hidden", children: (_e = insideSelect.option) === null || _e === void 0 ? void 0 : _e.map((item) => {
466
470
  var _a;
467
471
  const selected = ((_a = insideSelect.value) === null || _a === void 0 ? void 0 : _a.id) === item.id;
468
472
  return (_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, minH: s.optionRowMinH, py: s.optionRowPy, px: "0.75rem", fontSize: s.dropdownTextFontSize, fontWeight: selected ? 600 : 500, color: selected
469
473
  ? theme.colors.accentText
470
- : theme.colors.text[700], bg: selected
471
- ? dropdownActiveTint
472
- : "transparent", _hover: {
474
+ : theme.colors.text[700], bg: selected ? rowBackgrounds.selected : "transparent", _hover: {
473
475
  bg: selected
474
- ? dropdownActiveTint
475
- : dropdownHoverTint,
476
+ ? rowBackgrounds.selectedActive
477
+ : rowBackgrounds.active,
476
478
  }, cursor: "pointer", onClick: (e) => {
477
479
  e.stopPropagation();
478
480
  handleCustomSelect(item);
@@ -485,16 +487,12 @@ const SearchSelect = ({ id, label, options, onSelect, onSearch, isOptionLoading
485
487
  ? item.label.slice(0, chip.maxText) + "…"
486
488
  : item.label, onIconClick: (chip === null || chip === void 0 ? void 0 : chip.onClick) ? () => handleRemove(item === null || item === void 0 ? void 0 : item.id) : undefined, icon: (chip === null || chip === void 0 ? void 0 : chip.onClick) ? CircleX : undefined, colorScheme: "gray", size: s.tagSize }, item.id)))
487
489
  : selectedValues.length === 1 &&
488
- !isOpen && (_jsx(Box, { as: "button", type: "button", ref: triggerButtonRef, id: primaryTarget === "button" ? baseId : undefined, ...comboboxA11yProps("button"), "aria-label": !label ? String((_b = (_a = selectedValues[0]) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : "") : undefined, onFocus: () => setFocusedTrigger("button"), onBlur: () => setFocusedTrigger((prev) => (prev === "button" ? null : prev)), onClick: () => {
489
- setCustomSelectOpen(false);
490
- setIsOpen(true);
491
- }, fontSize: s.fieldFontSize, color: theme.colors.gray[800], background: "transparent", border: "none", cursor: "pointer", p: 0, display: "flex", alignItems: "center", flex: "1", minW: 0, children: _jsx(SelectTruncatedLabel, { label: String(selectedValues[0].label), maxWidth: "calc(100% - 2rem)", fontSize: s.fieldFontSize }) })), (chip === null || chip === void 0 ? void 0 : chip.maxChips) && isMultiple && selectedValues.length > chip.maxChips && (_jsx(Tag, { label: `+ ${selectedValues.length - chip.maxChips}`, colorScheme: "gray", size: s.tagSize }, "extra-count")), (isOpen || inputValue || !selectedValues.length) && (_jsx(Input, { ref: inputRef, id: primaryTarget === "input" ? baseId : undefined, "aria-autocomplete": "list", ...comboboxA11yProps("input"), variant: "unstyled", size: size, h: s.fieldHeight, minH: s.fieldHeight, fontSize: s.fieldFontSize, flex: "1",
490
+ !isOpen && (_jsx(Box, { as: "button", type: "button", ref: triggerButtonRef, id: primaryTarget === "button" ? baseId : undefined, ...comboboxA11yProps("button"), "aria-label": !label ? String((_b = (_a = selectedValues[0]) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : "") : undefined, onFocus: () => setFocusedTrigger("button"), onBlur: () => setFocusedTrigger((prev) => (prev === "button" ? null : prev)), onClick: () => openMenu(), fontSize: s.fieldFontSize, color: theme.colors.gray[800], background: "transparent", border: "none", cursor: "pointer", p: 0, display: "flex", alignItems: "center", flex: "1", minW: 0, children: _jsx(SelectTruncatedLabel, { label: String(selectedValues[0].label), maxWidth: "calc(100% - 2rem)", fontSize: s.fieldFontSize }) })), (chip === null || chip === void 0 ? void 0 : chip.maxChips) && isMultiple && selectedValues.length > chip.maxChips && (_jsx(Tag, { label: `+ ${selectedValues.length - chip.maxChips}`, colorScheme: "gray", size: s.tagSize }, "extra-count")), (isOpen || inputValue || !selectedValues.length) && (_jsx(Input, { ref: inputRef, id: primaryTarget === "input" ? baseId : undefined, "aria-autocomplete": "list", ...comboboxA11yProps("input"), variant: "unstyled", size: size, h: s.fieldHeight, minH: s.fieldHeight, fontSize: s.fieldFontSize, flex: "1",
492
491
  // minW="5rem"
493
492
  minW: "0", value: inputValue, onChange: (e) => setInputValue(e.target.value), onFocus: () => {
494
493
  setFocused(true);
495
494
  setFocusedTrigger("input");
496
- setCustomSelectOpen(false);
497
- setIsOpen(true);
495
+ openMenu();
498
496
  }, onBlur: () => {
499
497
  setFocused(false);
500
498
  setFocusedTrigger((prev) => (prev === "input" ? null : prev));
@@ -506,15 +504,22 @@ const SearchSelect = ({ id, label, options, onSelect, onSearch, isOptionLoading
506
504
  } }) })), isLoading ? (_jsx(Spinner, { size: s.spinnerSize })) : isValidIcon(rightIcon === null || rightIcon === void 0 ? void 0 : rightIcon.icon) ? (_jsx(IconButton, { icon: rightIcon === null || rightIcon === void 0 ? void 0 : rightIcon.icon, "aria-label": "right-icon", variant: "ghost", size: s.iconButtonSize, onClick: rightIcon === null || rightIcon === void 0 ? void 0 : rightIcon.onClick })) : (_jsx(Box, { as: "button", type: "button", ref: toggleButtonRef, id: primaryTarget === "toggle" ? baseId : undefined, ...comboboxA11yProps("toggle"), onFocus: () => setFocusedTrigger("toggle"), onBlur: () => setFocusedTrigger((prev) => (prev === "toggle" ? null : prev)), onClick: (e) => {
507
505
  e.preventDefault();
508
506
  e.stopPropagation();
509
- setIsOpen((prev) => {
510
- if (!prev)
511
- setCustomSelectOpen(false);
512
- return !prev;
513
- });
514
- }, "aria-label": "toggle-dropdown", display: "flex", alignItems: "center", children: isOpen ? (_jsx(ChevronUp, { size: s.chevronSize })) : (_jsx(ChevronDown, { size: s.chevronSize })) }))] })] }) }), isOpen && (_jsx(Portal, { children: _jsxs(Box, { ref: setDropdownMenuRef, id: listboxId, role: "listbox", "aria-multiselectable": isMultiple || undefined, position: "fixed", top: `${dropdownPos.top}px`, left: `${dropdownPos.left}px`, width: `${dropdownPos.width}px`, zIndex: 1500, maxH: "20rem", borderWidth: 1, borderColor: theme.colors.boxborder[200], borderRadius: "sm", bg: theme.colors.background[50], boxShadow: "md", display: "flex", flexDirection: "column", children: [isMultiple && isSelectAll && (_jsxs(Box, { py: s.optionRowPy, px: 3, cursor: "pointer", onClick: handleSelectAll, display: "flex", alignItems: "center", gap: 2, borderBottom: `0.063rem solid ${theme.colors.boxborder[200]}`, children: [_jsx(Checkbox, { isChecked: allFilteredSelected, sx: { pointerEvents: "none" }, size: s.checkboxSize }), _jsx(Text, { fontSize: s.dropdownTextFontSize, children: allFilteredSelected ? "Unselect All" : "Select All" })] })), _jsx(Box, { flex: "1", overflowY: "auto", onScroll: handleScroll, maxH: "15rem", borderBottom: "0.063rem solid", borderColor: theme.colors.boxborder[200], children: isOptionLoading && filteredOptions.length === 0 ? (_jsxs(Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH, children: [_jsx(Spinner, { size: s.spinnerSize }), _jsx(Text, { fontSize: s.dropdownTextFontSize, children: loadingText })] })) : !isOptionLoading && filteredOptions.length === 0 ? (_jsx(Text, { p: 3, fontSize: s.dropdownTextFontSize, color: theme.colors.textMuted, children: "No results found" })) : (_jsxs(_Fragment, { children: [filteredOptions.map((option, index) => (_jsxs(Box, { id: getOptionId(index), role: "option", "aria-selected": isSelected(option.id), py: s.optionRowPy, px: 3, minH: s.optionRowMinH, cursor: "pointer", bg: index === activeIndex
515
- ? dropdownActiveTint
516
- : isSelected(option.id)
517
- ? theme.colors.gray[100]
518
- : "transparent", _hover: { bg: dropdownHoverTint }, onClick: () => handleSelect(option), onMouseEnter: () => setActiveIndex(index), display: "flex", alignItems: "center", gap: 2, borderBottom: `0.063rem solid ${theme.colors.boxborder[200]}`, children: [isMultiple && (_jsx(Checkbox, { isChecked: isSelected(option.id), sx: { pointerEvents: "none" }, size: s.checkboxSize })), option.view ? (_jsx(_Fragment, { children: option.view })) : (_jsx(Text, { fontSize: s.dropdownTextFontSize, children: option.label }))] }, option.id))), ((pagination === null || pagination === void 0 ? void 0 : pagination.scrollLoading) || (isOptionLoading && filteredOptions.length > 0)) && (_jsxs(Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", justifyContent: "center", gap: 2, minH: s.optionRowMinH, children: [_jsx(Spinner, { size: s.spinnerSize }), _jsx(Text, { fontSize: s.dropdownTextFontSize, children: loadingText })] }))] })) }), (addNew === null || addNew === void 0 ? void 0 : addNew.enabled) && (_jsxs(Box, { py: s.optionRowPy, px: 3, borderTop: "0.063rem solid", borderColor: theme.colors.boxborder[200], bg: theme.colors.background[50], display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH, cursor: "pointer", onClick: addNew.onClick, _hover: { bg: dropdownHoverTint }, children: [addNew.icon || _jsx(Plus, { size: s.addNewIconSize }), _jsx(Text, { fontSize: s.dropdownTextFontSize, children: addNew.text || "Add New" })] }))] }) })), helperText && !error && _jsx(HelperText, { helperText: helperText }), error && _jsx(ErrorMessage, { errorMessage: errorMessage })] }));
507
+ if (isOpen) {
508
+ closeMenus();
509
+ }
510
+ else {
511
+ openMenu();
512
+ }
513
+ }, "aria-label": "toggle-dropdown", display: "flex", alignItems: "center", children: isOpen ? (_jsx(ChevronUp, { size: s.chevronSize })) : (_jsx(ChevronDown, { size: s.chevronSize })) }))] })] }) }), isOpen && (_jsx(Portal, { children: _jsxs(Box, { ref: setDropdownMenuRef, id: listboxId, role: "listbox", "aria-multiselectable": isMultiple || undefined, position: "fixed", top: `${dropdownPos.top}px`, left: `${dropdownPos.left}px`, width: `${dropdownPos.width}px`, zIndex: 1500, maxH: "20rem", borderWidth: 1, borderColor: theme.colors.boxborder[200], borderRadius: "sm", bg: theme.colors.background[50], boxShadow: "md", display: "flex", flexDirection: "column", children: [isMultiple && isSelectAll && (_jsxs(Box, { py: s.optionRowPy, px: 3, cursor: "pointer", onClick: handleSelectAll, display: "flex", alignItems: "center", gap: 2, borderBottom: `0.063rem solid ${theme.colors.boxborder[200]}`, children: [_jsx(Checkbox, { isChecked: allFilteredSelected, sx: { pointerEvents: "none" }, size: s.checkboxSize }), _jsx(Text, { fontSize: s.dropdownTextFontSize, children: allFilteredSelected ? "Unselect All" : "Select All" })] })), _jsx(Box, { flex: "1", overflowY: "auto", onScroll: handleScroll, maxH: "15rem", borderBottom: "0.063rem solid", borderColor: theme.colors.boxborder[200], children: isOptionLoading && filteredOptions.length === 0 ? (_jsxs(Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH, children: [_jsx(Spinner, { size: s.spinnerSize }), _jsx(Text, { fontSize: s.dropdownTextFontSize, children: loadingText })] })) : !isOptionLoading && filteredOptions.length === 0 ? (_jsx(Text, { p: 3, fontSize: s.dropdownTextFontSize, color: theme.colors.textMuted, children: "No results found" })) : (_jsxs(_Fragment, { children: [filteredOptions.map((option, index) => (_jsxs(Box, { id: getOptionId(index), role: "option", "aria-selected": isSelected(option.id), py: s.optionRowPy, px: 3, minH: s.optionRowMinH, cursor: "pointer", bg: isSelected(option.id)
514
+ ? index === activeIndex
515
+ ? rowBackgrounds.selectedActive
516
+ : rowBackgrounds.selected
517
+ : index === activeIndex
518
+ ? rowBackgrounds.active
519
+ : "transparent", _hover: {
520
+ bg: isSelected(option.id)
521
+ ? rowBackgrounds.selectedActive
522
+ : rowBackgrounds.active,
523
+ }, onClick: () => handleSelect(option), onMouseEnter: () => setActiveIndex(index), display: "flex", alignItems: "center", gap: 2, borderBottom: `0.063rem solid ${theme.colors.boxborder[200]}`, children: [isMultiple && (_jsx(Checkbox, { isChecked: isSelected(option.id), sx: { pointerEvents: "none" }, size: s.checkboxSize })), option.view ? (_jsx(_Fragment, { children: option.view })) : (_jsx(Text, { fontSize: s.dropdownTextFontSize, children: option.label }))] }, option.id))), ((pagination === null || pagination === void 0 ? void 0 : pagination.scrollLoading) || (isOptionLoading && filteredOptions.length > 0)) && (_jsxs(Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", justifyContent: "center", gap: 2, minH: s.optionRowMinH, children: [_jsx(Spinner, { size: s.spinnerSize }), _jsx(Text, { fontSize: s.dropdownTextFontSize, children: loadingText })] }))] })) }), (addNew === null || addNew === void 0 ? void 0 : addNew.enabled) && (_jsxs(Box, { py: s.optionRowPy, px: 3, borderTop: "0.063rem solid", borderColor: theme.colors.boxborder[200], bg: theme.colors.background[50], display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH, cursor: "pointer", onClick: addNew.onClick, _hover: { bg: rowBackgrounds.active }, children: [addNew.icon || _jsx(Plus, { size: s.addNewIconSize }), _jsx(Text, { fontSize: s.dropdownTextFontSize, children: addNew.text || "Add New" })] }))] }) })), helperText && !error && _jsx(HelperText, { helperText: helperText }), error && _jsx(ErrorMessage, { errorMessage: errorMessage })] }));
519
524
  };
520
525
  export default SearchSelect;
@@ -67,7 +67,7 @@ export const Select = {
67
67
  const primary = theme.colors.primary[500];
68
68
  return {
69
69
  field: {
70
- bg: theme.colors.gray[50],
70
+ bg: theme.colors.background[50],
71
71
  border: "0.063rem solid",
72
72
  borderColor,
73
73
  _hover: {
@@ -4,25 +4,38 @@ import { Box, Input, Spinner, VStack, Text, InputGroup, InputRightElement, HStac
4
4
  import { TextLabel } from "../Common/FormLabel.js";
5
5
  import { FIELD_RADIUS, fieldFocusRing } from "../Common/fieldStyles.js";
6
6
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
7
- import { resolveHoverTint } from "../../Theme/tokens/builders/outlineRung.js";
7
+ import { listRowBackgrounds } from "../../Theme/tokens/builders/rowStates.js";
8
+ import { useExclusiveOverlay } from "../../Hooks/useExclusiveOverlay.js";
8
9
  import { PlusIcon } from "lucide-react";
9
10
  import ErrorMessage from "../Common/ErrorMessage.js";
10
11
  const RenderOptions = ({ isOptionLoading, filteredOptions, loadingText, handleOptionClick, isProfile, isColorOptions, isOptionSelected, activeIndex, optionRefs, }) => {
11
12
  const theme = useCustomTheme();
13
+ const rowBackgrounds = useMemo(() => listRowBackgrounds(theme.colors), [theme.colors]);
12
14
  if (isOptionLoading) {
13
15
  return (_jsxs(VStack, { py: 2, children: [_jsx(Spinner, { size: "sm", color: theme.colors.accentText }), _jsx(Text, { color: theme.colors.accentText, children: loadingText })] }));
14
16
  }
15
17
  if (filteredOptions === null || filteredOptions === void 0 ? void 0 : filteredOptions.length) {
16
- return (_jsx(_Fragment, { children: filteredOptions.map((option, index) => (_jsxs(Box, { as: "button", type: "button", ref: (el) => {
17
- optionRefs.current[index] = el;
18
- }, role: "option", "aria-selected": isOptionSelected(option), tabIndex: index === activeIndex ? 0 : -1, w: "100%", textAlign: "left", border: "none", fontFamily: "inherit", bg: "transparent", px: 4, py: 2, cursor: "pointer", _hover: {
19
- backgroundColor: resolveHoverTint(theme.colors.primary[500], theme.colors.background[50]),
20
- }, onClick: () => handleOptionClick(option), onKeyDown: (e) => {
21
- if (e.key === "Enter" || e.key === " ") {
22
- e.preventDefault();
23
- handleOptionClick(option);
24
- }
25
- }, display: "flex", alignItems: "center", gap: "0.5rem", children: [isProfile && (_jsx(Box, { children: _jsx(Avatar, { size: "sm", name: option.label.toLocaleUpperCase(), src: option.profileUrl ? option.profileUrl : undefined }) })), isColorOptions && (_jsx(Box, { width: "0.8rem", height: "0.8rem", content: "", backgroundColor: option === null || option === void 0 ? void 0 : option.color, borderRadius: "50%" })), _jsxs(Box, { children: [_jsx(Box, { children: option.label }), option.email && (_jsx(Box, { fontSize: 12, color: theme.colors.textMuted, children: option.email }))] })] }, option.id))) }));
18
+ return (_jsx(_Fragment, { children: filteredOptions.map((option, index) => {
19
+ const selected = isOptionSelected(option);
20
+ const isActive = index === activeIndex;
21
+ const rowBg = selected
22
+ ? isActive
23
+ ? rowBackgrounds.selectedActive
24
+ : rowBackgrounds.selected
25
+ : isActive
26
+ ? rowBackgrounds.active
27
+ : "transparent";
28
+ return (_jsxs(Box, { as: "button", type: "button", ref: (el) => {
29
+ optionRefs.current[index] = el;
30
+ }, role: "option", "aria-selected": selected, tabIndex: isActive ? 0 : -1, w: "100%", textAlign: "left", border: "none", fontFamily: "inherit", bg: rowBg, px: 4, py: 2, cursor: "pointer", color: theme.colors.text[700], fontWeight: selected ? 600 : 500, transition: "background 0.12s ease", _hover: {
31
+ bg: selected ? rowBackgrounds.selectedActive : rowBackgrounds.active,
32
+ }, onClick: () => handleOptionClick(option), onKeyDown: (e) => {
33
+ if (e.key === "Enter" || e.key === " ") {
34
+ e.preventDefault();
35
+ handleOptionClick(option);
36
+ }
37
+ }, display: "flex", alignItems: "center", gap: "0.5rem", children: [isProfile && (_jsx(Box, { children: _jsx(Avatar, { size: "sm", name: option.label.toLocaleUpperCase(), src: option.profileUrl ? option.profileUrl : undefined }) })), isColorOptions && (_jsx(Box, { width: "0.8rem", height: "0.8rem", content: "", backgroundColor: option === null || option === void 0 ? void 0 : option.color, borderRadius: "50%" })), _jsxs(Box, { children: [_jsx(Box, { children: option.label }), option.email && (_jsx(Box, { fontSize: 12, color: theme.colors.textMuted, children: option.email }))] })] }, option.id));
38
+ }) }));
26
39
  }
27
40
  return (_jsx(Text, { px: 4, py: 2, color: theme.colors.textMuted, children: "No options found" }));
28
41
  };
@@ -37,6 +50,11 @@ BottomIcon = false, BottomText, handleBottomClick, BottomTextColor, isColorOptio
37
50
  const [selectedOptions, setSelectedOptions] = useState(initialSelectedOption ? [initialSelectedOption] : []);
38
51
  const [inputValue, setInputValue] = useState(searchQuery);
39
52
  const [isOpen, setIsOpen] = useState(false);
53
+ const requestExclusiveOpen = useExclusiveOverlay(isOpen, () => setIsOpen(false));
54
+ const openDropdown = useCallback(() => {
55
+ requestExclusiveOpen();
56
+ setIsOpen(true);
57
+ }, [requestExclusiveOpen]);
40
58
  const [position, setPosition] = useState("below");
41
59
  const inputRef = useRef(null);
42
60
  const dropdownRef = useRef(null);
@@ -188,7 +206,7 @@ BottomIcon = false, BottomText, handleBottomClick, BottomTextColor, isColorOptio
188
206
  handleOptionClick(matchingOption);
189
207
  }
190
208
  else if (!isOpen) {
191
- setIsOpen(true);
209
+ openDropdown();
192
210
  }
193
211
  }
194
212
  else if (e.key === "ArrowDown") {
@@ -197,7 +215,7 @@ BottomIcon = false, BottomText, handleBottomClick, BottomTextColor, isColorOptio
197
215
  e.preventDefault();
198
216
  if (!isOpen) {
199
217
  pendingFocusFirstOption.current = true;
200
- setIsOpen(true);
218
+ openDropdown();
201
219
  }
202
220
  else if (filteredOptions.length > 0) {
203
221
  focusOption(0);
@@ -243,12 +261,12 @@ BottomIcon = false, BottomText, handleBottomClick, BottomTextColor, isColorOptio
243
261
  document.removeEventListener("mousedown", handleClickOutside);
244
262
  };
245
263
  }, [isOpen]);
246
- return (_jsx(_Fragment, { children: _jsx(FormControl, { isInvalid: error, children: _jsxs(Box, { display: "flex", flexDirection: "column", position: "relative", sx: boxStyle, children: [label && (_jsx(TextLabel, { label: label, id: id, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), isMultipleSelect && selectedOptions.length > 0 && (_jsx(HStack, { spacing: 2, mb: 2, children: selectedOptions.map((option) => (_jsxs(Tag, { size: "md", borderRadius: "full", variant: "solid", colorScheme: "primary", children: [_jsx(TagLabel, { width: "50px", children: option.label }), _jsx(TagCloseButton, { onClick: () => handleRemoveOption(option) })] }, option.id))) })), _jsxs(InputGroup, { children: [_jsx(Input, { ref: inputRef, variant: "outline", borderRadius: FIELD_RADIUS, value: inputValue ? inputValue : "", onClick: () => setIsOpen(true), onFocus: () => {
264
+ return (_jsx(_Fragment, { children: _jsx(FormControl, { isInvalid: error, children: _jsxs(Box, { display: "flex", flexDirection: "column", position: "relative", sx: boxStyle, children: [label && (_jsx(TextLabel, { label: label, id: id, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), isMultipleSelect && selectedOptions.length > 0 && (_jsx(HStack, { spacing: 2, mb: 2, children: selectedOptions.map((option) => (_jsxs(Tag, { size: "md", borderRadius: "full", variant: "solid", colorScheme: "primary", children: [_jsx(TagLabel, { width: "50px", children: option.label }), _jsx(TagCloseButton, { onClick: () => handleRemoveOption(option) })] }, option.id))) })), _jsxs(InputGroup, { children: [_jsx(Input, { ref: inputRef, variant: "outline", borderRadius: FIELD_RADIUS, value: inputValue ? inputValue : "", onClick: openDropdown, onFocus: () => {
247
265
  if (skipNextInputFocusOpen.current) {
248
266
  skipNextInputFocusOpen.current = false;
249
267
  return;
250
268
  }
251
- setIsOpen(true);
269
+ openDropdown();
252
270
  }, onChange: (e) => handleInputChange(e.target.value), placeholder: placeholder, onKeyDown: handleKeyDown, id: id, name: name, role: "combobox", "aria-autocomplete": "list", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, cursor: "pointer", borderColor: theme.colors.boxborder[500], transition: "border-color 0.2s, box-shadow 0.2s", _hover: {
253
271
  borderColor: error
254
272
  ? theme.colors.semanticText.error
@@ -260,9 +278,9 @@ BottomIcon = false, BottomText, handleBottomClick, BottomTextColor, isColorOptio
260
278
  boxShadow: fieldFocusRing(theme, !!error),
261
279
  }, style: {
262
280
  ...inputStyle,
263
- backgroundColor: theme.colors.gray[50],
281
+ backgroundColor: theme.colors.background[50],
264
282
  fontWeight: 600,
265
- color: theme.colors.gray[700],
283
+ color: theme.colors.text[700],
266
284
  padding: "0 0.75rem",
267
285
  fontSize: 15,
268
286
  letterSpacing: 0.7,
@@ -7,6 +7,7 @@ import { placeholderInk } from "../../Theme/tokens/builders/placeholderInk.js";
7
7
  import { listRowBackgrounds } from "../../Theme/tokens/builders/rowStates.js";
8
8
  import { scrollbarStyles } from "../../Theme/tokens/builders/scrollbar.js";
9
9
  import { getFieldStateStyles } from "../Common/fieldStyles.js";
10
+ import { useExclusiveOverlay } from "../../Hooks/useExclusiveOverlay.js";
10
11
  import { TextLabel } from "../Common/FormLabel.js";
11
12
  import ErrorMessage from "../Common/ErrorMessage.js";
12
13
  import HelperText from "../Common/HelperText.js";
@@ -35,6 +36,7 @@ export default function SelectV2(props) {
35
36
  const { options = [], placeholder = "Select Option", label, error = false, errorMessage, helperText, isDisabled = false, isRequired = false, size = "md", isSearchable = true, width, formControlStyle, onBlur, onFocus, renderOption, renderValue, maxMenuHeight = "16rem", defaultOpen = false, "data-testid": dataTestId, "aria-label": ariaLabel, } = props;
36
37
  const theme = useCustomTheme();
37
38
  const { isOpen, onOpen, onClose } = useDisclosure({ defaultIsOpen: defaultOpen });
39
+ const requestExclusiveOpen = useExclusiveOverlay(isOpen, onClose);
38
40
  const [filterText, setFilterText] = useState("");
39
41
  const [activeIndex, setActiveIndex] = useState(-1);
40
42
  const triggerRef = useRef(null);
@@ -66,6 +68,7 @@ export default function SelectV2(props) {
66
68
  var _a;
67
69
  if (isDisabled)
68
70
  return;
71
+ requestExclusiveOpen();
69
72
  onFocus === null || onFocus === void 0 ? void 0 : onFocus();
70
73
  onOpen();
71
74
  const firstSelected = props.isMulti ? (_a = props.value) === null || _a === void 0 ? void 0 : _a[0] : props.value;
@@ -3,7 +3,6 @@ import { Box, IconButton, Spinner, Td, Tr } from "@chakra-ui/react";
3
3
  import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { normalizeTableCellValue, buildTablePalette, pickTableColor } from "../../../Utils/table.js";
5
5
  import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
6
- import { onFilled } from "../../../Theme/tokens/builders/accentText.js";
7
6
  import { TableBodyLoading } from "./TableLoading.js";
8
7
  import TableActions from "./TableActions.js";
9
8
  import { ChevronDown, ChevronRight } from "lucide-react";
@@ -99,7 +98,7 @@ const TableRow = React.memo(({ row, rowIndex, isChecked, isExpanded, isContent,
99
98
  const chromeHoverable = rowStyle ? "false" : "true";
100
99
  const rowContent = getRowContent(row);
101
100
  return (_jsxs(React.Fragment, { children: [_jsxs(Tr, { ref: mainRowRef, "aria-rowindex": ariaRowIndex, opacity: isLoading ? 0.4 : 1, pointerEvents: isLoading ? "none" : "auto", transition: "opacity 0.2s", sx: rowSx, children: [isContent && (_jsx(Td, { w: "6", p: 0, fontSize: 14, background: isChecked ? selectedFrozenBg : frozenCellBg, color: freezedTextColor, position: "sticky", borderBottom: borderStyle, boxShadow: leadSx, boxSizing: "border-box", "data-hoverable": chromeHoverable, left: "0px", zIndex: 1, className: "columns sticky-columns", children: !!(row === null || row === void 0 ? void 0 : row.content) && (_jsx(IconButton, { "aria-label": isExpanded ? "Collapse row" : "Expand row", color: theme.colors.textMuted, icon: isExpanded ? (_jsx(ChevronDown, { fontSize: 16 })) : (_jsx(ChevronRight, { fontSize: 16 })), _hover: { transform: "scale(1.1)" }, size: "sm", onClick: () => toggleRowExpansion(rowIndex), variant: "ghost" })) })), isCheckbox && (_jsx(Td, { w: variant.slot.width, minW: variant.slot.width, px: variant.slot.centered ? 0 : undefined, textAlign: variant.slot.centered ? "center" : undefined, fontSize: 14, fontWeight: 600, color: theme.colors.background[50], textTransform: "capitalize", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: "0px", zIndex: 1, className: "columns sticky-columns", children: _jsxs(Box, { display: restsOnIndex ? "grid" : undefined, placeItems: "center", children: [restsOnIndex && (_jsx(Box, { as: "span", className: "table-slot-index", gridArea: "1 / 1", color: variant.slot.indexInk, fontSize: "0.6875rem", fontWeight: 500, transition: "opacity 0.15s ease-in-out", sx: { fontVariantNumeric: "tabular-nums" }, children: rowIndex + 1 })), _jsx(Box, { as: "span", className: restsOnIndex ? "table-slot-box" : undefined, gridArea: restsOnIndex ? "1 / 1" : undefined, display: "flex", alignItems: "center", justifyContent: "center", transition: "opacity 0.15s ease-in-out", children: _jsx(CheckBox, { "aria-label": `Select row ${rowIndex + 1}`, onChange: () => handleCheckbox(getRowId(row)), isChecked: isChecked }) })] }) })), columns.map((header, headerIndex) => {
102
- var _a, _b, _c;
101
+ var _a, _b, _c, _d;
103
102
  if (header.isHidden)
104
103
  return null;
105
104
  const isFrozen = header.isFreeze;
@@ -107,21 +106,19 @@ const TableRow = React.memo(({ row, rowIndex, isChecked, isExpanded, isContent,
107
106
  const isStatus = header.type === "status" && !header.node;
108
107
  const rawStatus = String((_a = row[header.id]) !== null && _a !== void 0 ? _a : "");
109
108
  const statusColor = isStatus
110
- ? pickTableColor(rawStatus, palette, (_b = header.statusColors) === null || _b === void 0 ? void 0 : _b[rawStatus], theme)
109
+ ? (_c = (_b = header.statusPalette) === null || _b === void 0 ? void 0 : _b[rawStatus]) !== null && _c !== void 0 ? _c : pickTableColor(rawStatus, palette, (_d = header.statusColors) === null || _d === void 0 ? void 0 : _d[rawStatus], theme)
111
110
  : null;
112
- // Guards a `statusColor` built by an older external caller that predates `onSolid`.
113
- const statusOnSolid = statusColor
114
- ? (_c = statusColor.onSolid) !== null && _c !== void 0 ? _c : onFilled(statusColor.solid, theme.colors.white, theme.colors.black)
115
- : undefined;
116
111
  const isBleed = variant.cells.statusFill === "bleed" && !!statusColor;
112
+ const bleedBg = statusColor === null || statusColor === void 0 ? void 0 : statusColor.soft;
113
+ const bleedInk = statusColor === null || statusColor === void 0 ? void 0 : statusColor.text;
117
114
  const canHover = !isBleed && !((cellStyles === null || cellStyles === void 0 ? void 0 : cellStyles[header.id]) || rowStyle);
118
- return (_jsx(Td, { maxWidth: 500, minWidth: 120, height: `${rowHeight}px`, py: isBleed ? 0 : cellPy, px: isBleed ? 0 : undefined, onClick: () => handleCellClick(header), fontSize: 14, fontWeight: 400, position: isFrozen ? "sticky" : undefined, left: isFrozen ? leftOffsets[headerIndex] : undefined, zIndex: isFrozen ? 1 : 0, background: isBleed ? statusColor.solid : isChecked ? (isFrozen ? selectedFrozenBg : selectedBg) : isFrozen ? frozenCellBg : theme.colors.background[50], textOverflow: "ellipsis", boxShadow: isFirstDataCell ? leadSx : undefined, borderBottom: noBorders
115
+ return (_jsx(Td, { maxWidth: 500, minWidth: 120, height: `${rowHeight}px`, py: isBleed ? 0 : cellPy, px: isBleed ? 0 : undefined, onClick: () => handleCellClick(header), fontSize: 14, fontWeight: 400, position: isFrozen ? "sticky" : undefined, left: isFrozen ? leftOffsets[headerIndex] : undefined, zIndex: isFrozen ? 1 : 0, background: isBleed ? bleedBg : isChecked ? (isFrozen ? selectedFrozenBg : selectedBg) : isFrozen ? frozenCellBg : theme.colors.background[50], textOverflow: "ellipsis", boxShadow: isFirstDataCell ? leadSx : undefined, borderBottom: noBorders
119
116
  ? "none"
120
117
  : `0.063rem solid ${isFrozen || isChecked
121
118
  ? variant.row.frozenRuleColor
122
- : variant.row.ruleColor}`, className: `columns ${isFrozen ? "sticky-columns" : "scrollable-columns"}`, boxSizing: "border-box", color: isBleed ? statusOnSolid : variant.cells.ink, "data-hoverable": canHover ? "true" : "false", _hover: variant.row.hoverScope === "row" || !canHover
119
+ : variant.row.ruleColor}`, className: `columns ${isFrozen ? "sticky-columns" : "scrollable-columns"}`, boxSizing: "border-box", color: isBleed ? bleedInk : variant.cells.ink, "data-hoverable": canHover ? "true" : "false", _hover: variant.row.hoverScope === "row" || !canHover
123
120
  ? EMPTY_HOVER
124
- : hoverStyle, children: isBleed ? (_jsx(StatusCell, { value: normalizeTableCellValue(row[header.id]), onSolid: statusOnSolid })) : isStatus && statusColor ? (_jsx(StatusPill, { value: normalizeTableCellValue(row[header.id]), soft: statusColor.soft, ink: resolvePillInk(statusColor.text, statusColor.soft, theme.colors.background[50]), radius: variant.cells.pillRadius })) : (_jsx(Box, { display: "block", overflow: "hidden", whiteSpace: "normal", overflowWrap: "break-word", children: normalizeTableCellValue(header.node ? header.node(row) : row[header.id]) })) }, headerIndex + 1));
121
+ : hoverStyle, children: isBleed ? (_jsx(StatusCell, { value: normalizeTableCellValue(row[header.id]), onSolid: bleedInk })) : isStatus && statusColor ? (_jsx(StatusPill, { value: normalizeTableCellValue(row[header.id]), soft: statusColor.soft, ink: resolvePillInk(statusColor.text, statusColor.soft, theme.colors.background[50]), radius: variant.cells.pillRadius })) : (_jsx(Box, { display: "block", overflow: "hidden", whiteSpace: "normal", overflowWrap: "break-word", children: normalizeTableCellValue(header.node ? header.node(row) : row[header.id]) })) }, headerIndex + 1));
125
122
  }), isLink && (_jsx(Td, { w: 2, p: 0, fontSize: 14, background: isChecked ? (isActionFreeze ? selectedFrozenBg : selectedBg) : isActionFreeze ? frozenCellBg : theme.colors.background[50], color: freezedTextColor, position: isActionFreeze ? "sticky" : "relative", borderBottom: borderStyle, boxSizing: "border-box", right: 0, zIndex: 1, className: `columns sticky-columns${isActionFreeze ? "-right" : ""}`, children: (row.onLink || row.onEdit || row.onDelete) ? (_jsx(TableActions, { row: row })) : null }))] }), rowContent && isExpanded && (_jsx(Tr, { ref: expandedRowRef, children: _jsx(Td, { colSpan: columns.length +
126
123
  (isCheckbox ? 1 : 0) +
127
124
  (isContent ? 1 : 0) +
@@ -3,9 +3,17 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
3
  import { Box, Text, Input, Popover, PopoverTrigger, PopoverContent, PopoverBody, VStack, Portal } from "@chakra-ui/react";
4
4
  import { ChevronDown, ChevronUp } from "lucide-react";
5
5
  import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
6
+ import { listRowBackgrounds } from "../../../Theme/tokens/builders/rowStates.js";
7
+ import { useExclusiveOverlay } from "../../../Hooks/useExclusiveOverlay.js";
6
8
  const CompactSelect = ({ options, value, placeholder = "Select", height = "22px", onSelect, size = "xs" }) => {
7
9
  const theme = useCustomTheme();
10
+ const rowBackgrounds = useMemo(() => listRowBackgrounds(theme.colors), [theme.colors]);
8
11
  const [isOpen, setIsOpen] = useState(false);
12
+ const requestExclusiveOpen = useExclusiveOverlay(isOpen, () => setIsOpen(false));
13
+ const openDropdown = () => {
14
+ requestExclusiveOpen();
15
+ setIsOpen(true);
16
+ };
9
17
  const [query, setQuery] = useState("");
10
18
  const filtered = useMemo(() => {
11
19
  const q = query.trim().toLowerCase();
@@ -38,17 +46,30 @@ const CompactSelect = ({ options, value, placeholder = "Select", height = "22px"
38
46
  focusOption(filtered.length - 1);
39
47
  }
40
48
  }, [activeIndex, filtered.length, focusOption]);
41
- return (_jsxs(Popover, { isOpen: isOpen, onClose: () => setIsOpen(false), placement: "bottom-start", children: [_jsx(PopoverTrigger, { children: _jsxs(Box, { as: "button", type: "button", w: "100%", h: typeof height === "number" ? `${height}px` : height, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, px: 2, border: "0.063rem solid", borderColor: theme.colors.boxborder[500], bg: theme.colors.background[50], borderRadius: "base", onClick: () => setIsOpen((prev) => !prev), children: [_jsx(Text, { fontSize: size === "xs" ? "0.75rem" : "0.875rem", color: theme.colors.text[500], noOfLines: 1, textAlign: "left", children: (value === null || value === void 0 ? void 0 : value.label) || placeholder }), isOpen ? _jsx(ChevronUp, { size: 12 }) : _jsx(ChevronDown, { size: 12 })] }) }), _jsx(Portal, { children: _jsx(PopoverContent, { w: "100%", maxW: "14rem", p: 0, zIndex: 1600, bg: theme.colors.background[50], children: _jsx(PopoverBody, { p: 2, children: _jsxs(VStack, { spacing: 2, align: "stretch", children: [_jsx(Input, { size: size, placeholder: "Search", value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: (e) => {
49
+ return (_jsxs(Popover, { isOpen: isOpen, onClose: () => setIsOpen(false), placement: "bottom-start", children: [_jsx(PopoverTrigger, { children: _jsxs(Box, { as: "button", type: "button", w: "100%", h: typeof height === "number" ? `${height}px` : height, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, px: 2, border: "0.063rem solid", borderColor: theme.colors.boxborder[500], bg: theme.colors.background[50], borderRadius: "base", onClick: () => (isOpen ? setIsOpen(false) : openDropdown()), children: [_jsx(Text, { fontSize: size === "xs" ? "0.75rem" : "0.875rem", color: theme.colors.text[500], noOfLines: 1, textAlign: "left", children: (value === null || value === void 0 ? void 0 : value.label) || placeholder }), isOpen ? _jsx(ChevronUp, { size: 12 }) : _jsx(ChevronDown, { size: 12 })] }) }), _jsx(Portal, { children: _jsx(PopoverContent, { w: "100%", maxW: "14rem", p: 0, zIndex: 1600, bg: theme.colors.background[50], children: _jsx(PopoverBody, { p: 2, children: _jsxs(VStack, { spacing: 2, align: "stretch", children: [_jsx(Input, { size: size, placeholder: "Search", value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: (e) => {
42
50
  if (e.key === "ArrowDown" && filtered.length > 0) {
43
51
  e.preventDefault();
44
52
  focusOption(0);
45
53
  }
46
- }, sx: { fontSize: "0.75rem", height: "22px" } }), _jsxs(Box, { role: "listbox", "aria-label": placeholder, maxH: "12rem", overflowY: "auto", borderTop: "1px solid", borderColor: theme.colors.boxborder[200], onKeyDown: handleListKeyDown, children: [filtered.map((opt, i) => (_jsx(Box, { as: "button", type: "button", role: "option", "aria-selected": (value === null || value === void 0 ? void 0 : value.id) === opt.id, tabIndex: i === activeIndex ? 0 : -1, ref: (el) => {
47
- optionRefs.current[i] = el;
48
- }, w: "100%", textAlign: "left", border: "none", fontFamily: "inherit", px: 2, py: 1, cursor: "pointer", _hover: { bg: theme.colors.background[100] }, bg: (value === null || value === void 0 ? void 0 : value.id) === opt.id ? theme.colors.background[200] : theme.colors.transparent, onClick: () => {
49
- onSelect === null || onSelect === void 0 ? void 0 : onSelect(opt);
50
- setIsOpen(false);
51
- setQuery("");
52
- }, children: _jsx(Text, { fontSize: "0.75rem", children: opt.label }) }, opt.id))), filtered.length === 0 && (_jsx(Box, { px: 2, py: 2, children: _jsx(Text, { fontSize: "0.75rem", color: theme.colors.textMuted, children: "No results" }) }))] })] }) }) }) })] }));
54
+ }, sx: { fontSize: "0.75rem", height: "22px" } }), _jsxs(Box, { role: "listbox", "aria-label": placeholder, maxH: "12rem", overflowY: "auto", borderTop: "1px solid", borderColor: theme.colors.boxborder[200], onKeyDown: handleListKeyDown, children: [filtered.map((opt, i) => {
55
+ const selected = (value === null || value === void 0 ? void 0 : value.id) === opt.id;
56
+ const isActive = i === activeIndex;
57
+ const rowBg = selected
58
+ ? isActive
59
+ ? rowBackgrounds.selectedActive
60
+ : rowBackgrounds.selected
61
+ : isActive
62
+ ? rowBackgrounds.active
63
+ : theme.colors.transparent;
64
+ return (_jsx(Box, { as: "button", type: "button", role: "option", "aria-selected": selected, tabIndex: isActive ? 0 : -1, ref: (el) => {
65
+ optionRefs.current[i] = el;
66
+ }, w: "100%", textAlign: "left", border: "none", fontFamily: "inherit", px: 2, py: 1, cursor: "pointer", color: theme.colors.text[700], _hover: {
67
+ bg: selected ? rowBackgrounds.selectedActive : rowBackgrounds.active,
68
+ }, bg: rowBg, onClick: () => {
69
+ onSelect === null || onSelect === void 0 ? void 0 : onSelect(opt);
70
+ setIsOpen(false);
71
+ setQuery("");
72
+ }, children: _jsx(Text, { fontSize: "0.75rem", children: opt.label }) }, opt.id));
73
+ }), filtered.length === 0 && (_jsx(Box, { px: 2, py: 2, children: _jsx(Text, { fontSize: "0.75rem", color: theme.colors.textMuted, children: "No results" }) }))] })] }) }) }) })] }));
53
74
  };
54
75
  export default CompactSelect;
@@ -5,9 +5,11 @@ import Checkbox from "../../Checkbox/Checkbox.js";
5
5
  import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
6
6
  import { scrollbarStyles } from "../../../Theme/tokens/builders/scrollbar.js";
7
7
  import { accentTextOnCanvas } from "../../../Theme/tokens/builders/accentText.js";
8
+ import { listRowBackgrounds } from "../../../Theme/tokens/builders/rowStates.js";
8
9
  import { ChevronDown, ChevronUp, GripVertical } from "lucide-react";
9
10
  const ManageColumns = ({ columns, items, setItems, childInputMethodsRef, }) => {
10
11
  const theme = useCustomTheme();
12
+ const rowBackgrounds = useMemo(() => listRowBackgrounds(theme.colors), [theme.colors]);
11
13
  const [searchTerm, setSearchTerm] = useState("");
12
14
  const [draggedItemIndex, setDraggedItemIndex] = useState(null);
13
15
  const [error, setError] = useState(null);
@@ -78,14 +80,14 @@ const ManageColumns = ({ columns, items, setItems, childInputMethodsRef, }) => {
78
80
  return (_jsxs(ListItem, { draggable: true, onDragStart: () => handleDragStart(index), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, bg: isDraggingThisItem
79
81
  ? theme.colors.primary[100]
80
82
  : isDropZone
81
- ? theme.colors.primary[50]
83
+ ? rowBackgrounds.selected
82
84
  : "transparent", display: "flex", alignItems: "center", borderRadius: "sm", border: "1px solid", borderColor: isDraggingThisItem
83
85
  ? theme.colors.primary[400]
84
86
  : "transparent", cursor: "grab", fontSize: "13px", px: 2, py: "3px", mb: "3px", transition: "all 0.15s ease", _hover: {
85
- bg: theme.colors.gray[50],
87
+ bg: rowBackgrounds.active,
86
88
  borderColor: theme.colors.boxborder[200],
87
89
  }, _active: { cursor: "grabbing" }, children: [_jsx(Box, { as: "span", "aria-hidden": "true", display: "inline-flex", cursor: "grab", mr: 1, _hover: { color: theme.colors.gray[500] }, children: _jsx(GripVertical, { size: 14 }) }), _jsx(Checkbox, { isChecked: !item.isHidden, label: String(item.label), onChange: () => toggleCheckbox(item.id), size: "sm", labelSx: {
88
- color: item.isHidden ? theme.colors.gray[500] : theme.colors.gray[700],
90
+ color: item.isHidden ? theme.colors.textMuted : theme.colors.text[700],
89
91
  } }), _jsx(Text, { fontSize: "12px", color: theme.colors.gray[500], ml: 'auto', children: index + 1 }), _jsx(IconButton, { "aria-label": `Move ${item.label} up`, icon: _jsx(ChevronUp, { size: 14 }), variant: "ghost", size: "xs", ml: 1, minW: "auto", h: "auto", p: 0, color: theme.colors.gray[500], isDisabled: realIndex <= 0, onClick: () => moveItem(item.id, -1) }), _jsx(IconButton, { "aria-label": `Move ${item.label} down`, icon: _jsx(ChevronDown, { size: 14 }), variant: "ghost", size: "xs", ml: 1, minW: "auto", h: "auto", p: 0, color: theme.colors.gray[500], isDisabled: realIndex === -1 || realIndex >= items.length - 1, onClick: () => moveItem(item.id, 1) })] }, item.id));
90
92
  })) : (_jsx(Text, { color: theme.colors.textMuted, textAlign: "center", fontSize: "sm", py: 6, children: "No columns found" })) }), _jsxs(Text, { fontSize: "xs", color: theme.colors.gray[500], mt: 2, textAlign: "right", children: [visibleCount, " / ", items.length, " visible"] })] }));
91
93
  };
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Flex, IconButton, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalOverlay, Tabs, TabList, TabPanels, Tab, TabPanel, Text, } from "@chakra-ui/react";
3
- import { useCallback, useRef, useState } from "react";
3
+ import { useCallback, useMemo, useRef, useState } from "react";
4
4
  import { motion } from "framer-motion";
5
5
  import ManageColumns from "./ManageColumns.js";
6
6
  import Button from "../../Button/Button.js";
@@ -8,6 +8,7 @@ import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
8
8
  import { scrollbarStyles } from "../../../Theme/tokens/builders/scrollbar.js";
9
9
  import { Settings, Check } from "lucide-react";
10
10
  import ToolTip from "../../ToolTip/ToolTip.js";
11
+ import { listRowBackgrounds } from "../../../Theme/tokens/builders/rowStates.js";
11
12
  const MotionModalContent = motion(ModalContent);
12
13
  const DENSITY_OPTIONS = [
13
14
  { value: "compact", label: "Compact", desc: "Tight rows — fit more data on screen" },
@@ -16,6 +17,7 @@ const DENSITY_OPTIONS = [
16
17
  ];
17
18
  const TableSettings = ({ columns, onSave, density = "normal", onDensityChange, groupBy, }) => {
18
19
  const theme = useCustomTheme();
20
+ const rowBackgrounds = useMemo(() => listRowBackgrounds(theme.colors), [theme.colors]);
19
21
  const childInputMethodsRef = useRef({});
20
22
  const [settingsOpen, setSettingsOpen] = useState(false);
21
23
  const [selectedIndex, setSelectedIndex] = useState(0);
@@ -50,7 +52,7 @@ const TableSettings = ({ columns, onSave, density = "normal", onDensityChange, g
50
52
  color: theme.colors.accentText
51
53
  } }) }), _jsxs(Modal, { isOpen: settingsOpen, onClose: () => setSettingsOpen(false), size: "md", children: [_jsx(ModalOverlay, {}), _jsxs(MotionModalContent, { mt: "0", top: "0", position: "absolute", borderTopRadius: "none", initial: { y: "-100%", opacity: 0 }, animate: { y: 0, opacity: 1 }, exit: { y: "-100%", opacity: 0 }, transition: { duration: 0.4, ease: "easeOut" }, padding: "0", minW: "620px", minH: "520px", maxH: "90vh", display: "flex", flexDirection: "column", bg: theme.colors.background[50], overflow: "hidden", children: [_jsx(ModalCloseButton, { top: 3, right: 3, zIndex: 2 }), _jsxs(Tabs, { index: selectedIndex, onChange: setSelectedIndex, variant: "unstyled", display: "flex", flexDirection: "column", flex: "1", minH: 0, children: [_jsxs(Box, { pt: 4, px: 4, children: [_jsx(Text, { fontWeight: 600, fontSize: "md", mb: 3, children: "Table Settings" }), _jsxs(TabList, { gap: 0, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: [_jsx(Tab, { ...tabStyle, children: "Density" }), _jsx(Tab, { ...tabStyle, children: "Manage Columns" }), _jsx(Tab, { ...tabStyle, children: "Group" })] })] }), _jsx(ModalBody, { px: 4, py: 3, flex: "1", overflowY: "auto", sx: scrollbarStyles(theme.colors), children: _jsxs(TabPanels, { children: [_jsx(TabPanel, { px: 0, py: 1, children: _jsx(Flex, { direction: "column", gap: 2, children: DENSITY_OPTIONS.map((opt) => {
52
54
  const selected = density === opt.value;
53
- return (_jsxs(Flex, { as: "button", type: "button", align: "center", gap: 3, px: 3, py: 2.5, borderRadius: "lg", border: "1px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[200], bg: selected ? theme.colors.primary.opacity[8] : theme.colors.transparent, transition: "all 0.15s", _hover: { borderColor: theme.colors.accentText }, onClick: () => onDensityChange === null || onDensityChange === void 0 ? void 0 : onDensityChange(opt.value), children: [_jsx(Box, { boxSize: "1.1rem", borderRadius: "full", border: "2px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[500], display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: selected && _jsx(Check, { size: 11, color: theme.colors.accentText, strokeWidth: 3 }) }), _jsxs(Box, { textAlign: "left", children: [_jsx(Text, { fontSize: "13px", fontWeight: 600, color: theme.colors.text[700], children: opt.label }), _jsx(Text, { fontSize: "11px", color: theme.colors.textMuted, children: opt.desc })] })] }, opt.value));
55
+ return (_jsxs(Flex, { as: "button", type: "button", align: "center", gap: 3, px: 3, py: 2.5, borderRadius: "lg", border: "1px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[200], bg: selected ? rowBackgrounds.selected : theme.colors.transparent, transition: "all 0.15s", _hover: { borderColor: theme.colors.accentText }, onClick: () => onDensityChange === null || onDensityChange === void 0 ? void 0 : onDensityChange(opt.value), children: [_jsx(Box, { boxSize: "1.1rem", borderRadius: "full", border: "2px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[500], display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: selected && _jsx(Check, { size: 11, color: theme.colors.accentText, strokeWidth: 3 }) }), _jsxs(Box, { textAlign: "left", children: [_jsx(Text, { fontSize: "13px", fontWeight: 600, color: theme.colors.text[700], children: opt.label }), _jsx(Text, { fontSize: "11px", color: theme.colors.textMuted, children: opt.desc })] })] }, opt.value));
54
56
  }) }) }), _jsx(TabPanel, { px: 0, py: 0, children: _jsx(Box, { sx: {
55
57
  "& [role='listitem'], & > div > div": {
56
58
  py: "4px !important",
@@ -68,7 +70,7 @@ const TableSettings = ({ columns, onSave, density = "normal", onDensityChange, g
68
70
  .map((opt) => {
69
71
  var _a;
70
72
  const selected = selectedGroup === opt.id;
71
- return (_jsxs(Flex, { as: "button", type: "button", align: "center", gap: 3, px: 3, py: 2.5, borderRadius: "lg", border: "1px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[200], bg: selected ? theme.colors.primary.opacity[8] : theme.colors.transparent, transition: "all 0.15s", _hover: { borderColor: theme.colors.accentText }, onClick: () => setSelectedGroup(opt.id), children: [_jsx(Box, { boxSize: "1.1rem", borderRadius: "full", border: "2px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[500], display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: selected && _jsx(Check, { size: 11, color: theme.colors.accentText, strokeWidth: 3 }) }), _jsx(Text, { fontSize: "13px", fontWeight: 600, color: theme.colors.text[700], textAlign: "left", children: opt.label })] }, String((_a = opt.id) !== null && _a !== void 0 ? _a : "__none__")));
73
+ return (_jsxs(Flex, { as: "button", type: "button", align: "center", gap: 3, px: 3, py: 2.5, borderRadius: "lg", border: "1px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[200], bg: selected ? rowBackgrounds.selected : theme.colors.transparent, transition: "all 0.15s", _hover: { borderColor: theme.colors.accentText }, onClick: () => setSelectedGroup(opt.id), children: [_jsx(Box, { boxSize: "1.1rem", borderRadius: "full", border: "2px solid", borderColor: selected ? theme.colors.accentText : theme.colors.boxborder[500], display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: selected && _jsx(Check, { size: 11, color: theme.colors.accentText, strokeWidth: 3 }) }), _jsx(Text, { fontSize: "13px", fontWeight: 600, color: theme.colors.text[700], textAlign: "left", children: opt.label })] }, String((_a = opt.id) !== null && _a !== void 0 ? _a : "__none__")));
72
74
  }) })] })] }) })] }), _jsxs(ModalFooter, { gap: "0.5rem", borderTop: "1px solid", borderColor: theme.colors.boxborder[200], pt: 3, pb: 3, px: 4, children: [_jsx(Button, { label: "Close", size: "sm", onClick: () => setSettingsOpen(false), variant: "outline", colorScheme: "red" }), _jsx(Button, { label: "Save", size: "sm", onClick: handleSave })] })] })] })] }));
73
75
  };
74
76
  export default TableSettings;
@@ -20,7 +20,7 @@ export const EditableCell = ({ row, column, isEditable, handleCellClick, handleC
20
20
  return (_jsx(Box, { width: "50%", ref: cellRef, children: _jsx(Input, { type: "date", value: value, onChange: (e) => handleCellChange(row.id, column.label, e.target.value) }) }));
21
21
  }
22
22
  else if (column.label === "priority") {
23
- return (_jsx(Box, { width: "100%", ref: cellRef, children: _jsxs(Menu, { isOpen: true, children: [_jsx(MenuButton, { as: Button, rightIcon: _jsx(ChevronDown, {}), bg: colors.teal[50], color: accentTextOnCanvas(colors.teal, colors.teal[50]), _hover: { bg: colors.teal[100] }, _active: { bg: colors.teal[200] }, children: value }), _jsxs(MenuList, { children: [_jsx(MenuItem, { onClick: () => handleCellChange(row.id, column.label, "Low"), _hover: { bg: colors.teal[100] }, children: "Low" }), _jsx(MenuItem, { onClick: () => handleCellChange(row.id, column.label, "Medium"), _hover: { bg: colors.teal[100] }, children: "Medium" }), _jsx(MenuItem, { onClick: () => handleCellChange(row.id, column.label, "High"), _hover: { bg: colors.teal[100] }, children: "High" })] })] }) }));
23
+ return (_jsx(Box, { width: "100%", ref: cellRef, children: _jsxs(Menu, { isOpen: true, children: [_jsx(MenuButton, { as: Button, rightIcon: _jsx(ChevronDown, {}), bg: colors.teal[50], color: accentTextOnCanvas(colors.teal, colors.teal[50]), _hover: { bg: colors.teal[100] }, _active: { bg: colors.teal[200] }, children: value }), _jsxs(MenuList, { children: [_jsx(MenuItem, { onClick: () => handleCellChange(row.id, column.label, "Low"), children: "Low" }), _jsx(MenuItem, { onClick: () => handleCellChange(row.id, column.label, "Medium"), children: "Medium" }), _jsx(MenuItem, { onClick: () => handleCellChange(row.id, column.label, "High"), children: "High" })] })] }) }));
24
24
  }
25
25
  else {
26
26
  return (_jsx(Box, { width: "100%", ref: cellRef, children: _jsx(Input, { value: value, onChange: (e) => handleCellChange(row.id, column.label, e.target.value) }) }));
@@ -9,6 +9,6 @@ const DeactivateConfirmModal = ({ isOpen, onClose, userName, isLoading, onConfir
9
9
  const { colors } = useCustomTheme();
10
10
  const mode = isDarkCanvas(colors.backgroundColor.main) ? "dark" : "light";
11
11
  const errorTone = resolveStatusTone(colors.semantic.error, mode);
12
- return (_jsxs(Modal, { isOpen: isOpen, onClose: onClose, isCentered: true, children: [_jsx(ModalOverlay, { backdropFilter: "blur(4px)" }), _jsxs(ModalContent, { bg: colors.background[50], borderRadius: "2xl", overflow: "hidden", children: [_jsxs(ModalHeader, { borderBottom: "1px solid", borderColor: colors.boxborder[200], display: "flex", alignItems: "center", gap: 3, children: [_jsx(Flex, { align: "center", justify: "center", boxSize: "36px", borderRadius: "full", bg: errorTone.bg, color: errorTone.fg, children: _jsx(AlertTriangle, { size: 18 }) }), _jsx(Text, { fontSize: "1.05rem", fontWeight: 600, children: labels.confirmDeactivation })] }), _jsx(ModalCloseButton, {}), _jsx(ModalBody, { py: 6, children: _jsxs(VStack, { spacing: 4, align: "stretch", children: [_jsx(Text, { fontSize: "md", fontWeight: 500, color: colors.text[900], children: labels.deactivateConfirmQuestion }), _jsx(Box, { bg: colors.gray[50], borderRadius: "lg", p: 4, border: "1px solid", borderColor: colors.boxborder[200], children: _jsxs(Text, { color: colors.textMuted, fontSize: "sm", children: [userName ? `${userName} ` : "", labels.deactivateConfirmDescription] }) }), _jsxs(HStack, { justifyContent: "flex-end", spacing: 3, pt: 2, children: [_jsx(Button, { label: labels.cancel, onClick: onClose, variant: "outline", size: "sm", colorScheme: "gray" }), _jsx(Button, { label: labels.deactivateUser, onClick: onConfirm, colorScheme: "red", size: "sm", isLoading: isLoading, leftIcon: _jsx(Trash2, { size: 16 }) })] })] }) })] })] }));
12
+ return (_jsxs(Modal, { isOpen: isOpen, onClose: onClose, isCentered: true, children: [_jsx(ModalOverlay, { backdropFilter: "blur(4px)" }), _jsxs(ModalContent, { bg: colors.background[50], borderRadius: "2xl", overflow: "hidden", children: [_jsxs(ModalHeader, { borderBottom: "1px solid", borderColor: colors.boxborder[200], display: "flex", alignItems: "center", gap: 3, children: [_jsx(Flex, { align: "center", justify: "center", boxSize: "36px", borderRadius: "full", bg: errorTone.bg, color: errorTone.fg, children: _jsx(AlertTriangle, { size: 18 }) }), _jsx(Text, { fontSize: "1.05rem", fontWeight: 600, children: labels.confirmDeactivation })] }), _jsx(ModalCloseButton, {}), _jsx(ModalBody, { py: 6, children: _jsxs(VStack, { spacing: 4, align: "stretch", children: [_jsx(Text, { fontSize: "md", fontWeight: 500, color: colors.text[900], children: labels.deactivateConfirmQuestion }), _jsx(Box, { bg: colors.background[50], borderRadius: "lg", p: 4, border: "1px solid", borderColor: colors.boxborder[200], children: _jsxs(Text, { color: colors.textMuted, fontSize: "sm", children: [userName ? `${userName} ` : "", labels.deactivateConfirmDescription] }) }), _jsxs(HStack, { justifyContent: "flex-end", spacing: 3, pt: 2, children: [_jsx(Button, { label: labels.cancel, onClick: onClose, variant: "outline", size: "sm", colorScheme: "gray" }), _jsx(Button, { label: labels.deactivateUser, onClick: onConfirm, colorScheme: "red", size: "sm", isLoading: isLoading, leftIcon: _jsx(Trash2, { size: 16 }) })] })] }) })] })] }));
13
13
  };
14
14
  export default DeactivateConfirmModal;