@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,831 @@
1
+ import { a as defineHybridPropAliases, n as arrayHasChanged, r as booleanStringConverter, t as __decorate } from "./decorate-DbYFpi8R.js";
2
+ import { t as dispatchMonoEvent } from "./mono-event-CAZf0F_k.js";
3
+ import { t as isIconifyClass } from "./icon-BM9N-jOt.js";
4
+ import { a as validateColorProp, i as isThemeColorToken, n as colorClassToken, r as customColorStyle, t as CUSTOM_COLOR_CLASS } from "./color-CEYYtRX-.js";
5
+ import { html, isServer, nothing } from "lit";
6
+ import { property, state } from "lit/decorators.js";
7
+
8
+ //#region src/components/menu/menu-utils.ts
9
+ function isItem(node) {
10
+ return !node.type || node.type === "item";
11
+ }
12
+ function isGroup(node) {
13
+ return node.type === "group";
14
+ }
15
+ function isDivider(node) {
16
+ return node.type === "divider";
17
+ }
18
+ function isSubheader(node) {
19
+ return node.type === "subheader";
20
+ }
21
+ /**
22
+ * Walk the tree and collect the chain (root → leaf) leading to the item with
23
+ * the given id. Returns an empty array if not found.
24
+ */
25
+ function findActivePath(items, id) {
26
+ for (const node of items) {
27
+ if (node.id === id) return [node];
28
+ if (node.items?.length) {
29
+ const sub = findActivePath(node.items, id);
30
+ if (sub.length) return [node, ...sub];
31
+ }
32
+ }
33
+ return [];
34
+ }
35
+ function findItem(items, id) {
36
+ for (const node of items) {
37
+ if (node.id === id) return node;
38
+ if (node.items?.length) {
39
+ const sub = findItem(node.items, id);
40
+ if (sub) return sub;
41
+ }
42
+ }
43
+ return null;
44
+ }
45
+ /**
46
+ * Generate a 1–2 character alias from a menu item's title for the icon
47
+ * fallback (used by `renderMenuIcon` when no `item.icon` and no slot icon are
48
+ * provided). Each space-delimited word contributes its first character; output
49
+ * is uppercased and capped at `max` characters.
50
+ *
51
+ * Examples:
52
+ * getMenuAlias('Dashboard') → 'D'
53
+ * getMenuAlias('Post Budget') → 'PB'
54
+ * getMenuAlias('Sales Order Report') → 'SO'
55
+ * getMenuAlias('logbook') → 'L'
56
+ * getMenuAlias('') → ''
57
+ */
58
+ function getMenuAlias(input, max = 2) {
59
+ if (!input || typeof input !== "string") return "";
60
+ const words = input.trim().split(/\s+/).filter(Boolean);
61
+ if (!words.length) return "";
62
+ return words.slice(0, max).map((w) => w.charAt(0)).join("").toUpperCase();
63
+ }
64
+ function collectDefaultOpenGroups(items) {
65
+ const out = [];
66
+ const visit = (list) => {
67
+ for (const node of list) {
68
+ if (isGroup(node) && node.defaultOpen) out.push(node.id);
69
+ if (node.items?.length) visit(node.items);
70
+ }
71
+ };
72
+ visit(items);
73
+ return out;
74
+ }
75
+ function generateMenuRootClasses(props) {
76
+ return [
77
+ "mono-menu",
78
+ props.density,
79
+ colorClassToken(props.color),
80
+ props.nav ? "nav" : "plain",
81
+ props.selectable ? "" : "not-selectable",
82
+ props.disabled ? "disabled" : "",
83
+ props.cssClassName ?? "",
84
+ props.rootExtra ?? ""
85
+ ].filter(Boolean).join(" ");
86
+ }
87
+ function validateMenuProps(props) {
88
+ const errors = [];
89
+ if (props.density && ![
90
+ "compact",
91
+ "comfortable",
92
+ "default"
93
+ ].includes(props.density)) errors.push(`Invalid density: ${String(props.density)}`);
94
+ const colorError = validateColorProp(props.color);
95
+ if (colorError) errors.push(colorError);
96
+ return errors;
97
+ }
98
+ /**
99
+ * The Basecoat styling attributes for the menu ROOT, mirroring the props one
100
+ * for one. A prop at its DEFAULT emits nothing — `:not([mono-density])` is
101
+ * comfortable and `:not([mono-color])` is primary — so the rendered DOM is
102
+ * also the shortest hand-written markup that paints the same (see menu.css).
103
+ * `nav` defaults to TRUE, so `mono-plain` is the attribute that says
104
+ * something. Shared so `<mono-menu>` and a standalone `<mono-menu-list>`
105
+ * cannot drift apart.
106
+ */
107
+ function menuRootAttrs(props) {
108
+ return {
109
+ density: props.density === "comfortable" ? null : props.density,
110
+ color: isThemeColorToken(props.color) || props.color === "surface" ? props.color === "primary" ? null : props.color : CUSTOM_COLOR_CLASS
111
+ };
112
+ }
113
+
114
+ //#endregion
115
+ //#region src/components/menu/menu-render.ts
116
+ function clsFor(base, key, cssClass) {
117
+ const extra = cssClass?.[key];
118
+ return extra ? `${base} ${extra}` : base;
119
+ }
120
+ function renderMenuIcon(item, ctx) {
121
+ const slotNodes = ctx.getSlotIconNodes(item.id);
122
+ if (!!(slotNodes && slotNodes.length)) return html`
123
+ <span
124
+ class=${clsFor("mono-menu-icon", "icon", ctx.cssClass)}
125
+ mono-icon
126
+ aria-hidden="true"
127
+ >
128
+ <span data-mono-slot=${`icon-${item.id}`}></span>
129
+ </span>
130
+ `;
131
+ if (ctx.iconSlot && item.icon && isIconifyClass(item.icon)) return html`
132
+ <span
133
+ class=${clsFor("mono-menu-icon", "icon", ctx.cssClass)}
134
+ mono-icon
135
+ aria-hidden="true"
136
+ >
137
+ <slot name=${`icon-${item.id}`}></slot>
138
+ </span>
139
+ `;
140
+ if (item.icon && isIconifyClass(item.icon)) return html`
141
+ <span
142
+ class=${clsFor("mono-menu-icon", "icon", ctx.cssClass)}
143
+ mono-icon
144
+ aria-hidden="true"
145
+ >
146
+ <span class=${`mono-menu-iconify ${item.icon}`} mono-glyph></span>
147
+ </span>
148
+ `;
149
+ if (item.icon) return html`
150
+ <span
151
+ class=${clsFor("mono-menu-icon", "icon", ctx.cssClass)}
152
+ mono-icon
153
+ aria-hidden="true"
154
+ >
155
+ ${item.icon}
156
+ </span>
157
+ `;
158
+ const alias = getMenuAlias(item.title || item.id);
159
+ if (alias) return html`
160
+ <span
161
+ class=${`${clsFor("mono-menu-icon", "icon", ctx.cssClass)} alias`}
162
+ mono-icon
163
+ mono-alias
164
+ aria-hidden="true"
165
+ data-mono-alias=${alias}
166
+ >
167
+ ${alias}
168
+ </span>
169
+ `;
170
+ return nothing;
171
+ }
172
+ function renderMenuBadge(item, ctx) {
173
+ if (item.badge === void 0 || item.badge === null || item.badge === "") return nothing;
174
+ const colorClass = item.badgeColor && item.badgeColor !== "default" ? item.badgeColor : "";
175
+ return html`
176
+ <span
177
+ class=${`${clsFor("mono-menu-badge", "badge", ctx.cssClass)} ${colorClass}`.trim()}
178
+ mono-badge=${colorClass}
179
+ >
180
+ ${item.badge}
181
+ </span>
182
+ `;
183
+ }
184
+ function renderMenuAppend(item, ctx) {
185
+ if (item.badge !== void 0 && item.badge !== null && item.badge !== "") return renderMenuBadge(item, ctx);
186
+ if (!item.appendIcon) return nothing;
187
+ return html`
188
+ <span
189
+ class=${clsFor("mono-menu-append", "appendIcon", ctx.cssClass)}
190
+ mono-append
191
+ aria-hidden="true"
192
+ >
193
+ ${item.appendIcon}
194
+ </span>
195
+ `;
196
+ }
197
+ function renderMenuItemRow(item, ctx) {
198
+ const active = ctx.isSelected(item.id);
199
+ const itemClasses = [
200
+ clsFor("mono-menu-item", "item", ctx.cssClass),
201
+ active ? "active" : "",
202
+ active && ctx.cssClass?.itemActive ? ctx.cssClass.itemActive : "",
203
+ item.disabled ? "disabled" : "",
204
+ item.disabled && ctx.cssClass?.itemDisabled ? ctx.cssClass.itemDisabled : ""
205
+ ].filter(Boolean).join(" ");
206
+ const tag = item.href ? "a" : "button";
207
+ const actionInner = html`
208
+ ${renderMenuIcon(item, ctx)}
209
+ <span class=${clsFor("mono-menu-content", "content", ctx.cssClass)} mono-content>
210
+ <span class=${clsFor("mono-menu-title", "title", ctx.cssClass)} mono-title>
211
+ ${item.title ?? item.id}
212
+ </span>
213
+ ${item.subtitle ? html`<span
214
+ class=${clsFor("mono-menu-subtitle", "subtitle", ctx.cssClass)}
215
+ mono-subtitle
216
+ >${item.subtitle}</span
217
+ >` : nothing}
218
+ </span>
219
+ ${renderMenuAppend(item, ctx)}
220
+ `;
221
+ return html`
222
+ <li class=${itemClasses} mono-item ?mono-active=${active} ?mono-disabled=${!!item.disabled}>
223
+ ${tag === "a" ? html`
224
+ <a
225
+ class=${clsFor("mono-menu-action", "action", ctx.cssClass)}
226
+ mono-action
227
+ href=${item.href}
228
+ role=${ctx.selectable ? "option" : "link"}
229
+ aria-current=${active ? "page" : "false"}
230
+ aria-disabled=${item.disabled ? "true" : "false"}
231
+ @click=${(e) => ctx.onItemClick(item, e)}
232
+ >
233
+ ${actionInner}
234
+ </a>
235
+ ` : html`
236
+ <button
237
+ type="button"
238
+ class=${clsFor("mono-menu-action", "action", ctx.cssClass)}
239
+ mono-action
240
+ role=${ctx.selectable ? "option" : "menuitem"}
241
+ aria-selected=${ctx.selectable ? active ? "true" : "false" : nothing}
242
+ aria-disabled=${item.disabled ? "true" : "false"}
243
+ ?disabled=${item.disabled || ctx.disabled}
244
+ @click=${(e) => ctx.onItemClick(item, e)}
245
+ >
246
+ ${actionInner}
247
+ </button>
248
+ `}
249
+ ${ctx.bodySlot && !isGroup(item) ? html`<ul
250
+ class=${clsFor("mono-menu-list", "list", ctx.cssClass)}
251
+ mono-list
252
+ data-mono-slot="body"
253
+ ></ul>` : item.items?.length && !isGroup(item) ? html`<ul class=${clsFor("mono-menu-list", "list", ctx.cssClass)} mono-list>
254
+ ${renderMenuList(item.items, ctx)}
255
+ </ul>` : nothing}
256
+ </li>
257
+ `;
258
+ }
259
+ function renderMenuGroup(group, ctx) {
260
+ const open = ctx.isGroupOpen(group.id);
261
+ const ancestorActive = ctx.isGroupActive?.(group) ?? false;
262
+ const groupClasses = [clsFor("mono-menu-group", "group", ctx.cssClass), ancestorActive ? "active" : ""].filter(Boolean).join(" ");
263
+ return html`
264
+ <li
265
+ class=${groupClasses}
266
+ mono-item
267
+ mono-group
268
+ ?mono-open=${open}
269
+ ?mono-active=${ancestorActive}
270
+ ?mono-disabled=${!!group.disabled}
271
+ data-open=${open ? "true" : "false"}
272
+ >
273
+ <button
274
+ type="button"
275
+ class=${clsFor("mono-menu-group-header", "groupHeader", ctx.cssClass)}
276
+ mono-group-header
277
+ aria-expanded=${open ? "true" : "false"}
278
+ ?disabled=${group.disabled || ctx.disabled}
279
+ @click=${(e) => ctx.onGroupToggle(group, e)}
280
+ >
281
+ ${renderMenuIcon(group, ctx)}
282
+ <span class=${clsFor("mono-menu-content", "content", ctx.cssClass)} mono-content>
283
+ <span class=${clsFor("mono-menu-title", "title", ctx.cssClass)} mono-title>
284
+ ${group.title ?? group.id}
285
+ </span>
286
+ ${group.subtitle ? html`<span
287
+ class=${clsFor("mono-menu-subtitle", "subtitle", ctx.cssClass)}
288
+ mono-subtitle
289
+ >${group.subtitle}</span
290
+ >` : nothing}
291
+ </span>
292
+ <span
293
+ class=${clsFor("mono-menu-chevron", "groupChevron", ctx.cssClass)}
294
+ mono-chevron
295
+ aria-hidden="true"
296
+ >
297
+ ${ctx.chevronSvg ?? html`<span class="mono-icon i-mdi-chevron-right" aria-hidden="true"></span>`}
298
+ </span>
299
+ </button>
300
+ ${ctx.bodySlot ? html`<ul
301
+ class=${clsFor("mono-menu-list", "groupBody", ctx.cssClass)}
302
+ mono-list
303
+ mono-group-body
304
+ data-mono-slot="body"
305
+ ></ul>` : group.items?.length ? html`<ul
306
+ class=${clsFor("mono-menu-list", "groupBody", ctx.cssClass)}
307
+ mono-list
308
+ mono-group-body
309
+ >
310
+ ${renderMenuList(group.items, ctx)}
311
+ </ul>` : nothing}
312
+ </li>
313
+ `;
314
+ }
315
+ function renderMenuDivider(item, ctx) {
316
+ return html`<li
317
+ class=${clsFor("mono-menu-divider", "divider", ctx.cssClass)}
318
+ mono-divider
319
+ role="separator"
320
+ data-id=${item.id}
321
+ ></li>`;
322
+ }
323
+ function renderMenuSubheader(item, ctx) {
324
+ return html`<li
325
+ class=${clsFor("mono-menu-subheader", "subheader", ctx.cssClass)}
326
+ mono-subheader
327
+ data-id=${item.id}
328
+ >
329
+ ${item.title ?? ""}
330
+ </li>`;
331
+ }
332
+ function renderMenuList(list, ctx) {
333
+ return list.map((item) => {
334
+ if (isDivider(item)) return renderMenuDivider(item, ctx);
335
+ if (isSubheader(item)) return renderMenuSubheader(item, ctx);
336
+ if (isGroup(item)) return renderMenuGroup(item, ctx);
337
+ return renderMenuItemRow(item, ctx);
338
+ });
339
+ }
340
+ /**
341
+ * Render only the group rows from `list` — non-group items are skipped.
342
+ * Used by `<mono-menu-list type="group">`.
343
+ */
344
+ function renderMenuGroupsOnly(list, ctx) {
345
+ const out = [];
346
+ for (const item of list) if (isGroup(item)) out.push(renderMenuGroup(item, ctx));
347
+ return out;
348
+ }
349
+
350
+ //#endregion
351
+ //#region src/components/menu/menu-core.ts
352
+ /** Coerce any `items` input (array, JSON string, or other) to a MenuItem array. */
353
+ function coerceItems(value) {
354
+ if (Array.isArray(value)) return value;
355
+ if (typeof value === "string") {
356
+ if (!value) return [];
357
+ try {
358
+ const parsed = JSON.parse(value);
359
+ return Array.isArray(parsed) ? parsed : [];
360
+ } catch {
361
+ return [];
362
+ }
363
+ }
364
+ return [];
365
+ }
366
+ /**
367
+ * `MonoMenuCore` — all render-mode-agnostic logic for `mono-menu`: reactive
368
+ * props, hybrid aliases, css-class interop, selection + open-group state,
369
+ * default-open seeding, the click/toggle/change events, the full public API, and
370
+ * the chrome `render()` (which delegates the body to a `_renderBody()` hook).
371
+ *
372
+ * Leaves to each build: `createRenderRoot()`, the body strategy (light: slot
373
+ * capture / declarative `slot="body"`; shadow: items-driven only), and
374
+ * `_chevronSvg()` (light: undefined → UnoCSS icon span; shadow: inline SVG).
375
+ */
376
+ const MonoMenuCore = (superClass) => {
377
+ class MonoMenuCoreClass extends superClass {
378
+ constructor(...args) {
379
+ super(...args);
380
+ this.items = [];
381
+ this.modelValue = "";
382
+ this.multiple = false;
383
+ this.density = "comfortable";
384
+ this.color = "primary";
385
+ this.nav = true;
386
+ this.selectable = true;
387
+ this.disabled = false;
388
+ this.controlled = false;
389
+ this.cssClass = {};
390
+ this.cssClassName = "";
391
+ this._openGroups = /* @__PURE__ */ new Set();
392
+ this._seededGroups = /* @__PURE__ */ new Set();
393
+ this._slotIcons = /* @__PURE__ */ new Map();
394
+ this._listChildren = /* @__PURE__ */ new Set();
395
+ this._railSidebar = null;
396
+ this._railObserver = null;
397
+ this._railRetryRaf = null;
398
+ this._railRetryTimer = null;
399
+ defineHybridPropAliases(this, ["modelValue", "cssClass"]);
400
+ Object.defineProperty(this, "css-class", {
401
+ get: () => this.cssClass,
402
+ set: (value) => this._setCssClass(value),
403
+ configurable: true,
404
+ enumerable: false
405
+ });
406
+ Object.defineProperty(this, "cssclass", {
407
+ get: () => this.cssClass,
408
+ set: (value) => this._setCssClass(value),
409
+ configurable: true,
410
+ enumerable: false
411
+ });
412
+ }
413
+ static get observedAttributes() {
414
+ return [
415
+ ...super.observedAttributes ?? [],
416
+ "modelvalue",
417
+ "css-class",
418
+ "cssclass"
419
+ ];
420
+ }
421
+ attributeChangedCallback(name, oldValue, newValue) {
422
+ super.attributeChangedCallback(name, oldValue, newValue);
423
+ if (oldValue === newValue) return;
424
+ if (name === "modelvalue") {
425
+ this.modelValue = newValue ?? "";
426
+ return;
427
+ }
428
+ if (name === "css-class" || name === "cssclass") this._setCssClass(newValue);
429
+ }
430
+ connectedCallback() {
431
+ super.connectedCallback();
432
+ if (isServer) return;
433
+ this._setupRailSync();
434
+ }
435
+ disconnectedCallback() {
436
+ if (!isServer) this._teardownRailSync();
437
+ super.disconnectedCallback();
438
+ }
439
+ willUpdate(changed) {
440
+ if (typeof this.items === "string") this.items = coerceItems(this.items);
441
+ super.willUpdate?.(changed);
442
+ if (changed.has("items")) this._seedDefaultOpenGroups();
443
+ }
444
+ _seedDefaultOpenGroups() {
445
+ const existing = new Set(this._openGroups);
446
+ let changed = false;
447
+ for (const id of collectDefaultOpenGroups(this.items)) {
448
+ if (this._seededGroups.has(id)) continue;
449
+ this._seededGroups.add(id);
450
+ if (!existing.has(id)) {
451
+ existing.add(id);
452
+ changed = true;
453
+ }
454
+ }
455
+ if (!changed) return;
456
+ this._openGroups = existing;
457
+ }
458
+ _setCssClass(value) {
459
+ if (value == null) {
460
+ this.cssClass = {};
461
+ this.cssClassName = "";
462
+ return;
463
+ }
464
+ if (typeof value === "object") {
465
+ this.cssClass = value;
466
+ return;
467
+ }
468
+ if (typeof value === "string") {
469
+ const trimmed = value.trim();
470
+ if (!trimmed) {
471
+ this.cssClass = {};
472
+ this.cssClassName = "";
473
+ return;
474
+ }
475
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) try {
476
+ this.cssClass = JSON.parse(trimmed);
477
+ return;
478
+ } catch {}
479
+ this.cssClassName = trimmed;
480
+ }
481
+ }
482
+ _cls(base, key) {
483
+ const extra = this.cssClass?.[key];
484
+ return extra ? `${base} ${extra}` : base;
485
+ }
486
+ get _rootClasses() {
487
+ return generateMenuRootClasses({
488
+ density: this.density,
489
+ color: this.color,
490
+ nav: this.nav,
491
+ selectable: this.selectable,
492
+ disabled: this.disabled,
493
+ cssClassName: this.cssClassName,
494
+ rootExtra: this.cssClass?.root
495
+ });
496
+ }
497
+ _isSelected(id) {
498
+ if (this.multiple) return Array.isArray(this.modelValue) && this.modelValue.includes(id);
499
+ return !this.multiple && this.modelValue === id;
500
+ }
501
+ _isGroupOpen(id) {
502
+ return this._openGroups.has(id);
503
+ }
504
+ /** A group is "active" when the currently-selected item is a descendant. */
505
+ _isGroupActive(group) {
506
+ const selected = this.multiple ? Array.isArray(this.modelValue) ? this.modelValue : [] : [this.modelValue];
507
+ const ids = new Set(selected.filter(Boolean));
508
+ if (!ids.size) return false;
509
+ const contains = (node) => !!node.items?.some((child) => ids.has(child.id) || contains(child));
510
+ return contains(group);
511
+ }
512
+ _findRegisteredItem(id) {
513
+ for (const child of this._listChildren) {
514
+ const items = child.getMenuItems?.() ?? [];
515
+ const found = findItem(items, id);
516
+ if (found) return found;
517
+ }
518
+ return null;
519
+ }
520
+ _findAnyItem(id) {
521
+ return findItem(this.items, id) ?? this._findRegisteredItem(id);
522
+ }
523
+ _getRegisteredActivePath(id) {
524
+ for (const child of this._listChildren) {
525
+ const items = child.getMenuItems?.() ?? [];
526
+ const path = findActivePath(items, id);
527
+ if (path.length) return path;
528
+ }
529
+ return [];
530
+ }
531
+ select(id) {
532
+ const item = this._findAnyItem(id);
533
+ if (!item || !isItem(item)) return;
534
+ this._handleItemActivation(item);
535
+ }
536
+ deselect(id) {
537
+ if (!this.multiple) {
538
+ if (this.modelValue === id) {
539
+ const oldValue = this.modelValue;
540
+ this.modelValue = "";
541
+ this._emitChange(id, this._findAnyItem(id) ?? { id }, false, oldValue);
542
+ }
543
+ return;
544
+ }
545
+ if (Array.isArray(this.modelValue) && this.modelValue.includes(id)) {
546
+ const oldValue = [...this.modelValue];
547
+ this.modelValue = this.modelValue.filter((v) => v !== id);
548
+ this._emitChange(id, this._findAnyItem(id) ?? { id }, false, oldValue);
549
+ }
550
+ }
551
+ toggleGroup(id) {
552
+ const item = this._findAnyItem(id);
553
+ if (!item || !isGroup(item)) return;
554
+ this._handleGroupToggle(item);
555
+ }
556
+ expandGroup(id) {
557
+ if (this._openGroups.has(id)) return;
558
+ const next = new Set(this._openGroups);
559
+ next.add(id);
560
+ this._openGroups = next;
561
+ }
562
+ collapseGroup(id) {
563
+ if (!this._openGroups.has(id)) return;
564
+ const next = new Set(this._openGroups);
565
+ next.delete(id);
566
+ this._openGroups = next;
567
+ }
568
+ focus() {
569
+ this.querySelector(".mono-menu-action, .mono-menu-group-header")?.focus();
570
+ }
571
+ getActivePath() {
572
+ const id = !this.multiple ? this.modelValue : Array.isArray(this.modelValue) && this.modelValue.length ? this.modelValue[this.modelValue.length - 1] : "";
573
+ if (!id) return [];
574
+ const ownPath = findActivePath(this.items, id);
575
+ if (ownPath.length) return ownPath;
576
+ return this._getRegisteredActivePath(id);
577
+ }
578
+ requestItemActivation(item, event) {
579
+ this._handleItemActivation(item, event);
580
+ }
581
+ requestGroupToggle(group, event) {
582
+ this._handleGroupToggle(group, event);
583
+ }
584
+ isItemSelected(id) {
585
+ return this._isSelected(id);
586
+ }
587
+ isGroupOpenPublic(id) {
588
+ return this._isGroupOpen(id);
589
+ }
590
+ getSlotIconNodes(id) {
591
+ return this._slotIcons.get(id);
592
+ }
593
+ /** @internal called by `<mono-menu-list>` from its connectedCallback. */
594
+ _registerListChild(child) {
595
+ this._listChildren.add(child);
596
+ }
597
+ /** @internal called by `<mono-menu-list>` from its disconnectedCallback. */
598
+ _unregisterListChild(child) {
599
+ this._listChildren.delete(child);
600
+ }
601
+ /** Walk up across slot + shadow boundaries to the host `<mono-sidebar>`, if any. */
602
+ _findAncestorSidebar() {
603
+ let node = this.assignedSlot ?? this.parentNode;
604
+ while (node) {
605
+ if (node instanceof Element && (node.localName === "mono-sidebar" || node.localName === "mono-shadow-sidebar")) return node;
606
+ node = node.assignedSlot ?? (node instanceof ShadowRoot ? node.host : node.parentNode);
607
+ }
608
+ return null;
609
+ }
610
+ _setupRailSync(retries = 30) {
611
+ if (this._railObserver) this._teardownRailSync();
612
+ const sidebar = this._findAncestorSidebar();
613
+ if (!sidebar) {
614
+ if (retries <= 0 || isServer) return;
615
+ let fired = false;
616
+ const retry = () => {
617
+ if (fired) return;
618
+ fired = true;
619
+ this._railRetryRaf = null;
620
+ this._railRetryTimer = null;
621
+ if (this.isConnected) this._setupRailSync(retries - 1);
622
+ };
623
+ this._cancelRailRetry();
624
+ if (typeof requestAnimationFrame !== "undefined") this._railRetryRaf = requestAnimationFrame(retry);
625
+ this._railRetryTimer = setTimeout(retry, 32);
626
+ return;
627
+ }
628
+ this._railSidebar = sidebar;
629
+ this._applyRailCollapsed(sidebar.hasAttribute("data-rail-collapsed"));
630
+ this._railObserver = new MutationObserver(() => {
631
+ this._applyRailCollapsed(sidebar.hasAttribute("data-rail-collapsed"));
632
+ });
633
+ this._railObserver.observe(sidebar, {
634
+ attributes: true,
635
+ attributeFilter: ["data-rail-collapsed"]
636
+ });
637
+ }
638
+ _cancelRailRetry() {
639
+ if (this._railRetryRaf !== null && typeof cancelAnimationFrame !== "undefined") cancelAnimationFrame(this._railRetryRaf);
640
+ if (this._railRetryTimer !== null) clearTimeout(this._railRetryTimer);
641
+ this._railRetryRaf = null;
642
+ this._railRetryTimer = null;
643
+ }
644
+ _teardownRailSync() {
645
+ this._cancelRailRetry();
646
+ this._railObserver?.disconnect();
647
+ this._railObserver = null;
648
+ this._railSidebar = null;
649
+ }
650
+ static {
651
+ this._RAIL_COLLAPSE_VARS = [
652
+ ["--mono-menu-label-display", "none"],
653
+ ["--mono-menu-row-display", "flex"],
654
+ ["--mono-menu-row-justify", "center"],
655
+ ["--mono-menu-action-width", "auto"],
656
+ ["--mono-menu-action-justify", "center"],
657
+ ["--mono-menu-action-gap", "0"],
658
+ ["--mono-menu-group-children-display", "none"]
659
+ ];
660
+ }
661
+ _applyRailCollapsed(collapsed) {
662
+ this.toggleAttribute("rail-collapsed", collapsed);
663
+ const vars = MonoMenuCoreClass._RAIL_COLLAPSE_VARS;
664
+ if (collapsed) for (const [name, value] of vars) this.style.setProperty(name, value);
665
+ else for (const [name] of vars) this.style.removeProperty(name);
666
+ }
667
+ _handleItemActivation(item, event) {
668
+ if (item.disabled || this.disabled) return;
669
+ dispatchMonoEvent(this, "click", {
670
+ value: item.id,
671
+ item,
672
+ sourceEvent: event
673
+ });
674
+ if (this.controlled) return;
675
+ if (!this.selectable) return;
676
+ if (this.multiple) {
677
+ const oldArr = Array.isArray(this.modelValue) ? [...this.modelValue] : [];
678
+ let nextArr;
679
+ let selected;
680
+ if (oldArr.includes(item.id)) {
681
+ nextArr = oldArr.filter((v) => v !== item.id);
682
+ selected = false;
683
+ } else {
684
+ nextArr = [...oldArr, item.id];
685
+ selected = true;
686
+ }
687
+ this.modelValue = nextArr;
688
+ this._emitChange(item.id, item, selected, oldArr, event);
689
+ return;
690
+ }
691
+ const oldValue = this.modelValue;
692
+ if (oldValue === item.id) return;
693
+ this.modelValue = item.id;
694
+ this._emitChange(item.id, item, true, oldValue, event);
695
+ }
696
+ _emitChange(value, item, selected, oldValue, event) {
697
+ const detail = {
698
+ modelValue: this.modelValue,
699
+ oldValue,
700
+ value,
701
+ item,
702
+ selected,
703
+ sourceEvent: event
704
+ };
705
+ dispatchMonoEvent(this, "change", detail);
706
+ }
707
+ _handleGroupToggle(group, event) {
708
+ if (group.disabled || this.disabled) return;
709
+ const oldOpen = this._openGroups.has(group.id);
710
+ const next = new Set(this._openGroups);
711
+ if (oldOpen) next.delete(group.id);
712
+ else next.add(group.id);
713
+ this._openGroups = next;
714
+ const detail = {
715
+ groupId: group.id,
716
+ open: !oldOpen,
717
+ oldOpen,
718
+ group,
719
+ sourceEvent: event
720
+ };
721
+ dispatchMonoEvent(this, "toggle-group", detail);
722
+ }
723
+ /** Inline chevron — light: undefined (UnoCSS span); shadow: inline SVG. */
724
+ _chevronSvg() {}
725
+ /** Whether to project icons via native `<slot>` — light: false; shadow: true. */
726
+ _useIconSlots() {
727
+ return false;
728
+ }
729
+ _renderContext() {
730
+ return {
731
+ multiple: this.multiple,
732
+ selectable: this.selectable,
733
+ disabled: this.disabled,
734
+ cssClass: this.cssClass,
735
+ chevronSvg: this._chevronSvg(),
736
+ iconSlot: this._useIconSlots(),
737
+ isSelected: (id) => this._isSelected(id),
738
+ isGroupOpen: (id) => this._isGroupOpen(id),
739
+ isGroupActive: (group) => this._isGroupActive(group),
740
+ getSlotIconNodes: (id) => this._slotIcons.get(id),
741
+ onItemClick: (item, e) => this._handleItemActivation(item, e),
742
+ onGroupToggle: (group, e) => this._handleGroupToggle(group, e)
743
+ };
744
+ }
745
+ /** Default body — items-driven. Light overrides to add the slot="body" path. */
746
+ _renderBody() {
747
+ return html`
748
+ <ul
749
+ class=${this._cls("mono-menu-list", "list")}
750
+ mono-list
751
+ role=${this.selectable ? "listbox" : "menu"}
752
+ >
753
+ ${renderMenuList(this.items, this._renderContext())}
754
+ </ul>
755
+ `;
756
+ }
757
+ /**
758
+
759
+ * Carries a literal `color` (`#7c3aed`, `rgb(…)`) that no stylesheet can know about.
760
+ * Empty for a palette slot, which resolves entirely through the `.mono-menu.<token>`
761
+ * rules instead.
762
+ *
763
+ * Must land on the ROOT element, not the host: a class-based `-preset` declared on
764
+ * the root beats an inherited one, so a host-level write would silently lose. If a
765
+ * `_syncRootFromState`-style attribute re-assert is ever added here (sidebar has one),
766
+ * it has to serialize from THIS getter or it will wipe the colour.
767
+ */
768
+ get _inlineRootStyle() {
769
+ const raw = isThemeColorToken(this.color) || this.color === "surface" ? "" : this.color;
770
+ return customColorStyle(raw, "menu");
771
+ }
772
+ render() {
773
+ const attrs = menuRootAttrs(this);
774
+ return html`
775
+ <nav
776
+ class=${this._rootClasses}
777
+ style=${this._inlineRootStyle}
778
+ role="navigation"
779
+ mono-menu
780
+ mono-density=${attrs.density ?? nothing}
781
+ mono-color=${attrs.color ?? nothing}
782
+ ?mono-plain=${!this.nav}
783
+ ?mono-disabled=${this.disabled}
784
+ >
785
+ ${this._renderBody()}
786
+ </nav>
787
+ `;
788
+ }
789
+ }
790
+ __decorate([property({
791
+ attribute: "items",
792
+ converter: {
793
+ fromAttribute: (value) => coerceItems(value),
794
+ toAttribute: () => null
795
+ },
796
+ hasChanged: arrayHasChanged
797
+ })], MonoMenuCoreClass.prototype, "items", void 0);
798
+ __decorate([property({
799
+ attribute: "model-value",
800
+ reflect: true
801
+ })], MonoMenuCoreClass.prototype, "modelValue", void 0);
802
+ __decorate([property({
803
+ reflect: true,
804
+ converter: booleanStringConverter
805
+ })], MonoMenuCoreClass.prototype, "multiple", void 0);
806
+ __decorate([property({ type: String })], MonoMenuCoreClass.prototype, "density", void 0);
807
+ __decorate([property({ type: String })], MonoMenuCoreClass.prototype, "color", void 0);
808
+ __decorate([property({
809
+ reflect: true,
810
+ converter: booleanStringConverter
811
+ })], MonoMenuCoreClass.prototype, "nav", void 0);
812
+ __decorate([property({
813
+ reflect: true,
814
+ converter: booleanStringConverter
815
+ })], MonoMenuCoreClass.prototype, "selectable", void 0);
816
+ __decorate([property({
817
+ reflect: true,
818
+ converter: booleanStringConverter
819
+ })], MonoMenuCoreClass.prototype, "disabled", void 0);
820
+ __decorate([property({
821
+ reflect: true,
822
+ converter: booleanStringConverter
823
+ })], MonoMenuCoreClass.prototype, "controlled", void 0);
824
+ __decorate([property({ attribute: false })], MonoMenuCoreClass.prototype, "cssClass", void 0);
825
+ __decorate([property({ attribute: false })], MonoMenuCoreClass.prototype, "cssClassName", void 0);
826
+ __decorate([state()], MonoMenuCoreClass.prototype, "_openGroups", void 0);
827
+ return MonoMenuCoreClass;
828
+ };
829
+
830
+ //#endregion
831
+ export { isGroup as _, renderMenuGroup as a, validateMenuProps as b, renderMenuItemRow as c, collectDefaultOpenGroups as d, findActivePath as f, isDivider as g, getMenuAlias as h, renderMenuDivider as i, renderMenuList as l, generateMenuRootClasses as m, renderMenuAppend as n, renderMenuGroupsOnly as o, findItem as p, renderMenuBadge as r, renderMenuIcon as s, MonoMenuCore as t, renderMenuSubheader as u, isItem as v, isSubheader as y };