@5even7/dlc-ui 0.2.0 → 0.2.2

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