pixelize-design-library 2.4.2-beta.63 → 2.4.2-beta.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/COMPONENT-GOTCHAS.md +26 -3
  3. package/DESIGN-GUIDE.md +1 -0
  4. package/dist/Components/Button/Button.styles.js +7 -2
  5. package/dist/Components/Dropdown/DropDown.js +2 -9
  6. package/dist/Components/FilePreview/FilePreview.js +2 -1
  7. package/dist/Components/FileUploader/FileUploader.js +4 -0
  8. package/dist/Components/FileUploader/FileUploaderProps.d.ts +1 -1
  9. package/dist/Components/Input/TextInput.styles.js +10 -6
  10. package/dist/Components/KanbanBoard/KanbanBoard.js +6 -5
  11. package/dist/Components/NavigationBar/NavigationBar.js +2 -1
  12. package/dist/Components/OrgSwitcher/OrgSwitcher.js +2 -4
  13. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +6 -5
  14. package/dist/Components/ScrollToTop/ScrollToTop.js +4 -3
  15. package/dist/Components/SearchSelect/SearchSelect.js +4 -16
  16. package/dist/Components/Select/SelectPopup.js +1 -3
  17. package/dist/Components/Select/optionRowInk.d.ts +12 -0
  18. package/dist/Components/Select/optionRowInk.js +10 -1
  19. package/dist/Components/SelectSearch/SelectSearch.js +1 -10
  20. package/dist/Components/Table/Table.js +3 -2
  21. package/dist/Components/Table/TableProps.d.ts +1 -1
  22. package/dist/Components/Table/components/TableBody.js +9 -1
  23. package/dist/Components/Table/components/TableHeader.js +7 -2
  24. package/dist/Components/Table/components/TableLoading.d.ts +4 -1
  25. package/dist/Components/Table/components/TableLoading.js +6 -5
  26. package/dist/Components/Table/filters/CompactSelect.js +1 -10
  27. package/dist/Components/Table/variants/TableVariantContext.d.ts +1 -1
  28. package/dist/Components/Table/variants/TableVariantContext.js +3 -3
  29. package/dist/Components/WorkspaceWindow/WorkspaceTrayPreview.js +4 -0
  30. package/dist/Components/WorkspaceWindow/WorkspaceWindow.d.ts +2 -2
  31. package/dist/Components/WorkspaceWindow/WorkspaceWindow.js +25 -18
  32. package/dist/Components/WorkspaceWindow/WorkspaceWindowProps.d.ts +38 -2
  33. package/dist/Theme/chakra/Menu.styles.d.ts +8 -0
  34. package/dist/Theme/chakra/Menu.styles.js +7 -0
  35. package/dist/Theme/chakra/componentStyles.d.ts +8 -0
  36. package/dist/Theme/chakra/componentStyles.js +2 -2
  37. package/dist/Theme/tokens/builders/accentText.d.ts +2 -0
  38. package/dist/Theme/tokens/builders/accentText.js +7 -1
  39. package/dist/Theme/tokens/builders/filledSurface.d.ts +5 -1
  40. package/dist/Theme/tokens/builders/filledSurface.js +17 -4
  41. package/dist/Theme/tokens/builders/planeStep.d.ts +1 -0
  42. package/dist/Theme/tokens/builders/planeStep.js +5 -4
  43. package/dist/Utils/table.js +2 -2
  44. package/dist/esm/Components/Button/Button.styles.js +8 -3
  45. package/dist/esm/Components/Dropdown/DropDown.js +2 -9
  46. package/dist/esm/Components/FilePreview/FilePreview.js +3 -2
  47. package/dist/esm/Components/FileUploader/FileUploader.js +4 -0
  48. package/dist/esm/Components/Input/TextInput.styles.js +10 -6
  49. package/dist/esm/Components/KanbanBoard/KanbanBoard.js +6 -5
  50. package/dist/esm/Components/NavigationBar/NavigationBar.js +2 -1
  51. package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +2 -4
  52. package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +7 -6
  53. package/dist/esm/Components/ScrollToTop/ScrollToTop.js +5 -4
  54. package/dist/esm/Components/SearchSelect/SearchSelect.js +6 -18
  55. package/dist/esm/Components/Select/SelectPopup.js +2 -4
  56. package/dist/esm/Components/Select/optionRowInk.js +7 -0
  57. package/dist/esm/Components/SelectSearch/SelectSearch.js +2 -11
  58. package/dist/esm/Components/Table/Table.js +4 -3
  59. package/dist/esm/Components/Table/components/TableBody.js +10 -2
  60. package/dist/esm/Components/Table/components/TableHeader.js +9 -4
  61. package/dist/esm/Components/Table/components/TableLoading.js +5 -4
  62. package/dist/esm/Components/Table/filters/CompactSelect.js +2 -11
  63. package/dist/esm/Components/Table/variants/TableVariantContext.js +3 -3
  64. package/dist/esm/Components/WorkspaceWindow/WorkspaceTrayPreview.js +4 -0
  65. package/dist/esm/Components/WorkspaceWindow/WorkspaceWindow.js +26 -19
  66. package/dist/esm/Theme/chakra/Menu.styles.js +7 -0
  67. package/dist/esm/Theme/chakra/componentStyles.js +2 -2
  68. package/dist/esm/Theme/tokens/builders/accentText.js +5 -0
  69. package/dist/esm/Theme/tokens/builders/filledSurface.js +18 -5
  70. package/dist/esm/Theme/tokens/builders/planeStep.js +3 -3
  71. package/dist/esm/Utils/table.js +2 -2
  72. package/dist/esm/index.js +4 -4
  73. package/dist/index.d.ts +5 -5
  74. package/dist/index.js +11 -6
  75. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -18,6 +18,18 @@ next major.
18
18
 
19
19
  ### Added
20
20
 
21
+ - **`WorkspaceTray` is usable over an open modal.** It is portalled above the modal layer, labelled as a live region
22
+ (so Chakra's modal aria-hidden skips it) and outside the focus trap, so a window minimised over a wizard can be
23
+ restored without closing the wizard. New props: `placement` (`"bottom-end"` | `"bottom-start"`), `offset`,
24
+ `closeLabel(item)`, `dirtyLabel`, `label`; `WorkspaceTrayItem` gains `isDirty` (unsaved dot) and `subtitle`.
25
+ `WorkspaceWindow` gains `labels` ({minimize, close, openFullPage}) and `finalFocusRef`.
26
+ The tray now renders in a portal, so a test that queries inside its render container must query `document.body`.
27
+ - **`optionRowFill(rows, isActive)`** and **`optionRowCursorSx(rows)`** are exported from the package root: the one
28
+ fill an option row paints (the cursor's), and its `:hover`/`:focus` form for roving-focus lists.
29
+ - **`accentTextOnPlanes(scale, planes)`** is exported from the package root: the first accent rung clearing AA on every
30
+ plane in the list, for chrome that can land on the canvas, a card or an overlay.
31
+ - **`ruleOn(colors, plane)`** and **`MOTION_PRESS_SCALE`** are exported from the package root. `ruleOn` draws a divider at the
32
+ in-card weight on any plane (`cardRule` is `ruleOn` on `background[50]`); the press scale was only reachable by deep import.
21
33
  - **`Card variant="elevated"`**: borderless, `background[50]` lifted by `shadows.card`; declares a 0 border width so it
22
34
  never inherits an outline parent's rule.
23
35
  - **`bandOn`, `recessOn`, `cardRule`**: plane-step helpers that return the input unchanged in light and a visible step
@@ -381,6 +393,37 @@ next major.
381
393
 
382
394
  ### Changed (visual)
383
395
 
396
+ - **`Table` loading state.** With `isLoading` and no rows, each row now draws one skeleton per column (a checkbox
397
+ placeholder in the checkbox column, blank spacer cells) with the variant's row rule, instead of one bar spanning the
398
+ table. If `columns` is still empty while loading, the header shows four placeholder cells and a disabled select-all
399
+ instead of a lone checkbox stretched across the row. The select-all checkbox is disabled while `isLoading`.
400
+ - **`Table` defaults to `variant="studio"`.** Every `Table` rendered without `variant` (or with `variant={undefined}`)
401
+ now draws studio: flat small-caps header, one row rule, the select slot resting on the row number, status as a pill.
402
+ Keep the old look with `variant="classic"`. Measured 2026-10-14: crm-frontend has 38 `<Table>` call sites, none
403
+ passing `variant` (all 38 change); account-frontend 8 of 18 change (the other 10 already pass `"studio"`); hrms,
404
+ tickets and lfour render `Table` only through an `AppTable` wrapper that already defaults to studio (0 change).
405
+ - **Option rows fill only under the cursor; selection is the trailing check and weight 500.** `Select`, `SearchSelect`,
406
+ `SelectSearch`, `CompactSelect` and `OrgSwitcher` no longer fill the selected row: the selected fill sat 1.00-1.02:1
407
+ from the hover fill on all 18 brand x mode palettes, so the two read as one state. `SelectSearch`/`CompactSelect` no
408
+ longer fill row 0 on open beside the hovered row. `Dropdown` items keep `text[700]` under the cursor instead of turning
409
+ `accentText`. `SearchSelect` rows sit inset (`mx`, rounded) with the check at the trailing edge and no hairline
410
+ between rows. Text on every row state measures 7.69:1 or more (selected 12.43-19.90:1).
411
+ - **Chakra `Menu` items use option-row ink:** `text[700]` instead of `text[900]`; a checked `MenuItemOption` is weight
412
+ 500 with an `accentText` check, matching `Select`.
413
+ - **Dark `Button` `outline`/`ghost`/`link` ink is chosen against the canvas, the card and the overlay.** It cleared AA
414
+ on the canvas only, so in a dialog or popover it fell to 4.06-4.50:1 in 24 scheme x brand combos (lavender outline
415
+ 4.46:1, rosewood 4.10:1); now AA on all three planes (lavender 6.28:1, rosewood 5.57:1). Light mode is unchanged
416
+ (0 light combos move); 62 dark combos step lighter (emerald primary `#0f9d8a` -> `#14e3c7`).
417
+ - **Dark rules and pressed solids (owner review before release).** In dark only: the `NavigationBar` header rule and
418
+ leading divider, the `KanbanBoard` column edge, header rule and count pill, the filled `TextInput` (a visible band off
419
+ the card) and the Kanban drag-over column's dashed border (`focusRing.ring`, 3.1:1 or more instead of 1.7-2.7:1)
420
+ now read at the in-card rule weight instead of 1.03-1.16:1. Solid `hover`/`active` fills never fall below 1.5:1 against
421
+ the canvas (a pressed warning solid reached 1.00:1) and never flip the label colour, so zinc dark's pressed primary stays
422
+ light with dark ink instead of dropping to `#52525b`. `ScrollToTop`, `FilePreview`, `ProfilePhotoViewer`, the Table
423
+ clear-filters badge, Chakra `Badge`/`Radio` and the Table status pills now pass the canvas to `solidFillRung`: zinc dark
424
+ primary and every brand's dark gray solid move from `#52525b`/`#525252` (2.4:1) to `#e4e4e7`/`#a3a3a3` with dark ink.
425
+ Light mode and every other dark colour keep their fill; error/warning/info pressed fills in dark are lighter than before
426
+ and hover and press now share one rung.
384
427
  - **Elevation follows Pebble, per mode.** `shadows.sm`/`base`/`md`/`lg` are the Pebble card-press/
385
428
  card/float/dialog stacks, with new `card`, `float`, `dialog` and `sheet` role keys. Light shadows are
386
429
  softer and wider; dark mode gets its own heavier black ramp, so overlays cast a visible shadow on a
@@ -444,6 +487,10 @@ next major.
444
487
 
445
488
  ### Fixed
446
489
 
490
+ - **`WorkspaceTrayPreview`** reports `onOpenChange(false)` only after the card actually opened (it used to fire when
491
+ the pointer left before the open delay).
492
+ - **`FileUploader`** revokes the blob URL of an image the moment it is removed, and of images it rejects (over the total
493
+ size or past `maxFiles`); those URLs were created and never freed. Surviving URLs stay yours to revoke.
447
494
  - **`Table` settings sheet** fades in place instead of dropping in when the user prefers reduced motion.
448
495
  - **`SearchSelect`**: the Select All and Add New rows are reachable from the keyboard. Arrow keys, Home and End walk
449
496
  Select All, then the options, then Add New, and Enter runs them. Both are now `role="option"` rows, so a test that
@@ -342,7 +342,6 @@ rows per page does not reset `page` either. Reset it yourself, in `onPageSizeCha
342
342
 
343
343
  ### Four components with a behaviour their props do not hint at
344
344
 
345
- - `WorkspaceTrayPreview` `onOpenChange(false)` also fires when the pointer leaves before the card ever opened; track your own open state from `true`.
346
345
  - `Notification`'s countdown is computed when its dates change and never ticks; remount or change a date to refresh it. Overdue labels read "overdue by N hours ago".
347
346
  - `NoteTextArea` checks `maxNoteWordCount` against the title only until the note is next edited, so a long title can be saved; `handleCancel` always receives `false`.
348
347
  - `VerifyEmailOtp` fields set `autocomplete="off"`, so browser or OS one-time-code autofill never offers the code.
@@ -548,6 +547,19 @@ use `bandOn(fill, surface)` for a header strip, hover or selection tint, `recess
548
547
  or off cell, `cardRule(colors)` for a rule inside a card and `raisedRule(colors)` for a rule inside an overlay.
549
548
  All four return the old value unchanged in light mode.
550
549
 
550
+ ### A Chakra `ModalHeader` inside a coloured box keeps its own ink
551
+
552
+ The theme gives `ModalHeader` `color: colors.header[900]` and a bottom rule. Wrapping it in a
553
+ `Box bgGradient=… color={ink}` does not recolour it: the header paints `header[900]` itself, so the
554
+ title is dark navy on a blue/purple gradient (3.11–4.11:1 in light across the 9 brands, against
555
+ 4.62:1 for the gradient's own ink). Icons and badges inside it that read `currentColor` follow the
556
+ header, not the box.
557
+
558
+ **Apply:** put the ink on the header itself — `<ModalHeader color={resolved.ink} borderBottomWidth={0}>`
559
+ with `resolved = resolveGradient(stops, colors.white, colors.black)` — or use `LimitReachedModal`.
560
+ For an accent icon on the gradient, use `resolved.ink` unless the accent clears 3:1 on both
561
+ `resolved.from` and `resolved.to`; a theme `yellow[300]` drops to 2.61:1 in dark.
562
+
551
563
  ### `Drawer` / `Modal` / `ProfileCard` drop any child that isn't a named slot — use `portalChildren`
552
564
 
553
565
  All three match children by exact type (`child.type === XHeader/XBody/XFooter`) and render only
@@ -700,13 +712,13 @@ whose defaults arrive asynchronously doesn't open already red.
700
712
  ### A wrapper presetting a prop must destructure with a default, not rely on JSX prop order
701
713
 
702
714
  Wrapping a library component to preset a prop (e.g. `Table`'s `variant`) as
703
- `<Table variant="studio" {...props} />` silently reverts to the library's own default the moment a
715
+ `<Table variant="classic" {...props} />` silently reverts to the library's own default the moment a
704
716
  caller passes `variant={undefined}` — a later spread always wins in JSX, even with `undefined`,
705
717
  and the library component resolves that `undefined` via its own default parameter.
706
718
 
707
719
  **Apply:**
708
720
  ```tsx
709
- const AppTable = ({ variant = 'studio', ...props }: TableProps) => <Table variant={variant} {...props} />;
721
+ const AppTable = ({ variant = 'classic', ...props }: TableProps) => <Table variant={variant} {...props} />;
710
722
  ```
711
723
  Applies to any library prop with a default value, not just `Table`'s `variant`.
712
724
 
@@ -1843,6 +1855,17 @@ from `optionRowDescriptionInk(theme.colors)` (exported from the package root) ra
1843
1855
  `theme.colors.textMuted`. It is a no-op in light mode. The row's main label is
1844
1856
  `optionRowInk(theme.colors, isSelected)` with `optionRowWeight(isSelected)` — never brand ink.
1845
1857
 
1858
+ ### A custom option list must not fill the selected row
1859
+
1860
+ `listRowBackgrounds(colors).selected` and `.active` sit within 1.02:1 of each other on every brand
1861
+ and mode, so a list that fills both the selected row and the hovered row shows two identical fills
1862
+ and the user cannot tell which one is chosen. Library option lists paint one fill — the cursor's —
1863
+ and mark selection with `optionRowWeight` plus a trailing `Check` in `colors.accentText`.
1864
+
1865
+ **Apply:** `bg={optionRowFill(listRowBackgrounds(colors), isActive)}` for an index-driven list, or
1866
+ `{...optionRowCursorSx(listRowBackgrounds(colors))}` for rows that take DOM focus; both are exported
1867
+ from the package root. Text is `optionRowInk(colors, isSelected)`, unchanged on hover.
1868
+
1846
1869
  ### `Table`'s node column `label` needs `labelText` unless its text is plain children
1847
1870
 
1848
1871
  `columns[].label` accepts a node (an icon, a tooltip trigger) as well as a string or number. Every
package/DESIGN-GUIDE.md CHANGED
@@ -77,6 +77,7 @@ stay light in dark mode.
77
77
  | Status text/icon | `colors.semanticText.success \| error \| warning \| info` |
78
78
  | Status chip | `<Tag label="Won" colorScheme="green" />` (subtle, `sm` by default) — never a painted `Box`. Tone → `colorScheme`: success `green`, warning `orange`, error `red`, info `blue`, neutral `gray`. Quiet rows: `<Tag tone="success" display="dot" label=… />`; map an app's status vocabulary once with `<StatusTag status map label display />` |
79
79
  | Selectable list row (inbox, picker) | `listRowBackgrounds(colors)` for hover/selected + `sx={focusVisibleStyles(colors)}`; pad the list `p={2}` so the ring isn't clipped |
80
+ | Option row in a dropdown/menu/select | `optionRowFill` / `optionRowCursorSx` (fill = cursor only) + `optionRowInk` + a trailing `Check` for the selected row — never a selected fill |
80
81
  | Any filled surface you paint | `resolveFilledSurface(colors.<scale>, colors)` → `{ fill, color }` |
81
82
  | Icon tint chip, avatar tint | `bg={colors.primary.opacity[8]}` + `color={colors.accentText}` (`opacity` exists on `primary`/`secondary`/`tertiary` only) |
82
83
 
@@ -24,7 +24,12 @@ const controlSize = (size) => {
24
24
  return { h: height, minW: height, fontSize, px: paddingX };
25
25
  };
26
26
  // NOTE: [500] alone measures ~4.2 on a dark canvas — resolved per-mode so outline/ghost/link text stays readable.
27
- const onCanvasText = (theme, colorScheme) => (0, accentText_1.accentTextOnCanvas)(theme.colors[colorScheme], theme.colors.backgroundColor.main);
27
+ // NOTE: a bare button sits on the canvas, a card or an overlay; dark overlays are the hardest plane.
28
+ const onCanvasText = (theme, colorScheme) => (0, accentText_1.accentTextOnPlanes)(theme.colors[colorScheme], [
29
+ theme.colors.backgroundColor.main,
30
+ theme.colors.background[50],
31
+ theme.colors.surfaceRaised,
32
+ ]);
28
33
  // NOTE: [50] alone measured ~1.04 (invisible) in both modes — gray borrows the row-state steps.
29
34
  const onCanvasHoverBg = (theme, colorScheme, step) => {
30
35
  const scale = theme.colors[colorScheme];
@@ -36,7 +41,7 @@ const onCanvasHoverBg = (theme, colorScheme, step) => {
36
41
  return step === 16 ? rows.active : rows.selectedActive;
37
42
  };
38
43
  const swatch = (theme, colorScheme) => theme.colors[colorScheme];
39
- const buttonSolidRung = (theme, colorScheme) => (0, filledSurface_1.solidFillRung)(swatch(theme, colorScheme), theme.colors.white);
44
+ const buttonSolidRung = (theme, colorScheme) => (0, filledSurface_1.solidFillRung)(swatch(theme, colorScheme), theme.colors.white, theme.colors.backgroundColor.main);
40
45
  const darkerFill = (theme, colorScheme, step) => {
41
46
  const scale = swatch(theme, colorScheme);
42
47
  const rung = (0, filledSurface_1.darkerFillRung)(scale, theme.colors.backgroundColor.main, theme.colors.white, step);
@@ -8,6 +8,7 @@ const useCustomTheme_1 = require("../../Theme/useCustomTheme");
8
8
  const surfaceRaised_1 = require("../../Theme/tokens/builders/surfaceRaised");
9
9
  const scrollbar_1 = require("../../Theme/tokens/builders/scrollbar");
10
10
  const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
11
+ const optionRowInk_1 = require("../Select/optionRowInk");
11
12
  const useExclusiveOverlay_1 = require("../../Hooks/useExclusiveOverlay");
12
13
  const lucide_react_1 = require("lucide-react");
13
14
  const rafThrottle_1 = require("../../Utils/rafThrottle");
@@ -248,16 +249,8 @@ const Dropdown = (0, react_1.forwardRef)(({ dropDownButtonStyle, ButtonText, opt
248
249
  }, role: "menuitem", tabIndex: index === activeIndex ? 0 : -1, onClick: () => {
249
250
  handleListItemClick(option.id, option.label);
250
251
  focusTrigger();
251
- }, onKeyDown: (e) => handleItemKeyDown(e, option.id, option.label), mx: rowSpec.mx, px: rowSpec.px, py: rowSpec.py, minH: rowSpec.minH, borderRadius: optionRowSizes_1.OPTION_ROW_RADIUS, display: "flex", alignItems: "center", gap: rowSpec.gap, fontSize: rowSpec.fontSize, cursor: "pointer", color: theme.colors.text[700], transition: ROW_TRANSITION, _hover: {
252
+ }, onKeyDown: (e) => handleItemKeyDown(e, option.id, option.label), mx: rowSpec.mx, px: rowSpec.px, py: rowSpec.py, minH: rowSpec.minH, borderRadius: optionRowSizes_1.OPTION_ROW_RADIUS, display: "flex", alignItems: "center", gap: rowSpec.gap, fontSize: rowSpec.fontSize, cursor: "pointer", color: (0, optionRowInk_1.optionRowInk)(theme.colors, false), transition: ROW_TRANSITION, _hover: { bg: hoverTint }, _focus: { bg: hoverTint, outline: "none" }, _focusVisible: {
252
253
  bg: hoverTint,
253
- color: theme.colors.accentText,
254
- }, _focus: {
255
- bg: hoverTint,
256
- color: theme.colors.accentText,
257
- outline: "none",
258
- }, _focusVisible: {
259
- bg: hoverTint,
260
- color: theme.colors.accentText,
261
254
  boxShadow: `inset 0 0 0 2px ${theme.colors.focusRing.ring}`,
262
255
  }, borderBottom: divider
263
256
  ? `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, surfaceRaised_1.raisedRule)(theme.colors)}`
@@ -49,6 +49,7 @@ const downloadFile = async (fileUrl, fileName) => {
49
49
  /** Modal previewer inferring image/pdf/video/other from the extension — for an always-inline PDF-only panel use PdfViewer. */
50
50
  const FilePreview = ({ isOpen, onClose, fileUrl, fileName, fileType, hideDownload = false, size = "xl", }) => {
51
51
  const theme = (0, useCustomTheme_1.useCustomTheme)();
52
+ const downloadFill = (0, filledSurface_1.resolveFilledSurface)(theme.colors.primary, theme.colors);
52
53
  const [zoom, setZoom] = (0, react_1.useState)(1);
53
54
  const [rotation, setRotation] = (0, react_1.useState)(0);
54
55
  const kind = fileType || inferKind(fileUrl, fileName);
@@ -70,7 +71,7 @@ const FilePreview = ({ isOpen, onClose, fileUrl, fileName, fileType, hideDownloa
70
71
  if (kind === "video") {
71
72
  return ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "video", src: fileUrl, controls: true, width: "100%", borderRadius: "lg" }));
72
73
  }
73
- return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", align: "center", justify: "center", py: 12, gap: 3, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FileQuestion, { size: 48, color: theme.colors.textMuted }), (0, jsx_runtime_1.jsx)(react_2.Text, { color: theme.colors.textMuted, fontSize: "sm", children: "Preview isn't available for this file type." }), !hideDownload && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", align: "center", gap: 2, px: 4, py: 2, borderRadius: "lg", bg: theme.colors.primary[(0, filledSurface_1.solidFillRung)(theme.colors.primary, theme.colors.white)], color: (0, filledSurface_1.labelOnFill)(theme.colors.primary[(0, filledSurface_1.solidFillRung)(theme.colors.primary, theme.colors.white)], theme.colors.white, theme.colors.black), fontSize: "sm", fontWeight: 500, onClick: () => downloadFile(fileUrl, fileName), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { size: 16 }), " Download file"] }))] }));
74
+ return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", align: "center", justify: "center", py: 12, gap: 3, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FileQuestion, { size: 48, color: theme.colors.textMuted }), (0, jsx_runtime_1.jsx)(react_2.Text, { color: theme.colors.textMuted, fontSize: "sm", children: "Preview isn't available for this file type." }), !hideDownload && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", align: "center", gap: 2, px: 4, py: 2, borderRadius: "lg", bg: downloadFill.fill, color: downloadFill.color, fontSize: "sm", fontWeight: 500, onClick: () => downloadFile(fileUrl, fileName), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { size: 16 }), " Download file"] }))] }));
74
75
  };
75
76
  return ((0, jsx_runtime_1.jsxs)(react_2.Modal, { isOpen: isOpen, onClose: handleClose, size: size, isCentered: true, children: [(0, jsx_runtime_1.jsx)(react_2.ModalOverlay, { ...(0, overlay_styles_1.overlayScrimStyles)(theme.colors) }), (0, jsx_runtime_1.jsxs)(MotionContent, { bg: theme.colors.surfaceRaised, borderRadius: "xl", overflow: "hidden", initial: { opacity: 0, scale: 0.96, y: 8 }, animate: { opacity: 1, scale: 1, y: 0 }, transition: { duration: 0.2, ease: "easeOut" }, children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", justify: "space-between", px: 4, py: 3, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: [(0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: fileName || "File", placement: "bottom", children: (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "sm", fontWeight: 600, maxW: "60%", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: fileName || "Preview" }) }), (0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 1, children: [kind === "image" && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Zoom out", placement: "bottom", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Zoom out", size: "sm", variant: "ghost", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Minus, { size: 16 }), onClick: () => setZoom((z) => Math.max(0.25, z - 0.25)) }) }), (0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Zoom in", placement: "bottom", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Zoom in", size: "sm", variant: "ghost", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16 }), onClick: () => setZoom((z) => Math.min(4, z + 0.25)) }) }), (0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Rotate", placement: "bottom", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Rotate", size: "sm", variant: "ghost", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.RotateCw, { size: 16 }), onClick: () => setRotation((r) => (r + 90) % 360) }) })] })), !hideDownload && ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Download", placement: "bottom", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Download", size: "sm", variant: "ghost", color: theme.colors.semanticText.success, icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Download, { size: 18 }), onClick: () => downloadFile(fileUrl, fileName) }) })), (0, jsx_runtime_1.jsx)(react_2.ModalCloseButton, { position: "static" })] })] }), (0, jsx_runtime_1.jsx)(react_2.ModalBody, { p: 5, children: renderBody() })] })] }));
76
77
  };
@@ -10,6 +10,7 @@ const accentText_1 = require("../../Theme/tokens/builders/accentText");
10
10
  const fieldStyles_1 = require("../Common/fieldStyles");
11
11
  const motion_1 = require("../../Theme/tokens/primitives/motion");
12
12
  const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
13
+ const revokePreviews = (files) => files.forEach((f) => f.previewUrl && URL.revokeObjectURL(f.previewUrl));
13
14
  /** Self-contained widget; onFilesChange returns {id,name,size,previewUrl} metadata, never real File objects — cannot be used to upload bytes. */
14
15
  const FileUploader = ({ maxFiles = 10, maxTotalSize = 20, onFilesChange, acceptTypes = ["jpeg", "jpg", "png"], }) => {
15
16
  const { showToast } = (0, Toaster_1.useToaster)();
@@ -38,7 +39,9 @@ const FileUploader = ({ maxFiles = 10, maxTotalSize = 20, onFilesChange, acceptT
38
39
  }));
39
40
  const combinedFiles = [...uploadedFiles, ...newFiles].slice(0, maxFiles);
40
41
  const totalSizeBytes = combinedFiles.reduce((acc, f) => acc + f.size, 0);
42
+ revokePreviews(newFiles.filter((f) => !combinedFiles.includes(f)));
41
43
  if (totalSizeBytes > maxTotalBytes) {
44
+ revokePreviews(newFiles);
42
45
  showToast({
43
46
  title: `Total file size exceeds ${maxTotalSize} MB limit.`,
44
47
  duration: 3000,
@@ -68,6 +71,7 @@ const FileUploader = ({ maxFiles = 10, maxTotalSize = 20, onFilesChange, acceptT
68
71
  const handleDragLeave = () => setIsDragOver(false);
69
72
  const removeFile = (id) => {
70
73
  const filtered = uploadedFiles.filter((f) => f.id !== id);
74
+ revokePreviews(uploadedFiles.filter((f) => f.id === id));
71
75
  setUploadedFiles(filtered);
72
76
  onFilesChange === null || onFilesChange === void 0 ? void 0 : onFilesChange(filtered);
73
77
  };
@@ -18,6 +18,6 @@ export type FileUploaderProps = {
18
18
  maxTotalSize?: number;
19
19
  /** Extensions without dots, default jpeg/jpg/png; filters the picker only, drops are never checked. */
20
20
  acceptTypes?: string[];
21
- /** Whole list after each add or remove; revoke each image's previewUrl blob yourself. */
21
+ /** Whole list after each add or remove; the uploader revokes the blob of a removed or rejected image; revoke the rest yourself when done. */
22
22
  onFilesChange?: (files: UploadedFile[]) => void;
23
23
  };
@@ -4,6 +4,7 @@ exports.Input = exports.fieldSizes = exports.fieldAddonSx = exports.fieldFlushed
4
4
  const fieldStyles_1 = require("../Common/fieldStyles");
5
5
  const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
6
6
  const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
7
+ const planeStep_1 = require("../../Theme/tokens/builders/planeStep");
7
8
  /** Field look shared by Input, Textarea and NumberInput; `_invalid` also clears Chakra's stock invalid shadow. */
8
9
  const fieldPartStyles = (colors) => {
9
10
  const error = colors.semanticText.error;
@@ -18,12 +19,15 @@ const fieldPartStyles = (colors) => {
18
19
  };
19
20
  };
20
21
  exports.fieldPartStyles = fieldPartStyles;
21
- const fieldFilledStyles = (colors) => ({
22
- ...(0, exports.fieldPartStyles)(colors),
23
- bg: colors.background[100],
24
- borderColor: "transparent",
25
- _hover: { bg: colors.background[100], borderColor: "transparent" },
26
- });
22
+ const fieldFilledStyles = (colors) => {
23
+ const filledBand = (0, planeStep_1.bandOn)(colors.background[100], colors.background[50]);
24
+ return {
25
+ ...(0, exports.fieldPartStyles)(colors),
26
+ bg: filledBand,
27
+ borderColor: "transparent",
28
+ _hover: { bg: filledBand, borderColor: "transparent" },
29
+ };
30
+ };
27
31
  exports.fieldFilledStyles = fieldFilledStyles;
28
32
  const fieldFlushedStyles = (colors) => ({
29
33
  ...(0, exports.fieldPartStyles)(colors),
@@ -50,6 +50,7 @@ const motion_2 = require("../../Theme/chakra/motion");
50
50
  const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
51
51
  const usePreferences_1 = require("../../Hooks/usePreferences");
52
52
  const AccountCard_1 = __importDefault(require("./AccountCard"));
53
+ const planeStep_1 = require("../../Theme/tokens/builders/planeStep");
53
54
  const HeaderActions_1 = __importDefault(require("../Header/HeaderActions"));
54
55
  const MeasuredItem_1 = __importDefault(require("./MeasuredItem"));
55
56
  const OverflowTooltipText_1 = __importDefault(require("../SideBar/components/OverflowTooltipText"));
@@ -73,7 +74,7 @@ const MIN_LIST_HEIGHT = 120;
73
74
  const KANBAN_VIRTUALIZE_THRESHOLD = 30;
74
75
  const COLUMN_TRANSITION = `${(0, motion_1.transitionFor)(["background-color", "border-color"])}, ${(0, motion_1.transitionFor)(["width"], "base")}`;
75
76
  const SKELETON_ROWS = [3, 4, 3];
76
- const CardSkeleton = ({ colors, rows }) => ((0, jsx_runtime_1.jsx)(react_2.Box, { "data-testid": "kanban-card-skeleton", borderRadius: "lg", bg: colors.background[50], border: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${colors.boxborder[200]}`, p: 3, minH: "5rem", children: (0, jsx_runtime_1.jsx)(react_2.Flex, { direction: "column", gap: 2.5, children: Array.from({ length: rows }).map((_, i) => ((0, jsx_runtime_1.jsxs)(react_2.Flex, { gap: 2, align: "center", children: [(0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: 2.5, w: "30%", borderRadius: "sm" }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: 2.5, flex: "1", maxW: i % 2 ? "40%" : "55%", borderRadius: "sm" })] }, i))) }) }));
77
+ const CardSkeleton = ({ colors, rows }) => ((0, jsx_runtime_1.jsx)(react_2.Box, { "data-testid": "kanban-card-skeleton", borderRadius: "lg", bg: colors.background[50], border: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, planeStep_1.cardRule)(colors)}`, p: 3, minH: "5rem", children: (0, jsx_runtime_1.jsx)(react_2.Flex, { direction: "column", gap: 2.5, children: Array.from({ length: rows }).map((_, i) => ((0, jsx_runtime_1.jsxs)(react_2.Flex, { gap: 2, align: "center", children: [(0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: 2.5, w: "30%", borderRadius: "sm" }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: 2.5, flex: "1", maxW: i % 2 ? "40%" : "55%", borderRadius: "sm" })] }, i))) }) }));
77
78
  // Top buffer above the first card so its border + hover lift aren't clipped by the
78
79
  // scroll/virtualized list's top edge.
79
80
  const KANBAN_LIST_TOP_PAD = 6;
@@ -443,14 +444,14 @@ const KanbanBoard = ({ data, customColumns, customizeColumn, onDrag, onDelete, o
443
444
  return ((0, jsx_runtime_1.jsxs)(react_2.Box, { ref: provided.innerRef, ...provided.droppableProps, width: isColCollapsed ? COLLAPSED_KANBAN_COLUMN_WIDTH : columnWidth, borderRadius: "xl", background: snapshot.isDraggingOver
444
445
  ? colors.primary[50]
445
446
  : colors.background[100], border: `${borderWidths_1.BORDER_WIDTHS.hairline} ${snapshot.isDraggingOver ? "dashed" : "solid"} ${snapshot.isDraggingOver
446
- ? colors.primary[300]
447
- : colors.boxborder[200]}`, transition: COLUMN_TRANSITION, display: "flex", flexDirection: "column", flexShrink: 0, overflow: isColCollapsed ? "visible" : "hidden", height: COLUMN_HEIGHT, sx: (0, motion_2.reducedMotionSx)(), onMouseEnter: () => hoveredColumn.set(colId), onMouseLeave: () => hoveredColumn.set(null), onFocus: () => hoveredColumn.set(colId), onBlur: (e) => {
447
+ ? colors.focusRing.ring
448
+ : (0, planeStep_1.ruleOn)(colors, colors.background[100])}`, transition: COLUMN_TRANSITION, display: "flex", flexDirection: "column", flexShrink: 0, overflow: isColCollapsed ? "visible" : "hidden", height: COLUMN_HEIGHT, sx: (0, motion_2.reducedMotionSx)(), onMouseEnter: () => hoveredColumn.set(colId), onMouseLeave: () => hoveredColumn.set(null), onFocus: () => hoveredColumn.set(colId), onBlur: (e) => {
448
449
  if (!e.currentTarget.contains(e.relatedTarget))
449
450
  hoveredColumn.set(null);
450
451
  }, children: [isColCollapsed ? ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", align: "stretch", flex: "1", width: "100%", minH: 0, overflow: "visible", position: "relative", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "header", direction: "column", align: "center", flexShrink: 0, width: "100%", py: 3, px: 1, gap: 3, borderTop: "0.25rem solid", borderTopColor: (_a = column.color) !== null && _a !== void 0 ? _a : colors.primary[500], bg: colors.background[100], position: "relative", zIndex: 1, children: [enableColumnReorder && columnDragHandleProps ? ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", justify: "center", flexShrink: 0, cursor: "grab", ...columnDragHandleProps, "aria-label": `Reorder ${column.title} column`, children: (0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.GripVertical, size: 14, color: colors.textMuted }) })) : null, enableColumnCollapse && ((0, jsx_runtime_1.jsx)(react_2.Flex, { flexShrink: 0, w: "100%", justify: "center", bg: colors.background[100], position: "relative", zIndex: 3, children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Expand column", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 14 }), variant: "ghost", size: "xs", minW: "1.5rem", h: "1.75rem", onClick: () => toggleColumnCollapsed(colId) }) })), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", fontWeight: "700", fontSize: "xs", color: colors.text[700], sx: {
451
452
  writingMode: "vertical-rl",
452
453
  textOrientation: "mixed",
453
- }, maxH: `${Math.max(120, containerHeight - 200)}px`, overflow: "hidden", lineHeight: "1.2", title: column.title, children: column.title }), (0, jsx_runtime_1.jsx)(react_2.Badge, { minW: 5, h: 5, borderRadius: "full", border: `${borderWidths_1.BORDER_WIDTHS.hairline} solid`, borderColor: colors.boxborder[200], display: "flex", backgroundColor: colors.background[100], alignItems: "center", justifyContent: "center", color: colors.text[900], fontWeight: 600, fontSize: "xs", children: (_b = column === null || column === void 0 ? void 0 : column.items) === null || _b === void 0 ? void 0 : _b.length })] }), column.customNode ? ((0, jsx_runtime_1.jsx)(react_2.Box, { flexShrink: 0, minH: COLLAPSED_CUSTOM_NODE_TOP_RESERVE, w: "100%", bg: colors.background[100], "aria-hidden": true })) : null, column.customNode ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "section", "aria-label": "Column summary", flex: "1", minH: 0, w: "100%", overflow: "visible", py: 2, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "flex-start", bg: colors.background[100], position: "relative", zIndex: 2, children: (0, jsx_runtime_1.jsx)(react_2.Box, { position: "relative", transform: "rotate(90deg)", transformOrigin: "center center", marginTop: '1rem', children: (0, jsx_runtime_1.jsx)(react_2.VStack, { align: "stretch", spacing: 1, minW: "max-content", fontSize: "xs", color: colors.text[600], children: column.customNode() }) }) })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { flex: "1", minH: 0 }))] })) : ((0, jsx_runtime_1.jsxs)(react_2.Flex, { width: "100%", h: !isColCollapsed && !!((_c = column.customNode) === null || _c === void 0 ? void 0 : _c.call(column)) ? "auto" : "2.75rem", align: !isColCollapsed && !!((_d = column.customNode) === null || _d === void 0 ? void 0 : _d.call(column)) ? "flex-start" : "center", px: 3, py: 2, flexShrink: 0, justifyContent: "space-between", position: "relative", gap: 2, borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${colors.boxborder[200]}`, children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 1, minW: 0, flex: "1", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { boxSize: 2.5, borderRadius: "full", bg: (_e = column.color) !== null && _e !== void 0 ? _e : colors.primary[500], flexShrink: 0 }), enableColumnReorder && columnDragHandleProps ? ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", justify: "center", flexShrink: 0, cursor: "grab", ...columnDragHandleProps, "aria-label": `Reorder ${column.title} column`, children: (0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.GripVertical, size: 14, color: colors.textMuted }) })) : null, (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", fontWeight: "600", fontSize: "sm", color: colors.text[700], noOfLines: 1, minW: 0, children: (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "top", children: column.title }) })] }), column.customNode ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "section", "aria-label": "Column summary", width: "100%", flexShrink: 0, fontSize: "xs", color: colors.text[600], children: (_f = column.customNode) === null || _f === void 0 ? void 0 : _f.call(column) })) : null] }), (0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", alignItems: "center", gap: 2, children: [(0, jsx_runtime_1.jsx)(react_2.Badge, { minW: 6, h: 6, px: 2, borderRadius: "full", backgroundColor: colors.backgroundColor.subtle, display: "flex", alignItems: "center", justifyContent: "center", color: colors.text[500], fontWeight: 600, fontSize: "xs", children: (_g = column === null || column === void 0 ? void 0 : column.items) === null || _g === void 0 ? void 0 : _g.length }), enableColumnCollapse && ((0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Collapse column", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 14 }), variant: "ghost", size: "xs", minW: "1.5rem", h: "1.75rem", flexShrink: 0, onClick: () => toggleColumnCollapsed(colId) })), canDelete && column.items.length > 0 ? ((0, jsx_runtime_1.jsx)(ColumnDeleteAll, { colId: colId, title: column.title, hoveredColumn: hoveredColumn, colors: colors, onDelete: handleColumnDelete })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { boxSize: 4, flexShrink: 0 }))] })] })), !isColCollapsed && ((0, jsx_runtime_1.jsxs)(react_2.Box, { px: 2, flex: "1", overflowY: "auto", width: "100%", sx: {
454
+ }, maxH: `${Math.max(120, containerHeight - 200)}px`, overflow: "hidden", lineHeight: "1.2", title: column.title, children: column.title }), (0, jsx_runtime_1.jsx)(react_2.Badge, { minW: 5, h: 5, borderRadius: "full", border: `${borderWidths_1.BORDER_WIDTHS.hairline} solid`, borderColor: (0, planeStep_1.ruleOn)(colors, colors.background[100]), display: "flex", backgroundColor: colors.background[100], alignItems: "center", justifyContent: "center", color: colors.text[900], fontWeight: 600, fontSize: "xs", children: (_b = column === null || column === void 0 ? void 0 : column.items) === null || _b === void 0 ? void 0 : _b.length })] }), column.customNode ? ((0, jsx_runtime_1.jsx)(react_2.Box, { flexShrink: 0, minH: COLLAPSED_CUSTOM_NODE_TOP_RESERVE, w: "100%", bg: colors.background[100], "aria-hidden": true })) : null, column.customNode ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "section", "aria-label": "Column summary", flex: "1", minH: 0, w: "100%", overflow: "visible", py: 2, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "flex-start", bg: colors.background[100], position: "relative", zIndex: 2, children: (0, jsx_runtime_1.jsx)(react_2.Box, { position: "relative", transform: "rotate(90deg)", transformOrigin: "center center", marginTop: '1rem', children: (0, jsx_runtime_1.jsx)(react_2.VStack, { align: "stretch", spacing: 1, minW: "max-content", fontSize: "xs", color: colors.text[600], children: column.customNode() }) }) })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { flex: "1", minH: 0 }))] })) : ((0, jsx_runtime_1.jsxs)(react_2.Flex, { width: "100%", h: !isColCollapsed && !!((_c = column.customNode) === null || _c === void 0 ? void 0 : _c.call(column)) ? "auto" : "2.75rem", align: !isColCollapsed && !!((_d = column.customNode) === null || _d === void 0 ? void 0 : _d.call(column)) ? "flex-start" : "center", px: 3, py: 2, flexShrink: 0, justifyContent: "space-between", position: "relative", gap: 2, borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, planeStep_1.ruleOn)(colors, colors.background[100])}`, children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 1, minW: 0, flex: "1", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { boxSize: 2.5, borderRadius: "full", bg: (_e = column.color) !== null && _e !== void 0 ? _e : colors.primary[500], flexShrink: 0 }), enableColumnReorder && columnDragHandleProps ? ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", justify: "center", flexShrink: 0, cursor: "grab", ...columnDragHandleProps, "aria-label": `Reorder ${column.title} column`, children: (0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.GripVertical, size: 14, color: colors.textMuted }) })) : null, (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", fontWeight: "600", fontSize: "sm", color: colors.text[700], noOfLines: 1, minW: 0, children: (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "top", children: column.title }) })] }), column.customNode ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "section", "aria-label": "Column summary", width: "100%", flexShrink: 0, fontSize: "xs", color: colors.text[600], children: (_f = column.customNode) === null || _f === void 0 ? void 0 : _f.call(column) })) : null] }), (0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", alignItems: "center", gap: 2, children: [(0, jsx_runtime_1.jsx)(react_2.Badge, { minW: 6, h: 6, px: 2, borderRadius: "full", backgroundColor: colors.backgroundColor.subtle, display: "flex", alignItems: "center", justifyContent: "center", color: colors.text[500], fontWeight: 600, fontSize: "xs", children: (_g = column === null || column === void 0 ? void 0 : column.items) === null || _g === void 0 ? void 0 : _g.length }), enableColumnCollapse && ((0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Collapse column", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 14 }), variant: "ghost", size: "xs", minW: "1.5rem", h: "1.75rem", flexShrink: 0, onClick: () => toggleColumnCollapsed(colId) })), canDelete && column.items.length > 0 ? ((0, jsx_runtime_1.jsx)(ColumnDeleteAll, { colId: colId, title: column.title, hoveredColumn: hoveredColumn, colors: colors, onDelete: handleColumnDelete })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { boxSize: 4, flexShrink: 0 }))] })] })), !isColCollapsed && ((0, jsx_runtime_1.jsxs)(react_2.Box, { px: 2, flex: "1", overflowY: "auto", width: "100%", sx: {
454
455
  ...(0, scrollbar_1.scrollbarStyles)(colors),
455
456
  overflowY: "auto",
456
457
  overflowX: "hidden",
@@ -492,7 +493,7 @@ const KanbanBoard = ({ data, customColumns, customizeColumn, onDrag, onDelete, o
492
493
  }
493
494
  return renderColumnDroppable(colId, column, null, isColCollapsed);
494
495
  });
495
- const loadingSkeletonRow = Array.from({ length: 4 }).map((_, idx) => ((0, jsx_runtime_1.jsxs)(react_2.Box, { "aria-hidden": true, width: columnWidth, borderRadius: "xl", bg: colors.background[100], border: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${colors.boxborder[200]}`, flexShrink: 0, alignSelf: "flex-start", overflow: "hidden", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { h: "2.75rem", align: "center", gap: 2, px: 3, borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${colors.boxborder[200]}`, children: [(0, jsx_runtime_1.jsx)(react_2.SkeletonCircle, { size: "2.5" }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: 3, w: "40%", borderRadius: "sm" }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: 6, w: 6, ml: "auto", borderRadius: "full" })] }), (0, jsx_runtime_1.jsx)(react_2.Flex, { direction: "column", gap: 3, px: 2, pt: 1.5, pb: 3, children: SKELETON_ROWS.slice(0, 3 - (idx % 2)).map((rows, i) => ((0, jsx_runtime_1.jsx)(CardSkeleton, { colors: colors, rows: rows }, i))) })] }, idx)));
496
+ const loadingSkeletonRow = Array.from({ length: 4 }).map((_, idx) => ((0, jsx_runtime_1.jsxs)(react_2.Box, { "aria-hidden": true, width: columnWidth, borderRadius: "xl", bg: colors.background[100], border: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, planeStep_1.ruleOn)(colors, colors.background[100])}`, flexShrink: 0, alignSelf: "flex-start", overflow: "hidden", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { h: "2.75rem", align: "center", gap: 2, px: 3, borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, planeStep_1.ruleOn)(colors, colors.background[100])}`, children: [(0, jsx_runtime_1.jsx)(react_2.SkeletonCircle, { size: "2.5" }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: 3, w: "40%", borderRadius: "sm" }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: 6, w: 6, ml: "auto", borderRadius: "full" })] }), (0, jsx_runtime_1.jsx)(react_2.Flex, { direction: "column", gap: 3, px: 2, pt: 1.5, pb: 3, children: SKELETON_ROWS.slice(0, 3 - (idx % 2)).map((rows, i) => ((0, jsx_runtime_1.jsx)(CardSkeleton, { colors: colors, rows: rows }, i))) })] }, idx)));
496
497
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(HeaderActions_1.default, { select: kanbanSelect, edit: canDrag ? kanbanEdit : undefined, create: canCreate ? kanbanCreate : undefined }), (0, jsx_runtime_1.jsx)(dnd_1.DragDropContext, { onDragEnd: onDragEnd, children: (0, jsx_runtime_1.jsxs)(react_2.Box, { ref: containerRef, "data-testid": "kanban-board", "aria-busy": isBoardLoading || undefined, bg: colors.backgroundColor.main, h: height !== null && height !== void 0 ? height : `${viewportHeight}px`, maxH: maxH, position: "relative", overflow: "hidden", mt: 2, children: [showAddColumn && !isBoardLoading && !hasAnyColumns && ((0, jsx_runtime_1.jsx)(react_2.Flex, { position: "absolute", inset: 0, align: "center", justify: "center", pointerEvents: "none", zIndex: 1, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", align: "center", justify: "center", gap: 2, pointerEvents: "auto", cursor: "pointer", px: 6, py: 5, borderRadius: "lg", bg: colors.background[100], border: `0.125rem dashed ${colors.boxborder[500]}`, _hover: { borderColor: colors.primary[500] }, ...addColumnKeyboard, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Plus, size: 20, color: colors.text[700] }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "sm", color: colors.text[600], children: (customizeColumn === null || customizeColumn === void 0 ? void 0 : customizeColumn.buttonText) || "Add column" })] }) })), isBoardLoading ? ((0, jsx_runtime_1.jsx)(react_2.Flex, { role: "status", "aria-label": "Loading board", gap: 4, p: 4, pb: 6, overflowX: "auto", overflowY: "hidden", height: "100%", sx: flexScrollSx, children: loadingSkeletonRow })) : enableColumnReorder ? ((0, jsx_runtime_1.jsx)(dnd_1.Droppable, { droppableId: "COLUMN_REORDER", direction: "horizontal", type: "COLUMN", children: (colReorderProvided) => ((0, jsx_runtime_1.jsxs)(react_2.Flex, { ref: colReorderProvided.innerRef, ...colReorderProvided.droppableProps, gap: 4, p: 4, pb: 6, overflowX: "auto", overflowY: "hidden", height: "100%", sx: flexScrollSx, children: [columnsList, colReorderProvided.placeholder, addColumnBox] })) })) : ((0, jsx_runtime_1.jsxs)(react_2.Flex, { gap: 4, p: 4, pb: 6, overflowX: "auto", overflowY: "hidden", height: "100%", sx: flexScrollSx, children: [columnsList, addColumnBox] }))] }) })] }));
497
498
  };
498
499
  exports.default = KanbanBoard;
@@ -9,6 +9,7 @@ const react_1 = require("@chakra-ui/react");
9
9
  const Avatar_1 = __importDefault(require("../Avatar/Avatar"));
10
10
  const useCustomTheme_1 = require("../../Theme/useCustomTheme");
11
11
  const surfaceRaised_1 = require("../../Theme/tokens/builders/surfaceRaised");
12
+ const planeStep_1 = require("../../Theme/tokens/builders/planeStep");
12
13
  const accentText_1 = require("../../Theme/tokens/builders/accentText");
13
14
  const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
14
15
  const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
@@ -54,7 +55,7 @@ function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavO
54
55
  _focus: { bg: menuHoverBg },
55
56
  _active: { bg: rowBackgrounds.selectedActive },
56
57
  };
57
- return ((0, jsx_runtime_1.jsx)(react_1.Box, { bg: theme.colors.backgroundColor.light, px: 4, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { h: 16, alignItems: "center", justifyContent: "space-between", gap: 2, children: [(0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", gap: 1.5, alignItems: "center", flex: "1 1 0%", children: [(0, jsx_runtime_1.jsx)(react_1.Box, { as: "button", type: "button", onClick: () => onSideBarToggole === null || onSideBarToggole === void 0 ? void 0 : onSideBarToggole(), onMouseEnter: onSideBarPeek, onFocus: onSideBarPeek, "aria-label": sideBarToggole ? "Close navigation menu" : "Open navigation menu", "aria-expanded": !!sideBarToggole, ...iconButtonStyle, flexShrink: 0, display: forceSideBarToggle ? "flex" : { base: "flex", lg: "none" }, w: SIDEBAR_TOGGLE_HIT, h: SIDEBAR_TOGGLE_HIT, children: sideBarToggole ? ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftClose, { size: "1.25rem" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelRightClose, { size: "1.25rem" })) }), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) && ((0, jsx_runtime_1.jsx)(react_1.Box, { ...iconButtonStyle, as: "button", type: "button", "aria-label": "Go back", display: "flex", flexShrink: 0, onClick: () => { var _a; return (_a = navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) === null || _a === void 0 ? void 0 : _a.call(navigationBarText); }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.CircleArrowLeft, { size: "1.25rem", color: theme.colors.text[500] }) })), leading && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [leading, (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": "true", mx: 2, w: "1px", h: "1.625rem", flexShrink: 0, bg: theme.colors.boxborder[200] })] })), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text) && ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: typeof navigationBarText.text === "string" ? navigationBarText.text : "", overflowOnly: true, placement: "bottom", children: (0, jsx_runtime_1.jsx)(react_1.Text, { flex: "1 1 0%", w: 0, minW: 0, isTruncated: true, color: (0, accentText_1.accentTextOnCanvas)(theme.colors.secondary, theme.colors.backgroundColor.light), fontSize: "xl", fontWeight: 600, fontFamily: "open-sans, sans-serif", letterSpacing: "-0.013rem", children: navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text }) }))] }), (0, jsx_runtime_1.jsx)(react_1.Flex, { minW: 0, flexShrink: 1, children: (0, jsx_runtime_1.jsxs)(react_1.Stack, { direction: "row", alignItems: "center", spacing: 4, minW: 0, children: [moreIcon && ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", minW: 0, sx: { "& > *": { minW: 0 } }, children: moreIcon })), (0, jsx_runtime_1.jsxs)(react_1.Menu, { children: [(0, jsx_runtime_1.jsx)(react_1.MenuButton, { as: react_1.Button, rounded: "full", variant: "link", cursor: "pointer", minW: 0, flexShrink: 0, children: (0, jsx_runtime_1.jsx)(Avatar_1.default, { size: "sm", name: userName, src: userAvathar }) }), (0, jsx_runtime_1.jsx)(react_1.MenuList, { alignItems: "center", zIndex: 5, p: 0, py: "0.375rem",
58
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { bg: theme.colors.backgroundColor.light, px: 4, borderBottom: "1px solid", borderColor: (0, planeStep_1.ruleOn)(theme.colors, theme.colors.backgroundColor.light), children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { h: 16, alignItems: "center", justifyContent: "space-between", gap: 2, children: [(0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", gap: 1.5, alignItems: "center", flex: "1 1 0%", children: [(0, jsx_runtime_1.jsx)(react_1.Box, { as: "button", type: "button", onClick: () => onSideBarToggole === null || onSideBarToggole === void 0 ? void 0 : onSideBarToggole(), onMouseEnter: onSideBarPeek, onFocus: onSideBarPeek, "aria-label": sideBarToggole ? "Close navigation menu" : "Open navigation menu", "aria-expanded": !!sideBarToggole, ...iconButtonStyle, flexShrink: 0, display: forceSideBarToggle ? "flex" : { base: "flex", lg: "none" }, w: SIDEBAR_TOGGLE_HIT, h: SIDEBAR_TOGGLE_HIT, children: sideBarToggole ? ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftClose, { size: "1.25rem" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelRightClose, { size: "1.25rem" })) }), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) && ((0, jsx_runtime_1.jsx)(react_1.Box, { ...iconButtonStyle, as: "button", type: "button", "aria-label": "Go back", display: "flex", flexShrink: 0, onClick: () => { var _a; return (_a = navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) === null || _a === void 0 ? void 0 : _a.call(navigationBarText); }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.CircleArrowLeft, { size: "1.25rem", color: theme.colors.text[500] }) })), leading && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [leading, (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": "true", mx: 2, w: "1px", h: "1.625rem", flexShrink: 0, bg: (0, planeStep_1.ruleOn)(theme.colors, theme.colors.backgroundColor.light) })] })), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text) && ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: typeof navigationBarText.text === "string" ? navigationBarText.text : "", overflowOnly: true, placement: "bottom", children: (0, jsx_runtime_1.jsx)(react_1.Text, { flex: "1 1 0%", w: 0, minW: 0, isTruncated: true, color: (0, accentText_1.accentTextOnCanvas)(theme.colors.secondary, theme.colors.backgroundColor.light), fontSize: "xl", fontWeight: 600, fontFamily: "open-sans, sans-serif", letterSpacing: "-0.013rem", children: navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text }) }))] }), (0, jsx_runtime_1.jsx)(react_1.Flex, { minW: 0, flexShrink: 1, children: (0, jsx_runtime_1.jsxs)(react_1.Stack, { direction: "row", alignItems: "center", spacing: 4, minW: 0, children: [moreIcon && ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", minW: 0, sx: { "& > *": { minW: 0 } }, children: moreIcon })), (0, jsx_runtime_1.jsxs)(react_1.Menu, { children: [(0, jsx_runtime_1.jsx)(react_1.MenuButton, { as: react_1.Button, rounded: "full", variant: "link", cursor: "pointer", minW: 0, flexShrink: 0, children: (0, jsx_runtime_1.jsx)(Avatar_1.default, { size: "sm", name: userName, src: userAvathar }) }), (0, jsx_runtime_1.jsx)(react_1.MenuList, { alignItems: "center", zIndex: 5, p: 0, py: "0.375rem",
58
59
  // Without a cap one long title stretches the whole dropdown; titles truncate instead.
59
60
  maxW: "18rem", bg: theme.colors.surfaceRaised,
60
61
  // NOTE: Chakra's MenuItem inherits --menu-bg hardcoded to #fff via dead _dark — set it or items stay white.
@@ -12,6 +12,7 @@ const accentText_1 = require("../../Theme/tokens/builders/accentText");
12
12
  const chartColorsFromTheme_1 = require("../../Theme/tokens/builders/chartColorsFromTheme");
13
13
  const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
14
14
  const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
15
+ const optionRowInk_1 = require("../Select/optionRowInk");
15
16
  const useExclusiveOverlay_1 = require("../../Hooks/useExclusiveOverlay");
16
17
  const useMatchMedia_1 = require("../../Hooks/useMatchMedia");
17
18
  const ToolTip_1 = __importDefault(require("../ToolTip/ToolTip"));
@@ -111,14 +112,11 @@ const OrgSwitcher = ({ organizations, value, onChange, isLoading = false, isSear
111
112
  }
112
113
  }, borderRadius: "lg" })] }) })), (0, jsx_runtime_1.jsxs)(react_2.Box, { role: "listbox", "aria-label": "Organizations", maxH: "320px", overflowY: "auto", py: 1, onKeyDown: handleListKeyDown, children: [filtered.map((org, idx) => {
113
114
  const isActive = org.id === value;
114
- const rowHoverBg = isActive
115
- ? rowBackgrounds.selectedActive
116
- : rowBackgrounds.active;
117
115
  return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", role: "option", "aria-selected": isActive, ref: (el) => {
118
116
  optionRefs.current[idx] = el;
119
117
  if (idx === 0)
120
118
  firstOptionRef.current = el;
121
- }, tabIndex: idx === activeIndex ? 0 : -1, align: "center", gap: "10px", w: "100%", textAlign: "left", border: "none", fontFamily: "inherit", px: 3, py: 2, cursor: "pointer", bg: isActive ? rowBackgrounds.selected : "transparent", transition: "background 0.12s ease", _hover: { bg: rowHoverBg }, onClick: () => handleSelect(org), children: [(0, jsx_runtime_1.jsx)(Avatar, { org: org, boxSize: s.avatar, fontSize: s.sub }), (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: s.font, fontWeight: isActive ? 600 : 500, color: theme.colors.text[900], overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: org.name }), showRole && org.role && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: s.sub, color: theme.colors.text[500], overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: org.role }))] }), isActive && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: 16, color: theme.colors.accentText, flexShrink: 0 }))] }, org.id));
119
+ }, tabIndex: idx === activeIndex ? 0 : -1, align: "center", gap: "10px", w: "100%", textAlign: "left", border: "none", fontFamily: "inherit", px: 3, py: 2, cursor: "pointer", bg: "transparent", transition: "background 0.12s ease", ...(0, optionRowInk_1.optionRowCursorSx)(rowBackgrounds), onClick: () => handleSelect(org), children: [(0, jsx_runtime_1.jsx)(Avatar, { org: org, boxSize: s.avatar, fontSize: s.sub }), (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: s.font, fontWeight: isActive ? 600 : 500, color: theme.colors.text[900], overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: org.name }), showRole && org.role && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: s.sub, color: theme.colors.text[500], overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: org.role }))] }), isActive && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: 16, color: theme.colors.accentText, flexShrink: 0 }))] }, org.id));
122
120
  }), filtered.length === 0 && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "sm", color: theme.colors.textMuted, textAlign: "center", py: 6, children: "No organizations found" }))] })] }) })] }));
123
121
  };
124
122
  exports.default = OrgSwitcher;
@@ -26,6 +26,7 @@ function ProfilePhotoViewer({ photoUrl, onPhotoChange, imageWidth = "100px", ima
26
26
  const fileInputRef = (0, react_1.useRef)(null);
27
27
  const theme = (0, useCustomTheme_1.useCustomTheme)();
28
28
  const c = theme.colors;
29
+ const editFill = (0, filledSurface_1.resolveFilledSurface)(c.primary, c);
29
30
  const handlePhotoChange = (event) => {
30
31
  var _a;
31
32
  if (!isEditable)
@@ -75,14 +76,14 @@ function ProfilePhotoViewer({ photoUrl, onPhotoChange, imageWidth = "100px", ima
75
76
  "&:hover .ppv-media": {
76
77
  boxShadow: `0 0 0 0.1875rem ${c.primary.opacity[24]}`,
77
78
  },
78
- }, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { className: "ppv-media", borderRadius: imageBorderRadius, transition: RING_TRANSITION, children: renderMedia() }), hasActions && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.Box, { className: "ppv-overlay", position: "absolute", inset: 0, borderRadius: imageBorderRadius, bg: hoverScrim(0.3), opacity: 0, transition: FADE_TRANSITION, pointerEvents: "none" }), (0, jsx_runtime_1.jsxs)(react_2.HStack, { className: "ppv-actions", position: "absolute", right: editIconPositionRight, bottom: editIconPositionBottom, transform: "translate(-15%, -15%)", spacing: 1.5, opacity: revealOnHover ? 0 : 1, transition: FADE_TRANSITION, children: [isEditable && ((0, jsx_runtime_1.jsx)(react_2.Tooltip, { label: "Edit", "aria-label": "Edit", hasArrow: true, children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.SquarePen, { size: 14 }), isRound: isRound, size: editIconSize, onClick: handleClick, "aria-label": "Edit photo", bg: c.primary[(0, filledSurface_1.solidFillRung)(c.primary, c.white)], color: (0, filledSurface_1.labelOnFill)(c.primary[(0, filledSurface_1.solidFillRung)(c.primary, c.white)], c.white, c.black), border: `0.125rem solid ${c.background[50]}`, boxShadow: (_b = theme.shadows) === null || _b === void 0 ? void 0 : _b.md, style: style, transition: ACTION_TRANSITION, _hover: {
79
- bg: c.primary[600],
80
- color: (0, filledSurface_1.labelOnFill)(c.primary[600], c.white, c.black),
79
+ }, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { className: "ppv-media", borderRadius: imageBorderRadius, transition: RING_TRANSITION, children: renderMedia() }), hasActions && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.Box, { className: "ppv-overlay", position: "absolute", inset: 0, borderRadius: imageBorderRadius, bg: hoverScrim(0.3), opacity: 0, transition: FADE_TRANSITION, pointerEvents: "none" }), (0, jsx_runtime_1.jsxs)(react_2.HStack, { className: "ppv-actions", position: "absolute", right: editIconPositionRight, bottom: editIconPositionBottom, transform: "translate(-15%, -15%)", spacing: 1.5, opacity: revealOnHover ? 0 : 1, transition: FADE_TRANSITION, children: [isEditable && ((0, jsx_runtime_1.jsx)(react_2.Tooltip, { label: "Edit", "aria-label": "Edit", hasArrow: true, children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.SquarePen, { size: 14 }), isRound: isRound, size: editIconSize, onClick: handleClick, "aria-label": "Edit photo", bg: editFill.fill, color: editFill.color, border: `0.125rem solid ${c.background[50]}`, boxShadow: (_b = theme.shadows) === null || _b === void 0 ? void 0 : _b.md, style: style, transition: ACTION_TRANSITION, _hover: {
80
+ bg: editFill.hoverFill,
81
+ color: editFill.hoverColor,
81
82
  transform: "scale(1.1)",
82
83
  boxShadow: (_c = theme.shadows) === null || _c === void 0 ? void 0 : _c.lg,
83
84
  }, _active: {
84
- bg: c.primary[700],
85
- color: (0, filledSurface_1.labelOnFill)(c.primary[700], c.white, c.black),
85
+ bg: editFill.activeFill,
86
+ color: editFill.activeColor,
86
87
  } }) })), isView && ((0, jsx_runtime_1.jsx)(react_2.Tooltip, { label: "View", "aria-label": "View", hasArrow: true, children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Eye, { size: 14 }), isRound: isRound, size: editIconSize, onClick: handleIsView, "aria-label": "View photo", bg: c.background[50], color: c.text[700], border: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${border}`, boxShadow: (_d = theme.shadows) === null || _d === void 0 ? void 0 : _d.md, style: style, transition: ACTION_TRANSITION, _hover: {
87
88
  bg: c.gray[50],
88
89
  color: (0, accentText_1.accentTextOnCanvas)(c.primary, c.gray[50]),
@@ -19,6 +19,7 @@ const ScrollToTop = ({ children, tooltipLabel = "Scroll to top", threshold = 300
19
19
  const [visible, setVisible] = (0, react_1.useState)(false);
20
20
  const anchorRef = (0, react_1.useRef)(null);
21
21
  const theme = (0, useCustomTheme_1.useCustomTheme)();
22
+ const fill = (0, filledSurface_1.resolveFilledSurface)(theme.colors.primary, theme.colors);
22
23
  const getScroller = () => {
23
24
  var _a, _b;
24
25
  if (useWindow)
@@ -67,9 +68,9 @@ const ScrollToTop = ({ children, tooltipLabel = "Scroll to top", threshold = 300
67
68
  };
68
69
  // eslint-disable-next-line react-hooks/exhaustive-deps
69
70
  }, [useWindow, threshold]);
70
- return ((0, jsx_runtime_1.jsxs)(react_2.Box, { ref: anchorRef, position: "relative", children: [children, (0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: tooltipLabel, placement: "left", children: (0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: scrollToTop, "aria-label": tooltipLabel, border: "none", position: "fixed", bottom: bottom, right: right, zIndex: 1000, display: "flex", alignItems: "center", justifyContent: "center", boxSize: "44px", borderRadius: "full", cursor: "pointer", bg: theme.colors.primary[(0, filledSurface_1.solidFillRung)(theme.colors.primary, theme.colors.white)], color: (0, filledSurface_1.labelOnFill)(theme.colors.primary[(0, filledSurface_1.solidFillRung)(theme.colors.primary, theme.colors.white)], theme.colors.white, theme.colors.black), boxShadow: "md", opacity: visible ? 1 : 0, transform: visible ? "translateY(0) scale(1)" : "translateY(16px) scale(0.85)", pointerEvents: visible ? "auto" : "none", transition: (0, primitives_1.transitionFor)(["opacity", "transform", "box-shadow", "background-color", "color"], "base"), _hover: {
71
- bg: theme.colors.primary[600],
72
- color: (0, filledSurface_1.labelOnFill)(theme.colors.primary[600], theme.colors.white, theme.colors.black),
71
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { ref: anchorRef, position: "relative", children: [children, (0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: tooltipLabel, placement: "left", children: (0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: scrollToTop, "aria-label": tooltipLabel, border: "none", position: "fixed", bottom: bottom, right: right, zIndex: 1000, display: "flex", alignItems: "center", justifyContent: "center", boxSize: "44px", borderRadius: "full", cursor: "pointer", bg: fill.fill, color: fill.color, boxShadow: "md", opacity: visible ? 1 : 0, transform: visible ? "translateY(0) scale(1)" : "translateY(16px) scale(0.85)", pointerEvents: visible ? "auto" : "none", transition: (0, primitives_1.transitionFor)(["opacity", "transform", "box-shadow", "background-color", "color"], "base"), _hover: {
72
+ bg: fill.hoverFill,
73
+ color: fill.hoverColor,
73
74
  transform: "translateY(-2px) scale(1.05)",
74
75
  boxShadow: "lg",
75
76
  }, _active: { transform: "scale(0.95)" }, sx: { ...(0, focusRing_styles_1.focusVisibleStyles)(theme.colors), ...(0, motion_1.reducedMotionSx)({ transform: "none" }) }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronUp, { size: 24, strokeWidth: 2.5 }) }) })] }));
@@ -79,17 +79,9 @@ const normalizeMultiValue = (val) => {
79
79
  const DECORATIVE_CHECKBOX_SX = { pointerEvents: "none", "& input": { visibility: "hidden" } };
80
80
  const OptionRow = react_1.default.memo(function OptionRow({ option, index, optionId, isSelected, isActive, isMultiple, spec, colors, rowBackgrounds, checkboxSize, onSelect, onActivate, }) {
81
81
  const singleSelected = isSelected && !isMultiple;
82
- return ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: optionId, "data-index": index, role: "option", "aria-selected": isSelected, py: spec.py, px: spec.px, minH: spec.minH, cursor: "pointer", bg: isSelected
83
- ? isActive
84
- ? rowBackgrounds.selectedActive
85
- : rowBackgrounds.selected
86
- : isActive
87
- ? rowBackgrounds.active
88
- : "transparent", _hover: {
89
- bg: isSelected ? rowBackgrounds.selectedActive : rowBackgrounds.active,
90
- }, onClick: () => onSelect(option), onMouseEnter: () => onActivate(index), display: "flex", alignItems: "center", gap: spec.gap, color: (0, optionRowInk_1.optionRowInk)(colors, singleSelected),
82
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: optionId, "data-index": index, role: "option", "aria-selected": isSelected, mx: spec.mx, py: spec.py, px: spec.px, minH: spec.minH, borderRadius: optionRowSizes_1.OPTION_ROW_RADIUS, cursor: "pointer", bg: (0, optionRowInk_1.optionRowFill)(rowBackgrounds, isActive), onClick: () => onSelect(option), onMouseEnter: () => onActivate(index), display: "flex", alignItems: "center", gap: spec.gap, color: (0, optionRowInk_1.optionRowInk)(colors, singleSelected),
91
83
  // `view` is consumer JSX with no size of its own; it inherited the 16px body font.
92
- fontSize: spec.fontSize, fontWeight: (0, optionRowInk_1.optionRowWeight)(singleSelected), borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, surfaceRaised_1.raisedRule)(colors)}`, children: [isMultiple && ((0, jsx_runtime_1.jsx)(Checkbox_1.default, { isChecked: isSelected, sx: DECORATIVE_CHECKBOX_SX, size: checkboxSize })), option.view ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: option.view })) : ((0, jsx_runtime_1.jsx)(react_2.Text, { isTruncated: true, children: option.label })), singleSelected && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: spec.iconSize, color: colors.accentText, flexShrink: 0 }))] }));
84
+ fontSize: spec.fontSize, fontWeight: (0, optionRowInk_1.optionRowWeight)(singleSelected), children: [isMultiple && ((0, jsx_runtime_1.jsx)(Checkbox_1.default, { isChecked: isSelected, sx: DECORATIVE_CHECKBOX_SX, size: checkboxSize })), option.view ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: option.view })) : ((0, jsx_runtime_1.jsx)(react_2.Text, { flex: 1, minW: 0, isTruncated: true, children: option.label })), singleSelected && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: spec.iconSize, color: colors.accentText, flexShrink: 0 }))] }));
93
85
  });
94
86
  /** Full-featured combobox: search, chips, select-all, paginated infinite scroll — not DOM-virtualized despite the `virtualization` prop. */
95
87
  /** Prefer `Select` with `native={false}` for new work — not yet a drop-in; see select-absorption-spec.md. */
@@ -656,11 +648,7 @@ const SearchSelect = ({ id, label, options, onChange, onSelect, onSearch, isOpti
656
648
  }, children: [(0, jsx_runtime_1.jsxs)(react_2.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 ? ((0, jsx_runtime_1.jsx)(SelectTruncatedLabel_1.default, { label: insideLabel, maxWidth: insideSelect.width || "6rem", fontSize: s.fieldFontSize })) : ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: s.fieldFontSize, fontWeight: 500, color: theme.colors.textMuted, isTruncated: true, maxW: insideSelect.width || "6rem", children: insidePlaceholder })), (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, color: customSelectOpen ? theme.colors.accentText : theme.colors.textMuted, transition: CHEVRON_TRANSITION, transform: customSelectOpen ? "rotate(180deg)" : "rotate(0deg)", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: s.chevronSize }) })] }), customSelectOpen && ((0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsx)(react_2.Box, { ref: setInsideSelectMenuRef, id: insideSelectPortalId, role: "listbox", "aria-label": insidePlaceholder, onKeyDown: handleInsideMenuKeyDown, onFocus: stopFocusBubbling, onBlur: stopFocusBubbling, position: "fixed", style: { top: `${customSelectPos.top}px`, left: `${customSelectPos.left}px` }, zIndex: zIndices_1.default.popoverNested, bg: theme.colors.surfaceRaised, border: `${borderWidths_1.BORDER_WIDTHS.hairline} solid`, borderColor: theme.colors.boxborder[200], borderRadius: "xl", boxShadow: theme.shadows.lg, minW: `${customSelectPos.width}px`, maxW: "20rem", py: 1, overflow: "hidden", children: (_c = insideSelect.option) === null || _c === void 0 ? void 0 : _c.map((item) => {
657
649
  var _a;
658
650
  const selected = ((_a = insideSelect.value) === null || _a === void 0 ? void 0 : _a.id) === item.id;
659
- return ((0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: spec.gap, minH: spec.minH, py: spec.py, px: spec.px, fontSize: spec.fontSize, fontWeight: (0, optionRowInk_1.optionRowWeight)(selected), color: (0, optionRowInk_1.optionRowInk)(theme.colors, selected), bg: selected ? rowBackgrounds.selected : "transparent", _hover: {
660
- bg: selected
661
- ? rowBackgrounds.selectedActive
662
- : rowBackgrounds.active,
663
- }, cursor: "pointer", role: "option", "aria-selected": selected, tabIndex: -1, _focusVisible: insideFocusRing, onClick: (e) => {
651
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: spec.gap, minH: spec.minH, py: spec.py, px: spec.px, fontSize: spec.fontSize, fontWeight: (0, optionRowInk_1.optionRowWeight)(selected), color: (0, optionRowInk_1.optionRowInk)(theme.colors, selected), bg: "transparent", ...(0, optionRowInk_1.optionRowCursorSx)(rowBackgrounds), cursor: "pointer", role: "option", "aria-selected": selected, tabIndex: -1, _focusVisible: insideFocusRing, onClick: (e) => {
664
652
  e.stopPropagation();
665
653
  handleCustomSelect(item);
666
654
  }, children: [(0, jsx_runtime_1.jsx)(react_2.Text, { isTruncated: true, children: item.label }), selected && ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { size: spec.iconSize, color: theme.colors.accentText }))] }, item.id));
@@ -699,6 +687,6 @@ const SearchSelect = ({ id, label, options, onChange, onSelect, onSearch, isOpti
699
687
  top: `${dropdownPos.top}px`,
700
688
  left: `${dropdownPos.left}px`,
701
689
  width: `${dropdownPos.width}px`,
702
- }, zIndex: zIndices_1.default.popover, maxH: "20rem", borderWidth: 1, borderColor: theme.colors.boxborder[200], borderRadius: "xl", overflow: "hidden", bg: theme.colors.surfaceRaised, boxShadow: theme.shadows.lg, display: "flex", flexDirection: "column", children: [hasSelectAllRow && ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: selectAllId, role: "option", "aria-selected": allFilteredSelected, bg: activeIndex === searchSelectNav_1.SELECT_ALL_ROW ? rowBackgrounds.active : undefined, py: spec.py, px: spec.px, minH: spec.minH, cursor: "pointer", onClick: handleSelectAll, display: "flex", alignItems: "center", gap: spec.gap, color: theme.colors.text[700], borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, surfaceRaised_1.raisedRule)(theme.colors)}`, children: [(0, jsx_runtime_1.jsx)(Checkbox_1.default, { isChecked: allFilteredSelected, sx: DECORATIVE_CHECKBOX_SX, size: s.checkboxSize }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: spec.fontSize, children: allFilteredSelected ? "Unselect All" : "Select All" })] })), (0, jsx_runtime_1.jsx)(react_2.Box, { ref: optionsListRef, flex: "1", overflowY: "auto", onScroll: handleScroll, maxH: "15rem", borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid`, borderColor: (0, surfaceRaised_1.raisedRule)(theme.colors), children: isOptionLoading && filteredOptions.length === 0 ? ((0, jsx_runtime_1.jsxs)(react_2.Box, { py: spec.py, px: spec.px, display: "flex", alignItems: "center", gap: spec.gap, minH: spec.minH, color: theme.colors.textMuted, children: [(0, jsx_runtime_1.jsx)(react_2.Spinner, { size: s.spinnerSize }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: spec.fontSize, children: loadingText })] })) : !isOptionLoading && filteredOptions.length === 0 ? ((0, jsx_runtime_1.jsx)(react_2.Text, { p: 3, fontSize: spec.fontSize, color: theme.colors.textMuted, children: "No results found" })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [filteredOptions.map((option, index) => ((0, jsx_runtime_1.jsx)(OptionRow, { option: option, index: index, optionId: getOptionId(index), isSelected: isSelected(option.id), isActive: index === activeIndex, isMultiple: isMultiple, spec: spec, colors: theme.colors, rowBackgrounds: rowBackgrounds, checkboxSize: s.checkboxSize, onSelect: selectOption, onActivate: setActiveIndex }, option.id))), ((pagination === null || pagination === void 0 ? void 0 : pagination.scrollLoading) || (isOptionLoading && filteredOptions.length > 0)) && ((0, jsx_runtime_1.jsxs)(react_2.Box, { py: spec.py, px: spec.px, display: "flex", alignItems: "center", justifyContent: "center", gap: spec.gap, minH: spec.minH, color: theme.colors.textMuted, children: [(0, jsx_runtime_1.jsx)(react_2.Spinner, { size: s.spinnerSize }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: spec.fontSize, children: loadingText })] }))] })) }), (addNew === null || addNew === void 0 ? void 0 : addNew.enabled) && ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: addNewId, role: "option", "aria-selected": false, py: spec.py, px: spec.px, borderTop: `${borderWidths_1.BORDER_WIDTHS.hairline} solid`, borderColor: (0, surfaceRaised_1.raisedRule)(theme.colors), bg: activeIndex === searchSelectNav_1.ADD_NEW_ROW ? rowBackgrounds.active : theme.colors.surfaceRaised, display: "flex", alignItems: "center", gap: spec.gap, color: theme.colors.accentText, fontWeight: 500, minH: spec.minH, cursor: "pointer", onClick: addNew.onClick, _hover: { bg: rowBackgrounds.active }, children: [addNew.icon || (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: s.addNewIconSize }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: spec.fontSize, children: addNew.text || "Add New" })] }))] }) })), (0, jsx_runtime_1.jsx)(FieldMessage_1.default, { error: error, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId })] }));
690
+ }, zIndex: zIndices_1.default.popover, maxH: "20rem", borderWidth: 1, borderColor: theme.colors.boxborder[200], borderRadius: "xl", overflow: "hidden", bg: theme.colors.surfaceRaised, boxShadow: theme.shadows.lg, display: "flex", flexDirection: "column", children: [hasSelectAllRow && ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: selectAllId, role: "option", "aria-selected": allFilteredSelected, bg: activeIndex === searchSelectNav_1.SELECT_ALL_ROW ? rowBackgrounds.active : undefined, py: spec.py, px: spec.px, minH: spec.minH, cursor: "pointer", onClick: handleSelectAll, display: "flex", alignItems: "center", gap: spec.gap, color: theme.colors.text[700], borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, surfaceRaised_1.raisedRule)(theme.colors)}`, children: [(0, jsx_runtime_1.jsx)(Checkbox_1.default, { isChecked: allFilteredSelected, sx: DECORATIVE_CHECKBOX_SX, size: s.checkboxSize }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: spec.fontSize, children: allFilteredSelected ? "Unselect All" : "Select All" })] })), (0, jsx_runtime_1.jsx)(react_2.Box, { ref: optionsListRef, flex: "1", overflowY: "auto", onScroll: handleScroll, maxH: "15rem", py: 1, borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid`, borderColor: (0, surfaceRaised_1.raisedRule)(theme.colors), children: isOptionLoading && filteredOptions.length === 0 ? ((0, jsx_runtime_1.jsxs)(react_2.Box, { py: spec.py, px: spec.px, display: "flex", alignItems: "center", gap: spec.gap, minH: spec.minH, color: theme.colors.textMuted, children: [(0, jsx_runtime_1.jsx)(react_2.Spinner, { size: s.spinnerSize }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: spec.fontSize, children: loadingText })] })) : !isOptionLoading && filteredOptions.length === 0 ? ((0, jsx_runtime_1.jsx)(react_2.Text, { p: 3, fontSize: spec.fontSize, color: theme.colors.textMuted, children: "No results found" })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [filteredOptions.map((option, index) => ((0, jsx_runtime_1.jsx)(OptionRow, { option: option, index: index, optionId: getOptionId(index), isSelected: isSelected(option.id), isActive: index === activeIndex, isMultiple: isMultiple, spec: spec, colors: theme.colors, rowBackgrounds: rowBackgrounds, checkboxSize: s.checkboxSize, onSelect: selectOption, onActivate: setActiveIndex }, option.id))), ((pagination === null || pagination === void 0 ? void 0 : pagination.scrollLoading) || (isOptionLoading && filteredOptions.length > 0)) && ((0, jsx_runtime_1.jsxs)(react_2.Box, { py: spec.py, px: spec.px, display: "flex", alignItems: "center", justifyContent: "center", gap: spec.gap, minH: spec.minH, color: theme.colors.textMuted, children: [(0, jsx_runtime_1.jsx)(react_2.Spinner, { size: s.spinnerSize }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: spec.fontSize, children: loadingText })] }))] })) }), (addNew === null || addNew === void 0 ? void 0 : addNew.enabled) && ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: addNewId, role: "option", "aria-selected": false, py: spec.py, px: spec.px, borderTop: `${borderWidths_1.BORDER_WIDTHS.hairline} solid`, borderColor: (0, surfaceRaised_1.raisedRule)(theme.colors), bg: activeIndex === searchSelectNav_1.ADD_NEW_ROW ? rowBackgrounds.active : theme.colors.surfaceRaised, display: "flex", alignItems: "center", gap: spec.gap, color: theme.colors.accentText, fontWeight: 500, minH: spec.minH, cursor: "pointer", onClick: addNew.onClick, _hover: { bg: rowBackgrounds.active }, children: [addNew.icon || (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: s.addNewIconSize }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: spec.fontSize, children: addNew.text || "Add New" })] }))] }) })), (0, jsx_runtime_1.jsx)(FieldMessage_1.default, { error: error, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId })] }));
703
691
  };
704
692
  exports.default = SearchSelect;
@@ -74,9 +74,7 @@ const parseRemToPx = (value, fallbackPx) => {
74
74
  };
75
75
  const OptionRow = react_1.default.memo(function OptionRow({ option, index, listboxId, isSelected, isActive, isMulti, theme, backgrounds, spec, renderOption, onSelect, onActivate, }) {
76
76
  const isSingleSelected = isSelected && !isMulti;
77
- const selectedBg = isActive ? backgrounds.selectedActive : backgrounds.selected;
78
- const restBg = isActive ? backgrounds.active : "transparent";
79
- return ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: optionDomId(listboxId, option.id), "data-index": index, role: "option", "aria-selected": isSelected, "aria-disabled": option.isDisabled, onMouseEnter: () => onActivate(index), onClick: () => onSelect(option), mx: spec.mx, px: spec.px, py: spec.py, minH: spec.minH, borderRadius: "md", cursor: option.isDisabled ? "not-allowed" : "pointer", opacity: option.isDisabled ? 0.4 : 1, display: "flex", alignItems: "center", gap: spec.gap, fontSize: spec.fontSize, fontWeight: (0, optionRowInk_1.optionRowWeight)(isSingleSelected), color: (0, optionRowInk_1.optionRowInk)(theme.colors, isSingleSelected), bg: isSingleSelected ? selectedBg : restBg, transition: ROW_TRANSITION, sx: (0, motion_2.reducedMotionSx)(), children: [isMulti ? ((0, jsx_runtime_1.jsx)(react_2.Checkbox, { id: `${optionDomId(listboxId, option.id)}-checkbox`, isChecked: isSelected, isDisabled: option.isDisabled, pointerEvents: "none", tabIndex: -1, sx: DECORATIVE_CHECKBOX_SX })) : null, renderOption ? ((0, jsx_runtime_1.jsx)(react_2.Box, { flex: 1, minW: 0, children: renderOption(option, { isSelected, isActive }) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [option.icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: option.icon })) : null, (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: 1, minW: 0, isTruncated: true, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: option.label }), option.description ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "block", fontSize: spec.descriptionFontSize, color: (0, optionRowInk_1.optionRowDescriptionInk)(theme.colors), isTruncated: true, children: option.description })) : null] })] })), isSingleSelected ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: spec.iconSize, color: theme.colors.accentText, flexShrink: 0 })) : null] }));
77
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: optionDomId(listboxId, option.id), "data-index": index, role: "option", "aria-selected": isSelected, "aria-disabled": option.isDisabled, onMouseEnter: () => onActivate(index), onClick: () => onSelect(option), mx: spec.mx, px: spec.px, py: spec.py, minH: spec.minH, borderRadius: "md", cursor: option.isDisabled ? "not-allowed" : "pointer", opacity: option.isDisabled ? 0.4 : 1, display: "flex", alignItems: "center", gap: spec.gap, fontSize: spec.fontSize, fontWeight: (0, optionRowInk_1.optionRowWeight)(isSingleSelected), color: (0, optionRowInk_1.optionRowInk)(theme.colors, isSingleSelected), bg: (0, optionRowInk_1.optionRowFill)(backgrounds, isActive), transition: ROW_TRANSITION, sx: (0, motion_2.reducedMotionSx)(), children: [isMulti ? ((0, jsx_runtime_1.jsx)(react_2.Checkbox, { id: `${optionDomId(listboxId, option.id)}-checkbox`, isChecked: isSelected, isDisabled: option.isDisabled, pointerEvents: "none", tabIndex: -1, sx: DECORATIVE_CHECKBOX_SX })) : null, renderOption ? ((0, jsx_runtime_1.jsx)(react_2.Box, { flex: 1, minW: 0, children: renderOption(option, { isSelected, isActive }) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [option.icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: option.icon })) : null, (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: 1, minW: 0, isTruncated: true, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: option.label }), option.description ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "block", fontSize: spec.descriptionFontSize, color: (0, optionRowInk_1.optionRowDescriptionInk)(theme.colors), isTruncated: true, children: option.description })) : null] })] })), isSingleSelected ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: spec.iconSize, color: theme.colors.accentText, flexShrink: 0 })) : null] }));
80
78
  });
81
79
  const buildGroupedRows = (options) => {
82
80
  const rows = [];