@mono-lit/helper 0.0.9 → 0.0.10

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 (161) hide show
  1. package/dist/accordion-core-DaNyPWRr.js +277 -0
  2. package/dist/alert-core-DWtHbX_-.js +134 -0
  3. package/dist/breadcrumb-list-core-Dh68T8Cf.js +747 -0
  4. package/dist/{mono-button-CLkHg3WW.js → button-core-DerXg84Q.js} +3 -276
  5. package/dist/button-dropdown-core-DKYEOyjy.js +654 -0
  6. package/dist/button-utils-D5-66M02.js +63 -0
  7. package/dist/card-utils-l80qAmrN.js +312 -0
  8. package/dist/chart-core-DV7hD3ZY.js +801 -0
  9. package/dist/checkbox-utils-DKdrhAzF.js +337 -0
  10. package/dist/chip-utils-DpRrd7Zj.js +403 -0
  11. package/dist/{data-source-controller-C6C4ej_M.js → data-source-controller-DS_JLrmS.js} +1 -1
  12. package/dist/{data-source-options-fxT5QIX4.js → data-source-options-DJUNU26C.js} +6 -6
  13. package/dist/{data-source-read-BL266IW0.js → data-source-read-uKJpRAzx.js} +2 -2
  14. package/dist/date-core-CyuSyvvG.js +734 -0
  15. package/dist/drawer-core-DbFWvNln.js +759 -0
  16. package/dist/dropdown-core-BCH1pK14.js +511 -0
  17. package/dist/dropdown-table-core-SfHUJVFq.js +1342 -0
  18. package/dist/export.js +1 -1
  19. package/dist/{field-path-BabiMrrA.js → field-path-DK2VBWHl.js} +1 -1
  20. package/dist/field-tooltip.css_raw-DVblekCl.js +5 -0
  21. package/dist/{field-validation.css_raw-Cx6SGrfP.js → field-validation.css_raw-BU7C6173.js} +1 -170
  22. package/dist/file-upload-core-Cz_dBQMx.js +624 -0
  23. package/dist/filter-builder-core-DyWjbBP7.js +381 -0
  24. package/dist/{filter-builder-B6Y2mmbM.js → filter-builder-vbqIuPhX.js} +1 -1
  25. package/dist/{filter-eval-ChDSaAUH.js → filter-eval-CqeBnMYh.js} +1 -1
  26. package/dist/{filter-odata-Bi27XUpQ.js → filter-odata-GsczYKNC.js} +1 -1
  27. package/dist/{hydration-flush-BaE9gN3C.js → hydration-flush-Volt9X7Q.js} +2 -1071
  28. package/dist/index.js +11 -11
  29. package/dist/{index.node-DTqDBca7.js → index.node-Csy9zrr1.js} +4 -4
  30. package/dist/index.node.js +11 -11
  31. package/dist/input-utils-BglY-k0H.js +1145 -0
  32. package/dist/menu-core-DkAYuCZ2.js +831 -0
  33. package/dist/modal-core-CSBSPN_m.js +844 -0
  34. package/dist/mono-button-DVvZ03P-.js +280 -0
  35. package/dist/{mono-button.shadow-DqZMpcqY.js → mono-button.shadow-BANxMGln.js} +6 -594
  36. package/dist/{mono-data-chart-NKPdAgVq.js → mono-data-chart-ChF4J9RT.js} +6 -6
  37. package/dist/{mono-data-dropdown-B2iRpJuI.js → mono-data-dropdown-Bgj2PDfm.js} +1 -1
  38. package/dist/{mono-data-grid-llJCX9MC.js → mono-data-grid-DJkp96N-.js} +144 -46
  39. package/dist/{mono-event-BPku9HpS.js → mono-event-CAZf0F_k.js} +14 -9
  40. package/dist/{mono-form-controller-BrA10erm.js → mono-form-controller-DxZLvyg6.js} +2 -1
  41. package/dist/mono-table-checkbox-core-BKOMx8R5.js +5288 -0
  42. package/dist/nav-core-B5qU2dzn.js +225 -0
  43. package/dist/{normalize-error-D93O4q8g.js → normalize-error-BEcd1tmS.js} +2 -2
  44. package/dist/otp-core-DXg3vFLh.js +758 -0
  45. package/dist/radio-utils-Dk9Tl1jz.js +319 -0
  46. package/dist/rich-text-editor-core-Ddd_QaLn.js +1280 -0
  47. package/dist/select-utils-BgArYHk8.js +2140 -0
  48. package/dist/sidebar-core-CD6txDo3.js +583 -0
  49. package/dist/slider-core-vcWr321-.js +1014 -0
  50. package/dist/src/components/dropdown-table/dropdown-table-core.d.ts +2 -2
  51. package/dist/src/components/dropdown-table/dropdown-table-types.d.ts +1 -1
  52. package/dist/src/components/dropdown-table/index.d.ts +1 -1
  53. package/dist/src/components/dropdown-table/index.shadow.d.ts +1 -1
  54. package/dist/src/components/dropdown-table/mono-data-dropdown.d.ts +1 -1
  55. package/dist/src/components/form/form-types.d.ts +9 -3
  56. package/dist/src/components/input/input-core.d.ts +1 -1
  57. package/dist/src/components/input/input-types.d.ts +1 -1
  58. package/dist/src/components/otp/otp-core.d.ts +1 -1
  59. package/dist/src/components/select/select-core.d.ts +1 -1
  60. package/dist/src/components/select/select-types.d.ts +1 -1
  61. package/dist/src/components/slider/slider-core.d.ts +1 -1
  62. package/dist/src/components/slider/slider-types.d.ts +1 -1
  63. package/dist/src/components/table/filter-suggestion.d.ts +171 -0
  64. package/dist/src/components/table/index.d.ts +5 -4
  65. package/dist/src/components/table/index.shadow.d.ts +5 -4
  66. package/dist/src/components/table/mono-data-grid.d.ts +22 -3
  67. package/dist/src/components/table/mono-table-empty-core.d.ts +37 -0
  68. package/dist/src/components/table/mono-table-search-core.d.ts +22 -3
  69. package/dist/src/components/table/table-types.d.ts +74 -4
  70. package/dist/src/components/tag-input/tag-input-core.d.ts +1 -1
  71. package/dist/src/components/tag-input/tag-input-types.d.ts +1 -1
  72. package/dist/src/components/textarea/textarea-core.d.ts +1 -1
  73. package/dist/src/composables/mono-event.d.ts +7 -1
  74. package/dist/src/entries/index.d.ts +8 -6
  75. package/dist/src/entries/index.node.d.ts +8 -6
  76. package/dist/src/search/index.d.ts +1 -1
  77. package/dist/src/utils/group-count.d.ts +36 -0
  78. package/dist/switch-utils-CTZ4id2V.js +338 -0
  79. package/dist/tabs-core-r5-B8k_N.js +317 -0
  80. package/dist/tag-input-utils-D2JA90DQ.js +3060 -0
  81. package/dist/textarea-utils-VU1KeXm8.js +821 -0
  82. package/dist/ui/accordion.js +2 -274
  83. package/dist/ui/alert.js +2 -131
  84. package/dist/ui/breadcrumb.js +4 -745
  85. package/dist/ui/button-dropdown.js +4 -652
  86. package/dist/ui/button.js +2 -63
  87. package/dist/ui/card.js +2 -310
  88. package/dist/ui/chart.js +4 -800
  89. package/dist/ui/checkbox.js +4 -335
  90. package/dist/ui/chip.js +4 -402
  91. package/dist/ui/date.js +3 -732
  92. package/dist/ui/drawer.js +3 -757
  93. package/dist/ui/dropdown-table.js +5 -1341
  94. package/dist/ui/dropdown.js +4 -509
  95. package/dist/ui/file-upload.js +3 -622
  96. package/dist/ui/filter.js +5 -380
  97. package/dist/ui/form.js +1 -1
  98. package/dist/ui/index.css +118 -1
  99. package/dist/ui/input.js +3 -1141
  100. package/dist/ui/menu.js +4 -828
  101. package/dist/ui/modal.js +4 -843
  102. package/dist/ui/nav.js +4 -223
  103. package/dist/ui/otp.js +4 -756
  104. package/dist/ui/radio.js +4 -317
  105. package/dist/ui/rich-text-editor.js +4 -1278
  106. package/dist/ui/select.js +5 -2138
  107. package/dist/ui/shadow/accordion.js +4 -273
  108. package/dist/ui/shadow/alert.js +4 -130
  109. package/dist/ui/shadow/breadcrumb.js +5 -744
  110. package/dist/ui/shadow/button-dropdown.js +6 -652
  111. package/dist/ui/shadow/button.js +3 -63
  112. package/dist/ui/shadow/card.js +4 -309
  113. package/dist/ui/shadow/chart.js +6 -1576
  114. package/dist/ui/shadow/checkbox.js +4 -334
  115. package/dist/ui/shadow/chip.js +4 -396
  116. package/dist/ui/shadow/date.js +7 -731
  117. package/dist/ui/shadow/drawer.js +4 -756
  118. package/dist/ui/shadow/dropdown-table.js +8 -1762
  119. package/dist/ui/shadow/dropdown.js +4 -508
  120. package/dist/ui/shadow/file-upload.js +4 -620
  121. package/dist/ui/shadow/filter.js +7 -379
  122. package/dist/ui/shadow/input.js +6 -1140
  123. package/dist/ui/shadow/menu.js +5 -828
  124. package/dist/ui/shadow/modal.js +6 -1063
  125. package/dist/ui/shadow/nav.js +5 -223
  126. package/dist/ui/shadow/otp.js +6 -754
  127. package/dist/ui/shadow/radio.js +4 -316
  128. package/dist/ui/shadow/rich-text-editor.js +4 -1276
  129. package/dist/ui/shadow/select.js +6 -2136
  130. package/dist/ui/shadow/sidebar.js +5 -581
  131. package/dist/ui/shadow/slider.js +5 -1010
  132. package/dist/ui/shadow/switch.js +4 -335
  133. package/dist/ui/shadow/table.js +10 -4501
  134. package/dist/ui/shadow/tabs.js +6 -315
  135. package/dist/ui/shadow/tag-input.js +7 -3057
  136. package/dist/ui/shadow/textarea.js +6 -817
  137. package/dist/ui/sidebar.js +3 -581
  138. package/dist/ui/slider.js +4 -1012
  139. package/dist/ui/switch.js +4 -336
  140. package/dist/ui/table.js +9 -4502
  141. package/dist/ui/tabs.js +4 -315
  142. package/dist/ui/tag-input.js +5 -3058
  143. package/dist/ui/textarea.js +4 -819
  144. package/dist/vue.d.ts +3 -2
  145. package/package.json +3 -3
  146. package/dist/chip-strip-bNfLn52Z.js +0 -215
  147. package/dist/data-source-controller-Dx6IQ2CN.js +0 -243
  148. package/dist/data-source-options-BM4r4PRw.js +0 -558
  149. package/dist/data-source-read-HyBCRg1t.js +0 -242
  150. package/dist/excel-BXzr3uI1.js +0 -784
  151. package/dist/export-ixRdCS2y.js +0 -2388
  152. package/dist/field-tooltip-addon-CWCp19mJ.js +0 -702
  153. package/dist/field-tooltip.css_raw-U5UeTa2d.js +0 -269
  154. package/dist/filter-builder-C0T3pMx2.js +0 -208
  155. package/dist/form-control-core-BbiACMtL.js +0 -226
  156. package/dist/icon-ClxnYhBG.js +0 -19
  157. package/dist/import-Dc4eXC02.js +0 -612
  158. package/dist/light-slots-_no0r2Z-.js +0 -246
  159. package/dist/markdown-uGlE_OfJ.js +0 -20191
  160. package/dist/mono-data-grid-e9ZVBlNN.js +0 -4240
  161. package/dist/normalize-error-BmLbgANw.js +0 -1048
@@ -1,1345 +1,12 @@
1
- import { C as monoPendingGrace, _ as buildSizeStyle, a as __decorate, c as defineHybridPropAlias, d as optionalNumberConverter, f as customElement, i as withShadowUtilityStyles, l as defineHybridPropAliases, r as toShadowCss, s as booleanStringConverter, t as flushSsrHydration, u as numberStringConverter, v as toCssSize } from "../../hydration-flush-BaE9gN3C.js";
2
- import { t as dispatchMonoEvent } from "../../mono-event-BPku9HpS.js";
3
- import { n as detachEventHandlers, t as applyProps } from "../../element-props-xvw0EB7H.js";
4
- import { t as MonoFormControlCore } from "../../form-control-core-BbiACMtL.js";
5
- import { a as closeIcon, i as chevronIcon, n as caretIcon } from "../../field-icons-t8rXRCKs.js";
6
- import { n as FieldTooltipController, t as field_tooltip_css_raw_default } from "../../field-tooltip.css_raw-U5UeTa2d.js";
7
- import { n as label_position_css_raw_default, r as FieldValidationController, t as field_validation_css_raw_default } from "../../field-validation.css_raw-Cx6SGrfP.js";
8
- import { n as applyPopupPlacement, r as computePopupPlacement, t as PopupPortalController } from "../../popup-portal-CINuVjNY.js";
9
- import { t as createNotifier } from "../../notifier-BIrqUzRh.js";
10
- import { t as monoDataGrid } from "../../mono-data-grid-e9ZVBlNN.js";
11
- import { n as resolveChipLimit, r as visibleChipCap, t as ChipStripController } from "../../chip-strip-bNfLn52Z.js";
12
- import { LitElement, html, isServer, nothing, unsafeCSS } from "lit";
13
- import { property } from "lit/decorators.js";
14
- import { ifDefined } from "lit/directives/if-defined.js";
15
- import { styleMap } from "lit/directives/style-map.js";
1
+ import { t as monoDataDropdown } from "../../mono-data-dropdown-Bgj2PDfm.js";
2
+ import { t as customElement } from "../../mono-element-CKcT0rwv.js";
3
+ import { t as __decorate } from "../../decorate-DbYFpi8R.js";
4
+ import { t as MonoDropdownTableCore } from "../../dropdown-table-core-SfHUJVFq.js";
5
+ import { i as withShadowUtilityStyles, r as toShadowCss, t as flushSsrHydration } from "../../hydration-flush-Volt9X7Q.js";
6
+ import { n as label_position_css_raw_default, t as field_validation_css_raw_default } from "../../field-validation.css_raw-BU7C6173.js";
7
+ import { t as field_tooltip_css_raw_default } from "../../field-tooltip.css_raw-DVblekCl.js";
8
+ import { LitElement, html, isServer, unsafeCSS } from "lit";
16
9
 
17
- //#region src/components/dropdown-table/dropdown-table-core.ts
18
- /** Sentinel so an initial `model-value === our last emit` guard never matches by accident. */
19
- const SYMBOL_INIT = Symbol("init");
20
- /**
21
- * `MonoDropdownTableCore` — the field + popup shell for `<mono-dropdown-table>`. The
22
- * FIELD mirrors `<mono-select>` (same size/color/variant/validation/label props and
23
- * an identical look); the selection/value/display magic lives in the bound
24
- * {@link MonoDropdownController} (`monoDataDropdown`). The consumer's native `<table>`
25
- * + `mono-table-*` are slotted into the body-portaled panel; row clicks delegate to
26
- * `dd.toggleRow`. The panel is sized independently of the field via the `dropdown`
27
- * object (`matchWidth` is intentionally off). Reuses `PopupPortalController`,
28
- * `buildSizeStyle`, and the global `.mono-chip` classes.
29
- */
30
- const MonoDropdownTableCore = (superClass) => {
31
- class MonoDropdownTableCoreClass extends MonoFormControlCore(superClass) {
32
- static {
33
- this.monoPendingAuto = "data";
34
- }
35
- _monoPendingReady() {
36
- const grid = this._dd?.grid;
37
- if (!grid) return monoPendingGrace(this);
38
- if (grid.hasLoaded || grid.error) return true;
39
- return monoPendingGrace(this) && !grid.loading;
40
- }
41
- constructor(...args) {
42
- super(...args);
43
- this.size = "md";
44
- this.color = "primary";
45
- this.variant = "outlined";
46
- this.labelPosition = "top";
47
- this.validationPosition = "bottom";
48
- this.label = "";
49
- this.placeholder = "Select…";
50
- this.helperText = "";
51
- this.tooltip = null;
52
- this._tooltip = new FieldTooltipController(this, () => this.tooltip);
53
- this._validation = new FieldValidationController(this, () => ({
54
- position: this.validationPosition,
55
- ...this._validationNotice ?? {
56
- state: void 0,
57
- text: void 0
58
- },
59
- suppressed: this._isOpen || this._moreOpen
60
- }), () => this.renderRoot?.querySelector?.("[mono-dropdown-table] > [mono-dd-control] > [mono-dd-trigger]"));
61
- this.validationState = "default";
62
- this.validationMessage = "";
63
- this.errorMessage = "";
64
- this.successMessage = "";
65
- this.required = false;
66
- this.disabled = false;
67
- this.readonly = false;
68
- this.clearable = false;
69
- this.multiple = false;
70
- this.maxVisible = 5;
71
- this.chip = {};
72
- this.modelValue = void 0;
73
- this.placement = "bottom-start";
74
- this.flip = true;
75
- this.shift = true;
76
- this.offset = 6;
77
- this.autoFocusSearch = true;
78
- this.stayOpen = false;
79
- this.cssClass = {};
80
- this.cssClassName = "";
81
- this._moreOpen = false;
82
- this._resolvedSide = "bottom";
83
- this._lastEmitted = SYMBOL_INIT;
84
- this._chipStrip = new ChipStripController(this, {
85
- strip: () => this.renderRoot?.querySelector(".mono-dropdown-table-chip-strip"),
86
- enabled: () => this._inlineChips
87
- });
88
- this._popup = new PopupPortalController(this, {
89
- getPanel: () => this.renderRoot.querySelector(".mono-dropdown-table-panel"),
90
- getAnchor: () => this.renderRoot.querySelector(".mono-dropdown-table-trigger"),
91
- getStyleScope: () => this.renderRoot.querySelector(".mono-dropdown-table"),
92
- isOpen: () => this._isOpen,
93
- matchWidth: false,
94
- ...this._placementOpts(),
95
- onSideResolved: (side) => {
96
- this._resolvedSide = side;
97
- this._applySideClass();
98
- }
99
- });
100
- this._morePopup = new PopupPortalController(this, {
101
- getPanel: () => this.renderRoot.querySelector(".mono-dropdown-table-more"),
102
- getAnchor: () => this.renderRoot.querySelector(".mono-dropdown-table-more-chip"),
103
- getStyleScope: () => this.renderRoot.querySelector(".mono-dropdown-table"),
104
- isOpen: () => this._moreOpen,
105
- matchWidth: false,
106
- ...this._morePlacementOpts()
107
- });
108
- this._ddPropsQueued = false;
109
- this._onTriggerKeydown = (e) => {
110
- if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
111
- e.preventDefault();
112
- this.open();
113
- } else if (e.key === "Escape" && this._isOpen) {
114
- e.preventDefault();
115
- this.close();
116
- }
117
- };
118
- this._onDocPointer = (e) => {
119
- if (this.stayOpen) return;
120
- if (!this._isOpen && !this._moreOpen) return;
121
- const path = e.composedPath();
122
- if (path.includes(this)) return;
123
- if (this._popup.containsInPath(path)) return;
124
- if (this._morePopup.containsInPath(path)) return;
125
- this.close();
126
- };
127
- this._onDocKey = (e) => {
128
- if (e.key !== "Escape") return;
129
- if (!this._isOpen && !this._moreOpen) return;
130
- const path = e.composedPath();
131
- if (this._popup.ownsNestedInPath(path) || this._popup.inLayerAbove(path)) return;
132
- this.close();
133
- };
134
- this._onPanelClick = (e) => {
135
- if (this.disabled || this.readonly) return;
136
- const path = e.composedPath();
137
- if (path.some((n) => n?.matches?.("mono-table-checkbox, mono-shadow-table-checkbox, mono-checkbox, mono-shadow-checkbox, .mono-checkbox, input, button, a, select, textarea"))) return;
138
- const row = path.find((n) => n?.matches?.("[data-row-key]"));
139
- if (!row) return;
140
- const key = row.getAttribute("data-row-key");
141
- if (key == null) return;
142
- this._activeRowKey = key;
143
- this._focusZone = "list";
144
- this._dd?.toggleRow(key);
145
- this._reflectSelection();
146
- };
147
- this._onViewportChange = () => {
148
- if (!this._isOpen && !this._moreOpen || this._viewportFrame) return;
149
- this._viewportFrame = requestAnimationFrame(() => {
150
- this._viewportFrame = 0;
151
- if (this._isOpen) this._positionPanel();
152
- if (this._moreOpen) this._positionMorePanel();
153
- });
154
- };
155
- this._viewportBound = false;
156
- this._viewportFrame = 0;
157
- this._docBound = false;
158
- this._wasOpen = false;
159
- this._lastSelectedCount = 0;
160
- this._searchFocused = false;
161
- this._focusZone = "search";
162
- this._activeRowKey = null;
163
- this._panelTabHeld = false;
164
- this._panelTabConsumed = false;
165
- this._onPanelKeydown = (e) => {
166
- if (this.disabled || this.readonly || !this._isOpen) return;
167
- if (e.key === "Tab") {
168
- if (!this._searchEl()) return;
169
- e.preventDefault();
170
- if (!e.repeat) {
171
- this._panelTabHeld = true;
172
- this._panelTabConsumed = false;
173
- }
174
- return;
175
- }
176
- if (this._panelTabHeld && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
177
- e.preventDefault();
178
- this._panelTabConsumed = true;
179
- if (e.key === "ArrowDown") this._enterList();
180
- else this._enterSearch();
181
- return;
182
- }
183
- if (e.key === "ArrowDown" || e.key === "ArrowUp") {
184
- if (this._focusZone !== "list") return;
185
- e.preventDefault();
186
- this._moveActiveRow(e.key === "ArrowDown" ? 1 : -1);
187
- return;
188
- }
189
- if (e.key === "Enter" && this._focusZone === "list") {
190
- e.preventDefault();
191
- this._selectActiveRow();
192
- }
193
- };
194
- this._onPanelKeyup = (e) => {
195
- if (e.key !== "Tab" || !this._panelTabHeld) return;
196
- this._panelTabHeld = false;
197
- if (this._panelTabConsumed) return;
198
- if (this._focusZone === "search") this._enterList();
199
- else this._enterSearch();
200
- };
201
- defineHybridPropAliases(this, [
202
- "labelPosition",
203
- "validationPosition",
204
- "dataDropdown",
205
- "modelValue",
206
- "cssClass",
207
- "autoFocusSearch",
208
- "stayOpen",
209
- "maxVisible",
210
- "minVisible"
211
- ]);
212
- defineHybridPropAlias(this, "controlDataDropdown", "dataDropdown");
213
- for (const alias of ["css-class", "cssclass"]) Object.defineProperty(this, alias, {
214
- get: () => this.cssClass,
215
- set: (value) => this._setCssClass(value),
216
- configurable: true,
217
- enumerable: false
218
- });
219
- }
220
- /** Normalize an object | JSON string | plain-string `css-class` value. */
221
- _setCssClass(value) {
222
- if (value == null) {
223
- this.cssClass = {};
224
- this.cssClassName = "";
225
- return;
226
- }
227
- if (typeof value === "object") {
228
- this.cssClass = value;
229
- return;
230
- }
231
- if (typeof value === "string") {
232
- const trimmed = value.trim();
233
- if (!trimmed) {
234
- this.cssClass = {};
235
- this.cssClassName = "";
236
- return;
237
- }
238
- if (trimmed.startsWith("{") && trimmed.endsWith("}")) try {
239
- this.cssClass = JSON.parse(trimmed);
240
- return;
241
- } catch {}
242
- this.cssClassName = trimmed;
243
- }
244
- }
245
- /** Append the consumer's per-part override to a built-in class. */
246
- _cls(base, key) {
247
- const extra = this.cssClass?.[key];
248
- return extra ? `${base} ${extra}` : base;
249
- }
250
- /**
251
- * `chip` is an object prop, so the real binding is `:chip.prop="{…}"`. This
252
- * covers the two ways a *string* can arrive: a hand-written JSON attribute
253
- * (`chip='{"size":"md"}'`, incl. DSD/SSR), and Vue's `String(value)` mirror
254
- * of a plain `:chip="{…}"` binding — which yields `"[object Object]"` and
255
- * must be ignored, or it would wipe the property set moments later.
256
- */
257
- _setChip(value) {
258
- if (value == null) {
259
- this.chip = {};
260
- return;
261
- }
262
- if (typeof value === "object") {
263
- this.chip = value;
264
- return;
265
- }
266
- if (typeof value !== "string") return;
267
- const trimmed = value.trim();
268
- if (!trimmed) {
269
- this.chip = {};
270
- return;
271
- }
272
- if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return;
273
- try {
274
- this.chip = JSON.parse(trimmed);
275
- } catch {}
276
- }
277
- static get observedAttributes() {
278
- return [
279
- ...super.observedAttributes ?? [],
280
- "css-class",
281
- "cssclass",
282
- "chip"
283
- ];
284
- }
285
- attributeChangedCallback(name, old, value) {
286
- super.attributeChangedCallback(name, old, value);
287
- if (name === "css-class" || name === "cssclass") this._setCssClass(value);
288
- if (name === "chip") this._setChip(value);
289
- }
290
- /** The validation message and its state — the same precedence the message row uses. */
291
- get _validationNotice() {
292
- if (this.validationMessage) return {
293
- state: this._validationState,
294
- text: this.validationMessage
295
- };
296
- if (this.errorMessage) return {
297
- state: "invalid",
298
- text: this.errorMessage
299
- };
300
- if (this.successMessage) return {
301
- state: "valid",
302
- text: this.successMessage
303
- };
304
- return null;
305
- }
306
- /** Imperatively sync the `is-<side>` class — see `_resolvedSide`. */
307
- _applySideClass() {
308
- const root = this.renderRoot.querySelector(".mono-dropdown-table");
309
- if (!root) return;
310
- root.classList.toggle("is-top", this._resolvedSide === "top");
311
- root.classList.toggle("is-bottom", this._resolvedSide === "bottom");
312
- root.classList.toggle("is-left", this._resolvedSide === "left");
313
- root.classList.toggle("is-right", this._resolvedSide === "right");
314
- if (root.getAttribute("mono-side") !== this._resolvedSide) root.setAttribute("mono-side", this._resolvedSide);
315
- }
316
- /** Shared by the light path (the controller) and the shadow path (`_positionMorePanel`). */
317
- _morePlacementOpts() {
318
- return {
319
- side: () => "bottom",
320
- align: () => "start",
321
- offset: () => 4,
322
- flip: () => true,
323
- shift: () => true,
324
- constrainSize: () => true
325
- };
326
- }
327
- /**
328
- * Placement options shared by the light path (the controller) and the shadow
329
- * path (`_positionPanel`), so both run the identical algorithm.
330
- *
331
- * `constrainSize` is on: a field low in a dense grid can have less room than
332
- * the panel wants on BOTH sides, so flipping alone isn't enough — the panel
333
- * also has to shrink and scroll internally (see dropdown-table.css).
334
- */
335
- _placementOpts() {
336
- return {
337
- side: () => this._sideFromPlacement(this.placement),
338
- align: () => this._alignFromPlacement(this.placement),
339
- offset: () => this.offset,
340
- flip: () => this.flip,
341
- shift: () => this.shift,
342
- constrainSize: () => true
343
- };
344
- }
345
- _sideFromPlacement(p) {
346
- if (p.startsWith("top")) return "top";
347
- if (p.startsWith("left")) return "left";
348
- if (p.startsWith("right")) return "right";
349
- return "bottom";
350
- }
351
- _alignFromPlacement(p) {
352
- if (p.endsWith("-start")) return "start";
353
- if (p.endsWith("-end")) return "end";
354
- return "center";
355
- }
356
- get _dd() {
357
- return this.dataDropdown;
358
- }
359
- get _isOpen() {
360
- return !!this._dd?.open;
361
- }
362
- get _multi() {
363
- return this.multiple || !!this._dd?.multiple;
364
- }
365
- get _hasValue() {
366
- const v = this._dd?.value;
367
- return this._multi ? Array.isArray(v) && v.length > 0 : v != null;
368
- }
369
- /** Resolve the effective validation state (message props force it). */
370
- get _validationState() {
371
- if (this.validationState && this.validationState !== "default") return this.validationState;
372
- if (this.errorMessage) return "invalid";
373
- if (this.successMessage) return "valid";
374
- return "default";
375
- }
376
- get _wrapperClasses() {
377
- const v = this._validationState;
378
- return [
379
- "mono-dropdown-table",
380
- this.size,
381
- this.color,
382
- this.variant,
383
- `is-${this._resolvedSide}`,
384
- this._isOpen ? "open" : "",
385
- this._moreOpen ? "more-open" : "",
386
- this.disabled ? "disabled" : "",
387
- this.readonly ? "readonly" : "",
388
- v !== "default" ? `is-${v}` : "",
389
- this._hasValue ? "has-value" : "",
390
- this._multi ? "multiple" : "",
391
- this.cssClassName,
392
- this.cssClass?.root
393
- ].filter(Boolean).join(" ");
394
- }
395
- get _triggerClasses() {
396
- return [
397
- "mono-dropdown-table-trigger",
398
- this.size,
399
- this.color,
400
- this.variant,
401
- this.disabled ? "disabled" : "",
402
- this.readonly ? "readonly" : "",
403
- this.cssClass?.trigger
404
- ].filter(Boolean).join(" ");
405
- }
406
- connectedCallback() {
407
- super.connectedCallback();
408
- this._subscribe();
409
- this._wireDropdown();
410
- if (!isServer) this._syncViewportListeners();
411
- }
412
- disconnectedCallback() {
413
- this._off?.();
414
- this._off = void 0;
415
- this._panelObserver?.disconnect();
416
- this._panelObserver = void 0;
417
- if (this._dropdownWired) this._dropdownWired.onValueChange = null;
418
- if (!isServer) {
419
- document.removeEventListener("pointerdown", this._onDocPointer, true);
420
- document.removeEventListener("keydown", this._onDocKey, true);
421
- this._docBound = false;
422
- window.removeEventListener("scroll", this._onViewportChange, true);
423
- window.removeEventListener("resize", this._onViewportChange);
424
- if (this._viewportFrame) cancelAnimationFrame(this._viewportFrame);
425
- this._viewportFrame = 0;
426
- this._viewportBound = false;
427
- }
428
- super.disconnectedCallback();
429
- }
430
- willUpdate(changed) {
431
- if (changed.has("dataDropdown")) {
432
- this._subscribe();
433
- this._wireDropdown();
434
- }
435
- if (changed.has("modelValue")) this._pushModelToDd();
436
- if (changed.has("dataDropdown") || changed.has("max") || changed.has("min") || changed.has("chip")) this._pushLimits();
437
- super.willUpdate?.(changed);
438
- }
439
- /**
440
- * Second entry point for the props apply. `MonoFormControlCore` (composed
441
- * below this core) also overrides `update`, so chain `super`.
442
- */
443
- update(changed) {
444
- this._scheduleApplyDropdownProps();
445
- super.update(changed);
446
- }
447
- _subscribe() {
448
- this._off?.();
449
- detachEventHandlers(this);
450
- this._off = this._dd?.subscribe(() => {
451
- this._scheduleApplyDropdownProps();
452
- this.requestUpdate();
453
- });
454
- this._scheduleApplyDropdownProps();
455
- }
456
- /**
457
- * Deferred + de-duplicated, and driven from `update()` as well as
458
- * `_subscribe()` — the same belt-and-braces the table base needed once two
459
- * cores were found replacing `_subscribe` without chaining `super`. The
460
- * deferral keeps the reactive writes out of the update cycle, so they can't
461
- * trip Lit's change-in-update warning.
462
- */
463
- _scheduleApplyDropdownProps() {
464
- if (this._ddPropsQueued) return;
465
- if (typeof queueMicrotask !== "function") {
466
- this._applyDropdownProps();
467
- return;
468
- }
469
- this._ddPropsQueued = true;
470
- queueMicrotask(() => {
471
- this._ddPropsQueued = false;
472
- this._applyDropdownProps();
473
- });
474
- }
475
- /**
476
- * Pull `monoDataDropdown({ props: { dropdownTable } })` onto this element, so
477
- * the field needs nothing but `:data-dropdown.prop`. The CONTROLLER WINS for
478
- * keys it declares; the rest stay with the template.
479
- */
480
- _applyDropdownProps() {
481
- const dd = this._dd;
482
- if (!dd?.props) return;
483
- applyProps(this, dd.props().dropdownTable);
484
- }
485
- _wireDropdown() {
486
- const dd = this._dd;
487
- if (this._dropdownWired && this._dropdownWired !== dd) this._dropdownWired.onValueChange = null;
488
- this._dropdownWired = dd;
489
- if (!dd) return;
490
- dd.onValueChange = (v) => {
491
- this._lastEmitted = v;
492
- this.modelValue = v;
493
- this._emitChange(v);
494
- };
495
- this._pushModelToDd();
496
- }
497
- /**
498
- * The selection limits the element asks for: `chip.max` / `chip.min` pin,
499
- * `max` / `min` are the fallback, and `undefined` leaves the controller's own
500
- * option in force. They are ENFORCED by the controller's check store (the one
501
- * place a row click, the keyboard, a `<mono-table-checkbox>` and the
502
- * select-all drain all go through), so the element only forwards them.
503
- */
504
- _pushLimits() {
505
- const chip = this._chipProps;
506
- this._dd?.setLimits({
507
- max: resolveChipLimit(chip, "max", this.max),
508
- min: resolveChipLimit(chip, "min", this.min)
509
- });
510
- }
511
- /** Push an external `model-value` into the controller (guarding our own echo). */
512
- _pushModelToDd() {
513
- const dd = this._dd;
514
- if (!dd || this.modelValue === void 0) return;
515
- if (this._sameValue(this.modelValue, this._lastEmitted)) return;
516
- if (this._sameValue(this.modelValue, dd.value)) return;
517
- dd.setValue(this.modelValue);
518
- }
519
- _sameValue(a, b) {
520
- if (a === b) return true;
521
- if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, i) => String(x) === String(b[i]));
522
- return String(a) === String(b);
523
- }
524
- _emitChange(value) {
525
- const detail = {
526
- modelValue: value,
527
- value,
528
- selectedItems: this._dd?.selectedItems() ?? []
529
- };
530
- dispatchMonoEvent(this, "change", detail);
531
- }
532
- /** Whether the panel is currently open. */
533
- get isOpen() {
534
- return this._isOpen;
535
- }
536
- open() {
537
- if (this.disabled || this.readonly) return;
538
- this._dd?.setOpen(true);
539
- }
540
- close() {
541
- this._moreOpen = false;
542
- this._dd?.setOpen(false);
543
- this.requestUpdate();
544
- }
545
- toggle() {
546
- if (this.disabled || this.readonly) return;
547
- this._moreOpen = false;
548
- this._dd?.setOpen(!this._isOpen);
549
- }
550
- /**
551
- * Where the `[data-row-key]` rows live: light = the captured table inside the
552
- * (portaled) panel; shadow = the SLOTTED table (host's light-DOM children).
553
- */
554
- get _rowScope() {
555
- return this.renderRoot === this ? this._popup.panelRoot : this;
556
- }
557
- _reflectSelection(rows = this._rowEls()) {
558
- const dd = this._dd;
559
- if (!dd) return;
560
- if ((this._focusZone === "list" || this._activeRowKey != null) && rows.length && !rows.some((el) => el.getAttribute("data-row-key") === this._activeRowKey)) this._activeRowKey = rows[0].getAttribute("data-row-key");
561
- rows.forEach((el) => {
562
- const key = el.getAttribute("data-row-key");
563
- const on = key != null && dd.isSelected(key);
564
- const active = key != null && key === this._activeRowKey;
565
- el.classList.toggle("mono-dd-row-selected", on);
566
- el.classList.toggle("mono-dd-row-active", active);
567
- el.toggleAttribute("mono-selected", on);
568
- el.toggleAttribute("mono-dd-selected", on);
569
- el.toggleAttribute("mono-dd-active", active);
570
- if (on !== el.hasAttribute("aria-selected")) {
571
- if (on) el.setAttribute("aria-selected", "true");
572
- else el.removeAttribute("aria-selected");
573
- }
574
- });
575
- }
576
- /** Re-reflect after the consumer's Vue re-renders rows (paging/search). */
577
- _observePanel() {
578
- const root = this._rowScope;
579
- if (!root || this._panelObserver) return;
580
- const touchesRows = (nodes) => {
581
- for (const n of Array.from(nodes)) {
582
- if (n.nodeType !== 1) continue;
583
- const el = n;
584
- if (el.matches("[data-row-key]") || el.querySelector("[data-row-key]")) return true;
585
- }
586
- return false;
587
- };
588
- this._panelObserver = new MutationObserver((records) => {
589
- if (records.some((r) => touchesRows(r.addedNodes) || touchesRows(r.removedNodes))) this._reflectSelection();
590
- });
591
- this._panelObserver.observe(root, {
592
- childList: true,
593
- subtree: true
594
- });
595
- }
596
- /** True for the shadow build — a shadow host keeps its panel in the shadow root. */
597
- get _isShadowHost() {
598
- return this.renderRoot !== this;
599
- }
600
- /**
601
- * Position the panel for the SHADOW build (renderRoot ≠ this): the popup
602
- * controller only portals/positions LIGHT hosts (`_canPortal`), so a shadow
603
- * host places its own `position:fixed` panel. It runs the SAME shared math as
604
- * the light path — flip, shift and size-constrain included. Light is untouched.
605
- */
606
- _positionPanel() {
607
- if (isServer || !this._isShadowHost) return;
608
- if (!this._isOpen) return;
609
- const root = this.renderRoot;
610
- const panel = root.querySelector(".mono-dropdown-table-panel");
611
- const anchor = root.querySelector(".mono-dropdown-table-trigger");
612
- if (!panel || !anchor) return;
613
- const o = this._placementOpts();
614
- const placement = computePopupPlacement(anchor, panel, {
615
- side: o.side(),
616
- align: o.align(),
617
- offset: o.offset(),
618
- flip: o.flip(),
619
- shift: o.shift(),
620
- constrain: true
621
- });
622
- applyPopupPlacement(panel, placement, true);
623
- this._resolvedSide = placement.side;
624
- this._applySideClass();
625
- }
626
- /** The shadow build's in-place placement of the "+N more" panel — see `_positionPanel`. */
627
- _positionMorePanel() {
628
- if (isServer || !this._isShadowHost) return;
629
- if (!this._moreOpen) return;
630
- const root = this.renderRoot;
631
- const panel = root.querySelector(".mono-dropdown-table-more");
632
- const anchor = root.querySelector(".mono-dropdown-table-more-chip");
633
- if (!panel || !anchor) return;
634
- const o = this._morePlacementOpts();
635
- const placement = computePopupPlacement(anchor, panel, {
636
- side: o.side(),
637
- align: o.align(),
638
- offset: o.offset(),
639
- flip: o.flip(),
640
- shift: o.shift(),
641
- constrain: true
642
- });
643
- applyPopupPlacement(panel, placement, true);
644
- }
645
- /**
646
- * Outside-dismiss listeners, both builds, bound while a panel is OPEN only (select's rule).
647
- * Both handlers bail when the list and "+N more" panels are closed, so at rest they cost
648
- * only dispatch — two capture-phase `document` listeners per field.
649
- */
650
- _syncDocListeners() {
651
- const want = this.isConnected && (this._isOpen || this._moreOpen);
652
- if (want === this._docBound) return;
653
- this._docBound = want;
654
- if (want) {
655
- document.addEventListener("pointerdown", this._onDocPointer, true);
656
- document.addEventListener("keydown", this._onDocKey, true);
657
- } else {
658
- document.removeEventListener("pointerdown", this._onDocPointer, true);
659
- document.removeEventListener("keydown", this._onDocKey, true);
660
- }
661
- }
662
- /**
663
- * Shadow build only, and only while a panel is OPEN — the popup controller's rule. They used
664
- * to be bound at connect for every shadow instance: a capture-phase, non-passive `scroll`
665
- * listener on `window` per field, open or not, which also keeps the page's scrolling off the
666
- * compositor thread.
667
- */
668
- _syncViewportListeners() {
669
- if (isServer) return;
670
- this._syncDocListeners();
671
- const want = this._isShadowHost && this.isConnected && (this._isOpen || this._moreOpen);
672
- if (want === this._viewportBound) return;
673
- if (want) {
674
- window.addEventListener("scroll", this._onViewportChange, {
675
- capture: true,
676
- passive: true
677
- });
678
- window.addEventListener("resize", this._onViewportChange, { passive: true });
679
- } else {
680
- window.removeEventListener("scroll", this._onViewportChange, true);
681
- window.removeEventListener("resize", this._onViewportChange);
682
- if (this._viewportFrame) cancelAnimationFrame(this._viewportFrame);
683
- this._viewportFrame = 0;
684
- }
685
- this._viewportBound = want;
686
- }
687
- updated(changed) {
688
- super.updated(changed);
689
- if (isServer) return;
690
- this._syncViewportListeners();
691
- if (this._isOpen) {
692
- this._observePanel();
693
- this._reflectSelection();
694
- this._positionPanel();
695
- } else {
696
- this._panelObserver?.disconnect();
697
- this._panelObserver = void 0;
698
- }
699
- if (this._moreOpen) {
700
- if (!this._overflowItems(this._dd?.selectedItems() ?? []).length) {
701
- this._moreOpen = false;
702
- this.requestUpdate();
703
- } else this._positionMorePanel();
704
- }
705
- const selectedCount = this._dd?.selectedItems?.()?.length ?? 0;
706
- const capChanged = changed.has("maxVisible") || changed.has("minVisible") || changed.has("chip");
707
- if (selectedCount !== this._lastSelectedCount) {
708
- if (this._isOpen && selectedCount > this._lastSelectedCount && this._inlineChips) this._chipStrip.scrollToEnd();
709
- else this._chipStrip.invalidate();
710
- } else if (capChanged) this._chipStrip.invalidate();
711
- this._lastSelectedCount = selectedCount;
712
- if (this._isOpen !== this._wasOpen) {
713
- this._wasOpen = this._isOpen;
714
- if (this._isOpen) this._initPanelFocus();
715
- else {
716
- this._activeRowKey = null;
717
- this._focusZone = "search";
718
- this._panelTabHeld = false;
719
- this._restoreTriggerFocus();
720
- }
721
- }
722
- }
723
- /** The focusable trigger (`tabindex=0`), in both builds. */
724
- _triggerElement() {
725
- return this.renderRoot.querySelector(".mono-dropdown-table-trigger");
726
- }
727
- /**
728
- * Delegate focus to the trigger — the host itself isn't focusable. Needed by
729
- * anything that focuses the component from outside, e.g. the data grid
730
- * focusing the editor in a clicked cell (`focusRowCell`), which looks for an
731
- * inner `input/textarea/select/button` and otherwise falls back to calling
732
- * `focus()` on the element itself.
733
- */
734
- focus(options) {
735
- this._triggerElement()?.focus(options);
736
- }
737
- blur() {
738
- this._triggerElement()?.blur();
739
- }
740
- /** The search region's slotted content — light: captured nodes; shadow: `<slot>`. */
741
- _searchRegionElements() {
742
- if (this._isShadowHost) {
743
- const slot = this.renderRoot.querySelector("slot[name=\"search\"]");
744
- return slot ? slot.assignedElements({ flatten: true }) : [];
745
- }
746
- const sel = "[data-mono-slot=\"search\"]";
747
- const region = this.querySelector(sel) ?? this._popup.panelRoot?.querySelector?.(sel);
748
- return region ? Array.from(region.children) : [];
749
- }
750
- /**
751
- * Focus the panel's search box once the panel is rendered, placed and (light
752
- * build) portaled. Deferred a microtask so a slotted element that hasn't
753
- * rendered its input yet gets a chance to — `updateComplete` on the search
754
- * element itself, since it updates independently of this host.
755
- */
756
- /**
757
- * The element to focus for "the search box", or null when the panel has no
758
- * search region. `mono-table-search` / `mono-shadow-table-search` expose
759
- * `focus()` and delegate to their own input, so neither build needs a DOM
760
- * reach-in; anything else slotted in its place falls back to its first field.
761
- */
762
- _searchEl() {
763
- for (const el of this._searchRegionElements()) {
764
- if (el.matches("mono-table-search, mono-shadow-table-search")) return el;
765
- const sel = "input:not([type=\"hidden\"]), textarea, select";
766
- const field = el.matches(sel) ? el : el.querySelector(sel) ?? el.shadowRoot?.querySelector(sel);
767
- if (field) return field;
768
- }
769
- return null;
770
- }
771
- async _focusSearch() {
772
- await this.updateComplete;
773
- if (!this._isOpen) return;
774
- const el = this._searchEl();
775
- if (!el) return;
776
- const pending = el.updateComplete;
777
- if (pending) await pending;
778
- if (!this._isOpen) return;
779
- el.focus({ preventScroll: true });
780
- this._focusZone = "search";
781
- this._searchFocused = true;
782
- }
783
- _rowEls() {
784
- const root = this._rowScope;
785
- if (!root?.querySelectorAll) return [];
786
- return Array.from(root.querySelectorAll("[data-row-key]"));
787
- }
788
- _panelEl() {
789
- return (this._popup.panelRoot ?? this.renderRoot)?.querySelector?.(".mono-dropdown-table-panel") ?? null;
790
- }
791
- /** `rows`: the caller's own `_rowEls()` — one query per arrow key, not three. */
792
- _setActiveRow(key, reveal = false, rows = this._rowEls()) {
793
- this._activeRowKey = key;
794
- this._reflectSelection(rows);
795
- if (!reveal || key == null) return;
796
- rows.find((r) => r.getAttribute("data-row-key") === key)?.scrollIntoView?.({ block: "nearest" });
797
- }
798
- _moveActiveRow(delta) {
799
- const rows = this._rowEls();
800
- const keys = rows.map((r) => r.getAttribute("data-row-key") ?? "");
801
- if (!keys.length) return;
802
- const i = this._activeRowKey == null ? -1 : keys.indexOf(this._activeRowKey);
803
- const next = i < 0 ? delta > 0 ? 0 : keys.length - 1 : Math.min(Math.max(i + delta, 0), keys.length - 1);
804
- this._setActiveRow(keys[next], true, rows);
805
- }
806
- /** Move the keyboard into the row list, highlighting the first row. */
807
- _enterList() {
808
- this._focusZone = "list";
809
- if (this._activeRowKey == null) this._setActiveRow(this._rowEls()[0]?.getAttribute("data-row-key") ?? null, true);
810
- this._panelEl()?.focus({ preventScroll: true });
811
- }
812
- /** Move the keyboard back to the search box (no-op when there isn't one). */
813
- _enterSearch() {
814
- const el = this._searchEl();
815
- if (!el) return;
816
- this._focusZone = "search";
817
- el.focus({ preventScroll: true });
818
- }
819
- _selectActiveRow() {
820
- if (this._activeRowKey == null) return;
821
- this._dd?.toggleRow(this._activeRowKey);
822
- this._reflectSelection();
823
- }
824
- /**
825
- * Where the keyboard starts when the panel opens: the search box if there is
826
- * one, otherwise straight into the list with the first row highlighted.
827
- */
828
- async _initPanelFocus() {
829
- await this.updateComplete;
830
- if (!this._isOpen) return;
831
- const selected = this._dd?.selectedItems?.() ?? [];
832
- if (selected.length) this._setActiveRow(String(selected[selected.length - 1].key), true);
833
- if (this._searchEl()) {
834
- this._focusZone = "search";
835
- if (this.autoFocusSearch) this._focusSearch();
836
- return;
837
- }
838
- this._enterList();
839
- }
840
- /**
841
- * Hand focus back to the trigger when a panel that HAD focus closes — hiding
842
- * the panel blurs its input to `<body>`, which would otherwise strand the
843
- * keyboard. Covers every close path (Escape, outside pointerdown, a
844
- * controller-driven auto-close after a single-select pick) because it hangs
845
- * off the state edge rather than off `close()`.
846
- */
847
- _restoreTriggerFocus() {
848
- if (!this._searchFocused) return;
849
- this._searchFocused = false;
850
- const active = document.activeElement;
851
- const panel = this._popup.panelRoot?.querySelector?.(".mono-dropdown-table-panel");
852
- if (!(!active || active === document.body || this.contains(active) || !!panel?.contains(active))) return;
853
- this.focus({ preventScroll: true });
854
- }
855
- /** A panel region — light: a `data-mono-slot` capture target; shadow overrides with `<slot>`. */
856
- _renderRegion(cls, name) {
857
- return html`<div class="mono-dropdown-table-region ${cls}" mono-dd-region=${cls} data-mono-slot="${name}"></div>`;
858
- }
859
- _caretIcon() {
860
- return caretIcon();
861
- }
862
- _chevronIcon(dir) {
863
- return chevronIcon(dir);
864
- }
865
- /**
866
- * One scroll button. `active` false keeps the box — and therefore the row's
867
- * width — but hides it (`is-idle` → `visibility: hidden`), so reaching an end
868
- * of the strip costs no layout. `aria-hidden` keeps the hidden one out of
869
- * reach of assistive tech; `pointer-events: none` handles the pointer.
870
- */
871
- _renderScrollButton(dir, active) {
872
- const back = dir === -1;
873
- const base = `mono-dropdown-table-scroll mono-dropdown-table-scroll-${back ? "prev" : "next"}${active ? "" : " is-idle"}`;
874
- return html`<span
875
- role="button"
876
- tabindex="-1"
877
- class=${this._cls(base, back ? "scrollPrev" : "scrollNext")}
878
- mono-dd-scroll=${back ? "prev" : "next"}
879
- ?mono-idle=${!active}
880
- aria-label=${back ? "Scroll selection backward" : "Scroll selection forward"}
881
- aria-hidden=${active ? "false" : "true"}
882
- @mousedown=${(e) => e.preventDefault()}
883
- @click=${(e) => {
884
- e.stopPropagation();
885
- this._chipStrip.page(dir);
886
- }}
887
- >${this._chevronIcon(dir)}</span
888
- >`;
889
- }
890
- /** The `chip` prop, always an object (it can be assigned null from a binding). */
891
- get _chipProps() {
892
- return this.chip ?? {};
893
- }
894
- /** Chip layout: `inline` = one scrolling line, anything else = today's wrap. */
895
- get _chipBehaviour() {
896
- return this._chipProps.behaviour === "inline" ? "inline" : "flex";
897
- }
898
- /** True where a scrolling strip actually renders: multi, inline, with chips. */
899
- get _inlineChips() {
900
- return this._multi && this._hasValue && this._chipBehaviour === "inline";
901
- }
902
- /**
903
- * How many chips to draw for `total` selected rows before the rest collapse
904
- * into "+N more" — Infinity when uncapped or under the collapse floor.
905
- * `chip.maxVisible` / `chip.minVisible` pin, the element props are the
906
- * fallback (`resolveChipLimit`). Applies to `inline` as well: the "+N more"
907
- * chip then sits in the strip after the visible ones and its panel lists the
908
- * rest, exactly as in `flex`.
909
- */
910
- _visibleCap(total) {
911
- const chip = this._chipProps;
912
- return visibleChipCap(total, resolveChipLimit(chip, "maxVisible", this.maxVisible), resolveChipLimit(chip, "minVisible", this.minVisible));
913
- }
914
- /** The selection floor in force (element / chip / controller), 0 when none. */
915
- get _minSelected() {
916
- return this._dd?.limits().min ?? 0;
917
- }
918
- /** A chip can be removed while the selection sits above its floor. */
919
- get _canRemove() {
920
- return (this._dd?.selectedItems?.()?.length ?? 0) > this._minSelected;
921
- }
922
- /**
923
- * Chip skin matching the field skin: a `filled` field already tints its own
924
- * surface, so a soft chip would vanish into it — go solid; `underlined` is
925
- * minimal, so the chip stays outline. `chip.variant` pins one instead.
926
- */
927
- get _chipVariantClass() {
928
- const pinned = this._chipProps.variant;
929
- if (pinned) return pinned;
930
- if (this.variant === "filled") return "solid";
931
- if (this.variant === "underlined") return "outline";
932
- return "soft";
933
- }
934
- /** Chips wear the control's color unless `chip.color` pins another. */
935
- get _chipColorClass() {
936
- return this._chipProps.color ?? this.color;
937
- }
938
- /**
939
- * Classes shared by the selection chips and the "+N more" chip, in
940
- * `mono-chip`'s own order (`mono-chip <size> <variant>-<color> <shape>`), so
941
- * chip.css paints them exactly as it paints a real `<mono-chip>`.
942
- *
943
- * `mono-dropdown-table-chip` is a marker only — it scopes the `--mono-chip-*`
944
- * bridge in dropdown-table.css so the bridge never reaches a `<mono-chip>` a
945
- * consumer slots into the panel. `chip.color` deliberately picks a hue OTHER
946
- * than the control accent, so it adds the `-pinned` marker that switches the
947
- * bridge back off.
948
- */
949
- get _chipBaseClasses() {
950
- const chip = this._chipProps;
951
- return [
952
- "mono-dropdown-table-chip",
953
- chip.color ? "mono-dropdown-table-chip-pinned" : "",
954
- chip.size ?? (this.size === "xs" || this.size === "sm" ? "xs" : "sm"),
955
- `${this._chipVariantClass}-${this._chipColorClass}`,
956
- "",
957
- chip.dot ? "has-dot" : ""
958
- ].filter(Boolean).join(" ");
959
- }
960
- /**
961
- * Class for one chip part. Both class APIs append: the field-level key
962
- * (`cssClass.chip` / `.chipLabel` / `.chipRemove`) and the chip-level one
963
- * (`chip.cssClass.*`, which additionally reaches the parts the field has no
964
- * key for — `main`, `content`, `dot`).
965
- */
966
- _chipCls(base, chipKey, key) {
967
- return [
968
- base,
969
- key ? this.cssClass?.[key] : void 0,
970
- this._chipProps.cssClass?.[chipKey]
971
- ].filter(Boolean).join(" ");
972
- }
973
- _renderChip(it) {
974
- const chip = this._chipProps;
975
- const removable = !this.disabled && !this.readonly && this._canRemove;
976
- return html`
977
- <div
978
- class=${this._chipCls(`${this._chipBaseClasses}${removable ? " removable" : ""}`, "root", "chip")}
979
- mono-dd-chip
980
- ?mono-dd-removable=${removable}
981
- mono-dd-chip-color=${chip.color ?? nothing}
982
- mono-dd-chip-rounded=${chip.rounded ?? nothing}
983
- >
984
- <span class=${ifDefined(chip.cssClass?.main)} mono-dd-chip-main>
985
- <span class=${this._chipCls("chip-content", "content")} mono-dd-chip-content>
986
- ${chip.dot ? html`<span class=${this._chipCls("chip-dot", "dot")} mono-dd-chip-dot aria-hidden="true"></span>` : nothing}
987
- <span class=${this._chipCls("chip-label", "label", "chipLabel")} mono-dd-chip-label>${it.text}</span>
988
- ${removable ? html`<button
989
- type="button"
990
- class=${this._chipCls("chip-close", "close", "chipRemove")}
991
- mono-dd-chip-close
992
- aria-label=${chip.closeLabel ?? `Remove ${it.text}`}
993
- @click=${(e) => {
994
- e.stopPropagation();
995
- this._dd?.removeKey(it.key);
996
- }}
997
- >
998
- ${closeIcon()}
999
- </button>` : nothing}
1000
- </span>
1001
- </span>
1002
- </div>
1003
- `;
1004
- }
1005
- /**
1006
- * The chip region. `flex` returns the chips as bare children of the value
1007
- * span, so they wrap — the historical markup, unchanged. `inline` nests them
1008
- * in one `overflow-x: hidden` strip instead, which is what makes the row
1009
- * scroll as a unit.
1010
- */
1011
- _renderChipRegion(items) {
1012
- const chips = this._renderChips(items);
1013
- if (this._chipBehaviour !== "inline") return chips;
1014
- return html`
1015
- <span class=${this._cls("mono-dropdown-table-chip-strip", "chipStrip")} mono-dd-chip-strip>${chips}</span>
1016
- `;
1017
- }
1018
- _renderChips(items) {
1019
- const max = this._visibleCap(items.length);
1020
- const visible = max === Infinity ? items : items.slice(0, max);
1021
- const overflow = this._overflowItems(items);
1022
- const chips = visible.map((it) => this._renderChip(it));
1023
- if (overflow.length) chips.push(html`
1024
- <div
1025
- class=${this._cls(`${this._chipBaseClasses.replace(" has-dot", "")} clickable mono-dropdown-table-more-chip`, "moreChip")}
1026
- mono-dd-chip
1027
- mono-dd-more
1028
- mono-dd-chip-color=${this._chipProps.color ?? nothing}
1029
- mono-dd-chip-rounded=${this._chipProps.rounded ?? nothing}
1030
- >
1031
- <span
1032
- class=${ifDefined(this._chipProps.cssClass?.main)}
1033
- mono-dd-chip-main
1034
- role="button"
1035
- tabindex="0"
1036
- @mousedown=${(e) => e.preventDefault()}
1037
- @click=${(e) => {
1038
- e.stopPropagation();
1039
- const next = !this._moreOpen;
1040
- this._dd?.setOpen(false);
1041
- this._moreOpen = next;
1042
- this.requestUpdate();
1043
- }}
1044
- >
1045
- <span class=${this._chipCls("chip-content", "content")} mono-dd-chip-content
1046
- ><span class=${this._chipCls("chip-label", "label")} mono-dd-chip-label
1047
- >+${overflow.length} more</span
1048
- ></span
1049
- >
1050
- </span>
1051
- </div>
1052
- `);
1053
- return chips;
1054
- }
1055
- /** Selected rows past the visible cap — empty when uncapped or under the collapse floor. */
1056
- _overflowItems(items) {
1057
- const max = this._visibleCap(items.length);
1058
- return max === Infinity ? [] : items.slice(max);
1059
- }
1060
- /**
1061
- * Always rendered, shown by the root's `more-open` class: the panel lives in
1062
- * a body portal while open and a portaled node cannot be removed by a
1063
- * conditional render (Lit's ChildPart no longer contains it).
1064
- */
1065
- _renderMore(items) {
1066
- const overflow = this._moreOpen ? this._overflowItems(items) : [];
1067
- return html`<div class="mono-dropdown-table-more" mono-dd-more>${overflow.map((it) => this._renderChip(it))}</div>`;
1068
- }
1069
- _renderLabel() {
1070
- if (!this.label) return nothing;
1071
- return html`<label class=${this._cls("mono-dropdown-table-label", "label")} mono-dd-label
1072
- >${this.label}${this.required ? html`<span class=${this._cls("mono-dropdown-table-required", "required")} mono-dd-required-mark>*</span>` : nothing}${this._tooltip.render()}</label
1073
- >`;
1074
- }
1075
- _renderMessage() {
1076
- const base = this._cls("mono-dropdown-table-message", "message");
1077
- if (this._validation.moved) {
1078
- const notice = this._validationNotice;
1079
- return html`${this.helperText ? html`<div class="${base} helper" mono-dd-message="helper">${this.helperText}</div>` : nothing}<div
1080
- class="${base} ${notice.state}"
1081
- mono-dd-message=${notice.state}
1082
- mono-sr-only
1083
- role=${notice.state === "invalid" ? "alert" : nothing}
1084
- >${notice.text}</div>`;
1085
- }
1086
- if (this.validationMessage) {
1087
- const state = this._validationState;
1088
- return html`<div class="${base} ${state}" mono-dd-message=${state} role=${state === "invalid" ? "alert" : nothing}>
1089
- ${this.validationMessage}
1090
- </div>`;
1091
- }
1092
- if (this.errorMessage) return html`<div class="${base} invalid" mono-dd-message="invalid" role="alert">${this.errorMessage}</div>`;
1093
- if (this.successMessage) return html`<div class="${base} valid" mono-dd-message="valid">${this.successMessage}</div>`;
1094
- if (this.helperText) return html`<div class="${base} helper" mono-dd-message="helper">${this.helperText}</div>`;
1095
- return nothing;
1096
- }
1097
- _renderTrigger(items) {
1098
- const dd = this._dd;
1099
- const hasValue = this._hasValue;
1100
- const inert = this.disabled || this.readonly;
1101
- const canClear = this.clearable && hasValue && !inert && !(this._multi && this._minSelected > 0);
1102
- const inlineChips = this._inlineChips;
1103
- return html`
1104
- <div
1105
- class=${this._triggerClasses}
1106
- mono-dd-trigger
1107
- role="combobox"
1108
- tabindex=${this.disabled ? -1 : 0}
1109
- aria-expanded=${this._isOpen ? "true" : "false"}
1110
- @click=${() => this.toggle()}
1111
- @keydown=${this._onTriggerKeydown}
1112
- >
1113
- <span
1114
- class="${this._cls("mono-dropdown-table-value", "value")}${hasValue ? "" : ` mono-dropdown-table-placeholder${this.cssClass?.placeholder ? ` ${this.cssClass.placeholder}` : ""}`}${inlineChips ? " is-inline" : ""}"
1115
- mono-dd-value
1116
- ?mono-dd-placeholder=${!hasValue}
1117
- ?mono-inline=${inlineChips}
1118
- >
1119
- ${this._multi ? hasValue ? this._renderChipRegion(items) : this.placeholder : hasValue ? html`<span>${dd?.displayText()}</span>` : this.placeholder}
1120
- </span>
1121
- ${this._validation.renderIcon()}
1122
- <span class=${this._cls("mono-dropdown-table-actions", "actions")} mono-dd-actions>
1123
- ${inlineChips && this._chipStrip.overflowing ? html`${this._renderScrollButton(-1, this._chipStrip.canScrollStart)}
1124
- ${this._renderScrollButton(1, this._chipStrip.canScrollEnd)}` : nothing}
1125
- ${canClear ? html`<span
1126
- role="button"
1127
- tabindex="-1"
1128
- class=${this._cls("mono-dropdown-table-clear", "clear")}
1129
- mono-dd-clear
1130
- aria-label="Clear"
1131
- @mousedown=${(e) => e.preventDefault()}
1132
- @click=${(e) => {
1133
- e.stopPropagation();
1134
- this._dd?.clear();
1135
- this.close();
1136
- }}
1137
- >${closeIcon()}</span
1138
- >` : nothing}
1139
- ${!inert && !canClear ? html`<span
1140
- role="button"
1141
- tabindex="-1"
1142
- class=${this._cls("mono-dropdown-table-arrow", "arrow")}
1143
- mono-dd-arrow
1144
- aria-label="Toggle"
1145
- aria-expanded=${this._isOpen ? "true" : "false"}
1146
- @mousedown=${(e) => e.preventDefault()}
1147
- @click=${(e) => {
1148
- e.stopPropagation();
1149
- this.toggle();
1150
- }}
1151
- >${this._caretIcon()}</span
1152
- >` : nothing}
1153
- </span>
1154
- </div>
1155
- `;
1156
- }
1157
- /**
1158
- * Panel-only sizing from the `dropdown` object.
1159
- *
1160
- * `maxHeight` is published as the custom property `--_mono-dropdown-table-panel-max-h` rather than a direct
1161
- * `max-height`: the popup controller also constrains the panel (via `--mono-popup-avail-h`),
1162
- * and two writers on the same declaration would clobber each other across renders. The CSS
1163
- * combines both with `min()`. Everything else is a plain declaration.
1164
- *
1165
- * `height` is an EXACT height here now. It used to be the cap, because this object had no
1166
- * `maxHeight`; it does now, and the three popup components share one meaning.
1167
- */
1168
- _panelStyle() {
1169
- const d = this.dropdown;
1170
- if (!d) return {};
1171
- const s = {};
1172
- const w = toCssSize(d.width);
1173
- const mw = toCssSize(d.minWidth);
1174
- const xw = toCssSize(d.maxWidth);
1175
- const h = toCssSize(d.height);
1176
- const mh = toCssSize(d.minHeight);
1177
- const xh = toCssSize(d.maxHeight);
1178
- if (w) s.width = w;
1179
- if (mw) s["min-width"] = mw;
1180
- if (xw) s["max-width"] = xw;
1181
- if (h) s.height = h;
1182
- if (mh) s["min-height"] = mh;
1183
- if (xh) s["--_mono-dropdown-table-panel-max-h"] = xh;
1184
- return s;
1185
- }
1186
- render() {
1187
- const items = this._dd?.selectedItems() ?? [];
1188
- const state = this._validationState;
1189
- return html`
1190
- <div
1191
- class=${this._wrapperClasses}
1192
- style=${styleMap(buildSizeStyle(this))}
1193
- mono-dropdown-table
1194
- mono-size=${this.size === "md" ? nothing : this.size}
1195
- mono-color=${this.color === "primary" ? nothing : this.color}
1196
- mono-variant=${this.variant === "outlined" ? nothing : this.variant}
1197
- mono-label-position=${this.labelPosition === "top" ? nothing : this.labelPosition}
1198
- mono-validation-position=${this.validationPosition === "bottom" ? nothing : this.validationPosition}
1199
- mono-validation-state=${state === "default" ? nothing : state}
1200
- mono-side=${this._resolvedSide}
1201
- ?mono-open=${this._isOpen}
1202
- ?mono-more-open=${this._moreOpen}
1203
- ?mono-disabled=${this.disabled}
1204
- ?mono-readonly=${this.readonly}
1205
- ?mono-required=${this.required}
1206
- ?mono-clearable=${this.clearable}
1207
- ?mono-multiple=${this._multi}
1208
- ?mono-has-value=${this._hasValue}
1209
- >
1210
- ${this._renderLabel()}
1211
- <div
1212
- class="mono-dropdown-table-control${this._inlineChips ? " is-inline" : ""}"
1213
- mono-dd-control
1214
- ?mono-inline=${this._inlineChips}
1215
- >
1216
- ${this._renderTrigger(items)} ${this._renderMore(items)}
1217
- </div>
1218
- ${this._renderMessage()}
1219
- ${this._validation.renderFloat()}
1220
- <div
1221
- class="mono-dropdown-table-panel ${this._isOpen ? "open" : ""}"
1222
- mono-dd-panel
1223
- role="dialog"
1224
- tabindex="-1"
1225
- style=${styleMap(this._panelStyle())}
1226
- @click=${this._onPanelClick}
1227
- @keydown=${this._onPanelKeydown}
1228
- @keyup=${this._onPanelKeyup}
1229
- >
1230
- ${this._renderRegion("search", "search")}
1231
- ${this._renderRegion("body", "body")}
1232
- ${this._renderRegion("foot", "footer")}
1233
- </div>
1234
- </div>
1235
- `;
1236
- }
1237
- }
1238
- __decorate([property({ attribute: false })], MonoDropdownTableCoreClass.prototype, "dataDropdown", void 0);
1239
- __decorate([property({ type: String })], MonoDropdownTableCoreClass.prototype, "size", void 0);
1240
- __decorate([property({ type: String })], MonoDropdownTableCoreClass.prototype, "color", void 0);
1241
- __decorate([property({ type: String })], MonoDropdownTableCoreClass.prototype, "variant", void 0);
1242
- __decorate([property({
1243
- type: String,
1244
- attribute: "label-position"
1245
- })], MonoDropdownTableCoreClass.prototype, "labelPosition", void 0);
1246
- __decorate([property({
1247
- type: String,
1248
- attribute: "validation-position"
1249
- })], MonoDropdownTableCoreClass.prototype, "validationPosition", void 0);
1250
- __decorate([property({ type: String })], MonoDropdownTableCoreClass.prototype, "label", void 0);
1251
- __decorate([property({ type: String })], MonoDropdownTableCoreClass.prototype, "placeholder", void 0);
1252
- __decorate([property({
1253
- type: String,
1254
- attribute: "helper-text"
1255
- })], MonoDropdownTableCoreClass.prototype, "helperText", void 0);
1256
- __decorate([property()], MonoDropdownTableCoreClass.prototype, "tooltip", void 0);
1257
- __decorate([property({
1258
- type: String,
1259
- attribute: "validation-state"
1260
- })], MonoDropdownTableCoreClass.prototype, "validationState", void 0);
1261
- __decorate([property({
1262
- type: String,
1263
- attribute: "validation-message"
1264
- })], MonoDropdownTableCoreClass.prototype, "validationMessage", void 0);
1265
- __decorate([property({
1266
- type: String,
1267
- attribute: "error-message"
1268
- })], MonoDropdownTableCoreClass.prototype, "errorMessage", void 0);
1269
- __decorate([property({
1270
- type: String,
1271
- attribute: "success-message"
1272
- })], MonoDropdownTableCoreClass.prototype, "successMessage", void 0);
1273
- __decorate([property({
1274
- reflect: true,
1275
- converter: booleanStringConverter
1276
- })], MonoDropdownTableCoreClass.prototype, "required", void 0);
1277
- __decorate([property({
1278
- reflect: true,
1279
- converter: booleanStringConverter
1280
- })], MonoDropdownTableCoreClass.prototype, "disabled", void 0);
1281
- __decorate([property({
1282
- reflect: true,
1283
- converter: booleanStringConverter
1284
- })], MonoDropdownTableCoreClass.prototype, "readonly", void 0);
1285
- __decorate([property({
1286
- reflect: true,
1287
- converter: booleanStringConverter
1288
- })], MonoDropdownTableCoreClass.prototype, "clearable", void 0);
1289
- __decorate([property({
1290
- reflect: true,
1291
- converter: booleanStringConverter
1292
- })], MonoDropdownTableCoreClass.prototype, "multiple", void 0);
1293
- __decorate([property({ converter: optionalNumberConverter })], MonoDropdownTableCoreClass.prototype, "max", void 0);
1294
- __decorate([property({ converter: optionalNumberConverter })], MonoDropdownTableCoreClass.prototype, "min", void 0);
1295
- __decorate([property({
1296
- attribute: "max-visible",
1297
- converter: optionalNumberConverter
1298
- })], MonoDropdownTableCoreClass.prototype, "maxVisible", void 0);
1299
- __decorate([property({
1300
- attribute: "min-visible",
1301
- converter: optionalNumberConverter
1302
- })], MonoDropdownTableCoreClass.prototype, "minVisible", void 0);
1303
- __decorate([property({ attribute: false })], MonoDropdownTableCoreClass.prototype, "chip", void 0);
1304
- __decorate([property({ attribute: "model-value" })], MonoDropdownTableCoreClass.prototype, "modelValue", void 0);
1305
- __decorate([property({ type: String })], MonoDropdownTableCoreClass.prototype, "width", void 0);
1306
- __decorate([property({ type: String })], MonoDropdownTableCoreClass.prototype, "height", void 0);
1307
- __decorate([property({
1308
- type: String,
1309
- attribute: "min-width"
1310
- })], MonoDropdownTableCoreClass.prototype, "minWidth", void 0);
1311
- __decorate([property({
1312
- type: String,
1313
- attribute: "max-width"
1314
- })], MonoDropdownTableCoreClass.prototype, "maxWidth", void 0);
1315
- __decorate([property({
1316
- type: String,
1317
- attribute: "min-height"
1318
- })], MonoDropdownTableCoreClass.prototype, "minHeight", void 0);
1319
- __decorate([property({
1320
- type: String,
1321
- attribute: "max-height"
1322
- })], MonoDropdownTableCoreClass.prototype, "maxHeight", void 0);
1323
- __decorate([property({ attribute: false })], MonoDropdownTableCoreClass.prototype, "dropdown", void 0);
1324
- __decorate([property({ type: String })], MonoDropdownTableCoreClass.prototype, "placement", void 0);
1325
- __decorate([property({ converter: booleanStringConverter })], MonoDropdownTableCoreClass.prototype, "flip", void 0);
1326
- __decorate([property({ converter: booleanStringConverter })], MonoDropdownTableCoreClass.prototype, "shift", void 0);
1327
- __decorate([property({ converter: numberStringConverter })], MonoDropdownTableCoreClass.prototype, "offset", void 0);
1328
- __decorate([property({
1329
- attribute: "auto-focus-search",
1330
- converter: booleanStringConverter
1331
- })], MonoDropdownTableCoreClass.prototype, "autoFocusSearch", void 0);
1332
- __decorate([property({
1333
- attribute: "stay-open",
1334
- reflect: true,
1335
- converter: booleanStringConverter
1336
- })], MonoDropdownTableCoreClass.prototype, "stayOpen", void 0);
1337
- __decorate([property({ attribute: false })], MonoDropdownTableCoreClass.prototype, "cssClass", void 0);
1338
- __decorate([property({ attribute: false })], MonoDropdownTableCoreClass.prototype, "cssClassName", void 0);
1339
- return MonoDropdownTableCoreClass;
1340
- };
1341
-
1342
- //#endregion
1343
10
  //#region \0raw:C:\Users\VCT-DEV\Desktop\libs\packages\helper\src\components\dropdown-table\dropdown-table.css?raw.js
1344
11
  var dropdown_table_css_raw_default = "/* LEGACY CLASS ALIASES — every `[mono-x]` below is wrapped as `:is([mono-x], .legacy)`\r\n by `scripts/legacy-class-alias.mjs` (`.mono-dropdown-table-region.body`,\r\n `tr.mono-dd-row-selected`, …), so host CSS and hand-written markup on the pre-port\r\n class contract keep painting. Author with the attribute only; re-run the script. */\r\n/* =========================================================================\r\n mono-dropdown-table — a dropdown whose panel is a native `<table>` for\r\n picking row(s). An EXTENSION: Basecoat has no table picker, so the FIELD is\r\n the multi-select combobox's chip box (`.combobox-chips` + `.combobox-chip`,\r\n basecoat-css@1.0.2, vega style) on the `.field` / `.label` chrome, and the\r\n PANEL is the combobox's `[data-popover]` holding a ported `<table mono-table>`\r\n instead of a listbox — so the rows are the table's own rows.\r\n\r\n Styled by ATTRIBUTE, like Basecoat — and the attributes mirror the element's\r\n props one for one, so hand-written markup reads like the Lit / Vue tag:\r\n\r\n <mono-dropdown-table size=\"sm\" color=\"danger\" label=\"Owner\" clearable multiple>\r\n <div mono-dropdown-table mono-size=\"sm\" mono-color=\"danger\" mono-clearable mono-multiple>\r\n <label mono-dd-label>Owner</label>\r\n <div mono-dd-control>\r\n <div mono-dd-trigger role=\"combobox\">\r\n <span mono-dd-value>\r\n <div mono-dd-chip mono-dd-removable><span mono-dd-chip-main><span mono-dd-chip-content>\r\n <span mono-dd-chip-label>Ada</span><button mono-dd-chip-close>…</button></span></span></div>\r\n </span>\r\n <span mono-dd-actions><span mono-dd-arrow>…</span></span>\r\n </div>\r\n </div>\r\n <div mono-dd-panel><div mono-dd-region=\"body\"><table mono-table>…</table></div></div>\r\n </div>\r\n\r\n An absent attribute is the prop's default (`:not([mono-size])` = md,\r\n `:not([mono-color])` = primary, `:not([mono-variant])` = outlined). The element\r\n renders these attributes on its wrapper (both builds) plus the STATES\r\n `mono-open` / `mono-more-open` / `mono-has-value` / `mono-side`; the old\r\n classes (`.mono-dropdown-table.sm.open`) are still emitted as inert hooks until\r\n 2.0 but no rule here reads them. The chips are NOT `.mono-chip`s any more: they\r\n are Basecoat combobox chips painted here, and chip.css never sees them.\r\n\r\n THE PARTS ARE FAMILY-UNIQUE (`mono-dd-*`), never the bare `mono-chip` /\r\n `mono-panel` / `mono-actions` the field components use: the panel holds a whole\r\n `<table mono-table>` whose cells may carry a consumer's `<mono-chip>`, and a\r\n `[mono-dropdown-table] [mono-chip]` rule would repaint it.\r\n\r\n Selector map (ours ≡ upstream):\r\n [mono-dropdown-table] ≡ .field (gap-3, as margins) + .combobox (position: relative)\r\n [mono-dropdown-table] > [mono-dd-label] ≡ .field > label / .label\r\n [mono-dd-trigger] ≡ .combobox-chips (min-h-9 gap-1.5 rounded-md border-input px-1.5 py-1.5 text-sm shadow-xs)\r\n [mono-dd-value] ≡ the chip row; EXTENSION: the single value / placeholder text\r\n [mono-dd-chip] > [mono-dd-chip-main] ≡ .combobox-chip (h-5.5 gap-1 rounded-sm bg-muted px-1.5 text-xs font-medium)\r\n [mono-dd-chip] [mono-dd-chip-close] ≡ .combobox-chip-remove (-ms-1 opacity-50 hover:100, svg size-3.5)\r\n [mono-dd-chip][mono-dd-more] ≡ EXTENSION (the \"+N more\" counter chip, same box)\r\n [mono-dd-actions] > [mono-dd-arrow] > svg ≡ .combobox-trigger-icon (size-4 text-muted-foreground)\r\n [mono-dd-actions] > [mono-dd-clear] ≡ .combobox [data-clear] (size-6, painted as .btn[data-variant='ghost'])\r\n [mono-dd-actions] > [mono-dd-scroll] ≡ EXTENSION (the inline strip's ‹ › pager, same box)\r\n [mono-dd-panel] ≡ .combobox [data-popover] (bg-popover ring-1 rounded-md shadow-md); EXTENSION: a flex column of regions\r\n [mono-dd-region=\"search|body|foot\"] ≡ EXTENSION (search box / the scrolling table / the pager)\r\n [mono-dd-more] ≡ [data-popover] holding the overflow chips\r\n [mono-table] tbody tr[mono-selected] ≡ .table tr data-[state=selected] — the TABLE's own rule paints it\r\n [mono-table] tbody tr[mono-dd-active] ≡ .combobox [role='option'].active (bg-muted) — the keyboard cursor\r\n [mono-dd-message=\"…\"] ≡ .field > p / .field [role='alert']\r\n [mono-validation-state=\"invalid\"] ≡ .combobox-chips:has([aria-invalid=true]) + .field[data-invalid]\r\n [mono-validation-state=\"valid|warning\"] ≡ EXTENSION (the invalid pattern in --success / --warning)\r\n [mono-size=\"xs|sm|lg|xl|xxl\"] ≡ EXTENSION (the --mono-control-height-* ladder)\r\n [mono-variant=\"filled\"] ≡ EXTENSION (luma's .combobox-chips)\r\n [mono-variant=\"underlined\"] ≡ EXTENSION (sera's .combobox-chips: bottom edge only, no ring)\r\n\r\n FLAVORS: the field IS the tag-input's chip box and the panel IS its popover, so\r\n every metric here resolves `--mono-dropdown-table-<k>` → `--mono-tag-input-<k>`\r\n → the base, through the SAME per-size chains tag-input.css uses — a flavour\r\n that retunes the tag-input retunes this field for free, and no flavour file\r\n carries a dropdown-table entry. Every fallback is vega's value.\r\n\r\n THE PANELS ARE PORTALED (light build): [mono-dd-panel] and [mono-dd-more]\r\n move into a `<div data-mono-popup-portal>` under <body> while open, and the\r\n portal mirrors the wrapper's class AND mono-* attributes, so every rule here\r\n is scoped under `[mono-dropdown-table]` and never relies on the panel being\r\n inside the field. The shadow build keeps its panel in the shadow root and\r\n SLOTS the consumer's light-DOM `<table>` into it — the row rules therefore\r\n come in two forms: the portaled table, and the slotted one under the host.\r\n ========================================================================= */\r\n\r\nmono-dropdown-table {\r\n display: block;\r\n width: 100%;\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) {\r\n /* ── palette: each slot is a public knob over the tag-input's, over a Basecoat token ── */\r\n --_mono-dropdown-table-text: var(--mono-dropdown-table-text, var(--mono-tag-input-text, var(--foreground)));\r\n --_mono-dropdown-table-placeholder: var(--mono-dropdown-table-placeholder, var(--mono-tag-input-placeholder, var(--muted-foreground)));\r\n --_mono-dropdown-table-muted: var(--mono-dropdown-table-muted, var(--mono-tag-input-muted, var(--muted-foreground)));\r\n --_mono-dropdown-table-primary: var(--mono-dropdown-table-primary, var(--mono-tag-input-primary, var(--ring)));\r\n --_mono-dropdown-table-secondary: var(--mono-dropdown-table-secondary, var(--mono-tag-input-secondary, var(--muted-foreground)));\r\n --_mono-dropdown-table-success: var(--mono-dropdown-table-success, var(--mono-tag-input-success, var(--success)));\r\n --_mono-dropdown-table-danger: var(--mono-dropdown-table-danger, var(--mono-tag-input-danger, var(--destructive)));\r\n --_mono-dropdown-table-warning: var(--mono-dropdown-table-warning, var(--mono-tag-input-warning, var(--warning)));\r\n --_mono-dropdown-table-info: var(--mono-dropdown-table-info, var(--mono-tag-input-info, var(--info)));\r\n --_mono-dropdown-table-teal: var(--mono-dropdown-table-teal, var(--mono-tag-input-teal, var(--teal)));\r\n --_mono-dropdown-table-purple: var(--mono-dropdown-table-purple, var(--mono-tag-input-purple, var(--purple)));\r\n --_mono-dropdown-table-neutral: var(--mono-dropdown-table-neutral, var(--mono-tag-input-neutral, var(--neutral)));\r\n --_mono-dropdown-table-dark: var(--mono-dropdown-table-dark, var(--mono-tag-input-dark, var(--dark)));\r\n --_mono-dropdown-table-valid: var(--mono-dropdown-table-valid, var(--mono-tag-input-valid, var(--success)));\r\n --_mono-dropdown-table-invalid: var(--mono-dropdown-table-invalid, var(--mono-tag-input-invalid, var(--destructive)));\r\n\r\n /* ── the painted result — three tiers, base = .combobox-chips (vega) ──── */\r\n --_mono-dropdown-table-ring-color: var(--mono-dropdown-table-ring-color, var(--mono-dropdown-table-focus-color, var(--_mono-dropdown-table-ring-color-preset, var(--_mono-dropdown-table-primary))));\r\n --_mono-dropdown-table-ring-width: var(--mono-dropdown-table-ring-width, var(--mono-tag-input-ring-width, var(--_mono-dropdown-table-ring-width-preset, var(--mono-ring-width))));\r\n --_mono-dropdown-table-ring-alpha: var(--mono-dropdown-table-ring-alpha, var(--mono-tag-input-ring-alpha, var(--mono-ring-alpha)));\r\n --_mono-dropdown-table-border-color: var(--mono-dropdown-table-rest-border, var(--mono-dropdown-table-border-color, var(--mono-dropdown-table-border, var(--mono-tag-input-rest-border, var(--mono-tag-input-border-color, var(--mono-tag-input-border, var(--_mono-dropdown-table-border-color-preset, var(--input))))))));\r\n --_mono-dropdown-table-bg: var(--mono-dropdown-table-bg, var(--mono-dropdown-table-surface, var(--mono-tag-input-bg, var(--mono-tag-input-surface, var(--_mono-dropdown-table-bg-preset, var(--mono-mode-surface))))));\r\n --_mono-dropdown-table-shadow: var(--mono-dropdown-table-shadow, var(--mono-tag-input-shadow, var(--_mono-dropdown-table-shadow-preset, 0 0 #0000)));\r\n --_mono-dropdown-table-icon: var(--mono-dropdown-table-icon-size, var(--mono-tag-input-icon-size, calc(var(--mono-spacing) * 4)));\r\n\r\n /* ── md metrics live on the unqualified root ON PURPOSE: hand-written\r\n `<div mono-dropdown-table>` that names no size renders exactly like\r\n size=\"md\". basecoat@1.0.2 styles/vega.css .combobox-chips — min-h-9\r\n gap-1.5 rounded-md px-1.5 py-1.5 text-sm; .combobox-chip h-5.5 ── */\r\n --_mono-dropdown-table-height: var(--mono-dropdown-table-height-md, var(--mono-tag-input-height-md, var(--mono-control-height-md)));\r\n --_mono-dropdown-table-radius: var(--mono-dropdown-table-radius-md, var(--mono-tag-input-radius-md, var(--_mono-dropdown-table-radius-preset, var(--mono-dropdown-table-radius, var(--mono-tag-input-radius, var(--mono-radius-md))))));\r\n --_mono-dropdown-table-padding-x: var(--mono-dropdown-table-padding-x-md, var(--mono-tag-input-padding-x-md, var(--mono-dropdown-table-padding-x, var(--mono-tag-input-padding-x, var(--_mono-dropdown-table-padding-x-preset, calc(var(--mono-spacing) * 1.5))))));\r\n --_mono-dropdown-table-padding-y: var(--mono-dropdown-table-padding-y-md, var(--mono-tag-input-padding-y-md, var(--mono-dropdown-table-padding-y, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 1.5)))));\r\n --_mono-dropdown-table-gap: var(--mono-dropdown-table-chip-gap, var(--mono-tag-input-chip-gap, calc(var(--mono-spacing) * 1.5)));\r\n --_mono-dropdown-table-font-size: var(--mono-dropdown-table-font-md, var(--mono-tag-input-font-md, var(--mono-text-sm)));\r\n --_mono-dropdown-table-line-height: var(--mono-dropdown-table-line-height, var(--mono-tag-input-line-height, var(--mono-dropdown-table-line-height-md, var(--mono-tag-input-line-height-md, var(--mono-text-sm--lh)))));\r\n /* Same cap as tag-input's (see tag-input.css): one row of chips never outgrows the field's height. */\r\n --_mono-dropdown-table-chip-fit: calc(var(--_mono-dropdown-table-height) - 2 * var(--_mono-dropdown-table-padding-y) - 2 * var(--mono-border-width));\r\n --_mono-dropdown-table-chip-height: var(--mono-dropdown-table-chip-height-md, var(--mono-tag-input-chip-height-md, min(calc(var(--mono-spacing) * 5.5), var(--_mono-dropdown-table-chip-fit))));\r\n --_mono-dropdown-table-chip-font-size: var(--mono-dropdown-table-chip-font-size, var(--mono-tag-input-chip-font-size, var(--mono-text-xs)));\r\n --_mono-dropdown-table-chip-line-height: var(--mono-dropdown-table-chip-line-height, var(--mono-tag-input-chip-line-height, var(--mono-text-xs--lh)));\r\n --_mono-dropdown-table-action: calc(var(--mono-spacing) * 6);\r\n --_mono-dropdown-table-clear-glyph: calc(var(--mono-spacing) * 3.5);\r\n\r\n /* basecoat@1.0.2 styles/vega.css .field — flex w-full flex-col gap-3; mono:\r\n BLOCK flow with the gap as margins (see tag-input.css) */\r\n --_mono-dropdown-table-gap-y: var(--mono-dropdown-table-gap, var(--mono-tag-input-gap, calc(var(--mono-spacing) * 3)));\r\n position: relative;\r\n display: block;\r\n width: 100%;\r\n font-family: inherit;\r\n color: var(--_mono-dropdown-table-text);\r\n}\r\n\r\n/* The page's global `* { box-sizing: border-box }` does NOT cross the shadow\r\n boundary; without this the trigger's `min-height` would be its CONTENT height\r\n there (40px → 56px). Rewrites to `:host, :host *` in the shadow sheet. */\r\nmono-dropdown-table,\r\nmono-dropdown-table *,\r\n:is([mono-dropdown-table],.mono-dropdown-table),\r\n:is([mono-dropdown-table],.mono-dropdown-table) *,\r\n:is([mono-dropdown-table],.mono-dropdown-table) *::before,\r\n:is([mono-dropdown-table],.mono-dropdown-table) *::after {\r\n box-sizing: border-box;\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is(:is([mono-dd-label],.mono-dropdown-table-label), :is([mono-dd-message],.mono-dropdown-table-message))[mono-empty] {\r\n display: none;\r\n}\r\n\r\n/* =========================================\r\n Sizes — an EMPTY field's painted height IS the token (tests/perf/field-heights);\r\n a second row of chips grows it. The same chains as tag-input.css, one tier up.\r\n ========================================= */\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-size=\"xs\"],:where(.mono-dropdown-table.xs)) {\r\n --_mono-dropdown-table-height: var(--mono-dropdown-table-height-xs, var(--mono-tag-input-height-xs, var(--mono-control-height-xs)));\r\n --_mono-dropdown-table-radius: var(--mono-dropdown-table-radius-xs, var(--mono-tag-input-radius-xs, var(--_mono-dropdown-table-radius-preset, var(--mono-dropdown-table-radius, var(--mono-tag-input-radius, var(--mono-radius-md))))));\r\n --_mono-dropdown-table-padding-x: var(--mono-dropdown-table-padding-x-xs, var(--mono-tag-input-padding-x-xs, var(--mono-dropdown-table-padding-x, var(--mono-tag-input-padding-x, var(--_mono-dropdown-table-padding-x-preset, var(--mono-spacing))))));\r\n --_mono-dropdown-table-padding-y: var(--mono-dropdown-table-padding-y-xs, var(--mono-tag-input-padding-y-xs, var(--mono-dropdown-table-padding-y, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 0.5)))));\r\n --_mono-dropdown-table-gap: var(--mono-dropdown-table-chip-gap, var(--mono-tag-input-chip-gap, var(--mono-spacing)));\r\n --_mono-dropdown-table-font-size: var(--mono-dropdown-table-font-xs, var(--mono-tag-input-font-xs, var(--mono-text-xs)));\r\n --_mono-dropdown-table-line-height: var(--mono-dropdown-table-line-height, var(--mono-tag-input-line-height, var(--mono-dropdown-table-line-height-xs, var(--mono-tag-input-line-height-xs, var(--mono-text-xs--lh)))));\r\n --_mono-dropdown-table-chip-height: var(--mono-dropdown-table-chip-height-xs, var(--mono-tag-input-chip-height-xs, min(calc(var(--mono-spacing) * 4.5), var(--_mono-dropdown-table-chip-fit))));\r\n --_mono-dropdown-table-icon: var(--mono-dropdown-table-icon-size, var(--mono-tag-input-icon-size, calc(var(--mono-spacing) * 3.5)));\r\n --_mono-dropdown-table-action: calc(var(--mono-spacing) * 4);\r\n --_mono-dropdown-table-clear-glyph: calc(var(--mono-spacing) * 3);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-size=\"sm\"],:where(.mono-dropdown-table.sm)) {\r\n --_mono-dropdown-table-height: var(--mono-dropdown-table-height-sm, var(--mono-tag-input-height-sm, var(--mono-control-height-sm)));\r\n --_mono-dropdown-table-radius: var(--mono-dropdown-table-radius-sm, var(--mono-tag-input-radius-sm, var(--_mono-dropdown-table-radius-preset, var(--mono-dropdown-table-radius, var(--mono-tag-input-radius, var(--mono-radius-md))))));\r\n --_mono-dropdown-table-padding-x: var(--mono-dropdown-table-padding-x-sm, var(--mono-tag-input-padding-x-sm, var(--mono-dropdown-table-padding-x, var(--mono-tag-input-padding-x, var(--_mono-dropdown-table-padding-x-preset, var(--mono-spacing))))));\r\n --_mono-dropdown-table-padding-y: var(--mono-dropdown-table-padding-y-sm, var(--mono-tag-input-padding-y-sm, var(--mono-dropdown-table-padding-y, var(--mono-tag-input-padding-y, var(--mono-spacing)))));\r\n --_mono-dropdown-table-gap: var(--mono-dropdown-table-chip-gap, var(--mono-tag-input-chip-gap, var(--mono-spacing)));\r\n --_mono-dropdown-table-font-size: var(--mono-dropdown-table-font-sm, var(--mono-tag-input-font-sm, var(--mono-dropdown-table-font-md, var(--mono-tag-input-font-md, var(--mono-text-sm)))));\r\n --_mono-dropdown-table-line-height: var(--mono-dropdown-table-line-height, var(--mono-tag-input-line-height, var(--mono-dropdown-table-line-height-sm, var(--mono-tag-input-line-height-sm, var(--mono-text-sm--lh)))));\r\n --_mono-dropdown-table-chip-height: var(--mono-dropdown-table-chip-height-sm, var(--mono-tag-input-chip-height-sm, min(calc(var(--mono-spacing) * 5), var(--_mono-dropdown-table-chip-fit))));\r\n --_mono-dropdown-table-action: calc(var(--mono-spacing) * 5);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-size=\"lg\"],:where(.mono-dropdown-table.lg)) {\r\n --_mono-dropdown-table-height: var(--mono-dropdown-table-height-lg, var(--mono-tag-input-height-lg, var(--mono-control-height-lg)));\r\n --_mono-dropdown-table-radius: var(--mono-dropdown-table-radius-lg, var(--mono-tag-input-radius-lg, var(--_mono-dropdown-table-radius-preset, var(--mono-dropdown-table-radius, var(--mono-tag-input-radius, var(--mono-radius-md))))));\r\n --_mono-dropdown-table-padding-x: var(--mono-dropdown-table-padding-x-lg, var(--mono-tag-input-padding-x-lg, var(--mono-dropdown-table-padding-x, var(--mono-tag-input-padding-x, var(--_mono-dropdown-table-padding-x-preset, calc(var(--mono-spacing) * 1.5))))));\r\n --_mono-dropdown-table-padding-y: var(--mono-dropdown-table-padding-y-lg, var(--mono-tag-input-padding-y-lg, var(--mono-dropdown-table-padding-y, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 1.5)))));\r\n --_mono-dropdown-table-font-size: var(--mono-dropdown-table-font-lg, var(--mono-tag-input-font-lg, var(--mono-dropdown-table-font-md, var(--mono-tag-input-font-md, var(--mono-text-sm)))));\r\n --_mono-dropdown-table-line-height: var(--mono-dropdown-table-line-height, var(--mono-tag-input-line-height, var(--mono-dropdown-table-line-height-lg, var(--mono-tag-input-line-height-lg, var(--mono-text-sm--lh)))));\r\n --_mono-dropdown-table-chip-height: var(--mono-dropdown-table-chip-height-lg, var(--mono-tag-input-chip-height-lg, min(calc(var(--mono-spacing) * 6), var(--_mono-dropdown-table-chip-fit))));\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-size=\"xl\"],:where(.mono-dropdown-table.xl)) {\r\n --_mono-dropdown-table-height: var(--mono-dropdown-table-height-xl, var(--mono-tag-input-height-xl, var(--mono-control-height-xl)));\r\n --_mono-dropdown-table-radius: var(--mono-dropdown-table-radius-xl, var(--mono-tag-input-radius-xl, var(--_mono-dropdown-table-radius-preset, var(--mono-dropdown-table-radius, var(--mono-tag-input-radius, var(--mono-radius-md))))));\r\n --_mono-dropdown-table-padding-x: var(--mono-dropdown-table-padding-x-xl, var(--mono-tag-input-padding-x-xl, var(--mono-dropdown-table-padding-x, var(--mono-tag-input-padding-x, var(--_mono-dropdown-table-padding-x-preset, calc(var(--mono-spacing) * 2))))));\r\n --_mono-dropdown-table-padding-y: var(--mono-dropdown-table-padding-y-xl, var(--mono-tag-input-padding-y-xl, var(--mono-dropdown-table-padding-y, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 2)))));\r\n --_mono-dropdown-table-gap: var(--mono-dropdown-table-chip-gap, var(--mono-tag-input-chip-gap, calc(var(--mono-spacing) * 2)));\r\n --_mono-dropdown-table-font-size: var(--mono-dropdown-table-font-xl, var(--mono-tag-input-font-xl, var(--mono-text-base)));\r\n --_mono-dropdown-table-line-height: var(--mono-dropdown-table-line-height, var(--mono-tag-input-line-height, var(--mono-dropdown-table-line-height-xl, var(--mono-tag-input-line-height-xl, var(--mono-text-base--lh)))));\r\n --_mono-dropdown-table-chip-height: var(--mono-dropdown-table-chip-height-xl, var(--mono-tag-input-chip-height-xl, min(calc(var(--mono-spacing) * 6.5), var(--_mono-dropdown-table-chip-fit))));\r\n --_mono-dropdown-table-chip-font-size: var(--mono-dropdown-table-chip-font-size, var(--mono-tag-input-chip-font-size, var(--mono-text-sm)));\r\n --_mono-dropdown-table-chip-line-height: var(--mono-dropdown-table-chip-line-height, var(--mono-tag-input-chip-line-height, var(--mono-text-sm--lh)));\r\n --_mono-dropdown-table-icon: var(--mono-dropdown-table-icon-size, var(--mono-tag-input-icon-size, calc(var(--mono-spacing) * 5)));\r\n --_mono-dropdown-table-action: calc(var(--mono-spacing) * 7);\r\n --_mono-dropdown-table-clear-glyph: calc(var(--mono-spacing) * 4);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-size=\"xxl\"],:where(.mono-dropdown-table.xxl)) {\r\n --_mono-dropdown-table-height: var(--mono-dropdown-table-height-xxl, var(--mono-tag-input-height-xxl, var(--mono-control-height-xxl)));\r\n --_mono-dropdown-table-radius: var(--mono-dropdown-table-radius-xxl, var(--mono-tag-input-radius-xxl, var(--_mono-dropdown-table-radius-preset, var(--mono-dropdown-table-radius, var(--mono-tag-input-radius, var(--mono-radius-md))))));\r\n --_mono-dropdown-table-padding-x: var(--mono-dropdown-table-padding-x-xxl, var(--mono-tag-input-padding-x-xxl, var(--mono-dropdown-table-padding-x, var(--mono-tag-input-padding-x, var(--_mono-dropdown-table-padding-x-preset, calc(var(--mono-spacing) * 2.5))))));\r\n --_mono-dropdown-table-padding-y: var(--mono-dropdown-table-padding-y-xxl, var(--mono-tag-input-padding-y-xxl, var(--mono-dropdown-table-padding-y, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 2)))));\r\n --_mono-dropdown-table-gap: var(--mono-dropdown-table-chip-gap, var(--mono-tag-input-chip-gap, calc(var(--mono-spacing) * 2)));\r\n --_mono-dropdown-table-font-size: var(--mono-dropdown-table-font-xxl, var(--mono-tag-input-font-xxl, var(--mono-text-lg)));\r\n --_mono-dropdown-table-line-height: var(--mono-dropdown-table-line-height, var(--mono-tag-input-line-height, var(--mono-dropdown-table-line-height-xxl, var(--mono-tag-input-line-height-xxl, var(--mono-text-lg--lh)))));\r\n --_mono-dropdown-table-chip-height: var(--mono-dropdown-table-chip-height-xxl, var(--mono-tag-input-chip-height-xxl, min(calc(var(--mono-spacing) * 7), var(--_mono-dropdown-table-chip-fit))));\r\n --_mono-dropdown-table-chip-font-size: var(--mono-dropdown-table-chip-font-size, var(--mono-tag-input-chip-font-size, var(--mono-text-sm)));\r\n --_mono-dropdown-table-chip-line-height: var(--mono-dropdown-table-chip-line-height, var(--mono-tag-input-chip-line-height, var(--mono-text-sm--lh)));\r\n --_mono-dropdown-table-icon: var(--mono-dropdown-table-icon-size, var(--mono-tag-input-icon-size, calc(var(--mono-spacing) * 5)));\r\n --_mono-dropdown-table-action: calc(var(--mono-spacing) * 8);\r\n --_mono-dropdown-table-clear-glyph: calc(var(--mono-spacing) * 4);\r\n}\r\n\r\n/* =========================================\r\n Variants — each writes only `*-preset` slots, read from the dropdown-table's\r\n knob first and the tag-input's second (a flavour writes the latter)\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chips — rounded-md border border-input\r\n bg-transparent shadow-xs (dark:bg-input/30 via --mono-mode-surface) */\r\n:is([mono-dropdown-table],.mono-dropdown-table):is(:not([mono-variant]), :is([mono-variant=\"outlined\"],:where(.mono-dropdown-table.outlined))) {\r\n --_mono-dropdown-table-bg-preset: var(--mono-dropdown-table-outline-bg, var(--mono-tag-input-outline-bg));\r\n --_mono-dropdown-table-border-color-preset: var(--mono-dropdown-table-outline-border-color, var(--mono-tag-input-outline-border-color));\r\n --_mono-dropdown-table-side-border-color-preset: var(--mono-dropdown-table-outline-side-border-color, var(--mono-tag-input-outline-side-border-color));\r\n --_mono-dropdown-table-shadow-preset: var(--mono-dropdown-table-outline-shadow, var(--mono-tag-input-outline-shadow, var(--mono-shadow-xs)));\r\n --_mono-dropdown-table-ring-width-preset: var(--mono-dropdown-table-outline-ring-width, var(--mono-tag-input-outline-ring-width));\r\n --_mono-dropdown-table-radius-preset: var(--mono-dropdown-table-outline-radius, var(--mono-tag-input-outline-radius));\r\n --_mono-dropdown-table-padding-x-preset: var(--mono-dropdown-table-outline-padding-x, var(--mono-tag-input-outline-padding-x));\r\n}\r\n\r\n/* EXTENSION — filled ≡ basecoat@1.0.2 styles/luma.css .combobox-chips */\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-variant=\"filled\"],:where(.mono-dropdown-table.filled)) {\r\n --_mono-dropdown-table-bg-preset: var(--mono-dropdown-table-filled-bg, var(--mono-tag-input-filled-bg, color-mix(in oklab, var(--input) 50%, transparent)));\r\n --_mono-dropdown-table-border-color-preset: transparent;\r\n --_mono-dropdown-table-shadow-preset: 0 0 #0000;\r\n}\r\n\r\n/* EXTENSION — underlined ≡ basecoat@1.0.2 styles/sera.css .combobox-chips */\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-variant=\"underlined\"],:where(.mono-dropdown-table.underlined)) {\r\n --_mono-dropdown-table-bg-preset: transparent;\r\n --_mono-dropdown-table-side-border-color-preset: transparent;\r\n --_mono-dropdown-table-shadow-preset: 0 0 #0000;\r\n --_mono-dropdown-table-ring-width-preset: 0px;\r\n --_mono-dropdown-table-radius-preset: 0;\r\n --_mono-dropdown-table-padding-x-preset: 0;\r\n}\r\n\r\n/* =========================================\r\n Colours — the `color` prop is the FOCUS colour (ring + focused border)\r\n ========================================= */\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is(:not([mono-color]), :is([mono-color=\"primary\"],:where(.mono-dropdown-table.primary))) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-primary);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-color=\"secondary\"],:where(.mono-dropdown-table.secondary)) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-secondary);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-color=\"success\"],:where(.mono-dropdown-table.success)) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-success);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-color=\"danger\"],:where(.mono-dropdown-table.danger)) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-danger);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-color=\"warning\"],:where(.mono-dropdown-table.warning)) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-warning);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-color=\"info\"],:where(.mono-dropdown-table.info)) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-info);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-color=\"teal\"],:where(.mono-dropdown-table.teal)) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-teal);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-color=\"purple\"],:where(.mono-dropdown-table.purple)) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-purple);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-color=\"neutral\"],:where(.mono-dropdown-table.neutral)) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-neutral);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-color=\"dark\"],:where(.mono-dropdown-table.dark)) {\r\n --_mono-dropdown-table-ring-color-preset: var(--_mono-dropdown-table-dark);\r\n}\r\n\r\n/* =========================================\r\n Label\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .field > label, .label — flex items-center\r\n gap-2 text-sm leading-none font-medium select-none w-fit */\r\n:is([mono-dropdown-table],.mono-dropdown-table) > :is([mono-dd-label],.mono-dropdown-table-label) {\r\n display: flex;\r\n align-items: center;\r\n width: fit-content;\r\n margin: 0 0 var(--_mono-dropdown-table-gap-y);\r\n gap: var(--mono-dropdown-table-label-gap, var(--mono-tag-input-label-gap, calc(var(--mono-spacing) * 2)));\r\n font-size: var(--mono-dropdown-table-label-font-size, var(--mono-tag-input-label-font-size, var(--mono-text-sm)));\r\n line-height: var(--mono-dropdown-table-label-line-height, var(--mono-tag-input-label-line-height, 1));\r\n font-weight: var(--mono-dropdown-table-label-font-weight, var(--mono-tag-input-label-font-weight, var(--mono-label-font-weight, var(--mono-font-weight-medium))));\r\n text-transform: var(--mono-dropdown-table-label-text-transform, var(--mono-tag-input-label-text-transform, none));\r\n letter-spacing: var(--mono-dropdown-table-label-letter-spacing, var(--mono-tag-input-label-letter-spacing, normal));\r\n color: var(--_mono-dropdown-table-text);\r\n user-select: none;\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-disabled],.disabled) > :is([mono-dd-label],.mono-dropdown-table-label) {\r\n opacity: 0.5;\r\n pointer-events: none;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .field — data-invalid:text-destructive */\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-validation-state=\"invalid\"],:where(.mono-dropdown-table.is-invalid)) > :is([mono-dd-label],.mono-dropdown-table-label) {\r\n color: var(--_mono-dropdown-table-invalid);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-required-mark],.mono-dropdown-table-required) {\r\n color: var(--_mono-dropdown-table-danger);\r\n}\r\n\r\n/* `tooltip` prop — the info icon at the end of the label row (the label's\r\n flex gap spaces it). `pointer-events` is restored because a disabled field\r\n switches its label's off, and a disabled field is exactly where the reason\r\n is worth a hover. Knobs: --mono-dropdown-table-label-tooltip-size / -color / -opacity. */\r\n:where(:is([mono-dropdown-table],.mono-dropdown-table)) > :is([mono-dd-label],.mono-dropdown-table-label) > [mono-label-tooltip] {\r\n display: inline-flex;\r\n flex: none;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: var(--mono-dropdown-table-label-tooltip-size, 1.1em);\r\n color: var(--mono-dropdown-table-label-tooltip-color, currentColor);\r\n opacity: var(--mono-dropdown-table-label-tooltip-opacity, 0.6);\r\n border-radius: 9999px;\r\n cursor: help;\r\n pointer-events: auto;\r\n outline: none;\r\n transition: opacity 150ms ease;\r\n}\r\n\r\n:where(:is([mono-dropdown-table],.mono-dropdown-table)) > :is([mono-dd-label],.mono-dropdown-table-label) > [mono-label-tooltip]:is(:hover, :focus-visible) {\r\n opacity: 1;\r\n}\r\n\r\n:where(:is([mono-dropdown-table],.mono-dropdown-table)) > :is([mono-dd-label],.mono-dropdown-table-label) > [mono-label-tooltip]:focus-visible {\r\n outline: 2px solid currentColor;\r\n outline-offset: 2px;\r\n}\r\n\r\n:where(:is([mono-dropdown-table],.mono-dropdown-table)) > :is([mono-dd-label],.mono-dropdown-table-label) > [mono-label-tooltip] > [mono-icon] {\r\n width: 1em;\r\n height: 1em;\r\n}\r\n\r\n/* =========================================\r\n The field — the chip box (role=\"combobox\"; the search box lives in the panel)\r\n ========================================= */\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) > :is([mono-dd-control],.mono-dropdown-table-control) {\r\n position: relative;\r\n}\r\n\r\n/* The control is a grid/flex item in a host layout; once the value stops\r\n wrapping (inline strip) its automatic minimum is the full strip — pin it. */\r\n:is([mono-dropdown-table],.mono-dropdown-table) > :is([mono-dd-control],.mono-dropdown-table-control):is([mono-inline],.is-inline) {\r\n min-width: 0;\r\n}\r\n\r\n/* basecoat@1.0.2 components/combobox.css .combobox-chips — flex w-full min-w-0\r\n flex-wrap items-center */\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chips — min-h-9 gap-1.5 rounded-md\r\n border border-input bg-transparent bg-clip-padding px-1.5 py-1.5 text-sm\r\n shadow-xs transition-[color,box-shadow] focus-within:border-ring\r\n focus-within:ring-3 focus-within:ring-ring/50 has-[[aria-invalid=true]]:…;\r\n mono: one row — the value area wraps INSIDE it and the actions stay centred */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-trigger],.mono-dropdown-table-trigger) {\r\n --_mono-dropdown-table-bc: var(--_mono-dropdown-table-border-color);\r\n --_mono-dropdown-table-side-bc: var(--mono-dropdown-table-side-border-color, var(--mono-tag-input-side-border-color, var(--_mono-dropdown-table-side-border-color-preset, var(--_mono-dropdown-table-bc))));\r\n --_mono-dropdown-table-ring: 0 0 #0000;\r\n\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n gap: var(--_mono-dropdown-table-gap);\r\n width: 100%;\r\n min-width: 0;\r\n min-height: var(--_mono-dropdown-table-height);\r\n padding-block: var(--_mono-dropdown-table-padding-y);\r\n padding-inline: var(--_mono-dropdown-table-padding-x);\r\n outline-style: none;\r\n border: var(--mono-border-width) solid var(--_mono-dropdown-table-bc);\r\n border-top-color: var(--_mono-dropdown-table-side-bc);\r\n border-inline-color: var(--_mono-dropdown-table-side-bc);\r\n border-radius: var(--_mono-dropdown-table-radius);\r\n background: var(--_mono-dropdown-table-bg);\r\n background-clip: padding-box;\r\n color: var(--_mono-dropdown-table-text);\r\n box-shadow: var(--_mono-dropdown-table-ring), var(--_mono-dropdown-table-shadow);\r\n font-family: inherit;\r\n font-size: var(--_mono-dropdown-table-font-size);\r\n line-height: var(--_mono-dropdown-table-line-height);\r\n cursor: pointer;\r\n transition-property: color, box-shadow, border-color, background-color;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration);\r\n}\r\n\r\n/* focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 — and\r\n the OPEN state, which keeps the ring while the keyboard is in the panel */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-trigger],.mono-dropdown-table-trigger):focus-visible,\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-open],.open) :is([mono-dd-trigger],.mono-dropdown-table-trigger) {\r\n --_mono-dropdown-table-bc: var(--_mono-dropdown-table-ring-color);\r\n --_mono-dropdown-table-ring: 0 0 0 var(--_mono-dropdown-table-ring-width) color-mix(in oklab, var(--_mono-dropdown-table-ring-color) var(--_mono-dropdown-table-ring-alpha), transparent);\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chips — has-[[aria-invalid=true]]:border-destructive\r\n has-[[aria-invalid=true]]:ring-3 has-[[aria-invalid=true]]:ring-destructive/20 */\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-validation-state=\"invalid\"],:where(.mono-dropdown-table.is-invalid)) :is([mono-dd-trigger],.mono-dropdown-table-trigger) {\r\n --_mono-dropdown-table-bc: var(--mono-mode-invalid-border);\r\n --_mono-dropdown-table-ring: 0 0 0 var(--_mono-dropdown-table-ring-width) var(--mono-mode-invalid-ring);\r\n}\r\n\r\n/* EXTENSION — valid / warning are the invalid pattern in the role's colour */\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-validation-state=\"valid\"],:where(.mono-dropdown-table.is-valid)) :is([mono-dd-trigger],.mono-dropdown-table-trigger) {\r\n --_mono-dropdown-table-bc: color-mix(in oklab, var(--_mono-dropdown-table-valid) var(--mono-mode-state-border-alpha), transparent);\r\n --_mono-dropdown-table-ring: 0 0 0 var(--_mono-dropdown-table-ring-width) color-mix(in oklab, var(--_mono-dropdown-table-valid) var(--mono-mode-state-ring-alpha), transparent);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-validation-state=\"warning\"],:where(.mono-dropdown-table.is-warning)) :is([mono-dd-trigger],.mono-dropdown-table-trigger) {\r\n --_mono-dropdown-table-bc: color-mix(in oklab, var(--_mono-dropdown-table-warning) var(--mono-mode-state-border-alpha), transparent);\r\n --_mono-dropdown-table-ring: 0 0 0 var(--_mono-dropdown-table-ring-width) color-mix(in oklab, var(--_mono-dropdown-table-warning) var(--mono-mode-state-ring-alpha), transparent);\r\n}\r\n\r\n/* EXTENSION — readonly: a muted surface */\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-readonly],.readonly) :is([mono-dd-trigger],.mono-dropdown-table-trigger) {\r\n background: var(--mono-dropdown-table-readonly-bg, var(--mono-tag-input-readonly-bg, var(--muted)));\r\n cursor: default;\r\n}\r\n\r\n/* .combobox-chips > input:disabled — opacity-50 (on the box, so the chips fade\r\n with it). The strip's ‹ › pager opts back in so the chips can still be read. */\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-disabled],.disabled) :is([mono-dd-trigger],.mono-dropdown-table-trigger) {\r\n opacity: 0.5;\r\n pointer-events: none;\r\n cursor: not-allowed;\r\n background: var(--mono-dropdown-table-disabled-bg, var(--mono-tag-input-disabled-bg, var(--_mono-dropdown-table-bg)));\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-disabled],.disabled) :is([mono-dd-scroll],.mono-dropdown-table-scroll):not(:is([mono-idle],.is-idle)) {\r\n pointer-events: auto;\r\n cursor: pointer;\r\n}\r\n\r\n/* ── the value area: chips (multi) or one line of text ────────────────── */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-value],.mono-dropdown-table-value) {\r\n flex: 1 1 auto;\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: center;\r\n gap: var(--_mono-dropdown-table-gap);\r\n min-width: 0;\r\n /* the chip row is the box's height; an empty value never exceeds it */\r\n min-height: var(--_mono-dropdown-table-chip-height);\r\n overflow: hidden;\r\n color: var(--_mono-dropdown-table-text);\r\n}\r\n\r\n/* EXTENSION — a text value (single select, or the placeholder) sits where a\r\n `.select` puts its text (px-3), not where a chip does (px-1.5): the inset is\r\n what keeps this field's text in line with a `<mono-select>` beside it. */\r\n:is([mono-dropdown-table],.mono-dropdown-table):not([mono-multiple][mono-has-value]) :is([mono-dd-value],.mono-dropdown-table-value) {\r\n padding-inline-start: var(--mono-dropdown-table-text-inset, calc(var(--mono-spacing) * 1.5));\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-value],.mono-dropdown-table-value):is([mono-dd-placeholder],.mono-dropdown-table-placeholder) {\r\n color: var(--_mono-dropdown-table-placeholder);\r\n white-space: nowrap;\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-value],.mono-dropdown-table-value) > span {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n/* =========================================\r\n Chips\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 components/combobox.css .combobox-chip — inline-flex w-fit\r\n shrink-0 items-center whitespace-nowrap */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip) {\r\n display: inline-flex;\r\n width: fit-content;\r\n max-width: 100%;\r\n flex-shrink: 0;\r\n align-items: center;\r\n white-space: nowrap;\r\n vertical-align: middle;\r\n line-height: 1;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chip — h-5.5 gap-1 rounded-sm bg-muted\r\n px-1.5 text-xs font-medium text-foreground, has-[>.combobox-chip-remove]:pe-0 */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip) > [mono-dd-chip-main] {\r\n display: inline-flex;\r\n align-items: center;\r\n height: var(--_mono-dropdown-table-chip-height);\r\n max-width: 100%;\r\n gap: var(--mono-dropdown-table-chip-content-gap, var(--mono-tag-input-chip-content-gap, var(--mono-spacing)));\r\n margin: 0;\r\n padding-inline: var(--mono-dropdown-table-chip-padding-x, var(--mono-tag-input-chip-padding-x, calc(var(--mono-spacing) * 1.5)));\r\n border: 0;\r\n border-radius: var(--mono-dropdown-table-chip-radius, var(--mono-tag-input-chip-radius, var(--mono-radius-sm)));\r\n background: var(--mono-dropdown-table-chip-bg, var(--mono-tag-input-chip-bg, var(--muted)));\r\n color: var(--mono-dropdown-table-chip-color, var(--mono-tag-input-chip-color, var(--_mono-dropdown-table-text)));\r\n font-family: inherit;\r\n font-size: var(--_mono-dropdown-table-chip-font-size);\r\n line-height: var(--_mono-dropdown-table-chip-line-height);\r\n font-weight: var(--mono-dropdown-table-chip-font-weight, var(--mono-tag-input-chip-font-weight, var(--mono-font-weight-medium)));\r\n text-decoration: none;\r\n cursor: default;\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-removable] > [mono-dd-chip-main] {\r\n padding-inline-end: 0;\r\n}\r\n\r\n/* EXTENSION — `chip.rounded`: the chip's own corner scale over the combobox\r\n chip's rounded-sm (the same words `<mono-chip rounded>` takes) */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-rounded=\"none\"] > [mono-dd-chip-main] { border-radius: 0; }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-rounded=\"xs\"] > [mono-dd-chip-main] { border-radius: var(--mono-radius-xs); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-rounded=\"sm\"] > [mono-dd-chip-main] { border-radius: var(--mono-radius-sm); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-rounded=\"md\"] > [mono-dd-chip-main] { border-radius: var(--mono-radius-md); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-rounded=\"lg\"] > [mono-dd-chip-main] { border-radius: var(--mono-radius-lg); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-rounded=\"xl\"] > [mono-dd-chip-main] { border-radius: var(--mono-radius-xl); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-rounded=\"xxl\"] > [mono-dd-chip-main] { border-radius: var(--mono-radius-2xl); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-rounded=\"full\"] > [mono-dd-chip-main] { border-radius: var(--mono-radius-full); }\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip) [mono-dd-chip-content] {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: inherit;\r\n min-width: 0;\r\n max-width: 100%;\r\n height: 100%;\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip) [mono-dd-chip-label] {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n/* EXTENSION — `chip.dot`: a coloured dot before the label (the badge's dot idiom) */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip) [mono-dd-chip-dot] {\r\n flex: 0 0 auto;\r\n width: calc(var(--mono-spacing) * 1.5);\r\n height: calc(var(--mono-spacing) * 1.5);\r\n border-radius: var(--mono-radius-full);\r\n background: currentColor;\r\n}\r\n\r\n/* EXTENSION — `chip.color` pins a hue: the tonal pattern (bg-x/10 text-x, dark 20).\r\n Without one the chips follow the field's `color` — the ring colour — the way\r\n they always did here. */\r\n:is([mono-dropdown-table],.mono-dropdown-table):not(:is(:not([mono-color]), :is([mono-color=\"primary\"],:where(.mono-dropdown-table.primary)))) :is([mono-dd-chip],.mono-dropdown-table-chip):not([mono-dd-chip-color]) > [mono-dd-chip-main] {\r\n background: color-mix(in oklab, var(--_mono-dropdown-table-ring-color) var(--mono-mode-tint), transparent);\r\n color: var(--_mono-dropdown-table-ring-color);\r\n}\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"primary\"] > [mono-dd-chip-main] { background: color-mix(in oklab, var(--primary) var(--mono-mode-tint), transparent); color: var(--primary); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"secondary\"] > [mono-dd-chip-main] { background: var(--secondary); color: var(--secondary-foreground); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"success\"] > [mono-dd-chip-main] { background: color-mix(in oklab, var(--success) var(--mono-mode-tint), transparent); color: var(--success); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"danger\"] > [mono-dd-chip-main] { background: color-mix(in oklab, var(--destructive) var(--mono-mode-tint), transparent); color: var(--destructive); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"warning\"] > [mono-dd-chip-main] { background: color-mix(in oklab, var(--warning) var(--mono-mode-tint), transparent); color: var(--warning); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"info\"] > [mono-dd-chip-main] { background: color-mix(in oklab, var(--info) var(--mono-mode-tint), transparent); color: var(--info); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"teal\"] > [mono-dd-chip-main] { background: color-mix(in oklab, var(--teal) var(--mono-mode-tint), transparent); color: var(--teal); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"purple\"] > [mono-dd-chip-main] { background: color-mix(in oklab, var(--purple) var(--mono-mode-tint), transparent); color: var(--purple); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"neutral\"] > [mono-dd-chip-main] { background: color-mix(in oklab, var(--neutral) var(--mono-mode-tint), transparent); color: var(--neutral); }\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip)[mono-dd-chip-color=\"dark\"] > [mono-dd-chip-main] { background: var(--dark); color: var(--dark-foreground); }\r\n\r\n/* basecoat@1.0.2 components/combobox.css .combobox-chip-remove — inline-flex\r\n shrink-0 items-center justify-center */\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chip-remove — -ms-1 opacity-50\r\n hover:opacity-100, svg size-3.5 */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip) [mono-dd-chip-close] {\r\n display: inline-flex;\r\n flex-shrink: 0;\r\n align-items: center;\r\n justify-content: center;\r\n /* explicit: the element still carries chip.css's `.chip-close` class as a hook,\r\n which pins a 1rem box — the raw markup has no such class */\r\n width: auto;\r\n height: 100%;\r\n min-width: 0;\r\n margin: 0;\r\n transform: none;\r\n margin-inline-start: calc(var(--mono-spacing) * -1);\r\n padding: 0 var(--mono-spacing);\r\n border: 0;\r\n border-radius: inherit;\r\n background: transparent;\r\n color: inherit;\r\n font: inherit;\r\n line-height: 1;\r\n opacity: 0.5;\r\n cursor: pointer;\r\n outline-style: none;\r\n transition-property: opacity;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip) [mono-dd-chip-close]:focus-visible {\r\n opacity: 1;\r\n}\r\n\r\n@media (hover: hover) {\r\n :is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip) [mono-dd-chip-close]:hover {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip) [mono-dd-chip-close] > :is(svg, .mono-icon, :is([mono-icon],.mono-icon)) {\r\n display: block;\r\n width: calc(var(--mono-spacing) * 3.5);\r\n height: calc(var(--mono-spacing) * 3.5);\r\n pointer-events: none;\r\n}\r\n\r\n/* EXTENSION — the \"+N more\" counter chip is a control */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip):is([mono-dd-more],.mono-dropdown-table-more) > [mono-dd-chip-main] {\r\n cursor: pointer;\r\n outline-style: none;\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip):is([mono-dd-more],.mono-dropdown-table-more) > [mono-dd-chip-main]:focus-visible {\r\n box-shadow: 0 0 0 var(--_mono-dropdown-table-ring-width) color-mix(in oklab, var(--_mono-dropdown-table-ring-color) var(--_mono-dropdown-table-ring-alpha), transparent);\r\n}\r\n\r\n@media (hover: hover) {\r\n :is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip],.mono-dropdown-table-chip):is([mono-dd-more],.mono-dropdown-table-more) > [mono-dd-chip-main]:hover {\r\n background: var(--mono-mode-surface-hover);\r\n }\r\n}\r\n\r\n/* ── the inline chip strip (`chip.behaviour: 'inline'`) ──────────────────\r\n One line that never grows: the value stops wrapping, the chips live in their\r\n own strip, and the strip absorbs the overflow instead of the field.\r\n\r\n `overflow-x: hidden` — NOT `auto` — is the whole scroll contract. Hidden still\r\n honours a programmatic `scrollLeft`, so `ChipStripController` can page the\r\n strip while the browser paints no scrollbar and refuses to scroll it from the\r\n wheel, a click-drag or the arrow keys. */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-value],.mono-dropdown-table-value):is([mono-inline],.is-inline) {\r\n flex-wrap: nowrap;\r\n}\r\n\r\n/* Two attributes deliberately: the strip is a direct `span` child of the value\r\n area, so the `[mono-dd-value] > span` ellipsis rule above matches it too. */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-value],.mono-dropdown-table-value) > :is([mono-dd-chip-strip],.mono-dropdown-table-chip-strip) {\r\n display: flex;\r\n flex-wrap: nowrap;\r\n align-items: center;\r\n gap: var(--_mono-dropdown-table-gap);\r\n flex: 0 1 auto;\r\n min-width: 0;\r\n overflow-x: hidden;\r\n overflow-y: hidden;\r\n text-overflow: clip;\r\n /* NO `scroll-behavior: smooth` — see ChipStripController (one scroll event per\r\n frame would reposition every open popup). */\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-chip-strip],.mono-dropdown-table-chip-strip) > * {\r\n flex-shrink: 0;\r\n}\r\n\r\n/* =========================================\r\n Actions — ‹ › pager, clear, caret\r\n ========================================= */\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-actions],.mono-dropdown-table-actions) {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--mono-spacing);\r\n flex: 0 0 auto;\r\n line-height: 1;\r\n /* The row's buttons are size-6 — 2px taller than a chip — and they sit IN the\r\n flex row (centred beside a wrapping value, unlike tag-input's pinned corner),\r\n so on their own they would floor the field 2px above the token. A negative\r\n block margin folds that back: the row costs exactly one chip height. */\r\n margin-block: calc((var(--_mono-dropdown-table-chip-height) - var(--_mono-dropdown-table-action)) / 2);\r\n}\r\n\r\n/* basecoat@1.0.2 components/combobox.css .combobox [data-clear] — size-6 border-0\r\n bg-transparent p-0 text-current; the caret ≡ .combobox-trigger-icon (size-4\r\n text-muted-foreground), the pager the same box. Painted as .btn[data-variant='ghost']. */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-clear],.mono-dropdown-table-clear),\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-arrow],.mono-dropdown-table-arrow),\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-scroll],.mono-dropdown-table-scroll) {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex: 0 0 auto;\r\n width: var(--_mono-dropdown-table-action);\r\n height: var(--_mono-dropdown-table-action);\r\n margin: 0;\r\n padding: 0;\r\n border: 0;\r\n border-radius: var(--mono-dropdown-table-clear-radius, var(--mono-tag-input-clear-radius, calc(var(--radius) - 5px)));\r\n background: transparent;\r\n color: var(--_mono-dropdown-table-muted);\r\n font: inherit;\r\n line-height: 1;\r\n cursor: pointer;\r\n outline-style: none;\r\n transition-property: color, background-color, transform;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is(:is([mono-dd-clear],.mono-dropdown-table-clear), :is([mono-dd-arrow],.mono-dropdown-table-arrow), :is([mono-dd-scroll],.mono-dropdown-table-scroll)) > :is(svg, .mono-icon, :is([mono-icon],.mono-icon)) {\r\n display: block;\r\n width: var(--_mono-dropdown-table-icon);\r\n height: var(--_mono-dropdown-table-icon);\r\n pointer-events: none;\r\n transition-property: transform;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-clear],.mono-dropdown-table-clear) > :is(svg, .mono-icon, :is([mono-icon],.mono-icon)) {\r\n width: var(--_mono-dropdown-table-clear-glyph);\r\n height: var(--_mono-dropdown-table-clear-glyph);\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .btn[data-variant='ghost'] — hover:bg-muted hover:text-foreground */\r\n@media (hover: hover) {\r\n :is([mono-dropdown-table],.mono-dropdown-table) :is(:is([mono-dd-clear],.mono-dropdown-table-clear), :is([mono-dd-arrow],.mono-dropdown-table-arrow), :is([mono-dd-scroll],.mono-dropdown-table-scroll)):hover {\r\n background: var(--mono-mode-ghost-hover);\r\n color: var(--_mono-dropdown-table-text);\r\n }\r\n}\r\n\r\n/* EXTENSION — the caret turns while the panel is open */\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-open],.open) :is([mono-dd-arrow],.mono-dropdown-table-arrow) > :is(svg, .mono-icon, :is([mono-icon],.mono-icon)) {\r\n transform: rotate(180deg);\r\n}\r\n\r\n/* At an end of the strip the pager keeps its box but disappears — hiding it with\r\n `display: none` would shrink the row and shove the strip sideways mid-click. */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-scroll],.mono-dropdown-table-scroll):is([mono-idle],.is-idle) {\r\n visibility: hidden;\r\n pointer-events: none;\r\n}\r\n\r\n/* =========================================\r\n The \"+N more\" overflow panel — a popover holding the overflow chips\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .combobox [data-popover] — bg-popover ring-1\r\n ring-foreground/10 rounded-md shadow-md; EXTENSION: p-1.5 gap-1.5 flex-wrap.\r\n Portaled to <body> and placed `fixed` from the \"+N more\" chip by its own\r\n popup controller in the light build; in the shadow build `_positionMorePanel`\r\n runs the same math in place — the absolute rule is the pre-placement fallback. */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-more],.mono-dropdown-table-more) {\r\n position: absolute;\r\n top: calc(100% + calc(var(--mono-spacing) * 1.5));\r\n left: 0;\r\n z-index: var(--mono-popup-z, 1000);\r\n display: none;\r\n flex-wrap: wrap;\r\n align-items: flex-start;\r\n gap: var(--_mono-dropdown-table-gap);\r\n max-width: 20rem;\r\n /* `--mono-popup-avail-h` = the room left on the side the panel opened on. */\r\n max-height: min(14rem, var(--mono-popup-avail-h, 100vh));\r\n overflow: auto;\r\n /* Portaled + anchored: a chained scroll would drag this panel off-screen. */\r\n overscroll-behavior: contain;\r\n padding: calc(var(--mono-spacing) * 1.5);\r\n border-radius: var(--mono-dropdown-table-dropdown-radius, var(--mono-tag-input-dropdown-radius, var(--mono-radius-md)));\r\n background: var(--mono-dropdown-table-dropdown-bg, var(--mono-tag-input-dropdown-bg, var(--popover)));\r\n color: var(--mono-dropdown-table-dropdown-color, var(--mono-tag-input-dropdown-color, var(--popover-foreground)));\r\n box-shadow: var(--mono-dropdown-table-dropdown-ring, var(--mono-tag-input-dropdown-ring, 0 0 0 1px color-mix(in oklab, var(--foreground) 10%, transparent))), var(--mono-dropdown-table-dropdown-shadow, var(--mono-tag-input-dropdown-shadow, var(--mono-shadow-md)));\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-more-open],.more-open) :is([mono-dd-more],.mono-dropdown-table-more) {\r\n display: flex;\r\n}\r\n\r\n/* =========================================\r\n The panel — sized by the `dropdown` prop, NOT the field\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 components/popover.css [data-popover] — absolute z-50 overflow;\r\n mono: `display: none` while closed, `position: fixed` (the popup controller\r\n sets top/left), `--mono-popup-z` from the shared stack */\r\n/* basecoat@1.0.2 styles/vega.css .combobox [data-popover] — bg-popover\r\n text-popover-foreground ring-foreground/10 rounded-md p-0 shadow-md ring-1;\r\n EXTENSION: a flex column of three regions, the middle one scrolling */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-panel],.mono-dropdown-table-panel) {\r\n display: none;\r\n position: fixed;\r\n z-index: var(--mono-popup-z, 1000);\r\n flex-direction: column;\r\n width: max-content;\r\n min-width: var(--mono-dropdown-table-dropdown-min-width, 18rem);\r\n max-width: min(90vw, 60rem);\r\n /* Two independent caps, combined so neither can clobber the other:\r\n --_mono-dropdown-table-panel-max-h the consumer's `:dropdown.prop=\"{ maxHeight }\"` (else 60vh)\r\n --mono-popup-avail-h the room actually left between the field and the\r\n viewport edge on the side the panel opened on */\r\n max-height: min(var(--_mono-dropdown-table-panel-max-h, 60vh), var(--mono-popup-avail-h, 100vh));\r\n overflow: hidden;\r\n isolation: isolate;\r\n border-radius: var(--mono-dropdown-table-dropdown-radius, var(--mono-tag-input-dropdown-radius, var(--mono-radius-md)));\r\n background: var(--mono-dropdown-table-dropdown-bg, var(--mono-tag-input-dropdown-bg, var(--popover)));\r\n color: var(--mono-dropdown-table-dropdown-color, var(--mono-tag-input-dropdown-color, var(--popover-foreground)));\r\n box-shadow: var(--mono-dropdown-table-dropdown-ring, var(--mono-tag-input-dropdown-ring, 0 0 0 1px color-mix(in oklab, var(--foreground) 10%, transparent))), var(--mono-dropdown-table-dropdown-shadow, var(--mono-tag-input-dropdown-shadow, var(--mono-shadow-md)));\r\n font-size: var(--_mono-dropdown-table-font-size);\r\n line-height: var(--_mono-dropdown-table-line-height);\r\n outline-style: none;\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table):is([mono-open],.open) :is([mono-dd-panel],.mono-dropdown-table-panel) {\r\n display: flex;\r\n}\r\n\r\n/* The panel is a container; its own ring would just outline the whole popup. */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-panel],.mono-dropdown-table-panel):focus,\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-panel],.mono-dropdown-table-panel):focus-visible {\r\n outline: none;\r\n}\r\n\r\n/* EXTENSION — the search box above the rows, the pager below, on hairlines */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-region=\"search\"],:where(.mono-dropdown-table-region.search)) {\r\n flex: 0 0 auto;\r\n padding: var(--mono-dropdown-table-region-padding, calc(var(--mono-spacing) * 2));\r\n border-bottom: var(--mono-border-width) solid var(--border);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-region=\"body\"],:where(.mono-dropdown-table-region.body)) {\r\n flex: 1 1 auto;\r\n /* `min-height: 0` lets the body shrink below its content height inside the flex\r\n column — without it the region floors at its intrinsic size and the panel\r\n overflows its own max-height instead of scrolling the table. */\r\n min-height: 0;\r\n overflow: auto;\r\n overscroll-behavior: contain;\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-region=\"foot\"],:where(.mono-dropdown-table-region.foot)) {\r\n flex: 0 0 auto;\r\n padding: var(--mono-dropdown-table-region-padding, calc(var(--mono-spacing) * 2));\r\n border-top: var(--mono-border-width) solid var(--border);\r\n}\r\n\r\n/* light: a region with nothing captured is `:empty`; shadow: regions wrap a\r\n `<slot>` (never `:empty`), so the element marks an unassigned one `mono-empty` */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-region],.mono-dropdown-table-region):empty,\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-region],.mono-dropdown-table-region)[mono-empty] {\r\n display: none;\r\n}\r\n\r\n/* =========================================\r\n The rows — the ported table's own rows, in TWO contexts\r\n -----------------------------------------\r\n light: the captured `<table mono-table>` inside the (portaled) body region;\r\n shadow: the SLOTTED table — a light-DOM child of the host, so the host tag is\r\n the scope (these rules reach it from the page sheet, not the shadow one).\r\n\r\n A picked row is the TABLE's `mono-selected` row (the element sets it, the same\r\n attribute `<mono-table-checkbox>` sets), so the table's own wash + rail paint\r\n it and a flavour that retunes `--mono-table-selected-bg` retunes it here. The\r\n keyboard cursor is Basecoat's `.active` option — the `--muted` row, like hover.\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .table tr — hover:bg-muted/50; the table ships\r\n with hover off, the picker turns it on through the table's PUBLIC knob */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-region=\"body\"],:where(.mono-dropdown-table-region.body)),\r\nmono-shadow-dropdown-table {\r\n --mono-table-hover-bg: var(--mono-dropdown-table-row-hover-bg, color-mix(in oklab, var(--muted) 50%, var(--mono-table-surface, var(--background))));\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-region=\"body\"],:where(.mono-dropdown-table-region.body)) :is([mono-table],.mono-table) tbody tr[data-row-key],\r\nmono-shadow-dropdown-table :is([mono-table],.mono-table) tbody tr[data-row-key] {\r\n cursor: pointer;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .select:not(select) [role='option'].active, .select:not(select) [role='option']:focus-visible — bg-muted text-foreground\r\n Written the way table.css asks a row state to be written:\r\n the row-colour variable AND the paint, so a pinned cell follows. */\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-region=\"body\"],:where(.mono-dropdown-table-region.body)) :is([mono-table],.mono-table) tbody tr:is([mono-dd-active],.mono-dd-row-active),\r\nmono-shadow-dropdown-table :is([mono-table],.mono-table) tbody tr:is([mono-dd-active],.mono-dd-row-active) {\r\n --_mono-table-row-bg: var(--mono-dropdown-table-row-active-bg, var(--mono-tag-input-option-active-bg, var(--muted)));\r\n background: var(--_mono-table-row-bg);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-region=\"body\"],:where(.mono-dropdown-table-region.body)) :is([mono-table],.mono-table) tbody tr:is([mono-selected],.mono-dd-row-selected) > td,\r\nmono-shadow-dropdown-table :is([mono-table],.mono-table) tbody tr:is([mono-selected],.mono-dd-row-selected) > td {\r\n font-weight: var(--mono-font-weight-medium);\r\n}\r\n\r\n/* =========================================\r\n Message\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .fieldset legend + p, .field > p, .field section > p */\r\n:is([mono-dropdown-table],.mono-dropdown-table) > :is([mono-dd-message],.mono-dropdown-table-message) {\r\n display: block;\r\n margin-top: var(--_mono-dropdown-table-gap-y);\r\n font-size: var(--mono-dropdown-table-message-font-size, var(--mono-tag-input-message-font-size, var(--mono-text-sm)));\r\n line-height: var(--mono-dropdown-table-message-line-height, var(--mono-tag-input-message-line-height, var(--mono-leading-normal)));\r\n font-weight: var(--mono-font-weight-normal);\r\n text-align: start;\r\n color: var(--_mono-dropdown-table-muted);\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .field [role=\"alert\"] — text-destructive text-sm */\r\n:is([mono-dropdown-table],.mono-dropdown-table) > :is([mono-dd-message=\"invalid\"],:where(.mono-dropdown-table-message.invalid)) {\r\n color: var(--_mono-dropdown-table-invalid);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) > :is([mono-dd-message=\"valid\"],:where(.mono-dropdown-table-message.valid)) {\r\n color: var(--_mono-dropdown-table-valid);\r\n}\r\n\r\n:is([mono-dropdown-table],.mono-dropdown-table) > :is([mono-dd-message=\"warning\"],:where(.mono-dropdown-table-message.warning)) {\r\n color: var(--_mono-dropdown-table-warning);\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n :is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-trigger],.mono-dropdown-table-trigger),\r\n :is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-clear],.mono-dropdown-table-clear),\r\n :is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-arrow],.mono-dropdown-table-arrow),\r\n :is([mono-dropdown-table],.mono-dropdown-table) :is([mono-dd-scroll],.mono-dropdown-table-scroll),\r\n :is([mono-dropdown-table],.mono-dropdown-table) [mono-dd-chip-close] {\r\n transition: none;\r\n }\r\n}\r\n\r\n/* =========================================\r\n label-position — the slots form/label-position.css reads\r\n (top / notched / left / right; public knobs: --mono-dropdown-table-label-width,\r\n -label-side-gap, -label-notch-font-size, -label-notch-bg)\r\n ========================================= */\r\n\r\n[mono-dropdown-table][mono-label-position] {\r\n --_mono-lp-width: var(--mono-dropdown-table-label-width, auto);\r\n --_mono-lp-gap: var(--mono-dropdown-table-label-side-gap, calc(var(--mono-spacing) * 3));\r\n --_mono-lp-height: var(--_mono-dropdown-table-height);\r\n --_mono-lp-box-min: var(--_mono-dropdown-table-height);\r\n /* + the single-value text inset (multi chips start at the padding) */\r\n --_mono-lp-padding-x: calc(var(--_mono-dropdown-table-padding-x) + var(--mono-dropdown-table-text-inset, calc(var(--mono-spacing) * 1.5)));\r\n --_mono-lp-padding-y: var(--_mono-dropdown-table-padding-y);\r\n --_mono-lp-font: var(--mono-dropdown-table-label-notch-font-size, var(--mono-text-xs));\r\n --_mono-lp-notch-bg: var(--mono-dropdown-table-label-notch-bg, var(--background));\r\n --_mono-lp-field-bg: var(--_mono-dropdown-table-bg);\r\n}\r\n";
1345
12
 
@@ -1385,426 +52,5 @@ let MonoDropdownTableShadow = class MonoDropdownTableShadow extends withShadowUt
1385
52
  };
1386
53
  MonoDropdownTableShadow = __decorate([customElement("mono-shadow-dropdown-table")], MonoDropdownTableShadow);
1387
54
 
1388
- //#endregion
1389
- //#region src/components/dropdown-table/mono-data-dropdown.ts
1390
- function monoDataDropdown(source = null, opts = {}) {
1391
- const keyExpr = opts.keyExpr ?? "Id";
1392
- const displayExpr = opts.displayExpr;
1393
- const multiple = !!opts.multiple;
1394
- const { state: _stateRef, max: _optMax, min: _optMin, ...gridOpts } = opts;
1395
- const grid = monoDataGrid(source, gridOpts);
1396
- const optionLimits = {
1397
- max: opts.max,
1398
- min: opts.min
1399
- };
1400
- let elementLimits = {};
1401
- function effectiveLimits() {
1402
- return {
1403
- max: elementLimits.max ?? optionLimits.max,
1404
- min: elementLimits.min ?? optionLimits.min
1405
- };
1406
- }
1407
- function applyLimits() {
1408
- const { max, min } = effectiveLimits();
1409
- grid.check().configure({
1410
- max: max ?? null,
1411
- min: min ?? null
1412
- });
1413
- }
1414
- function setLimits(next) {
1415
- if (next.max === elementLimits.max && next.min === elementLimits.min) return;
1416
- elementLimits = {
1417
- max: next.max,
1418
- min: next.min
1419
- };
1420
- applyLimits();
1421
- notify();
1422
- }
1423
- if (multiple) applyLimits();
1424
- /** The field element's own props — the one slot the inner grid knows nothing about. */
1425
- const dropdownTableProps = { ...opts.props?.dropdownTable ?? {} };
1426
- /** Merged element props: the grid's slots plus this dropdown's field slot. */
1427
- function props() {
1428
- return {
1429
- ...grid.props(),
1430
- dropdownTable: dropdownTableProps
1431
- };
1432
- }
1433
- function propsSnapshot() {
1434
- const g = grid.props();
1435
- return {
1436
- ...g,
1437
- th: (g.th ?? []).map((c) => ({ ...c })),
1438
- dropdownTable: { ...dropdownTableProps }
1439
- };
1440
- }
1441
- const notifier = createNotifier({ onFlush: () => {
1442
- if (opts.state) opts.state.value = propsSnapshot();
1443
- } });
1444
- const notify = notifier.notify;
1445
- let _value = multiple ? [] : null;
1446
- const cache = /* @__PURE__ */ new Map();
1447
- const keyStr = (k) => String(k);
1448
- /** Coerce a key to the source's key type (number vs string), inferred from a row. */
1449
- function normKey(k) {
1450
- if (k == null || k === "") return k;
1451
- if (typeof grid.items[0]?.[keyExpr] === "number" && !Number.isNaN(Number(k))) return Number(k);
1452
- return k;
1453
- }
1454
- function displayOf(row) {
1455
- if (row == null) return "";
1456
- if (typeof displayExpr === "function") return String(displayExpr(row) ?? "");
1457
- if (typeof displayExpr === "string" && displayExpr) return String(row[displayExpr] ?? "");
1458
- return String(row[keyExpr] ?? "");
1459
- }
1460
- function keysOf(v) {
1461
- if (multiple) return Array.isArray(v) ? v : v == null ? [] : [v];
1462
- return v == null ? [] : [v];
1463
- }
1464
- function cacheRow(key, data) {
1465
- const nk = normKey(key);
1466
- cache.set(keyStr(nk), {
1467
- key: nk,
1468
- text: displayOf(data),
1469
- data
1470
- });
1471
- }
1472
- /** Find a currently-loaded row by key (so a clicked row caches its display text). */
1473
- function findRow(key) {
1474
- const ks = keyStr(normKey(key));
1475
- return grid.items.find((r) => keyStr(normKey(r?.[keyExpr])) === ks);
1476
- }
1477
- function emitChange() {
1478
- ctrl.onValueChange?.(multiple ? checkedKeys() : _value);
1479
- }
1480
- /**
1481
- * MULTI-SELECT IS THE GRID'S `check()` STORE — there is not a second one.
1482
- *
1483
- * The dropdown used to keep its own `_value` array beside the grid's selection,
1484
- * which is why `<mono-table-checkbox>` could bind to `dd.table` and tick without
1485
- * the chips ever moving: it drove the other store. Delegating means every
1486
- * `mono-table-*` helper works in the panel the same way, and drain / `pending` /
1487
- * per-page / the drain memo come from the grid instead of being reimplemented.
1488
- *
1489
- * `_value` stays the SINGLE-select store only, and remains the shape consumers
1490
- * bind (`modelValue`): for multi it is derived from the check store on read.
1491
- */
1492
- const check = () => grid.check();
1493
- /**
1494
- * A row for `check()` to key by. It stores rows, but a selection can name a key
1495
- * whose row is not loaded (a preset `modelValue`, or a key resolved later), so
1496
- * fall back to a stub carrying just the key — `rowKeyOf` only reads `keyExpr`.
1497
- */
1498
- function rowFor(key, rowData) {
1499
- const nk = normKey(key);
1500
- return rowData ?? findRow(nk) ?? cache.get(keyStr(nk))?.data ?? { [keyExpr]: nk };
1501
- }
1502
- /** What is selected right now, whichever store owns it. */
1503
- function currentKeys() {
1504
- return multiple ? checkedKeys() : keysOf(_value);
1505
- }
1506
- /** The multi-select value, derived from the check store (insertion order). */
1507
- function checkedKeys() {
1508
- return check().rows().map((row) => normKey(row?.[keyExpr]));
1509
- }
1510
- function isSelected(key) {
1511
- if (multiple) return check().isChecked(keyStr(normKey(key)));
1512
- const ks = keyStr(normKey(key));
1513
- return keysOf(_value).some((k) => keyStr(normKey(k)) === ks);
1514
- }
1515
- function toggleRow(key, rowData) {
1516
- const nk = normKey(key);
1517
- const data = rowData ?? findRow(nk);
1518
- if (data !== void 0) cacheRow(nk, data);
1519
- if (multiple) {
1520
- const on = check().isChecked(keyStr(nk));
1521
- check().toggle(rowFor(nk, data), !on);
1522
- } else {
1523
- _value = nk;
1524
- setOpen(false);
1525
- }
1526
- emitChange();
1527
- notify();
1528
- }
1529
- function removeKey(key) {
1530
- const nk = normKey(key);
1531
- if (multiple) check().toggle(rowFor(nk), false);
1532
- else _value = null;
1533
- emitChange();
1534
- notify();
1535
- }
1536
- function clear() {
1537
- if (multiple) check().clear();
1538
- else _value = null;
1539
- emitChange();
1540
- notify();
1541
- }
1542
- /**
1543
- * Rows this controller already holds, indexed by key — the check store first
1544
- * (it keeps whole row objects, not just keys), then the loaded page.
1545
- *
1546
- * Built lazily and ONLY when a key actually missed the cache: after a drain
1547
- * `check().rows()` can hold thousands of rows, and it allocates a fresh array
1548
- * on every call, so touching it per render would be a real cost for nothing.
1549
- */
1550
- function heldRows() {
1551
- const index = /* @__PURE__ */ new Map();
1552
- const add = (row) => {
1553
- const key = row?.[keyExpr];
1554
- if (key === void 0 || key === null) return;
1555
- const ks = keyStr(normKey(key));
1556
- if (!index.has(ks)) index.set(ks, row);
1557
- };
1558
- for (const row of grid.items) add(row);
1559
- if (multiple) for (const row of check().rows()) add(row);
1560
- return index;
1561
- }
1562
- /**
1563
- * Selected keys, labelled.
1564
- *
1565
- * A cache miss falls back to the rows already in memory before degrading to
1566
- * `String(key)`. Without that, selecting through the GRID — which is what
1567
- * `<mono-table-checkbox>` does, since it calls `check.selectAll()` directly
1568
- * rather than `dd.selectAll()` — showed every chip as its own key: only
1569
- * `selectAll()` primes the cache, and the grid subscription just notifies.
1570
- * The row was in `check().rows()` the whole time.
1571
- */
1572
- function selectedItems() {
1573
- const keys = currentKeys();
1574
- let held;
1575
- return keys.map((k) => {
1576
- const nk = normKey(k);
1577
- const ks = keyStr(nk);
1578
- const hit = cache.get(ks);
1579
- if (hit) return hit;
1580
- held ??= heldRows();
1581
- const row = held.get(ks);
1582
- if (row === void 0) return {
1583
- key: nk,
1584
- text: String(nk),
1585
- data: void 0
1586
- };
1587
- cacheRow(nk, row);
1588
- return cache.get(ks) ?? {
1589
- key: nk,
1590
- text: displayOf(row),
1591
- data: row
1592
- };
1593
- });
1594
- }
1595
- function displayText() {
1596
- return selectedItems().map((i) => i.text).join(", ");
1597
- }
1598
- /**
1599
- * Seed the display cache from rows you already hold, so `resolveSelected` has
1600
- * nothing left to fetch. The point of `setValue`'s `rows` argument and of
1601
- * {@link selectAll}: without it, setting N keys costs N/50 `in` requests to
1602
- * re-read text that was already in hand.
1603
- */
1604
- function primeCache(rows) {
1605
- if (!rows?.length) return;
1606
- for (const row of rows) cacheRow(row?.[keyExpr], row);
1607
- }
1608
- function setValue(next, rows) {
1609
- primeCache(rows);
1610
- if (multiple) check().replace(keysOf(next).map((k) => rowFor(k)));
1611
- else _value = next;
1612
- resolveSelected();
1613
- notify();
1614
- }
1615
- /**
1616
- * Select every row the source can return — the dropdown's answer to the table's
1617
- * `<mono-table-checkbox type="all" mode="all">`.
1618
- *
1619
- * `table.getData()` does the draining (chunked `store.load`, paging left alone)
1620
- * and honours the live filter + search, so "search, then select all" selects the
1621
- * matches and nothing else. The drained rows prime the cache, so this costs the
1622
- * drain and NO display-resolution requests.
1623
- *
1624
- * Emits like `toggleRow` rather than going through `setValue`: `setValue` is the
1625
- * inbound path (the element pushes `modelValue` down it) and deliberately does
1626
- * not emit, so a silent bulk change would leave the element's `modelValue` stale
1627
- * and the next push would overwrite the selection with it.
1628
- */
1629
- async function selectAll() {
1630
- if (!multiple) return;
1631
- await check().selectAll();
1632
- primeCache(check().rows());
1633
- emitChange();
1634
- notify();
1635
- }
1636
- function setOpen(next) {
1637
- if (ctrl.open === next) return;
1638
- ctrl.open = next;
1639
- if (!next) pruneCache();
1640
- notify();
1641
- }
1642
- /**
1643
- * Drop cached rows no current key needs, once the cache has outgrown the selection.
1644
- *
1645
- * The cache exists to label chips whose row is not on the loaded page; it only ever grew —
1646
- * every key ever selected, and after a select-all every drained row — and was cleared only on
1647
- * `bind()`. Pruned on close, with slack, so toggling a few rows never thrashes it.
1648
- */
1649
- function pruneCache() {
1650
- const keys = currentKeys();
1651
- if (cache.size <= keys.length * 2 + 200) return;
1652
- const keep = new Set(keys.map((k) => keyStr(normKey(k))));
1653
- for (const k of cache.keys()) if (!keep.has(k)) cache.delete(k);
1654
- }
1655
- function hasStore() {
1656
- const s = grid.dataSource;
1657
- return typeof s?.store === "function" && !!s.store();
1658
- }
1659
- function storeRows(res) {
1660
- return Array.isArray(res) ? res : res?.data ?? [];
1661
- }
1662
- function chunk(arr, size) {
1663
- const out = [];
1664
- for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
1665
- return out;
1666
- }
1667
- /**
1668
- * `run` over every part, at most `limit` requests in flight — the result order kept.
1669
- *
1670
- * A thousand preset keys are twenty `in` chunks (or ~67 OR-chain chunks in the fallback), and
1671
- * `Promise.all` over them fired every request at once: a burst a backend may throttle or reject,
1672
- * and that queues behind the browser's per-host connection cap anyway.
1673
- */
1674
- async function mapLimited(parts, limit, run) {
1675
- const out = new Array(parts.length);
1676
- let next = 0;
1677
- const worker = async () => {
1678
- while (next < parts.length) {
1679
- const i = next++;
1680
- out[i] = await run(parts[i]);
1681
- }
1682
- };
1683
- await Promise.all(Array.from({ length: Math.min(limit, parts.length) }, worker));
1684
- return out;
1685
- }
1686
- const RESOLVE_CONCURRENCY = 4;
1687
- const selectFields = () => typeof displayExpr === "string" && displayExpr ? [keyExpr, displayExpr] : void 0;
1688
- async function resolveSelected() {
1689
- const missing = currentKeys().filter((k) => !cache.has(keyStr(normKey(k))));
1690
- if (!missing.length) return;
1691
- const s = grid.dataSource;
1692
- if (hasStore()) {
1693
- const store = s.store();
1694
- let rows = [];
1695
- try {
1696
- rows = (await mapLimited(chunk(missing, 50), RESOLVE_CONCURRENCY, (part) => store.load({
1697
- filter: [
1698
- keyExpr,
1699
- "in",
1700
- part
1701
- ],
1702
- select: selectFields()
1703
- }))).flatMap(storeRows);
1704
- } catch {
1705
- const orFilter = (arr) => arr.map((v) => [
1706
- keyExpr,
1707
- "=",
1708
- v
1709
- ]).reduce((a, b) => a ? [
1710
- a,
1711
- "or",
1712
- b
1713
- ] : b, null);
1714
- rows = (await mapLimited(chunk(missing, 15), RESOLVE_CONCURRENCY, (part) => store.load({
1715
- filter: orFilter(part),
1716
- select: selectFields()
1717
- }))).flatMap(storeRows);
1718
- }
1719
- for (const row of rows) cacheRow(row?.[keyExpr], row);
1720
- } else if (typeof s?.data === "function") {
1721
- const all = s.data();
1722
- const byKey = new Map(all.map((r) => [keyStr(r?.[keyExpr]), r]));
1723
- for (const k of missing) {
1724
- const row = byKey.get(keyStr(normKey(k)));
1725
- if (row) cacheRow(k, row);
1726
- }
1727
- }
1728
- notify();
1729
- }
1730
- /**
1731
- * Forward a grid notify only when something THIS controller's readers use has moved.
1732
- *
1733
- * Forwarding every one re-rendered the whole `<mono-dropdown-table>` (chips, `selectedItems()`),
1734
- * repositioned its open panel (a forced layout) and re-reflected the selection onto every row —
1735
- * for notifies that change none of it, chiefly each virtual-scroll window shift. What the field
1736
- * reads from the grid: the selection (`check().version` / `pending`), the load state
1737
- * (`loading` / `hasLoaded` / `error` — the skeleton release), and the rows for chip labels and
1738
- * key typing — the page array itself, or under virtual scroll (whose `items` is only the window)
1739
- * the loaded count. Rows a window shift brings in are re-reflected by the panel's own
1740
- * MutationObserver, not by this notify.
1741
- */
1742
- let forwarded = [];
1743
- const gridSignature = () => {
1744
- const c = grid.check();
1745
- return [
1746
- c.version,
1747
- c.pending,
1748
- grid.loading,
1749
- grid.hasLoaded,
1750
- grid.error,
1751
- grid.scrollMode === "virtual" ? grid.loadedCount : grid.items,
1752
- grid.totalCount,
1753
- grid.hasMore,
1754
- grid.pageIndex
1755
- ];
1756
- };
1757
- const offGrid = grid.subscribe(() => {
1758
- const sig = gridSignature();
1759
- if (sig.length === forwarded.length && sig.every((v, i) => Object.is(v, forwarded[i]))) return;
1760
- forwarded = sig;
1761
- notify();
1762
- });
1763
- const ctrl = {
1764
- grid,
1765
- /** Alias of {@link grid} — the inner `controlMonoTable`. Preferred in new
1766
- * code (`dd.table.load()` / `:control-table.prop="dd.table"`); `grid` stays. */
1767
- table: grid,
1768
- props,
1769
- multiple,
1770
- open: false,
1771
- onValueChange: null,
1772
- get value() {
1773
- return multiple ? checkedKeys() : _value;
1774
- },
1775
- get selectAllPending() {
1776
- return multiple ? check().pending : false;
1777
- },
1778
- set value(next) {
1779
- setValue(next);
1780
- },
1781
- isSelected,
1782
- limits: effectiveLimits,
1783
- setLimits,
1784
- toggleRow,
1785
- removeKey,
1786
- clear,
1787
- selectAll,
1788
- selectedItems,
1789
- displayText,
1790
- setValue,
1791
- setOpen,
1792
- resolveSelected,
1793
- subscribe: notifier.subscribe,
1794
- bind(next) {
1795
- grid.bind(next);
1796
- cache.clear();
1797
- resolveSelected();
1798
- notify();
1799
- },
1800
- dispose() {
1801
- offGrid();
1802
- notifier.clear();
1803
- grid.dispose();
1804
- }
1805
- };
1806
- return ctrl;
1807
- }
1808
-
1809
55
  //#endregion
1810
56
  export { MonoDropdownTableCore, MonoDropdownTableShadow, monoDataDropdown };