@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
@@ -1,629 +1,10 @@
1
1
  import { g as monoHostChildNodes } from "../mono-ui-kvLVIf1V.js";
2
2
  import { t as customElement } from "../mono-element-CKcT0rwv.js";
3
- import { a as defineHybridPropAliases, i as defineHybridPropAlias, n as arrayHasChanged, r as booleanStringConverter, t as __decorate } from "../decorate-DbYFpi8R.js";
4
- import { t as dispatchMonoEvent } from "../mono-event-BPku9HpS.js";
5
- import { t as isIconifyClass } from "../icon-ClxnYhBG.js";
3
+ import { t as __decorate } from "../decorate-DbYFpi8R.js";
6
4
  import { a as parkDetachedNodes, s as placeSlotNode } from "../light-slots-B5Ck0t_E.js";
7
- import { t as MonoFormControlCore } from "../form-control-core-CRZPZ1ru.js";
8
- import { LitElement, html, isServer, nothing } from "lit";
9
- import { property, query, state } from "lit/decorators.js";
10
- import { ifDefined } from "lit/directives/if-defined.js";
5
+ import { a as validateFileUploadProps, i as getFileIcon, n as createUploadItem, r as formatFileSize, t as MonoFileUploadCore } from "../file-upload-core-Cz_dBQMx.js";
6
+ import { LitElement } from "lit";
11
7
 
12
- //#region src/components/file-upload/file-upload-utils.ts
13
- function validateFileUploadProps(props) {
14
- const validVariants = ["default", "compact"];
15
- const validStates = [
16
- "default",
17
- "valid",
18
- "invalid",
19
- "warning"
20
- ];
21
- if (props.variant && !validVariants.includes(props.variant)) return false;
22
- if (props.validationState && !validStates.includes(props.validationState)) return false;
23
- return true;
24
- }
25
- function formatFileSize(size) {
26
- if (size < 1024) return `${size} B`;
27
- if (size < 1048576) return `${Math.round(size / 1024)} KB`;
28
- return `${(size / 1048576).toFixed(1)} MB`;
29
- }
30
- /**
31
- * Pick a default file-type icon. Returns an MDI iconify utility class
32
- * (`i-mdi-*`, resolved by UnoCSS preset-icons) — see
33
- * https://icon-sets.iconify.design/mdi/ . The render layer paints these as a
34
- * masked SVG via {@link isIconifyClass}. The full set is safelisted in
35
- * `uno.config.ts` so the CSS ships in `dist/ui/index.css`.
36
- */
37
- function getFileIcon(type, name) {
38
- const ext = name.split(".").pop()?.toLowerCase() ?? "";
39
- if (type.startsWith("image/")) return "i-mdi-file-image";
40
- if (type.includes("pdf") || ext === "pdf") return "i-mdi-file-pdf-box";
41
- if (type.includes("sheet") || [
42
- "xls",
43
- "xlsx",
44
- "csv"
45
- ].includes(ext)) return "i-mdi-file-excel";
46
- if (type.includes("word") || ["doc", "docx"].includes(ext)) return "i-mdi-file-word";
47
- if (type.includes("zip") || [
48
- "zip",
49
- "rar",
50
- "7z"
51
- ].includes(ext)) return "i-mdi-zip-box";
52
- if (type.includes("video/")) return "i-mdi-file-video";
53
- if (type.includes("audio/")) return "i-mdi-file-music";
54
- return "i-mdi-file";
55
- }
56
- function createUploadItem(file) {
57
- const isImage = file.type.startsWith("image/");
58
- return {
59
- id: `${file.name}-${file.size}-${file.lastModified}`,
60
- file,
61
- name: file.name,
62
- size: file.size,
63
- type: file.type,
64
- previewUrl: isImage ? URL.createObjectURL(file) : void 0
65
- };
66
- }
67
-
68
- //#endregion
69
- //#region src/components/file-upload/file-upload-core.ts
70
- const numberStringConverter = {
71
- fromAttribute(value) {
72
- if (value === null || value === "") return 0;
73
- const parsed = Number(value);
74
- return Number.isFinite(parsed) ? parsed : 0;
75
- },
76
- toAttribute(value) {
77
- if (value === void 0 || value === null) return null;
78
- return String(value);
79
- }
80
- };
81
- /**
82
- * `MonoFileUploadCore` — all render-mode-agnostic logic for `mono-file-upload`:
83
- * reactive props (incl. SSR boolean + modelValue-array coercion), hybrid aliases,
84
- * camelCase attribute fallbacks, the file pipeline (validate / add / drag-drop /
85
- * remove / clear), the `mno-change`/`mno-remove`/`mno-error` events, and the
86
- * dropzone/list/message `render()`. Icon rendering goes through overridable hooks
87
- * (`_renderDropzoneIcon`/`_renderDefaultGlyph`/`_renderRemoveIcon`/
88
- * `_renderThumbGlyph`) — the light build keeps `data-mono-slot` + `i-mdi-*` iconify
89
- * classes; the shadow build uses native `<slot>` + inline SVG (iconify can't paint
90
- * inside a shadow root).
91
- *
92
- * SSR-safe: no `document`/`window` access at module/ctor scope; the file pipeline
93
- * and `_inputEl` (`@query`) only run client-side from user interaction.
94
- */
95
- const MonoFileUploadCore = (superClass) => {
96
- class MonoFileUploadCoreClass extends MonoFormControlCore(superClass) {
97
- constructor(...args) {
98
- super(...args);
99
- this.label = "";
100
- this.helperText = "";
101
- this.icon = "";
102
- this.removeIcon = "";
103
- this.accept = "";
104
- this.multiple = false;
105
- this.disabled = false;
106
- this.required = false;
107
- this.dragdrop = true;
108
- this.maxFileSize = 0;
109
- this.maxFiles = 0;
110
- this.modelValue = [];
111
- this.cssClass = {};
112
- this.variant = "default";
113
- this.validationState = "default";
114
- this.validationMessage = "";
115
- this._dragOver = false;
116
- this._hasIconSlot = false;
117
- this._hasTitleSlot = false;
118
- this._hasSubtitleSlot = false;
119
- this._previewsRevoked = false;
120
- defineHybridPropAliases(this, [
121
- "helperText",
122
- "maxFileSize",
123
- "maxFiles",
124
- "modelValue",
125
- "validationState",
126
- "validationMessage",
127
- "cssClass",
128
- "removeIcon"
129
- ]);
130
- defineHybridPropAlias(this, "placeholder", "title");
131
- defineHybridPropAlias(this, "subtext", "subtitle");
132
- this.title = "Klik atau seret file ke sini";
133
- this.subtitle = "Pilih file untuk diunggah";
134
- }
135
- static get observedAttributes() {
136
- return [
137
- ...super.observedAttributes ?? [],
138
- "helpertext",
139
- "maxfilesize",
140
- "maxfiles",
141
- "modelvalue",
142
- "validationstate",
143
- "validationmessage",
144
- "removeicon",
145
- "remove-icon",
146
- "placeholder",
147
- "subtext"
148
- ];
149
- }
150
- attributeChangedCallback(name, oldValue, newValue) {
151
- super.attributeChangedCallback(name, oldValue, newValue);
152
- if (oldValue === newValue) return;
153
- if (name === "helpertext") {
154
- this.helperText = newValue ?? "";
155
- return;
156
- }
157
- if (name === "maxfilesize") {
158
- this.maxFileSize = this._toNumber(newValue);
159
- return;
160
- }
161
- if (name === "maxfiles") {
162
- this.maxFiles = this._toNumber(newValue);
163
- return;
164
- }
165
- if (name === "modelvalue") {
166
- this.modelValue = this._toFileUploadItems(newValue);
167
- return;
168
- }
169
- if (name === "validationstate") {
170
- this.validationState = newValue ?? "default";
171
- return;
172
- }
173
- if (name === "validationmessage") {
174
- this.validationMessage = newValue ?? "";
175
- return;
176
- }
177
- if (name === "removeicon" || name === "remove-icon") {
178
- this.removeIcon = newValue ?? "";
179
- return;
180
- }
181
- if (name === "placeholder") {
182
- this.title = newValue ?? "";
183
- return;
184
- }
185
- if (name === "subtext") this.subtitle = newValue ?? "";
186
- }
187
- willUpdate(changed) {
188
- for (const key of [
189
- "multiple",
190
- "disabled",
191
- "required",
192
- "dragdrop"
193
- ]) if (typeof this[key] === "string") {
194
- const normalized = this[key].toLowerCase().trim();
195
- this[key] = normalized === "" || normalized === "true";
196
- }
197
- if (typeof this.modelValue === "string") this.modelValue = this._toFileUploadItems(this.modelValue);
198
- super.willUpdate?.(changed);
199
- }
200
- connectedCallback() {
201
- super.connectedCallback?.();
202
- this._restorePreviews();
203
- }
204
- disconnectedCallback() {
205
- this._revokePreviews();
206
- this._previewsRevoked = true;
207
- super.disconnectedCallback();
208
- }
209
- /**
210
- * Re-create the object URLs that `disconnectedCallback` revoked.
211
- *
212
- * Revoking on unmount is right — a blob URL pins the whole file in memory — but
213
- * the files SURVIVE a reconnect (a `v-if` toggle, `<KeepAlive>`, Vue moving the
214
- * node), and nothing re-created their previews. `modelValue` kept the same
215
- * `previewUrl` STRING pointing at a dead URL, so every thumbnail was broken from
216
- * then on. It hid well: an `<img>` already decoded before the unmount keeps
217
- * painting, so the damage only surfaced once a later re-render built a fresh
218
- * `<img>` from the same src.
219
- *
220
- * Only the disconnect path restores. `clear()` and the single-select replace also
221
- * revoke, but those files are gone for good and must NOT come back.
222
- *
223
- * Mutates the items in place rather than rebuilding `modelValue`: the consumer
224
- * holds these same object references, so an in-place write keeps both sides on
225
- * one live URL and avoids emitting a change event for what was never a user edit.
226
- */
227
- _restorePreviews() {
228
- if (isServer || !this._previewsRevoked) return;
229
- this._previewsRevoked = false;
230
- let restored = false;
231
- for (const item of this.modelValue) {
232
- if (!item.file || !item.previewUrl) continue;
233
- item.previewUrl = URL.createObjectURL(item.file);
234
- restored = true;
235
- }
236
- if (restored) this.requestUpdate();
237
- }
238
- _toNumber(value) {
239
- if (typeof value === "number") return Number.isFinite(value) ? value : 0;
240
- if (typeof value === "string") {
241
- const parsed = Number(value);
242
- return Number.isFinite(parsed) ? parsed : 0;
243
- }
244
- return 0;
245
- }
246
- _toFileUploadItems(value) {
247
- if (Array.isArray(value)) return value;
248
- if (typeof value === "string") {
249
- if (!value.trim()) return [];
250
- try {
251
- const parsed = JSON.parse(value);
252
- return Array.isArray(parsed) ? parsed : [];
253
- } catch {
254
- return [];
255
- }
256
- }
257
- return [];
258
- }
259
- get _wrapperClasses() {
260
- return [
261
- "mono-file-upload",
262
- this.variant,
263
- this.disabled ? "disabled" : "",
264
- this._dragOver ? "dragover" : "",
265
- this.validationState !== "default" ? this.validationState : "",
266
- this.cssClass?.root ?? ""
267
- ].filter(Boolean).join(" ");
268
- }
269
- _cls(base, key) {
270
- const extra = this.cssClass?.[key];
271
- return extra ? `${base} ${extra}` : base;
272
- }
273
- _cloneValue(value) {
274
- return [...value];
275
- }
276
- _createModelDetail(args) {
277
- const currentValue = this._cloneValue(args.modelValue);
278
- return {
279
- modelValue: currentValue,
280
- currentValue,
281
- oldValue: this._cloneValue(args.oldValue),
282
- files: currentValue,
283
- addedFiles: args.addedFiles ? this._cloneValue(args.addedFiles) : [],
284
- removedFile: args.removedFile,
285
- action: args.action,
286
- sourceEvent: args.sourceEvent
287
- };
288
- }
289
- _emitChange(detail) {
290
- dispatchMonoEvent(this, "change", detail);
291
- }
292
- _emitRemove(detail) {
293
- dispatchMonoEvent(this, "remove", detail);
294
- }
295
- _emitError(detail) {
296
- dispatchMonoEvent(this, "error", detail);
297
- }
298
- _emitValueEvents(detail) {
299
- this._emitChange(detail);
300
- }
301
- _revokePreviews(files = this.modelValue) {
302
- files.forEach((item) => {
303
- if (item.previewUrl) URL.revokeObjectURL(item.previewUrl);
304
- });
305
- }
306
- _openPicker() {
307
- if (this.disabled) return;
308
- this._inputEl?.click();
309
- }
310
- _validateFiles(files, sourceEvent) {
311
- let nextFiles = files;
312
- if (this.maxFileSize > 0) {
313
- const oversized = nextFiles.find((file) => file.size > this.maxFileSize);
314
- if (oversized) {
315
- this._emitError({
316
- message: `File "${oversized.name}" exceeds the maximum size limit.`,
317
- reason: "max-file-size",
318
- file: oversized,
319
- maxFileSize: this.maxFileSize,
320
- sourceEvent
321
- });
322
- nextFiles = nextFiles.filter((file) => file.size <= this.maxFileSize);
323
- }
324
- }
325
- if (this.maxFiles > 0) {
326
- const existingCount = this.multiple ? this.modelValue.length : 0;
327
- const allowed = Math.max(this.maxFiles - existingCount, 0);
328
- if (nextFiles.length > allowed) {
329
- this._emitError({
330
- message: `Only ${this.maxFiles} file(s) are allowed.`,
331
- reason: "max-files",
332
- maxFiles: this.maxFiles,
333
- sourceEvent
334
- });
335
- nextFiles = nextFiles.slice(0, allowed);
336
- }
337
- }
338
- return nextFiles;
339
- }
340
- _addFiles(files, sourceEvent) {
341
- if (!files.length) return;
342
- const validFiles = this._validateFiles(files, sourceEvent);
343
- if (!validFiles.length) return;
344
- const oldValue = this._cloneValue(this.modelValue);
345
- const addedFiles = validFiles.map((file) => createUploadItem(file));
346
- let action = "add";
347
- if (this.multiple) this.modelValue = [...this.modelValue, ...addedFiles];
348
- else {
349
- const replacedFiles = this._cloneValue(this.modelValue);
350
- this._revokePreviews(replacedFiles);
351
- this.modelValue = addedFiles.slice(0, 1);
352
- action = oldValue.length ? "replace" : "add";
353
- }
354
- const detail = this._createModelDetail({
355
- modelValue: this.modelValue,
356
- oldValue,
357
- addedFiles,
358
- action,
359
- sourceEvent
360
- });
361
- this._emitValueEvents(detail);
362
- }
363
- _handleInputChange(event) {
364
- const input = event.currentTarget;
365
- const files = Array.from(input.files ?? []);
366
- this._addFiles(files, event);
367
- input.value = "";
368
- }
369
- _handleDragOver(event) {
370
- if (!this.dragdrop || this.disabled) return;
371
- event.preventDefault();
372
- this._dragOver = true;
373
- }
374
- _handleDragLeave() {
375
- this._dragOver = false;
376
- }
377
- _handleDrop(event) {
378
- if (!this.dragdrop || this.disabled) return;
379
- event.preventDefault();
380
- this._dragOver = false;
381
- const files = Array.from(event.dataTransfer?.files ?? []);
382
- this._addFiles(files, event);
383
- }
384
- _removeFile(id, sourceEvent) {
385
- const removedFile = this.modelValue.find((file) => file.id === id);
386
- if (!removedFile) return;
387
- const oldValue = this._cloneValue(this.modelValue);
388
- if (removedFile.previewUrl) URL.revokeObjectURL(removedFile.previewUrl);
389
- this.modelValue = this.modelValue.filter((file) => file.id !== id);
390
- const detail = this._createModelDetail({
391
- modelValue: this.modelValue,
392
- oldValue,
393
- removedFile,
394
- action: "remove",
395
- sourceEvent
396
- });
397
- this._emitRemove({
398
- ...detail,
399
- removedFile,
400
- action: "remove"
401
- });
402
- this._emitValueEvents(detail);
403
- }
404
- clear() {
405
- if (!this.modelValue.length) return;
406
- const oldValue = this._cloneValue(this.modelValue);
407
- this._revokePreviews();
408
- this.modelValue = [];
409
- const detail = this._createModelDetail({
410
- modelValue: this.modelValue,
411
- oldValue,
412
- action: "clear"
413
- });
414
- this._emitValueEvents(detail);
415
- }
416
- /** Shadow build returns true to render the icon via a native `<slot>`. */
417
- _useIconSlots() {
418
- return false;
419
- }
420
- /** Default dropzone glyph. Shadow build overrides with an inline SVG. */
421
- _renderDefaultGlyph() {
422
- return html`<span
423
- class="mono-file-upload-default-icon i-mdi-cloud-upload-outline"
424
- mono-glyph
425
- aria-hidden="true"
426
- ></span>`;
427
- }
428
- _renderDropzoneIcon() {
429
- const cls = this._cls("mono-file-upload-icon", "icon");
430
- if (this._hasIconSlot) return html`<div class=${cls} mono-icon aria-hidden="true"><span data-mono-slot="icon"></span></div>`;
431
- if (this.icon && isIconifyClass(this.icon)) return html`<div class=${cls} mono-icon aria-hidden="true"><span class=${`mono-file-upload-iconify ${this.icon}`} mono-glyph></span></div>`;
432
- if (this.icon) return html`<div class=${cls} mono-icon aria-hidden="true">${this.icon}</div>`;
433
- return html`<div class=${cls} mono-icon aria-hidden="true">${this._renderDefaultGlyph()}</div>`;
434
- }
435
- /** Classes of the secondary line — the new `subtitle` key and the old `subtext` one. */
436
- get _subtitleClasses() {
437
- return [
438
- "mono-file-upload-subtitle",
439
- "mono-file-upload-subtext",
440
- this.cssClass?.subtitle ?? "",
441
- this.cssClass?.subtext ?? ""
442
- ].filter(Boolean).join(" ");
443
- }
444
- /**
445
- * Dropzone headline. A `slot="title"` child beats the prop: the light build
446
- * renders an empty `[data-mono-slot]` region it re-parents the captured node
447
- * into; the shadow build overrides this with a native `<slot>` whose fallback
448
- * is the prop text. (A separate template per branch — Lit's trailing child
449
- * part would otherwise clear nodes appended after it.)
450
- */
451
- _renderTitle() {
452
- const cls = this._cls("mono-file-upload-title", "title");
453
- if (this._hasTitleSlot) return html`<div class=${cls} mono-title data-mono-slot="title"></div>`;
454
- return html`<div class=${cls} mono-title ?mono-empty=${!this.title}>${this.title}</div>`;
455
- }
456
- /** Dropzone secondary line — `mono-subtitle`, plus the old `mono-subtext` hook. */
457
- _renderSubtitle() {
458
- const cls = this._subtitleClasses;
459
- if (this._hasSubtitleSlot) return html`<div class=${cls} mono-subtitle mono-subtext data-mono-slot="subtitle"></div>`;
460
- return html`<div class=${cls} mono-subtitle mono-subtext ?mono-empty=${!this.subtitle}>${this.subtitle}</div>`;
461
- }
462
- _renderRemoveIcon() {
463
- if (this.removeIcon && isIconifyClass(this.removeIcon)) return html`<span class=${`mono-file-upload-iconify ${this.removeIcon}`} mono-glyph></span>`;
464
- if (this.removeIcon) return html`${this.removeIcon}`;
465
- return html`<span class="mono-file-upload-iconify mono-icon i-mdi-close" mono-glyph aria-hidden="true"></span>`;
466
- }
467
- /** File-type thumb glyph (non-image). Shadow build overrides with an inline SVG. */
468
- _renderThumbGlyph(item) {
469
- const icon = getFileIcon(item.type, item.name);
470
- return isIconifyClass(icon) ? html`<span class=${`mono-file-upload-iconify ${icon}`} mono-glyph aria-hidden="true"></span>` : html`${icon}`;
471
- }
472
- _renderMessage() {
473
- const extra = this.cssClass?.message ?? "";
474
- if (this.validationMessage) return html`
475
- <div
476
- class="mono-file-upload-message ${this.validationState} ${extra}"
477
- mono-message=${this.validationState}
478
- role=${this.validationState === "invalid" ? "alert" : nothing}
479
- >
480
- ${this.validationMessage}
481
- </div>
482
- `;
483
- if (this.helperText) return html`
484
- <div class="mono-file-upload-message helper ${extra}" mono-message="helper">${this.helperText}</div>
485
- `;
486
- return nothing;
487
- }
488
- _renderList() {
489
- if (!this.modelValue.length) return nothing;
490
- return html`
491
- <div class=${this._cls("mono-file-upload-list", "list")} mono-list>
492
- ${this.modelValue.map((item) => html`
493
- <div class=${this._cls("mono-file-upload-item", "item")} mono-item>
494
- <div class=${this._cls("mono-file-upload-thumb", "thumb")} mono-thumb>
495
- ${item.previewUrl ? html`<img src=${item.previewUrl} alt=${item.name} />` : this._renderThumbGlyph(item)}
496
- </div>
497
-
498
- <div class=${this._cls("mono-file-upload-file", "file")} mono-file>
499
- <div class=${this._cls("mono-file-upload-name", "name")} mono-name>${item.name}</div>
500
- <div class=${this._cls("mono-file-upload-meta", "meta")} mono-meta>${formatFileSize(item.size)}</div>
501
- </div>
502
-
503
- <button
504
- type="button"
505
- class=${this._cls("mono-file-upload-remove", "remove")}
506
- mono-remove
507
- aria-label=${ifDefined(`Remove ${item.name}`)}
508
- @click=${(event) => this._removeFile(item.id, event)}
509
- >
510
- ${this._renderRemoveIcon()}
511
- </button>
512
- </div>
513
- `)}
514
- </div>
515
- `;
516
- }
517
- render() {
518
- return html`
519
- <div
520
- class=${this._wrapperClasses}
521
- mono-file-upload
522
- mono-variant=${this.variant === "default" ? nothing : this.variant}
523
- mono-validation-state=${this.validationState === "default" ? nothing : this.validationState}
524
- ?mono-disabled=${this.disabled}
525
- ?mono-required=${this.required}
526
- ?mono-multiple=${this.multiple}
527
- ?mono-no-dragdrop=${!this.dragdrop}
528
- ?mono-dragover=${this._dragOver}
529
- title=""
530
- >
531
- ${this.label ? html`
532
- <label class=${this._cls("mono-file-upload-label", "label")} mono-label>
533
- ${this.label}
534
- ${this.required ? html`<span class=${this._cls("mono-file-upload-required", "required")} mono-required-mark>*</span>` : nothing}
535
- </label>
536
- ` : nothing}
537
-
538
- <div
539
- class=${this._cls("mono-file-upload-dropzone", "dropzone")}
540
- mono-dropzone
541
- @click=${this._openPicker}
542
- @dragover=${this._handleDragOver}
543
- @dragleave=${this._handleDragLeave}
544
- @drop=${this._handleDrop}
545
- >
546
- ${this._renderDropzoneIcon()}
547
- ${this._renderTitle()}
548
- ${this._renderSubtitle()}
549
-
550
- <input
551
- class=${this._cls("mono-file-upload-input", "input")}
552
- mono-native
553
- type="file"
554
- accept=${ifDefined(this.accept || void 0)}
555
- ?multiple=${this.multiple}
556
- ?disabled=${this.disabled}
557
- @change=${this._handleInputChange}
558
- />
559
- </div>
560
-
561
- ${this._renderList()}
562
- ${this._renderMessage()}
563
- </div>
564
- `;
565
- }
566
- }
567
- __decorate([property({ type: String })], MonoFileUploadCoreClass.prototype, "label", void 0);
568
- __decorate([property({
569
- type: String,
570
- attribute: "helper-text"
571
- })], MonoFileUploadCoreClass.prototype, "helperText", void 0);
572
- __decorate([property({ type: String })], MonoFileUploadCoreClass.prototype, "title", void 0);
573
- __decorate([property({ type: String })], MonoFileUploadCoreClass.prototype, "subtitle", void 0);
574
- __decorate([property({ type: String })], MonoFileUploadCoreClass.prototype, "icon", void 0);
575
- __decorate([property({
576
- type: String,
577
- attribute: "remove-icon"
578
- })], MonoFileUploadCoreClass.prototype, "removeIcon", void 0);
579
- __decorate([property({ type: String })], MonoFileUploadCoreClass.prototype, "accept", void 0);
580
- __decorate([property({
581
- reflect: true,
582
- converter: booleanStringConverter
583
- })], MonoFileUploadCoreClass.prototype, "multiple", void 0);
584
- __decorate([property({
585
- reflect: true,
586
- converter: booleanStringConverter
587
- })], MonoFileUploadCoreClass.prototype, "disabled", void 0);
588
- __decorate([property({
589
- reflect: true,
590
- converter: booleanStringConverter
591
- })], MonoFileUploadCoreClass.prototype, "required", void 0);
592
- __decorate([property({
593
- reflect: true,
594
- converter: booleanStringConverter
595
- })], MonoFileUploadCoreClass.prototype, "dragdrop", void 0);
596
- __decorate([property({
597
- attribute: "max-file-size",
598
- converter: numberStringConverter
599
- })], MonoFileUploadCoreClass.prototype, "maxFileSize", void 0);
600
- __decorate([property({
601
- attribute: "max-files",
602
- converter: numberStringConverter
603
- })], MonoFileUploadCoreClass.prototype, "maxFiles", void 0);
604
- __decorate([property({
605
- attribute: false,
606
- hasChanged: arrayHasChanged
607
- })], MonoFileUploadCoreClass.prototype, "modelValue", void 0);
608
- __decorate([property({ attribute: false })], MonoFileUploadCoreClass.prototype, "cssClass", void 0);
609
- __decorate([property({ type: String })], MonoFileUploadCoreClass.prototype, "variant", void 0);
610
- __decorate([property({
611
- type: String,
612
- attribute: "validation-state"
613
- })], MonoFileUploadCoreClass.prototype, "validationState", void 0);
614
- __decorate([property({
615
- type: String,
616
- attribute: "validation-message"
617
- })], MonoFileUploadCoreClass.prototype, "validationMessage", void 0);
618
- __decorate([state()], MonoFileUploadCoreClass.prototype, "_dragOver", void 0);
619
- __decorate([state()], MonoFileUploadCoreClass.prototype, "_hasIconSlot", void 0);
620
- __decorate([state()], MonoFileUploadCoreClass.prototype, "_hasTitleSlot", void 0);
621
- __decorate([state()], MonoFileUploadCoreClass.prototype, "_hasSubtitleSlot", void 0);
622
- __decorate([query(".mono-file-upload-input")], MonoFileUploadCoreClass.prototype, "_inputEl", void 0);
623
- return MonoFileUploadCoreClass;
624
- };
625
-
626
- //#endregion
627
8
  //#region src/components/file-upload/mono-file-upload.ts
628
9
  /** Named slots the light build captures: the dropzone icon and its two text lines. */
629
10
  const FILE_UPLOAD_LIGHT_SLOTS = [