@5even7/dlc-ui 0.1.0 → 0.2.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/progress.cjs CHANGED
@@ -135,6 +135,9 @@ function _objectSpread2(e) {
135
135
  }
136
136
  return e;
137
137
  }
138
+ function _readOnlyError(r) {
139
+ throw new TypeError('"' + r + '" is read-only');
140
+ }
138
141
  function _slicedToArray(r, e) {
139
142
  return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
140
143
  }
@@ -307,7 +310,7 @@ var PALETTES$1 = {
307
310
  var CAPSULE_PRESETS = [{
308
311
  id: 'original',
309
312
  code: 'NC-01',
310
- name: 'ORIGINAL',
313
+ name: '初光',
311
314
  group: 'warm',
312
315
  seed: 1.7,
313
316
  speed: 0.5,
@@ -315,7 +318,7 @@ var CAPSULE_PRESETS = [{
315
318
  }, {
316
319
  id: 'ocean',
317
320
  code: 'NC-02',
318
- name: 'OCEAN',
321
+ name: '沧溟',
319
322
  group: 'cold',
320
323
  seed: 8.2,
321
324
  speed: 0.48,
@@ -323,7 +326,7 @@ var CAPSULE_PRESETS = [{
323
326
  }, {
324
327
  id: 'klein',
325
328
  code: 'NC-03',
326
- name: 'KLEIN',
329
+ name: '玄夜',
327
330
  group: 'cold',
328
331
  seed: 14.1,
329
332
  speed: 0.49,
@@ -331,7 +334,7 @@ var CAPSULE_PRESETS = [{
331
334
  }, {
332
335
  id: 'ultraviolet',
333
336
  code: 'NC-04',
334
- name: 'ULTRAVIOLET',
337
+ name: '紫霄',
335
338
  group: 'cold',
336
339
  seed: 23.4,
337
340
  speed: 0.47,
@@ -339,7 +342,7 @@ var CAPSULE_PRESETS = [{
339
342
  }, {
340
343
  id: 'chrome',
341
344
  code: 'NC-05',
342
- name: 'CHROME',
345
+ name: '银汉',
343
346
  group: 'cold',
344
347
  seed: 37.8,
345
348
  speed: 0.42,
@@ -347,7 +350,7 @@ var CAPSULE_PRESETS = [{
347
350
  }, {
348
351
  id: 'plus',
349
352
  code: 'NC-06',
350
- name: 'PLUS',
353
+ name: '熔金',
351
354
  group: 'warm',
352
355
  seed: 51.3,
353
356
  speed: 0.5,
@@ -357,7 +360,7 @@ var CAPSULE_PRESETS = [{
357
360
  var PROGRESS_PRESETS = [{
358
361
  id: 'model-training',
359
362
  code: 'NC-10',
360
- name: 'MODEL TRAINING',
363
+ name: '星火',
361
364
  subtitle: 'SHA 4.5 + 100 2026 TKN',
362
365
  group: 'progress',
363
366
  initialProgress: 43,
@@ -366,7 +369,7 @@ var PROGRESS_PRESETS = [{
366
369
  }, {
367
370
  id: 'agent-migration',
368
371
  code: 'NC-11',
369
- name: 'AGENT MIGRATION',
372
+ name: '迁流',
370
373
  subtitle: 'TRANSFERRING PROTOCOL',
371
374
  group: 'progress',
372
375
  initialProgress: 33,
@@ -375,7 +378,7 @@ var PROGRESS_PRESETS = [{
375
378
  }, {
376
379
  id: 'visual-training',
377
380
  code: 'NC-12',
378
- name: 'VISUAL TRAINING',
381
+ name: '幻境',
379
382
  subtitle: 'GENERATING POWER ++',
380
383
  group: 'progress',
381
384
  initialProgress: 58,
@@ -384,7 +387,7 @@ var PROGRESS_PRESETS = [{
384
387
  }, {
385
388
  id: 'tide',
386
389
  code: 'NC-13',
387
- name: 'TIDE',
390
+ name: '汐潮',
388
391
  subtitle: 'MOON PULL / COAST',
389
392
  group: 'progress',
390
393
  initialProgress: 30,
@@ -393,20 +396,18 @@ var PROGRESS_PRESETS = [{
393
396
  }];
394
397
 
395
398
  [].concat(_toConsumableArray(CAPSULE_PRESETS), _toConsumableArray(PROGRESS_PRESETS));
396
- function validateProgressPreset(preset) {
397
- return Boolean(preset && typeof preset.id === 'string' && typeof preset.code === 'string' && typeof preset.name === 'string' && preset.group === 'progress' && Number.isFinite(preset.initialProgress) && ['flow', 'tide'].indexOf(preset.edgeStyle || 'flow') !== -1 && Array.isArray(preset.colors) && preset.colors.length === 4);
398
- }
399
+
400
+ /**
401
+ * Resolve a preset by its literary name (e.g. '沧溟').
402
+ * Matching is case-insensitive and ignores surrounding whitespace,
403
+ * so '沧溟' and ' 沧溟 ' both work.
404
+ */
399
405
  function getPreset(kind, ref) {
400
406
  var list = PROGRESS_PRESETS ;
401
407
  if (!list) throw new Error("Unknown preset kind: ".concat(kind, " (use \"capsule\" or \"progress\")"));
402
- if (ref && _typeof(ref) === 'object') {
403
- var valid = validateProgressPreset(ref);
404
- if (!valid) throw new Error("Invalid ".concat(kind, " preset object"));
405
- return ref;
406
- }
407
408
  var key = String(ref).trim().toLowerCase();
408
409
  var found = list.find(function (preset) {
409
- return preset.id.toLowerCase() === key || preset.code.toLowerCase() === key || preset.name.toLowerCase() === key;
410
+ return preset.name.toLowerCase() === key;
410
411
  });
411
412
  if (!found) throw new Error("Unknown ".concat(kind, " preset: ").concat(ref));
412
413
  return found;
@@ -420,30 +421,236 @@ var DEFAULTS = {
420
421
  max: 100,
421
422
  draggable: true,
422
423
  keyboard: true,
424
+ disabled: false,
425
+ valueSuffix: '%',
423
426
  edgeStyle: 'flow',
424
427
  quality: 'auto',
425
428
  renderer: 'auto',
426
- showCopy: true,
429
+ textRatio: 54,
430
+ showValue: true,
427
431
  respectReducedMotion: true
428
432
  }
429
433
  };
430
434
 
431
- /**
432
- * All user-facing copy lives here so wording/brand changes never require a
433
- * global search. Templates use {brand} {code} {name} placeholders.
435
+ /**
436
+ * Internal accessibility labels and small UI text. Since the copy API was
437
+ * removed (slots own the text area), these are no longer user-overridable.
438
+ * Templates use {brand} {code} {name} placeholders.
434
439
  */
435
440
  var COPY = {
436
441
  brandName: '画境观屿',
437
- dragLabel: 'DRAG',
438
442
  valueSuffix: '%',
439
443
  progressAria: '{brand} {code} 加载进度',
440
444
  capsuleAria: '打开 {name} 沉浸预览'
441
445
  };
442
446
 
443
- function hexToRgba(hex) {
447
+ /**
448
+ * Color helpers. `normalizeColor` converts any supported CSS color
449
+ * (hex / named / rgb() / rgba()) into a 6-digit hex string, so renderers can
450
+ * keep working with #rrggbb only. rgba() alpha is intentionally dropped:
451
+ * the WebGL shader has no per-color alpha channel, and the component is
452
+ * opaque by design — use component-level `opacity` for transparency.
453
+ */
454
+
455
+ var NAMED_COLORS = {
456
+ aliceblue: '#f0f8ff',
457
+ antiquewhite: '#faebd7',
458
+ aqua: '#00ffff',
459
+ aquamarine: '#7fffd4',
460
+ azure: '#f0ffff',
461
+ beige: '#f5f5dc',
462
+ bisque: '#ffe4c4',
463
+ black: '#000000',
464
+ blanchedalmond: '#ffebcd',
465
+ blue: '#0000ff',
466
+ blueviolet: '#8a2be2',
467
+ brown: '#a52a2a',
468
+ burlywood: '#deb887',
469
+ cadetblue: '#5f9ea0',
470
+ chartreuse: '#7fff00',
471
+ chocolate: '#d2691e',
472
+ coral: '#ff7f50',
473
+ cornflowerblue: '#6495ed',
474
+ cornsilk: '#fff8dc',
475
+ crimson: '#dc143c',
476
+ cyan: '#00ffff',
477
+ darkblue: '#00008b',
478
+ darkcyan: '#008b8b',
479
+ darkgoldenrod: '#b8860b',
480
+ darkgray: '#a9a9a9',
481
+ darkgreen: '#006400',
482
+ darkgrey: '#a9a9a9',
483
+ darkkhaki: '#bdb76b',
484
+ darkmagenta: '#8b008b',
485
+ darkolivegreen: '#556b2f',
486
+ darkorange: '#ff8c00',
487
+ darkorchid: '#9932cc',
488
+ darkred: '#8b0000',
489
+ darksalmon: '#e9967a',
490
+ darkseagreen: '#8fbc8f',
491
+ darkslateblue: '#483d8b',
492
+ darkslategray: '#2f4f4f',
493
+ darkslategrey: '#2f4f4f',
494
+ darkturquoise: '#00ced1',
495
+ darkviolet: '#9400d3',
496
+ deeppink: '#ff1493',
497
+ deepskyblue: '#00bfff',
498
+ dimgray: '#696969',
499
+ dimgrey: '#696969',
500
+ dodgerblue: '#1e90ff',
501
+ firebrick: '#b22222',
502
+ floralwhite: '#fffaf0',
503
+ forestgreen: '#228b22',
504
+ fuchsia: '#ff00ff',
505
+ gainsboro: '#dcdcdc',
506
+ ghostwhite: '#f8f8ff',
507
+ gold: '#ffd700',
508
+ goldenrod: '#daa520',
509
+ gray: '#808080',
510
+ green: '#008000',
511
+ greenyellow: '#adff2f',
512
+ grey: '#808080',
513
+ honeydew: '#f0fff0',
514
+ hotpink: '#ff69b4',
515
+ indianred: '#cd5c5c',
516
+ indigo: '#4b0082',
517
+ ivory: '#fffff0',
518
+ khaki: '#f0e68c',
519
+ lavender: '#e6e6fa',
520
+ lavenderblush: '#fff0f5',
521
+ lawngreen: '#7cfc00',
522
+ lemonchiffon: '#fffacd',
523
+ lightblue: '#add8e6',
524
+ lightcoral: '#f08080',
525
+ lightcyan: '#e0ffff',
526
+ lightgoldenrodyellow: '#fafad2',
527
+ lightgray: '#d3d3d3',
528
+ lightgreen: '#90ee90',
529
+ lightgrey: '#d3d3d3',
530
+ lightpink: '#ffb6c1',
531
+ lightsalmon: '#ffa07a',
532
+ lightseagreen: '#20b2aa',
533
+ lightskyblue: '#87cefa',
534
+ lightslategray: '#778899',
535
+ lightslategrey: '#778899',
536
+ lightsteelblue: '#b0c4de',
537
+ lightyellow: '#ffffe0',
538
+ lime: '#00ff00',
539
+ limegreen: '#32cd32',
540
+ linen: '#faf0e6',
541
+ magenta: '#ff00ff',
542
+ maroon: '#800000',
543
+ mediumaquamarine: '#66cdaa',
544
+ mediumblue: '#0000cd',
545
+ mediumorchid: '#ba55d3',
546
+ mediumpurple: '#9370db',
547
+ mediumseagreen: '#3cb371',
548
+ mediumslateblue: '#7b68ee',
549
+ mediumspringgreen: '#00fa9a',
550
+ mediumturquoise: '#48d1cc',
551
+ mediumvioletred: '#c71585',
552
+ midnightblue: '#191970',
553
+ mintcream: '#f5fffa',
554
+ mistyrose: '#ffe4e1',
555
+ moccasin: '#ffe4b5',
556
+ navajowhite: '#ffdead',
557
+ navy: '#000080',
558
+ oldlace: '#fdf5e6',
559
+ olive: '#808000',
560
+ olivedrab: '#6b8e23',
561
+ orange: '#ffa500',
562
+ orangered: '#ff4500',
563
+ orchid: '#da70d6',
564
+ palegoldenrod: '#eee8aa',
565
+ palegreen: '#98fb98',
566
+ paleturquoise: '#afeeee',
567
+ palevioletred: '#db7093',
568
+ papayawhip: '#ffefd5',
569
+ peachpuff: '#ffdab9',
570
+ peru: '#cd853f',
571
+ pink: '#ffc0cb',
572
+ plum: '#dda0dd',
573
+ powderblue: '#b0e0e6',
574
+ purple: '#800080',
575
+ rebeccapurple: '#663399',
576
+ red: '#ff0000',
577
+ rosybrown: '#bc8f8f',
578
+ royalblue: '#4169e1',
579
+ saddlebrown: '#8b4513',
580
+ salmon: '#fa8072',
581
+ sandybrown: '#f4a460',
582
+ seagreen: '#2e8b57',
583
+ seashell: '#fff5ee',
584
+ sienna: '#a0522d',
585
+ silver: '#c0c0c0',
586
+ skyblue: '#87ceeb',
587
+ slateblue: '#6a5acd',
588
+ slategray: '#708090',
589
+ slategrey: '#708090',
590
+ snow: '#fffafa',
591
+ springgreen: '#00ff7f',
592
+ steelblue: '#4682b4',
593
+ tan: '#d2b48c',
594
+ teal: '#008080',
595
+ thistle: '#d8bfd8',
596
+ tomato: '#ff6347',
597
+ turquoise: '#40e0d0',
598
+ violet: '#ee82ee',
599
+ wheat: '#f5deb3',
600
+ white: '#ffffff',
601
+ whitesmoke: '#f5f5f5',
602
+ yellow: '#ffff00',
603
+ yellowgreen: '#9acd32'
604
+ };
605
+ function clampChannel(value) {
606
+ return Math.min(255, Math.max(0, Math.round(value)));
607
+ }
608
+ function normalizeRgbArgs(args) {
609
+ var parts = args.split(/[,\s/]+/).filter(Boolean);
610
+ if (parts.length < 3) return null;
611
+ var to255 = function to255(value) {
612
+ if (typeof value !== 'string' || !value) return null;
613
+ if (value.endsWith('%')) return clampChannel(parseFloat(value) / 100 * 255);
614
+ var number = Number(value);
615
+ return Number.isFinite(number) ? clampChannel(number) : null;
616
+ };
617
+ var red = to255(parts[0]);
618
+ var green = to255(parts[1]);
619
+ var blue = to255(parts[2]);
620
+ if (red === null || green === null || blue === null) return null;
621
+ return "#".concat([red, green, blue].map(function (n) {
622
+ return n.toString(16).padStart(2, '0');
623
+ }).join(''));
624
+ }
625
+
626
+ /**
627
+ * Convert any supported CSS color into `#rrggbb`. Returns null when the
628
+ * value cannot be parsed. Supports: #rgb / #rrggbb (case-insensitive),
629
+ * CSS named colors, rgb() / rgba() with comma or modern space syntax,
630
+ * including percentages. Alpha in rgba() is ignored.
631
+ */
632
+ function normalizeColor(value) {
633
+ if (typeof value !== 'string') return null;
634
+ var input = value.trim();
635
+ if (!input) return null;
636
+ var lower = input.toLowerCase();
637
+ if (NAMED_COLORS[lower]) return NAMED_COLORS[lower];
638
+ if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(input)) {
639
+ var hex = input.slice(1).toLowerCase();
640
+ if (hex.length === 3) return "#".concat(hex.split('').map(function (c) {
641
+ return c + c;
642
+ }).join(''));
643
+ return "#".concat(hex);
644
+ }
645
+ var match = input.match(/^rgba?\((.*)\)$/i);
646
+ if (match) return normalizeRgbArgs(match[1]);
647
+ return null;
648
+ }
649
+ function hexToRgba(color) {
444
650
  var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
445
- var normalized = hex.replace('#', '');
446
- var value = Number.parseInt(normalized, 16);
651
+ var hex = normalizeColor(color);
652
+ if (!hex) return 'rgba(0, 0, 0, 0)';
653
+ var value = Number.parseInt(hex.slice(1), 16);
447
654
  var red = value >> 16 & 255;
448
655
  var green = value >> 8 & 255;
449
656
  var blue = value & 255;
@@ -966,6 +1173,22 @@ function attachProgressFlowOverlay(_ref) {
966
1173
  };
967
1174
  }
968
1175
 
1176
+ /**
1177
+ * Run a callback asynchronously, right after the current task and before the
1178
+ * next paint. Used for mount-time events (ready / error) so listeners that
1179
+ * are attached after create() still receive them. Falls back for legacy
1180
+ * browsers that lack queueMicrotask / Promise.
1181
+ */
1182
+ function nextTick(fn) {
1183
+ if (typeof queueMicrotask === 'function') {
1184
+ queueMicrotask(fn);
1185
+ } else if (typeof Promise !== 'undefined' && typeof Promise.resolve === 'function') {
1186
+ Promise.resolve().then(fn);
1187
+ } else {
1188
+ setTimeout(fn, 0);
1189
+ }
1190
+ }
1191
+
969
1192
  var clamp = function clamp(value, min, max) {
970
1193
  return Math.min(Math.max(value, min), max);
971
1194
  };
@@ -1054,7 +1277,8 @@ var FLOW_PROFILES = {
1054
1277
  };
1055
1278
  var ProgressCapsuleController = /*#__PURE__*/function () {
1056
1279
  function ProgressCapsuleController(_ref) {
1057
- var _options$min,
1280
+ var _options$valueSuffix,
1281
+ _options$min,
1058
1282
  _options$max,
1059
1283
  _options$value,
1060
1284
  _this = this;
@@ -1064,7 +1288,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1064
1288
  preset = _ref.preset,
1065
1289
  emitter = _ref.emitter,
1066
1290
  options = _ref.options,
1067
- copy = _ref.copy;
1291
+ copy = _ref.copy,
1292
+ dirty = _ref.dirty;
1068
1293
  _classCallCheck(this, ProgressCapsuleController);
1069
1294
  this.root = root;
1070
1295
  this.canvas = canvas;
@@ -1073,6 +1298,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1073
1298
  this.emitter = emitter;
1074
1299
  this.options = options;
1075
1300
  this.copy = copy;
1301
+ this.dirty = dirty;
1302
+ this.valueSuffix = (_options$valueSuffix = options.valueSuffix) !== null && _options$valueSuffix !== void 0 ? _options$valueSuffix : copy.valueSuffix;
1076
1303
  this.profile = preset.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
1077
1304
  this.min = (_options$min = options.min) !== null && _options$min !== void 0 ? _options$min : 0;
1078
1305
  this.max = (_options$max = options.max) !== null && _options$max !== void 0 ? _options$max : 100;
@@ -1112,12 +1339,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1112
1339
  var rounded = Math.round(this.value);
1113
1340
  this.root.style.setProperty('--progress', this.value.toFixed(2));
1114
1341
  this.root.setAttribute('aria-valuenow', String(rounded));
1115
- this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.copy.valueSuffix));
1116
- this.valueElement.textContent = "".concat(rounded).concat(this.copy.valueSuffix);
1117
- if (!this.suppressEvents) this.emitter.emit('change', {
1118
- value: this.value,
1119
- source: source
1120
- });
1342
+ this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.valueSuffix));
1343
+ if (this.valueElement) this.valueElement.textContent = "".concat(rounded).concat(this.valueSuffix);
1344
+ if (!this.suppressEvents) {
1345
+ if (this.dirty) this.dirty.value = true;
1346
+ this.emitter.emit('change', {
1347
+ value: this.value,
1348
+ source: source
1349
+ });
1350
+ }
1351
+ }
1352
+ }, {
1353
+ key: "setValueSuffix",
1354
+ value: function setValueSuffix(suffix) {
1355
+ this.valueSuffix = String(suffix == null ? '' : suffix);
1356
+ var rounded = Math.round(this.value);
1357
+ if (this.valueElement) this.valueElement.textContent = "".concat(rounded).concat(this.valueSuffix);
1358
+ this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.valueSuffix));
1359
+ return this;
1121
1360
  }
1122
1361
  }, {
1123
1362
  key: "resizeCanvas",
@@ -1292,7 +1531,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1292
1531
  var width = this.width;
1293
1532
  var height = this.height;
1294
1533
  if (!ctx || width <= 0 || height <= 0) return;
1295
- var shoreline = width * (this.value / 100);
1534
+ var range = Math.max(this.max - this.min, 1);
1535
+ var shoreline = width * Math.min(Math.max((this.value - this.min) / range, 0), 1);
1296
1536
  var time = this.flowTime;
1297
1537
  var _this$preset$colors = _slicedToArray(this.preset.colors, 4),
1298
1538
  dark = _this$preset$colors[0],
@@ -1407,7 +1647,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1407
1647
  value: function updateFromPointer(event) {
1408
1648
  var bounds = this.root.getBoundingClientRect();
1409
1649
  var ratio = bounds.width > 0 ? (event.clientX - bounds.left) / bounds.width : 0;
1410
- this.setProgress(ratio * 100, 'drag');
1650
+ this.setProgress(this.min + ratio * (this.max - this.min), 'drag');
1411
1651
  }
1412
1652
  }, {
1413
1653
  key: "beginDrag",
@@ -1415,6 +1655,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1415
1655
  if (event.button !== undefined && event.button !== 0) return;
1416
1656
  event.preventDefault();
1417
1657
  this.dragging = true;
1658
+ this.pendingPointer = null;
1659
+ this._dragRaf = 0;
1418
1660
  this.root.classList.add('is-dragging');
1419
1661
  try {
1420
1662
  var _this$root$setPointer, _this$root;
@@ -1428,15 +1670,31 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1428
1670
  }, {
1429
1671
  key: "moveDrag",
1430
1672
  value: function moveDrag(event) {
1673
+ var _this2 = this;
1431
1674
  if (!this.dragging) return;
1432
1675
  event.preventDefault();
1433
- this.updateFromPointer(event);
1676
+ // rAF 合并:一帧最多一次 setProgress/change,视觉仍每帧更新。
1677
+ this.pendingPointer = event;
1678
+ if (this._dragRaf) return;
1679
+ this._dragRaf = requestAnimationFrame(function () {
1680
+ _this2._dragRaf = 0;
1681
+ var pending = _this2.pendingPointer;
1682
+ _this2.pendingPointer = null;
1683
+ if (pending) _this2.updateFromPointer(pending);
1684
+ });
1434
1685
  }
1435
1686
  }, {
1436
1687
  key: "endDrag",
1437
1688
  value: function endDrag(event) {
1438
1689
  if (!this.dragging) return;
1439
1690
  this.dragging = false;
1691
+ if (this._dragRaf) {
1692
+ cancelAnimationFrame(this._dragRaf);
1693
+ this._dragRaf = 0;
1694
+ }
1695
+ var pending = this.pendingPointer;
1696
+ this.pendingPointer = null;
1697
+ if (pending) this.updateFromPointer(pending);
1440
1698
  this.root.classList.remove('is-dragging');
1441
1699
  try {
1442
1700
  var _this$root$hasPointer, _this$root2;
@@ -1451,19 +1709,19 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1451
1709
  }, {
1452
1710
  key: "bindEvents",
1453
1711
  value: function bindEvents() {
1454
- var _this2 = this;
1712
+ var _this3 = this;
1455
1713
  if (this.options.draggable !== false) {
1456
1714
  this.handlers.pointerdown = function (event) {
1457
- return _this2.beginDrag(event);
1715
+ return _this3.beginDrag(event);
1458
1716
  };
1459
1717
  this.handlers.pointermove = function (event) {
1460
- return _this2.moveDrag(event);
1718
+ return _this3.moveDrag(event);
1461
1719
  };
1462
1720
  this.handlers.pointerup = function (event) {
1463
- return _this2.endDrag(event);
1721
+ return _this3.endDrag(event);
1464
1722
  };
1465
1723
  this.handlers.pointercancel = function (event) {
1466
- return _this2.endDrag(event);
1724
+ return _this3.endDrag(event);
1467
1725
  };
1468
1726
  this.root.addEventListener('pointerdown', this.handlers.pointerdown);
1469
1727
  this.root.addEventListener('pointermove', this.handlers.pointermove);
@@ -1472,23 +1730,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1472
1730
  }
1473
1731
  if (this.options.keyboard !== false) {
1474
1732
  this.handlers.keydown = function (event) {
1733
+ var step = (_this3.max - _this3.min) * 0.02;
1475
1734
  var actions = {
1476
- ArrowLeft: -2,
1477
- ArrowDown: -2,
1478
- ArrowRight: 2,
1479
- ArrowUp: 2,
1480
- PageDown: -10,
1481
- PageUp: 10
1735
+ ArrowLeft: -step,
1736
+ ArrowDown: -step,
1737
+ ArrowRight: step,
1738
+ ArrowUp: step,
1739
+ PageDown: -step * 5,
1740
+ PageUp: step * 5
1482
1741
  };
1483
1742
  if (event.key === 'Home') {
1484
1743
  event.preventDefault();
1485
- _this2.setProgress(_this2.min, 'keyboard');
1744
+ _this3.setProgress(_this3.min, 'keyboard');
1486
1745
  } else if (event.key === 'End') {
1487
1746
  event.preventDefault();
1488
- _this2.setProgress(_this2.max, 'keyboard');
1747
+ _this3.setProgress(_this3.max, 'keyboard');
1489
1748
  } else if (actions[event.key]) {
1490
1749
  event.preventDefault();
1491
- _this2.setProgress(_this2.value + actions[event.key], 'keyboard');
1750
+ _this3.setProgress(_this3.value + actions[event.key], 'keyboard');
1492
1751
  } else {
1493
1752
  return;
1494
1753
  }
@@ -1525,6 +1784,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1525
1784
  }, {
1526
1785
  key: "dispose",
1527
1786
  value: function dispose() {
1787
+ if (this._dragRaf) cancelAnimationFrame(this._dragRaf);
1528
1788
  if (this.resizeObserver) this.resizeObserver.disconnect();else window.removeEventListener('resize', this.resizeCanvas);
1529
1789
  for (var _i = 0, _Object$keys = Object.keys(this.handlers); _i < _Object$keys.length; _i++) {
1530
1790
  var name = _Object$keys[_i];
@@ -1537,11 +1797,14 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1537
1797
  }();
1538
1798
 
1539
1799
  /**
1540
- * Mount a fluid progress capsule into `container`.
1541
- *
1542
- * Options: preset (id/code/name or object), width, height, value, min, max,
1543
- * draggable, keyboard, colors, edgeStyle, quality,
1544
- * respectReducedMotion, copy, cssVars.
1800
+ * Mount a fluid progress capsule into `container`.
1801
+ *
1802
+ * Options: preset (id/code/name or object), width, height, value, min, max,
1803
+ * draggable, keyboard, colors, edgeStyle, textRatio (0-100, text region
1804
+ * width in percent), text (HTML string or DOM nodes for the text slot),
1805
+ * colorContent (HTML string or DOM nodes for the color slot),
1806
+ * showValue (show/hide the right-side percentage), quality,
1807
+ * respectReducedMotion, cssVars.
1545
1808
  */
1546
1809
  function createProgressCapsule(container) {
1547
1810
  var _options$preset, _merged$min, _merged$max;
@@ -1549,64 +1812,93 @@ function createProgressCapsule(container) {
1549
1812
  if (!container || typeof container.appendChild !== 'function') {
1550
1813
  throw new Error('createProgressCapsule: container element is required');
1551
1814
  }
1552
- var preset = _objectSpread2({}, getPreset('progress', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : 'NC-10'));
1815
+ var preset = _objectSpread2({}, getPreset('progress', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '星火'));
1553
1816
  var merged = normalizeOptions(DEFAULTS.progress, preset, options);
1554
- var copy = _objectSpread2(_objectSpread2({}, COPY), merged.copy || {});
1817
+ var normalizedColors = merged.colors.map(normalizeColor);
1818
+ if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
1819
+ preset.edgeStyle = merged.edgeStyle;
1820
+ var copy = COPY;
1821
+ var customLabel = typeof options.label === 'string' && options.label ? options.label : null;
1822
+ // Vue 的裸布尔属性(<ProgressCapsule disabled />)会传成空字符串,
1823
+ // 这里统一按 true 处理。
1824
+ var disabled = merged.disabled === true || merged.disabled === '' || merged.disabled === 'true';
1825
+ var effectiveDraggable = disabled ? false : merged.draggable !== false;
1826
+ var effectiveKeyboard = disabled ? false : merged.keyboard !== false;
1827
+ var dirty = {
1828
+ preset: false,
1829
+ colors: false,
1830
+ textRatio: false,
1831
+ cssVars: false,
1832
+ edgeStyle: false,
1833
+ value: false
1834
+ };
1555
1835
  var root = document.createElement('div');
1556
1836
  root.className = 'hj-capsule-root hj-progress-root';
1557
1837
  root.setAttribute('role', 'slider');
1558
1838
  root.setAttribute('tabindex', '0');
1559
- root.setAttribute('data-draggable', String(merged.draggable !== false));
1839
+ root.setAttribute('data-draggable', String(effectiveDraggable));
1840
+ if (disabled) {
1841
+ root.setAttribute('aria-disabled', 'true');
1842
+ root.classList.add('is-disabled');
1843
+ }
1560
1844
  root.setAttribute('aria-valuemin', String((_merged$min = merged.min) !== null && _merged$min !== void 0 ? _merged$min : 0));
1561
1845
  root.setAttribute('aria-valuemax', String((_merged$max = merged.max) !== null && _merged$max !== void 0 ? _merged$max : 100));
1562
1846
  root.setAttribute('aria-valuenow', String(preset.initialProgress));
1563
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
1564
- brand: copy.brandName,
1565
- code: preset.code,
1566
- name: preset.name
1567
- }));
1568
- if (merged.keyboard === false) root.setAttribute('tabindex', '-1');
1847
+ var updateAria = function updateAria() {
1848
+ root.setAttribute('aria-label', customLabel || interpolate(copy.progressAria, {
1849
+ brand: copy.brandName,
1850
+ code: preset.code,
1851
+ name: preset.name
1852
+ }));
1853
+ };
1854
+ updateAria();
1855
+ if (!effectiveKeyboard) root.setAttribute('tabindex', '-1');
1569
1856
  var canvas = document.createElement('canvas');
1570
1857
  canvas.className = 'hj-progress-canvas';
1571
1858
  canvas.setAttribute('aria-hidden', 'true');
1572
- var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
1573
- var copyText = function copyText(key, fallback) {
1574
- var value = copy[key];
1575
- return value === undefined ? fallback : value;
1576
- };
1577
- function buildCopyHtml() {
1578
- var html = '';
1579
- var brandText = copy.brandName || '';
1580
- var subtitleText = copyText('subtitle', preset.subtitle);
1581
- if (brandText) html += "<span class=\"hj-progress-name\">".concat(brandText, "</span>");
1582
- if (subtitleText) html += "<span class=\"hj-progress-subtitle\">".concat(subtitleText, "</span>");
1583
- return html;
1584
- }
1585
- var copyLayer = document.createElement('div');
1586
- copyLayer.className = 'hj-progress-copy';
1587
- var renderCopy = function renderCopy() {
1588
- if (copyEnabled) copyLayer.innerHTML = buildCopyHtml();
1859
+
1860
+ // Slot containers are always present but transparent by default; they only
1861
+ // provide geometry, never typography/padding/background (docs: 插槽 CSS 约定).
1862
+ var fillContent = function fillContent(layer, content) {
1863
+ layer.innerHTML = '';
1864
+ if (content == null) return;
1865
+ if (typeof content === 'string') {
1866
+ layer.innerHTML = content;
1867
+ return;
1868
+ }
1869
+ var nodes = Array.isArray(content) ? content : [content];
1870
+ var _iterator2 = _createForOfIteratorHelper(nodes),
1871
+ _step2;
1872
+ try {
1873
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
1874
+ var node = _step2.value;
1875
+ if (node && typeof node.nodeType === 'number') layer.appendChild(node);
1876
+ }
1877
+ } catch (err) {
1878
+ _iterator2.e(err);
1879
+ } finally {
1880
+ _iterator2.f();
1881
+ }
1589
1882
  };
1590
- renderCopy();
1591
- if (copy.background) {
1592
- root.style.setProperty('--hj-progress-copy-bg', copy.background);
1593
- root.style.setProperty('--hj-progress-copy-pad', '6px 12px');
1883
+ var textLayer = document.createElement('div');
1884
+ textLayer.className = 'hj-progress-text hj-progress-copy';
1885
+ var visualLayer = document.createElement('div');
1886
+ visualLayer.className = 'hj-progress-visual';
1887
+ fillContent(textLayer, options.text);
1888
+ fillContent(visualLayer, options.colorContent);
1889
+ var valueElement = merged.showValue === false ? null : document.createElement('div');
1890
+ if (valueElement) {
1891
+ valueElement.className = 'hj-progress-value';
1892
+ valueElement.setAttribute('aria-hidden', 'true');
1594
1893
  }
1595
- if (copy.color) root.style.setProperty('--hj-progress-copy-color', copy.color);
1596
- var valueElement = document.createElement('div');
1597
- valueElement.className = 'hj-progress-value';
1598
- valueElement.setAttribute('aria-hidden', 'true');
1599
- var dragLabel = document.createElement('span');
1600
- dragLabel.className = 'hj-progress-drag-label';
1601
- dragLabel.setAttribute('aria-hidden', 'true');
1602
- dragLabel.textContent = copy.dragLabel;
1603
1894
  root.appendChild(canvas);
1604
- if (copyEnabled) root.appendChild(copyLayer);
1605
- root.appendChild(valueElement);
1606
- root.appendChild(dragLabel);
1895
+ root.appendChild(textLayer);
1896
+ root.appendChild(visualLayer);
1897
+ if (valueElement) root.appendChild(valueElement);
1607
1898
  container.appendChild(root);
1608
1899
  var emitter = createEmitter();
1609
1900
  var paused = merged.respectReducedMotion && prefersReducedMotion();
1901
+ var disposed = false;
1610
1902
  var applySize = function applySize() {
1611
1903
  root.style.width = parseSize(merged.width);
1612
1904
  root.style.height = parseSize(merged.height);
@@ -1615,6 +1907,9 @@ function createProgressCapsule(container) {
1615
1907
  var name = _Object$keys2[_i2];
1616
1908
  root.style.setProperty(name, vars[name]);
1617
1909
  }
1910
+ if (merged.textRatio !== undefined) {
1911
+ root.style.setProperty('--hj-text-width', "".concat(merged.textRatio, "%"));
1912
+ }
1618
1913
  };
1619
1914
  applySize();
1620
1915
  var controller = new ProgressCapsuleController({
@@ -1623,8 +1918,12 @@ function createProgressCapsule(container) {
1623
1918
  valueElement: valueElement,
1624
1919
  preset: preset,
1625
1920
  emitter: emitter,
1626
- options: merged,
1627
- copy: copy
1921
+ options: _objectSpread2(_objectSpread2({}, merged), {}, {
1922
+ draggable: effectiveDraggable,
1923
+ keyboard: effectiveKeyboard
1924
+ }),
1925
+ copy: copy,
1926
+ dirty: dirty
1628
1927
  });
1629
1928
  var overlay = null;
1630
1929
  if (merged.renderer !== 'canvas2d') {
@@ -1637,7 +1936,14 @@ function createProgressCapsule(container) {
1637
1936
  }
1638
1937
  });
1639
1938
  }
1640
- if (overlay) controller.webglActive = true;
1939
+ if (overlay) controller.webglActive = true;else if (merged.renderer !== 'canvas2d') {
1940
+ nextTick(function () {
1941
+ if (disposed) return;
1942
+ emitter.emit('error', {
1943
+ message: 'WebGL2 unavailable, using Canvas2D fallback'
1944
+ });
1945
+ });
1946
+ }
1641
1947
  var visibility = createVisibilityGuard(root);
1642
1948
  var flowTime = 0;
1643
1949
  var unsubscribe = subscribeScheduler(function (delta, now) {
@@ -1650,16 +1956,14 @@ function createProgressCapsule(container) {
1650
1956
  }, function () {
1651
1957
  return paused;
1652
1958
  });
1653
- emitter.emit('ready', {
1654
- preset: _objectSpread2({}, preset)
1959
+ nextTick(function () {
1960
+ if (disposed) return;
1961
+ emitter.emit('ready', {
1962
+ preset: _objectSpread2({}, preset)
1963
+ });
1655
1964
  });
1656
1965
  var syncDom = function syncDom() {
1657
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
1658
- brand: copy.brandName,
1659
- code: preset.code,
1660
- name: preset.name
1661
- }));
1662
- renderCopy();
1966
+ updateAria();
1663
1967
  };
1664
1968
  return {
1665
1969
  element: root,
@@ -1681,8 +1985,11 @@ function createProgressCapsule(container) {
1681
1985
  },
1682
1986
  setPreset: function setPreset(ref) {
1683
1987
  var next = getPreset('progress', ref);
1988
+ dirty.preset = true;
1684
1989
  Object.assign(preset, next);
1685
- controller.preset = next;
1990
+ var nextColors = preset.colors.map(normalizeColor);
1991
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
1992
+ controller.preset = preset;
1686
1993
  controller.profile = next.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[next.id] || FLOW_PROFILES['visual-training'];
1687
1994
  controller.flowTime = stringSeed(next.id) * 31;
1688
1995
  controller.seed = stringSeed("".concat(next.id, "-reference")) * Math.PI * 2;
@@ -1692,7 +1999,7 @@ function createProgressCapsule(container) {
1692
1999
  overlay = attachProgressFlowOverlay({
1693
2000
  root: root,
1694
2001
  canvas: canvas,
1695
- preset: next,
2002
+ preset: preset,
1696
2003
  getProgress: function getProgress() {
1697
2004
  return controller.value;
1698
2005
  }
@@ -1701,14 +2008,74 @@ function createProgressCapsule(container) {
1701
2008
  controller.webglActive = Boolean(overlay);
1702
2009
  controller.resizeCanvas();
1703
2010
  emitter.emit('presetchange', {
1704
- preset: _objectSpread2({}, next)
2011
+ preset: _objectSpread2({}, preset)
1705
2012
  });
1706
2013
  return this;
1707
2014
  },
2015
+ setEdgeStyle: function setEdgeStyle(edgeStyle) {
2016
+ var value = String(edgeStyle || '').toLowerCase();
2017
+ if (value !== 'flow' && value !== 'tide') return this;
2018
+ dirty.edgeStyle = true;
2019
+ preset.edgeStyle = value;
2020
+ controller.profile = value === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
2021
+ if (overlay) {
2022
+ overlay.dispose();
2023
+ overlay = attachProgressFlowOverlay({
2024
+ root: root,
2025
+ canvas: canvas,
2026
+ preset: preset,
2027
+ getProgress: function getProgress() {
2028
+ return controller.value;
2029
+ }
2030
+ });
2031
+ }
2032
+ controller.webglActive = Boolean(overlay);
2033
+ controller.resizeCanvas();
2034
+ return this;
2035
+ },
2036
+ setText: function setText(content) {
2037
+ fillContent(textLayer, content);
2038
+ return this;
2039
+ },
2040
+ setColorContent: function setColorContent(content) {
2041
+ fillContent(visualLayer, content);
2042
+ return this;
2043
+ },
2044
+ setTextRatio: function setTextRatio(ratio) {
2045
+ var value = Number(ratio);
2046
+ if (!Number.isFinite(value) || value < 0 || value > 100) return this;
2047
+ dirty.textRatio = true;
2048
+ merged.textRatio = value;
2049
+ root.style.setProperty('--hj-text-width', "".concat(value, "%"));
2050
+ return this;
2051
+ },
2052
+ setCssVars: function setCssVars(vars) {
2053
+ if (!vars || _typeof(vars) !== 'object') return this;
2054
+ dirty.cssVars = true;
2055
+ merged.cssVars = _objectSpread2(_objectSpread2({}, merged.cssVars || {}), vars);
2056
+ for (var _i3 = 0, _Object$keys3 = Object.keys(vars); _i3 < _Object$keys3.length; _i3++) {
2057
+ var name = _Object$keys3[_i3];
2058
+ root.style.setProperty(name, vars[name]);
2059
+ }
2060
+ return this;
2061
+ },
2062
+ setLabel: function setLabel(label) {
2063
+ _readOnlyError("customLabel");
2064
+ updateAria();
2065
+ return this;
2066
+ },
2067
+ setValueSuffix: function setValueSuffix(suffix) {
2068
+ controller.setValueSuffix(suffix);
2069
+ return this;
2070
+ },
1708
2071
  setColors: function setColors(colors) {
1709
- if (!Array.isArray(colors) || colors.length !== 4) return this;
1710
- controller.setColors(colors);
1711
- if (overlay) overlay.setColors(colors);
2072
+ var next = Array.isArray(colors) ? colors.map(normalizeColor) : [];
2073
+ if (next.length !== 4 || next.some(function (color) {
2074
+ return !color;
2075
+ })) return this;
2076
+ dirty.colors = true;
2077
+ controller.setColors(next);
2078
+ if (overlay) overlay.setColors(next);
1712
2079
  controller.resizeCanvas();
1713
2080
  return this;
1714
2081
  },
@@ -1738,12 +2105,16 @@ function createProgressCapsule(container) {
1738
2105
  return this;
1739
2106
  },
1740
2107
  dispose: function dispose() {
2108
+ disposed = true;
1741
2109
  unsubscribe();
1742
2110
  visibility.dispose();
1743
2111
  if (overlay) overlay.dispose();
1744
2112
  controller.dispose();
1745
2113
  root.remove();
1746
- }
2114
+ },
2115
+ textRatio: merged.textRatio,
2116
+ cssVars: merged.cssVars,
2117
+ dirty: dirty
1747
2118
  };
1748
2119
  }
1749
2120