@crewlethq/ui 0.4.3 → 0.4.4

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 (50) hide show
  1. package/dist/Combobox/index.js +3 -3
  2. package/dist/CommandPalette/index.js +3 -3
  3. package/dist/DataTable/index.js +4 -4
  4. package/dist/{DataTable-ITNACQ2X.css → DataTable-37UWTRN6.css} +9 -5
  5. package/dist/DataView/index.js +10 -10
  6. package/dist/DateTimePicker/index.js +2 -2
  7. package/dist/DiffList/index.js +1 -1
  8. package/dist/Input/index.js +1 -1
  9. package/dist/ListInput/index.js +3 -3
  10. package/dist/Listbox/index.js +1 -1
  11. package/dist/Listbox/useListbox.d.ts +14 -0
  12. package/dist/Listbox/useOptionKeys.d.ts +12 -1
  13. package/dist/{Listbox-X2DOTSQA.css → Listbox-ZXYYNN6U.css} +28 -0
  14. package/dist/Menu/index.js +1 -1
  15. package/dist/{Menu-6DE7I66I.css → Menu-BT5PMFJI.css} +15 -0
  16. package/dist/Popover/index.js +1 -1
  17. package/dist/SegmentedControl/index.js +2 -2
  18. package/dist/Select/index.js +2 -2
  19. package/dist/{Select-2X77FSWR.css → Select-E24U5LBC.css} +34 -0
  20. package/dist/Table/index.js +1 -1
  21. package/dist/{Table-MDOLVUAW.css → Table-TGCS4C3F.css} +14 -4
  22. package/dist/Tabs/index.js +1 -1
  23. package/dist/{Tabs-VLICJFVB.css → Tabs-MJ2E3VPK.css} +33 -1
  24. package/dist/TagsInput/index.js +3 -3
  25. package/dist/ThemeSwitcher/index.js +3 -3
  26. package/dist/TimeWindowPicker/index.js +5 -5
  27. package/dist/Tooltip/index.js +1 -1
  28. package/dist/{chunk-XV6WRMBC.js → chunk-5KSRXHOW.js} +3 -0
  29. package/dist/{chunk-BJSKPEZI.js → chunk-6KCO2D5C.js} +2 -2
  30. package/dist/{chunk-6ZFVFA56.js → chunk-7PEFUMQJ.js} +2 -2
  31. package/dist/{chunk-ESCO4XYW.js → chunk-AJNCATWZ.js} +2 -2
  32. package/dist/{chunk-HQNHV7D6.js → chunk-AQTBF4EB.js} +1 -1
  33. package/dist/{chunk-34VGEDVV.js → chunk-CC67MUUO.js} +8 -8
  34. package/dist/{chunk-UG46QBLT.js → chunk-DB2VDLVR.js} +1 -1
  35. package/dist/{chunk-DD5BBGBE.js → chunk-EFSG7HNU.js} +8 -4
  36. package/dist/{chunk-LFJ6UJTI.js → chunk-FSOW3ARP.js} +2 -2
  37. package/dist/{chunk-O6232G37.js → chunk-GKHAKGOF.js} +14 -2
  38. package/dist/{chunk-GTOUGQQK.js → chunk-KIC7BZYJ.js} +8 -6
  39. package/dist/{chunk-OFHBK7RI.js → chunk-KNYYCWMK.js} +31 -11
  40. package/dist/{chunk-UOGSZKLT.js → chunk-MW356IVK.js} +2 -2
  41. package/dist/{chunk-WQX73TWF.js → chunk-PATXSJGR.js} +5 -4
  42. package/dist/{chunk-QEUY3A5P.js → chunk-Q3B66TJM.js} +3 -2
  43. package/dist/{chunk-2HQR4U4D.js → chunk-R66KLW7S.js} +1 -1
  44. package/dist/{chunk-FBZAKNSX.js → chunk-T43A26SD.js} +4 -1
  45. package/dist/{chunk-FEFTGVMF.js → chunk-V2N3BMOT.js} +7 -2
  46. package/dist/{chunk-WOYYD2YR.js → chunk-XJWXPRSK.js} +3 -3
  47. package/dist/generated/index.js +31 -31
  48. package/dist/index.js +31 -31
  49. package/dist/styles.css +139 -16
  50. package/package.json +3 -3
@@ -1,6 +1,6 @@
1
- export { Combobox } from '../chunk-UOGSZKLT.js';
2
- import '../chunk-GTOUGQQK.js';
3
- import '../chunk-O6232G37.js';
1
+ export { Combobox } from '../chunk-MW356IVK.js';
2
+ import '../chunk-KIC7BZYJ.js';
3
+ import '../chunk-GKHAKGOF.js';
4
4
  import '../chunk-PQADV6P6.js';
5
5
  import '../chunk-ITHXJHBB.js';
6
6
  import '../chunk-F27EPQ7D.js';
@@ -1,7 +1,7 @@
1
- export { CommandPalette } from '../chunk-ESCO4XYW.js';
1
+ export { CommandPalette } from '../chunk-AJNCATWZ.js';
2
+ import '../chunk-KIC7BZYJ.js';
3
+ import '../chunk-GKHAKGOF.js';
2
4
  import '../chunk-2EOKFKHX.js';
3
- import '../chunk-GTOUGQQK.js';
4
- import '../chunk-O6232G37.js';
5
5
  import '../chunk-PQADV6P6.js';
6
6
  import '../chunk-7RPGY3JE.js';
7
7
  import '../chunk-ITHXJHBB.js';
@@ -1,10 +1,10 @@
1
- export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-WQX73TWF.js';
2
- import '../chunk-FBZAKNSX.js';
1
+ export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-PATXSJGR.js';
2
+ import '../chunk-T43A26SD.js';
3
3
  import '../chunk-EUCC37WY.js';
4
- import '../chunk-2EOKFKHX.js';
5
- import '../chunk-AV2DXAEL.js';
6
4
  import '../chunk-2PRH365R.js';
5
+ import '../chunk-AV2DXAEL.js';
7
6
  import '../chunk-5VNUYO76.js';
7
+ import '../chunk-2EOKFKHX.js';
8
8
  import '../chunk-PQADV6P6.js';
9
9
  import '../chunk-7RPGY3JE.js';
10
10
  import '../chunk-ITHXJHBB.js';
@@ -16,11 +16,15 @@
16
16
  --crewlet-data-table-active-sort-color: var(--color-brand-accent-ink);
17
17
  width: 100%;
18
18
  position: relative;
19
- overflow-x: auto;
20
- /* The gesture stops at the table's own edge. Without it a trackpad swipe
21
- that runs out of table carries on into the browser's back navigation, so
22
- one column too far left loses the page. */
23
- overscroll-behavior-x: contain;
19
+ /* NO SCROLLER HERE. This carried `overflow-x: auto` and its own
20
+ `overscroll-behavior-x`, and neither could act: `.crewlet-data-table__scroll`
21
+ is rendered inside it for BOTH variants at `width: 100%`, so it absorbs
22
+ the table's width and the root never has anything to scroll. What the
23
+ declaration did still do is make this a scroll container — and per CSS
24
+ Overflow that pulls `overflow-y` to `auto` as well — so it quietly became
25
+ the scrollport a `position: sticky` descendant resolves against. The inner
26
+ wrapper carries the real scrolling and the gesture containment, which is
27
+ what the layout comment further down already describes. */
24
28
  }
25
29
 
26
30
  .crewlet-data-table--default .crewlet-data-table__table {
@@ -1,20 +1,20 @@
1
- export { DATA_VIEW_TOOLBAR_LABELS, DataView, DataViewToolbar, FILTER_AXIS_LABELS, FilterAxisBar, FilterAxisChip, applyColumnFilters, applyFilters, blankFilterValue, defaultOperator, filterDefsFromColumns, filterHasValue, filterPredicate, formatFilterValue, operatorOf, tableColumns } from '../chunk-34VGEDVV.js';
1
+ export { DATA_VIEW_TOOLBAR_LABELS, DataView, DataViewToolbar, FILTER_AXIS_LABELS, FilterAxisBar, FilterAxisChip, applyColumnFilters, applyFilters, blankFilterValue, defaultOperator, filterDefsFromColumns, filterHasValue, filterPredicate, formatFilterValue, operatorOf, tableColumns } from '../chunk-CC67MUUO.js';
2
2
  import '../chunk-5EKIWVOR.js';
3
- import '../chunk-HOXGBLEY.js';
4
3
  import '../chunk-3CZ7XAVY.js';
4
+ import '../chunk-HOXGBLEY.js';
5
5
  import '../chunk-SFZOKW2G.js';
6
- import '../chunk-WQX73TWF.js';
7
- import '../chunk-FBZAKNSX.js';
6
+ import '../chunk-PATXSJGR.js';
7
+ import '../chunk-T43A26SD.js';
8
8
  import '../chunk-EUCC37WY.js';
9
- import '../chunk-2EOKFKHX.js';
10
- import '../chunk-UG46QBLT.js';
11
- import '../chunk-DD5BBGBE.js';
9
+ import '../chunk-DB2VDLVR.js';
10
+ import '../chunk-EFSG7HNU.js';
12
11
  import '../chunk-GXQ3B46I.js';
13
- import '../chunk-AV2DXAEL.js';
14
12
  import '../chunk-2PRH365R.js';
13
+ import '../chunk-AV2DXAEL.js';
15
14
  import '../chunk-5VNUYO76.js';
16
- import '../chunk-GTOUGQQK.js';
17
- import '../chunk-O6232G37.js';
15
+ import '../chunk-KIC7BZYJ.js';
16
+ import '../chunk-GKHAKGOF.js';
17
+ import '../chunk-2EOKFKHX.js';
18
18
  import '../chunk-BHHIIK3M.js';
19
19
  import '../chunk-PQADV6P6.js';
20
20
  import '../chunk-7RPGY3JE.js';
@@ -1,5 +1,5 @@
1
- export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-UG46QBLT.js';
2
- import '../chunk-DD5BBGBE.js';
1
+ export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-DB2VDLVR.js';
2
+ import '../chunk-EFSG7HNU.js';
3
3
  import '../chunk-GXQ3B46I.js';
4
4
  import '../chunk-7RPGY3JE.js';
5
5
  import '../chunk-ITHXJHBB.js';
@@ -1,3 +1,3 @@
1
- export { DIFF_LIST_LABELS, DiffList } from '../chunk-HQNHV7D6.js';
1
+ export { DIFF_LIST_LABELS, DiffList } from '../chunk-AQTBF4EB.js';
2
2
  import '../chunk-BZFWDIV6.js';
3
3
  import '../chunk-ODEQTPFM.js';
@@ -1,4 +1,4 @@
1
- export { FormField, FormRow, FormSection, Input, InputAffix, Label, ReadOnlyField, Textarea } from '../chunk-O6232G37.js';
1
+ export { FormField, FormRow, FormSection, Input, InputAffix, Label, ReadOnlyField, Textarea } from '../chunk-GKHAKGOF.js';
2
2
  import '../chunk-PQADV6P6.js';
3
3
  import '../chunk-F27EPQ7D.js';
4
4
  import '../chunk-BZFWDIV6.js';
@@ -1,10 +1,10 @@
1
- export { ListInput } from '../chunk-LFJ6UJTI.js';
1
+ export { ListInput } from '../chunk-FSOW3ARP.js';
2
2
  import '../chunk-SFZOKW2G.js';
3
- import '../chunk-O6232G37.js';
3
+ import '../chunk-GKHAKGOF.js';
4
4
  import '../chunk-PQADV6P6.js';
5
- import '../chunk-RSAQOKH3.js';
6
5
  import '../chunk-7RPGY3JE.js';
7
6
  import '../chunk-ITHXJHBB.js';
8
7
  import '../chunk-F27EPQ7D.js';
8
+ import '../chunk-RSAQOKH3.js';
9
9
  import '../chunk-BZFWDIV6.js';
10
10
  import '../chunk-ODEQTPFM.js';
@@ -1,2 +1,2 @@
1
- export { TYPE_AHEAD_WINDOW, useListbox, useOptionKeys } from '../chunk-GTOUGQQK.js';
1
+ export { TYPE_AHEAD_WINDOW, useListbox, useOptionKeys } from '../chunk-KIC7BZYJ.js';
2
2
  import '../chunk-ITHXJHBB.js';
@@ -82,6 +82,20 @@ export interface Listbox {
82
82
  listId: string;
83
83
  /** The list on screen: what a press outside is measured against, and what scrolls. */
84
84
  listRef: (el: HTMLElement | null) => void;
85
+ /**
86
+ * THE SURFACE, where it is bigger than the list — and a consumer uses this
87
+ * OR `listRef`, never both.
88
+ *
89
+ * `listRef` does two jobs because for most consumers one element does both:
90
+ * the list is what scrolls AND what a press outside is measured against. A
91
+ * popup that carries anything beside its list breaks that: a Select with
92
+ * `searchable` puts a search box in the panel as a SIBLING of the list, so a
93
+ * press on it was measured against the list, came out `outside`, and
94
+ * dismissed the popup the reader was trying to type into — the control could
95
+ * not be used with a pointer at all. Naming the surface separately is what
96
+ * keeps the two questions apart.
97
+ */
98
+ panelRef: (el: HTMLElement | null) => void;
85
99
  /** The element around the field: a press on it is not outside the list. */
86
100
  anchorRef: (el: HTMLElement | null) => void;
87
101
  /** The id of the option element at `index`. */
@@ -44,6 +44,17 @@ export interface OptionKeysOptions {
44
44
  * letters belong to a search box: that list has no type-ahead, on purpose.
45
45
  */
46
46
  textOf?: ((index: number) => string) | undefined;
47
+ /**
48
+ * Whether Home and End move the HIGHLIGHT. True by default, and false for a
49
+ * list whose field is editable, where they belong to the caret.
50
+ *
51
+ * The same split `textOf` makes, for the same reason. WAI-ARIA states it
52
+ * outright for a combobox with a listbox popup: Home and End move visual
53
+ * focus in the list only when the combobox is NOT editable; when it is, they
54
+ * are the text's. This hook cannot tell — its whole input is a count, a
55
+ * disabled predicate and some strings — so the component that knows says so.
56
+ */
57
+ ends?: boolean | undefined;
47
58
  }
48
59
  export interface OptionKeys {
49
60
  /**
@@ -61,4 +72,4 @@ export interface OptionKeys {
61
72
  */
62
73
  opening: (chosen: number) => number;
63
74
  }
64
- export declare function useOptionKeys({ listbox, count, disabled, textOf }: OptionKeysOptions): OptionKeys;
75
+ export declare function useOptionKeys({ listbox, count, disabled, textOf, ends }: OptionKeysOptions): OptionKeys;
@@ -32,6 +32,29 @@
32
32
  display: flex;
33
33
  align-items: center;
34
34
  gap: var(--spacing-2);
35
+ /*
36
+ * A ROW IS NEVER SHRUNK BELOW ITS OWN CONTENT, and `flex: none` is what says
37
+ * so. The list above is a column flex container with a `max-height` and
38
+ * `overflow-y: auto`, which makes every row a flex ITEM, and a flex item's
39
+ * automatic minimum size is normally its content — that is what stops a
40
+ * column from compressing its children and makes the container scroll
41
+ * instead. The `min-height` below REPLACES that automatic minimum with a
42
+ * fixed floor, so once the rows no longer fit, the free space goes negative
43
+ * and every row shrinks to exactly that floor BEFORE the scrollbar appears.
44
+ * A row is `overflow: visible`, so its content then paints over its
45
+ * neighbours.
46
+ *
47
+ * It is not a corner case: a row is 19.5px of text plus 16px of padding =
48
+ * 35.5px against a 28px floor, so EVERY row of a list long enough to scroll
49
+ * was over-tall. Measured in Chromium on a nine-option Select — five rows
50
+ * drawn over each other, two of them at 59px inside a 28px box.
51
+ *
52
+ * `flex: none` is `0 0 auto`: the basis stays content-derived and the row
53
+ * can no longer shrink, which leaves `min-height` doing the one job it was
54
+ * written for — a floor under a SHORT row, not a cap on a tall one. The
55
+ * scroller absorbs the excess, one row deep, which is what it is for.
56
+ */
57
+ flex: none;
35
58
  min-height: var(--size-row-sm);
36
59
  padding: var(--spacing-2) var(--spacing-3);
37
60
  border-radius: var(--radius-md);
@@ -103,7 +126,12 @@
103
126
  font-size: var(--font-size-compact);
104
127
  }
105
128
 
129
+ /* AND NEITHER IS THE SEPARATOR, for the same reason one step further: its
130
+ content minimum is zero, so it is the one child a squeezed column can
131
+ flatten completely — exactly when the list is long enough to need the
132
+ grouping it draws. */
106
133
  .crewlet-listbox__separator {
134
+ flex: none;
107
135
  height: 1px;
108
136
  margin: var(--spacing-1) 0;
109
137
  background: var(--color-border-default);
@@ -1,4 +1,4 @@
1
- export { Menu } from '../chunk-FBZAKNSX.js';
1
+ export { Menu } from '../chunk-T43A26SD.js';
2
2
  import '../chunk-7RPGY3JE.js';
3
3
  import '../chunk-ITHXJHBB.js';
4
4
  import '../chunk-F27EPQ7D.js';
@@ -70,6 +70,21 @@
70
70
  align-items: center;
71
71
  gap: var(--spacing-2);
72
72
  width: 100%;
73
+ /*
74
+ * THE SAME RULE THE LISTBOX ROW STATES, and it has to be stated twice
75
+ * because a menu's rows are deliberately not in that family (see the head of
76
+ * Listbox.css). The panel above is a column flex scroller, `__group` is
77
+ * `display: contents` so every item is a direct flex item of it, and the
78
+ * `min-height` below replaces the automatic minimum that would otherwise
79
+ * hold a row at its content. Once the menu is long enough to scroll, the
80
+ * free space goes negative and the rows shrink to that floor first.
81
+ *
82
+ * A plain row survives it by accident — one nowrap line is 19.5px, under the
83
+ * floor, so there is nothing to shrink. A `--described` row does not: it
84
+ * adds `padding-block` and stacks a label over a wrapping description, which
85
+ * is ~52px squeezed into 28px and drawn over the rows either side.
86
+ */
87
+ flex: none;
73
88
  min-height: var(--size-row-sm);
74
89
  padding: 0 var(--spacing-2);
75
90
  border: none;
@@ -1,4 +1,4 @@
1
- export { Popover } from '../chunk-DD5BBGBE.js';
1
+ export { Popover } from '../chunk-EFSG7HNU.js';
2
2
  import '../chunk-7RPGY3JE.js';
3
3
  import '../chunk-ITHXJHBB.js';
4
4
  import '../chunk-ODEQTPFM.js';
@@ -1,5 +1,5 @@
1
- export { SegmentedControl } from '../chunk-6ZFVFA56.js';
2
- import '../chunk-QEUY3A5P.js';
1
+ export { SegmentedControl } from '../chunk-7PEFUMQJ.js';
2
+ import '../chunk-Q3B66TJM.js';
3
3
  import '../chunk-BHHIIK3M.js';
4
4
  import '../chunk-BZFWDIV6.js';
5
5
  import '../chunk-ODEQTPFM.js';
@@ -1,5 +1,5 @@
1
- export { Select } from '../chunk-OFHBK7RI.js';
2
- import '../chunk-GTOUGQQK.js';
1
+ export { Select } from '../chunk-KNYYCWMK.js';
2
+ import '../chunk-KIC7BZYJ.js';
3
3
  import '../chunk-7RPGY3JE.js';
4
4
  import '../chunk-ITHXJHBB.js';
5
5
  import '../chunk-ODEQTPFM.js';
@@ -297,9 +297,25 @@ svg.crewlet-select__chevron {
297
297
  min-width: 0;
298
298
  }
299
299
 
300
+ /*
301
+ * ONE LINE, WHICH IS WHAT THE ELLIPSIS BELOW WAS ALWAYS FOR. `overflow:
302
+ * hidden` clips what leaves the box and `text-overflow` replaces what a LINE
303
+ * cannot hold — and neither does anything to text that is simply allowed to
304
+ * wrap, which is what this rule did without `white-space`. A long option
305
+ * silently grew a second line instead of ellipsing, and with the row's own
306
+ * flex minimum gone (see Listbox.css) that second line was drawn over the
307
+ * option underneath.
308
+ *
309
+ * The trigger's `.crewlet-select__label` a hundred lines above has carried all
310
+ * three since it was written; this is the same register on the same text, and
311
+ * `.crewlet-listbox__hint` states the rule outright — "never wrapped: a hint
312
+ * that broke across two lines turned every row in the list a different
313
+ * height".
314
+ */
300
315
  .crewlet-select__option-label {
301
316
  overflow: hidden;
302
317
  text-overflow: ellipsis;
318
+ white-space: nowrap;
303
319
  }
304
320
 
305
321
  .crewlet-select__option-desc {
@@ -317,6 +333,24 @@ svg.crewlet-select__chevron {
317
333
 
318
334
  /* ── The search box ──────────────────────────────────────────────────── */
319
335
 
336
+ /*
337
+ * THE RING IS DRAWN WHERE THE ELEMENT IS. The input below clears the user
338
+ * agent's outline, and the frame's `:focus-within` rule is the package's one
339
+ * replacement for it — but that rule's own premise is that everything
340
+ * focusable sits INSIDE `.crewlet-select`, and this box does not: the panel is
341
+ * portalled into the layer host, outside that subtree, so `:focus-within`
342
+ * could never match while focus was in the search field. And focus is moved
343
+ * here on every open, so the one control a searchable Select puts a reader in
344
+ * was the one with no focus indicator at all.
345
+ *
346
+ * On the band rather than the input, and INSET, because the panel clips: an
347
+ * outset ring on the input would be cut by the menu's own `overflow: hidden`.
348
+ */
349
+ .crewlet-select__search:focus-within {
350
+ outline: 2px solid var(--color-focus);
351
+ outline-offset: var(--size-focus-ring-inset-offset);
352
+ }
353
+
320
354
  .crewlet-select__search {
321
355
  display: flex;
322
356
  align-items: center;
@@ -1,3 +1,3 @@
1
- export { Table } from '../chunk-FEFTGVMF.js';
1
+ export { Table } from '../chunk-V2N3BMOT.js';
2
2
  import '../chunk-BZFWDIV6.js';
3
3
  import '../chunk-ODEQTPFM.js';
@@ -29,10 +29,20 @@
29
29
  .crewlet-table__container {
30
30
  /* The overflow is a safety net for a cell that cannot wrap (a long token, a
31
31
  hash); the fixed layout below is what keeps a table inside the width it is
32
- given. A `maxHeight` turns this into the vertical scroller the sticky
33
- header needs, which is the only way a long table keeps its column names. */
34
- overflow-x: auto;
35
- overflow-y: var(--crewlet-table-overflow-y, visible);
32
+ given. A `maxHeight` gives it something to scroll vertically, which is
33
+ what the sticky header needs and the only way a long table keeps its
34
+ column names.
35
+
36
+ BOTH AXES, STATED. This was `overflow-y: var(--crewlet-table-overflow-y,
37
+ visible)`, and the fallback was unreachable: per CSS Overflow, when one
38
+ axis is not `visible` the other computes to `auto`, so the unconditional
39
+ `overflow-x: auto` beside it made this box a scrollport in both
40
+ directions in every state. The variable had exactly one reachable value —
41
+ the `auto` Table.tsx wrote beside the max-height — so it read as a knob
42
+ with a default nothing could ever select. Without a max-height there is
43
+ simply nothing to scroll to, which is what made the difference invisible
44
+ rather than what made it absent. */
45
+ overflow: auto;
36
46
  max-height: var(--crewlet-table-max-height, none);
37
47
  overscroll-behavior-x: contain;
38
48
  flex: 1;
@@ -1,4 +1,4 @@
1
- export { TabPanel, Tabs, tabId } from '../chunk-QEUY3A5P.js';
1
+ export { TabPanel, Tabs, tabId } from '../chunk-Q3B66TJM.js';
2
2
  import '../chunk-BHHIIK3M.js';
3
3
  import '../chunk-BZFWDIV6.js';
4
4
  import '../chunk-ODEQTPFM.js';
@@ -50,7 +50,21 @@
50
50
  */
51
51
  content: '';
52
52
  position: absolute;
53
- bottom: -1px;
53
+ /*
54
+ * ON THE PADDING EDGE, NOT BELOW IT. This is an absolutely positioned child
55
+ * of the row, and the row is a scroll container: `overflow-x: auto` makes
56
+ * `overflow-y` compute to `auto` as well, so there is no axis on which it
57
+ * does not clip. Clipping is to the PADDING edge and the row's own 1px
58
+ * `border-bottom` lies outside it, so at `bottom: -1px` a 2px bar was cut in
59
+ * half — and the half removed was the lower one, the half meant to sit on
60
+ * the baseline rule and replace it. `scrollbar-width: none` above then hid
61
+ * the 1px vertical scrollbar that would have given the game away.
62
+ *
63
+ * `overflow: visible` is not the way out: the horizontal scrolling is the
64
+ * row's whole contract. The bar sits at 0 instead and paints over the row's
65
+ * last two pixels, which is where a reader sees it anyway.
66
+ */
67
+ bottom: 0;
54
68
  /*
55
69
  * Under the LABEL, not under the tab's box: the measurement is the button,
56
70
  * which carries the small side pad an inset focus ring needs, and a bar
@@ -108,6 +122,24 @@
108
122
  align-items: center;
109
123
  justify-content: center;
110
124
  gap: var(--spacing-1);
125
+ /*
126
+ * A TAB IS NEVER SQUEEZED, which is what makes the row above it SCROLL.
127
+ *
128
+ * `.crewlet-tabs--underline` is a `width: 100%` flex row with
129
+ * `overflow-x: auto`, and its own comment states the contract: the row
130
+ * scrolls rather than overflowing the page. That behaviour came entirely
131
+ * from each tab's automatic minimum resolving to its `nowrap` label, which
132
+ * is what makes the line unable to fit — and the explicit `min-width` below
133
+ * REPLACES that automatic minimum with a flat 24px for every item, not just
134
+ * the narrow ones the floor is for. With the default `flex-shrink: 1` the
135
+ * tabs were squeezed toward 24px until the line fitted, the strip stopped
136
+ * scrolling, and the labels — `nowrap`, with `min-width: 0` and no clip —
137
+ * spilled out of their buttons over their neighbours.
138
+ *
139
+ * `flex: none` is what the comment above already claims: "a tab whose label
140
+ * is wider than the floor is untouched".
141
+ */
142
+ flex: none;
111
143
  /* Never under the 24px target floor, at any density. */
112
144
  min-height: var(--size-control-sm);
113
145
  min-width: var(--size-target-min);
@@ -1,10 +1,10 @@
1
- export { TagsInput } from '../chunk-BJSKPEZI.js';
1
+ export { TagsInput } from '../chunk-6KCO2D5C.js';
2
2
  import '../chunk-S2XHHEW4.js';
3
3
  import '../chunk-PZSWF74H.js';
4
- import '../chunk-GTOUGQQK.js';
5
- import '../chunk-RSAQOKH3.js';
4
+ import '../chunk-KIC7BZYJ.js';
6
5
  import '../chunk-7RPGY3JE.js';
7
6
  import '../chunk-ITHXJHBB.js';
8
7
  import '../chunk-F27EPQ7D.js';
8
+ import '../chunk-RSAQOKH3.js';
9
9
  import '../chunk-BZFWDIV6.js';
10
10
  import '../chunk-ODEQTPFM.js';
@@ -1,6 +1,6 @@
1
- export { DensitySwitcher, ThemeSwitcher, applyDensity, applyStoredPreferences, applyTheme, useDensityPreference, useThemePreference } from '../chunk-2HQR4U4D.js';
2
- import '../chunk-6ZFVFA56.js';
3
- import '../chunk-QEUY3A5P.js';
1
+ export { DensitySwitcher, ThemeSwitcher, applyDensity, applyStoredPreferences, applyTheme, useDensityPreference, useThemePreference } from '../chunk-R66KLW7S.js';
2
+ import '../chunk-7PEFUMQJ.js';
3
+ import '../chunk-Q3B66TJM.js';
4
4
  import '../chunk-BHHIIK3M.js';
5
5
  import '../chunk-BZFWDIV6.js';
6
6
  import '../chunk-ODEQTPFM.js';
@@ -1,9 +1,9 @@
1
- export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-WOYYD2YR.js';
2
- import '../chunk-OFHBK7RI.js';
3
- import '../chunk-DD5BBGBE.js';
1
+ export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-XJWXPRSK.js';
2
+ import '../chunk-KNYYCWMK.js';
3
+ import '../chunk-EFSG7HNU.js';
4
4
  import '../chunk-GXQ3B46I.js';
5
- import '../chunk-GTOUGQQK.js';
6
- import '../chunk-O6232G37.js';
5
+ import '../chunk-KIC7BZYJ.js';
6
+ import '../chunk-GKHAKGOF.js';
7
7
  import '../chunk-PQADV6P6.js';
8
8
  import '../chunk-7RPGY3JE.js';
9
9
  import '../chunk-ITHXJHBB.js';
@@ -1,4 +1,4 @@
1
- export { Tooltip } from '../chunk-XV6WRMBC.js';
1
+ export { Tooltip } from '../chunk-5KSRXHOW.js';
2
2
  import '../chunk-7RPGY3JE.js';
3
3
  import '../chunk-ITHXJHBB.js';
4
4
  import '../chunk-ODEQTPFM.js';
@@ -123,10 +123,13 @@ function Tooltip({
123
123
  container?.addEventListener(LAYER_REPOSITION_EVENT, onLayout);
124
124
  window.addEventListener("resize", onLayout);
125
125
  window.addEventListener("scroll", onLayout, true);
126
+ const resize = typeof ResizeObserver === "function" ? new ResizeObserver(onLayout) : null;
127
+ if (panel.current) resize?.observe(panel.current);
126
128
  return () => {
127
129
  container?.removeEventListener(LAYER_REPOSITION_EVENT, onLayout);
128
130
  window.removeEventListener("resize", onLayout);
129
131
  window.removeEventListener("scroll", onLayout, true);
132
+ resize?.disconnect();
130
133
  };
131
134
  }, [open, container, position]);
132
135
  useEffect(() => {
@@ -1,8 +1,8 @@
1
1
  import { Tag } from './chunk-S2XHHEW4.js';
2
- import { useListbox } from './chunk-GTOUGQQK.js';
3
- import { announce } from './chunk-RSAQOKH3.js';
2
+ import { useListbox } from './chunk-KIC7BZYJ.js';
4
3
  import { isComposing } from './chunk-ITHXJHBB.js';
5
4
  import { IconButton } from './chunk-F27EPQ7D.js';
5
+ import { announce } from './chunk-RSAQOKH3.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
7
  import './TagsInput-W4P36PRJ.css';
8
8
  import { forwardRef, useState, useRef, useId, useImperativeHandle, useEffect, useMemo, useLayoutEffect } from 'react';
@@ -1,8 +1,8 @@
1
- import { useRoving, tabStop, tabId } from './chunk-QEUY3A5P.js';
1
+ import { useRoving, tabStop, tabId } from './chunk-Q3B66TJM.js';
2
2
  import { Count } from './chunk-BHHIIK3M.js';
3
3
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
- import './Tabs-VLICJFVB.css';
5
+ import './Tabs-MJ2E3VPK.css';
6
6
  import './SegmentedControl-X3BI3XU4.css';
7
7
  import { useId } from 'react';
8
8
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,6 +1,6 @@
1
+ import { useListbox } from './chunk-KIC7BZYJ.js';
2
+ import { Input } from './chunk-GKHAKGOF.js';
1
3
  import { Modal } from './chunk-2EOKFKHX.js';
2
- import { useListbox } from './chunk-GTOUGQQK.js';
3
- import { Input } from './chunk-O6232G37.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './CommandPalette-CSJDUCQA.css';
6
6
  import { useId, useMemo } from 'react';
@@ -37,7 +37,7 @@ function DiffList({ rows, emptyMessage, labels: overrides, className }) {
37
37
  /* @__PURE__ */ jsx(VisuallyHidden, { children: labels[row.kind] })
38
38
  ] }),
39
39
  /* @__PURE__ */ jsx("span", { className: "crewlet-diff-list__path", children: row.path }),
40
- /* @__PURE__ */ jsx("span", { className: "crewlet-diff-list__value", children: row.kind === "added" ? row.to : row.kind === "removed" ? row.from : /* @__PURE__ */ jsxs(Fragment, { children: [
40
+ /* @__PURE__ */ jsx("span", { className: "crewlet-diff-list__value", children: row.kind === "added" ? /* @__PURE__ */ jsx("span", { className: "crewlet-diff-list__to", children: row.to }) : row.kind === "removed" ? /* @__PURE__ */ jsx("span", { className: "crewlet-diff-list__from", children: row.from }) : /* @__PURE__ */ jsxs(Fragment, { children: [
41
41
  /* @__PURE__ */ jsx("span", { className: "crewlet-diff-list__from", children: row.from }),
42
42
  /* @__PURE__ */ jsx(ArrowForwardGlyph, { className: "crewlet-diff-list__arrow", size: "sm" }),
43
43
  /* @__PURE__ */ jsx(VisuallyHidden, { children: labels.to }),
@@ -1,13 +1,13 @@
1
1
  import { Toolbar } from './chunk-5EKIWVOR.js';
2
- import { PageHeader } from './chunk-HOXGBLEY.js';
3
2
  import { RelativeTime } from './chunk-3CZ7XAVY.js';
3
+ import { PageHeader } from './chunk-HOXGBLEY.js';
4
4
  import { Kbd } from './chunk-SFZOKW2G.js';
5
- import { DataTable } from './chunk-WQX73TWF.js';
6
- import { Menu } from './chunk-FBZAKNSX.js';
7
- import { DateTimePicker } from './chunk-UG46QBLT.js';
8
- import { Popover } from './chunk-DD5BBGBE.js';
9
- import { useListbox, useOptionKeys } from './chunk-GTOUGQQK.js';
10
- import { Input } from './chunk-O6232G37.js';
5
+ import { DataTable } from './chunk-PATXSJGR.js';
6
+ import { Menu } from './chunk-T43A26SD.js';
7
+ import { DateTimePicker } from './chunk-DB2VDLVR.js';
8
+ import { Popover } from './chunk-EFSG7HNU.js';
9
+ import { useListbox, useOptionKeys } from './chunk-KIC7BZYJ.js';
10
+ import { Input } from './chunk-GKHAKGOF.js';
11
11
  import { Count } from './chunk-BHHIIK3M.js';
12
12
  import { IconButton } from './chunk-F27EPQ7D.js';
13
13
  import { Button } from './chunk-BZYDZBAN.js';
@@ -456,7 +456,7 @@ function OptionListEditor({ def, value, labels, onCommit }) {
456
456
  role: "listbox",
457
457
  "aria-label": labels.options(def.label),
458
458
  "aria-multiselectable": multiple || void 0,
459
- "aria-activedescendant": options.length > 0 ? listbox.optionId(listbox.active) : void 0,
459
+ "aria-activedescendant": listbox.active >= 0 ? listbox.optionId(listbox.active) : void 0,
460
460
  tabIndex: 0,
461
461
  className: "crewlet-filter-axis__options",
462
462
  onKeyDown,
@@ -1,4 +1,4 @@
1
- import { Popover } from './chunk-DD5BBGBE.js';
1
+ import { Popover } from './chunk-EFSG7HNU.js';
2
2
  import { today, CalendarGrid, shiftMonth, compareDays } from './chunk-GXQ3B46I.js';
3
3
  import { IconButton } from './chunk-F27EPQ7D.js';
4
4
  import { Button } from './chunk-BZYDZBAN.js';
@@ -50,10 +50,10 @@ function Popover({
50
50
  const inHost = container !== document.body;
51
51
  const host = inHost ? container.getBoundingClientRect() : viewportBounds();
52
52
  const rect = at.getBoundingClientRect();
53
+ box.style.width = width === "match" ? `${rect.width}px` : "";
53
54
  const own = box.getBoundingClientRect();
54
- const panelWidth = width === "match" ? rect.width : own.width;
55
55
  const local = {
56
- x: (align === "end" ? rect.right - panelWidth : rect.left) - (inHost ? host.x : 0),
56
+ x: (align === "end" ? rect.right - own.width : rect.left) - (inHost ? host.x : 0),
57
57
  y: rect.top - (inHost ? host.y : 0),
58
58
  width: rect.width,
59
59
  height: rect.height
@@ -69,15 +69,16 @@ function Popover({
69
69
  close("anchor-gone");
70
70
  return;
71
71
  }
72
+ const asked = width === "match" ? rect.width : void 0;
72
73
  const spot = placePopup(
73
74
  local,
74
- { width: panelWidth, height: own.height },
75
+ { width: own.width, height: own.height },
75
76
  bounds,
76
77
  LAYER_GAP,
77
78
  side === "top" ? "above" : "below"
78
79
  );
79
80
  setPlace(
80
- (was) => was && was.left === spot.left && was.top === spot.top && was.side === spot.side && was.width === panelWidth ? was : { left: spot.left, top: spot.top, side: spot.side, width: width === "match" ? panelWidth : void 0 }
81
+ (was) => was && was.left === spot.left && was.top === spot.top && was.side === spot.side && was.width === asked ? was : { left: spot.left, top: spot.top, side: spot.side, width: asked }
81
82
  );
82
83
  }, [align, close, container, side, width]);
83
84
  useLayoutEffect(() => {
@@ -87,10 +88,13 @@ function Popover({
87
88
  container?.addEventListener(LAYER_REPOSITION_EVENT, onLayout);
88
89
  window.addEventListener("resize", onLayout);
89
90
  window.addEventListener("scroll", onLayout, true);
91
+ const resize = typeof ResizeObserver === "function" ? new ResizeObserver(onLayout) : null;
92
+ if (panel.current) resize?.observe(panel.current);
90
93
  return () => {
91
94
  container?.removeEventListener(LAYER_REPOSITION_EVENT, onLayout);
92
95
  window.removeEventListener("resize", onLayout);
93
96
  window.removeEventListener("scroll", onLayout, true);
97
+ resize?.disconnect();
94
98
  };
95
99
  }, [open, container, position]);
96
100
  useEffect(() => {
@@ -1,8 +1,8 @@
1
1
  import { Kbd } from './chunk-SFZOKW2G.js';
2
- import { FormField, Textarea, Input } from './chunk-O6232G37.js';
3
- import { announce } from './chunk-RSAQOKH3.js';
2
+ import { FormField, Textarea, Input } from './chunk-GKHAKGOF.js';
4
3
  import { isComposing } from './chunk-ITHXJHBB.js';
5
4
  import { IconButton } from './chunk-F27EPQ7D.js';
5
+ import { announce } from './chunk-RSAQOKH3.js';
6
6
  import './ListInput-O7LJKOIG.css';
7
7
  import { useState, useRef, useLayoutEffect } from 'react';
8
8
  import { ArrowUpwardGlyph, ArrowDownwardGlyph, CloseGlyph, AddGlyph } from '@crewlethq/icons/glyphs';