@mono-lit/helper 0.0.8 → 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-CLqE8F8P.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-DUXo_jxd.js → mono-data-dropdown-Bgj2PDfm.js} +1 -1
  38. package/dist/{mono-data-grid-Bb00QM72.js → mono-data-grid-DJkp96N-.js} +346 -51
  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 +58 -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 +130 -5
  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-Bkr-e1-i.js +0 -4043
  161. package/dist/normalize-error-BmLbgANw.js +0 -1048
@@ -0,0 +1,1145 @@
1
+ import { d as buildSizeStyle } from "./mono-ui-kvLVIf1V.js";
2
+ import { a as defineHybridPropAliases, r as booleanStringConverter, t as __decorate } from "./decorate-DbYFpi8R.js";
3
+ import { t as dispatchMonoEvent } from "./mono-event-CAZf0F_k.js";
4
+ import { t as MonoFormControlCore } from "./form-control-core-CRZPZ1ru.js";
5
+ import { a as parseFormat, c as stripFormat, i as normaliseValue, n as caretAfterFormat, s as significantFor, t as applyFormat } from "./input-format-GrRCJBqV.js";
6
+ import { n as cssPart } from "./css-class-B6Tc_MAx.js";
7
+ import { t as FieldTooltipController } from "./field-tooltip-Csk4s2ve.js";
8
+ import { t as FieldValidationController } from "./field-validation-CFmUmuDx.js";
9
+ import { html, nothing } from "lit";
10
+ import { property, query, state } from "lit/decorators.js";
11
+ import { ifDefined } from "lit/directives/if-defined.js";
12
+ import { styleMap } from "lit/directives/style-map.js";
13
+
14
+ //#region src/components/input/input-core.ts
15
+ const numberStringConverter = {
16
+ fromAttribute(value) {
17
+ if (value === null || value === "") return void 0;
18
+ const parsed = Number(value);
19
+ return Number.isFinite(parsed) ? parsed : void 0;
20
+ },
21
+ toAttribute(value) {
22
+ if (value === void 0 || value === null) return null;
23
+ return String(value);
24
+ }
25
+ };
26
+ /**
27
+ * `modelValue` reflects to `model-value`, but only while it is TEXT — a `type="file"` value is a
28
+ * `File` / `File[]`, which would otherwise land in the DOM as `"[object File]"`.
29
+ */
30
+ const modelValueConverter = {
31
+ fromAttribute(value) {
32
+ return value ?? "";
33
+ },
34
+ toAttribute(value) {
35
+ return typeof value === "string" ? value : null;
36
+ }
37
+ };
38
+ /**
39
+ * `MonoInputCore` — all render-mode-agnostic logic for `mono-input`: reactive
40
+ * props, hybrid prop aliases (camelCase ↔ kebab ↔ lowercase), attribute
41
+ * observation, value/model two-way sync, events, validation/class computation,
42
+ * sizing, and imperative focus/blur/select.
43
+ *
44
+ * It deliberately leaves out:
45
+ * - `createRenderRoot()` (light vs shadow) — set by each wrapper.
46
+ * - the slot strategy + `render()` — light uses a capture/`data-mono-slot`
47
+ * hack; shadow uses native `<slot>` with slotchange-driven presence. The
48
+ * shared `_hasXxxSlotState` `@state` fields back both strategies and feed the
49
+ * class getters.
50
+ */
51
+ const MonoInputCore = (superClass) => {
52
+ class MonoInputCoreClass extends MonoFormControlCore(superClass) {
53
+ constructor(...args) {
54
+ super(...args);
55
+ this.cssClass = {};
56
+ this.cssClassName = "";
57
+ this.type = "text";
58
+ this.size = "md";
59
+ this.color = "primary";
60
+ this.variant = "outlined";
61
+ this.labelPosition = "top";
62
+ this.validationPosition = "bottom";
63
+ this.modelValue = "";
64
+ this.value = "";
65
+ this.accept = "";
66
+ this.multiple = false;
67
+ this.showValue = true;
68
+ this.formatOn = "input";
69
+ this.name = "";
70
+ this.placeholder = "";
71
+ this.label = "";
72
+ this.helperText = "";
73
+ this.tooltip = null;
74
+ this._tooltip = new FieldTooltipController(this, () => this.tooltip);
75
+ this._validation = new FieldValidationController(this, () => ({
76
+ position: this.validationPosition,
77
+ ...this._validationNotice ?? {
78
+ state: void 0,
79
+ text: void 0
80
+ }
81
+ }), () => this.renderRoot?.querySelector?.("[mono-input] > [mono-field]"));
82
+ this.validationState = "default";
83
+ this.validationMessage = "";
84
+ this.error = false;
85
+ this.errorMessage = "";
86
+ this.success = false;
87
+ this.successMessage = "";
88
+ this.pattern = "";
89
+ this.autocomplete = "";
90
+ this.inputmode = "";
91
+ this.disabled = false;
92
+ this.readonly = false;
93
+ this.required = false;
94
+ this.clearable = false;
95
+ this.autofocus = false;
96
+ this._display = "";
97
+ this._focused = false;
98
+ this._internalWrite = false;
99
+ this._hasPrefixSlotState = false;
100
+ this._hasSuffixSlotState = false;
101
+ this._hasLabelSlotState = false;
102
+ this._hasHelperSlotState = false;
103
+ this._inputId = `mono-input-${Math.random().toString(36).slice(2)}`;
104
+ this._messageId = `${this._inputId}-message`;
105
+ defineHybridPropAliases(this, [
106
+ "labelPosition",
107
+ "validationPosition",
108
+ "modelValue",
109
+ "formatDisplay",
110
+ "formatValue",
111
+ "formatOn",
112
+ "formatLocale",
113
+ "helperText",
114
+ "validationState",
115
+ "validationMessage",
116
+ "errorMessage",
117
+ "successMessage",
118
+ "ariaLabelText",
119
+ "minLength",
120
+ "maxLength",
121
+ "maxFileSize",
122
+ "showValue",
123
+ "cssClass",
124
+ "minWidth",
125
+ "maxWidth",
126
+ "minHeight",
127
+ "maxHeight"
128
+ ]);
129
+ for (const alias of [
130
+ "ariaLabel",
131
+ "aria-label",
132
+ "arialabel"
133
+ ]) Object.defineProperty(this, alias, {
134
+ get: () => this.ariaLabelText,
135
+ set: (value) => {
136
+ this.ariaLabelText = value == null ? void 0 : String(value);
137
+ },
138
+ configurable: true,
139
+ enumerable: false
140
+ });
141
+ Object.defineProperty(this, "maxlength", {
142
+ get: () => this.maxLength,
143
+ set: (value) => {
144
+ this.maxLength = this._toOptionalNumber(value);
145
+ },
146
+ configurable: true,
147
+ enumerable: false
148
+ });
149
+ Object.defineProperty(this, "minlength", {
150
+ get: () => this.minLength,
151
+ set: (value) => {
152
+ this.minLength = this._toOptionalNumber(value);
153
+ },
154
+ configurable: true,
155
+ enumerable: false
156
+ });
157
+ }
158
+ static get observedAttributes() {
159
+ return [
160
+ ...super.observedAttributes ?? [],
161
+ "modelvalue",
162
+ "helpertext",
163
+ "validationstate",
164
+ "validationmessage",
165
+ "errormessage",
166
+ "successmessage",
167
+ "arialabeltext",
168
+ "arialabel",
169
+ "minlength",
170
+ "maxlength",
171
+ "maxfilesize",
172
+ "showvalue",
173
+ "css-class",
174
+ "cssclass",
175
+ "formatdisplay",
176
+ "format-display",
177
+ "formatvalue",
178
+ "format-value",
179
+ "formaton",
180
+ "formatlocale"
181
+ ];
182
+ }
183
+ attributeChangedCallback(name, oldValue, newValue) {
184
+ super.attributeChangedCallback(name, oldValue, newValue);
185
+ if (oldValue === newValue) return;
186
+ switch (name) {
187
+ case "css-class":
188
+ case "cssclass":
189
+ this.cssClassName = newValue ?? "";
190
+ return;
191
+ case "formatdisplay":
192
+ case "format-display":
193
+ this._setFormatFromAttribute("formatDisplay", newValue);
194
+ return;
195
+ case "formatvalue":
196
+ case "format-value":
197
+ this._setFormatFromAttribute("formatValue", newValue);
198
+ return;
199
+ case "formaton":
200
+ this.formatOn = newValue ?? "input";
201
+ return;
202
+ case "formatlocale":
203
+ this.formatLocale = newValue ?? void 0;
204
+ return;
205
+ case "modelvalue":
206
+ this.modelValue = newValue ?? "";
207
+ return;
208
+ case "helpertext":
209
+ this.helperText = newValue ?? "";
210
+ return;
211
+ case "validationstate":
212
+ this.validationState = newValue ?? "default";
213
+ return;
214
+ case "validationmessage":
215
+ this.validationMessage = newValue ?? "";
216
+ return;
217
+ case "errormessage":
218
+ this.errorMessage = newValue ?? "";
219
+ return;
220
+ case "successmessage":
221
+ this.successMessage = newValue ?? "";
222
+ return;
223
+ case "arialabeltext":
224
+ case "arialabel":
225
+ this.ariaLabelText = newValue ?? void 0;
226
+ return;
227
+ case "minlength":
228
+ this.minLength = this._toOptionalNumber(newValue);
229
+ return;
230
+ case "maxlength":
231
+ this.maxLength = this._toOptionalNumber(newValue);
232
+ return;
233
+ case "maxfilesize":
234
+ this.maxFileSize = this._toOptionalNumber(newValue);
235
+ return;
236
+ case "showvalue":
237
+ this.showValue = newValue === null ? true : booleanStringConverter.fromAttribute(newValue);
238
+ return;
239
+ }
240
+ }
241
+ /** The validation message and its state — the same precedence the message row uses. */
242
+ get _validationNotice() {
243
+ if (this.validationMessage) return {
244
+ state: this._resolvedValidationState,
245
+ text: this.validationMessage
246
+ };
247
+ if (this.errorMessage) return {
248
+ state: "invalid",
249
+ text: this.errorMessage
250
+ };
251
+ if (this.successMessage) return {
252
+ state: "valid",
253
+ text: this.successMessage
254
+ };
255
+ return null;
256
+ }
257
+ /** The message that moved to the icon / float bubble, kept for assistive tech only. */
258
+ _renderMovedMessage() {
259
+ const notice = this._validationNotice;
260
+ return html`<div
261
+ class=${`${this._cls("mono-input-message", "message")} ${notice.state}`}
262
+ mono-message=${notice.state}
263
+ mono-sr-only
264
+ role=${notice.state === "invalid" ? "alert" : nothing}
265
+ >${notice.text}</div>`;
266
+ }
267
+ willUpdate(changed) {
268
+ if (this._isFile) {
269
+ if (changed.has("modelValue") || changed.has("type")) {
270
+ const files = this._fileList();
271
+ const names = this._fileNames(files);
272
+ this.value = names;
273
+ this._display = names;
274
+ if (!files.length && this._fileEl) this._fileEl.value = "";
275
+ }
276
+ this._internalWrite = false;
277
+ return;
278
+ }
279
+ if (changed.has("modelValue") && this.value !== this.modelValue) this.value = typeof this.modelValue === "string" ? this.modelValue : "";
280
+ if (changed.has("value") && this.modelValue !== this.value) this.modelValue = String(this.value ?? "");
281
+ if (!this._internalWrite && !this._focused && (changed.has("value") || changed.has("modelValue") || changed.has("formatDisplay"))) this._syncDisplayFromValue();
282
+ this._internalWrite = false;
283
+ }
284
+ firstUpdated() {
285
+ if (this.autofocus) this.focus();
286
+ }
287
+ _toOptionalNumber(value) {
288
+ if (value === void 0 || value === null || value === "") return void 0;
289
+ if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
290
+ if (typeof value === "string") {
291
+ const parsed = Number(value);
292
+ return Number.isFinite(parsed) ? parsed : void 0;
293
+ }
294
+ }
295
+ get _hasPrefixSlot() {
296
+ return this._hasPrefixSlotState;
297
+ }
298
+ get _hasSuffixSlot() {
299
+ return this._hasSuffixSlotState;
300
+ }
301
+ get _hasLabelSlot() {
302
+ return this._hasLabelSlotState;
303
+ }
304
+ get _hasHelperSlot() {
305
+ return this._hasHelperSlotState;
306
+ }
307
+ get _resolvedValidationState() {
308
+ if (this.validationState && this.validationState !== "default") return this.validationState;
309
+ if (this.error || this.errorMessage) return "invalid";
310
+ if (this.success || this.successMessage) return "valid";
311
+ return "default";
312
+ }
313
+ _cls(base, key) {
314
+ return cssPart(this.cssClass, base, key);
315
+ }
316
+ get _wrapperClasses() {
317
+ return [
318
+ "mono-input",
319
+ this.size,
320
+ this.color,
321
+ this.variant,
322
+ this.disabled ? "disabled" : "",
323
+ this.readonly ? "readonly" : "",
324
+ this._resolvedValidationState !== "default" ? `is-${this._resolvedValidationState}` : "",
325
+ this._hasPrefixSlot ? "has-prefix" : "",
326
+ this._hasSuffixSlot || this.clearable || this._isFile ? "has-suffix" : "",
327
+ this.value ? "has-value" : "",
328
+ this.cssClassName,
329
+ this.cssClass?.root
330
+ ].filter(Boolean).join(" ");
331
+ }
332
+ get _fieldClasses() {
333
+ return [
334
+ this._cls("mono-input-field", "field"),
335
+ this.size,
336
+ this.color,
337
+ this.variant,
338
+ this.disabled ? "disabled" : "",
339
+ this.readonly ? "readonly" : "",
340
+ this._resolvedValidationState !== "default" ? `is-${this._resolvedValidationState}` : "",
341
+ this._hasPrefixSlot ? "has-prefix" : "",
342
+ this._hasSuffixSlot || this.clearable || this._isFile ? "has-suffix" : "",
343
+ this.value ? "has-value" : ""
344
+ ].filter(Boolean).join(" ");
345
+ }
346
+ get _isFile() {
347
+ return this.type === "file";
348
+ }
349
+ get _isRange() {
350
+ return this.type === "range";
351
+ }
352
+ /** `min` / `max` / `step` as the native range resolves them (0 / 100 / 1 when unset). */
353
+ _rangeBounds() {
354
+ const min = this._toOptionalNumber(this.min) ?? 0;
355
+ const rawMax = this._toOptionalNumber(this.max) ?? 100;
356
+ const max = rawMax < min ? min : rawMax;
357
+ const step = this._toOptionalNumber(this.step);
358
+ return {
359
+ min,
360
+ max,
361
+ step: step && step > 0 ? step : 1
362
+ };
363
+ }
364
+ /**
365
+ * The value the slider is actually AT, as a string. An empty value is not a position — the
366
+ * native range parks itself at the midpoint — so the readout and the fill follow the native
367
+ * rule rather than reading `''` as 0. The model is not rewritten: nothing was chosen yet.
368
+ */
369
+ get _rangeValue() {
370
+ const { min, max, step } = this._rangeBounds();
371
+ const target = this._toOptionalNumber(this.value) ?? min + (max - min) / 2;
372
+ const snapped = min + Math.round((target - min) / step) * step;
373
+ return String(Number(Math.min(max, Math.max(min, snapped)).toFixed(10)));
374
+ }
375
+ /** How far along the track the value sits, 0–100 — drives the fill. */
376
+ get _rangeProgress() {
377
+ const { min, max } = this._rangeBounds();
378
+ if (max === min) return 0;
379
+ return (Number(this._rangeValue) - min) / (max - min) * 100;
380
+ }
381
+ /** The readout text: the value drawn through `format-display`. */
382
+ get _rangeText() {
383
+ return this._formatDisplay(this._rangeValue, { pad: true });
384
+ }
385
+ /**
386
+ * A native range ignores `readonly`, so a readonly slider would still move. Put the thumb
387
+ * back where the value says and report that the event was handled.
388
+ */
389
+ _revertReadonlyRange(event) {
390
+ if (!this._isRange || !this.readonly || this.disabled) return false;
391
+ event.currentTarget.value = this._rangeValue;
392
+ event.stopPropagation();
393
+ return true;
394
+ }
395
+ /** `modelValue` as an array of files, whatever shape it arrived in (File, File[], null, ''). */
396
+ _fileList() {
397
+ const isFile = (v) => !!v && typeof v === "object" && typeof v.name === "string";
398
+ const v = this.modelValue;
399
+ if (Array.isArray(v)) return v.filter(isFile);
400
+ return isFile(v) ? [v] : [];
401
+ }
402
+ _fileNames(files) {
403
+ return files.map((f) => f.name).join(", ");
404
+ }
405
+ _openFilePicker() {
406
+ if (this.disabled || this.readonly) return;
407
+ this._fileEl?.click();
408
+ }
409
+ _handleFileKeydown(event) {
410
+ if (event.key !== "Enter" && event.key !== " ") return;
411
+ event.preventDefault();
412
+ this._openFilePicker();
413
+ }
414
+ /** Files above `maxFileSize` are dropped, each one reported through `error`. */
415
+ _acceptFiles(files, sourceEvent) {
416
+ const limit = this.maxFileSize;
417
+ if (!limit || limit <= 0) return files;
418
+ return files.filter((file) => {
419
+ if (file.size <= limit) return true;
420
+ const detail = {
421
+ message: `File "${file.name}" exceeds the maximum size limit.`,
422
+ reason: "max-file-size",
423
+ file,
424
+ maxFileSize: limit,
425
+ sourceEvent
426
+ };
427
+ dispatchMonoEvent(this, "error", detail);
428
+ return false;
429
+ });
430
+ }
431
+ /**
432
+ * The picker's native `input` fires BEFORE its `change`, i.e. before the value below is
433
+ * written — left to bubble, a host `@input` (and a bound form) would read the OLD value. Our
434
+ * own `input` is emitted from the change handler instead.
435
+ */
436
+ _swallowNativeInput(event) {
437
+ event.stopPropagation();
438
+ }
439
+ _handleFileChange(event) {
440
+ if (this.disabled || this.readonly) return;
441
+ const input = event.currentTarget;
442
+ const files = this._acceptFiles(Array.from(input.files ?? []), event);
443
+ if (!files.length) {
444
+ input.value = "";
445
+ return;
446
+ }
447
+ this._internalWrite = true;
448
+ const oldValue = this.modelValue;
449
+ const nextValue = this.multiple ? files : files[0];
450
+ this.modelValue = nextValue;
451
+ this.value = this._display = this._fileNames(files);
452
+ const detail = this._createModelDetail({
453
+ modelValue: nextValue,
454
+ oldValue,
455
+ sourceEvent: event
456
+ });
457
+ this._emitInput(detail);
458
+ this._emitChange(detail);
459
+ }
460
+ _createModelDetail(args) {
461
+ return {
462
+ ...this._isFile ? { files: this._fileList() } : {},
463
+ modelValue: args.modelValue,
464
+ currentValue: args.modelValue,
465
+ oldValue: args.oldValue,
466
+ value: args.modelValue,
467
+ displayValue: this._display,
468
+ name: this.name,
469
+ sourceEvent: args.sourceEvent
470
+ };
471
+ }
472
+ _emitInput(detail) {
473
+ dispatchMonoEvent(this, "input", detail);
474
+ }
475
+ _emitChange(detail) {
476
+ dispatchMonoEvent(this, "change", detail);
477
+ }
478
+ _emitClear(detail) {
479
+ dispatchMonoEvent(this, "clear", detail);
480
+ }
481
+ /**
482
+ * Take a format from an ATTRIBUTE.
483
+ *
484
+ * Both format props are `attribute: false`, because a function cannot cross an attribute —
485
+ * so Lit ignores the markup form entirely and this is what puts it back. Two guards, both
486
+ * borrowed from `mono-select`'s `displayValue`, which has exactly this shape:
487
+ *
488
+ * - a function already set through `.prop` is never overwritten by an attribute;
489
+ * - Vue stringifies non-primitive props when it also mirrors them as attributes, so a value
490
+ * that merely LOOKS like a serialized function is skipped — otherwise the real function,
491
+ * arriving a tick later, would be clobbered by its own `String()` form.
492
+ */
493
+ _setFormatFromAttribute(key, next) {
494
+ if (typeof this[key] === "function") return;
495
+ const value = next ?? "";
496
+ if (this._looksLikeSerializedFunction(value)) return;
497
+ this[key] = value;
498
+ }
499
+ _looksLikeSerializedFunction(value) {
500
+ const trimmed = value.trim();
501
+ if (!trimmed) return false;
502
+ return /^(?:asyncs+)?(?:function|([^)]*)s*=>|[A-Za-z_$][w$]*s*=>)/.test(trimmed);
503
+ }
504
+ /** Is either format prop set? Everything below short-circuits when not. */
505
+ get _hasFormat() {
506
+ return !!(this.formatDisplay || this.formatValue);
507
+ }
508
+ /** The display pattern parsed once per read — used for stripping and for caret significance. */
509
+ get _displayDescriptor() {
510
+ const format = this.formatDisplay ?? this.formatValue;
511
+ return typeof format === "string" && format ? parseFormat(format) : null;
512
+ }
513
+ /**
514
+ * The text in the field, reduced to what the user actually typed.
515
+ *
516
+ * A function format has no inverse, so there is nothing to strip — the typed text IS the raw
517
+ * value, and a caller using a function owns both directions.
518
+ */
519
+ _rawFromDisplay(text) {
520
+ return stripFormat(text, this._displayDescriptor, this.formatLocale);
521
+ }
522
+ /** Re-render the display from the current value. Skipped while focused — see the call site. */
523
+ _syncDisplayFromValue() {
524
+ const raw = this._rawFromDisplay(String(this.value ?? ""));
525
+ this._display = this._formatDisplay(raw, { pad: true });
526
+ }
527
+ _formatDisplay(raw, opts = {}) {
528
+ if (!this.formatDisplay) return raw;
529
+ if (typeof this.formatDisplay === "function") return String(this.formatDisplay({
530
+ value: raw,
531
+ type: this.type,
532
+ locale: this.formatLocale
533
+ }) ?? "");
534
+ const descriptor = parseFormat(this.formatDisplay);
535
+ if (!descriptor) return raw;
536
+ return applyFormat(raw, descriptor, this.formatLocale, opts);
537
+ }
538
+ _formatValue(raw) {
539
+ if (!this.formatValue) return raw;
540
+ if (typeof this.formatValue === "function") return String(this.formatValue({
541
+ value: raw,
542
+ type: this.type,
543
+ locale: this.formatLocale
544
+ }) ?? "");
545
+ const descriptor = parseFormat(this.formatValue);
546
+ if (!descriptor) return raw;
547
+ return normaliseValue(raw, descriptor);
548
+ }
549
+ /**
550
+ * Hold a formatted numeric value inside `min` / `max`.
551
+ *
552
+ * Those two are otherwise INERT on this component. They are forwarded to the native input, and
553
+ * the platform only honours them on `number`, `range` and the date types — while a numeric
554
+ * format REQUIRES `type="text"`, because a native number input blanks itself the moment a
555
+ * grouping separator appears. So `max="100"` on a formatted field did exactly nothing, which
556
+ * is the opposite of what it reads like. This is what gives it meaning.
557
+ *
558
+ * Only the number-pattern path clamps. Everywhere else `min` / `max` keep their native
559
+ * meaning and are simply passed through, so a plain `type="text"` field is untouched —
560
+ * clamping arbitrary text against a number would be nonsense.
561
+ *
562
+ * `max` applies WHILE TYPING; `min` only on commit. The asymmetry is deliberate: a lower
563
+ * bound is crossed on the way to almost every legal value — with `min="10"`, clamping live
564
+ * would rewrite the first `1` to `10` and `15` could never be typed — whereas an upper bound
565
+ * is only ever crossed by overshooting, which is precisely when it should cut.
566
+ *
567
+ * A part-typed value is left alone. `''` and a lone `-` return early, and a trailing decimal
568
+ * point parses to the integer before it, so `"2."` under `max="100"` keeps its point instead
569
+ * of having it deleted from under the caret.
570
+ *
571
+ * Values arriving from OUTSIDE — a `modelValue` binding, a form write-back — are deliberately
572
+ * not clamped: this bounds what a person types, and silently rewriting data handed to the
573
+ * field would hide a mismatch rather than surface it.
574
+ */
575
+ _clampRaw(raw, opts = {}) {
576
+ if (this._displayDescriptor?.kind !== "number") return raw;
577
+ if (!raw || raw === "-") return raw;
578
+ const n = Number(raw);
579
+ if (!Number.isFinite(n)) return raw;
580
+ const max = this._toOptionalNumber(this.max);
581
+ if (max != null && n > max) return String(max);
582
+ const min = this._toOptionalNumber(this.min);
583
+ if (opts.commit && min != null && n < min) return String(min);
584
+ return raw;
585
+ }
586
+ /**
587
+ * Rewrite the field and put the caret back where the user left it.
588
+ *
589
+ * Written IMPERATIVELY rather than through `this._display` alone, and that is the whole trick:
590
+ * lit commits `.value` in a microtask AFTER this handler returns, and the browser parks the
591
+ * caret at the end of any value it is handed. Writing here — synchronously, inside the input
592
+ * event — means the caret can be restored in the same breath, and setting `_display` to the
593
+ * same string afterwards leaves lit's committed value already matching, so it never writes
594
+ * again and never gets the chance to move it.
595
+ */
596
+ _applyDisplay(input, next, caretBefore) {
597
+ const prev = input.value;
598
+ if (prev === next) {
599
+ this._display = next;
600
+ return;
601
+ }
602
+ input.value = next;
603
+ this._display = next;
604
+ if (caretBefore == null) return;
605
+ const significant = significantFor(this._displayDescriptor, this.formatLocale);
606
+ const caret = caretAfterFormat(next, caretBefore, prev, significant);
607
+ try {
608
+ input.setSelectionRange(caret, caret);
609
+ } catch {}
610
+ }
611
+ _handleInput(event) {
612
+ if (this._revertReadonlyRange(event)) return;
613
+ if (this.disabled || this.readonly) return;
614
+ this._internalWrite = true;
615
+ const input = event.currentTarget;
616
+ const oldValue = this.modelValue;
617
+ if (!this._hasFormat || this._isRange) {
618
+ const nextValue = input.value;
619
+ this.value = nextValue;
620
+ this.modelValue = nextValue;
621
+ this._display = nextValue;
622
+ this._emitInput(this._createModelDetail({
623
+ modelValue: nextValue,
624
+ oldValue,
625
+ sourceEvent: event
626
+ }));
627
+ return;
628
+ }
629
+ const caret = input.selectionStart;
630
+ const raw = this._clampRaw(this._rawFromDisplay(input.value));
631
+ const nextValue = this._formatValue(raw);
632
+ if (this.formatOn === "input") this._applyDisplay(input, this._formatDisplay(raw), caret);
633
+ else this._display = input.value;
634
+ this.value = nextValue;
635
+ this.modelValue = nextValue;
636
+ this._emitInput(this._createModelDetail({
637
+ modelValue: nextValue,
638
+ oldValue,
639
+ sourceEvent: event
640
+ }));
641
+ }
642
+ _handleChange(event) {
643
+ if (this._revertReadonlyRange(event)) return;
644
+ if (this.disabled || this.readonly) return;
645
+ this._internalWrite = true;
646
+ const input = event.currentTarget;
647
+ const oldValue = this.modelValue;
648
+ if (!this._hasFormat || this._isRange) {
649
+ const nextValue = input.value;
650
+ this.value = nextValue;
651
+ this.modelValue = nextValue;
652
+ this._display = nextValue;
653
+ this._emitChange(this._createModelDetail({
654
+ modelValue: nextValue,
655
+ oldValue,
656
+ sourceEvent: event
657
+ }));
658
+ return;
659
+ }
660
+ const raw = this._clampRaw(this._rawFromDisplay(input.value), { commit: true });
661
+ const nextValue = this._formatValue(raw);
662
+ this._applyDisplay(input, this._formatDisplay(raw, { pad: true }), null);
663
+ this.value = nextValue;
664
+ this.modelValue = nextValue;
665
+ this._emitChange(this._createModelDetail({
666
+ modelValue: nextValue,
667
+ oldValue,
668
+ sourceEvent: event
669
+ }));
670
+ }
671
+ _handleFocus() {
672
+ this._focused = true;
673
+ }
674
+ _handleBlur() {
675
+ this._focused = false;
676
+ if (this._hasFormat) this._syncDisplayFromValue();
677
+ }
678
+ _handleClear() {
679
+ if (this.disabled || this.readonly) return;
680
+ this._internalWrite = true;
681
+ const oldValue = this.modelValue;
682
+ if (this._isFile) {
683
+ const empty = this.multiple ? [] : null;
684
+ this.modelValue = empty;
685
+ this.value = this._display = "";
686
+ if (this._fileEl) this._fileEl.value = "";
687
+ this._inputEl?.focus();
688
+ const detail = this._createModelDetail({
689
+ modelValue: empty,
690
+ oldValue
691
+ });
692
+ this._emitInput(detail);
693
+ this._emitChange(detail);
694
+ this._emitClear(detail);
695
+ return;
696
+ }
697
+ const nextValue = "";
698
+ this.value = nextValue;
699
+ this.modelValue = nextValue;
700
+ this._display = nextValue;
701
+ if (this._inputEl) {
702
+ this._inputEl.value = nextValue;
703
+ this._inputEl.focus();
704
+ }
705
+ const detail = this._createModelDetail({
706
+ modelValue: nextValue,
707
+ oldValue
708
+ });
709
+ this._emitInput(detail);
710
+ this._emitClear(detail);
711
+ }
712
+ /** Inline sizing applied to the root wrapper. */
713
+ _sizeStyle() {
714
+ return buildSizeStyle(this);
715
+ }
716
+ /**
717
+ * The root wrapper, shared by both builds. Its `mono-*` attributes mirror the
718
+ * props one for one and are what input.css styles (`[mono-input][mono-size="sm"]`);
719
+ * a prop at its default emits NO attribute, so the DOM reads exactly like the
720
+ * hand-written CSS-tab markup. The classes stay as inert hooks until 2.0.
721
+ */
722
+ _renderWrapper(inner) {
723
+ const state = this._resolvedValidationState;
724
+ return html`<div
725
+ class=${this._wrapperClasses}
726
+ style=${styleMap(this._sizeStyle())}
727
+ mono-input
728
+ mono-size=${this.size === "md" ? nothing : this.size}
729
+ mono-color=${this.color === "primary" ? nothing : this.color}
730
+ mono-variant=${this.variant === "outlined" ? nothing : this.variant}
731
+ mono-label-position=${this.labelPosition === "top" ? nothing : this.labelPosition}
732
+ mono-validation-position=${this.validationPosition === "bottom" ? nothing : this.validationPosition}
733
+ mono-validation-state=${state === "default" ? nothing : state}
734
+ mono-type=${this._isFile || this._isRange ? this.type : nothing}
735
+ ?mono-disabled=${this.disabled}
736
+ ?mono-readonly=${this.readonly}
737
+ ?mono-required=${this.required}
738
+ ?mono-clearable=${this.clearable}
739
+ >${inner}</div>`;
740
+ }
741
+ /** Computed aria-label fallback chain (shared by both builds' render()). */
742
+ get _ariaLabel() {
743
+ return this.ariaLabelText || this.label || this.placeholder || void 0;
744
+ }
745
+ /** id referenced by aria-describedby when a message is shown. */
746
+ get _describedBy() {
747
+ return this.validationMessage || this.errorMessage || this.successMessage || this.helperText || this._hasHelperSlot ? this._messageId : void 0;
748
+ }
749
+ /**
750
+ * `type="file"`: a hidden native picker, and in front of it a read-only text input showing
751
+ * the picked name(s). The text input keeps `mono-native` + `.mono-input-native`, so focus,
752
+ * the label's `for`, sizing and the focus ring all behave exactly as on a text field.
753
+ */
754
+ _renderFileNative() {
755
+ return html`
756
+ <input
757
+ type="file"
758
+ mono-file-input
759
+ hidden
760
+ tabindex="-1"
761
+ accept=${ifDefined(this.accept || void 0)}
762
+ ?multiple=${this.multiple}
763
+ name=${ifDefined(this.name || void 0)}
764
+ ?disabled=${this.disabled}
765
+ @input=${this._swallowNativeInput}
766
+ @change=${this._handleFileChange}
767
+ />
768
+ <input
769
+ id=${this._inputId}
770
+ class=${`${this._cls("mono-input-native", "native")} ${this.size}`}
771
+ mono-native
772
+ mono-file
773
+ type="text"
774
+ readonly
775
+ .value=${this._display}
776
+ placeholder=${ifDefined(this.placeholder || void 0)}
777
+ ?disabled=${this.disabled}
778
+ ?required=${this.required}
779
+ aria-label=${ifDefined(this._ariaLabel)}
780
+ aria-invalid=${this._resolvedValidationState === "invalid" ? "true" : "false"}
781
+ aria-describedby=${ifDefined(this._describedBy)}
782
+ aria-haspopup="dialog"
783
+ @focus=${this._handleFocus}
784
+ @blur=${this._handleBlur}
785
+ @click=${this._openFilePicker}
786
+ @keydown=${this._handleFileKeydown}
787
+ />
788
+ `;
789
+ }
790
+ /** `type="file"` — the upload glyph at the end of the field; clicking it opens the picker too. */
791
+ _renderFileIcon() {
792
+ if (!this._isFile) return nothing;
793
+ return html`
794
+ <span
795
+ class=${this._cls("mono-input-suffix", "fileIcon")}
796
+ mono-suffix
797
+ mono-file-icon
798
+ aria-hidden="true"
799
+ @click=${this._openFilePicker}
800
+ >${this.renderIcon("upload")}</span>
801
+ `;
802
+ }
803
+ /**
804
+ * `type="range"`: Basecoat's slider. The fill is a gradient stop on the track, so the element
805
+ * writes the position as `--mono-input-range-value` (Basecoat's `--slider-value`) — hand-written
806
+ * markup sets the same property itself.
807
+ */
808
+ _renderRangeNative() {
809
+ const { min, max, step } = this._rangeBounds();
810
+ const text = this._rangeText;
811
+ return html`
812
+ <input
813
+ id=${this._inputId}
814
+ class=${`${this._cls("mono-input-native", "native")} ${this.size}`}
815
+ mono-native
816
+ mono-range
817
+ type="range"
818
+ min=${min}
819
+ max=${max}
820
+ step=${ifDefined(this.step == null ? void 0 : step)}
821
+ .value=${this._rangeValue}
822
+ name=${ifDefined(this.name || void 0)}
823
+ style=${`--mono-input-range-value: ${this._rangeProgress}%`}
824
+ ?disabled=${this.disabled}
825
+ ?required=${this.required}
826
+ aria-label=${ifDefined(this._ariaLabel)}
827
+ aria-valuetext=${ifDefined(text !== this._rangeValue ? text : void 0)}
828
+ aria-readonly=${ifDefined(this.readonly ? "true" : void 0)}
829
+ aria-invalid=${this._resolvedValidationState === "invalid" ? "true" : "false"}
830
+ aria-describedby=${ifDefined(this._describedBy)}
831
+ @focus=${this._handleFocus}
832
+ @blur=${this._handleBlur}
833
+ @input=${this._handleInput}
834
+ @change=${this._handleChange}
835
+ />
836
+ `;
837
+ }
838
+ /**
839
+ * `type="range"` — the value readout. It sits at the end of the LABEL row when there is a
840
+ * label (the EJI ONE layout), and after the slider when there is not; each build calls this
841
+ * from both places and exactly one of them renders. `aria-hidden`: the slider already
842
+ * announces its value (`aria-valuetext` carries the formatted text).
843
+ */
844
+ _renderRangeValue(where) {
845
+ if (!this._isRange || !this.showValue) return nothing;
846
+ const inLabel = !!(this.label || this._hasLabelSlot);
847
+ if (where === "label" !== inLabel) return nothing;
848
+ return html`<span class=${this._cls("mono-input-range-value", "rangeValue")} mono-range-value aria-hidden="true">${this._rangeText}</span>`;
849
+ }
850
+ /** The native <input>, shared by both builds' render(). */
851
+ _renderNative() {
852
+ if (this._isFile) return this._renderFileNative();
853
+ if (this._isRange) return this._renderRangeNative();
854
+ return html`
855
+ <input
856
+ id=${this._inputId}
857
+ class=${`${this._cls("mono-input-native", "native")} ${this.size}`}
858
+ mono-native
859
+ type=${this.type}
860
+ .value=${this._display}
861
+ name=${ifDefined(this.name || void 0)}
862
+ placeholder=${ifDefined(this.placeholder || void 0)}
863
+ pattern=${ifDefined(this.pattern || void 0)}
864
+ autocomplete=${ifDefined(this.autocomplete || void 0)}
865
+ inputmode=${ifDefined(this.inputmode || void 0)}
866
+ minlength=${ifDefined(this.minLength)}
867
+ maxlength=${ifDefined(this.maxLength)}
868
+ min=${ifDefined(this.min)}
869
+ max=${ifDefined(this.max)}
870
+ step=${ifDefined(this.step)}
871
+ ?disabled=${this.disabled}
872
+ ?readonly=${this.readonly}
873
+ ?required=${this.required}
874
+ aria-label=${ifDefined(this._ariaLabel)}
875
+ aria-invalid=${this._resolvedValidationState === "invalid" ? "true" : "false"}
876
+ aria-describedby=${ifDefined(this._describedBy)}
877
+ @focus=${this._handleFocus}
878
+ @blur=${this._handleBlur}
879
+ @input=${this._handleInput}
880
+ @change=${this._handleChange}
881
+ />
882
+ `;
883
+ }
884
+ /** The clear button (uses the build-specific icon). */
885
+ _renderClear() {
886
+ if (this._isRange || !(this.clearable && this.value && !this.disabled && !this.readonly)) return nothing;
887
+ return html`
888
+ <button
889
+ type="button"
890
+ class=${this._cls("mono-input-clear", "clear")}
891
+ mono-clear
892
+ aria-label="Clear input"
893
+ @click=${this._handleClear}
894
+ >
895
+ ${this.renderIcon("close")}
896
+ </button>
897
+ `;
898
+ }
899
+ /**
900
+ * Icon hook — overridden per build. Light: global `.mono-icon`/`i-mdi-*`
901
+ * UnoCSS icon. Shadow: inline SVG (global icon CSS can't reach a shadow root).
902
+ */
903
+ renderIcon(_name) {
904
+ return html``;
905
+ }
906
+ focus(options) {
907
+ this._inputEl?.focus(options);
908
+ }
909
+ blur() {
910
+ this._inputEl?.blur();
911
+ }
912
+ select() {
913
+ this._inputEl?.select();
914
+ }
915
+ }
916
+ __decorate([property({ attribute: false })], MonoInputCoreClass.prototype, "cssClass", void 0);
917
+ __decorate([property({
918
+ type: String,
919
+ attribute: "css-class"
920
+ })], MonoInputCoreClass.prototype, "cssClassName", void 0);
921
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "type", void 0);
922
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "size", void 0);
923
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "color", void 0);
924
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "variant", void 0);
925
+ __decorate([property({
926
+ type: String,
927
+ attribute: "label-position"
928
+ })], MonoInputCoreClass.prototype, "labelPosition", void 0);
929
+ __decorate([property({
930
+ type: String,
931
+ attribute: "validation-position"
932
+ })], MonoInputCoreClass.prototype, "validationPosition", void 0);
933
+ __decorate([property({
934
+ attribute: "model-value",
935
+ reflect: true,
936
+ converter: modelValueConverter
937
+ })], MonoInputCoreClass.prototype, "modelValue", void 0);
938
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "value", void 0);
939
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "accept", void 0);
940
+ __decorate([property({
941
+ reflect: true,
942
+ converter: booleanStringConverter
943
+ })], MonoInputCoreClass.prototype, "multiple", void 0);
944
+ __decorate([property({
945
+ attribute: "max-file-size",
946
+ converter: numberStringConverter
947
+ })], MonoInputCoreClass.prototype, "maxFileSize", void 0);
948
+ __decorate([property({
949
+ attribute: "show-value",
950
+ converter: { fromAttribute: (v) => v === null ? true : booleanStringConverter.fromAttribute(v) }
951
+ })], MonoInputCoreClass.prototype, "showValue", void 0);
952
+ __decorate([property({ attribute: false })], MonoInputCoreClass.prototype, "formatDisplay", void 0);
953
+ __decorate([property({ attribute: false })], MonoInputCoreClass.prototype, "formatValue", void 0);
954
+ __decorate([property({ attribute: "format-on" })], MonoInputCoreClass.prototype, "formatOn", void 0);
955
+ __decorate([property({ attribute: "format-locale" })], MonoInputCoreClass.prototype, "formatLocale", void 0);
956
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "name", void 0);
957
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "placeholder", void 0);
958
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "label", void 0);
959
+ __decorate([property({
960
+ type: String,
961
+ attribute: "helper-text"
962
+ })], MonoInputCoreClass.prototype, "helperText", void 0);
963
+ __decorate([property()], MonoInputCoreClass.prototype, "tooltip", void 0);
964
+ __decorate([property({
965
+ type: String,
966
+ attribute: "validation-state"
967
+ })], MonoInputCoreClass.prototype, "validationState", void 0);
968
+ __decorate([property({
969
+ type: String,
970
+ attribute: "validation-message"
971
+ })], MonoInputCoreClass.prototype, "validationMessage", void 0);
972
+ __decorate([property({
973
+ reflect: true,
974
+ converter: booleanStringConverter
975
+ })], MonoInputCoreClass.prototype, "error", void 0);
976
+ __decorate([property({
977
+ type: String,
978
+ attribute: "error-message"
979
+ })], MonoInputCoreClass.prototype, "errorMessage", void 0);
980
+ __decorate([property({
981
+ reflect: true,
982
+ converter: booleanStringConverter
983
+ })], MonoInputCoreClass.prototype, "success", void 0);
984
+ __decorate([property({
985
+ type: String,
986
+ attribute: "success-message"
987
+ })], MonoInputCoreClass.prototype, "successMessage", void 0);
988
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "pattern", void 0);
989
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "autocomplete", void 0);
990
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "inputmode", void 0);
991
+ __decorate([property({
992
+ type: String,
993
+ attribute: "aria-label"
994
+ })], MonoInputCoreClass.prototype, "ariaLabelText", void 0);
995
+ __decorate([property({
996
+ attribute: "min-length",
997
+ converter: numberStringConverter
998
+ })], MonoInputCoreClass.prototype, "minLength", void 0);
999
+ __decorate([property({
1000
+ attribute: "max-length",
1001
+ converter: numberStringConverter
1002
+ })], MonoInputCoreClass.prototype, "maxLength", void 0);
1003
+ __decorate([property({ type: Number })], MonoInputCoreClass.prototype, "min", void 0);
1004
+ __decorate([property({ type: Number })], MonoInputCoreClass.prototype, "max", void 0);
1005
+ __decorate([property({ type: Number })], MonoInputCoreClass.prototype, "step", void 0);
1006
+ __decorate([property({
1007
+ reflect: true,
1008
+ converter: booleanStringConverter
1009
+ })], MonoInputCoreClass.prototype, "disabled", void 0);
1010
+ __decorate([property({
1011
+ reflect: true,
1012
+ converter: booleanStringConverter
1013
+ })], MonoInputCoreClass.prototype, "readonly", void 0);
1014
+ __decorate([property({
1015
+ reflect: true,
1016
+ converter: booleanStringConverter
1017
+ })], MonoInputCoreClass.prototype, "required", void 0);
1018
+ __decorate([property({
1019
+ reflect: true,
1020
+ converter: booleanStringConverter
1021
+ })], MonoInputCoreClass.prototype, "clearable", void 0);
1022
+ __decorate([property({
1023
+ reflect: true,
1024
+ converter: booleanStringConverter
1025
+ })], MonoInputCoreClass.prototype, "autofocus", void 0);
1026
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "width", void 0);
1027
+ __decorate([property({ type: String })], MonoInputCoreClass.prototype, "height", void 0);
1028
+ __decorate([property({
1029
+ type: String,
1030
+ attribute: "min-width"
1031
+ })], MonoInputCoreClass.prototype, "minWidth", void 0);
1032
+ __decorate([property({
1033
+ type: String,
1034
+ attribute: "max-width"
1035
+ })], MonoInputCoreClass.prototype, "maxWidth", void 0);
1036
+ __decorate([property({
1037
+ type: String,
1038
+ attribute: "min-height"
1039
+ })], MonoInputCoreClass.prototype, "minHeight", void 0);
1040
+ __decorate([property({
1041
+ type: String,
1042
+ attribute: "max-height"
1043
+ })], MonoInputCoreClass.prototype, "maxHeight", void 0);
1044
+ __decorate([query(".mono-input-native")], MonoInputCoreClass.prototype, "_inputEl", void 0);
1045
+ __decorate([query("[mono-file-input]")], MonoInputCoreClass.prototype, "_fileEl", void 0);
1046
+ __decorate([state()], MonoInputCoreClass.prototype, "_display", void 0);
1047
+ __decorate([state()], MonoInputCoreClass.prototype, "_focused", void 0);
1048
+ __decorate([state()], MonoInputCoreClass.prototype, "_hasPrefixSlotState", void 0);
1049
+ __decorate([state()], MonoInputCoreClass.prototype, "_hasSuffixSlotState", void 0);
1050
+ __decorate([state()], MonoInputCoreClass.prototype, "_hasLabelSlotState", void 0);
1051
+ __decorate([state()], MonoInputCoreClass.prototype, "_hasHelperSlotState", void 0);
1052
+ return MonoInputCoreClass;
1053
+ };
1054
+
1055
+ //#endregion
1056
+ //#region src/components/input/input-utils.ts
1057
+ function validateInputProps(props) {
1058
+ const validTypes = [
1059
+ "text",
1060
+ "email",
1061
+ "password",
1062
+ "number",
1063
+ "tel",
1064
+ "url",
1065
+ "date",
1066
+ "time",
1067
+ "month",
1068
+ "week",
1069
+ "search"
1070
+ ];
1071
+ const validSizes = [
1072
+ "xs",
1073
+ "sm",
1074
+ "md",
1075
+ "lg",
1076
+ "xl",
1077
+ "xxl"
1078
+ ];
1079
+ const validColors = [
1080
+ "primary",
1081
+ "secondary",
1082
+ "success",
1083
+ "danger",
1084
+ "warning",
1085
+ "info",
1086
+ "teal",
1087
+ "purple",
1088
+ "neutral",
1089
+ "dark"
1090
+ ];
1091
+ const validVariants = [
1092
+ "outlined",
1093
+ "filled",
1094
+ "underlined"
1095
+ ];
1096
+ if (props.type && !validTypes.includes(props.type)) return false;
1097
+ if (props.size && !validSizes.includes(props.size)) return false;
1098
+ if (props.color && !validColors.includes(props.color)) return false;
1099
+ if (props.variant && !validVariants.includes(props.variant)) return false;
1100
+ return true;
1101
+ }
1102
+ function generateInputAttributes(type, disabled, readonly, required, pattern, min, max, step, placeholder) {
1103
+ return {
1104
+ type,
1105
+ disabled: disabled || void 0,
1106
+ readonly: readonly || void 0,
1107
+ required: required || void 0,
1108
+ pattern: pattern || void 0,
1109
+ min,
1110
+ max,
1111
+ step,
1112
+ placeholder: placeholder || void 0
1113
+ };
1114
+ }
1115
+ function generateInputAriaAttributes(disabled, readonly, required, hasError, label, errorMessage) {
1116
+ return {
1117
+ "aria-disabled": disabled ? "true" : void 0,
1118
+ "aria-readonly": readonly ? "true" : void 0,
1119
+ "aria-required": required ? "true" : void 0,
1120
+ "aria-invalid": hasError ? "true" : void 0,
1121
+ "aria-label": label || void 0,
1122
+ "aria-errormessage": hasError ? errorMessage || void 0 : void 0
1123
+ };
1124
+ }
1125
+ function getInputIcon(type) {
1126
+ const iconMap = {
1127
+ text: "M4 6h16M4 12h16M4 18h10",
1128
+ email: "M4 6h16v12H4z M4 7l8 6 8-6",
1129
+ password: "M12 17a2 2 0 1 0 0-4a2 2 0 0 0 0 4zm6-7V8a6 6 0 1 0-12 0v2",
1130
+ number: "M8 4v16M16 4v16M5 9h14M5 15h14",
1131
+ tel: "M6.6 10.8a15.5 15.5 0 0 0 6.6 6.6l2.2-2.2a1.5 1.5 0 0 1 1.5-.36a10 10 0 0 0 3.1.5a1 1 0 0 1 1 1V20a1 1 0 0 1-1 1A17 17 0 0 1 3 4a1 1 0 0 1 1-1h3.06a1 1 0 0 1 1 1a10 10 0 0 0 .5 3.1a1.5 1.5 0 0 1-.36 1.5z",
1132
+ url: "M10 14a5 5 0 0 1 0-7l1-1a5 5 0 0 1 7 7l-1 1M14 10a5 5 0 0 1 0 7l-1 1a5 5 0 0 1-7-7l1-1",
1133
+ date: "M7 3v3M17 3v3M4 8h16M5 5h14v16H5z",
1134
+ time: "M12 7v5l3 3M12 22a10 10 0 1 0 0-20a10 10 0 0 0 0 20z",
1135
+ month: "M7 3v3M17 3v3M5 5h14v14H5zM8 11h8",
1136
+ week: "M7 3v3M17 3v3M5 5h14v16H5zM9 11h6M9 15h4",
1137
+ search: "M21 21l-4.35-4.35M10.5 18a7.5 7.5 0 1 1 0-15a7.5 7.5 0 0 1 0 15z",
1138
+ file: "M12 16V8M8.5 11.5L12 8l3.5 3.5M7 18h10",
1139
+ range: "M4 12h16M9 9a3 3 0 1 0 0 6a3 3 0 0 0 0-6z"
1140
+ };
1141
+ return iconMap[type] ?? iconMap.text;
1142
+ }
1143
+
1144
+ //#endregion
1145
+ export { MonoInputCore as a, validateInputProps as i, generateInputAttributes as n, getInputIcon as r, generateInputAriaAttributes as t };