haiku-react-ui 1.0.0 → 1.0.1

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.
package/dist/index.cjs CHANGED
@@ -3,9 +3,8 @@
3
3
  var classVarianceAuthority = require('class-variance-authority');
4
4
  var clsx = require('clsx');
5
5
  var tailwindMerge = require('tailwind-merge');
6
- var react = require('@iconify/react');
7
- var jsxRuntime = require('react/jsx-runtime');
8
6
  var React2 = require('react');
7
+ var jsxRuntime = require('react/jsx-runtime');
9
8
 
10
9
  function _interopNamespace(e) {
11
10
  if (e && e.__esModule) return e;
@@ -31,6 +30,1396 @@ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
31
30
  function cn(...inputs) {
32
31
  return tailwindMerge.twMerge(clsx.clsx(inputs));
33
32
  }
33
+ function getIconsTree(data, names) {
34
+ const icons = data.icons;
35
+ const aliases = data.aliases || /* @__PURE__ */ Object.create(null);
36
+ const resolved = /* @__PURE__ */ Object.create(null);
37
+ function resolve(name) {
38
+ if (icons[name]) return resolved[name] = [];
39
+ if (!(name in resolved)) {
40
+ resolved[name] = null;
41
+ const parent = aliases[name] && aliases[name].parent;
42
+ const value = parent && resolve(parent);
43
+ if (value) resolved[name] = [parent].concat(value);
44
+ }
45
+ return resolved[name];
46
+ }
47
+ Object.keys(icons).concat(Object.keys(aliases)).forEach(resolve);
48
+ return resolved;
49
+ }
50
+ var defaultIconDimensions = Object.freeze({
51
+ left: 0,
52
+ top: 0,
53
+ width: 16,
54
+ height: 16
55
+ });
56
+ var defaultIconTransformations = Object.freeze({
57
+ rotate: 0,
58
+ vFlip: false,
59
+ hFlip: false
60
+ });
61
+ var defaultIconProps = Object.freeze({
62
+ ...defaultIconDimensions,
63
+ ...defaultIconTransformations
64
+ });
65
+ var defaultExtendedIconProps = Object.freeze({
66
+ ...defaultIconProps,
67
+ body: "",
68
+ hidden: false
69
+ });
70
+ function mergeIconTransformations(obj1, obj2) {
71
+ const result = {};
72
+ if (!obj1.hFlip !== !obj2.hFlip) result.hFlip = true;
73
+ if (!obj1.vFlip !== !obj2.vFlip) result.vFlip = true;
74
+ const rotate = ((obj1.rotate || 0) + (obj2.rotate || 0)) % 4;
75
+ if (rotate) result.rotate = rotate;
76
+ return result;
77
+ }
78
+ function mergeIconData(parent, child) {
79
+ const result = mergeIconTransformations(parent, child);
80
+ for (const key in defaultExtendedIconProps) if (key in defaultIconTransformations) {
81
+ if (key in parent && !(key in result)) result[key] = defaultIconTransformations[key];
82
+ } else if (key in child) result[key] = child[key];
83
+ else if (key in parent) result[key] = parent[key];
84
+ return result;
85
+ }
86
+ function internalGetIconData(data, name, tree) {
87
+ const icons = data.icons;
88
+ const aliases = data.aliases || /* @__PURE__ */ Object.create(null);
89
+ let currentProps = {};
90
+ function parse(name$1) {
91
+ currentProps = mergeIconData(icons[name$1] || aliases[name$1], currentProps);
92
+ }
93
+ parse(name);
94
+ tree.forEach(parse);
95
+ return mergeIconData(data, currentProps);
96
+ }
97
+ function parseIconSet(data, callback) {
98
+ const names = [];
99
+ if (typeof data !== "object" || typeof data.icons !== "object") return names;
100
+ if (data.not_found instanceof Array) data.not_found.forEach((name) => {
101
+ callback(name, null);
102
+ names.push(name);
103
+ });
104
+ const tree = getIconsTree(data);
105
+ for (const name in tree) {
106
+ const item = tree[name];
107
+ if (item) {
108
+ callback(name, internalGetIconData(data, name, item));
109
+ names.push(name);
110
+ }
111
+ }
112
+ return names;
113
+ }
114
+ var optionalPropertyDefaults = {
115
+ provider: "",
116
+ aliases: {},
117
+ not_found: {},
118
+ ...defaultIconDimensions
119
+ };
120
+ function checkOptionalProps(item, defaults) {
121
+ for (const prop in defaults) if (prop in item && typeof item[prop] !== typeof defaults[prop]) return false;
122
+ return true;
123
+ }
124
+ function quicklyValidateIconSet(obj) {
125
+ if (typeof obj !== "object" || obj === null) return null;
126
+ const data = obj;
127
+ if (typeof data.prefix !== "string" || !obj.icons || typeof obj.icons !== "object") return null;
128
+ if (!checkOptionalProps(obj, optionalPropertyDefaults)) return null;
129
+ const icons = data.icons;
130
+ for (const name in icons) {
131
+ const icon = icons[name];
132
+ if (!name || typeof icon.body !== "string" || !checkOptionalProps(icon, defaultExtendedIconProps)) return null;
133
+ }
134
+ const aliases = data.aliases || /* @__PURE__ */ Object.create(null);
135
+ for (const name in aliases) {
136
+ const icon = aliases[name];
137
+ const parent = icon.parent;
138
+ if (!name || typeof parent !== "string" || !icons[parent] && !aliases[parent] || !checkOptionalProps(icon, defaultExtendedIconProps)) return null;
139
+ }
140
+ return data;
141
+ }
142
+ var dataStorage = /* @__PURE__ */ Object.create(null);
143
+ function newStorage(provider, prefix) {
144
+ return {
145
+ provider,
146
+ prefix,
147
+ icons: /* @__PURE__ */ Object.create(null),
148
+ missing: /* @__PURE__ */ new Set()
149
+ };
150
+ }
151
+ function getStorage(provider, prefix) {
152
+ const providerStorage = dataStorage[provider] || (dataStorage[provider] = /* @__PURE__ */ Object.create(null));
153
+ return providerStorage[prefix] || (providerStorage[prefix] = newStorage(provider, prefix));
154
+ }
155
+ function addIconSet(storage2, data) {
156
+ if (!quicklyValidateIconSet(data)) return [];
157
+ return parseIconSet(data, (name, icon) => {
158
+ if (icon) storage2.icons[name] = icon;
159
+ else storage2.missing.add(name);
160
+ });
161
+ }
162
+ function addIconToStorage(storage2, name, icon) {
163
+ try {
164
+ if (typeof icon.body === "string") {
165
+ storage2.icons[name] = { ...icon };
166
+ return true;
167
+ }
168
+ } catch (err) {
169
+ }
170
+ return false;
171
+ }
172
+ var matchIconName = /^[a-z0-9]+(-[a-z0-9]+)*$/;
173
+ var stringToIcon = (value, validate, allowSimpleName, provider = "") => {
174
+ const colonSeparated = value.split(":");
175
+ if (value.slice(0, 1) === "@") {
176
+ if (colonSeparated.length < 2 || colonSeparated.length > 3) return null;
177
+ provider = colonSeparated.shift().slice(1);
178
+ }
179
+ if (colonSeparated.length > 3 || !colonSeparated.length) return null;
180
+ if (colonSeparated.length > 1) {
181
+ const name$1 = colonSeparated.pop();
182
+ const prefix = colonSeparated.pop();
183
+ const result = {
184
+ provider: colonSeparated.length > 0 ? colonSeparated[0] : provider,
185
+ prefix,
186
+ name: name$1
187
+ };
188
+ return validate && !validateIconName(result) ? null : result;
189
+ }
190
+ const name = colonSeparated[0];
191
+ const dashSeparated = name.split("-");
192
+ if (dashSeparated.length > 1) {
193
+ const result = {
194
+ provider,
195
+ prefix: dashSeparated.shift(),
196
+ name: dashSeparated.join("-")
197
+ };
198
+ return validate && !validateIconName(result) ? null : result;
199
+ }
200
+ if (allowSimpleName && provider === "") {
201
+ const result = {
202
+ provider,
203
+ prefix: "",
204
+ name
205
+ };
206
+ return validate && !validateIconName(result, allowSimpleName) ? null : result;
207
+ }
208
+ return null;
209
+ };
210
+ var validateIconName = (icon, allowSimpleName) => {
211
+ if (!icon) return false;
212
+ return !!((allowSimpleName && icon.prefix === "" || !!icon.prefix) && !!icon.name);
213
+ };
214
+ var simpleNames = false;
215
+ function allowSimpleNames(allow) {
216
+ if (typeof allow === "boolean") simpleNames = allow;
217
+ return simpleNames;
218
+ }
219
+ function getIconData(name) {
220
+ const icon = typeof name === "string" ? stringToIcon(name, true, simpleNames) : name;
221
+ if (icon) {
222
+ const storage2 = getStorage(icon.provider, icon.prefix);
223
+ const iconName = icon.name;
224
+ return storage2.icons[iconName] || (storage2.missing.has(iconName) ? null : void 0);
225
+ }
226
+ }
227
+ function addIcon(name, data) {
228
+ const icon = stringToIcon(name, true, simpleNames);
229
+ if (!icon) return false;
230
+ const storage2 = getStorage(icon.provider, icon.prefix);
231
+ if (data) return addIconToStorage(storage2, icon.name, data);
232
+ else {
233
+ storage2.missing.add(icon.name);
234
+ return true;
235
+ }
236
+ }
237
+ function addCollection(data, provider) {
238
+ if (typeof data !== "object") return false;
239
+ if (typeof provider !== "string") provider = data.provider || "";
240
+ if (simpleNames && !provider && !data.prefix) {
241
+ let added = false;
242
+ if (quicklyValidateIconSet(data)) {
243
+ data.prefix = "";
244
+ parseIconSet(data, (name, icon) => {
245
+ if (addIcon(name, icon)) added = true;
246
+ });
247
+ }
248
+ return added;
249
+ }
250
+ const prefix = data.prefix;
251
+ if (!validateIconName({
252
+ prefix,
253
+ name: "a"
254
+ })) return false;
255
+ const storage2 = getStorage(provider, prefix);
256
+ return !!addIconSet(storage2, data);
257
+ }
258
+ var defaultIconSizeCustomisations = Object.freeze({
259
+ width: null,
260
+ height: null
261
+ });
262
+ var defaultIconCustomisations = Object.freeze({
263
+ ...defaultIconSizeCustomisations,
264
+ ...defaultIconTransformations
265
+ });
266
+ var unitsSplit = /(-?[0-9.]*[0-9]+[0-9.]*)/g;
267
+ var unitsTest = /^-?[0-9.]*[0-9]+[0-9.]*$/g;
268
+ function calculateSize(size, ratio, precision) {
269
+ if (ratio === 1) return size;
270
+ precision = precision || 100;
271
+ if (typeof size === "number") return Math.ceil(size * ratio * precision) / precision;
272
+ if (typeof size !== "string") return size;
273
+ const oldParts = size.split(unitsSplit);
274
+ if (oldParts === null || !oldParts.length) return size;
275
+ const newParts = [];
276
+ let code = oldParts.shift();
277
+ let isNumber2 = unitsTest.test(code);
278
+ while (true) {
279
+ if (isNumber2) {
280
+ const num = parseFloat(code);
281
+ if (isNaN(num)) newParts.push(code);
282
+ else newParts.push(Math.ceil(num * ratio * precision) / precision);
283
+ } else newParts.push(code);
284
+ code = oldParts.shift();
285
+ if (code === void 0) return newParts.join("");
286
+ isNumber2 = !isNumber2;
287
+ }
288
+ }
289
+ function splitSVGDefs(content, tag = "defs") {
290
+ let defs = "";
291
+ const index = content.indexOf("<" + tag);
292
+ while (index >= 0) {
293
+ const start = content.indexOf(">", index);
294
+ const end = content.indexOf("</" + tag);
295
+ if (start === -1 || end === -1) break;
296
+ const endEnd = content.indexOf(">", end);
297
+ if (endEnd === -1) break;
298
+ defs += content.slice(start + 1, end).trim();
299
+ content = content.slice(0, index).trim() + content.slice(endEnd + 1);
300
+ }
301
+ return {
302
+ defs,
303
+ content
304
+ };
305
+ }
306
+ function mergeDefsAndContent(defs, content) {
307
+ return defs ? "<defs>" + defs + "</defs>" + content : content;
308
+ }
309
+ function wrapSVGContent(body, start, end) {
310
+ const split = splitSVGDefs(body);
311
+ return mergeDefsAndContent(split.defs, start + split.content + end);
312
+ }
313
+ var isUnsetKeyword = (value) => value === "unset" || value === "undefined" || value === "none";
314
+ function iconToSVG(icon, customisations) {
315
+ const fullIcon = {
316
+ ...defaultIconProps,
317
+ ...icon
318
+ };
319
+ const fullCustomisations = {
320
+ ...defaultIconCustomisations,
321
+ ...customisations
322
+ };
323
+ const box = {
324
+ left: fullIcon.left,
325
+ top: fullIcon.top,
326
+ width: fullIcon.width,
327
+ height: fullIcon.height
328
+ };
329
+ let body = fullIcon.body;
330
+ [fullIcon, fullCustomisations].forEach((props) => {
331
+ const transformations = [];
332
+ const hFlip = props.hFlip;
333
+ const vFlip = props.vFlip;
334
+ let rotation = props.rotate;
335
+ if (hFlip) if (vFlip) rotation += 2;
336
+ else {
337
+ transformations.push("translate(" + (box.width + box.left).toString() + " " + (0 - box.top).toString() + ")");
338
+ transformations.push("scale(-1 1)");
339
+ box.top = box.left = 0;
340
+ }
341
+ else if (vFlip) {
342
+ transformations.push("translate(" + (0 - box.left).toString() + " " + (box.height + box.top).toString() + ")");
343
+ transformations.push("scale(1 -1)");
344
+ box.top = box.left = 0;
345
+ }
346
+ let tempValue;
347
+ if (rotation < 0) rotation -= Math.floor(rotation / 4) * 4;
348
+ rotation = rotation % 4;
349
+ switch (rotation) {
350
+ case 1:
351
+ tempValue = box.height / 2 + box.top;
352
+ transformations.unshift("rotate(90 " + tempValue.toString() + " " + tempValue.toString() + ")");
353
+ break;
354
+ case 2:
355
+ transformations.unshift("rotate(180 " + (box.width / 2 + box.left).toString() + " " + (box.height / 2 + box.top).toString() + ")");
356
+ break;
357
+ case 3:
358
+ tempValue = box.width / 2 + box.left;
359
+ transformations.unshift("rotate(-90 " + tempValue.toString() + " " + tempValue.toString() + ")");
360
+ break;
361
+ }
362
+ if (rotation % 2 === 1) {
363
+ if (box.left !== box.top) {
364
+ tempValue = box.left;
365
+ box.left = box.top;
366
+ box.top = tempValue;
367
+ }
368
+ if (box.width !== box.height) {
369
+ tempValue = box.width;
370
+ box.width = box.height;
371
+ box.height = tempValue;
372
+ }
373
+ }
374
+ if (transformations.length) body = wrapSVGContent(body, '<g transform="' + transformations.join(" ") + '">', "</g>");
375
+ });
376
+ const customisationsWidth = fullCustomisations.width;
377
+ const customisationsHeight = fullCustomisations.height;
378
+ const boxWidth = box.width;
379
+ const boxHeight = box.height;
380
+ let width;
381
+ let height;
382
+ if (customisationsWidth === null) {
383
+ height = customisationsHeight === null ? "1em" : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
384
+ width = calculateSize(height, boxWidth / boxHeight);
385
+ } else {
386
+ width = customisationsWidth === "auto" ? boxWidth : customisationsWidth;
387
+ height = customisationsHeight === null ? calculateSize(width, boxHeight / boxWidth) : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
388
+ }
389
+ const attributes = {};
390
+ const setAttr = (prop, value) => {
391
+ if (!isUnsetKeyword(value)) attributes[prop] = value.toString();
392
+ };
393
+ setAttr("width", width);
394
+ setAttr("height", height);
395
+ const viewBox = [
396
+ box.left,
397
+ box.top,
398
+ boxWidth,
399
+ boxHeight
400
+ ];
401
+ attributes.viewBox = viewBox.join(" ");
402
+ return {
403
+ attributes,
404
+ viewBox,
405
+ body
406
+ };
407
+ }
408
+ var regex = /\sid="(\S+)"/g;
409
+ var randomPrefix = "IconifyId" + Date.now().toString(16) + (Math.random() * 16777216 | 0).toString(16);
410
+ var counter = 0;
411
+ function replaceIDs(body, prefix = randomPrefix) {
412
+ const ids = [];
413
+ let match;
414
+ while (match = regex.exec(body)) ids.push(match[1]);
415
+ if (!ids.length) return body;
416
+ const suffix = "suffix" + (Math.random() * 16777216 | Date.now()).toString(16);
417
+ ids.forEach((id) => {
418
+ const newID = typeof prefix === "function" ? prefix(id) : prefix + (counter++).toString();
419
+ const escapedID = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
420
+ body = body.replace(new RegExp('([#;"])(' + escapedID + ')([")]|\\.[a-z])', "g"), "$1" + newID + suffix + "$3");
421
+ });
422
+ body = body.replace(new RegExp(suffix, "g"), "");
423
+ return body;
424
+ }
425
+ var storage = /* @__PURE__ */ Object.create(null);
426
+ function setAPIModule(provider, item) {
427
+ storage[provider] = item;
428
+ }
429
+ function getAPIModule(provider) {
430
+ return storage[provider] || storage[""];
431
+ }
432
+ function createAPIConfig(source) {
433
+ let resources;
434
+ if (typeof source.resources === "string") resources = [source.resources];
435
+ else {
436
+ resources = source.resources;
437
+ if (!(resources instanceof Array) || !resources.length) return null;
438
+ }
439
+ const result = {
440
+ resources,
441
+ path: source.path || "/",
442
+ maxURL: source.maxURL || 500,
443
+ rotate: source.rotate || 750,
444
+ timeout: source.timeout || 5e3,
445
+ random: source.random === true,
446
+ index: source.index || 0,
447
+ dataAfterTimeout: source.dataAfterTimeout !== false
448
+ };
449
+ return result;
450
+ }
451
+ var configStorage = /* @__PURE__ */ Object.create(null);
452
+ var fallBackAPISources = ["https://api.simplesvg.com", "https://api.unisvg.com"];
453
+ var fallBackAPI = [];
454
+ while (fallBackAPISources.length > 0) if (fallBackAPISources.length === 1) fallBackAPI.push(fallBackAPISources.shift());
455
+ else if (Math.random() > 0.5) fallBackAPI.push(fallBackAPISources.shift());
456
+ else fallBackAPI.push(fallBackAPISources.pop());
457
+ configStorage[""] = createAPIConfig({ resources: ["https://api.iconify.design"].concat(fallBackAPI) });
458
+ function addAPIProvider(provider, customConfig) {
459
+ const config = createAPIConfig(customConfig);
460
+ if (config === null) return false;
461
+ configStorage[provider] = config;
462
+ return true;
463
+ }
464
+ function getAPIConfig(provider) {
465
+ return configStorage[provider];
466
+ }
467
+ var detectFetch = () => {
468
+ let callback;
469
+ try {
470
+ callback = fetch;
471
+ if (typeof callback === "function") return callback;
472
+ } catch (err) {
473
+ }
474
+ };
475
+ var fetchModule = detectFetch();
476
+ function calculateMaxLength(provider, prefix) {
477
+ const config = getAPIConfig(provider);
478
+ if (!config) return 0;
479
+ let result;
480
+ if (!config.maxURL) result = 0;
481
+ else {
482
+ let maxHostLength = 0;
483
+ config.resources.forEach((item) => {
484
+ const host = item;
485
+ maxHostLength = Math.max(maxHostLength, host.length);
486
+ });
487
+ const url = prefix + ".json?icons=";
488
+ result = config.maxURL - maxHostLength - config.path.length - url.length;
489
+ }
490
+ return result;
491
+ }
492
+ function shouldAbort(status) {
493
+ return status === 404;
494
+ }
495
+ var prepare = (provider, prefix, icons) => {
496
+ const results = [];
497
+ const maxLength = calculateMaxLength(provider, prefix);
498
+ const type = "icons";
499
+ let item = {
500
+ type,
501
+ provider,
502
+ prefix,
503
+ icons: []
504
+ };
505
+ let length = 0;
506
+ icons.forEach((name, index) => {
507
+ length += name.length + 1;
508
+ if (length >= maxLength && index > 0) {
509
+ results.push(item);
510
+ item = {
511
+ type,
512
+ provider,
513
+ prefix,
514
+ icons: []
515
+ };
516
+ length = name.length;
517
+ }
518
+ item.icons.push(name);
519
+ });
520
+ results.push(item);
521
+ return results;
522
+ };
523
+ function getPath(provider) {
524
+ if (typeof provider === "string") {
525
+ const config = getAPIConfig(provider);
526
+ if (config) return config.path;
527
+ }
528
+ return "/";
529
+ }
530
+ var send = (host, params, callback) => {
531
+ if (!fetchModule) {
532
+ callback("abort", 424);
533
+ return;
534
+ }
535
+ let path = getPath(params.provider);
536
+ switch (params.type) {
537
+ case "icons": {
538
+ const prefix = params.prefix;
539
+ const icons = params.icons;
540
+ const iconsList = icons.join(",");
541
+ const urlParams = new URLSearchParams({ icons: iconsList });
542
+ path += prefix + ".json?" + urlParams.toString();
543
+ break;
544
+ }
545
+ case "custom": {
546
+ const uri = params.uri;
547
+ path += uri.slice(0, 1) === "/" ? uri.slice(1) : uri;
548
+ break;
549
+ }
550
+ default:
551
+ callback("abort", 400);
552
+ return;
553
+ }
554
+ let defaultError = 503;
555
+ fetchModule(host + path).then((response) => {
556
+ const status = response.status;
557
+ if (status !== 200) {
558
+ setTimeout(() => {
559
+ callback(shouldAbort(status) ? "abort" : "next", status);
560
+ });
561
+ return;
562
+ }
563
+ defaultError = 501;
564
+ return response.json();
565
+ }).then((data) => {
566
+ if (typeof data !== "object" || data === null) {
567
+ setTimeout(() => {
568
+ if (data === 404) callback("abort", data);
569
+ else callback("next", defaultError);
570
+ });
571
+ return;
572
+ }
573
+ setTimeout(() => {
574
+ callback("success", data);
575
+ });
576
+ }).catch(() => {
577
+ callback("next", defaultError);
578
+ });
579
+ };
580
+ var fetchAPIModule = {
581
+ prepare,
582
+ send
583
+ };
584
+ function removeCallback(storages, id) {
585
+ storages.forEach((storage2) => {
586
+ const items = storage2.loaderCallbacks;
587
+ if (items) storage2.loaderCallbacks = items.filter((row) => row.id !== id);
588
+ });
589
+ }
590
+ function updateCallbacks(storage2) {
591
+ if (!storage2.pendingCallbacksFlag) {
592
+ storage2.pendingCallbacksFlag = true;
593
+ setTimeout(() => {
594
+ storage2.pendingCallbacksFlag = false;
595
+ const items = storage2.loaderCallbacks ? storage2.loaderCallbacks.slice(0) : [];
596
+ if (!items.length) return;
597
+ let hasPending = false;
598
+ const provider = storage2.provider;
599
+ const prefix = storage2.prefix;
600
+ items.forEach((item) => {
601
+ const icons = item.icons;
602
+ const oldLength = icons.pending.length;
603
+ icons.pending = icons.pending.filter((icon) => {
604
+ if (icon.prefix !== prefix) return true;
605
+ const name = icon.name;
606
+ if (storage2.icons[name]) icons.loaded.push({
607
+ provider,
608
+ prefix,
609
+ name
610
+ });
611
+ else if (storage2.missing.has(name)) icons.missing.push({
612
+ provider,
613
+ prefix,
614
+ name
615
+ });
616
+ else {
617
+ hasPending = true;
618
+ return true;
619
+ }
620
+ return false;
621
+ });
622
+ if (icons.pending.length !== oldLength) {
623
+ if (!hasPending) removeCallback([storage2], item.id);
624
+ item.callback(icons.loaded.slice(0), icons.missing.slice(0), icons.pending.slice(0), item.abort);
625
+ }
626
+ });
627
+ });
628
+ }
629
+ }
630
+ var idCounter = 0;
631
+ function storeCallback(callback, icons, pendingSources) {
632
+ const id = idCounter++;
633
+ const abort = removeCallback.bind(null, pendingSources, id);
634
+ if (!icons.pending.length) return abort;
635
+ const item = {
636
+ id,
637
+ icons,
638
+ callback,
639
+ abort
640
+ };
641
+ pendingSources.forEach((storage2) => {
642
+ (storage2.loaderCallbacks || (storage2.loaderCallbacks = [])).push(item);
643
+ });
644
+ return abort;
645
+ }
646
+ function sortIcons(icons) {
647
+ const result = {
648
+ loaded: [],
649
+ missing: [],
650
+ pending: []
651
+ };
652
+ const storage2 = /* @__PURE__ */ Object.create(null);
653
+ icons.sort((a, b) => {
654
+ if (a.provider !== b.provider) return a.provider.localeCompare(b.provider);
655
+ if (a.prefix !== b.prefix) return a.prefix.localeCompare(b.prefix);
656
+ return a.name.localeCompare(b.name);
657
+ });
658
+ let lastIcon = {
659
+ provider: "",
660
+ prefix: "",
661
+ name: ""
662
+ };
663
+ icons.forEach((icon) => {
664
+ if (lastIcon.name === icon.name && lastIcon.prefix === icon.prefix && lastIcon.provider === icon.provider) return;
665
+ lastIcon = icon;
666
+ const provider = icon.provider;
667
+ const prefix = icon.prefix;
668
+ const name = icon.name;
669
+ const providerStorage = storage2[provider] || (storage2[provider] = /* @__PURE__ */ Object.create(null));
670
+ const localStorage = providerStorage[prefix] || (providerStorage[prefix] = getStorage(provider, prefix));
671
+ let list;
672
+ if (name in localStorage.icons) list = result.loaded;
673
+ else if (prefix === "" || localStorage.missing.has(name)) list = result.missing;
674
+ else list = result.pending;
675
+ const item = {
676
+ provider,
677
+ prefix,
678
+ name
679
+ };
680
+ list.push(item);
681
+ });
682
+ return result;
683
+ }
684
+ function listToIcons(list, validate = true, simpleNames2 = false) {
685
+ const result = [];
686
+ list.forEach((item) => {
687
+ const icon = typeof item === "string" ? stringToIcon(item, validate, simpleNames2) : item;
688
+ if (icon) result.push(icon);
689
+ });
690
+ return result;
691
+ }
692
+ var defaultConfig = {
693
+ resources: [],
694
+ index: 0,
695
+ timeout: 2e3,
696
+ rotate: 750,
697
+ random: false,
698
+ dataAfterTimeout: false
699
+ };
700
+ function sendQuery(config, payload, query, done) {
701
+ const resourcesCount = config.resources.length;
702
+ const startIndex = config.random ? Math.floor(Math.random() * resourcesCount) : config.index;
703
+ let resources;
704
+ if (config.random) {
705
+ let list = config.resources.slice(0);
706
+ resources = [];
707
+ while (list.length > 1) {
708
+ const nextIndex = Math.floor(Math.random() * list.length);
709
+ resources.push(list[nextIndex]);
710
+ list = list.slice(0, nextIndex).concat(list.slice(nextIndex + 1));
711
+ }
712
+ resources = resources.concat(list);
713
+ } else resources = config.resources.slice(startIndex).concat(config.resources.slice(0, startIndex));
714
+ const startTime = Date.now();
715
+ let status = "pending";
716
+ let queriesSent = 0;
717
+ let lastError;
718
+ let timer = null;
719
+ let queue = [];
720
+ let doneCallbacks = [];
721
+ if (typeof done === "function") doneCallbacks.push(done);
722
+ function resetTimer() {
723
+ if (timer) {
724
+ clearTimeout(timer);
725
+ timer = null;
726
+ }
727
+ }
728
+ function abort() {
729
+ if (status === "pending") status = "aborted";
730
+ resetTimer();
731
+ queue.forEach((item) => {
732
+ if (item.status === "pending") item.status = "aborted";
733
+ });
734
+ queue = [];
735
+ }
736
+ function subscribe(callback, overwrite) {
737
+ if (overwrite) doneCallbacks = [];
738
+ if (typeof callback === "function") doneCallbacks.push(callback);
739
+ }
740
+ function getQueryStatus() {
741
+ return {
742
+ startTime,
743
+ payload,
744
+ status,
745
+ queriesSent,
746
+ queriesPending: queue.length,
747
+ subscribe,
748
+ abort
749
+ };
750
+ }
751
+ function failQuery() {
752
+ status = "failed";
753
+ doneCallbacks.forEach((callback) => {
754
+ callback(void 0, lastError);
755
+ });
756
+ }
757
+ function clearQueue() {
758
+ queue.forEach((item) => {
759
+ if (item.status === "pending") item.status = "aborted";
760
+ });
761
+ queue = [];
762
+ }
763
+ function moduleResponse(item, response, data) {
764
+ const isError = response !== "success";
765
+ queue = queue.filter((queued) => queued !== item);
766
+ switch (status) {
767
+ case "pending":
768
+ break;
769
+ case "failed":
770
+ if (isError || !config.dataAfterTimeout) return;
771
+ break;
772
+ default:
773
+ return;
774
+ }
775
+ if (response === "abort") {
776
+ lastError = data;
777
+ failQuery();
778
+ return;
779
+ }
780
+ if (isError) {
781
+ lastError = data;
782
+ if (!queue.length) if (!resources.length) failQuery();
783
+ else execNext();
784
+ return;
785
+ }
786
+ resetTimer();
787
+ clearQueue();
788
+ if (!config.random) {
789
+ const index = config.resources.indexOf(item.resource);
790
+ if (index !== -1 && index !== config.index) config.index = index;
791
+ }
792
+ status = "completed";
793
+ doneCallbacks.forEach((callback) => {
794
+ callback(data);
795
+ });
796
+ }
797
+ function execNext() {
798
+ if (status !== "pending") return;
799
+ resetTimer();
800
+ const resource = resources.shift();
801
+ if (resource === void 0) {
802
+ if (queue.length) {
803
+ timer = setTimeout(() => {
804
+ resetTimer();
805
+ if (status === "pending") {
806
+ clearQueue();
807
+ failQuery();
808
+ }
809
+ }, config.timeout);
810
+ return;
811
+ }
812
+ failQuery();
813
+ return;
814
+ }
815
+ const item = {
816
+ status: "pending",
817
+ resource,
818
+ callback: (status$1, data) => {
819
+ moduleResponse(item, status$1, data);
820
+ }
821
+ };
822
+ queue.push(item);
823
+ queriesSent++;
824
+ timer = setTimeout(execNext, config.rotate);
825
+ query(resource, payload, item.callback);
826
+ }
827
+ setTimeout(execNext);
828
+ return getQueryStatus;
829
+ }
830
+ function initRedundancy(cfg) {
831
+ const config = {
832
+ ...defaultConfig,
833
+ ...cfg
834
+ };
835
+ let queries = [];
836
+ function cleanup() {
837
+ queries = queries.filter((item) => item().status === "pending");
838
+ }
839
+ function query(payload, queryCallback, doneCallback) {
840
+ const query$1 = sendQuery(config, payload, queryCallback, (data, error) => {
841
+ cleanup();
842
+ if (doneCallback) doneCallback(data, error);
843
+ });
844
+ queries.push(query$1);
845
+ return query$1;
846
+ }
847
+ function find(callback) {
848
+ return queries.find((value) => {
849
+ return callback(value);
850
+ }) || null;
851
+ }
852
+ const instance = {
853
+ query,
854
+ find,
855
+ setIndex: (index) => {
856
+ config.index = index;
857
+ },
858
+ getIndex: () => config.index,
859
+ cleanup
860
+ };
861
+ return instance;
862
+ }
863
+ function emptyCallback$1() {
864
+ }
865
+ var redundancyCache = /* @__PURE__ */ Object.create(null);
866
+ function getRedundancyCache(provider) {
867
+ if (!redundancyCache[provider]) {
868
+ const config = getAPIConfig(provider);
869
+ if (!config) return;
870
+ const redundancy = initRedundancy(config);
871
+ const cachedReundancy = {
872
+ config,
873
+ redundancy
874
+ };
875
+ redundancyCache[provider] = cachedReundancy;
876
+ }
877
+ return redundancyCache[provider];
878
+ }
879
+ function sendAPIQuery(target, query, callback) {
880
+ let redundancy;
881
+ let send2;
882
+ if (typeof target === "string") {
883
+ const api = getAPIModule(target);
884
+ if (!api) {
885
+ callback(void 0, 424);
886
+ return emptyCallback$1;
887
+ }
888
+ send2 = api.send;
889
+ const cached = getRedundancyCache(target);
890
+ if (cached) redundancy = cached.redundancy;
891
+ } else {
892
+ const config = createAPIConfig(target);
893
+ if (config) {
894
+ redundancy = initRedundancy(config);
895
+ const moduleKey = target.resources ? target.resources[0] : "";
896
+ const api = getAPIModule(moduleKey);
897
+ if (api) send2 = api.send;
898
+ }
899
+ }
900
+ if (!redundancy || !send2) {
901
+ callback(void 0, 424);
902
+ return emptyCallback$1;
903
+ }
904
+ return redundancy.query(query, send2, callback)().abort;
905
+ }
906
+ function emptyCallback() {
907
+ }
908
+ function loadedNewIcons(storage2) {
909
+ if (!storage2.iconsLoaderFlag) {
910
+ storage2.iconsLoaderFlag = true;
911
+ setTimeout(() => {
912
+ storage2.iconsLoaderFlag = false;
913
+ updateCallbacks(storage2);
914
+ });
915
+ }
916
+ }
917
+ function checkIconNamesForAPI(icons) {
918
+ const valid = [];
919
+ const invalid = [];
920
+ icons.forEach((name) => {
921
+ (name.match(matchIconName) ? valid : invalid).push(name);
922
+ });
923
+ return {
924
+ valid,
925
+ invalid
926
+ };
927
+ }
928
+ function parseLoaderResponse(storage2, icons, data) {
929
+ function checkMissing() {
930
+ const pending = storage2.pendingIcons;
931
+ icons.forEach((name) => {
932
+ if (pending) pending.delete(name);
933
+ if (!storage2.icons[name]) storage2.missing.add(name);
934
+ });
935
+ }
936
+ if (data && typeof data === "object") try {
937
+ const parsed = addIconSet(storage2, data);
938
+ if (!parsed.length) {
939
+ checkMissing();
940
+ return;
941
+ }
942
+ } catch (err) {
943
+ console.error(err);
944
+ }
945
+ checkMissing();
946
+ loadedNewIcons(storage2);
947
+ }
948
+ function parsePossiblyAsyncResponse(response, callback) {
949
+ if (response instanceof Promise) response.then((data) => {
950
+ callback(data);
951
+ }).catch(() => {
952
+ callback(null);
953
+ });
954
+ else callback(response);
955
+ }
956
+ function loadNewIcons(storage2, icons) {
957
+ if (!storage2.iconsToLoad) storage2.iconsToLoad = icons;
958
+ else storage2.iconsToLoad = storage2.iconsToLoad.concat(icons).sort();
959
+ if (!storage2.iconsQueueFlag) {
960
+ storage2.iconsQueueFlag = true;
961
+ setTimeout(() => {
962
+ storage2.iconsQueueFlag = false;
963
+ const { provider, prefix } = storage2;
964
+ const icons$1 = storage2.iconsToLoad;
965
+ delete storage2.iconsToLoad;
966
+ if (!icons$1 || !icons$1.length) return;
967
+ const customIconLoader = storage2.loadIcon;
968
+ if (storage2.loadIcons && (icons$1.length > 1 || !customIconLoader)) {
969
+ parsePossiblyAsyncResponse(storage2.loadIcons(icons$1, prefix, provider), (data) => {
970
+ parseLoaderResponse(storage2, icons$1, data);
971
+ });
972
+ return;
973
+ }
974
+ if (customIconLoader) {
975
+ icons$1.forEach((name) => {
976
+ const response = customIconLoader(name, prefix, provider);
977
+ parsePossiblyAsyncResponse(response, (data) => {
978
+ const iconSet = data ? {
979
+ prefix,
980
+ icons: { [name]: data }
981
+ } : null;
982
+ parseLoaderResponse(storage2, [name], iconSet);
983
+ });
984
+ });
985
+ return;
986
+ }
987
+ const { valid, invalid } = checkIconNamesForAPI(icons$1);
988
+ if (invalid.length) parseLoaderResponse(storage2, invalid, null);
989
+ if (!valid.length) return;
990
+ const api = prefix.match(matchIconName) ? getAPIModule(provider) : null;
991
+ if (!api) {
992
+ parseLoaderResponse(storage2, valid, null);
993
+ return;
994
+ }
995
+ const params = api.prepare(provider, prefix, valid);
996
+ params.forEach((item) => {
997
+ sendAPIQuery(provider, item, (data) => {
998
+ parseLoaderResponse(storage2, item.icons, data);
999
+ });
1000
+ });
1001
+ });
1002
+ }
1003
+ }
1004
+ var loadIcons = (icons, callback) => {
1005
+ const cleanedIcons = listToIcons(icons, true, allowSimpleNames());
1006
+ const sortedIcons = sortIcons(cleanedIcons);
1007
+ if (!sortedIcons.pending.length) {
1008
+ let callCallback = true;
1009
+ if (callback) setTimeout(() => {
1010
+ if (callCallback) callback(sortedIcons.loaded, sortedIcons.missing, sortedIcons.pending, emptyCallback);
1011
+ });
1012
+ return () => {
1013
+ callCallback = false;
1014
+ };
1015
+ }
1016
+ const newIcons = /* @__PURE__ */ Object.create(null);
1017
+ const sources = [];
1018
+ let lastProvider, lastPrefix;
1019
+ sortedIcons.pending.forEach((icon) => {
1020
+ const { provider, prefix } = icon;
1021
+ if (prefix === lastPrefix && provider === lastProvider) return;
1022
+ lastProvider = provider;
1023
+ lastPrefix = prefix;
1024
+ sources.push(getStorage(provider, prefix));
1025
+ const providerNewIcons = newIcons[provider] || (newIcons[provider] = /* @__PURE__ */ Object.create(null));
1026
+ if (!providerNewIcons[prefix]) providerNewIcons[prefix] = [];
1027
+ });
1028
+ sortedIcons.pending.forEach((icon) => {
1029
+ const { provider, prefix, name } = icon;
1030
+ const storage2 = getStorage(provider, prefix);
1031
+ const pendingQueue = storage2.pendingIcons || (storage2.pendingIcons = /* @__PURE__ */ new Set());
1032
+ if (!pendingQueue.has(name)) {
1033
+ pendingQueue.add(name);
1034
+ newIcons[provider][prefix].push(name);
1035
+ }
1036
+ });
1037
+ sources.forEach((storage2) => {
1038
+ const list = newIcons[storage2.provider][storage2.prefix];
1039
+ if (list.length) loadNewIcons(storage2, list);
1040
+ });
1041
+ return callback ? storeCallback(callback, sortedIcons, sources) : emptyCallback;
1042
+ };
1043
+ function mergeCustomisations(defaults, item) {
1044
+ const result = { ...defaults };
1045
+ for (const key in item) {
1046
+ const value = item[key];
1047
+ const valueType = typeof value;
1048
+ if (key in defaultIconSizeCustomisations) {
1049
+ if (value === null || value && (valueType === "string" || valueType === "number")) result[key] = value;
1050
+ } else if (valueType === typeof result[key]) result[key] = key === "rotate" ? value % 4 : value;
1051
+ }
1052
+ return result;
1053
+ }
1054
+ var separator = /[\s,]+/;
1055
+ function flipFromString(custom, flip) {
1056
+ flip.split(separator).forEach((str) => {
1057
+ const value = str.trim();
1058
+ switch (value) {
1059
+ case "horizontal":
1060
+ custom.hFlip = true;
1061
+ break;
1062
+ case "vertical":
1063
+ custom.vFlip = true;
1064
+ break;
1065
+ }
1066
+ });
1067
+ }
1068
+ function rotateFromString(value, defaultValue = 0) {
1069
+ const units = value.replace(/^-?[0-9.]*/, "");
1070
+ function cleanup(value$1) {
1071
+ while (value$1 < 0) value$1 += 4;
1072
+ return value$1 % 4;
1073
+ }
1074
+ if (units === "") {
1075
+ const num = parseInt(value);
1076
+ return isNaN(num) ? 0 : cleanup(num);
1077
+ } else if (units !== value) {
1078
+ let split = 0;
1079
+ switch (units) {
1080
+ case "%":
1081
+ split = 25;
1082
+ break;
1083
+ case "deg":
1084
+ split = 90;
1085
+ }
1086
+ if (split) {
1087
+ let num = parseFloat(value.slice(0, value.length - units.length));
1088
+ if (isNaN(num)) return 0;
1089
+ num = num / split;
1090
+ return num % 1 === 0 ? cleanup(num) : 0;
1091
+ }
1092
+ }
1093
+ return defaultValue;
1094
+ }
1095
+ function iconToHTML(body, attributes) {
1096
+ let renderAttribsHTML = body.indexOf("xlink:") === -1 ? "" : ' xmlns:xlink="http://www.w3.org/1999/xlink"';
1097
+ for (const attr in attributes) renderAttribsHTML += " " + attr + '="' + attributes[attr] + '"';
1098
+ return '<svg xmlns="http://www.w3.org/2000/svg"' + renderAttribsHTML + ">" + body + "</svg>";
1099
+ }
1100
+ function encodeSVGforURL(svg) {
1101
+ return svg.replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ");
1102
+ }
1103
+ function svgToData(svg) {
1104
+ return "data:image/svg+xml," + encodeSVGforURL(svg);
1105
+ }
1106
+ function svgToURL(svg) {
1107
+ return 'url("' + svgToData(svg) + '")';
1108
+ }
1109
+ var policy;
1110
+ function createPolicy() {
1111
+ try {
1112
+ policy = window.trustedTypes.createPolicy("iconify", { createHTML: (s) => s });
1113
+ } catch (err) {
1114
+ policy = null;
1115
+ }
1116
+ }
1117
+ function cleanUpInnerHTML(html) {
1118
+ if (policy === void 0) createPolicy();
1119
+ return policy ? policy.createHTML(html) : html;
1120
+ }
1121
+ var defaultExtendedIconCustomisations = {
1122
+ ...defaultIconCustomisations,
1123
+ inline: false
1124
+ };
1125
+ var svgDefaults = {
1126
+ "xmlns": "http://www.w3.org/2000/svg",
1127
+ "xmlnsXlink": "http://www.w3.org/1999/xlink",
1128
+ "aria-hidden": true,
1129
+ "role": "img"
1130
+ };
1131
+ var commonProps = {
1132
+ display: "inline-block"
1133
+ };
1134
+ var monotoneProps = {
1135
+ backgroundColor: "currentColor"
1136
+ };
1137
+ var coloredProps = {
1138
+ backgroundColor: "transparent"
1139
+ };
1140
+ var propsToAdd = {
1141
+ Image: "var(--svg)",
1142
+ Repeat: "no-repeat",
1143
+ Size: "100% 100%"
1144
+ };
1145
+ var propsToAddTo = {
1146
+ WebkitMask: monotoneProps,
1147
+ mask: monotoneProps,
1148
+ background: coloredProps
1149
+ };
1150
+ for (const prefix in propsToAddTo) {
1151
+ const list = propsToAddTo[prefix];
1152
+ for (const prop in propsToAdd) {
1153
+ list[prefix + prop] = propsToAdd[prop];
1154
+ }
1155
+ }
1156
+ var inlineDefaults = {
1157
+ ...defaultExtendedIconCustomisations,
1158
+ inline: true
1159
+ };
1160
+ function fixSize(value) {
1161
+ return value + (value.match(/^[-0-9.]+$/) ? "px" : "");
1162
+ }
1163
+ var render = (icon, props, name) => {
1164
+ const defaultProps = props.inline ? inlineDefaults : defaultExtendedIconCustomisations;
1165
+ const customisations = mergeCustomisations(defaultProps, props);
1166
+ const mode = props.mode || "svg";
1167
+ const style = {};
1168
+ const customStyle = props.style || {};
1169
+ const componentProps = {
1170
+ ...mode === "svg" ? svgDefaults : {}
1171
+ };
1172
+ if (name) {
1173
+ const iconName = stringToIcon(name, false, true);
1174
+ if (iconName) {
1175
+ const classNames = ["iconify"];
1176
+ const props2 = [
1177
+ "provider",
1178
+ "prefix"
1179
+ ];
1180
+ for (const prop of props2) {
1181
+ if (iconName[prop]) {
1182
+ classNames.push("iconify--" + iconName[prop]);
1183
+ }
1184
+ }
1185
+ componentProps.className = classNames.join(" ");
1186
+ }
1187
+ }
1188
+ for (let key in props) {
1189
+ const value = props[key];
1190
+ if (value === void 0) {
1191
+ continue;
1192
+ }
1193
+ switch (key) {
1194
+ // Properties to ignore
1195
+ case "icon":
1196
+ case "style":
1197
+ case "children":
1198
+ case "onLoad":
1199
+ case "mode":
1200
+ case "ssr":
1201
+ case "fallback":
1202
+ break;
1203
+ // Forward ref
1204
+ case "_ref":
1205
+ componentProps.ref = value;
1206
+ break;
1207
+ // Merge class names
1208
+ case "className":
1209
+ componentProps[key] = (componentProps[key] ? componentProps[key] + " " : "") + value;
1210
+ break;
1211
+ // Boolean attributes
1212
+ case "inline":
1213
+ case "hFlip":
1214
+ case "vFlip":
1215
+ customisations[key] = value === true || value === "true" || value === 1;
1216
+ break;
1217
+ // Flip as string: 'horizontal,vertical'
1218
+ case "flip":
1219
+ if (typeof value === "string") {
1220
+ flipFromString(customisations, value);
1221
+ }
1222
+ break;
1223
+ // Color: copy to style
1224
+ case "color":
1225
+ style.color = value;
1226
+ break;
1227
+ // Rotation as string
1228
+ case "rotate":
1229
+ if (typeof value === "string") {
1230
+ customisations[key] = rotateFromString(value);
1231
+ } else if (typeof value === "number") {
1232
+ customisations[key] = value;
1233
+ }
1234
+ break;
1235
+ // Remove aria-hidden
1236
+ case "ariaHidden":
1237
+ case "aria-hidden":
1238
+ if (value !== true && value !== "true") {
1239
+ delete componentProps["aria-hidden"];
1240
+ }
1241
+ break;
1242
+ // Copy missing property if it does not exist in customisations
1243
+ default:
1244
+ if (defaultProps[key] === void 0) {
1245
+ componentProps[key] = value;
1246
+ }
1247
+ }
1248
+ }
1249
+ const item = iconToSVG(icon, customisations);
1250
+ const renderAttribs = item.attributes;
1251
+ if (customisations.inline) {
1252
+ style.verticalAlign = "-0.125em";
1253
+ }
1254
+ if (mode === "svg") {
1255
+ componentProps.style = {
1256
+ ...style,
1257
+ ...customStyle
1258
+ };
1259
+ Object.assign(componentProps, renderAttribs);
1260
+ let localCounter = 0;
1261
+ let id = props.id;
1262
+ if (typeof id === "string") {
1263
+ id = id.replace(/-/g, "_");
1264
+ }
1265
+ componentProps.dangerouslySetInnerHTML = {
1266
+ __html: cleanUpInnerHTML(replaceIDs(item.body, id ? () => id + "ID" + localCounter++ : "iconifyReact"))
1267
+ };
1268
+ return React2.createElement("svg", componentProps);
1269
+ }
1270
+ const { body, width, height } = icon;
1271
+ const useMask = mode === "mask" || (mode === "bg" ? false : body.indexOf("currentColor") !== -1);
1272
+ const html = iconToHTML(body, {
1273
+ ...renderAttribs,
1274
+ width: width + "",
1275
+ height: height + ""
1276
+ });
1277
+ componentProps.style = {
1278
+ ...style,
1279
+ "--svg": svgToURL(html),
1280
+ "width": fixSize(renderAttribs.width),
1281
+ "height": fixSize(renderAttribs.height),
1282
+ ...commonProps,
1283
+ ...useMask ? monotoneProps : coloredProps,
1284
+ ...customStyle
1285
+ };
1286
+ return React2.createElement("span", componentProps);
1287
+ };
1288
+ allowSimpleNames(true);
1289
+ setAPIModule("", fetchAPIModule);
1290
+ if (typeof document !== "undefined" && typeof window !== "undefined") {
1291
+ const _window = window;
1292
+ if (_window.IconifyPreload !== void 0) {
1293
+ const preload = _window.IconifyPreload;
1294
+ const err = "Invalid IconifyPreload syntax.";
1295
+ if (typeof preload === "object" && preload !== null) {
1296
+ (preload instanceof Array ? preload : [preload]).forEach((item) => {
1297
+ try {
1298
+ if (
1299
+ // Check if item is an object and not null/array
1300
+ typeof item !== "object" || item === null || item instanceof Array || // Check for 'icons' and 'prefix'
1301
+ typeof item.icons !== "object" || typeof item.prefix !== "string" || // Add icon set
1302
+ !addCollection(item)
1303
+ ) {
1304
+ console.error(err);
1305
+ }
1306
+ } catch (e) {
1307
+ console.error(err);
1308
+ }
1309
+ });
1310
+ }
1311
+ }
1312
+ if (_window.IconifyProviders !== void 0) {
1313
+ const providers = _window.IconifyProviders;
1314
+ if (typeof providers === "object" && providers !== null) {
1315
+ for (let key in providers) {
1316
+ const err = "IconifyProviders[" + key + "] is invalid.";
1317
+ try {
1318
+ const value = providers[key];
1319
+ if (typeof value !== "object" || !value || value.resources === void 0) {
1320
+ continue;
1321
+ }
1322
+ if (!addAPIProvider(key, value)) {
1323
+ console.error(err);
1324
+ }
1325
+ } catch (e) {
1326
+ console.error(err);
1327
+ }
1328
+ }
1329
+ }
1330
+ }
1331
+ }
1332
+ function IconComponent(props) {
1333
+ const [mounted, setMounted] = React2.useState(!!props.ssr);
1334
+ const [abort, setAbort] = React2.useState({});
1335
+ function getInitialState(mounted2) {
1336
+ if (mounted2) {
1337
+ const name2 = props.icon;
1338
+ if (typeof name2 === "object") {
1339
+ return {
1340
+ name: "",
1341
+ data: name2
1342
+ };
1343
+ }
1344
+ const data2 = getIconData(name2);
1345
+ if (data2) {
1346
+ return {
1347
+ name: name2,
1348
+ data: data2
1349
+ };
1350
+ }
1351
+ }
1352
+ return {
1353
+ name: ""
1354
+ };
1355
+ }
1356
+ const [state, setState] = React2.useState(getInitialState(!!props.ssr));
1357
+ function cleanup() {
1358
+ const callback = abort.callback;
1359
+ if (callback) {
1360
+ callback();
1361
+ setAbort({});
1362
+ }
1363
+ }
1364
+ function changeState(newState) {
1365
+ if (JSON.stringify(state) !== JSON.stringify(newState)) {
1366
+ cleanup();
1367
+ setState(newState);
1368
+ return true;
1369
+ }
1370
+ }
1371
+ function updateState() {
1372
+ var _a;
1373
+ const name2 = props.icon;
1374
+ if (typeof name2 === "object") {
1375
+ changeState({
1376
+ name: "",
1377
+ data: name2
1378
+ });
1379
+ return;
1380
+ }
1381
+ const data2 = getIconData(name2);
1382
+ if (changeState({
1383
+ name: name2,
1384
+ data: data2
1385
+ })) {
1386
+ if (data2 === void 0) {
1387
+ const callback = loadIcons([name2], updateState);
1388
+ setAbort({
1389
+ callback
1390
+ });
1391
+ } else if (data2) {
1392
+ (_a = props.onLoad) === null || _a === void 0 ? void 0 : _a.call(props, name2);
1393
+ }
1394
+ }
1395
+ }
1396
+ React2.useEffect(() => {
1397
+ setMounted(true);
1398
+ return cleanup;
1399
+ }, []);
1400
+ React2.useEffect(() => {
1401
+ if (mounted) {
1402
+ updateState();
1403
+ }
1404
+ }, [props.icon, mounted]);
1405
+ const { name, data } = state;
1406
+ if (!data) {
1407
+ return props.children ? props.children : props.fallback ? props.fallback : React2.createElement("span", {});
1408
+ }
1409
+ return render({
1410
+ ...defaultIconProps,
1411
+ ...data
1412
+ }, props, name);
1413
+ }
1414
+ var Icon = React2.forwardRef((props, ref) => IconComponent({
1415
+ ...props,
1416
+ _ref: ref
1417
+ }));
1418
+ React2.forwardRef((props, ref) => IconComponent({
1419
+ inline: true,
1420
+ ...props,
1421
+ _ref: ref
1422
+ }));
34
1423
  var buttonVariants = classVarianceAuthority.cva(
35
1424
  "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-300 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-primary-700 dark:focus-visible:ring-offset-zinc-950",
36
1425
  {
@@ -301,7 +1690,7 @@ function Button({
301
1690
  "aria-hidden": "true",
302
1691
  className: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent"
303
1692
  }
304
- ) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon, width: "16", height: "16" }) : icon : null,
1693
+ ) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, width: "16", height: "16" }) : icon : null,
305
1694
  children
306
1695
  ]
307
1696
  }
@@ -327,7 +1716,7 @@ function Button({
327
1716
  "aria-hidden": "true",
328
1717
  className: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent"
329
1718
  }
330
- ) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon, width: "16", height: "16" }) : icon : null,
1719
+ ) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, width: "16", height: "16" }) : icon : null,
331
1720
  children
332
1721
  ]
333
1722
  }
@@ -373,7 +1762,7 @@ function Avatar({
373
1762
  url,
374
1763
  ...props
375
1764
  }) {
376
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(avatarVariants({ shape, size, variant }), className), ...props, children: icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon, className: "w-[80%] h-[80%]" }) : icon : url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: url, alt, className: "w-full h-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: alt ? alt.charAt(0).toUpperCase() : "?" }) });
1765
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(avatarVariants({ shape, size, variant }), className), ...props, children: icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: "w-[80%] h-[80%]" }) : icon : url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: url, alt, className: "w-full h-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: alt ? alt.charAt(0).toUpperCase() : "?" }) });
377
1766
  }
378
1767
  function PlayBoard({
379
1768
  icon,
@@ -854,6 +2243,138 @@ var uploadFile = ({
854
2243
  }
855
2244
  xhr.send(formData);
856
2245
  });
2246
+ var splitFileIntoChunks = (file, chunkSize) => {
2247
+ const chunks = [];
2248
+ let start = 0;
2249
+ let index = 0;
2250
+ while (start < file.size) {
2251
+ const end = Math.min(start + chunkSize, file.size);
2252
+ const blob = file.slice(start, end);
2253
+ chunks.push({
2254
+ blob,
2255
+ index,
2256
+ start,
2257
+ end
2258
+ });
2259
+ start = end;
2260
+ index++;
2261
+ }
2262
+ return chunks;
2263
+ };
2264
+ var uploadChunk = ({
2265
+ action,
2266
+ chunk,
2267
+ chunkIndex,
2268
+ totalChunks,
2269
+ fileName,
2270
+ fileSize,
2271
+ method = "post",
2272
+ headers,
2273
+ onProgress,
2274
+ signal
2275
+ }) => new Promise((resolve, reject) => {
2276
+ const xhr = new XMLHttpRequest();
2277
+ xhr.open(method.toUpperCase(), action, true);
2278
+ const handleAbort = () => {
2279
+ xhr.abort();
2280
+ };
2281
+ if (headers) {
2282
+ Object.entries(headers).forEach(([key, value]) => {
2283
+ xhr.setRequestHeader(key, value);
2284
+ });
2285
+ }
2286
+ xhr.upload.onprogress = (event) => {
2287
+ onProgress == null ? void 0 : onProgress(event);
2288
+ };
2289
+ xhr.onload = () => {
2290
+ signal == null ? void 0 : signal.removeEventListener("abort", handleAbort);
2291
+ if (xhr.status >= 200 && xhr.status < 300) {
2292
+ resolve(xhr.responseText);
2293
+ } else {
2294
+ reject(new Error(`Chunk upload failed: ${xhr.statusText}`));
2295
+ }
2296
+ };
2297
+ xhr.onerror = (event) => {
2298
+ signal == null ? void 0 : signal.removeEventListener("abort", handleAbort);
2299
+ reject(event);
2300
+ };
2301
+ xhr.onabort = () => {
2302
+ signal == null ? void 0 : signal.removeEventListener("abort", handleAbort);
2303
+ reject(new DOMException("Chunk upload aborted", "AbortError"));
2304
+ };
2305
+ if (signal == null ? void 0 : signal.aborted) {
2306
+ reject(new DOMException("Chunk upload aborted", "AbortError"));
2307
+ return;
2308
+ }
2309
+ signal == null ? void 0 : signal.addEventListener("abort", handleAbort);
2310
+ const formData = new FormData();
2311
+ formData.append("file", chunk);
2312
+ formData.append("chunkIndex", String(chunkIndex));
2313
+ formData.append("totalChunks", String(totalChunks));
2314
+ formData.append("fileName", fileName);
2315
+ formData.append("fileSize", String(fileSize));
2316
+ xhr.send(formData);
2317
+ });
2318
+ var checkUploadedChunks = (action, file, chunkSize, headers) => new Promise((resolve, _reject) => {
2319
+ const xhr = new XMLHttpRequest();
2320
+ const params = new URLSearchParams({
2321
+ fileName: file.name,
2322
+ fileSize: String(file.size),
2323
+ chunkSize: String(chunkSize)
2324
+ });
2325
+ xhr.open("GET", `${action}?${params}`, true);
2326
+ if (headers) {
2327
+ Object.entries(headers).forEach(([key, value]) => {
2328
+ xhr.setRequestHeader(key, value);
2329
+ });
2330
+ }
2331
+ xhr.onload = () => {
2332
+ if (xhr.status >= 200 && xhr.status < 300) {
2333
+ resolve(xhr.responseText);
2334
+ } else {
2335
+ resolve("[]");
2336
+ }
2337
+ };
2338
+ xhr.onerror = () => {
2339
+ resolve("[]");
2340
+ };
2341
+ xhr.ontimeout = () => {
2342
+ resolve("[]");
2343
+ };
2344
+ xhr.send();
2345
+ }).then((responseText) => {
2346
+ try {
2347
+ const data = JSON.parse(responseText);
2348
+ return data.uploadedChunks || [];
2349
+ } catch (e) {
2350
+ return [];
2351
+ }
2352
+ });
2353
+ var mergeChunks = (action, fileName, totalChunks, method = "post", headers) => new Promise((resolve, reject) => {
2354
+ const xhr = new XMLHttpRequest();
2355
+ xhr.open(method.toUpperCase(), action, true);
2356
+ if (headers) {
2357
+ Object.entries(headers).forEach(([key, value]) => {
2358
+ xhr.setRequestHeader(key, value);
2359
+ });
2360
+ }
2361
+ xhr.setRequestHeader("Content-Type", "application/json");
2362
+ xhr.onload = () => {
2363
+ if (xhr.status >= 200 && xhr.status < 300) {
2364
+ resolve(xhr.responseText);
2365
+ } else {
2366
+ reject(new Error(`Merge chunks failed: ${xhr.statusText}`));
2367
+ }
2368
+ };
2369
+ xhr.onerror = (event) => {
2370
+ reject(event);
2371
+ };
2372
+ const body = JSON.stringify({
2373
+ fileName,
2374
+ totalChunks
2375
+ });
2376
+ xhr.send(body);
2377
+ });
857
2378
  var uploadTriggerVariants = classVarianceAuthority.cva(
858
2379
  "flex cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-300 focus-visible:ring-offset-2 focus-visible:ring-offset-white",
859
2380
  {
@@ -958,7 +2479,7 @@ function ButtonUpload({
958
2479
  onReset();
959
2480
  },
960
2481
  children: /* @__PURE__ */ jsxRuntime.jsx(
961
- react.Icon,
2482
+ Icon,
962
2483
  {
963
2484
  icon: "bx:reset",
964
2485
  width: "18",
@@ -980,7 +2501,7 @@ function ButtonUpload({
980
2501
  onCancel();
981
2502
  },
982
2503
  children: /* @__PURE__ */ jsxRuntime.jsx(
983
- react.Icon,
2504
+ Icon,
984
2505
  {
985
2506
  icon: "fluent-emoji-flat:stop-sign",
986
2507
  width: "18",
@@ -990,7 +2511,7 @@ function ButtonUpload({
990
2511
  )
991
2512
  }
992
2513
  ) : null;
993
- const statusIcon = status === "success" ? /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "icon-park:success", width: "16", height: "16" }) : status === "error" ? /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "material-icon-theme:folder-error", width: "16", height: "16" }) : status === "uploading" ? /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "line-md:loading-loop", width: "16", height: "16" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "line-md:upload", width: "16", height: "16" });
2514
+ const statusIcon = status === "success" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: "icon-park:success", width: "16", height: "16" }) : status === "error" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: "material-icon-theme:folder-error", width: "16", height: "16" }) : status === "uploading" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: "line-md:loading-loop", width: "16", height: "16" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: "line-md:upload", width: "16", height: "16" });
994
2515
  return /* @__PURE__ */ jsxRuntime.jsxs(
995
2516
  UploadTrigger,
996
2517
  {
@@ -1105,7 +2626,97 @@ function ImageUpload({
1105
2626
  }
1106
2627
  );
1107
2628
  }
1108
- function FileItem({ file, onRemove, onCancel }) {
2629
+ function ChunkItem({ index, progress, isCompleted, isUploading, isPending }) {
2630
+ const getStatusColor = () => {
2631
+ if (isCompleted) return "bg-green-500";
2632
+ if (isUploading) return "bg-blue-500";
2633
+ return "bg-gray-300";
2634
+ };
2635
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxRuntime.jsx(
2636
+ "div",
2637
+ {
2638
+ className: `w-2 h-2 rounded-full ${getStatusColor()} transition-all duration-200`,
2639
+ title: `\u5206\u7247 ${index + 1}: ${isCompleted ? "\u5DF2\u5B8C\u6210" : isUploading ? `${progress}%` : "\u7B49\u5F85\u4E2D"}`,
2640
+ children: isUploading && /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "w-2 h-2 -rotate-90", viewBox: "0 0 8 8", children: [
2641
+ /* @__PURE__ */ jsxRuntime.jsx(
2642
+ "circle",
2643
+ {
2644
+ cx: "4",
2645
+ cy: "4",
2646
+ r: "3",
2647
+ fill: "none",
2648
+ stroke: "#e5e7eb",
2649
+ strokeWidth: "1"
2650
+ }
2651
+ ),
2652
+ /* @__PURE__ */ jsxRuntime.jsx(
2653
+ "circle",
2654
+ {
2655
+ cx: "4",
2656
+ cy: "4",
2657
+ r: "3",
2658
+ fill: "none",
2659
+ stroke: "#3b82f6",
2660
+ strokeWidth: "1",
2661
+ strokeDasharray: `${progress * 0.188} 18.8`,
2662
+ strokeLinecap: "round"
2663
+ }
2664
+ )
2665
+ ] })
2666
+ }
2667
+ ) });
2668
+ }
2669
+ function ChunkList({ chunkProgress, totalChunks }) {
2670
+ if (!chunkProgress || totalChunks <= 1) {
2671
+ return null;
2672
+ }
2673
+ const { uploadedChunks, chunkIndex, chunkProgress: currentProgress } = chunkProgress;
2674
+ const chunks = Array.from({ length: totalChunks }, (_, i) => {
2675
+ if (i < uploadedChunks) {
2676
+ return { index: i, status: "completed" };
2677
+ } else if (i === chunkIndex) {
2678
+ return { index: i, status: "uploading", progress: currentProgress };
2679
+ } else {
2680
+ return { index: i, status: "pending" };
2681
+ }
2682
+ });
2683
+ if (totalChunks > 20) {
2684
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-gray-400", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
2685
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2686
+ uploadedChunks,
2687
+ "/",
2688
+ totalChunks,
2689
+ " \u5206\u7247\u5DF2\u4E0A\u4F20"
2690
+ ] }),
2691
+ chunkIndex !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-blue-500", children: [
2692
+ "\u5F53\u524D: \u5206\u7247 ",
2693
+ chunkIndex + 1,
2694
+ " (",
2695
+ currentProgress,
2696
+ "%)"
2697
+ ] })
2698
+ ] }) });
2699
+ }
2700
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex items-center gap-0.5 flex-wrap", children: [
2701
+ chunks.map((chunk) => /* @__PURE__ */ jsxRuntime.jsx(
2702
+ ChunkItem,
2703
+ {
2704
+ index: chunk.index,
2705
+ progress: chunk.progress || 0,
2706
+ isCompleted: chunk.status === "completed",
2707
+ isUploading: chunk.status === "uploading",
2708
+ isPending: chunk.status === "pending"
2709
+ },
2710
+ chunk.index
2711
+ )),
2712
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-400 ml-1", children: [
2713
+ uploadedChunks,
2714
+ "/",
2715
+ totalChunks
2716
+ ] })
2717
+ ] });
2718
+ }
2719
+ function FileItem({ file, onRemove, onCancel, chunkProgress }) {
1109
2720
  const { id, file: fileData, status, progress, error } = file;
1110
2721
  const iconMap = {
1111
2722
  idle: { icon: "lucide:file", className: "text-gray-400" },
@@ -1120,24 +2731,33 @@ function FileItem({ file, onRemove, onCancel }) {
1120
2731
  return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
1121
2732
  };
1122
2733
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 p-3 border rounded-md bg-white dark:bg-zinc-800", children: [
1123
- /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: iconConfig.icon, className: iconConfig.className, width: 20 }),
2734
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: iconConfig.icon, className: iconConfig.className, width: 20 }),
1124
2735
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
1125
2736
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1126
2737
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium text-md", children: fileData.name }),
1127
2738
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500 ml-2", children: formatSize(fileData.size) })
1128
2739
  ] }),
1129
2740
  (status === "uploading" || status === "success") && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1", children: [
1130
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 w-full bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
1131
- "div",
2741
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2742
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-1.5 bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
2743
+ "div",
2744
+ {
2745
+ className: "h-full bg-blue-500 transition-all duration-300",
2746
+ style: { width: `${progress}%` }
2747
+ }
2748
+ ) }),
2749
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-500 whitespace-nowrap", children: [
2750
+ progress,
2751
+ "%"
2752
+ ] })
2753
+ ] }),
2754
+ chunkProgress && chunkProgress.totalChunks > 1 && /* @__PURE__ */ jsxRuntime.jsx(
2755
+ ChunkList,
1132
2756
  {
1133
- className: "h-full bg-blue-500 transition-all duration-300",
1134
- style: { width: `${progress}%` }
2757
+ chunkProgress,
2758
+ totalChunks: chunkProgress.totalChunks
1135
2759
  }
1136
- ) }),
1137
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-500", children: [
1138
- progress,
1139
- "%"
1140
- ] })
2760
+ )
1141
2761
  ] }),
1142
2762
  status === "error" && error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-xs text-red-500", children: error.message })
1143
2763
  ] }),
@@ -1149,7 +2769,7 @@ function FileItem({ file, onRemove, onCancel }) {
1149
2769
  onClick: () => onCancel(id),
1150
2770
  className: "p-1 hover:bg-gray-100 rounded",
1151
2771
  title: "\u53D6\u6D88",
1152
- children: /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "lucide:x", className: "w-4 h-4 text-gray-500" })
2772
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: "lucide:x", className: "w-4 h-4 text-gray-500" })
1153
2773
  }
1154
2774
  ),
1155
2775
  status !== "uploading" && onRemove && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1159,13 +2779,13 @@ function FileItem({ file, onRemove, onCancel }) {
1159
2779
  onClick: () => onRemove(id),
1160
2780
  className: "p-1 hover:bg-gray-100 rounded",
1161
2781
  title: "\u5220\u9664",
1162
- children: /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "lucide:trash-2", className: "w-4 h-4 text-gray-500" })
2782
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: "lucide:trash-2", className: "w-4 h-4 text-gray-500" })
1163
2783
  }
1164
2784
  )
1165
2785
  ] })
1166
2786
  ] });
1167
2787
  }
1168
- function FileList({ files, onRemove, onCancel, show = true }) {
2788
+ function FileList({ files, onRemove, onCancel, show = true, chunkProgressMap }) {
1169
2789
  if (!show || files.length === 0) {
1170
2790
  return null;
1171
2791
  }
@@ -1174,7 +2794,8 @@ function FileList({ files, onRemove, onCancel, show = true }) {
1174
2794
  {
1175
2795
  file,
1176
2796
  onRemove,
1177
- onCancel
2797
+ onCancel,
2798
+ chunkProgress: chunkProgressMap == null ? void 0 : chunkProgressMap[file.id]
1178
2799
  },
1179
2800
  file.id
1180
2801
  )) });
@@ -1189,6 +2810,26 @@ var DEFAULT_OPTIONS = {
1189
2810
  method: "post",
1190
2811
  name: "file"
1191
2812
  };
2813
+ var DEFAULT_CHUNKED_CONFIG = {
2814
+ chunked: false,
2815
+ chunkSize: 2 * 1024 * 1024,
2816
+ // 2MB
2817
+ chunkConcurrency: 0,
2818
+ // 0 表示根据文件大小自动计算
2819
+ resumable: false,
2820
+ chunkedUrl: "",
2821
+ mergeUrl: "",
2822
+ chunkThreshold: 5 * 1024 * 1024
2823
+ // 5MB
2824
+ };
2825
+ var calculateConcurrency = (fileSize) => {
2826
+ const mb = fileSize / 1024 / 1024;
2827
+ if (mb < 10) return 2;
2828
+ if (mb < 50) return 3;
2829
+ if (mb < 100) return 4;
2830
+ if (mb < 500) return 5;
2831
+ return 6;
2832
+ };
1192
2833
  var createUploadError = (type, message, file, originalError) => ({
1193
2834
  type,
1194
2835
  message,
@@ -1201,6 +2842,10 @@ function Upload(config) {
1201
2842
  ...DEFAULT_OPTIONS,
1202
2843
  ...config
1203
2844
  };
2845
+ const chunkedConfig = {
2846
+ ...DEFAULT_CHUNKED_CONFIG,
2847
+ ...config.chunkedConfig
2848
+ };
1204
2849
  const {
1205
2850
  mode,
1206
2851
  autoUpload,
@@ -1224,11 +2869,21 @@ function Upload(config) {
1224
2869
  onError,
1225
2870
  onComplete
1226
2871
  } = options;
2872
+ const {
2873
+ chunked,
2874
+ chunkSize,
2875
+ chunkConcurrency,
2876
+ resumable,
2877
+ chunkedUrl,
2878
+ mergeUrl,
2879
+ chunkThreshold
2880
+ } = chunkedConfig;
1227
2881
  const [files, setFiles] = React2.useState([]);
1228
2882
  const [isDragging, setIsDragging] = React2.useState(false);
1229
2883
  const [previewUrl, setPreviewUrl] = React2.useState(null);
1230
2884
  const [status, setStatus] = React2.useState("idle");
1231
2885
  const [progress, setProgress] = React2.useState(0);
2886
+ const [chunkProgress, setChunkProgress] = React2.useState({});
1232
2887
  const inputId = React2.useId();
1233
2888
  const abortRef = React2.useRef(null);
1234
2889
  const cancelRef = React2.useRef(false);
@@ -1278,6 +2933,24 @@ function Upload(config) {
1278
2933
  const { file } = fileItem;
1279
2934
  const controller = new AbortController();
1280
2935
  abortRef.current = controller;
2936
+ const useChunkedUpload = chunked && file.size > chunkThreshold;
2937
+ if (!useChunkedUpload) {
2938
+ return uploadWithNormalMode(
2939
+ fileItem,
2940
+ totalBytes,
2941
+ uploadedBytes,
2942
+ controller
2943
+ );
2944
+ }
2945
+ return uploadWithChunkedMode(
2946
+ fileItem,
2947
+ totalBytes,
2948
+ uploadedBytes,
2949
+ controller
2950
+ );
2951
+ };
2952
+ const uploadWithNormalMode = async (fileItem, totalBytes, uploadedBytes, controller) => {
2953
+ const { file } = fileItem;
1281
2954
  try {
1282
2955
  const formData = new FormData();
1283
2956
  formData.append(name, file);
@@ -1335,6 +3008,156 @@ function Upload(config) {
1335
3008
  return { ...fileItem, status: "error", error };
1336
3009
  }
1337
3010
  };
3011
+ const uploadWithChunkedMode = async (fileItem, totalBytes, uploadedBytes, controller) => {
3012
+ const { file } = fileItem;
3013
+ const fileId = fileItem.id;
3014
+ try {
3015
+ let uploadedChunkIndices = [];
3016
+ if (resumable && chunkedUrl) {
3017
+ uploadedChunkIndices = await checkUploadedChunks(
3018
+ chunkedUrl,
3019
+ file,
3020
+ chunkSize,
3021
+ headers
3022
+ );
3023
+ }
3024
+ const chunks = splitFileIntoChunks(file, chunkSize);
3025
+ const totalChunks = chunks.length;
3026
+ const actualConcurrency = chunkConcurrency > 0 ? Math.min(chunkConcurrency, totalChunks) : Math.min(calculateConcurrency(file.size), totalChunks);
3027
+ const chunksToUpload = chunks.filter(
3028
+ (chunk) => !uploadedChunkIndices.includes(chunk.index)
3029
+ );
3030
+ const completedChunksRef = { current: uploadedChunkIndices.length };
3031
+ const chunkProgressMapRef = { current: /* @__PURE__ */ new Map() };
3032
+ const uploadTasks = chunksToUpload.map((chunk) => async () => {
3033
+ if (cancelRef.current || controller.signal.aborted) {
3034
+ throw new DOMException("Upload aborted", "AbortError");
3035
+ }
3036
+ chunkProgressMapRef.current.set(chunk.index, 0);
3037
+ await uploadChunk({
3038
+ action,
3039
+ chunk: chunk.blob,
3040
+ chunkIndex: chunk.index,
3041
+ totalChunks,
3042
+ fileName: file.name,
3043
+ fileSize: file.size,
3044
+ method,
3045
+ headers,
3046
+ signal: controller.signal,
3047
+ onProgress: (event) => {
3048
+ if (!event.lengthComputable) {
3049
+ return;
3050
+ }
3051
+ const chunkLoaded = event.loaded;
3052
+ const chunkTotal = chunk.end - chunk.start;
3053
+ const chunkProgressPercent = Math.min(
3054
+ 100,
3055
+ Math.round(chunkLoaded / chunkTotal * 100)
3056
+ );
3057
+ chunkProgressMapRef.current.set(chunk.index, chunkProgressPercent);
3058
+ const completedCount = completedChunksRef.current;
3059
+ let inProgressProgress = 0;
3060
+ chunkProgressMapRef.current.forEach((progress2) => {
3061
+ inProgressProgress += progress2;
3062
+ });
3063
+ const totalProgress = Math.min(
3064
+ 100,
3065
+ Math.round(
3066
+ (completedCount * 100 + inProgressProgress) / totalChunks
3067
+ )
3068
+ );
3069
+ setChunkProgress((prev) => ({
3070
+ ...prev,
3071
+ [fileId]: {
3072
+ chunkIndex: chunk.index,
3073
+ chunkProgress: chunkProgressPercent,
3074
+ totalProgress,
3075
+ uploadedChunks: completedCount,
3076
+ totalChunks
3077
+ }
3078
+ }));
3079
+ setProgress(totalProgress);
3080
+ onProgress == null ? void 0 : onProgress(totalProgress, file);
3081
+ setFiles(
3082
+ (prev) => prev.map(
3083
+ (f) => f.id === fileItem.id ? { ...f, progress: totalProgress } : f
3084
+ )
3085
+ );
3086
+ }
3087
+ });
3088
+ completedChunksRef.current++;
3089
+ chunkProgressMapRef.current.delete(chunk.index);
3090
+ return chunk.index;
3091
+ });
3092
+ const executeWithConcurrency = async (tasks, limit) => {
3093
+ const results = [];
3094
+ const executing = [];
3095
+ let taskIndex = 0;
3096
+ const runTask = async (task) => {
3097
+ const result = await task();
3098
+ return result;
3099
+ };
3100
+ while (taskIndex < tasks.length || executing.length > 0) {
3101
+ while (taskIndex < tasks.length && executing.length < limit) {
3102
+ const task = tasks[taskIndex];
3103
+ taskIndex++;
3104
+ const promise = runTask(task).then((result) => {
3105
+ results.push(result);
3106
+ return result;
3107
+ });
3108
+ executing.push(promise);
3109
+ }
3110
+ if (executing.length > 0) {
3111
+ await Promise.race(executing);
3112
+ const completedIndex = executing.findIndex(
3113
+ (p) => p.then !== void 0
3114
+ );
3115
+ if (completedIndex !== -1) {
3116
+ executing.splice(completedIndex, 1);
3117
+ }
3118
+ }
3119
+ }
3120
+ return results;
3121
+ };
3122
+ await executeWithConcurrency(uploadTasks, actualConcurrency);
3123
+ let responseText = "";
3124
+ if (mergeUrl) {
3125
+ responseText = await mergeChunks(
3126
+ mergeUrl,
3127
+ file.name,
3128
+ totalChunks,
3129
+ method === "get" ? "post" : method,
3130
+ headers
3131
+ );
3132
+ }
3133
+ const updatedFile = {
3134
+ ...fileItem,
3135
+ status: "success",
3136
+ progress: 100,
3137
+ response: responseText || "Chunked upload completed"
3138
+ };
3139
+ setChunkProgress((prev) => {
3140
+ const newProgress = { ...prev };
3141
+ delete newProgress[fileId];
3142
+ return newProgress;
3143
+ });
3144
+ onSuccess == null ? void 0 : onSuccess(responseText || "Chunked upload completed", file);
3145
+ return updatedFile;
3146
+ } catch (event) {
3147
+ const isAbort = cancelRef.current || (event == null ? void 0 : event.name) === "AbortError";
3148
+ if (isAbort) {
3149
+ return { ...fileItem, status: "idle", progress: 0 };
3150
+ }
3151
+ const error = createUploadError(
3152
+ "NETWORK_ERROR",
3153
+ event instanceof Error ? event.message : "\u5206\u7247\u4E0A\u4F20\u5931\u8D25",
3154
+ file,
3155
+ event instanceof Error ? event : void 0
3156
+ );
3157
+ onError == null ? void 0 : onError(error, file);
3158
+ return { ...fileItem, status: "error", error };
3159
+ }
3160
+ };
1338
3161
  const uploadFiles = React2.useCallback(async (filesToUpload) => {
1339
3162
  var _a;
1340
3163
  if (!action || filesToUpload.length === 0) {
@@ -1368,7 +3191,12 @@ function Upload(config) {
1368
3191
  uploadedFiles.push(result);
1369
3192
  setFiles(
1370
3193
  (prev) => prev.map(
1371
- (f) => f.id === fileItem.id ? { ...f, status: result.status, response: result.response } : f
3194
+ (f) => f.id === fileItem.id ? {
3195
+ ...f,
3196
+ status: result.status,
3197
+ response: result.response,
3198
+ progress: result.status === "success" ? 100 : f.progress
3199
+ } : f
1372
3200
  )
1373
3201
  );
1374
3202
  if (result.status === "success") {
@@ -1534,7 +3362,8 @@ function Upload(config) {
1534
3362
  files,
1535
3363
  show: showFileList,
1536
3364
  onRemove: handleRemoveFile,
1537
- onCancel: handleCancelFile
3365
+ onCancel: handleCancelFile,
3366
+ chunkProgressMap: chunkProgress
1538
3367
  }
1539
3368
  )
1540
3369
  ] });