@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/vue3.cjs CHANGED
@@ -150,6 +150,9 @@ function _objectSpread2(e) {
150
150
  }
151
151
  return e;
152
152
  }
153
+ function _readOnlyError(r) {
154
+ throw new TypeError('"' + r + '" is read-only');
155
+ }
153
156
  function _slicedToArray(r, e) {
154
157
  return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
155
158
  }
@@ -433,7 +436,7 @@ var DEFAULTS = {
433
436
  renderer: 'auto',
434
437
  respectReducedMotion: true,
435
438
  mouseColor: true,
436
- showCopy: true
439
+ textRatio: 39
437
440
  },
438
441
  progress: {
439
442
  width: 454,
@@ -442,35 +445,242 @@ var DEFAULTS = {
442
445
  max: 100,
443
446
  draggable: true,
444
447
  keyboard: true,
448
+ disabled: false,
449
+ valueSuffix: '%',
445
450
  edgeStyle: 'flow',
446
451
  quality: 'auto',
447
452
  renderer: 'auto',
448
- showCopy: true,
453
+ textRatio: 54,
454
+ showValue: true,
449
455
  respectReducedMotion: true
450
456
  }
451
457
  };
452
458
 
453
- /**
454
- * All user-facing copy lives here so wording/brand changes never require a
455
- * global search. Templates use {brand} {code} {name} placeholders.
459
+ /**
460
+ * Internal accessibility labels and small UI text. Since the copy API was
461
+ * removed (slots own the text area), these are no longer user-overridable.
462
+ * Templates use {brand} {code} {name} placeholders.
456
463
  */
457
464
  var COPY = {
458
465
  brandName: '画境观屿',
459
- dragLabel: 'DRAG',
460
466
  valueSuffix: '%',
461
467
  progressAria: '{brand} {code} 加载进度',
462
468
  capsuleAria: '打开 {name} 沉浸预览'
463
469
  };
464
470
 
465
- function hexToRgb01$1(hex) {
466
- var normalized = hex.replace('#', '');
467
- var value = Number.parseInt(normalized, 16);
471
+ /**
472
+ * Color helpers. `normalizeColor` converts any supported CSS color
473
+ * (hex / named / rgb() / rgba()) into a 6-digit hex string, so renderers can
474
+ * keep working with #rrggbb only. rgba() alpha is intentionally dropped:
475
+ * the WebGL shader has no per-color alpha channel, and the component is
476
+ * opaque by design — use component-level `opacity` for transparency.
477
+ */
478
+
479
+ var NAMED_COLORS = {
480
+ aliceblue: '#f0f8ff',
481
+ antiquewhite: '#faebd7',
482
+ aqua: '#00ffff',
483
+ aquamarine: '#7fffd4',
484
+ azure: '#f0ffff',
485
+ beige: '#f5f5dc',
486
+ bisque: '#ffe4c4',
487
+ black: '#000000',
488
+ blanchedalmond: '#ffebcd',
489
+ blue: '#0000ff',
490
+ blueviolet: '#8a2be2',
491
+ brown: '#a52a2a',
492
+ burlywood: '#deb887',
493
+ cadetblue: '#5f9ea0',
494
+ chartreuse: '#7fff00',
495
+ chocolate: '#d2691e',
496
+ coral: '#ff7f50',
497
+ cornflowerblue: '#6495ed',
498
+ cornsilk: '#fff8dc',
499
+ crimson: '#dc143c',
500
+ cyan: '#00ffff',
501
+ darkblue: '#00008b',
502
+ darkcyan: '#008b8b',
503
+ darkgoldenrod: '#b8860b',
504
+ darkgray: '#a9a9a9',
505
+ darkgreen: '#006400',
506
+ darkgrey: '#a9a9a9',
507
+ darkkhaki: '#bdb76b',
508
+ darkmagenta: '#8b008b',
509
+ darkolivegreen: '#556b2f',
510
+ darkorange: '#ff8c00',
511
+ darkorchid: '#9932cc',
512
+ darkred: '#8b0000',
513
+ darksalmon: '#e9967a',
514
+ darkseagreen: '#8fbc8f',
515
+ darkslateblue: '#483d8b',
516
+ darkslategray: '#2f4f4f',
517
+ darkslategrey: '#2f4f4f',
518
+ darkturquoise: '#00ced1',
519
+ darkviolet: '#9400d3',
520
+ deeppink: '#ff1493',
521
+ deepskyblue: '#00bfff',
522
+ dimgray: '#696969',
523
+ dimgrey: '#696969',
524
+ dodgerblue: '#1e90ff',
525
+ firebrick: '#b22222',
526
+ floralwhite: '#fffaf0',
527
+ forestgreen: '#228b22',
528
+ fuchsia: '#ff00ff',
529
+ gainsboro: '#dcdcdc',
530
+ ghostwhite: '#f8f8ff',
531
+ gold: '#ffd700',
532
+ goldenrod: '#daa520',
533
+ gray: '#808080',
534
+ green: '#008000',
535
+ greenyellow: '#adff2f',
536
+ grey: '#808080',
537
+ honeydew: '#f0fff0',
538
+ hotpink: '#ff69b4',
539
+ indianred: '#cd5c5c',
540
+ indigo: '#4b0082',
541
+ ivory: '#fffff0',
542
+ khaki: '#f0e68c',
543
+ lavender: '#e6e6fa',
544
+ lavenderblush: '#fff0f5',
545
+ lawngreen: '#7cfc00',
546
+ lemonchiffon: '#fffacd',
547
+ lightblue: '#add8e6',
548
+ lightcoral: '#f08080',
549
+ lightcyan: '#e0ffff',
550
+ lightgoldenrodyellow: '#fafad2',
551
+ lightgray: '#d3d3d3',
552
+ lightgreen: '#90ee90',
553
+ lightgrey: '#d3d3d3',
554
+ lightpink: '#ffb6c1',
555
+ lightsalmon: '#ffa07a',
556
+ lightseagreen: '#20b2aa',
557
+ lightskyblue: '#87cefa',
558
+ lightslategray: '#778899',
559
+ lightslategrey: '#778899',
560
+ lightsteelblue: '#b0c4de',
561
+ lightyellow: '#ffffe0',
562
+ lime: '#00ff00',
563
+ limegreen: '#32cd32',
564
+ linen: '#faf0e6',
565
+ magenta: '#ff00ff',
566
+ maroon: '#800000',
567
+ mediumaquamarine: '#66cdaa',
568
+ mediumblue: '#0000cd',
569
+ mediumorchid: '#ba55d3',
570
+ mediumpurple: '#9370db',
571
+ mediumseagreen: '#3cb371',
572
+ mediumslateblue: '#7b68ee',
573
+ mediumspringgreen: '#00fa9a',
574
+ mediumturquoise: '#48d1cc',
575
+ mediumvioletred: '#c71585',
576
+ midnightblue: '#191970',
577
+ mintcream: '#f5fffa',
578
+ mistyrose: '#ffe4e1',
579
+ moccasin: '#ffe4b5',
580
+ navajowhite: '#ffdead',
581
+ navy: '#000080',
582
+ oldlace: '#fdf5e6',
583
+ olive: '#808000',
584
+ olivedrab: '#6b8e23',
585
+ orange: '#ffa500',
586
+ orangered: '#ff4500',
587
+ orchid: '#da70d6',
588
+ palegoldenrod: '#eee8aa',
589
+ palegreen: '#98fb98',
590
+ paleturquoise: '#afeeee',
591
+ palevioletred: '#db7093',
592
+ papayawhip: '#ffefd5',
593
+ peachpuff: '#ffdab9',
594
+ peru: '#cd853f',
595
+ pink: '#ffc0cb',
596
+ plum: '#dda0dd',
597
+ powderblue: '#b0e0e6',
598
+ purple: '#800080',
599
+ rebeccapurple: '#663399',
600
+ red: '#ff0000',
601
+ rosybrown: '#bc8f8f',
602
+ royalblue: '#4169e1',
603
+ saddlebrown: '#8b4513',
604
+ salmon: '#fa8072',
605
+ sandybrown: '#f4a460',
606
+ seagreen: '#2e8b57',
607
+ seashell: '#fff5ee',
608
+ sienna: '#a0522d',
609
+ silver: '#c0c0c0',
610
+ skyblue: '#87ceeb',
611
+ slateblue: '#6a5acd',
612
+ slategray: '#708090',
613
+ slategrey: '#708090',
614
+ snow: '#fffafa',
615
+ springgreen: '#00ff7f',
616
+ steelblue: '#4682b4',
617
+ tan: '#d2b48c',
618
+ teal: '#008080',
619
+ thistle: '#d8bfd8',
620
+ tomato: '#ff6347',
621
+ turquoise: '#40e0d0',
622
+ violet: '#ee82ee',
623
+ wheat: '#f5deb3',
624
+ white: '#ffffff',
625
+ whitesmoke: '#f5f5f5',
626
+ yellow: '#ffff00',
627
+ yellowgreen: '#9acd32'
628
+ };
629
+ function clampChannel(value) {
630
+ return Math.min(255, Math.max(0, Math.round(value)));
631
+ }
632
+ function normalizeRgbArgs(args) {
633
+ var parts = args.split(/[,\s/]+/).filter(Boolean);
634
+ if (parts.length < 3) return null;
635
+ var to255 = function to255(value) {
636
+ if (typeof value !== 'string' || !value) return null;
637
+ if (value.endsWith('%')) return clampChannel(parseFloat(value) / 100 * 255);
638
+ var number = Number(value);
639
+ return Number.isFinite(number) ? clampChannel(number) : null;
640
+ };
641
+ var red = to255(parts[0]);
642
+ var green = to255(parts[1]);
643
+ var blue = to255(parts[2]);
644
+ if (red === null || green === null || blue === null) return null;
645
+ return "#".concat([red, green, blue].map(function (n) {
646
+ return n.toString(16).padStart(2, '0');
647
+ }).join(''));
648
+ }
649
+
650
+ /**
651
+ * Convert any supported CSS color into `#rrggbb`. Returns null when the
652
+ * value cannot be parsed. Supports: #rgb / #rrggbb (case-insensitive),
653
+ * CSS named colors, rgb() / rgba() with comma or modern space syntax,
654
+ * including percentages. Alpha in rgba() is ignored.
655
+ */
656
+ function normalizeColor(value) {
657
+ if (typeof value !== 'string') return null;
658
+ var input = value.trim();
659
+ if (!input) return null;
660
+ var lower = input.toLowerCase();
661
+ if (NAMED_COLORS[lower]) return NAMED_COLORS[lower];
662
+ if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(input)) {
663
+ var hex = input.slice(1).toLowerCase();
664
+ if (hex.length === 3) return "#".concat(hex.split('').map(function (c) {
665
+ return c + c;
666
+ }).join(''));
667
+ return "#".concat(hex);
668
+ }
669
+ var match = input.match(/^rgba?\((.*)\)$/i);
670
+ if (match) return normalizeRgbArgs(match[1]);
671
+ return null;
672
+ }
673
+ function hexToRgb01$1(color) {
674
+ var hex = normalizeColor(color);
675
+ if (!hex) return [0, 0, 0];
676
+ var value = Number.parseInt(hex.slice(1), 16);
468
677
  return [(value >> 16 & 255) / 255, (value >> 8 & 255) / 255, (value & 255) / 255];
469
678
  }
470
- function hexToRgba(hex) {
679
+ function hexToRgba(color) {
471
680
  var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
472
- var normalized = hex.replace('#', '');
473
- var value = Number.parseInt(normalized, 16);
681
+ var hex = normalizeColor(color);
682
+ if (!hex) return 'rgba(0, 0, 0, 0)';
683
+ var value = Number.parseInt(hex.slice(1), 16);
474
684
  var red = value >> 16 & 255;
475
685
  var green = value >> 8 & 255;
476
686
  var blue = value & 255;
@@ -551,6 +761,26 @@ var CosmicRenderer = /*#__PURE__*/function () {
551
761
  this.options.dprCap = cap;
552
762
  this.resize();
553
763
  }
764
+ }, {
765
+ key: "setMouseColor",
766
+ value: function setMouseColor(enabled) {
767
+ this.options.mouseColor = enabled !== false;
768
+ if (this.options.mouseColor) {
769
+ if (this.onPointerMove) return this;
770
+ _assertClassBrand(_CosmicRenderer_brand, this, _bindEvents).call(this);
771
+ return this;
772
+ }
773
+ if (this.onPointerMove) {
774
+ var target = this.eventTarget;
775
+ target.removeEventListener('pointermove', this.onPointerMove);
776
+ target.removeEventListener('pointerdown', this.onPointerMove);
777
+ target.removeEventListener('pointerleave', this.onPointerLeave);
778
+ this.onPointerMove = null;
779
+ this.onPointerLeave = null;
780
+ }
781
+ this.motionTarget = 0;
782
+ return this;
783
+ }
554
784
  }, {
555
785
  key: "randomize",
556
786
  value: function randomize() {
@@ -699,6 +929,8 @@ var FallbackRenderer = /*#__PURE__*/function () {
699
929
  var _this$canvas = this.canvas,
700
930
  width = _this$canvas.width,
701
931
  height = _this$canvas.height;
932
+ var t = time * (this.preset.speed || 1);
933
+ var phase = (this.preset.seed || 0) * 0.7;
702
934
  var gradient = ctx.createLinearGradient(0, 0, width, height);
703
935
  gradient.addColorStop(0, this.preset.colors[0]);
704
936
  gradient.addColorStop(0.38, this.preset.colors[1]);
@@ -708,8 +940,8 @@ var FallbackRenderer = /*#__PURE__*/function () {
708
940
  ctx.fillRect(0, 0, width, height);
709
941
  ctx.globalCompositeOperation = 'screen';
710
942
  for (var index = 0; index < 6; index += 1) {
711
- var x = (0.5 + 0.45 * Math.sin(time * 0.32 + index * 1.7)) * width;
712
- var y = (0.5 + 0.4 * Math.cos(time * 0.25 + index)) * height;
943
+ var x = (0.5 + 0.45 * Math.sin(t * 0.32 + index * 1.7 + phase)) * width;
944
+ var y = (0.5 + 0.4 * Math.cos(t * 0.25 + index + phase)) * height;
713
945
  var radius = Math.max(width, height) * (0.08 + index % 3 * 0.04);
714
946
  var glow = ctx.createRadialGradient(x, y, 0, x, y, radius);
715
947
  glow.addColorStop(0, rgb(this.preset.colors[(index + 1) % 4], 0.24));
@@ -733,7 +965,12 @@ var FallbackRenderer = /*#__PURE__*/function () {
733
965
  }
734
966
  }, {
735
967
  key: "randomize",
736
- value: function randomize() {}
968
+ value: function randomize() {
969
+ if (this.preset) this.preset.seed = Math.random() * 100;
970
+ }
971
+ }, {
972
+ key: "setMouseColor",
973
+ value: function setMouseColor() {}
737
974
  }, {
738
975
  key: "dispose",
739
976
  value: function dispose() {}
@@ -844,16 +1081,34 @@ function createVisibilityGuard(element) {
844
1081
  };
845
1082
  }
846
1083
 
847
- function prefersReducedMotion$1() {
1084
+ /**
1085
+ * Run a callback asynchronously, right after the current task and before the
1086
+ * next paint. Used for mount-time events (ready / error) so listeners that
1087
+ * are attached after create() still receive them. Falls back for legacy
1088
+ * browsers that lack queueMicrotask / Promise.
1089
+ */
1090
+ function nextTick(fn) {
1091
+ if (typeof queueMicrotask === 'function') {
1092
+ queueMicrotask(fn);
1093
+ } else if (typeof Promise !== 'undefined' && typeof Promise.resolve === 'function') {
1094
+ Promise.resolve().then(fn);
1095
+ } else {
1096
+ setTimeout(fn, 0);
1097
+ }
1098
+ }
1099
+
1100
+ function prefersReducedMotion$2() {
848
1101
  return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
849
1102
  }
850
1103
 
851
1104
  /**
852
- * Mount a cosmic (nebula) capsule into `container`.
853
- *
854
- * Options: preset (id/code/name or object), width, height (number=px or
855
- * string with px/%/vw/vh/em/rem), colors, seed, speed, quality,
856
- * respectReducedMotion, copy, cssVars.
1105
+ * Mount a cosmic (nebula) capsule into `container`.
1106
+ *
1107
+ * Options: preset (literary name), width, height (number=px or string with
1108
+ * px/%/vw/vh/em/rem), colors, seed, speed, textRatio (0-100, text region
1109
+ * width in percent), text (HTML string or DOM nodes for the text slot),
1110
+ * colorContent (HTML string or DOM nodes for the color slot), quality,
1111
+ * renderer, respectReducedMotion, mouseColor, cssVars.
857
1112
  */
858
1113
  function createCapsule(container) {
859
1114
  var _options$preset;
@@ -863,51 +1118,71 @@ function createCapsule(container) {
863
1118
  }
864
1119
  var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '初光'));
865
1120
  var merged = normalizeOptions(DEFAULTS.capsule, preset, options);
866
- var copy = _objectSpread2(_objectSpread2({}, COPY), merged.copy || {});
1121
+ var normalizedColors = merged.colors.map(normalizeColor);
1122
+ if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
1123
+ preset.seed = merged.seed;
1124
+ preset.speed = merged.speed;
1125
+ var customLabel = typeof options.label === 'string' && options.label ? options.label : null;
867
1126
  var root = document.createElement('div');
868
1127
  root.className = 'hj-capsule-root hj-capsule-cosmic';
869
1128
  root.dataset.group = preset.group;
870
1129
  root.dataset.mode = 'nebula';
871
1130
  root.dataset.theme = preset.theme || 'light';
872
- root.setAttribute('aria-label', copy.capsuleAria.replace('{name}', preset.name));
873
- var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
874
- var copyText = function copyText(key, fallback) {
875
- var value = copy[key];
876
- return value === undefined ? fallback : value;
1131
+ root.setAttribute('role', 'img');
1132
+ var updateAria = function updateAria() {
1133
+ root.setAttribute('aria-label', customLabel || COPY.capsuleAria.replace('{name}', preset.name));
877
1134
  };
878
- function buildCopyHtml() {
879
- var codeText = copyText('code', preset.code);
880
- var nameText = copyText('name', preset.name);
881
- var subtitleText = copyText('subtitle', preset.subtitle);
882
- var stateText = copyText('state', 'LIVE COSMIC STUDY');
883
- var html = '';
884
- if (codeText) html += "<span class=\"hj-capsule-code\">".concat(codeText, "</span>");
885
- if (nameText) html += "<span class=\"hj-capsule-name\">".concat(nameText, "</span>");
886
- if (subtitleText) html += "<span class=\"hj-capsule-brand\">".concat(subtitleText, "</span>");
887
- if (stateText) html += "<span class=\"hj-capsule-state\">".concat(stateText, "</span>");
888
- return html;
889
- }
890
- var copyLayer = document.createElement('div');
891
- copyLayer.className = 'hj-capsule-copy';
892
- var renderCopy = function renderCopy() {
893
- if (copyEnabled) copyLayer.innerHTML = buildCopyHtml();
894
- };
895
- renderCopy();
896
- var isHexColor = function isHexColor(value) {
897
- return typeof value === 'string' && /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(value);
1135
+ updateAria();
1136
+
1137
+ // Slot containers are always present but transparent by default: without
1138
+ // content they are invisible, so "no slot" behaves like the old
1139
+ // showCopy=false. They only provide geometry — no typography, padding or
1140
+ // background is imposed on user content (see docs: 插槽 CSS 约定).
1141
+ var fillContent = function fillContent(layer, content) {
1142
+ layer.innerHTML = '';
1143
+ if (content == null) return;
1144
+ if (typeof content === 'string') {
1145
+ layer.innerHTML = content;
1146
+ return;
1147
+ }
1148
+ var nodes = Array.isArray(content) ? content : [content];
1149
+ var _iterator = _createForOfIteratorHelper(nodes),
1150
+ _step;
1151
+ try {
1152
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
1153
+ var node = _step.value;
1154
+ if (node && typeof node.nodeType === 'number') layer.appendChild(node);
1155
+ }
1156
+ } catch (err) {
1157
+ _iterator.e(err);
1158
+ } finally {
1159
+ _iterator.f();
1160
+ }
898
1161
  };
899
- if (copy.background) {
900
- root.style.setProperty('--hj-copy-bg', isHexColor(copy.background) ? "linear-gradient(90deg, ".concat(copy.background, " 0%, ").concat(copy.background, " 74%, ").concat(hexToRgba(copy.background, 0.97), " 84%, ").concat(hexToRgba(copy.background, 0), " 100%)") : copy.background);
901
- }
902
- if (copy.color) root.style.setProperty('--hj-copy-color', copy.color);
1162
+ var textLayer = document.createElement('div');
1163
+ textLayer.className = 'hj-capsule-text hj-capsule-copy';
1164
+ var visualLayer = document.createElement('div');
1165
+ visualLayer.className = 'hj-capsule-visual';
1166
+ fillContent(textLayer, options.text);
1167
+ fillContent(visualLayer, options.colorContent);
903
1168
  var canvas = document.createElement('canvas');
904
1169
  canvas.className = 'hj-capsule-canvas';
905
1170
  canvas.setAttribute('aria-hidden', 'true');
906
- if (copyEnabled) root.appendChild(copyLayer);
1171
+ root.appendChild(textLayer);
1172
+ root.appendChild(visualLayer);
907
1173
  root.appendChild(canvas);
908
1174
  container.appendChild(root);
909
1175
  var emitter = createEmitter();
910
- var paused = merged.respectReducedMotion && prefersReducedMotion$1();
1176
+ var paused = merged.respectReducedMotion && prefersReducedMotion$2();
1177
+ var disposed = false;
1178
+ var dirty = {
1179
+ preset: false,
1180
+ seed: false,
1181
+ speed: false,
1182
+ colors: false,
1183
+ textRatio: false,
1184
+ cssVars: false
1185
+ };
911
1186
  var renderer;
912
1187
  var useWebgl = merged.renderer !== 'canvas2d';
913
1188
  if (useWebgl) {
@@ -917,8 +1192,11 @@ function createCapsule(container) {
917
1192
  });
918
1193
  } catch (error) {
919
1194
  renderer = new FallbackRenderer(canvas, merged);
920
- emitter.emit('error', {
921
- message: String(error && error.message ? error.message : error)
1195
+ nextTick(function () {
1196
+ if (disposed) return;
1197
+ emitter.emit('error', {
1198
+ message: String(error && error.message ? error.message : error)
1199
+ });
922
1200
  });
923
1201
  }
924
1202
  } else {
@@ -932,6 +1210,9 @@ function createCapsule(container) {
932
1210
  var name = _Object$keys[_i];
933
1211
  root.style.setProperty(name, vars[name]);
934
1212
  }
1213
+ if (merged.textRatio !== undefined) {
1214
+ root.style.setProperty('--hj-text-width', "".concat(merged.textRatio, "%"));
1215
+ }
935
1216
  renderer.resize();
936
1217
  };
937
1218
  applySize();
@@ -981,13 +1262,16 @@ function createCapsule(container) {
981
1262
  }, function () {
982
1263
  return paused;
983
1264
  });
984
- emitter.emit('ready', {
985
- preset: _objectSpread2({}, preset)
1265
+ nextTick(function () {
1266
+ if (disposed) return;
1267
+ emitter.emit('ready', {
1268
+ preset: _objectSpread2({}, preset)
1269
+ });
986
1270
  });
987
- var syncCopy = function syncCopy() {
1271
+ var syncTheme = function syncTheme() {
988
1272
  root.dataset.mode = 'nebula';
989
1273
  root.dataset.theme = preset.theme || 'light';
990
- renderCopy();
1274
+ updateAria();
991
1275
  };
992
1276
  return {
993
1277
  element: root,
@@ -997,9 +1281,12 @@ function createCapsule(container) {
997
1281
  off: emitter.off,
998
1282
  setPreset: function setPreset(ref) {
999
1283
  var next = getPreset('capsule', ref);
1284
+ dirty.preset = true;
1000
1285
  Object.assign(preset, next);
1001
- renderer.setPreset(next);
1002
- syncCopy();
1286
+ var nextColors = preset.colors.map(normalizeColor);
1287
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
1288
+ renderer.setPreset(_objectSpread2({}, preset));
1289
+ syncTheme();
1003
1290
  renderer.resize();
1004
1291
  emitter.emit('presetchange', {
1005
1292
  preset: _objectSpread2({}, next)
@@ -1007,16 +1294,21 @@ function createCapsule(container) {
1007
1294
  return this;
1008
1295
  },
1009
1296
  setColors: function setColors(colors) {
1010
- if (!Array.isArray(colors) || colors.length !== 4) return this;
1011
- preset.colors = colors;
1297
+ var next = Array.isArray(colors) ? colors.map(normalizeColor) : [];
1298
+ if (next.length !== 4 || next.some(function (color) {
1299
+ return !color;
1300
+ })) return this;
1301
+ dirty.colors = true;
1302
+ preset.colors = next;
1012
1303
  renderer.setPreset(_objectSpread2(_objectSpread2({}, preset), {}, {
1013
- colors: colors
1304
+ colors: next
1014
1305
  }));
1015
1306
  return this;
1016
1307
  },
1017
1308
  setSeed: function setSeed(seed) {
1018
1309
  var value = Number(seed);
1019
1310
  if (!Number.isFinite(value)) return this;
1311
+ dirty.seed = true;
1020
1312
  preset.seed = value;
1021
1313
  renderer.setPreset(_objectSpread2({}, preset));
1022
1314
  return this;
@@ -1024,10 +1316,42 @@ function createCapsule(container) {
1024
1316
  setSpeed: function setSpeed(speed) {
1025
1317
  var value = Number(speed);
1026
1318
  if (!Number.isFinite(value)) return this;
1319
+ dirty.speed = true;
1027
1320
  preset.speed = value;
1028
1321
  renderer.setPreset(_objectSpread2({}, preset));
1029
1322
  return this;
1030
1323
  },
1324
+ setText: function setText(content) {
1325
+ fillContent(textLayer, content);
1326
+ return this;
1327
+ },
1328
+ setColorContent: function setColorContent(content) {
1329
+ fillContent(visualLayer, content);
1330
+ return this;
1331
+ },
1332
+ setTextRatio: function setTextRatio(ratio) {
1333
+ var value = Number(ratio);
1334
+ if (!Number.isFinite(value) || value < 0 || value > 100) return this;
1335
+ dirty.textRatio = true;
1336
+ merged.textRatio = value;
1337
+ root.style.setProperty('--hj-text-width', "".concat(value, "%"));
1338
+ return this;
1339
+ },
1340
+ setCssVars: function setCssVars(vars) {
1341
+ if (!vars || _typeof(vars) !== 'object') return this;
1342
+ dirty.cssVars = true;
1343
+ merged.cssVars = _objectSpread2(_objectSpread2({}, merged.cssVars || {}), vars);
1344
+ for (var _i2 = 0, _Object$keys2 = Object.keys(vars); _i2 < _Object$keys2.length; _i2++) {
1345
+ var name = _Object$keys2[_i2];
1346
+ root.style.setProperty(name, vars[name]);
1347
+ }
1348
+ return this;
1349
+ },
1350
+ setLabel: function setLabel(label) {
1351
+ customLabel = typeof label === 'string' && label ? label : null;
1352
+ updateAria();
1353
+ return this;
1354
+ },
1031
1355
  setSize: function setSize(width, height) {
1032
1356
  if (width !== undefined) merged.width = width;
1033
1357
  if (height !== undefined) merged.height = height;
@@ -1035,7 +1359,7 @@ function createCapsule(container) {
1035
1359
  return this;
1036
1360
  },
1037
1361
  randomize: function randomize() {
1038
- renderer.randomize();
1362
+ this.setSeed(Math.random() * 100);
1039
1363
  return this;
1040
1364
  },
1041
1365
  pause: function pause() {
@@ -1052,12 +1376,16 @@ function createCapsule(container) {
1052
1376
  return this;
1053
1377
  },
1054
1378
  dispose: function dispose() {
1379
+ disposed = true;
1055
1380
  unsubscribe();
1056
1381
  visibility.dispose();
1057
1382
  if (resizeObserver) resizeObserver.disconnect();else window.removeEventListener('resize', renderer.resize);
1058
1383
  renderer.dispose();
1059
1384
  root.remove();
1060
- }
1385
+ },
1386
+ textRatio: merged.textRatio,
1387
+ cssVars: merged.cssVars,
1388
+ dirty: dirty
1061
1389
  };
1062
1390
  }
1063
1391
 
@@ -1499,7 +1827,7 @@ function interpolate(template, values) {
1499
1827
  return values[key] !== undefined ? values[key] : '';
1500
1828
  });
1501
1829
  }
1502
- function prefersReducedMotion() {
1830
+ function prefersReducedMotion$1() {
1503
1831
  return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
1504
1832
  }
1505
1833
  var FLOW_PROFILES = {
@@ -1561,7 +1889,8 @@ var FLOW_PROFILES = {
1561
1889
  };
1562
1890
  var ProgressCapsuleController = /*#__PURE__*/function () {
1563
1891
  function ProgressCapsuleController(_ref) {
1564
- var _options$min,
1892
+ var _options$valueSuffix,
1893
+ _options$min,
1565
1894
  _options$max,
1566
1895
  _options$value,
1567
1896
  _this = this;
@@ -1571,7 +1900,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1571
1900
  preset = _ref.preset,
1572
1901
  emitter = _ref.emitter,
1573
1902
  options = _ref.options,
1574
- copy = _ref.copy;
1903
+ copy = _ref.copy,
1904
+ dirty = _ref.dirty;
1575
1905
  _classCallCheck(this, ProgressCapsuleController);
1576
1906
  this.root = root;
1577
1907
  this.canvas = canvas;
@@ -1580,6 +1910,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1580
1910
  this.emitter = emitter;
1581
1911
  this.options = options;
1582
1912
  this.copy = copy;
1913
+ this.dirty = dirty;
1914
+ this.valueSuffix = (_options$valueSuffix = options.valueSuffix) !== null && _options$valueSuffix !== void 0 ? _options$valueSuffix : copy.valueSuffix;
1583
1915
  this.profile = preset.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
1584
1916
  this.min = (_options$min = options.min) !== null && _options$min !== void 0 ? _options$min : 0;
1585
1917
  this.max = (_options$max = options.max) !== null && _options$max !== void 0 ? _options$max : 100;
@@ -1619,12 +1951,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1619
1951
  var rounded = Math.round(this.value);
1620
1952
  this.root.style.setProperty('--progress', this.value.toFixed(2));
1621
1953
  this.root.setAttribute('aria-valuenow', String(rounded));
1622
- this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.copy.valueSuffix));
1623
- this.valueElement.textContent = "".concat(rounded).concat(this.copy.valueSuffix);
1624
- if (!this.suppressEvents) this.emitter.emit('change', {
1625
- value: this.value,
1626
- source: source
1627
- });
1954
+ this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.valueSuffix));
1955
+ if (this.valueElement) this.valueElement.textContent = "".concat(rounded).concat(this.valueSuffix);
1956
+ if (!this.suppressEvents) {
1957
+ if (this.dirty) this.dirty.value = true;
1958
+ this.emitter.emit('change', {
1959
+ value: this.value,
1960
+ source: source
1961
+ });
1962
+ }
1963
+ }
1964
+ }, {
1965
+ key: "setValueSuffix",
1966
+ value: function setValueSuffix(suffix) {
1967
+ this.valueSuffix = String(suffix == null ? '' : suffix);
1968
+ var rounded = Math.round(this.value);
1969
+ if (this.valueElement) this.valueElement.textContent = "".concat(rounded).concat(this.valueSuffix);
1970
+ this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.valueSuffix));
1971
+ return this;
1628
1972
  }
1629
1973
  }, {
1630
1974
  key: "resizeCanvas",
@@ -1799,7 +2143,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1799
2143
  var width = this.width;
1800
2144
  var height = this.height;
1801
2145
  if (!ctx || width <= 0 || height <= 0) return;
1802
- var shoreline = width * (this.value / 100);
2146
+ var range = Math.max(this.max - this.min, 1);
2147
+ var shoreline = width * Math.min(Math.max((this.value - this.min) / range, 0), 1);
1803
2148
  var time = this.flowTime;
1804
2149
  var _this$preset$colors = _slicedToArray(this.preset.colors, 4),
1805
2150
  dark = _this$preset$colors[0],
@@ -1914,7 +2259,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1914
2259
  value: function updateFromPointer(event) {
1915
2260
  var bounds = this.root.getBoundingClientRect();
1916
2261
  var ratio = bounds.width > 0 ? (event.clientX - bounds.left) / bounds.width : 0;
1917
- this.setProgress(ratio * 100, 'drag');
2262
+ this.setProgress(this.min + ratio * (this.max - this.min), 'drag');
1918
2263
  }
1919
2264
  }, {
1920
2265
  key: "beginDrag",
@@ -1922,6 +2267,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1922
2267
  if (event.button !== undefined && event.button !== 0) return;
1923
2268
  event.preventDefault();
1924
2269
  this.dragging = true;
2270
+ this.pendingPointer = null;
2271
+ this._dragRaf = 0;
1925
2272
  this.root.classList.add('is-dragging');
1926
2273
  try {
1927
2274
  var _this$root$setPointer, _this$root;
@@ -1935,15 +2282,31 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1935
2282
  }, {
1936
2283
  key: "moveDrag",
1937
2284
  value: function moveDrag(event) {
2285
+ var _this2 = this;
1938
2286
  if (!this.dragging) return;
1939
2287
  event.preventDefault();
1940
- this.updateFromPointer(event);
2288
+ // rAF 合并:一帧最多一次 setProgress/change,视觉仍每帧更新。
2289
+ this.pendingPointer = event;
2290
+ if (this._dragRaf) return;
2291
+ this._dragRaf = requestAnimationFrame(function () {
2292
+ _this2._dragRaf = 0;
2293
+ var pending = _this2.pendingPointer;
2294
+ _this2.pendingPointer = null;
2295
+ if (pending) _this2.updateFromPointer(pending);
2296
+ });
1941
2297
  }
1942
2298
  }, {
1943
2299
  key: "endDrag",
1944
2300
  value: function endDrag(event) {
1945
2301
  if (!this.dragging) return;
1946
2302
  this.dragging = false;
2303
+ if (this._dragRaf) {
2304
+ cancelAnimationFrame(this._dragRaf);
2305
+ this._dragRaf = 0;
2306
+ }
2307
+ var pending = this.pendingPointer;
2308
+ this.pendingPointer = null;
2309
+ if (pending) this.updateFromPointer(pending);
1947
2310
  this.root.classList.remove('is-dragging');
1948
2311
  try {
1949
2312
  var _this$root$hasPointer, _this$root2;
@@ -1958,19 +2321,19 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1958
2321
  }, {
1959
2322
  key: "bindEvents",
1960
2323
  value: function bindEvents() {
1961
- var _this2 = this;
2324
+ var _this3 = this;
1962
2325
  if (this.options.draggable !== false) {
1963
2326
  this.handlers.pointerdown = function (event) {
1964
- return _this2.beginDrag(event);
2327
+ return _this3.beginDrag(event);
1965
2328
  };
1966
2329
  this.handlers.pointermove = function (event) {
1967
- return _this2.moveDrag(event);
2330
+ return _this3.moveDrag(event);
1968
2331
  };
1969
2332
  this.handlers.pointerup = function (event) {
1970
- return _this2.endDrag(event);
2333
+ return _this3.endDrag(event);
1971
2334
  };
1972
2335
  this.handlers.pointercancel = function (event) {
1973
- return _this2.endDrag(event);
2336
+ return _this3.endDrag(event);
1974
2337
  };
1975
2338
  this.root.addEventListener('pointerdown', this.handlers.pointerdown);
1976
2339
  this.root.addEventListener('pointermove', this.handlers.pointermove);
@@ -1979,23 +2342,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1979
2342
  }
1980
2343
  if (this.options.keyboard !== false) {
1981
2344
  this.handlers.keydown = function (event) {
2345
+ var step = (_this3.max - _this3.min) * 0.02;
1982
2346
  var actions = {
1983
- ArrowLeft: -2,
1984
- ArrowDown: -2,
1985
- ArrowRight: 2,
1986
- ArrowUp: 2,
1987
- PageDown: -10,
1988
- PageUp: 10
2347
+ ArrowLeft: -step,
2348
+ ArrowDown: -step,
2349
+ ArrowRight: step,
2350
+ ArrowUp: step,
2351
+ PageDown: -step * 5,
2352
+ PageUp: step * 5
1989
2353
  };
1990
2354
  if (event.key === 'Home') {
1991
2355
  event.preventDefault();
1992
- _this2.setProgress(_this2.min, 'keyboard');
2356
+ _this3.setProgress(_this3.min, 'keyboard');
1993
2357
  } else if (event.key === 'End') {
1994
2358
  event.preventDefault();
1995
- _this2.setProgress(_this2.max, 'keyboard');
2359
+ _this3.setProgress(_this3.max, 'keyboard');
1996
2360
  } else if (actions[event.key]) {
1997
2361
  event.preventDefault();
1998
- _this2.setProgress(_this2.value + actions[event.key], 'keyboard');
2362
+ _this3.setProgress(_this3.value + actions[event.key], 'keyboard');
1999
2363
  } else {
2000
2364
  return;
2001
2365
  }
@@ -2032,6 +2396,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
2032
2396
  }, {
2033
2397
  key: "dispose",
2034
2398
  value: function dispose() {
2399
+ if (this._dragRaf) cancelAnimationFrame(this._dragRaf);
2035
2400
  if (this.resizeObserver) this.resizeObserver.disconnect();else window.removeEventListener('resize', this.resizeCanvas);
2036
2401
  for (var _i = 0, _Object$keys = Object.keys(this.handlers); _i < _Object$keys.length; _i++) {
2037
2402
  var name = _Object$keys[_i];
@@ -2044,11 +2409,14 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
2044
2409
  }();
2045
2410
 
2046
2411
  /**
2047
- * Mount a fluid progress capsule into `container`.
2048
- *
2049
- * Options: preset (id/code/name or object), width, height, value, min, max,
2050
- * draggable, keyboard, colors, edgeStyle, quality,
2051
- * respectReducedMotion, copy, cssVars.
2412
+ * Mount a fluid progress capsule into `container`.
2413
+ *
2414
+ * Options: preset (id/code/name or object), width, height, value, min, max,
2415
+ * draggable, keyboard, colors, edgeStyle, textRatio (0-100, text region
2416
+ * width in percent), text (HTML string or DOM nodes for the text slot),
2417
+ * colorContent (HTML string or DOM nodes for the color slot),
2418
+ * showValue (show/hide the right-side percentage), quality,
2419
+ * respectReducedMotion, cssVars.
2052
2420
  */
2053
2421
  function createProgressCapsule(container) {
2054
2422
  var _options$preset, _merged$min, _merged$max;
@@ -2058,62 +2426,91 @@ function createProgressCapsule(container) {
2058
2426
  }
2059
2427
  var preset = _objectSpread2({}, getPreset('progress', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '星火'));
2060
2428
  var merged = normalizeOptions(DEFAULTS.progress, preset, options);
2061
- var copy = _objectSpread2(_objectSpread2({}, COPY), merged.copy || {});
2429
+ var normalizedColors = merged.colors.map(normalizeColor);
2430
+ if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
2431
+ preset.edgeStyle = merged.edgeStyle;
2432
+ var copy = COPY;
2433
+ var customLabel = typeof options.label === 'string' && options.label ? options.label : null;
2434
+ // Vue 的裸布尔属性(<ProgressCapsule disabled />)会传成空字符串,
2435
+ // 这里统一按 true 处理。
2436
+ var disabled = merged.disabled === true || merged.disabled === '' || merged.disabled === 'true';
2437
+ var effectiveDraggable = disabled ? false : merged.draggable !== false;
2438
+ var effectiveKeyboard = disabled ? false : merged.keyboard !== false;
2439
+ var dirty = {
2440
+ preset: false,
2441
+ colors: false,
2442
+ textRatio: false,
2443
+ cssVars: false,
2444
+ edgeStyle: false,
2445
+ value: false
2446
+ };
2062
2447
  var root = document.createElement('div');
2063
2448
  root.className = 'hj-capsule-root hj-progress-root';
2064
2449
  root.setAttribute('role', 'slider');
2065
2450
  root.setAttribute('tabindex', '0');
2066
- root.setAttribute('data-draggable', String(merged.draggable !== false));
2451
+ root.setAttribute('data-draggable', String(effectiveDraggable));
2452
+ if (disabled) {
2453
+ root.setAttribute('aria-disabled', 'true');
2454
+ root.classList.add('is-disabled');
2455
+ }
2067
2456
  root.setAttribute('aria-valuemin', String((_merged$min = merged.min) !== null && _merged$min !== void 0 ? _merged$min : 0));
2068
2457
  root.setAttribute('aria-valuemax', String((_merged$max = merged.max) !== null && _merged$max !== void 0 ? _merged$max : 100));
2069
2458
  root.setAttribute('aria-valuenow', String(preset.initialProgress));
2070
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
2071
- brand: copy.brandName,
2072
- code: preset.code,
2073
- name: preset.name
2074
- }));
2075
- if (merged.keyboard === false) root.setAttribute('tabindex', '-1');
2459
+ var updateAria = function updateAria() {
2460
+ root.setAttribute('aria-label', customLabel || interpolate(copy.progressAria, {
2461
+ brand: copy.brandName,
2462
+ code: preset.code,
2463
+ name: preset.name
2464
+ }));
2465
+ };
2466
+ updateAria();
2467
+ if (!effectiveKeyboard) root.setAttribute('tabindex', '-1');
2076
2468
  var canvas = document.createElement('canvas');
2077
2469
  canvas.className = 'hj-progress-canvas';
2078
2470
  canvas.setAttribute('aria-hidden', 'true');
2079
- var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
2080
- var copyText = function copyText(key, fallback) {
2081
- var value = copy[key];
2082
- return value === undefined ? fallback : value;
2083
- };
2084
- function buildCopyHtml() {
2085
- var html = '';
2086
- var brandText = copy.brandName || '';
2087
- var subtitleText = copyText('subtitle', preset.subtitle);
2088
- if (brandText) html += "<span class=\"hj-progress-name\">".concat(brandText, "</span>");
2089
- if (subtitleText) html += "<span class=\"hj-progress-subtitle\">".concat(subtitleText, "</span>");
2090
- return html;
2091
- }
2092
- var copyLayer = document.createElement('div');
2093
- copyLayer.className = 'hj-progress-copy';
2094
- var renderCopy = function renderCopy() {
2095
- if (copyEnabled) copyLayer.innerHTML = buildCopyHtml();
2471
+
2472
+ // Slot containers are always present but transparent by default; they only
2473
+ // provide geometry, never typography/padding/background (docs: 插槽 CSS 约定).
2474
+ var fillContent = function fillContent(layer, content) {
2475
+ layer.innerHTML = '';
2476
+ if (content == null) return;
2477
+ if (typeof content === 'string') {
2478
+ layer.innerHTML = content;
2479
+ return;
2480
+ }
2481
+ var nodes = Array.isArray(content) ? content : [content];
2482
+ var _iterator2 = _createForOfIteratorHelper(nodes),
2483
+ _step2;
2484
+ try {
2485
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
2486
+ var node = _step2.value;
2487
+ if (node && typeof node.nodeType === 'number') layer.appendChild(node);
2488
+ }
2489
+ } catch (err) {
2490
+ _iterator2.e(err);
2491
+ } finally {
2492
+ _iterator2.f();
2493
+ }
2096
2494
  };
2097
- renderCopy();
2098
- if (copy.background) {
2099
- root.style.setProperty('--hj-progress-copy-bg', copy.background);
2100
- root.style.setProperty('--hj-progress-copy-pad', '6px 12px');
2495
+ var textLayer = document.createElement('div');
2496
+ textLayer.className = 'hj-progress-text hj-progress-copy';
2497
+ var visualLayer = document.createElement('div');
2498
+ visualLayer.className = 'hj-progress-visual';
2499
+ fillContent(textLayer, options.text);
2500
+ fillContent(visualLayer, options.colorContent);
2501
+ var valueElement = merged.showValue === false ? null : document.createElement('div');
2502
+ if (valueElement) {
2503
+ valueElement.className = 'hj-progress-value';
2504
+ valueElement.setAttribute('aria-hidden', 'true');
2101
2505
  }
2102
- if (copy.color) root.style.setProperty('--hj-progress-copy-color', copy.color);
2103
- var valueElement = document.createElement('div');
2104
- valueElement.className = 'hj-progress-value';
2105
- valueElement.setAttribute('aria-hidden', 'true');
2106
- var dragLabel = document.createElement('span');
2107
- dragLabel.className = 'hj-progress-drag-label';
2108
- dragLabel.setAttribute('aria-hidden', 'true');
2109
- dragLabel.textContent = copy.dragLabel;
2110
2506
  root.appendChild(canvas);
2111
- if (copyEnabled) root.appendChild(copyLayer);
2112
- root.appendChild(valueElement);
2113
- root.appendChild(dragLabel);
2507
+ root.appendChild(textLayer);
2508
+ root.appendChild(visualLayer);
2509
+ if (valueElement) root.appendChild(valueElement);
2114
2510
  container.appendChild(root);
2115
2511
  var emitter = createEmitter();
2116
- var paused = merged.respectReducedMotion && prefersReducedMotion();
2512
+ var paused = merged.respectReducedMotion && prefersReducedMotion$1();
2513
+ var disposed = false;
2117
2514
  var applySize = function applySize() {
2118
2515
  root.style.width = parseSize(merged.width);
2119
2516
  root.style.height = parseSize(merged.height);
@@ -2122,6 +2519,9 @@ function createProgressCapsule(container) {
2122
2519
  var name = _Object$keys2[_i2];
2123
2520
  root.style.setProperty(name, vars[name]);
2124
2521
  }
2522
+ if (merged.textRatio !== undefined) {
2523
+ root.style.setProperty('--hj-text-width', "".concat(merged.textRatio, "%"));
2524
+ }
2125
2525
  };
2126
2526
  applySize();
2127
2527
  var controller = new ProgressCapsuleController({
@@ -2130,8 +2530,12 @@ function createProgressCapsule(container) {
2130
2530
  valueElement: valueElement,
2131
2531
  preset: preset,
2132
2532
  emitter: emitter,
2133
- options: merged,
2134
- copy: copy
2533
+ options: _objectSpread2(_objectSpread2({}, merged), {}, {
2534
+ draggable: effectiveDraggable,
2535
+ keyboard: effectiveKeyboard
2536
+ }),
2537
+ copy: copy,
2538
+ dirty: dirty
2135
2539
  });
2136
2540
  var overlay = null;
2137
2541
  if (merged.renderer !== 'canvas2d') {
@@ -2144,7 +2548,14 @@ function createProgressCapsule(container) {
2144
2548
  }
2145
2549
  });
2146
2550
  }
2147
- if (overlay) controller.webglActive = true;
2551
+ if (overlay) controller.webglActive = true;else if (merged.renderer !== 'canvas2d') {
2552
+ nextTick(function () {
2553
+ if (disposed) return;
2554
+ emitter.emit('error', {
2555
+ message: 'WebGL2 unavailable, using Canvas2D fallback'
2556
+ });
2557
+ });
2558
+ }
2148
2559
  var visibility = createVisibilityGuard(root);
2149
2560
  var flowTime = 0;
2150
2561
  var unsubscribe = subscribeScheduler(function (delta, now) {
@@ -2157,16 +2568,14 @@ function createProgressCapsule(container) {
2157
2568
  }, function () {
2158
2569
  return paused;
2159
2570
  });
2160
- emitter.emit('ready', {
2161
- preset: _objectSpread2({}, preset)
2571
+ nextTick(function () {
2572
+ if (disposed) return;
2573
+ emitter.emit('ready', {
2574
+ preset: _objectSpread2({}, preset)
2575
+ });
2162
2576
  });
2163
2577
  var syncDom = function syncDom() {
2164
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
2165
- brand: copy.brandName,
2166
- code: preset.code,
2167
- name: preset.name
2168
- }));
2169
- renderCopy();
2578
+ updateAria();
2170
2579
  };
2171
2580
  return {
2172
2581
  element: root,
@@ -2188,8 +2597,11 @@ function createProgressCapsule(container) {
2188
2597
  },
2189
2598
  setPreset: function setPreset(ref) {
2190
2599
  var next = getPreset('progress', ref);
2600
+ dirty.preset = true;
2191
2601
  Object.assign(preset, next);
2192
- controller.preset = next;
2602
+ var nextColors = preset.colors.map(normalizeColor);
2603
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
2604
+ controller.preset = preset;
2193
2605
  controller.profile = next.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[next.id] || FLOW_PROFILES['visual-training'];
2194
2606
  controller.flowTime = stringSeed(next.id) * 31;
2195
2607
  controller.seed = stringSeed("".concat(next.id, "-reference")) * Math.PI * 2;
@@ -2199,7 +2611,7 @@ function createProgressCapsule(container) {
2199
2611
  overlay = attachProgressFlowOverlay({
2200
2612
  root: root,
2201
2613
  canvas: canvas,
2202
- preset: next,
2614
+ preset: preset,
2203
2615
  getProgress: function getProgress() {
2204
2616
  return controller.value;
2205
2617
  }
@@ -2208,13 +2620,14 @@ function createProgressCapsule(container) {
2208
2620
  controller.webglActive = Boolean(overlay);
2209
2621
  controller.resizeCanvas();
2210
2622
  emitter.emit('presetchange', {
2211
- preset: _objectSpread2({}, next)
2623
+ preset: _objectSpread2({}, preset)
2212
2624
  });
2213
2625
  return this;
2214
2626
  },
2215
2627
  setEdgeStyle: function setEdgeStyle(edgeStyle) {
2216
2628
  var value = String(edgeStyle || '').toLowerCase();
2217
2629
  if (value !== 'flow' && value !== 'tide') return this;
2630
+ dirty.edgeStyle = true;
2218
2631
  preset.edgeStyle = value;
2219
2632
  controller.profile = value === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
2220
2633
  if (overlay) {
@@ -2232,10 +2645,49 @@ function createProgressCapsule(container) {
2232
2645
  controller.resizeCanvas();
2233
2646
  return this;
2234
2647
  },
2648
+ setText: function setText(content) {
2649
+ fillContent(textLayer, content);
2650
+ return this;
2651
+ },
2652
+ setColorContent: function setColorContent(content) {
2653
+ fillContent(visualLayer, content);
2654
+ return this;
2655
+ },
2656
+ setTextRatio: function setTextRatio(ratio) {
2657
+ var value = Number(ratio);
2658
+ if (!Number.isFinite(value) || value < 0 || value > 100) return this;
2659
+ dirty.textRatio = true;
2660
+ merged.textRatio = value;
2661
+ root.style.setProperty('--hj-text-width', "".concat(value, "%"));
2662
+ return this;
2663
+ },
2664
+ setCssVars: function setCssVars(vars) {
2665
+ if (!vars || _typeof(vars) !== 'object') return this;
2666
+ dirty.cssVars = true;
2667
+ merged.cssVars = _objectSpread2(_objectSpread2({}, merged.cssVars || {}), vars);
2668
+ for (var _i3 = 0, _Object$keys3 = Object.keys(vars); _i3 < _Object$keys3.length; _i3++) {
2669
+ var name = _Object$keys3[_i3];
2670
+ root.style.setProperty(name, vars[name]);
2671
+ }
2672
+ return this;
2673
+ },
2674
+ setLabel: function setLabel(label) {
2675
+ _readOnlyError("customLabel");
2676
+ updateAria();
2677
+ return this;
2678
+ },
2679
+ setValueSuffix: function setValueSuffix(suffix) {
2680
+ controller.setValueSuffix(suffix);
2681
+ return this;
2682
+ },
2235
2683
  setColors: function setColors(colors) {
2236
- if (!Array.isArray(colors) || colors.length !== 4) return this;
2237
- controller.setColors(colors);
2238
- if (overlay) overlay.setColors(colors);
2684
+ var next = Array.isArray(colors) ? colors.map(normalizeColor) : [];
2685
+ if (next.length !== 4 || next.some(function (color) {
2686
+ return !color;
2687
+ })) return this;
2688
+ dirty.colors = true;
2689
+ controller.setColors(next);
2690
+ if (overlay) overlay.setColors(next);
2239
2691
  controller.resizeCanvas();
2240
2692
  return this;
2241
2693
  },
@@ -2265,12 +2717,223 @@ function createProgressCapsule(container) {
2265
2717
  return this;
2266
2718
  },
2267
2719
  dispose: function dispose() {
2720
+ disposed = true;
2268
2721
  unsubscribe();
2269
2722
  visibility.dispose();
2270
2723
  if (overlay) overlay.dispose();
2271
2724
  controller.dispose();
2272
2725
  root.remove();
2726
+ },
2727
+ textRatio: merged.textRatio,
2728
+ cssVars: merged.cssVars,
2729
+ dirty: dirty
2730
+ };
2731
+ }
2732
+
2733
+ function prefersReducedMotion() {
2734
+ return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
2735
+ }
2736
+
2737
+ /**
2738
+ * Mount the cosmic (nebula) material as a background layer inside `host`.
2739
+ *
2740
+ * The layer is absolutely positioned and defaults to `z-index: -1`, so it
2741
+ * paints behind the host's in-flow content: text/buttons/images inside the
2742
+ * host sit on top with zero extra CSS. Host gets `position: relative;
2743
+ * isolation: isolate` automatically so the layer can never escape its box
2744
+ * (or break stacking outside it).
2745
+ *
2746
+ * Options: preset (id/code/name or object), colors, seed, speed, quality,
2747
+ * renderer, mouseColor, respectReducedMotion, opacity (0-1), fallbackColor
2748
+ * (true=preset base color, a hex string, or false to disable).
2749
+ */
2750
+ function createColorBackground(host) {
2751
+ var _options$preset;
2752
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2753
+ if (!host || typeof host.appendChild !== 'function') {
2754
+ throw new Error('createColorBackground: host element is required');
2755
+ }
2756
+ var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '初光'));
2757
+ var merged = normalizeOptions({
2758
+ quality: DEFAULTS.capsule.quality,
2759
+ renderer: DEFAULTS.capsule.renderer,
2760
+ respectReducedMotion: DEFAULTS.capsule.respectReducedMotion,
2761
+ mouseColor: true,
2762
+ opacity: 1,
2763
+ fallbackColor: true
2764
+ }, preset, options);
2765
+ var normalizedColors = merged.colors.map(normalizeColor);
2766
+ if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
2767
+ preset.seed = merged.seed;
2768
+ preset.speed = merged.speed;
2769
+ var computed = getComputedStyle(host);
2770
+ if (computed.position === 'static' || computed.position === '') {
2771
+ host.style.position = 'relative';
2772
+ }
2773
+ host.style.isolation = 'isolate';
2774
+ var layer = document.createElement('div');
2775
+ layer.className = 'dlc-color-layer';
2776
+ var syncLayerVars = function syncLayerVars() {
2777
+ layer.style.setProperty('--dlc-color-opacity', String(merged.opacity));
2778
+ var fallback = merged.fallbackColor === false || merged.fallbackColor == null ? 'transparent' : typeof merged.fallbackColor === 'string' ? merged.fallbackColor : preset.colors[0];
2779
+ layer.style.setProperty('--dlc-color-bg', fallback);
2780
+ };
2781
+ syncLayerVars();
2782
+ var canvas = document.createElement('canvas');
2783
+ canvas.className = 'dlc-color-canvas';
2784
+ canvas.setAttribute('aria-hidden', 'true');
2785
+ layer.appendChild(canvas);
2786
+ host.appendChild(layer);
2787
+ var emitter = createEmitter();
2788
+ var paused = merged.respectReducedMotion && prefersReducedMotion();
2789
+ var disposed = false;
2790
+ var dirty = {
2791
+ preset: false,
2792
+ seed: false,
2793
+ speed: false,
2794
+ colors: false,
2795
+ opacity: false,
2796
+ fallbackColor: false,
2797
+ mouseColor: false
2798
+ };
2799
+ var renderer;
2800
+ var useWebgl = merged.renderer !== 'canvas2d';
2801
+ if (useWebgl) {
2802
+ try {
2803
+ renderer = new CosmicRenderer(canvas, merged, {
2804
+ dprCap: dprCapFor(merged.quality),
2805
+ mouseColor: merged.mouseColor !== false,
2806
+ eventTarget: host
2807
+ });
2808
+ } catch (error) {
2809
+ renderer = new FallbackRenderer(canvas, merged);
2810
+ nextTick(function () {
2811
+ if (disposed) return;
2812
+ emitter.emit('error', {
2813
+ message: String(error && error.message ? error.message : error)
2814
+ });
2815
+ });
2273
2816
  }
2817
+ } else {
2818
+ renderer = new FallbackRenderer(canvas, merged);
2819
+ }
2820
+ var resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(function () {
2821
+ return renderer.resize();
2822
+ }) : null;
2823
+ if (resizeObserver) resizeObserver.observe(host);else window.addEventListener('resize', renderer.resize);
2824
+ var visibility = createVisibilityGuard(layer);
2825
+ var animationTime = 0;
2826
+ var unsubscribe = subscribeScheduler(function (delta) {
2827
+ animationTime += delta;
2828
+ if (visibility.isVisible()) renderer.draw(animationTime);
2829
+ }, function () {
2830
+ return paused;
2831
+ });
2832
+ nextTick(function () {
2833
+ if (disposed) return;
2834
+ emitter.emit('ready', {
2835
+ preset: _objectSpread2({}, preset)
2836
+ });
2837
+ });
2838
+ return {
2839
+ element: host,
2840
+ layer: layer,
2841
+ canvas: canvas,
2842
+ preset: preset,
2843
+ on: emitter.on,
2844
+ off: emitter.off,
2845
+ setPreset: function setPreset(ref) {
2846
+ var next = getPreset('capsule', ref);
2847
+ dirty.preset = true;
2848
+ Object.assign(preset, next);
2849
+ var nextColors = preset.colors.map(normalizeColor);
2850
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
2851
+ renderer.setPreset(_objectSpread2({}, preset));
2852
+ renderer.resize();
2853
+ syncLayerVars();
2854
+ emitter.emit('presetchange', {
2855
+ preset: _objectSpread2({}, preset)
2856
+ });
2857
+ return this;
2858
+ },
2859
+ setColors: function setColors(colors) {
2860
+ var next = Array.isArray(colors) ? colors.map(normalizeColor) : [];
2861
+ if (next.length !== 4 || next.some(function (color) {
2862
+ return !color;
2863
+ })) return this;
2864
+ dirty.colors = true;
2865
+ preset.colors = next;
2866
+ renderer.setPreset(_objectSpread2(_objectSpread2({}, preset), {}, {
2867
+ colors: next
2868
+ }));
2869
+ syncLayerVars();
2870
+ return this;
2871
+ },
2872
+ setSeed: function setSeed(seed) {
2873
+ var value = Number(seed);
2874
+ if (!Number.isFinite(value)) return this;
2875
+ dirty.seed = true;
2876
+ preset.seed = value;
2877
+ renderer.setPreset(_objectSpread2({}, preset));
2878
+ return this;
2879
+ },
2880
+ setSpeed: function setSpeed(speed) {
2881
+ var value = Number(speed);
2882
+ if (!Number.isFinite(value)) return this;
2883
+ dirty.speed = true;
2884
+ preset.speed = value;
2885
+ renderer.setPreset(_objectSpread2({}, preset));
2886
+ return this;
2887
+ },
2888
+ setFallbackColor: function setFallbackColor(value) {
2889
+ dirty.fallbackColor = true;
2890
+ merged.fallbackColor = value;
2891
+ syncLayerVars();
2892
+ return this;
2893
+ },
2894
+ setMouseColor: function setMouseColor(value) {
2895
+ dirty.mouseColor = true;
2896
+ merged.mouseColor = value !== false;
2897
+ if (typeof renderer.setMouseColor === 'function') renderer.setMouseColor(merged.mouseColor);
2898
+ return this;
2899
+ },
2900
+ setQuality: function setQuality(quality) {
2901
+ merged.quality = quality;
2902
+ if (typeof renderer.setDprCap === 'function') renderer.setDprCap(dprCapFor(quality));
2903
+ return this;
2904
+ },
2905
+ setOpacity: function setOpacity(value) {
2906
+ var opacity = Number(value);
2907
+ if (!Number.isFinite(opacity)) return this;
2908
+ dirty.opacity = true;
2909
+ merged.opacity = Math.min(1, Math.max(0, opacity));
2910
+ layer.style.setProperty('--dlc-color-opacity', String(merged.opacity));
2911
+ return this;
2912
+ },
2913
+ randomize: function randomize() {
2914
+ this.setSeed(Math.random() * 100);
2915
+ return this;
2916
+ },
2917
+ pause: function pause() {
2918
+ paused = true;
2919
+ return this;
2920
+ },
2921
+ resume: function resume() {
2922
+ paused = false;
2923
+ return this;
2924
+ },
2925
+ dispose: function dispose() {
2926
+ disposed = true;
2927
+ unsubscribe();
2928
+ visibility.dispose();
2929
+ if (resizeObserver) resizeObserver.disconnect();else window.removeEventListener('resize', renderer.resize);
2930
+ renderer.dispose();
2931
+ layer.remove();
2932
+ },
2933
+ opacity: merged.opacity,
2934
+ fallbackColor: merged.fallbackColor,
2935
+ mouseColor: merged.mouseColor,
2936
+ dirty: dirty
2274
2937
  };
2275
2938
  }
2276
2939
 
@@ -2282,6 +2945,7 @@ function createProgressCapsule(container) {
2282
2945
 
2283
2946
  var CAPSULE_EVENTS = ['ready', 'error', 'click', 'pointerdown', 'pointerup', 'dblclick', 'pointerenter', 'pointerleave', 'presetchange'];
2284
2947
  var PROGRESS_EVENTS = ['ready', 'error', 'change', 'dragstart', 'dragend', 'presetchange'];
2948
+ var COLOR_EVENTS = ['ready', 'error', 'presetchange'];
2285
2949
  function hookEvents(controller, events, emit) {
2286
2950
  var _iterator = _createForOfIteratorHelper(events),
2287
2951
  _step;
@@ -2312,15 +2976,18 @@ function makeWrapper(_ref) {
2312
2976
  var internalMethods = {
2313
2977
  mountController: function mountController() {
2314
2978
  var _this = this;
2315
- this.controller = create(this.$el, this.$props);
2979
+ var extraState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2980
+ this.controller = create(this.$el, _objectSpread2(_objectSpread2({}, this.$props), extraState));
2316
2981
  hookEvents(this.controller, events, function (event, payload) {
2317
2982
  return _this.$emit(event, payload);
2318
2983
  });
2984
+ this.moveSlots();
2985
+ this.applyAttrs();
2319
2986
  },
2320
2987
  recreate: function recreate() {
2988
+ var extraState = this.runtimeState();
2321
2989
  if (this.controller) this.controller.dispose();
2322
- if (this.$el) this.$el.innerHTML = '';
2323
- this.mountController();
2990
+ this.mountController(extraState);
2324
2991
  },
2325
2992
  scheduleRecreate: function scheduleRecreate() {
2326
2993
  var _this2 = this;
@@ -2330,6 +2997,52 @@ function makeWrapper(_ref) {
2330
2997
  _this2._recreateQueued = false;
2331
2998
  _this2.recreate();
2332
2999
  });
3000
+ },
3001
+ moveSlots: function moveSlots() {
3002
+ if (!this.controller || !this.controller.element || !this.$el) return;
3003
+ var root = this.controller.element;
3004
+ var textLayer = root.querySelector('.hj-capsule-text, .hj-progress-text');
3005
+ var visualLayer = root.querySelector('.hj-capsule-visual, .hj-progress-visual');
3006
+ var move = function move(wrapper, layer) {
3007
+ if (!wrapper || !layer) return;
3008
+ for (var _i = 0, _Array$from = Array.from(wrapper.childNodes); _i < _Array$from.length; _i++) {
3009
+ var node = _Array$from[_i];
3010
+ layer.appendChild(node);
3011
+ }
3012
+ };
3013
+ var refs = this.$refs || {};
3014
+ move(refs.slotText, textLayer);
3015
+ move(refs.slotColor, visualLayer);
3016
+ },
3017
+ applyAttrs: function applyAttrs() {
3018
+ if (!this.controller || !this.controller.element || !this.$attrs) return;
3019
+ var root = this.controller.element;
3020
+ for (var _i2 = 0, _Object$keys = Object.keys(this.$attrs); _i2 < _Object$keys.length; _i2++) {
3021
+ var key = _Object$keys[_i2];
3022
+ if (key === 'class' || key === 'style') continue;
3023
+ var value = this.$attrs[key];
3024
+ if (value == null || value === false) root.removeAttribute(key);else root.setAttribute(key, String(value));
3025
+ }
3026
+ },
3027
+ runtimeState: function runtimeState() {
3028
+ var controller = this.controller;
3029
+ if (!controller || !controller.dirty) return {};
3030
+ var dirty = controller.dirty;
3031
+ var state = {};
3032
+ if (dirty.preset && controller.preset) state.preset = controller.preset.name;
3033
+ if (dirty.seed && controller.preset && controller.preset.seed !== undefined) state.seed = controller.preset.seed;
3034
+ if (dirty.speed && controller.preset && controller.preset.speed !== undefined) state.speed = controller.preset.speed;
3035
+ if (dirty.colors && controller.preset && Array.isArray(controller.preset.colors)) {
3036
+ state.colors = _toConsumableArray(controller.preset.colors);
3037
+ }
3038
+ if (dirty.textRatio && controller.textRatio !== undefined) state.textRatio = controller.textRatio;
3039
+ if (dirty.cssVars && controller.cssVars) state.cssVars = _objectSpread2({}, controller.cssVars);
3040
+ if (dirty.value && typeof controller.getValue === 'function') state.value = controller.getValue();
3041
+ if (dirty.edgeStyle && controller.preset) state.edgeStyle = controller.preset.edgeStyle;
3042
+ if (dirty.opacity) state.opacity = controller.opacity;
3043
+ if (dirty.fallbackColor) state.fallbackColor = controller.fallbackColor;
3044
+ if (dirty.mouseColor) state.mouseColor = controller.mouseColor;
3045
+ return state;
2333
3046
  }
2334
3047
  };
2335
3048
  return {
@@ -2337,6 +3050,7 @@ function makeWrapper(_ref) {
2337
3050
  props: props,
2338
3051
  emits: events,
2339
3052
  render: render,
3053
+ inheritAttrs: false,
2340
3054
  mounted: function mounted() {
2341
3055
  this.mountController();
2342
3056
  },
@@ -2346,6 +3060,10 @@ function makeWrapper(_ref) {
2346
3060
  beforeDestroy: function beforeDestroy() {
2347
3061
  if (this.controller) this.controller.dispose();
2348
3062
  },
3063
+ updated: function updated() {
3064
+ this.moveSlots();
3065
+ this.applyAttrs();
3066
+ },
2349
3067
  watch: _objectSpread2({
2350
3068
  preset: function preset(value) {
2351
3069
  if (value && this.controller) this.controller.setPreset(value);
@@ -2369,7 +3087,7 @@ function makeWrapper(_ref) {
2369
3087
  function makeCapsuleWrapper(createCapsule, render) {
2370
3088
  return makeWrapper({
2371
3089
  name: 'CosmicCapsule',
2372
- props: ['preset', 'width', 'height', 'colors', 'seed', 'speed', 'mouseColor', 'renderer', 'quality', 'respectReducedMotion', 'copy', 'cssVars'],
3090
+ props: ['preset', 'width', 'height', 'colors', 'seed', 'speed', 'textRatio', 'label', 'mouseColor', 'renderer', 'quality', 'respectReducedMotion', 'cssVars'],
2373
3091
  events: CAPSULE_EVENTS,
2374
3092
  create: createCapsule,
2375
3093
  render: render,
@@ -2386,6 +3104,15 @@ function makeCapsuleWrapper(createCapsule, render) {
2386
3104
  this.controller.setSpeed(speed);
2387
3105
  }
2388
3106
  },
3107
+ textRatio: function textRatio(value) {
3108
+ if (value !== undefined && this.controller) this.controller.setTextRatio(Number(value));
3109
+ },
3110
+ cssVars: function cssVars(value) {
3111
+ if (value && this.controller) this.controller.setCssVars(value);
3112
+ },
3113
+ label: function label(value) {
3114
+ if (this.controller) this.controller.setLabel(value);
3115
+ },
2389
3116
  mouseColor: function mouseColor() {
2390
3117
  this.scheduleRecreate();
2391
3118
  },
@@ -2412,6 +3139,21 @@ function makeCapsuleWrapper(createCapsule, render) {
2412
3139
  setColors: function setColors(colors) {
2413
3140
  return this.controller && this.controller.setColors(colors);
2414
3141
  },
3142
+ setText: function setText(content) {
3143
+ return this.controller && this.controller.setText(content);
3144
+ },
3145
+ setColorContent: function setColorContent(content) {
3146
+ return this.controller && this.controller.setColorContent(content);
3147
+ },
3148
+ setTextRatio: function setTextRatio(ratio) {
3149
+ return this.controller && this.controller.setTextRatio(ratio);
3150
+ },
3151
+ setCssVars: function setCssVars(vars) {
3152
+ return this.controller && this.controller.setCssVars(vars);
3153
+ },
3154
+ setLabel: function setLabel(label) {
3155
+ return this.controller && this.controller.setLabel(label);
3156
+ },
2415
3157
  setQuality: function setQuality(quality) {
2416
3158
  return this.controller && this.controller.setQuality(quality);
2417
3159
  },
@@ -2424,7 +3166,7 @@ function makeCapsuleWrapper(createCapsule, render) {
2424
3166
  function makeProgressWrapper(createProgressCapsule, render) {
2425
3167
  return makeWrapper({
2426
3168
  name: 'ProgressCapsule',
2427
- props: ['preset', 'width', 'height', 'value', 'min', 'max', 'draggable', 'keyboard', 'edgeStyle', 'colors', 'quality', 'renderer', 'respectReducedMotion', 'copy', 'cssVars'],
3169
+ props: ['preset', 'width', 'height', 'value', 'min', 'max', 'draggable', 'keyboard', 'disabled', 'edgeStyle', 'colors', 'textRatio', 'label', 'showValue', 'valueSuffix', 'quality', 'renderer', 'respectReducedMotion', 'cssVars'],
2428
3170
  events: PROGRESS_EVENTS,
2429
3171
  create: createProgressCapsule,
2430
3172
  render: render,
@@ -2441,6 +3183,24 @@ function makeProgressWrapper(createProgressCapsule, render) {
2441
3183
  edgeStyle: function edgeStyle(value) {
2442
3184
  if (value && this.controller) this.controller.setEdgeStyle(value);
2443
3185
  },
3186
+ textRatio: function textRatio(value) {
3187
+ if (value !== undefined && this.controller) this.controller.setTextRatio(Number(value));
3188
+ },
3189
+ cssVars: function cssVars(value) {
3190
+ if (value && this.controller) this.controller.setCssVars(value);
3191
+ },
3192
+ label: function label(value) {
3193
+ if (this.controller) this.controller.setLabel(value);
3194
+ },
3195
+ valueSuffix: function valueSuffix(value) {
3196
+ if (value !== undefined && this.controller) this.controller.setValueSuffix(value);
3197
+ },
3198
+ showValue: function showValue() {
3199
+ this.scheduleRecreate();
3200
+ },
3201
+ disabled: function disabled() {
3202
+ this.scheduleRecreate();
3203
+ },
2444
3204
  draggable: function draggable() {
2445
3205
  this.scheduleRecreate();
2446
3206
  },
@@ -2479,9 +3239,99 @@ function makeProgressWrapper(createProgressCapsule, render) {
2479
3239
  setColors: function setColors(colors) {
2480
3240
  return this.controller && this.controller.setColors(colors);
2481
3241
  },
3242
+ setText: function setText(content) {
3243
+ return this.controller && this.controller.setText(content);
3244
+ },
3245
+ setColorContent: function setColorContent(content) {
3246
+ return this.controller && this.controller.setColorContent(content);
3247
+ },
3248
+ setTextRatio: function setTextRatio(ratio) {
3249
+ return this.controller && this.controller.setTextRatio(ratio);
3250
+ },
3251
+ setCssVars: function setCssVars(vars) {
3252
+ return this.controller && this.controller.setCssVars(vars);
3253
+ },
3254
+ setLabel: function setLabel(label) {
3255
+ return this.controller && this.controller.setLabel(label);
3256
+ },
3257
+ setValueSuffix: function setValueSuffix(suffix) {
3258
+ return this.controller && this.controller.setValueSuffix(suffix);
3259
+ },
3260
+ setQuality: function setQuality(quality) {
3261
+ return this.controller && this.controller.setQuality(quality);
3262
+ },
3263
+ getController: function getController() {
3264
+ return this.controller;
3265
+ }
3266
+ }
3267
+ });
3268
+ }
3269
+ function makeColorWrapper(createColorBackground, render) {
3270
+ return makeWrapper({
3271
+ name: 'ColorBackground',
3272
+ props: ['preset', 'colors', 'seed', 'speed', 'quality', 'renderer', 'mouseColor', 'respectReducedMotion', 'opacity', 'fallbackColor'],
3273
+ events: COLOR_EVENTS,
3274
+ create: createColorBackground,
3275
+ render: render,
3276
+ watch: {
3277
+ seed: function seed(value) {
3278
+ var seed = Number(value);
3279
+ if (this.controller && Number.isFinite(seed)) this.controller.setSeed(seed);
3280
+ },
3281
+ speed: function speed(value) {
3282
+ var speed = Number(value);
3283
+ if (this.controller && Number.isFinite(speed)) this.controller.setSpeed(speed);
3284
+ },
3285
+ opacity: function opacity(value) {
3286
+ if (value !== undefined && this.controller) this.controller.setOpacity(Number(value));
3287
+ },
3288
+ fallbackColor: function fallbackColor(value) {
3289
+ if (this.controller) this.controller.setFallbackColor(value);
3290
+ },
3291
+ mouseColor: function mouseColor(value) {
3292
+ if (this.controller) this.controller.setMouseColor(value);
3293
+ },
3294
+ renderer: function renderer() {
3295
+ this.scheduleRecreate();
3296
+ },
3297
+ respectReducedMotion: function respectReducedMotion() {
3298
+ this.scheduleRecreate();
3299
+ }
3300
+ },
3301
+ methods: {
3302
+ setPreset: function setPreset(preset) {
3303
+ return this.controller && this.controller.setPreset(preset);
3304
+ },
3305
+ setColors: function setColors(colors) {
3306
+ return this.controller && this.controller.setColors(colors);
3307
+ },
3308
+ setSeed: function setSeed(seed) {
3309
+ return this.controller && this.controller.setSeed(seed);
3310
+ },
3311
+ setSpeed: function setSpeed(speed) {
3312
+ return this.controller && this.controller.setSpeed(speed);
3313
+ },
2482
3314
  setQuality: function setQuality(quality) {
2483
3315
  return this.controller && this.controller.setQuality(quality);
2484
3316
  },
3317
+ setOpacity: function setOpacity(value) {
3318
+ return this.controller && this.controller.setOpacity(value);
3319
+ },
3320
+ setFallbackColor: function setFallbackColor(value) {
3321
+ return this.controller && this.controller.setFallbackColor(value);
3322
+ },
3323
+ setMouseColor: function setMouseColor(value) {
3324
+ return this.controller && this.controller.setMouseColor(value);
3325
+ },
3326
+ randomize: function randomize() {
3327
+ return this.controller && this.controller.randomize();
3328
+ },
3329
+ pause: function pause() {
3330
+ return this.controller && this.controller.pause();
3331
+ },
3332
+ resume: function resume() {
3333
+ return this.controller && this.controller.resume();
3334
+ },
2485
3335
  getController: function getController() {
2486
3336
  return this.controller;
2487
3337
  }
@@ -2489,14 +3339,31 @@ function makeProgressWrapper(createProgressCapsule, render) {
2489
3339
  });
2490
3340
  }
2491
3341
 
2492
- // Vue3 does NOT pass `h` to the render option; it must be imported.
3342
+ // Vue3 does NOT pass `h` to the render option; it must be imported. Slot
3343
+ // content renders into two marker wrappers, then moveSlots moves it into the
3344
+ // component's slot containers.
2493
3345
  var render = function render() {
2494
3346
  return vue.h('div', {
2495
3347
  class: 'hj-vue-host'
2496
- });
3348
+ }, [vue.h('div', {
3349
+ class: 'hj-vue-slot-text',
3350
+ ref: 'slotText'
3351
+ }, this.$slots.default ? this.$slots.default() : []), vue.h('div', {
3352
+ class: 'hj-vue-slot-color',
3353
+ ref: 'slotColor'
3354
+ }, this.$slots.color ? this.$slots.color() : [])]);
3355
+ };
3356
+
3357
+ // Color 的宿主内容就是组件内容:直接放在 host 里,浮在背景层上方。
3358
+ var renderColor = function renderColor() {
3359
+ return vue.h('div', {
3360
+ class: 'hj-vue-host'
3361
+ }, this.$slots.default ? this.$slots.default() : []);
2497
3362
  };
2498
3363
  var CosmicCapsule = makeCapsuleWrapper(createCapsule, render);
2499
3364
  var ProgressCapsule = makeProgressWrapper(createProgressCapsule, render);
3365
+ var ColorBackground = makeColorWrapper(createColorBackground, renderColor);
2500
3366
 
3367
+ exports.ColorBackground = ColorBackground;
2501
3368
  exports.CosmicCapsule = CosmicCapsule;
2502
3369
  exports.ProgressCapsule = ProgressCapsule;