@olenbetong/appframe-ds 1.3.5 → 1.3.7

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 (178) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/package.json +5 -5
  3. package/scripts/copyAssets.mjs +27 -27
  4. package/src/AfLookup/Lookup.css +129 -129
  5. package/src/AfLookup/Lookup.tsx +186 -186
  6. package/src/AfLookup/LookupCombobox.css +78 -78
  7. package/src/AfLookup/LookupCombobox.tsx +237 -237
  8. package/src/AfLookup/LookupEdit.tsx +130 -130
  9. package/src/AfLookup/LookupGrid.tsx +124 -124
  10. package/src/AfLookup/index.ts +5 -5
  11. package/src/autocomplete/Autocomplete.css +256 -256
  12. package/src/autocomplete/Autocomplete.tsx +320 -320
  13. package/src/autocomplete/AutocompleteFrame.tsx +168 -168
  14. package/src/autocomplete/Combobox.tsx +286 -286
  15. package/src/autocomplete/index.ts +4 -4
  16. package/src/autocomplete/types.ts +204 -204
  17. package/src/autocomplete/utils.ts +183 -183
  18. package/src/binding/BoundNumericTextField.tsx +102 -102
  19. package/src/binding/BoundTextField.tsx +49 -49
  20. package/src/binding/CancelButton.tsx +30 -30
  21. package/src/binding/CancelIconButton.tsx +30 -30
  22. package/src/binding/DataEditToolbar.css +23 -23
  23. package/src/binding/DataEditToolbar.tsx +84 -84
  24. package/src/binding/DeleteButton.tsx +35 -35
  25. package/src/binding/DeleteIconButton.tsx +35 -35
  26. package/src/binding/RefreshButton.tsx +31 -31
  27. package/src/binding/RefreshIconButton.tsx +33 -33
  28. package/src/binding/RefreshRowIconButton.tsx +33 -33
  29. package/src/binding/SaveButton.tsx +37 -37
  30. package/src/binding/SaveIconButton.tsx +38 -38
  31. package/src/container/Container.tsx +49 -49
  32. package/src/container/index.ts +1 -1
  33. package/src/cutoff/CutOffPicker.css +12 -12
  34. package/src/cutoff/CutOffPicker.tsx +165 -165
  35. package/src/cutoff/context.tsx +194 -194
  36. package/src/cutoff/dsCutOffDates.ts +21 -21
  37. package/src/cutoff/index.ts +4 -4
  38. package/src/cutoff/utils.test.ts +59 -59
  39. package/src/cutoff/utils.ts +276 -276
  40. package/src/filter/ChipListInput.tsx +79 -79
  41. package/src/filter/FieldFilterPanel.css +150 -150
  42. package/src/filter/FieldFilterPanel.tsx +309 -309
  43. package/src/filter/FilterBuilder.css +152 -152
  44. package/src/filter/FilterBuilder.test.tsx +153 -153
  45. package/src/filter/FilterBuilder.tsx +435 -435
  46. package/src/filter/FilterEditor.css +231 -231
  47. package/src/filter/FilterEditor.test.tsx +285 -285
  48. package/src/filter/FilterEditor.tsx +75 -75
  49. package/src/filter/FilterGroupEditor.tsx +160 -160
  50. package/src/filter/FilterNameDialog.css +22 -22
  51. package/src/filter/FilterNameDialog.tsx +81 -81
  52. package/src/filter/FilterRow.tsx +117 -117
  53. package/src/filter/FilterShareDialog.css +28 -28
  54. package/src/filter/FilterShareDialog.tsx +201 -201
  55. package/src/filter/FilterStringField.tsx +78 -78
  56. package/src/filter/FilterValueEditor.tsx +239 -239
  57. package/src/filter/SavedFilterTree.css +107 -107
  58. package/src/filter/SavedFilterTree.test.tsx +94 -94
  59. package/src/filter/SavedFilterTree.tsx +218 -218
  60. package/src/filter/fieldFilter.test.ts +158 -158
  61. package/src/filter/fieldFilter.ts +139 -139
  62. package/src/filter/index.ts +27 -27
  63. package/src/filter/types.ts +38 -38
  64. package/src/filter/useDistinctValues.test.ts +102 -102
  65. package/src/filter/useDistinctValues.ts +230 -230
  66. package/src/global.d.ts +11 -11
  67. package/src/grid/AfGridColumnsPanel.tsx +118 -118
  68. package/src/grid/AfGridContext.tsx +51 -51
  69. package/src/grid/AfGridError.tsx +46 -46
  70. package/src/grid/AfHeaderFilterCell.tsx +147 -147
  71. package/src/grid/AfHeaderFilterPanel.tsx +111 -111
  72. package/src/grid/GridEditLookup.css +12 -12
  73. package/src/grid/GridEditLookup.tsx +121 -121
  74. package/src/grid/Toolbar.tsx +233 -233
  75. package/src/grid/editing.ts +100 -100
  76. package/src/grid/filter.ts +78 -78
  77. package/src/grid/formatters.ts +48 -48
  78. package/src/grid/index.css +245 -245
  79. package/src/grid/index.tsx +503 -503
  80. package/src/grid/license.ts +48 -48
  81. package/src/grid/localization.ts +369 -369
  82. package/src/grid/slots/index.tsx +334 -334
  83. package/src/grid/slots/slots.css +64 -64
  84. package/src/grid/slots/slots.test.tsx +39 -39
  85. package/src/grid/theme.tsx +138 -138
  86. package/src/grid/useAfColumns.tsx +371 -371
  87. package/src/grid/useAfCurrentIndex.ts +63 -63
  88. package/src/grid/useAfData.ts +20 -20
  89. package/src/grid/useAfFilter.ts +160 -160
  90. package/src/grid/useAfFilterFields.ts +55 -55
  91. package/src/grid/useAfGridApi.ts +71 -71
  92. package/src/grid/useAfKeyBindings.ts +36 -36
  93. package/src/grid/useAfNewItemRow.ts +258 -258
  94. package/src/grid/useAfPagination.ts +53 -53
  95. package/src/grid/useAfPersistedState.ts +230 -230
  96. package/src/grid/useAfRowEditModel.ts +145 -145
  97. package/src/grid/useAfRowGrouping.ts +47 -47
  98. package/src/grid/useAfServerAggregation.test.ts +68 -68
  99. package/src/grid/useAfServerAggregation.ts +158 -158
  100. package/src/grid/useAfSortModel.ts +84 -84
  101. package/src/i18n.ts +13 -13
  102. package/src/index.ts +14 -14
  103. package/src/input/InputAdornments.css +84 -84
  104. package/src/input/InputAdornments.tsx +102 -102
  105. package/src/input/index.ts +1 -1
  106. package/src/layout/AppMenu.tsx +74 -74
  107. package/src/layout/AppMenuDrawer.css +70 -70
  108. package/src/layout/AppMenuDrawer.tsx +122 -122
  109. package/src/layout/ErrorBoundary.tsx +162 -162
  110. package/src/layout/PageContainer.css +48 -48
  111. package/src/layout/PageContainer.tsx +41 -41
  112. package/src/layout/ResponsiveDialog.css +86 -86
  113. package/src/layout/ResponsiveDialog.tsx +55 -55
  114. package/src/layout/index.tsx +69 -69
  115. package/src/link/Link.tsx +23 -23
  116. package/src/link/index.ts +1 -1
  117. package/src/mdi/Mdi.css +138 -138
  118. package/src/mdi/Mdi.test.tsx +91 -91
  119. package/src/mdi/Mdi.tsx +141 -141
  120. package/src/mdi/MdiConfirmCloseDialog.tsx +47 -47
  121. package/src/mdi/MdiContext.tsx +59 -59
  122. package/src/mdi/MdiDocumentContext.tsx +60 -60
  123. package/src/mdi/MdiPanel.tsx +61 -61
  124. package/src/mdi/MdiRestore.test.tsx +86 -86
  125. package/src/mdi/MdiTab.tsx +30 -30
  126. package/src/mdi/controller.test.ts +382 -382
  127. package/src/mdi/controller.ts +656 -656
  128. package/src/mdi/dockviewHost.ts +132 -132
  129. package/src/mdi/fakeHost.ts +200 -200
  130. package/src/mdi/host.ts +44 -44
  131. package/src/mdi/ids.test.ts +20 -20
  132. package/src/mdi/ids.ts +18 -18
  133. package/src/mdi/index.ts +31 -31
  134. package/src/mdi/layoutRestore.test.ts +156 -156
  135. package/src/mdi/layoutRestore.ts +311 -311
  136. package/src/mdi/layoutSpec.test.ts +143 -143
  137. package/src/mdi/layoutSpec.ts +214 -214
  138. package/src/mdi/layoutStore.test.ts +93 -93
  139. package/src/mdi/layoutStore.ts +99 -99
  140. package/src/mdi/memorySettingsStore.ts +21 -21
  141. package/src/mdi/registry.ts +34 -34
  142. package/src/mdi/testTypes.ts +37 -37
  143. package/src/mdi/theme.ts +22 -22
  144. package/src/mdi/types.ts +214 -214
  145. package/src/page/Page.css +53 -53
  146. package/src/page/PageBlock.css +64 -64
  147. package/src/page/PageBlock.tsx +92 -92
  148. package/src/page/PageHeader.css +88 -88
  149. package/src/page/PageHeader.tsx +115 -115
  150. package/src/page/PageTitle.css +5 -5
  151. package/src/page/PageTitle.tsx +21 -21
  152. package/src/page/index.ts +4 -4
  153. package/src/paper/Paper.tsx +52 -52
  154. package/src/progress/LinearProgress.css +93 -93
  155. package/src/progress/LinearProgress.tsx +104 -104
  156. package/src/progress/index.ts +1 -1
  157. package/src/report-downloader/ReportDownloader.css +67 -67
  158. package/src/report-downloader/components/StatusItem.tsx +87 -87
  159. package/src/report-downloader/components/StatusList.tsx +28 -28
  160. package/src/report-downloader/index.ts +41 -41
  161. package/src/report-downloader/status.tsx +92 -92
  162. package/src/sortable/DropIndicator.css +51 -51
  163. package/src/sortable/DropIndicator.tsx +27 -27
  164. package/src/sortable/SortableItemList.css +21 -21
  165. package/src/sortable/SortableItemList.tsx +264 -264
  166. package/src/sortable/index.ts +8 -8
  167. package/src/sortable/reorderSortOrder.ts +126 -126
  168. package/src/sortable/sortOrder.ts +101 -101
  169. package/src/sortable/types.ts +9 -9
  170. package/src/sortable/useSortableContainer.ts +53 -53
  171. package/src/sortable/useSortableItem.ts +95 -95
  172. package/src/sortable/useSortableList.ts +117 -117
  173. package/src/test/happy-dom-document-class.ts +24 -24
  174. package/src/test/setup.ts +12 -12
  175. package/src/theme/useDsColorScheme.ts +53 -53
  176. package/tsconfig.build.json +9 -9
  177. package/tsconfig.json +8 -8
  178. package/vitest.config.ts +10 -10
@@ -1,79 +1,79 @@
1
- import { ChipRemovable, Textfield } from "@digdir/designsystemet-react";
2
- import { useState } from "react";
3
- import { getLocalizedString } from "../i18n.js";
4
-
5
- export type ChipListInputProps = {
6
- value: string[];
7
- onChange: (value: string[]) => void;
8
- readOnly?: boolean;
9
- "aria-label": string;
10
- "data-size"?: "sm" | "md" | "lg";
11
- type?: "text" | "number" | "date" | "datetime-local";
12
- };
13
-
14
- /**
15
- * Free text editor for the list operators. Values are added with Enter and
16
- * rendered as removable chips.
17
- */
18
- export function ChipListInput({
19
- value,
20
- onChange,
21
- readOnly,
22
- type = "text",
23
- "aria-label": ariaLabel,
24
- "data-size": size,
25
- }: ChipListInputProps) {
26
- let [draft, setDraft] = useState("");
27
-
28
- function commit() {
29
- let trimmed = draft.trim();
30
- if (!trimmed || value.includes(trimmed)) {
31
- setDraft("");
32
- return;
33
- }
34
-
35
- onChange([...value, trimmed]);
36
- setDraft("");
37
- }
38
-
39
- function handleKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
40
- if (event.key === "Enter") {
41
- // The editor is often rendered inside a dialog; committing a value
42
- // must not submit or close it.
43
- event.preventDefault();
44
- commit();
45
- } else if (event.key === "Backspace" && draft === "" && value.length > 0) {
46
- onChange(value.slice(0, -1));
47
- }
48
- }
49
-
50
- return (
51
- <div className="ObFilterEditor-chipList">
52
- {value.map((item, index) => (
53
- <ChipRemovable
54
- // Values are deduplicated on add, so the value is a stable key.
55
- key={item}
56
- data-size={size}
57
- disabled={readOnly}
58
- aria-label={`${getLocalizedString("Remove")} ${item}`}
59
- onClick={() => onChange(value.filter((_, i) => i !== index))}
60
- >
61
- {item}
62
- </ChipRemovable>
63
- ))}
64
- {!readOnly && (
65
- <Textfield
66
- className="ObFilterEditor-chipListInput"
67
- aria-label={ariaLabel}
68
- data-size={size}
69
- type={type}
70
- value={draft}
71
- placeholder={getLocalizedString("Add value")}
72
- onChange={(event) => setDraft(event.target.value)}
73
- onKeyDown={handleKeyDown}
74
- onBlur={commit}
75
- />
76
- )}
77
- </div>
78
- );
79
- }
1
+ import { ChipRemovable, Textfield } from "@digdir/designsystemet-react";
2
+ import { useState } from "react";
3
+ import { getLocalizedString } from "../i18n.js";
4
+
5
+ export type ChipListInputProps = {
6
+ value: string[];
7
+ onChange: (value: string[]) => void;
8
+ readOnly?: boolean;
9
+ "aria-label": string;
10
+ "data-size"?: "sm" | "md" | "lg";
11
+ type?: "text" | "number" | "date" | "datetime-local";
12
+ };
13
+
14
+ /**
15
+ * Free text editor for the list operators. Values are added with Enter and
16
+ * rendered as removable chips.
17
+ */
18
+ export function ChipListInput({
19
+ value,
20
+ onChange,
21
+ readOnly,
22
+ type = "text",
23
+ "aria-label": ariaLabel,
24
+ "data-size": size,
25
+ }: ChipListInputProps) {
26
+ let [draft, setDraft] = useState("");
27
+
28
+ function commit() {
29
+ let trimmed = draft.trim();
30
+ if (!trimmed || value.includes(trimmed)) {
31
+ setDraft("");
32
+ return;
33
+ }
34
+
35
+ onChange([...value, trimmed]);
36
+ setDraft("");
37
+ }
38
+
39
+ function handleKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
40
+ if (event.key === "Enter") {
41
+ // The editor is often rendered inside a dialog; committing a value
42
+ // must not submit or close it.
43
+ event.preventDefault();
44
+ commit();
45
+ } else if (event.key === "Backspace" && draft === "" && value.length > 0) {
46
+ onChange(value.slice(0, -1));
47
+ }
48
+ }
49
+
50
+ return (
51
+ <div className="ObFilterEditor-chipList">
52
+ {value.map((item, index) => (
53
+ <ChipRemovable
54
+ // Values are deduplicated on add, so the value is a stable key.
55
+ key={item}
56
+ data-size={size}
57
+ disabled={readOnly}
58
+ aria-label={`${getLocalizedString("Remove")} ${item}`}
59
+ onClick={() => onChange(value.filter((_, i) => i !== index))}
60
+ >
61
+ {item}
62
+ </ChipRemovable>
63
+ ))}
64
+ {!readOnly && (
65
+ <Textfield
66
+ className="ObFilterEditor-chipListInput"
67
+ aria-label={ariaLabel}
68
+ data-size={size}
69
+ type={type}
70
+ value={draft}
71
+ placeholder={getLocalizedString("Add value")}
72
+ onChange={(event) => setDraft(event.target.value)}
73
+ onKeyDown={handleKeyDown}
74
+ onBlur={commit}
75
+ />
76
+ )}
77
+ </div>
78
+ );
79
+ }
@@ -1,150 +1,150 @@
1
- .ObFieldFilterPanel-root {
2
- display: flex;
3
- flex-direction: column;
4
- gap: var(--ds-size-3, 0.75rem);
5
-
6
- /*
7
- * The panel is sized by whatever it is put in — a popover, a dialog, a
8
- * sidebar. It fills that container and lets the distinct list take up the
9
- * slack, so the list grows and shrinks with the container instead of
10
- * carrying a height of its own.
11
- */
12
- block-size: 100%;
13
- min-block-size: 0;
14
- }
15
-
16
- .ObFieldFilterPanel-heading {
17
- font-weight: var(--ds-font-weight-medium, 500);
18
- color: var(--ds-color-neutral-text-default);
19
- }
20
-
21
- .ObFieldFilterPanel-criteria {
22
- display: flex;
23
- flex-direction: column;
24
- flex: 0 0 auto;
25
- gap: var(--ds-size-2, 0.5rem);
26
- }
27
-
28
- .ObFieldFilterPanel-criterion {
29
- display: flex;
30
- flex-direction: column;
31
- gap: var(--ds-size-1, 0.25rem);
32
- }
33
-
34
- /*
35
- * The filter editor's value cell is written for the filter builder's horizontal
36
- * rows, where growing is what makes it fill the row. Stacked vertically that
37
- * same `flex-grow` makes it stretch to fill the whole panel instead.
38
- */
39
- .ObFieldFilterPanel-criterion > .ObFilterEditor-valueCell {
40
- flex: 0 0 auto;
41
- }
42
-
43
- .ObFieldFilterPanel-distinct {
44
- /*
45
- * The parts the section cannot usefully shrink past, named so the floor below
46
- * and the list's own minimum cannot drift apart.
47
- */
48
- --obFieldFilterPanel-list-min-size: 8rem;
49
- --obFieldFilterPanel-toolbar-size: 2.75rem; /* a `sm` search field */
50
- --obFieldFilterPanel-hint-size: 1.25rem; /* one line of truncation hint */
51
-
52
- display: flex;
53
- flex-direction: column;
54
- flex: 1 1 auto;
55
- gap: var(--ds-size-2, 0.5rem);
56
- padding-block-start: var(--ds-size-2, 0.5rem);
57
- border-block-start: var(--ds-border-width-default, 1px) solid var(--ds-color-neutral-border-subtle, #e7e7e7);
58
-
59
- /*
60
- * The section follows the panel's height, but only down to the toolbar, the
61
- * hint and the list's own minimum. Without a floor it kept shrinking while
62
- * the list held its minimum, and since the overflow here is visible the list
63
- * spilled out and painted over the buttons the panel puts after it.
64
- *
65
- * The floor has to be an explicit length. `auto` resolves to min-content, and
66
- * the list is the scroll container, so its min-content height is the whole
67
- * unscrolled list — that would stretch the section to fit every distinct
68
- * value. Once the panel is too short for this, it scrolls instead.
69
- */
70
- min-block-size: calc(
71
- var(--obFieldFilterPanel-list-min-size) + var(--obFieldFilterPanel-toolbar-size) +
72
- var(--obFieldFilterPanel-hint-size) + 2 * var(--ds-size-2, 0.5rem)
73
- );
74
- }
75
-
76
- .ObFieldFilterPanel-distinctToolbar {
77
- display: flex;
78
- flex: 0 0 auto;
79
- gap: var(--ds-size-1, 0.25rem);
80
- align-items: center;
81
- }
82
-
83
- .ObFieldFilterPanel-distinctToolbar .ds-search {
84
- flex: 1;
85
- min-inline-size: 0;
86
- }
87
-
88
- /*
89
- * The active sort is held down, so it is clear which of the two is in effect.
90
- * Neutral tokens rather than accent ones: the accent scale is only defined
91
- * inside a `data-color` scope, and the panel can be dropped anywhere.
92
- */
93
- .ObFieldFilterPanel-distinctToolbar .ds-button[aria-pressed="true"] {
94
- color: var(--ds-color-neutral-text-default, #292c30);
95
- background: var(--ds-color-neutral-surface-active, #c9cacb);
96
- box-shadow: inset 0 0 0 var(--ds-border-width-default, 1px) var(--ds-color-neutral-border-subtle, #e7e7e7);
97
- }
98
-
99
- /*
100
- * Both the list and the spinner that replaces it while loading use this box, so
101
- * the panel does not jump when the values arrive. It is the part that takes up
102
- * whatever room the container has left, and it never collapses to nothing.
103
- */
104
- .ObFieldFilterPanel-valuesBox {
105
- flex: 1 1 auto;
106
- min-block-size: var(--obFieldFilterPanel-list-min-size, 8rem);
107
- border: var(--ds-border-width-default, 1px) solid var(--ds-color-neutral-border-subtle, #e7e7e7);
108
- border-radius: var(--ds-border-radius-md, 0.25rem);
109
- background: var(--ds-color-neutral-surface-tinted, rgb(0 0 0 / 2%));
110
- }
111
-
112
- .ObFieldFilterPanel-values {
113
- display: flex;
114
- flex-direction: column;
115
- gap: var(--ds-size-1, 0.25rem);
116
- margin: 0;
117
- padding: var(--ds-size-1, 0.25rem);
118
- overflow-y: auto;
119
- list-style: none;
120
- }
121
-
122
- .ObFieldFilterPanel-value {
123
- padding-inline: var(--ds-size-1, 0.25rem);
124
- }
125
-
126
- .ObFieldFilterPanel-loading {
127
- display: flex;
128
- align-items: center;
129
- justify-content: center;
130
- padding: var(--ds-size-4, 1rem);
131
- }
132
-
133
- .ObFieldFilterPanel-error {
134
- margin: 0;
135
- color: var(--ds-color-danger-text-default);
136
- }
137
-
138
- .ObFieldFilterPanel-hint {
139
- margin: 0;
140
- flex: 0 0 auto;
141
- font-size: var(--ds-font-size-1, 0.75rem);
142
- color: var(--ds-color-neutral-text-subtle, #68707c);
143
- }
144
-
145
- .ObFieldFilterPanel-actions {
146
- display: flex;
147
- flex: 0 0 auto;
148
- gap: var(--ds-size-2, 0.5rem);
149
- justify-content: flex-end;
150
- }
1
+ .ObFieldFilterPanel-root {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--ds-size-3, 0.75rem);
5
+
6
+ /*
7
+ * The panel is sized by whatever it is put in — a popover, a dialog, a
8
+ * sidebar. It fills that container and lets the distinct list take up the
9
+ * slack, so the list grows and shrinks with the container instead of
10
+ * carrying a height of its own.
11
+ */
12
+ block-size: 100%;
13
+ min-block-size: 0;
14
+ }
15
+
16
+ .ObFieldFilterPanel-heading {
17
+ font-weight: var(--ds-font-weight-medium, 500);
18
+ color: var(--ds-color-neutral-text-default);
19
+ }
20
+
21
+ .ObFieldFilterPanel-criteria {
22
+ display: flex;
23
+ flex-direction: column;
24
+ flex: 0 0 auto;
25
+ gap: var(--ds-size-2, 0.5rem);
26
+ }
27
+
28
+ .ObFieldFilterPanel-criterion {
29
+ display: flex;
30
+ flex-direction: column;
31
+ gap: var(--ds-size-1, 0.25rem);
32
+ }
33
+
34
+ /*
35
+ * The filter editor's value cell is written for the filter builder's horizontal
36
+ * rows, where growing is what makes it fill the row. Stacked vertically that
37
+ * same `flex-grow` makes it stretch to fill the whole panel instead.
38
+ */
39
+ .ObFieldFilterPanel-criterion > .ObFilterEditor-valueCell {
40
+ flex: 0 0 auto;
41
+ }
42
+
43
+ .ObFieldFilterPanel-distinct {
44
+ /*
45
+ * The parts the section cannot usefully shrink past, named so the floor below
46
+ * and the list's own minimum cannot drift apart.
47
+ */
48
+ --obFieldFilterPanel-list-min-size: 8rem;
49
+ --obFieldFilterPanel-toolbar-size: 2.75rem; /* a `sm` search field */
50
+ --obFieldFilterPanel-hint-size: 1.25rem; /* one line of truncation hint */
51
+
52
+ display: flex;
53
+ flex-direction: column;
54
+ flex: 1 1 auto;
55
+ gap: var(--ds-size-2, 0.5rem);
56
+ padding-block-start: var(--ds-size-2, 0.5rem);
57
+ border-block-start: var(--ds-border-width-default, 1px) solid var(--ds-color-neutral-border-subtle, #e7e7e7);
58
+
59
+ /*
60
+ * The section follows the panel's height, but only down to the toolbar, the
61
+ * hint and the list's own minimum. Without a floor it kept shrinking while
62
+ * the list held its minimum, and since the overflow here is visible the list
63
+ * spilled out and painted over the buttons the panel puts after it.
64
+ *
65
+ * The floor has to be an explicit length. `auto` resolves to min-content, and
66
+ * the list is the scroll container, so its min-content height is the whole
67
+ * unscrolled list — that would stretch the section to fit every distinct
68
+ * value. Once the panel is too short for this, it scrolls instead.
69
+ */
70
+ min-block-size: calc(
71
+ var(--obFieldFilterPanel-list-min-size) + var(--obFieldFilterPanel-toolbar-size) +
72
+ var(--obFieldFilterPanel-hint-size) + 2 * var(--ds-size-2, 0.5rem)
73
+ );
74
+ }
75
+
76
+ .ObFieldFilterPanel-distinctToolbar {
77
+ display: flex;
78
+ flex: 0 0 auto;
79
+ gap: var(--ds-size-1, 0.25rem);
80
+ align-items: center;
81
+ }
82
+
83
+ .ObFieldFilterPanel-distinctToolbar .ds-search {
84
+ flex: 1;
85
+ min-inline-size: 0;
86
+ }
87
+
88
+ /*
89
+ * The active sort is held down, so it is clear which of the two is in effect.
90
+ * Neutral tokens rather than accent ones: the accent scale is only defined
91
+ * inside a `data-color` scope, and the panel can be dropped anywhere.
92
+ */
93
+ .ObFieldFilterPanel-distinctToolbar .ds-button[aria-pressed="true"] {
94
+ color: var(--ds-color-neutral-text-default, #292c30);
95
+ background: var(--ds-color-neutral-surface-active, #c9cacb);
96
+ box-shadow: inset 0 0 0 var(--ds-border-width-default, 1px) var(--ds-color-neutral-border-subtle, #e7e7e7);
97
+ }
98
+
99
+ /*
100
+ * Both the list and the spinner that replaces it while loading use this box, so
101
+ * the panel does not jump when the values arrive. It is the part that takes up
102
+ * whatever room the container has left, and it never collapses to nothing.
103
+ */
104
+ .ObFieldFilterPanel-valuesBox {
105
+ flex: 1 1 auto;
106
+ min-block-size: var(--obFieldFilterPanel-list-min-size, 8rem);
107
+ border: var(--ds-border-width-default, 1px) solid var(--ds-color-neutral-border-subtle, #e7e7e7);
108
+ border-radius: var(--ds-border-radius-md, 0.25rem);
109
+ background: var(--ds-color-neutral-surface-tinted, rgb(0 0 0 / 2%));
110
+ }
111
+
112
+ .ObFieldFilterPanel-values {
113
+ display: flex;
114
+ flex-direction: column;
115
+ gap: var(--ds-size-1, 0.25rem);
116
+ margin: 0;
117
+ padding: var(--ds-size-1, 0.25rem);
118
+ overflow-y: auto;
119
+ list-style: none;
120
+ }
121
+
122
+ .ObFieldFilterPanel-value {
123
+ padding-inline: var(--ds-size-1, 0.25rem);
124
+ }
125
+
126
+ .ObFieldFilterPanel-loading {
127
+ display: flex;
128
+ align-items: center;
129
+ justify-content: center;
130
+ padding: var(--ds-size-4, 1rem);
131
+ }
132
+
133
+ .ObFieldFilterPanel-error {
134
+ margin: 0;
135
+ color: var(--ds-color-danger-text-default);
136
+ }
137
+
138
+ .ObFieldFilterPanel-hint {
139
+ margin: 0;
140
+ flex: 0 0 auto;
141
+ font-size: var(--ds-font-size-1, 0.75rem);
142
+ color: var(--ds-color-neutral-text-subtle, #68707c);
143
+ }
144
+
145
+ .ObFieldFilterPanel-actions {
146
+ display: flex;
147
+ flex: 0 0 auto;
148
+ gap: var(--ds-size-2, 0.5rem);
149
+ justify-content: flex-end;
150
+ }