@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
@@ -0,0 +1,654 @@
1
+ import { t as applyProps } from "./element-props-xvw0EB7H.js";
2
+ import { a as defineHybridPropAliases, o as numberStringConverter, r as booleanStringConverter, t as __decorate } from "./decorate-DbYFpi8R.js";
3
+ import { t as dispatchMonoEvent } from "./mono-event-CAZf0F_k.js";
4
+ import { a as rateLimitHasChanged } from "./rate-limit-e9Jlpl5l.js";
5
+ import { t as PopupPortalController } from "./popup-portal-CINuVjNY.js";
6
+ import { html, isServer, nothing } from "lit";
7
+ import { ref } from "lit/directives/ref.js";
8
+ import { property, state } from "lit/decorators.js";
9
+ import { repeat } from "lit/directives/repeat.js";
10
+
11
+ //#region src/components/button/button-dropdown-core.ts
12
+ /**
13
+ * Would these two entry lists RENDER identically?
14
+ *
15
+ * Function-valued fields are skipped: a consumer rebuilds `onClick` on every render
16
+ * so it closes over the current row, and those handlers are resolved at click time
17
+ * rather than baked into the DOM, so they cannot make the output differ. Everything
18
+ * else — label, icon, size, color, variant, disabled — is compared strictly, and any
19
+ * non-primitive field (a fresh `cssClass` object, say) simply compares unequal and
20
+ * falls back to a normal update. Conservative by construction: a false "same" would
21
+ * show stale markup, a false "different" only costs the render we have today.
22
+ */
23
+ function sameButtonItems(a, b) {
24
+ if (a === b) return true;
25
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
26
+ for (let i = 0; i < a.length; i++) {
27
+ const x = a[i];
28
+ const y = b[i];
29
+ if (x === y) continue;
30
+ if (!x || !y || typeof x !== "object" || typeof y !== "object") return false;
31
+ const keys = Object.keys(x);
32
+ if (keys.length !== Object.keys(y).length) return false;
33
+ for (const key of keys) {
34
+ const xv = x[key];
35
+ const yv = y[key];
36
+ if (typeof xv === "function" && typeof yv === "function") continue;
37
+ if (xv !== yv) return false;
38
+ }
39
+ }
40
+ return true;
41
+ }
42
+ /**
43
+ * `MonoButtonDropdownCore` — everything render-mode-agnostic for
44
+ * `mono-button-dropdown`.
45
+ *
46
+ * The behaviour in one line: **while `buttons.length <= min` the entries render
47
+ * as plain buttons; past that they ALL move into a dropdown and only the trigger
48
+ * is left.** That all-or-nothing rule is deliberate (it mirrors the Vuetify
49
+ * `ButtonMenu` this replaces) — a partial split would leave the row's width
50
+ * jumping around as the action list changes.
51
+ *
52
+ * Two pieces are borrowed rather than rebuilt:
53
+ * - **`PopupPortalController`** does the positioning, flipping and z-index
54
+ * stacking, exactly as `mono-dropdown` uses it, so this panel ranks correctly
55
+ * against modals and other popups.
56
+ * - **Each entry is a real `<mono-button>`**, so every `ButtonProps` — `loading`,
57
+ * `throttle`, `handler`, `badge` — keeps working with nothing re-implemented.
58
+ * Props are pushed on with `applyProps` rather than a fixed attribute list, so
59
+ * a prop added to the button later flows through without touching this file.
60
+ */
61
+ /**
62
+ * The component's PUBLIC custom properties, handed to the popup portal so a
63
+ * relocated panel keeps overrides an ancestor of the host set — a portaled panel
64
+ * is a child of `<body>`, so it inherits none of them, and `getComputedStyle`
65
+ * cannot enumerate custom properties for the portal to copy them blindly.
66
+ *
67
+ * Kept in step with button-dropdown.css by tests/button-dropdown-attributes.test.ts.
68
+ */
69
+ const BUTTON_DROPDOWN_STYLE_VARS = [
70
+ "--mono-button-dropdown-bg",
71
+ "--mono-button-dropdown-border",
72
+ "--mono-button-dropdown-dark",
73
+ "--mono-button-dropdown-danger",
74
+ "--mono-button-dropdown-gap",
75
+ "--mono-button-dropdown-info",
76
+ "--mono-button-dropdown-item-base-color",
77
+ "--mono-button-dropdown-item-base-hover-bg",
78
+ "--mono-button-dropdown-item-base-hover-color",
79
+ "--mono-button-dropdown-item-color",
80
+ "--mono-button-dropdown-item-font-weight",
81
+ "--mono-button-dropdown-item-hover",
82
+ "--mono-button-dropdown-item-hover-bg",
83
+ "--mono-button-dropdown-item-hover-color",
84
+ "--mono-button-dropdown-item-radius",
85
+ "--mono-button-dropdown-item-radius-lg",
86
+ "--mono-button-dropdown-item-radius-xl",
87
+ "--mono-button-dropdown-item-radius-xxl",
88
+ "--mono-button-dropdown-light",
89
+ "--mono-button-dropdown-list-gap",
90
+ "--mono-button-dropdown-min-width",
91
+ "--mono-button-dropdown-min-width-lg",
92
+ "--mono-button-dropdown-min-width-md",
93
+ "--mono-button-dropdown-min-width-sm",
94
+ "--mono-button-dropdown-min-width-xl",
95
+ "--mono-button-dropdown-min-width-xs",
96
+ "--mono-button-dropdown-min-width-xxl",
97
+ "--mono-button-dropdown-offset",
98
+ "--mono-button-dropdown-offset-lg",
99
+ "--mono-button-dropdown-offset-md",
100
+ "--mono-button-dropdown-offset-sm",
101
+ "--mono-button-dropdown-offset-xl",
102
+ "--mono-button-dropdown-offset-xs",
103
+ "--mono-button-dropdown-offset-xxl",
104
+ "--mono-button-dropdown-padding",
105
+ "--mono-button-dropdown-padding-lg",
106
+ "--mono-button-dropdown-padding-md",
107
+ "--mono-button-dropdown-padding-sm",
108
+ "--mono-button-dropdown-padding-xl",
109
+ "--mono-button-dropdown-padding-xs",
110
+ "--mono-button-dropdown-padding-xxl",
111
+ "--mono-button-dropdown-primary",
112
+ "--mono-button-dropdown-purple",
113
+ "--mono-button-dropdown-radius",
114
+ "--mono-button-dropdown-radius-lg",
115
+ "--mono-button-dropdown-radius-md",
116
+ "--mono-button-dropdown-radius-sm",
117
+ "--mono-button-dropdown-radius-xl",
118
+ "--mono-button-dropdown-radius-xs",
119
+ "--mono-button-dropdown-radius-xxl",
120
+ "--mono-button-dropdown-ring-color",
121
+ "--mono-button-dropdown-ring-width",
122
+ "--mono-button-dropdown-secondary",
123
+ "--mono-button-dropdown-shadow",
124
+ "--mono-button-dropdown-success",
125
+ "--mono-button-dropdown-surface",
126
+ "--mono-button-dropdown-teal",
127
+ "--mono-button-dropdown-text",
128
+ "--mono-button-dropdown-warning"
129
+ ];
130
+ const MonoButtonDropdownCore = (superClass) => {
131
+ class MonoButtonDropdownCoreClass extends superClass {
132
+ constructor(...args) {
133
+ super(...args);
134
+ this._panelEl = null;
135
+ this._triggerEl = null;
136
+ this._popup = new PopupPortalController(this, {
137
+ getPanel: () => this._panelEl,
138
+ getAnchor: () => this._triggerEl,
139
+ /**
140
+ * The INNER wrapper, not the host — it's what carries
141
+ * `.mono-button-dropdown`, and therefore the `--_mono-button-dropdown-*`
142
+ * variables every panel rule reads. The portal mirrors this element's class
143
+ * onto itself, so the relocated panel keeps inheriting them; pointing at the
144
+ * host (which has no class) left the panel transparent and border-less,
145
+ * since each value resolved to an undefined var.
146
+ */
147
+ getStyleScope: () => this.renderRoot?.querySelector?.(".mono-button-dropdown"),
148
+ isOpen: () => this.modelValue,
149
+ side: () => this._side(),
150
+ align: () => this._align(),
151
+ offset: () => this.offset,
152
+ styleVars: () => BUTTON_DROPDOWN_STYLE_VARS,
153
+ flip: () => true,
154
+ shift: () => true,
155
+ onSideResolved: (side) => {
156
+ if (this._resolvedSide !== side) this._resolvedSide = side;
157
+ }
158
+ });
159
+ this._buttons = [];
160
+ this.min = 1;
161
+ this.placement = "bottom-end";
162
+ this.offset = 4;
163
+ this.modelValue = false;
164
+ this.disabled = false;
165
+ this.closeOnSelect = true;
166
+ this.closeOnOutsideClick = true;
167
+ this.closeOnEscape = true;
168
+ this.cssClass = {};
169
+ this._resolvedSide = "bottom";
170
+ this._documentBound = false;
171
+ this._onDocumentClick = (event) => {
172
+ if (!this.modelValue || !this.closeOnOutsideClick) return;
173
+ const path = event.composedPath();
174
+ if (path.includes(this) || this._popup.containsInPath(path)) return;
175
+ this._setOpen(false, "outside", event);
176
+ };
177
+ this._onDocumentKeydown = (event) => {
178
+ if (!this.modelValue) return;
179
+ if (event.key === "Escape" && this.closeOnEscape) {
180
+ this._setOpen(false, "escape", event);
181
+ this._focusTrigger();
182
+ return;
183
+ }
184
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
185
+ const rows = this._menuButtons();
186
+ if (!rows.length) return;
187
+ event.preventDefault();
188
+ rows[(rows.findIndex((b) => b === document.activeElement || b.contains(document.activeElement)) + (event.key === "ArrowDown" ? 1 : -1) + rows.length) % rows.length]?.focus?.();
189
+ }
190
+ };
191
+ this._itemEls = /* @__PURE__ */ new Map();
192
+ this._itemParts = /* @__PURE__ */ new Map();
193
+ this.bindPanel = (el) => {
194
+ this._panelEl = el ?? null;
195
+ };
196
+ this._rootEl = null;
197
+ this.bindRoot = (el) => {
198
+ this._rootEl = el ?? null;
199
+ this._applyRootAttrs(this._rootEl);
200
+ };
201
+ defineHybridPropAliases(this, [
202
+ "modelValue",
203
+ "closeOnSelect",
204
+ "closeOnOutsideClick",
205
+ "closeOnEscape",
206
+ "cssClass",
207
+ "cssClassName"
208
+ ]);
209
+ }
210
+ /**
211
+ * Entries for this dropdown.
212
+ *
213
+ * `noAccessor` because assignment does two things, only one of which is an
214
+ * update. Building a fresh array on every render is the NORMAL shape whenever an
215
+ * entry's `onClick` closes over the current row — and with one dropdown per table
216
+ * row that means an unrelated re-render (a filter panel opening, say) hands N
217
+ * dropdowns a brand-new array and re-renders all of them. Measured on a 2000-row
218
+ * table: 737ms of blocked main thread per toggle, against 60ms when the array
219
+ * identity happened to be stable. Nothing about the RENDER differed.
220
+ *
221
+ * So: compare by content and skip the update when it is equivalent. Handlers are
222
+ * excluded from that comparison deliberately — they are rebuilt every render by
223
+ * design and are resolved at CLICK time from `_itemParts`, never captured in the
224
+ * listener closure (see `_itemElement`). That is also why `_retargetItemParts()`
225
+ * has to run on EVERY assignment including a skipped one: `_itemParts` is
226
+ * normally refreshed during render, so without it a suppressed update would
227
+ * leave the cached entries pointing at the previous array's closures and a click
228
+ * would fire the wrong row's handler.
229
+ */
230
+ get buttons() {
231
+ return this._buttons;
232
+ }
233
+ set buttons(next) {
234
+ const previous = this._buttons;
235
+ this._buttons = next ?? [];
236
+ this._retargetItemParts();
237
+ if (!sameButtonItems(previous, this._buttons)) this.requestUpdate("buttons", previous);
238
+ }
239
+ /**
240
+ * Point the cached entry elements at the CURRENT array without rendering, so a
241
+ * click resolves this render's `item`/`index` even when the update was skipped.
242
+ */
243
+ _retargetItemParts() {
244
+ if (!this._itemParts?.size) return;
245
+ for (const [key, state] of this._itemParts) {
246
+ const index = Number(key.slice(2));
247
+ const item = this._buttons[index];
248
+ if (item) this._itemParts.set(key, {
249
+ ...state,
250
+ item,
251
+ index
252
+ });
253
+ }
254
+ }
255
+ connectedCallback() {
256
+ super.connectedCallback();
257
+ if (isServer) return;
258
+ this._syncDocument();
259
+ }
260
+ disconnectedCallback() {
261
+ this._syncDocument(false);
262
+ super.disconnectedCallback();
263
+ }
264
+ /**
265
+ * Outside-click / Escape listeners, bound while OPEN only (select's rule). Both handlers
266
+ * bail when closed, and a grid that puts one of these in every row held two `document`
267
+ * listeners per row — one capture-phase — in the path of every click and keystroke.
268
+ */
269
+ _syncDocument(want = this.modelValue && this.isConnected) {
270
+ if (isServer || want === this._documentBound) return;
271
+ this._documentBound = want;
272
+ if (want) {
273
+ document.addEventListener("click", this._onDocumentClick, true);
274
+ document.addEventListener("keydown", this._onDocumentKeydown);
275
+ } else {
276
+ document.removeEventListener("click", this._onDocumentClick, true);
277
+ document.removeEventListener("keydown", this._onDocumentKeydown);
278
+ }
279
+ }
280
+ /** Entries are behind the trigger once there are more of them than `min`. */
281
+ get collapsed() {
282
+ return (this.buttons?.length ?? 0) > Math.max(0, this.min ?? 1);
283
+ }
284
+ show(source = "manual") {
285
+ this._setOpen(true, source);
286
+ }
287
+ hide(source = "manual") {
288
+ this._setOpen(false, source);
289
+ }
290
+ toggle(source = "manual") {
291
+ this._setOpen(!this.modelValue, source);
292
+ }
293
+ _setOpen(next, source, sourceEvent) {
294
+ if (this.disabled && next) return;
295
+ if (this.modelValue === next) return;
296
+ this.modelValue = next;
297
+ const detail = {
298
+ modelValue: next,
299
+ collapsed: this.collapsed,
300
+ source,
301
+ sourceEvent
302
+ };
303
+ dispatchMonoEvent(this, next ? "open" : "close", detail);
304
+ }
305
+ /** The rendered entry buttons inside the open panel, in order. */
306
+ _menuButtons() {
307
+ return this._panelEl ? Array.from(this._panelEl.querySelectorAll("[data-mono-bd-item]")) : [];
308
+ }
309
+ _focusTrigger() {
310
+ this._triggerEl?.focus?.();
311
+ }
312
+ _side() {
313
+ return this.placement?.split("-")[0] ?? "bottom";
314
+ }
315
+ _align() {
316
+ const part = this.placement?.split("-")[1];
317
+ return part === "start" || part === "end" ? part : "center";
318
+ }
319
+ /** Light renders `mono-button`; the shadow build overrides with its own tag. */
320
+ _buttonTag() {
321
+ return "mono-button";
322
+ }
323
+ /**
324
+ * Whether entry content can be written as a Lit template.
325
+ *
326
+ * **It can't for the light build.** A light `<mono-button>` CAPTURES its
327
+ * children in `connectedCallback` and relocates them into its own
328
+ * `[data-mono-slot]` targets — including nodes our template rendered into it.
329
+ * That ejects this element's part markers, and the next render dies with
330
+ * "this `ChildPart` has no `parentNode`". So the light build hands Lit a
331
+ * fully-built element instead (see `_itemElement`), leaving Lit no parts
332
+ * inside the button to lose.
333
+ *
334
+ * The shadow build has no such problem: it projects through a native
335
+ * `<slot>`, moves nothing, and stays SSR-safe.
336
+ */
337
+ _declarativeItems() {
338
+ return false;
339
+ }
340
+ updated(changed) {
341
+ super.updated?.(changed);
342
+ this._syncDocument();
343
+ this._applyRootAttrs(this._rootEl);
344
+ }
345
+ willUpdate(changed) {
346
+ if (changed.has("buttons")) this._pruneItemCache();
347
+ super.willUpdate?.(changed);
348
+ }
349
+ /** Forget cached entries whose index no longer exists in `buttons`. */
350
+ _pruneItemCache() {
351
+ const len = this.buttons?.length ?? 0;
352
+ for (const key of [...this._itemEls.keys()]) {
353
+ const index = Number(key.slice(2));
354
+ if (!Number.isFinite(index) || index >= len) {
355
+ this._itemEls.delete(key);
356
+ this._itemParts.delete(key);
357
+ }
358
+ }
359
+ }
360
+ /** Build (or update) the real element for one entry. */
361
+ _itemElement(item, index, inMenu, opts) {
362
+ const key = `${inMenu ? "m" : "r"}:${index}`;
363
+ let el = this._itemEls.get(key);
364
+ const prev = this._itemParts.get(key);
365
+ if (el && prev && (prev.label !== item.label || prev.icon !== item.icon)) {
366
+ this._itemEls.delete(key);
367
+ el = void 0;
368
+ }
369
+ if (!el) {
370
+ el = document.createElement(this._buttonTag());
371
+ el.setAttribute("data-mono-bd-item", "");
372
+ if (item.icon) {
373
+ const icon = document.createElement("span");
374
+ icon.setAttribute("slot", "icon");
375
+ icon.className = `mono-icon ${item.icon}`;
376
+ el.appendChild(icon);
377
+ }
378
+ if (item.label) el.appendChild(document.createTextNode(item.label));
379
+ el.addEventListener("click", ((event) => {
380
+ const state = this._itemParts.get(key);
381
+ if (state) this._onItemClick(state.item, state.index, event);
382
+ }));
383
+ el.addEventListener("mno-click", (e) => e.stopPropagation());
384
+ el.addEventListener("mnoClick", (e) => e.stopPropagation());
385
+ this._itemEls.set(key, el);
386
+ }
387
+ this._itemParts.set(key, {
388
+ label: item.label,
389
+ icon: item.icon,
390
+ item,
391
+ index
392
+ });
393
+ el.className = opts.cls;
394
+ this._applyItem(el, item);
395
+ return el;
396
+ }
397
+ _cls(base, key) {
398
+ const extra = this.cssClass?.[key];
399
+ return extra ? `${base} ${extra}` : base;
400
+ }
401
+ /**
402
+ * Push an entry's props onto its rendered `<mono-button>`.
403
+ *
404
+ * Done imperatively via a Lit ref callback rather than as template
405
+ * attributes: object/function props (`handler`, `cssClass`, `throttle`) can't
406
+ * cross as attributes, and going through `applyProps` means any prop the
407
+ * button gains later works here with no change.
408
+ */
409
+ _applyItem(el, item) {
410
+ if (!el) return;
411
+ const { label: _l, icon: _i, onClick: _c, className: _n, ...rest } = item;
412
+ applyProps(el, rest);
413
+ if (this.disabled) el.disabled = true;
414
+ }
415
+ _onItemClick(item, index, event) {
416
+ if (item.disabled || this.disabled) return;
417
+ item.onClick?.(event);
418
+ dispatchMonoEvent(this, "click", {
419
+ item,
420
+ index,
421
+ modelValue: this.modelValue,
422
+ collapsed: this.collapsed,
423
+ source: "trigger",
424
+ sourceEvent: event
425
+ });
426
+ if (this.collapsed && this.closeOnSelect) this._setOpen(false, "manual", event);
427
+ }
428
+ /** One entry, as a real button element carrying its own props. */
429
+ renderItem(item, index, inMenu) {
430
+ const tag = this._buttonTag();
431
+ const cls = [
432
+ inMenu ? "mono-button-dropdown-item-btn" : "mono-button-dropdown-row-btn",
433
+ inMenu && item.color ? `mono-bd-c-${item.color}` : "",
434
+ item.className ?? ""
435
+ ].filter(Boolean).join(" ");
436
+ const content = html`
437
+ ${item.icon ? html`<span slot="icon" class="mono-icon ${item.icon}"></span>` : nothing}
438
+ ${item.label ?? nothing}
439
+ `;
440
+ const onClick = (e) => this._onItemClick(item, index, e);
441
+ if (!this._declarativeItems()) return this._itemElement(item, index, inMenu, {
442
+ cls,
443
+ onClick
444
+ });
445
+ const bind = (el) => this._applyItem(el, item);
446
+ const stop = (e) => e.stopPropagation();
447
+ return tag === "mono-button" ? html`<mono-button
448
+ class=${cls}
449
+ data-mono-bd-item
450
+ ${ref(bind)}
451
+ @click=${onClick}
452
+ @mno-click=${stop}
453
+ @mnoClick=${stop}
454
+ >${content}</mono-button
455
+ >` : html`<mono-shadow-button
456
+ class=${cls}
457
+ data-mono-bd-item
458
+ ${ref(bind)}
459
+ @click=${onClick}
460
+ @mno-click=${stop}
461
+ @mnoClick=${stop}
462
+ >${content}</mono-shadow-button
463
+ >`;
464
+ }
465
+ /** The inline row — every entry as a plain button, no dropdown involved. */
466
+ renderRow() {
467
+ return html`
468
+ <div class=${this._cls("mono-button-dropdown-row", "row")} mono-row ?hidden=${this.collapsed}>
469
+ ${this.collapsed ? nothing : repeat(this.buttons ?? [], (_item, i) => i, (item, i) => this.renderItem(item, i, false))}
470
+ </div>
471
+ `;
472
+ }
473
+ /** Class + state for the panel, which each build writes into its own template. */
474
+ get panelClass() {
475
+ return this._cls("mono-button-dropdown-panel", "panel");
476
+ }
477
+ get panelHidden() {
478
+ return !this.collapsed || !this.modelValue;
479
+ }
480
+ /**
481
+ * The prop mirrors, each omitted at its default so `:not([mono-size])` means
482
+ * "md" for hand-written markup exactly as it does for the element.
483
+ */
484
+ _computeRootAttrs() {
485
+ const align = this._align();
486
+ const side = this.modelValue ? this._resolvedSide : this._side();
487
+ return {
488
+ "mono-size": !this.size || this.size === "md" ? null : this.size,
489
+ "mono-color": !this.color || this.color === "primary" ? null : this.color,
490
+ "mono-variant": !this.variant || this.variant === "solid" ? null : this.variant,
491
+ "mono-rounded": this.rounded ?? null,
492
+ "mono-placement": this.placement === "bottom-end" ? null : this.placement,
493
+ "mono-side": side === "bottom" ? null : side,
494
+ "mono-align": align === "end" ? null : align,
495
+ "mono-open": this.modelValue ? "" : null,
496
+ "mono-collapsed": this.collapsed ? "" : null,
497
+ "mono-disabled": this.disabled ? "" : null,
498
+ "mono-fixed": this._positionsPanel() ? "" : null
499
+ };
500
+ }
501
+ /** Does this build measure and place the panel itself? (light only — see above.) */
502
+ _positionsPanel() {
503
+ return !isServer && this.renderRoot === this;
504
+ }
505
+ _applyRootAttrs(root) {
506
+ if (!root) return;
507
+ if (!root.hasAttribute("mono-button-dropdown")) root.setAttribute("mono-button-dropdown", "");
508
+ for (const [name, value] of Object.entries(this._computeRootAttrs())) if (value === null) root.removeAttribute(name);
509
+ else if (root.getAttribute(name) !== value) root.setAttribute(name, value);
510
+ }
511
+ /**
512
+ * An entry's `color` inside the menu.
513
+ *
514
+ * It is NOT a button colour in there (see button-dropdown.css): the row takes
515
+ * the role as its INK and a 10%/20% wash of it on hover, the way Basecoat
516
+ * treats `[data-variant='destructive']`. `primary` is written out rather
517
+ * than dropped as a default, because the panel's own ink is the popover
518
+ * foreground, not the primary role.
519
+ */
520
+ _itemColorAttr(item) {
521
+ return item.color ?? null;
522
+ }
523
+ /** The menu rows. Lives INSIDE the panel, so these parts travel with it. */
524
+ renderMenuList() {
525
+ return html`
526
+ <ul class=${this._cls("mono-button-dropdown-list", "list")} mono-list>
527
+ ${this.collapsed ? repeat(this.buttons ?? [], (_item, i) => i, (item, i) => html`
528
+ <li
529
+ class=${this._cls("mono-button-dropdown-item", "item")}
530
+ mono-item
531
+ mono-item-color=${this._itemColorAttr(item) ?? nothing}
532
+ role="none"
533
+ >
534
+ ${this.renderItem(item, i, true)}
535
+ </li>
536
+ `) : nothing}
537
+ </ul>
538
+ `;
539
+ }
540
+ /** The `⋮` trigger. `nothing` while the entries are inline. */
541
+ renderTrigger() {
542
+ if (!this.collapsed) return nothing;
543
+ return this._renderTriggerButton();
544
+ }
545
+ _renderTriggerButton() {
546
+ const t = {
547
+ ...this.color ? { color: this.color } : {},
548
+ ...this.variant ? { variant: this.variant } : {},
549
+ ...this.size ? { size: this.size } : {},
550
+ ...this.rounded ? { rounded: this.rounded } : {},
551
+ ...this.trigger ?? {}
552
+ };
553
+ const tag = this._buttonTag();
554
+ const triggerCls = this._cls("mono-button-dropdown-trigger", "trigger");
555
+ const bindTrigger = (el) => {
556
+ this._triggerEl = el ?? null;
557
+ if (!el) return;
558
+ const { label: _l, icon: _i, ...rest } = t;
559
+ applyProps(el, rest);
560
+ if (this.disabled) el.disabled = true;
561
+ };
562
+ const stop = (e) => e.stopPropagation();
563
+ const onTrigger = (e) => {
564
+ e.stopPropagation();
565
+ this.toggle("trigger");
566
+ };
567
+ if (!this._declarativeItems()) {
568
+ let el = this._itemEls.get("trigger");
569
+ if (!el) {
570
+ el = document.createElement(tag);
571
+ el.setAttribute("mono-trigger", "");
572
+ const icon = document.createElement("span");
573
+ icon.setAttribute("slot", "icon");
574
+ icon.className = `mono-icon ${t.icon ?? "i-mdi-dots-vertical"}`;
575
+ el.appendChild(icon);
576
+ if (t.label) el.appendChild(document.createTextNode(t.label));
577
+ if (!t.label) el.setAttribute("icon-only", "true");
578
+ el.addEventListener("click", onTrigger);
579
+ el.addEventListener("mno-click", stop);
580
+ el.addEventListener("mnoClick", stop);
581
+ this._itemEls.set("trigger", el);
582
+ }
583
+ el.className = triggerCls;
584
+ bindTrigger(el);
585
+ return el;
586
+ }
587
+ const triggerContent = html`
588
+ <span slot="icon" class="mono-icon ${t.icon ?? "i-mdi-dots-vertical"}"></span>
589
+ ${t.label ?? nothing}
590
+ `;
591
+ return tag === "mono-button" ? html`<mono-button
592
+ class=${triggerCls}
593
+ mono-trigger
594
+ icon-only=${t.label ? nothing : "true"}
595
+ ${ref(bindTrigger)}
596
+ @click=${onTrigger}
597
+ @mno-click=${stop}
598
+ @mnoClick=${stop}
599
+ >${triggerContent}</mono-button
600
+ >` : html`<mono-shadow-button
601
+ class=${triggerCls}
602
+ mono-trigger
603
+ icon-only=${t.label ? nothing : "true"}
604
+ ${ref(bindTrigger)}
605
+ @click=${onTrigger}
606
+ @mno-click=${stop}
607
+ @mnoClick=${stop}
608
+ >${triggerContent}</mono-shadow-button
609
+ >`;
610
+ }
611
+ }
612
+ __decorate([property({
613
+ attribute: false,
614
+ noAccessor: true
615
+ })], MonoButtonDropdownCoreClass.prototype, "buttons", null);
616
+ __decorate([property({ converter: numberStringConverter })], MonoButtonDropdownCoreClass.prototype, "min", void 0);
617
+ __decorate([property({ type: String })], MonoButtonDropdownCoreClass.prototype, "placement", void 0);
618
+ __decorate([property({ converter: numberStringConverter })], MonoButtonDropdownCoreClass.prototype, "offset", void 0);
619
+ __decorate([property({ type: String })], MonoButtonDropdownCoreClass.prototype, "color", void 0);
620
+ __decorate([property({ type: String })], MonoButtonDropdownCoreClass.prototype, "variant", void 0);
621
+ __decorate([property({ type: String })], MonoButtonDropdownCoreClass.prototype, "size", void 0);
622
+ __decorate([property({ type: String })], MonoButtonDropdownCoreClass.prototype, "rounded", void 0);
623
+ __decorate([property({
624
+ attribute: false,
625
+ hasChanged: rateLimitHasChanged
626
+ })], MonoButtonDropdownCoreClass.prototype, "trigger", void 0);
627
+ __decorate([property({
628
+ attribute: "model-value",
629
+ reflect: true,
630
+ converter: booleanStringConverter
631
+ })], MonoButtonDropdownCoreClass.prototype, "modelValue", void 0);
632
+ __decorate([property({
633
+ reflect: true,
634
+ converter: booleanStringConverter
635
+ })], MonoButtonDropdownCoreClass.prototype, "disabled", void 0);
636
+ __decorate([property({
637
+ attribute: "close-on-select",
638
+ converter: booleanStringConverter
639
+ })], MonoButtonDropdownCoreClass.prototype, "closeOnSelect", void 0);
640
+ __decorate([property({
641
+ attribute: "close-on-outside-click",
642
+ converter: booleanStringConverter
643
+ })], MonoButtonDropdownCoreClass.prototype, "closeOnOutsideClick", void 0);
644
+ __decorate([property({
645
+ attribute: "close-on-escape",
646
+ converter: booleanStringConverter
647
+ })], MonoButtonDropdownCoreClass.prototype, "closeOnEscape", void 0);
648
+ __decorate([property({ attribute: false })], MonoButtonDropdownCoreClass.prototype, "cssClass", void 0);
649
+ __decorate([state()], MonoButtonDropdownCoreClass.prototype, "_resolvedSide", void 0);
650
+ return MonoButtonDropdownCoreClass;
651
+ };
652
+
653
+ //#endregion
654
+ export { MonoButtonDropdownCore as t };