@5even7/dlc-ui 0.2.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
  }
@@ -418,30 +421,236 @@ var DEFAULTS = {
418
421
  max: 100,
419
422
  draggable: true,
420
423
  keyboard: true,
424
+ disabled: false,
425
+ valueSuffix: '%',
421
426
  edgeStyle: 'flow',
422
427
  quality: 'auto',
423
428
  renderer: 'auto',
424
- showCopy: true,
429
+ textRatio: 54,
430
+ showValue: true,
425
431
  respectReducedMotion: true
426
432
  }
427
433
  };
428
434
 
429
- /**
430
- * All user-facing copy lives here so wording/brand changes never require a
431
- * 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.
432
439
  */
433
440
  var COPY = {
434
441
  brandName: '画境观屿',
435
- dragLabel: 'DRAG',
436
442
  valueSuffix: '%',
437
443
  progressAria: '{brand} {code} 加载进度',
438
444
  capsuleAria: '打开 {name} 沉浸预览'
439
445
  };
440
446
 
441
- 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) {
442
650
  var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
443
- var normalized = hex.replace('#', '');
444
- 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);
445
654
  var red = value >> 16 & 255;
446
655
  var green = value >> 8 & 255;
447
656
  var blue = value & 255;
@@ -964,6 +1173,22 @@ function attachProgressFlowOverlay(_ref) {
964
1173
  };
965
1174
  }
966
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
+
967
1192
  var clamp = function clamp(value, min, max) {
968
1193
  return Math.min(Math.max(value, min), max);
969
1194
  };
@@ -1052,7 +1277,8 @@ var FLOW_PROFILES = {
1052
1277
  };
1053
1278
  var ProgressCapsuleController = /*#__PURE__*/function () {
1054
1279
  function ProgressCapsuleController(_ref) {
1055
- var _options$min,
1280
+ var _options$valueSuffix,
1281
+ _options$min,
1056
1282
  _options$max,
1057
1283
  _options$value,
1058
1284
  _this = this;
@@ -1062,7 +1288,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1062
1288
  preset = _ref.preset,
1063
1289
  emitter = _ref.emitter,
1064
1290
  options = _ref.options,
1065
- copy = _ref.copy;
1291
+ copy = _ref.copy,
1292
+ dirty = _ref.dirty;
1066
1293
  _classCallCheck(this, ProgressCapsuleController);
1067
1294
  this.root = root;
1068
1295
  this.canvas = canvas;
@@ -1071,6 +1298,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1071
1298
  this.emitter = emitter;
1072
1299
  this.options = options;
1073
1300
  this.copy = copy;
1301
+ this.dirty = dirty;
1302
+ this.valueSuffix = (_options$valueSuffix = options.valueSuffix) !== null && _options$valueSuffix !== void 0 ? _options$valueSuffix : copy.valueSuffix;
1074
1303
  this.profile = preset.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
1075
1304
  this.min = (_options$min = options.min) !== null && _options$min !== void 0 ? _options$min : 0;
1076
1305
  this.max = (_options$max = options.max) !== null && _options$max !== void 0 ? _options$max : 100;
@@ -1110,12 +1339,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1110
1339
  var rounded = Math.round(this.value);
1111
1340
  this.root.style.setProperty('--progress', this.value.toFixed(2));
1112
1341
  this.root.setAttribute('aria-valuenow', String(rounded));
1113
- this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.copy.valueSuffix));
1114
- this.valueElement.textContent = "".concat(rounded).concat(this.copy.valueSuffix);
1115
- if (!this.suppressEvents) this.emitter.emit('change', {
1116
- value: this.value,
1117
- source: source
1118
- });
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;
1119
1360
  }
1120
1361
  }, {
1121
1362
  key: "resizeCanvas",
@@ -1290,7 +1531,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1290
1531
  var width = this.width;
1291
1532
  var height = this.height;
1292
1533
  if (!ctx || width <= 0 || height <= 0) return;
1293
- 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);
1294
1536
  var time = this.flowTime;
1295
1537
  var _this$preset$colors = _slicedToArray(this.preset.colors, 4),
1296
1538
  dark = _this$preset$colors[0],
@@ -1405,7 +1647,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1405
1647
  value: function updateFromPointer(event) {
1406
1648
  var bounds = this.root.getBoundingClientRect();
1407
1649
  var ratio = bounds.width > 0 ? (event.clientX - bounds.left) / bounds.width : 0;
1408
- this.setProgress(ratio * 100, 'drag');
1650
+ this.setProgress(this.min + ratio * (this.max - this.min), 'drag');
1409
1651
  }
1410
1652
  }, {
1411
1653
  key: "beginDrag",
@@ -1413,6 +1655,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1413
1655
  if (event.button !== undefined && event.button !== 0) return;
1414
1656
  event.preventDefault();
1415
1657
  this.dragging = true;
1658
+ this.pendingPointer = null;
1659
+ this._dragRaf = 0;
1416
1660
  this.root.classList.add('is-dragging');
1417
1661
  try {
1418
1662
  var _this$root$setPointer, _this$root;
@@ -1426,15 +1670,31 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1426
1670
  }, {
1427
1671
  key: "moveDrag",
1428
1672
  value: function moveDrag(event) {
1673
+ var _this2 = this;
1429
1674
  if (!this.dragging) return;
1430
1675
  event.preventDefault();
1431
- 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
+ });
1432
1685
  }
1433
1686
  }, {
1434
1687
  key: "endDrag",
1435
1688
  value: function endDrag(event) {
1436
1689
  if (!this.dragging) return;
1437
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);
1438
1698
  this.root.classList.remove('is-dragging');
1439
1699
  try {
1440
1700
  var _this$root$hasPointer, _this$root2;
@@ -1449,19 +1709,19 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1449
1709
  }, {
1450
1710
  key: "bindEvents",
1451
1711
  value: function bindEvents() {
1452
- var _this2 = this;
1712
+ var _this3 = this;
1453
1713
  if (this.options.draggable !== false) {
1454
1714
  this.handlers.pointerdown = function (event) {
1455
- return _this2.beginDrag(event);
1715
+ return _this3.beginDrag(event);
1456
1716
  };
1457
1717
  this.handlers.pointermove = function (event) {
1458
- return _this2.moveDrag(event);
1718
+ return _this3.moveDrag(event);
1459
1719
  };
1460
1720
  this.handlers.pointerup = function (event) {
1461
- return _this2.endDrag(event);
1721
+ return _this3.endDrag(event);
1462
1722
  };
1463
1723
  this.handlers.pointercancel = function (event) {
1464
- return _this2.endDrag(event);
1724
+ return _this3.endDrag(event);
1465
1725
  };
1466
1726
  this.root.addEventListener('pointerdown', this.handlers.pointerdown);
1467
1727
  this.root.addEventListener('pointermove', this.handlers.pointermove);
@@ -1470,23 +1730,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1470
1730
  }
1471
1731
  if (this.options.keyboard !== false) {
1472
1732
  this.handlers.keydown = function (event) {
1733
+ var step = (_this3.max - _this3.min) * 0.02;
1473
1734
  var actions = {
1474
- ArrowLeft: -2,
1475
- ArrowDown: -2,
1476
- ArrowRight: 2,
1477
- ArrowUp: 2,
1478
- PageDown: -10,
1479
- PageUp: 10
1735
+ ArrowLeft: -step,
1736
+ ArrowDown: -step,
1737
+ ArrowRight: step,
1738
+ ArrowUp: step,
1739
+ PageDown: -step * 5,
1740
+ PageUp: step * 5
1480
1741
  };
1481
1742
  if (event.key === 'Home') {
1482
1743
  event.preventDefault();
1483
- _this2.setProgress(_this2.min, 'keyboard');
1744
+ _this3.setProgress(_this3.min, 'keyboard');
1484
1745
  } else if (event.key === 'End') {
1485
1746
  event.preventDefault();
1486
- _this2.setProgress(_this2.max, 'keyboard');
1747
+ _this3.setProgress(_this3.max, 'keyboard');
1487
1748
  } else if (actions[event.key]) {
1488
1749
  event.preventDefault();
1489
- _this2.setProgress(_this2.value + actions[event.key], 'keyboard');
1750
+ _this3.setProgress(_this3.value + actions[event.key], 'keyboard');
1490
1751
  } else {
1491
1752
  return;
1492
1753
  }
@@ -1523,6 +1784,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1523
1784
  }, {
1524
1785
  key: "dispose",
1525
1786
  value: function dispose() {
1787
+ if (this._dragRaf) cancelAnimationFrame(this._dragRaf);
1526
1788
  if (this.resizeObserver) this.resizeObserver.disconnect();else window.removeEventListener('resize', this.resizeCanvas);
1527
1789
  for (var _i = 0, _Object$keys = Object.keys(this.handlers); _i < _Object$keys.length; _i++) {
1528
1790
  var name = _Object$keys[_i];
@@ -1535,11 +1797,14 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1535
1797
  }();
1536
1798
 
1537
1799
  /**
1538
- * Mount a fluid progress capsule into `container`.
1539
- *
1540
- * Options: preset (id/code/name or object), width, height, value, min, max,
1541
- * draggable, keyboard, colors, edgeStyle, quality,
1542
- * 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.
1543
1808
  */
1544
1809
  function createProgressCapsule(container) {
1545
1810
  var _options$preset, _merged$min, _merged$max;
@@ -1549,62 +1814,91 @@ function createProgressCapsule(container) {
1549
1814
  }
1550
1815
  var preset = _objectSpread2({}, getPreset('progress', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '星火'));
1551
1816
  var merged = normalizeOptions(DEFAULTS.progress, preset, options);
1552
- 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
+ };
1553
1835
  var root = document.createElement('div');
1554
1836
  root.className = 'hj-capsule-root hj-progress-root';
1555
1837
  root.setAttribute('role', 'slider');
1556
1838
  root.setAttribute('tabindex', '0');
1557
- 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
+ }
1558
1844
  root.setAttribute('aria-valuemin', String((_merged$min = merged.min) !== null && _merged$min !== void 0 ? _merged$min : 0));
1559
1845
  root.setAttribute('aria-valuemax', String((_merged$max = merged.max) !== null && _merged$max !== void 0 ? _merged$max : 100));
1560
1846
  root.setAttribute('aria-valuenow', String(preset.initialProgress));
1561
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
1562
- brand: copy.brandName,
1563
- code: preset.code,
1564
- name: preset.name
1565
- }));
1566
- 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');
1567
1856
  var canvas = document.createElement('canvas');
1568
1857
  canvas.className = 'hj-progress-canvas';
1569
1858
  canvas.setAttribute('aria-hidden', 'true');
1570
- var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
1571
- var copyText = function copyText(key, fallback) {
1572
- var value = copy[key];
1573
- return value === undefined ? fallback : value;
1574
- };
1575
- function buildCopyHtml() {
1576
- var html = '';
1577
- var brandText = copy.brandName || '';
1578
- var subtitleText = copyText('subtitle', preset.subtitle);
1579
- if (brandText) html += "<span class=\"hj-progress-name\">".concat(brandText, "</span>");
1580
- if (subtitleText) html += "<span class=\"hj-progress-subtitle\">".concat(subtitleText, "</span>");
1581
- return html;
1582
- }
1583
- var copyLayer = document.createElement('div');
1584
- copyLayer.className = 'hj-progress-copy';
1585
- var renderCopy = function renderCopy() {
1586
- 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
+ }
1587
1882
  };
1588
- renderCopy();
1589
- if (copy.background) {
1590
- root.style.setProperty('--hj-progress-copy-bg', copy.background);
1591
- 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');
1592
1893
  }
1593
- if (copy.color) root.style.setProperty('--hj-progress-copy-color', copy.color);
1594
- var valueElement = document.createElement('div');
1595
- valueElement.className = 'hj-progress-value';
1596
- valueElement.setAttribute('aria-hidden', 'true');
1597
- var dragLabel = document.createElement('span');
1598
- dragLabel.className = 'hj-progress-drag-label';
1599
- dragLabel.setAttribute('aria-hidden', 'true');
1600
- dragLabel.textContent = copy.dragLabel;
1601
1894
  root.appendChild(canvas);
1602
- if (copyEnabled) root.appendChild(copyLayer);
1603
- root.appendChild(valueElement);
1604
- root.appendChild(dragLabel);
1895
+ root.appendChild(textLayer);
1896
+ root.appendChild(visualLayer);
1897
+ if (valueElement) root.appendChild(valueElement);
1605
1898
  container.appendChild(root);
1606
1899
  var emitter = createEmitter();
1607
1900
  var paused = merged.respectReducedMotion && prefersReducedMotion();
1901
+ var disposed = false;
1608
1902
  var applySize = function applySize() {
1609
1903
  root.style.width = parseSize(merged.width);
1610
1904
  root.style.height = parseSize(merged.height);
@@ -1613,6 +1907,9 @@ function createProgressCapsule(container) {
1613
1907
  var name = _Object$keys2[_i2];
1614
1908
  root.style.setProperty(name, vars[name]);
1615
1909
  }
1910
+ if (merged.textRatio !== undefined) {
1911
+ root.style.setProperty('--hj-text-width', "".concat(merged.textRatio, "%"));
1912
+ }
1616
1913
  };
1617
1914
  applySize();
1618
1915
  var controller = new ProgressCapsuleController({
@@ -1621,8 +1918,12 @@ function createProgressCapsule(container) {
1621
1918
  valueElement: valueElement,
1622
1919
  preset: preset,
1623
1920
  emitter: emitter,
1624
- options: merged,
1625
- copy: copy
1921
+ options: _objectSpread2(_objectSpread2({}, merged), {}, {
1922
+ draggable: effectiveDraggable,
1923
+ keyboard: effectiveKeyboard
1924
+ }),
1925
+ copy: copy,
1926
+ dirty: dirty
1626
1927
  });
1627
1928
  var overlay = null;
1628
1929
  if (merged.renderer !== 'canvas2d') {
@@ -1635,7 +1936,14 @@ function createProgressCapsule(container) {
1635
1936
  }
1636
1937
  });
1637
1938
  }
1638
- 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
+ }
1639
1947
  var visibility = createVisibilityGuard(root);
1640
1948
  var flowTime = 0;
1641
1949
  var unsubscribe = subscribeScheduler(function (delta, now) {
@@ -1648,16 +1956,14 @@ function createProgressCapsule(container) {
1648
1956
  }, function () {
1649
1957
  return paused;
1650
1958
  });
1651
- emitter.emit('ready', {
1652
- preset: _objectSpread2({}, preset)
1959
+ nextTick(function () {
1960
+ if (disposed) return;
1961
+ emitter.emit('ready', {
1962
+ preset: _objectSpread2({}, preset)
1963
+ });
1653
1964
  });
1654
1965
  var syncDom = function syncDom() {
1655
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
1656
- brand: copy.brandName,
1657
- code: preset.code,
1658
- name: preset.name
1659
- }));
1660
- renderCopy();
1966
+ updateAria();
1661
1967
  };
1662
1968
  return {
1663
1969
  element: root,
@@ -1679,8 +1985,11 @@ function createProgressCapsule(container) {
1679
1985
  },
1680
1986
  setPreset: function setPreset(ref) {
1681
1987
  var next = getPreset('progress', ref);
1988
+ dirty.preset = true;
1682
1989
  Object.assign(preset, next);
1683
- controller.preset = next;
1990
+ var nextColors = preset.colors.map(normalizeColor);
1991
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
1992
+ controller.preset = preset;
1684
1993
  controller.profile = next.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[next.id] || FLOW_PROFILES['visual-training'];
1685
1994
  controller.flowTime = stringSeed(next.id) * 31;
1686
1995
  controller.seed = stringSeed("".concat(next.id, "-reference")) * Math.PI * 2;
@@ -1690,7 +1999,7 @@ function createProgressCapsule(container) {
1690
1999
  overlay = attachProgressFlowOverlay({
1691
2000
  root: root,
1692
2001
  canvas: canvas,
1693
- preset: next,
2002
+ preset: preset,
1694
2003
  getProgress: function getProgress() {
1695
2004
  return controller.value;
1696
2005
  }
@@ -1699,13 +2008,14 @@ function createProgressCapsule(container) {
1699
2008
  controller.webglActive = Boolean(overlay);
1700
2009
  controller.resizeCanvas();
1701
2010
  emitter.emit('presetchange', {
1702
- preset: _objectSpread2({}, next)
2011
+ preset: _objectSpread2({}, preset)
1703
2012
  });
1704
2013
  return this;
1705
2014
  },
1706
2015
  setEdgeStyle: function setEdgeStyle(edgeStyle) {
1707
2016
  var value = String(edgeStyle || '').toLowerCase();
1708
2017
  if (value !== 'flow' && value !== 'tide') return this;
2018
+ dirty.edgeStyle = true;
1709
2019
  preset.edgeStyle = value;
1710
2020
  controller.profile = value === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
1711
2021
  if (overlay) {
@@ -1723,10 +2033,49 @@ function createProgressCapsule(container) {
1723
2033
  controller.resizeCanvas();
1724
2034
  return this;
1725
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
+ },
1726
2071
  setColors: function setColors(colors) {
1727
- if (!Array.isArray(colors) || colors.length !== 4) return this;
1728
- controller.setColors(colors);
1729
- 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);
1730
2079
  controller.resizeCanvas();
1731
2080
  return this;
1732
2081
  },
@@ -1756,12 +2105,16 @@ function createProgressCapsule(container) {
1756
2105
  return this;
1757
2106
  },
1758
2107
  dispose: function dispose() {
2108
+ disposed = true;
1759
2109
  unsubscribe();
1760
2110
  visibility.dispose();
1761
2111
  if (overlay) overlay.dispose();
1762
2112
  controller.dispose();
1763
2113
  root.remove();
1764
- }
2114
+ },
2115
+ textRatio: merged.textRatio,
2116
+ cssVars: merged.cssVars,
2117
+ dirty: dirty
1765
2118
  };
1766
2119
  }
1767
2120