@5even7/dlc-ui 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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
  }
@@ -322,7 +325,7 @@ var PALETTES$1 = {
322
325
  var CAPSULE_PRESETS = [{
323
326
  id: 'original',
324
327
  code: 'NC-01',
325
- name: 'ORIGINAL',
328
+ name: '初光',
326
329
  group: 'warm',
327
330
  seed: 1.7,
328
331
  speed: 0.5,
@@ -330,7 +333,7 @@ var CAPSULE_PRESETS = [{
330
333
  }, {
331
334
  id: 'ocean',
332
335
  code: 'NC-02',
333
- name: 'OCEAN',
336
+ name: '沧溟',
334
337
  group: 'cold',
335
338
  seed: 8.2,
336
339
  speed: 0.48,
@@ -338,7 +341,7 @@ var CAPSULE_PRESETS = [{
338
341
  }, {
339
342
  id: 'klein',
340
343
  code: 'NC-03',
341
- name: 'KLEIN',
344
+ name: '玄夜',
342
345
  group: 'cold',
343
346
  seed: 14.1,
344
347
  speed: 0.49,
@@ -346,7 +349,7 @@ var CAPSULE_PRESETS = [{
346
349
  }, {
347
350
  id: 'ultraviolet',
348
351
  code: 'NC-04',
349
- name: 'ULTRAVIOLET',
352
+ name: '紫霄',
350
353
  group: 'cold',
351
354
  seed: 23.4,
352
355
  speed: 0.47,
@@ -354,7 +357,7 @@ var CAPSULE_PRESETS = [{
354
357
  }, {
355
358
  id: 'chrome',
356
359
  code: 'NC-05',
357
- name: 'CHROME',
360
+ name: '银汉',
358
361
  group: 'cold',
359
362
  seed: 37.8,
360
363
  speed: 0.42,
@@ -362,7 +365,7 @@ var CAPSULE_PRESETS = [{
362
365
  }, {
363
366
  id: 'plus',
364
367
  code: 'NC-06',
365
- name: 'PLUS',
368
+ name: '熔金',
366
369
  group: 'warm',
367
370
  seed: 51.3,
368
371
  speed: 0.5,
@@ -372,7 +375,7 @@ var CAPSULE_PRESETS = [{
372
375
  var PROGRESS_PRESETS = [{
373
376
  id: 'model-training',
374
377
  code: 'NC-10',
375
- name: 'MODEL TRAINING',
378
+ name: '星火',
376
379
  subtitle: 'SHA 4.5 + 100 2026 TKN',
377
380
  group: 'progress',
378
381
  initialProgress: 43,
@@ -381,7 +384,7 @@ var PROGRESS_PRESETS = [{
381
384
  }, {
382
385
  id: 'agent-migration',
383
386
  code: 'NC-11',
384
- name: 'AGENT MIGRATION',
387
+ name: '迁流',
385
388
  subtitle: 'TRANSFERRING PROTOCOL',
386
389
  group: 'progress',
387
390
  initialProgress: 33,
@@ -390,7 +393,7 @@ var PROGRESS_PRESETS = [{
390
393
  }, {
391
394
  id: 'visual-training',
392
395
  code: 'NC-12',
393
- name: 'VISUAL TRAINING',
396
+ name: '幻境',
394
397
  subtitle: 'GENERATING POWER ++',
395
398
  group: 'progress',
396
399
  initialProgress: 58,
@@ -399,7 +402,7 @@ var PROGRESS_PRESETS = [{
399
402
  }, {
400
403
  id: 'tide',
401
404
  code: 'NC-13',
402
- name: 'TIDE',
405
+ name: '汐潮',
403
406
  subtitle: 'MOON PULL / COAST',
404
407
  group: 'progress',
405
408
  initialProgress: 30,
@@ -408,23 +411,18 @@ var PROGRESS_PRESETS = [{
408
411
  }];
409
412
 
410
413
  [].concat(_toConsumableArray(CAPSULE_PRESETS), _toConsumableArray(PROGRESS_PRESETS));
411
- function validatePreset(preset) {
412
- return Boolean(preset && typeof preset.id === 'string' && typeof preset.code === 'string' && typeof preset.name === 'string' && Number.isFinite(preset.seed) && Number.isFinite(preset.speed) && Array.isArray(preset.colors) && preset.colors.length === 4);
413
- }
414
- function validateProgressPreset(preset) {
415
- return Boolean(preset && typeof preset.id === 'string' && typeof preset.code === 'string' && typeof preset.name === 'string' && preset.group === 'progress' && Number.isFinite(preset.initialProgress) && ['flow', 'tide'].indexOf(preset.edgeStyle || 'flow') !== -1 && Array.isArray(preset.colors) && preset.colors.length === 4);
416
- }
414
+
415
+ /**
416
+ * Resolve a preset by its literary name (e.g. '沧溟').
417
+ * Matching is case-insensitive and ignores surrounding whitespace,
418
+ * so '沧溟' and ' 沧溟 ' both work.
419
+ */
417
420
  function getPreset(kind, ref) {
418
421
  var list = kind === 'capsule' ? CAPSULE_PRESETS : kind === 'progress' ? PROGRESS_PRESETS : null;
419
422
  if (!list) throw new Error("Unknown preset kind: ".concat(kind, " (use \"capsule\" or \"progress\")"));
420
- if (ref && _typeof(ref) === 'object') {
421
- var valid = kind === 'capsule' ? validatePreset(ref) : validateProgressPreset(ref);
422
- if (!valid) throw new Error("Invalid ".concat(kind, " preset object"));
423
- return ref;
424
- }
425
423
  var key = String(ref).trim().toLowerCase();
426
424
  var found = list.find(function (preset) {
427
- return preset.id.toLowerCase() === key || preset.code.toLowerCase() === key || preset.name.toLowerCase() === key;
425
+ return preset.name.toLowerCase() === key;
428
426
  });
429
427
  if (!found) throw new Error("Unknown ".concat(kind, " preset: ").concat(ref));
430
428
  return found;
@@ -437,9 +435,8 @@ var DEFAULTS = {
437
435
  quality: 'auto',
438
436
  renderer: 'auto',
439
437
  respectReducedMotion: true,
440
- interactive: true,
441
438
  mouseColor: true,
442
- showCopy: true
439
+ textRatio: 39
443
440
  },
444
441
  progress: {
445
442
  width: 454,
@@ -448,35 +445,242 @@ var DEFAULTS = {
448
445
  max: 100,
449
446
  draggable: true,
450
447
  keyboard: true,
448
+ disabled: false,
449
+ valueSuffix: '%',
451
450
  edgeStyle: 'flow',
452
451
  quality: 'auto',
453
452
  renderer: 'auto',
454
- showCopy: true,
453
+ textRatio: 54,
454
+ showValue: true,
455
455
  respectReducedMotion: true
456
456
  }
457
457
  };
458
458
 
459
- /**
460
- * All user-facing copy lives here so wording/brand changes never require a
461
- * 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.
462
463
  */
463
464
  var COPY = {
464
465
  brandName: '画境观屿',
465
- dragLabel: 'DRAG',
466
466
  valueSuffix: '%',
467
467
  progressAria: '{brand} {code} 加载进度',
468
468
  capsuleAria: '打开 {name} 沉浸预览'
469
469
  };
470
470
 
471
- function hexToRgb01$1(hex) {
472
- var normalized = hex.replace('#', '');
473
- 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);
474
677
  return [(value >> 16 & 255) / 255, (value >> 8 & 255) / 255, (value & 255) / 255];
475
678
  }
476
- function hexToRgba(hex) {
679
+ function hexToRgba(color) {
477
680
  var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
478
- var normalized = hex.replace('#', '');
479
- 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);
480
684
  var red = value >> 16 & 255;
481
685
  var green = value >> 8 & 255;
482
686
  var blue = value & 255;
@@ -557,6 +761,26 @@ var CosmicRenderer = /*#__PURE__*/function () {
557
761
  this.options.dprCap = cap;
558
762
  this.resize();
559
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
+ }
560
784
  }, {
561
785
  key: "randomize",
562
786
  value: function randomize() {
@@ -705,6 +929,8 @@ var FallbackRenderer = /*#__PURE__*/function () {
705
929
  var _this$canvas = this.canvas,
706
930
  width = _this$canvas.width,
707
931
  height = _this$canvas.height;
932
+ var t = time * (this.preset.speed || 1);
933
+ var phase = (this.preset.seed || 0) * 0.7;
708
934
  var gradient = ctx.createLinearGradient(0, 0, width, height);
709
935
  gradient.addColorStop(0, this.preset.colors[0]);
710
936
  gradient.addColorStop(0.38, this.preset.colors[1]);
@@ -714,8 +940,8 @@ var FallbackRenderer = /*#__PURE__*/function () {
714
940
  ctx.fillRect(0, 0, width, height);
715
941
  ctx.globalCompositeOperation = 'screen';
716
942
  for (var index = 0; index < 6; index += 1) {
717
- var x = (0.5 + 0.45 * Math.sin(time * 0.32 + index * 1.7)) * width;
718
- 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;
719
945
  var radius = Math.max(width, height) * (0.08 + index % 3 * 0.04);
720
946
  var glow = ctx.createRadialGradient(x, y, 0, x, y, radius);
721
947
  glow.addColorStop(0, rgb(this.preset.colors[(index + 1) % 4], 0.24));
@@ -739,7 +965,12 @@ var FallbackRenderer = /*#__PURE__*/function () {
739
965
  }
740
966
  }, {
741
967
  key: "randomize",
742
- 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() {}
743
974
  }, {
744
975
  key: "dispose",
745
976
  value: function dispose() {}
@@ -850,16 +1081,34 @@ function createVisibilityGuard(element) {
850
1081
  };
851
1082
  }
852
1083
 
853
- 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() {
854
1101
  return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
855
1102
  }
856
1103
 
857
1104
  /**
858
- * Mount a cosmic (nebula) capsule into `container`.
859
- *
860
- * Options: preset (id/code/name or object), width, height (number=px or
861
- * string with px/%/vw/vh/em/rem), colors, seed, speed, quality, interactive,
862
- * 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.
863
1112
  */
864
1113
  function createCapsule(container) {
865
1114
  var _options$preset;
@@ -867,53 +1116,73 @@ function createCapsule(container) {
867
1116
  if (!container || typeof container.appendChild !== 'function') {
868
1117
  throw new Error('createCapsule: container element is required');
869
1118
  }
870
- var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : 'NC-01'));
1119
+ var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '初光'));
871
1120
  var merged = normalizeOptions(DEFAULTS.capsule, preset, options);
872
- 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;
873
1126
  var root = document.createElement('div');
874
1127
  root.className = 'hj-capsule-root hj-capsule-cosmic';
875
1128
  root.dataset.group = preset.group;
876
1129
  root.dataset.mode = 'nebula';
877
1130
  root.dataset.theme = preset.theme || 'light';
878
- root.setAttribute('aria-label', copy.capsuleAria.replace('{name}', preset.name));
879
- var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
880
- var copyText = function copyText(key, fallback) {
881
- var value = copy[key];
882
- 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));
883
1134
  };
884
- function buildCopyHtml() {
885
- var codeText = copyText('code', preset.code);
886
- var nameText = copyText('name', preset.name);
887
- var subtitleText = copyText('subtitle', preset.subtitle);
888
- var stateText = copyText('state', 'LIVE COSMIC STUDY');
889
- var html = '';
890
- if (codeText) html += "<span class=\"hj-capsule-code\">".concat(codeText, "</span>");
891
- if (nameText) html += "<span class=\"hj-capsule-name\">".concat(nameText, "</span>");
892
- if (subtitleText) html += "<span class=\"hj-capsule-brand\">".concat(subtitleText, "</span>");
893
- if (stateText) html += "<span class=\"hj-capsule-state\">".concat(stateText, "</span>");
894
- return html;
895
- }
896
- var copyLayer = document.createElement('div');
897
- copyLayer.className = 'hj-capsule-copy';
898
- var renderCopy = function renderCopy() {
899
- if (copyEnabled) copyLayer.innerHTML = buildCopyHtml();
900
- };
901
- renderCopy();
902
- var isHexColor = function isHexColor(value) {
903
- 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
+ }
904
1161
  };
905
- if (copy.background) {
906
- 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);
907
- }
908
- 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);
909
1168
  var canvas = document.createElement('canvas');
910
1169
  canvas.className = 'hj-capsule-canvas';
911
1170
  canvas.setAttribute('aria-hidden', 'true');
912
- if (copyEnabled) root.appendChild(copyLayer);
1171
+ root.appendChild(textLayer);
1172
+ root.appendChild(visualLayer);
913
1173
  root.appendChild(canvas);
914
1174
  container.appendChild(root);
915
1175
  var emitter = createEmitter();
916
- 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
+ };
917
1186
  var renderer;
918
1187
  var useWebgl = merged.renderer !== 'canvas2d';
919
1188
  if (useWebgl) {
@@ -923,8 +1192,11 @@ function createCapsule(container) {
923
1192
  });
924
1193
  } catch (error) {
925
1194
  renderer = new FallbackRenderer(canvas, merged);
926
- emitter.emit('error', {
927
- 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
+ });
928
1200
  });
929
1201
  }
930
1202
  } else {
@@ -938,6 +1210,9 @@ function createCapsule(container) {
938
1210
  var name = _Object$keys[_i];
939
1211
  root.style.setProperty(name, vars[name]);
940
1212
  }
1213
+ if (merged.textRatio !== undefined) {
1214
+ root.style.setProperty('--hj-text-width', "".concat(merged.textRatio, "%"));
1215
+ }
941
1216
  renderer.resize();
942
1217
  };
943
1218
  applySize();
@@ -946,18 +1221,16 @@ function createCapsule(container) {
946
1221
  }) : null;
947
1222
  if (resizeObserver) resizeObserver.observe(root);else window.addEventListener('resize', renderer.resize);
948
1223
  var visibility = createVisibilityGuard(root);
949
- if (merged.interactive !== false) {
950
- root.addEventListener('pointerenter', function () {
951
- return emitter.emit('pointerenter', {
952
- preset: _objectSpread2({}, preset)
953
- });
1224
+ root.addEventListener('pointerenter', function () {
1225
+ return emitter.emit('pointerenter', {
1226
+ preset: _objectSpread2({}, preset)
954
1227
  });
955
- root.addEventListener('pointerleave', function () {
956
- return emitter.emit('pointerleave', {
957
- preset: _objectSpread2({}, preset)
958
- });
1228
+ });
1229
+ root.addEventListener('pointerleave', function () {
1230
+ return emitter.emit('pointerleave', {
1231
+ preset: _objectSpread2({}, preset)
959
1232
  });
960
- }
1233
+ });
961
1234
  root.addEventListener('click', function (event) {
962
1235
  emitter.emit('click', {
963
1236
  event: event,
@@ -989,13 +1262,16 @@ function createCapsule(container) {
989
1262
  }, function () {
990
1263
  return paused;
991
1264
  });
992
- emitter.emit('ready', {
993
- preset: _objectSpread2({}, preset)
1265
+ nextTick(function () {
1266
+ if (disposed) return;
1267
+ emitter.emit('ready', {
1268
+ preset: _objectSpread2({}, preset)
1269
+ });
994
1270
  });
995
- var syncCopy = function syncCopy() {
1271
+ var syncTheme = function syncTheme() {
996
1272
  root.dataset.mode = 'nebula';
997
1273
  root.dataset.theme = preset.theme || 'light';
998
- renderCopy();
1274
+ updateAria();
999
1275
  };
1000
1276
  return {
1001
1277
  element: root,
@@ -1005,9 +1281,12 @@ function createCapsule(container) {
1005
1281
  off: emitter.off,
1006
1282
  setPreset: function setPreset(ref) {
1007
1283
  var next = getPreset('capsule', ref);
1284
+ dirty.preset = true;
1008
1285
  Object.assign(preset, next);
1009
- renderer.setPreset(next);
1010
- syncCopy();
1286
+ var nextColors = preset.colors.map(normalizeColor);
1287
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
1288
+ renderer.setPreset(_objectSpread2({}, preset));
1289
+ syncTheme();
1011
1290
  renderer.resize();
1012
1291
  emitter.emit('presetchange', {
1013
1292
  preset: _objectSpread2({}, next)
@@ -1015,13 +1294,64 @@ function createCapsule(container) {
1015
1294
  return this;
1016
1295
  },
1017
1296
  setColors: function setColors(colors) {
1018
- if (!Array.isArray(colors) || colors.length !== 4) return this;
1019
- 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;
1020
1303
  renderer.setPreset(_objectSpread2(_objectSpread2({}, preset), {}, {
1021
- colors: colors
1304
+ colors: next
1022
1305
  }));
1023
1306
  return this;
1024
1307
  },
1308
+ setSeed: function setSeed(seed) {
1309
+ var value = Number(seed);
1310
+ if (!Number.isFinite(value)) return this;
1311
+ dirty.seed = true;
1312
+ preset.seed = value;
1313
+ renderer.setPreset(_objectSpread2({}, preset));
1314
+ return this;
1315
+ },
1316
+ setSpeed: function setSpeed(speed) {
1317
+ var value = Number(speed);
1318
+ if (!Number.isFinite(value)) return this;
1319
+ dirty.speed = true;
1320
+ preset.speed = value;
1321
+ renderer.setPreset(_objectSpread2({}, preset));
1322
+ return this;
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
+ },
1025
1355
  setSize: function setSize(width, height) {
1026
1356
  if (width !== undefined) merged.width = width;
1027
1357
  if (height !== undefined) merged.height = height;
@@ -1029,7 +1359,7 @@ function createCapsule(container) {
1029
1359
  return this;
1030
1360
  },
1031
1361
  randomize: function randomize() {
1032
- renderer.randomize();
1362
+ this.setSeed(Math.random() * 100);
1033
1363
  return this;
1034
1364
  },
1035
1365
  pause: function pause() {
@@ -1046,12 +1376,16 @@ function createCapsule(container) {
1046
1376
  return this;
1047
1377
  },
1048
1378
  dispose: function dispose() {
1379
+ disposed = true;
1049
1380
  unsubscribe();
1050
1381
  visibility.dispose();
1051
1382
  if (resizeObserver) resizeObserver.disconnect();else window.removeEventListener('resize', renderer.resize);
1052
1383
  renderer.dispose();
1053
1384
  root.remove();
1054
- }
1385
+ },
1386
+ textRatio: merged.textRatio,
1387
+ cssVars: merged.cssVars,
1388
+ dirty: dirty
1055
1389
  };
1056
1390
  }
1057
1391
 
@@ -1493,7 +1827,7 @@ function interpolate(template, values) {
1493
1827
  return values[key] !== undefined ? values[key] : '';
1494
1828
  });
1495
1829
  }
1496
- function prefersReducedMotion() {
1830
+ function prefersReducedMotion$1() {
1497
1831
  return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
1498
1832
  }
1499
1833
  var FLOW_PROFILES = {
@@ -1555,7 +1889,8 @@ var FLOW_PROFILES = {
1555
1889
  };
1556
1890
  var ProgressCapsuleController = /*#__PURE__*/function () {
1557
1891
  function ProgressCapsuleController(_ref) {
1558
- var _options$min,
1892
+ var _options$valueSuffix,
1893
+ _options$min,
1559
1894
  _options$max,
1560
1895
  _options$value,
1561
1896
  _this = this;
@@ -1565,7 +1900,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1565
1900
  preset = _ref.preset,
1566
1901
  emitter = _ref.emitter,
1567
1902
  options = _ref.options,
1568
- copy = _ref.copy;
1903
+ copy = _ref.copy,
1904
+ dirty = _ref.dirty;
1569
1905
  _classCallCheck(this, ProgressCapsuleController);
1570
1906
  this.root = root;
1571
1907
  this.canvas = canvas;
@@ -1574,6 +1910,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1574
1910
  this.emitter = emitter;
1575
1911
  this.options = options;
1576
1912
  this.copy = copy;
1913
+ this.dirty = dirty;
1914
+ this.valueSuffix = (_options$valueSuffix = options.valueSuffix) !== null && _options$valueSuffix !== void 0 ? _options$valueSuffix : copy.valueSuffix;
1577
1915
  this.profile = preset.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
1578
1916
  this.min = (_options$min = options.min) !== null && _options$min !== void 0 ? _options$min : 0;
1579
1917
  this.max = (_options$max = options.max) !== null && _options$max !== void 0 ? _options$max : 100;
@@ -1613,12 +1951,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1613
1951
  var rounded = Math.round(this.value);
1614
1952
  this.root.style.setProperty('--progress', this.value.toFixed(2));
1615
1953
  this.root.setAttribute('aria-valuenow', String(rounded));
1616
- this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.copy.valueSuffix));
1617
- this.valueElement.textContent = "".concat(rounded).concat(this.copy.valueSuffix);
1618
- if (!this.suppressEvents) this.emitter.emit('change', {
1619
- value: this.value,
1620
- source: source
1621
- });
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;
1622
1972
  }
1623
1973
  }, {
1624
1974
  key: "resizeCanvas",
@@ -1793,7 +2143,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1793
2143
  var width = this.width;
1794
2144
  var height = this.height;
1795
2145
  if (!ctx || width <= 0 || height <= 0) return;
1796
- 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);
1797
2148
  var time = this.flowTime;
1798
2149
  var _this$preset$colors = _slicedToArray(this.preset.colors, 4),
1799
2150
  dark = _this$preset$colors[0],
@@ -1908,7 +2259,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1908
2259
  value: function updateFromPointer(event) {
1909
2260
  var bounds = this.root.getBoundingClientRect();
1910
2261
  var ratio = bounds.width > 0 ? (event.clientX - bounds.left) / bounds.width : 0;
1911
- this.setProgress(ratio * 100, 'drag');
2262
+ this.setProgress(this.min + ratio * (this.max - this.min), 'drag');
1912
2263
  }
1913
2264
  }, {
1914
2265
  key: "beginDrag",
@@ -1916,6 +2267,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1916
2267
  if (event.button !== undefined && event.button !== 0) return;
1917
2268
  event.preventDefault();
1918
2269
  this.dragging = true;
2270
+ this.pendingPointer = null;
2271
+ this._dragRaf = 0;
1919
2272
  this.root.classList.add('is-dragging');
1920
2273
  try {
1921
2274
  var _this$root$setPointer, _this$root;
@@ -1929,15 +2282,31 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1929
2282
  }, {
1930
2283
  key: "moveDrag",
1931
2284
  value: function moveDrag(event) {
2285
+ var _this2 = this;
1932
2286
  if (!this.dragging) return;
1933
2287
  event.preventDefault();
1934
- 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
+ });
1935
2297
  }
1936
2298
  }, {
1937
2299
  key: "endDrag",
1938
2300
  value: function endDrag(event) {
1939
2301
  if (!this.dragging) return;
1940
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);
1941
2310
  this.root.classList.remove('is-dragging');
1942
2311
  try {
1943
2312
  var _this$root$hasPointer, _this$root2;
@@ -1952,19 +2321,19 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1952
2321
  }, {
1953
2322
  key: "bindEvents",
1954
2323
  value: function bindEvents() {
1955
- var _this2 = this;
2324
+ var _this3 = this;
1956
2325
  if (this.options.draggable !== false) {
1957
2326
  this.handlers.pointerdown = function (event) {
1958
- return _this2.beginDrag(event);
2327
+ return _this3.beginDrag(event);
1959
2328
  };
1960
2329
  this.handlers.pointermove = function (event) {
1961
- return _this2.moveDrag(event);
2330
+ return _this3.moveDrag(event);
1962
2331
  };
1963
2332
  this.handlers.pointerup = function (event) {
1964
- return _this2.endDrag(event);
2333
+ return _this3.endDrag(event);
1965
2334
  };
1966
2335
  this.handlers.pointercancel = function (event) {
1967
- return _this2.endDrag(event);
2336
+ return _this3.endDrag(event);
1968
2337
  };
1969
2338
  this.root.addEventListener('pointerdown', this.handlers.pointerdown);
1970
2339
  this.root.addEventListener('pointermove', this.handlers.pointermove);
@@ -1973,23 +2342,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1973
2342
  }
1974
2343
  if (this.options.keyboard !== false) {
1975
2344
  this.handlers.keydown = function (event) {
2345
+ var step = (_this3.max - _this3.min) * 0.02;
1976
2346
  var actions = {
1977
- ArrowLeft: -2,
1978
- ArrowDown: -2,
1979
- ArrowRight: 2,
1980
- ArrowUp: 2,
1981
- PageDown: -10,
1982
- PageUp: 10
2347
+ ArrowLeft: -step,
2348
+ ArrowDown: -step,
2349
+ ArrowRight: step,
2350
+ ArrowUp: step,
2351
+ PageDown: -step * 5,
2352
+ PageUp: step * 5
1983
2353
  };
1984
2354
  if (event.key === 'Home') {
1985
2355
  event.preventDefault();
1986
- _this2.setProgress(_this2.min, 'keyboard');
2356
+ _this3.setProgress(_this3.min, 'keyboard');
1987
2357
  } else if (event.key === 'End') {
1988
2358
  event.preventDefault();
1989
- _this2.setProgress(_this2.max, 'keyboard');
2359
+ _this3.setProgress(_this3.max, 'keyboard');
1990
2360
  } else if (actions[event.key]) {
1991
2361
  event.preventDefault();
1992
- _this2.setProgress(_this2.value + actions[event.key], 'keyboard');
2362
+ _this3.setProgress(_this3.value + actions[event.key], 'keyboard');
1993
2363
  } else {
1994
2364
  return;
1995
2365
  }
@@ -2026,6 +2396,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
2026
2396
  }, {
2027
2397
  key: "dispose",
2028
2398
  value: function dispose() {
2399
+ if (this._dragRaf) cancelAnimationFrame(this._dragRaf);
2029
2400
  if (this.resizeObserver) this.resizeObserver.disconnect();else window.removeEventListener('resize', this.resizeCanvas);
2030
2401
  for (var _i = 0, _Object$keys = Object.keys(this.handlers); _i < _Object$keys.length; _i++) {
2031
2402
  var name = _Object$keys[_i];
@@ -2038,11 +2409,14 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
2038
2409
  }();
2039
2410
 
2040
2411
  /**
2041
- * Mount a fluid progress capsule into `container`.
2042
- *
2043
- * Options: preset (id/code/name or object), width, height, value, min, max,
2044
- * draggable, keyboard, colors, edgeStyle, quality,
2045
- * 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.
2046
2420
  */
2047
2421
  function createProgressCapsule(container) {
2048
2422
  var _options$preset, _merged$min, _merged$max;
@@ -2050,64 +2424,93 @@ function createProgressCapsule(container) {
2050
2424
  if (!container || typeof container.appendChild !== 'function') {
2051
2425
  throw new Error('createProgressCapsule: container element is required');
2052
2426
  }
2053
- var preset = _objectSpread2({}, getPreset('progress', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : 'NC-10'));
2427
+ var preset = _objectSpread2({}, getPreset('progress', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '星火'));
2054
2428
  var merged = normalizeOptions(DEFAULTS.progress, preset, options);
2055
- 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
+ };
2056
2447
  var root = document.createElement('div');
2057
2448
  root.className = 'hj-capsule-root hj-progress-root';
2058
2449
  root.setAttribute('role', 'slider');
2059
2450
  root.setAttribute('tabindex', '0');
2060
- 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
+ }
2061
2456
  root.setAttribute('aria-valuemin', String((_merged$min = merged.min) !== null && _merged$min !== void 0 ? _merged$min : 0));
2062
2457
  root.setAttribute('aria-valuemax', String((_merged$max = merged.max) !== null && _merged$max !== void 0 ? _merged$max : 100));
2063
2458
  root.setAttribute('aria-valuenow', String(preset.initialProgress));
2064
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
2065
- brand: copy.brandName,
2066
- code: preset.code,
2067
- name: preset.name
2068
- }));
2069
- 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');
2070
2468
  var canvas = document.createElement('canvas');
2071
2469
  canvas.className = 'hj-progress-canvas';
2072
2470
  canvas.setAttribute('aria-hidden', 'true');
2073
- var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
2074
- var copyText = function copyText(key, fallback) {
2075
- var value = copy[key];
2076
- return value === undefined ? fallback : value;
2077
- };
2078
- function buildCopyHtml() {
2079
- var html = '';
2080
- var brandText = copy.brandName || '';
2081
- var subtitleText = copyText('subtitle', preset.subtitle);
2082
- if (brandText) html += "<span class=\"hj-progress-name\">".concat(brandText, "</span>");
2083
- if (subtitleText) html += "<span class=\"hj-progress-subtitle\">".concat(subtitleText, "</span>");
2084
- return html;
2085
- }
2086
- var copyLayer = document.createElement('div');
2087
- copyLayer.className = 'hj-progress-copy';
2088
- var renderCopy = function renderCopy() {
2089
- 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
+ }
2090
2494
  };
2091
- renderCopy();
2092
- if (copy.background) {
2093
- root.style.setProperty('--hj-progress-copy-bg', copy.background);
2094
- 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');
2095
2505
  }
2096
- if (copy.color) root.style.setProperty('--hj-progress-copy-color', copy.color);
2097
- var valueElement = document.createElement('div');
2098
- valueElement.className = 'hj-progress-value';
2099
- valueElement.setAttribute('aria-hidden', 'true');
2100
- var dragLabel = document.createElement('span');
2101
- dragLabel.className = 'hj-progress-drag-label';
2102
- dragLabel.setAttribute('aria-hidden', 'true');
2103
- dragLabel.textContent = copy.dragLabel;
2104
2506
  root.appendChild(canvas);
2105
- if (copyEnabled) root.appendChild(copyLayer);
2106
- root.appendChild(valueElement);
2107
- root.appendChild(dragLabel);
2507
+ root.appendChild(textLayer);
2508
+ root.appendChild(visualLayer);
2509
+ if (valueElement) root.appendChild(valueElement);
2108
2510
  container.appendChild(root);
2109
2511
  var emitter = createEmitter();
2110
- var paused = merged.respectReducedMotion && prefersReducedMotion();
2512
+ var paused = merged.respectReducedMotion && prefersReducedMotion$1();
2513
+ var disposed = false;
2111
2514
  var applySize = function applySize() {
2112
2515
  root.style.width = parseSize(merged.width);
2113
2516
  root.style.height = parseSize(merged.height);
@@ -2116,6 +2519,9 @@ function createProgressCapsule(container) {
2116
2519
  var name = _Object$keys2[_i2];
2117
2520
  root.style.setProperty(name, vars[name]);
2118
2521
  }
2522
+ if (merged.textRatio !== undefined) {
2523
+ root.style.setProperty('--hj-text-width', "".concat(merged.textRatio, "%"));
2524
+ }
2119
2525
  };
2120
2526
  applySize();
2121
2527
  var controller = new ProgressCapsuleController({
@@ -2124,8 +2530,12 @@ function createProgressCapsule(container) {
2124
2530
  valueElement: valueElement,
2125
2531
  preset: preset,
2126
2532
  emitter: emitter,
2127
- options: merged,
2128
- copy: copy
2533
+ options: _objectSpread2(_objectSpread2({}, merged), {}, {
2534
+ draggable: effectiveDraggable,
2535
+ keyboard: effectiveKeyboard
2536
+ }),
2537
+ copy: copy,
2538
+ dirty: dirty
2129
2539
  });
2130
2540
  var overlay = null;
2131
2541
  if (merged.renderer !== 'canvas2d') {
@@ -2138,7 +2548,14 @@ function createProgressCapsule(container) {
2138
2548
  }
2139
2549
  });
2140
2550
  }
2141
- 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
+ }
2142
2559
  var visibility = createVisibilityGuard(root);
2143
2560
  var flowTime = 0;
2144
2561
  var unsubscribe = subscribeScheduler(function (delta, now) {
@@ -2151,16 +2568,14 @@ function createProgressCapsule(container) {
2151
2568
  }, function () {
2152
2569
  return paused;
2153
2570
  });
2154
- emitter.emit('ready', {
2155
- preset: _objectSpread2({}, preset)
2571
+ nextTick(function () {
2572
+ if (disposed) return;
2573
+ emitter.emit('ready', {
2574
+ preset: _objectSpread2({}, preset)
2575
+ });
2156
2576
  });
2157
2577
  var syncDom = function syncDom() {
2158
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
2159
- brand: copy.brandName,
2160
- code: preset.code,
2161
- name: preset.name
2162
- }));
2163
- renderCopy();
2578
+ updateAria();
2164
2579
  };
2165
2580
  return {
2166
2581
  element: root,
@@ -2182,8 +2597,11 @@ function createProgressCapsule(container) {
2182
2597
  },
2183
2598
  setPreset: function setPreset(ref) {
2184
2599
  var next = getPreset('progress', ref);
2600
+ dirty.preset = true;
2185
2601
  Object.assign(preset, next);
2186
- controller.preset = next;
2602
+ var nextColors = preset.colors.map(normalizeColor);
2603
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
2604
+ controller.preset = preset;
2187
2605
  controller.profile = next.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[next.id] || FLOW_PROFILES['visual-training'];
2188
2606
  controller.flowTime = stringSeed(next.id) * 31;
2189
2607
  controller.seed = stringSeed("".concat(next.id, "-reference")) * Math.PI * 2;
@@ -2193,7 +2611,7 @@ function createProgressCapsule(container) {
2193
2611
  overlay = attachProgressFlowOverlay({
2194
2612
  root: root,
2195
2613
  canvas: canvas,
2196
- preset: next,
2614
+ preset: preset,
2197
2615
  getProgress: function getProgress() {
2198
2616
  return controller.value;
2199
2617
  }
@@ -2202,14 +2620,74 @@ function createProgressCapsule(container) {
2202
2620
  controller.webglActive = Boolean(overlay);
2203
2621
  controller.resizeCanvas();
2204
2622
  emitter.emit('presetchange', {
2205
- preset: _objectSpread2({}, next)
2623
+ preset: _objectSpread2({}, preset)
2206
2624
  });
2207
2625
  return this;
2208
2626
  },
2627
+ setEdgeStyle: function setEdgeStyle(edgeStyle) {
2628
+ var value = String(edgeStyle || '').toLowerCase();
2629
+ if (value !== 'flow' && value !== 'tide') return this;
2630
+ dirty.edgeStyle = true;
2631
+ preset.edgeStyle = value;
2632
+ controller.profile = value === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
2633
+ if (overlay) {
2634
+ overlay.dispose();
2635
+ overlay = attachProgressFlowOverlay({
2636
+ root: root,
2637
+ canvas: canvas,
2638
+ preset: preset,
2639
+ getProgress: function getProgress() {
2640
+ return controller.value;
2641
+ }
2642
+ });
2643
+ }
2644
+ controller.webglActive = Boolean(overlay);
2645
+ controller.resizeCanvas();
2646
+ return this;
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
+ },
2209
2683
  setColors: function setColors(colors) {
2210
- if (!Array.isArray(colors) || colors.length !== 4) return this;
2211
- controller.setColors(colors);
2212
- 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);
2213
2691
  controller.resizeCanvas();
2214
2692
  return this;
2215
2693
  },
@@ -2239,12 +2717,223 @@ function createProgressCapsule(container) {
2239
2717
  return this;
2240
2718
  },
2241
2719
  dispose: function dispose() {
2720
+ disposed = true;
2242
2721
  unsubscribe();
2243
2722
  visibility.dispose();
2244
2723
  if (overlay) overlay.dispose();
2245
2724
  controller.dispose();
2246
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
+ });
2247
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
2248
2937
  };
2249
2938
  }
2250
2939
 
@@ -2256,6 +2945,7 @@ function createProgressCapsule(container) {
2256
2945
 
2257
2946
  var CAPSULE_EVENTS = ['ready', 'error', 'click', 'pointerdown', 'pointerup', 'dblclick', 'pointerenter', 'pointerleave', 'presetchange'];
2258
2947
  var PROGRESS_EVENTS = ['ready', 'error', 'change', 'dragstart', 'dragend', 'presetchange'];
2948
+ var COLOR_EVENTS = ['ready', 'error', 'presetchange'];
2259
2949
  function hookEvents(controller, events, emit) {
2260
2950
  var _iterator = _createForOfIteratorHelper(events),
2261
2951
  _step;
@@ -2286,15 +2976,18 @@ function makeWrapper(_ref) {
2286
2976
  var internalMethods = {
2287
2977
  mountController: function mountController() {
2288
2978
  var _this = this;
2289
- 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));
2290
2981
  hookEvents(this.controller, events, function (event, payload) {
2291
2982
  return _this.$emit(event, payload);
2292
2983
  });
2984
+ this.moveSlots();
2985
+ this.applyAttrs();
2293
2986
  },
2294
2987
  recreate: function recreate() {
2988
+ var extraState = this.runtimeState();
2295
2989
  if (this.controller) this.controller.dispose();
2296
- if (this.$el) this.$el.innerHTML = '';
2297
- this.mountController();
2990
+ this.mountController(extraState);
2298
2991
  },
2299
2992
  scheduleRecreate: function scheduleRecreate() {
2300
2993
  var _this2 = this;
@@ -2304,6 +2997,52 @@ function makeWrapper(_ref) {
2304
2997
  _this2._recreateQueued = false;
2305
2998
  _this2.recreate();
2306
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;
2307
3046
  }
2308
3047
  };
2309
3048
  return {
@@ -2311,6 +3050,7 @@ function makeWrapper(_ref) {
2311
3050
  props: props,
2312
3051
  emits: events,
2313
3052
  render: render,
3053
+ inheritAttrs: false,
2314
3054
  mounted: function mounted() {
2315
3055
  this.mountController();
2316
3056
  },
@@ -2320,6 +3060,10 @@ function makeWrapper(_ref) {
2320
3060
  beforeDestroy: function beforeDestroy() {
2321
3061
  if (this.controller) this.controller.dispose();
2322
3062
  },
3063
+ updated: function updated() {
3064
+ this.moveSlots();
3065
+ this.applyAttrs();
3066
+ },
2323
3067
  watch: _objectSpread2({
2324
3068
  preset: function preset(value) {
2325
3069
  if (value && this.controller) this.controller.setPreset(value);
@@ -2343,7 +3087,7 @@ function makeWrapper(_ref) {
2343
3087
  function makeCapsuleWrapper(createCapsule, render) {
2344
3088
  return makeWrapper({
2345
3089
  name: 'CosmicCapsule',
2346
- props: ['preset', 'width', 'height', 'colors', 'seed', 'speed', 'interactive', 'mouseColor', 'renderer', 'quality', 'respectReducedMotion', 'copy', 'cssVars'],
3090
+ props: ['preset', 'width', 'height', 'colors', 'seed', 'speed', 'textRatio', 'label', 'mouseColor', 'renderer', 'quality', 'respectReducedMotion', 'cssVars'],
2347
3091
  events: CAPSULE_EVENTS,
2348
3092
  create: createCapsule,
2349
3093
  render: render,
@@ -2351,21 +3095,23 @@ function makeCapsuleWrapper(createCapsule, render) {
2351
3095
  seed: function seed(value) {
2352
3096
  var seed = Number(value);
2353
3097
  if (this.controller && Number.isFinite(seed)) {
2354
- this.controller.setPreset(_objectSpread2(_objectSpread2({}, this.controller.preset), {}, {
2355
- seed: seed
2356
- }));
3098
+ this.controller.setSeed(seed);
2357
3099
  }
2358
3100
  },
2359
3101
  speed: function speed(value) {
2360
3102
  var speed = Number(value);
2361
3103
  if (this.controller && Number.isFinite(speed)) {
2362
- this.controller.setPreset(_objectSpread2(_objectSpread2({}, this.controller.preset), {}, {
2363
- speed: speed
2364
- }));
3104
+ this.controller.setSpeed(speed);
2365
3105
  }
2366
3106
  },
2367
- interactive: function interactive() {
2368
- this.scheduleRecreate();
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);
2369
3115
  },
2370
3116
  mouseColor: function mouseColor() {
2371
3117
  this.scheduleRecreate();
@@ -2393,6 +3139,21 @@ function makeCapsuleWrapper(createCapsule, render) {
2393
3139
  setColors: function setColors(colors) {
2394
3140
  return this.controller && this.controller.setColors(colors);
2395
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
+ },
2396
3157
  setQuality: function setQuality(quality) {
2397
3158
  return this.controller && this.controller.setQuality(quality);
2398
3159
  },
@@ -2405,7 +3166,7 @@ function makeCapsuleWrapper(createCapsule, render) {
2405
3166
  function makeProgressWrapper(createProgressCapsule, render) {
2406
3167
  return makeWrapper({
2407
3168
  name: 'ProgressCapsule',
2408
- 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'],
2409
3170
  events: PROGRESS_EVENTS,
2410
3171
  create: createProgressCapsule,
2411
3172
  render: render,
@@ -2420,9 +3181,25 @@ function makeProgressWrapper(createProgressCapsule, render) {
2420
3181
  if (value !== undefined && this.controller) this.controller.setRange(this.controller.min, value);
2421
3182
  },
2422
3183
  edgeStyle: function edgeStyle(value) {
2423
- if (value && this.controller) this.controller.setPreset(_objectSpread2(_objectSpread2({}, this.controller.preset), {}, {
2424
- edgeStyle: value
2425
- }));
3184
+ if (value && this.controller) this.controller.setEdgeStyle(value);
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();
2426
3203
  },
2427
3204
  draggable: function draggable() {
2428
3205
  this.scheduleRecreate();
@@ -2462,6 +3239,24 @@ function makeProgressWrapper(createProgressCapsule, render) {
2462
3239
  setColors: function setColors(colors) {
2463
3240
  return this.controller && this.controller.setColors(colors);
2464
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
+ },
2465
3260
  setQuality: function setQuality(quality) {
2466
3261
  return this.controller && this.controller.setQuality(quality);
2467
3262
  },
@@ -2471,15 +3266,104 @@ function makeProgressWrapper(createProgressCapsule, render) {
2471
3266
  }
2472
3267
  });
2473
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
+ },
3314
+ setQuality: function setQuality(quality) {
3315
+ return this.controller && this.controller.setQuality(quality);
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
+ },
3335
+ getController: function getController() {
3336
+ return this.controller;
3337
+ }
3338
+ }
3339
+ });
3340
+ }
2474
3341
 
2475
- // 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.
2476
3345
  var render = function render() {
2477
3346
  return vue.h('div', {
2478
3347
  class: 'hj-vue-host'
2479
- });
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() : []);
2480
3362
  };
2481
3363
  var CosmicCapsule = makeCapsuleWrapper(createCapsule, render);
2482
3364
  var ProgressCapsule = makeProgressWrapper(createProgressCapsule, render);
3365
+ var ColorBackground = makeColorWrapper(createColorBackground, renderColor);
2483
3366
 
3367
+ exports.ColorBackground = ColorBackground;
2484
3368
  exports.CosmicCapsule = CosmicCapsule;
2485
3369
  exports.ProgressCapsule = ProgressCapsule;