@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/vue2.cjs CHANGED
@@ -148,6 +148,9 @@ function _objectSpread2(e) {
148
148
  }
149
149
  return e;
150
150
  }
151
+ function _readOnlyError(r) {
152
+ throw new TypeError('"' + r + '" is read-only');
153
+ }
151
154
  function _slicedToArray(r, e) {
152
155
  return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
153
156
  }
@@ -320,7 +323,7 @@ var PALETTES$1 = {
320
323
  var CAPSULE_PRESETS = [{
321
324
  id: 'original',
322
325
  code: 'NC-01',
323
- name: 'ORIGINAL',
326
+ name: '初光',
324
327
  group: 'warm',
325
328
  seed: 1.7,
326
329
  speed: 0.5,
@@ -328,7 +331,7 @@ var CAPSULE_PRESETS = [{
328
331
  }, {
329
332
  id: 'ocean',
330
333
  code: 'NC-02',
331
- name: 'OCEAN',
334
+ name: '沧溟',
332
335
  group: 'cold',
333
336
  seed: 8.2,
334
337
  speed: 0.48,
@@ -336,7 +339,7 @@ var CAPSULE_PRESETS = [{
336
339
  }, {
337
340
  id: 'klein',
338
341
  code: 'NC-03',
339
- name: 'KLEIN',
342
+ name: '玄夜',
340
343
  group: 'cold',
341
344
  seed: 14.1,
342
345
  speed: 0.49,
@@ -344,7 +347,7 @@ var CAPSULE_PRESETS = [{
344
347
  }, {
345
348
  id: 'ultraviolet',
346
349
  code: 'NC-04',
347
- name: 'ULTRAVIOLET',
350
+ name: '紫霄',
348
351
  group: 'cold',
349
352
  seed: 23.4,
350
353
  speed: 0.47,
@@ -352,7 +355,7 @@ var CAPSULE_PRESETS = [{
352
355
  }, {
353
356
  id: 'chrome',
354
357
  code: 'NC-05',
355
- name: 'CHROME',
358
+ name: '银汉',
356
359
  group: 'cold',
357
360
  seed: 37.8,
358
361
  speed: 0.42,
@@ -360,7 +363,7 @@ var CAPSULE_PRESETS = [{
360
363
  }, {
361
364
  id: 'plus',
362
365
  code: 'NC-06',
363
- name: 'PLUS',
366
+ name: '熔金',
364
367
  group: 'warm',
365
368
  seed: 51.3,
366
369
  speed: 0.5,
@@ -370,7 +373,7 @@ var CAPSULE_PRESETS = [{
370
373
  var PROGRESS_PRESETS = [{
371
374
  id: 'model-training',
372
375
  code: 'NC-10',
373
- name: 'MODEL TRAINING',
376
+ name: '星火',
374
377
  subtitle: 'SHA 4.5 + 100 2026 TKN',
375
378
  group: 'progress',
376
379
  initialProgress: 43,
@@ -379,7 +382,7 @@ var PROGRESS_PRESETS = [{
379
382
  }, {
380
383
  id: 'agent-migration',
381
384
  code: 'NC-11',
382
- name: 'AGENT MIGRATION',
385
+ name: '迁流',
383
386
  subtitle: 'TRANSFERRING PROTOCOL',
384
387
  group: 'progress',
385
388
  initialProgress: 33,
@@ -388,7 +391,7 @@ var PROGRESS_PRESETS = [{
388
391
  }, {
389
392
  id: 'visual-training',
390
393
  code: 'NC-12',
391
- name: 'VISUAL TRAINING',
394
+ name: '幻境',
392
395
  subtitle: 'GENERATING POWER ++',
393
396
  group: 'progress',
394
397
  initialProgress: 58,
@@ -397,7 +400,7 @@ var PROGRESS_PRESETS = [{
397
400
  }, {
398
401
  id: 'tide',
399
402
  code: 'NC-13',
400
- name: 'TIDE',
403
+ name: '汐潮',
401
404
  subtitle: 'MOON PULL / COAST',
402
405
  group: 'progress',
403
406
  initialProgress: 30,
@@ -406,23 +409,18 @@ var PROGRESS_PRESETS = [{
406
409
  }];
407
410
 
408
411
  [].concat(_toConsumableArray(CAPSULE_PRESETS), _toConsumableArray(PROGRESS_PRESETS));
409
- function validatePreset(preset) {
410
- 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);
411
- }
412
- function validateProgressPreset(preset) {
413
- 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);
414
- }
412
+
413
+ /**
414
+ * Resolve a preset by its literary name (e.g. '沧溟').
415
+ * Matching is case-insensitive and ignores surrounding whitespace,
416
+ * so '沧溟' and ' 沧溟 ' both work.
417
+ */
415
418
  function getPreset(kind, ref) {
416
419
  var list = kind === 'capsule' ? CAPSULE_PRESETS : kind === 'progress' ? PROGRESS_PRESETS : null;
417
420
  if (!list) throw new Error("Unknown preset kind: ".concat(kind, " (use \"capsule\" or \"progress\")"));
418
- if (ref && _typeof(ref) === 'object') {
419
- var valid = kind === 'capsule' ? validatePreset(ref) : validateProgressPreset(ref);
420
- if (!valid) throw new Error("Invalid ".concat(kind, " preset object"));
421
- return ref;
422
- }
423
421
  var key = String(ref).trim().toLowerCase();
424
422
  var found = list.find(function (preset) {
425
- return preset.id.toLowerCase() === key || preset.code.toLowerCase() === key || preset.name.toLowerCase() === key;
423
+ return preset.name.toLowerCase() === key;
426
424
  });
427
425
  if (!found) throw new Error("Unknown ".concat(kind, " preset: ").concat(ref));
428
426
  return found;
@@ -435,9 +433,8 @@ var DEFAULTS = {
435
433
  quality: 'auto',
436
434
  renderer: 'auto',
437
435
  respectReducedMotion: true,
438
- interactive: true,
439
436
  mouseColor: true,
440
- showCopy: true
437
+ textRatio: 39
441
438
  },
442
439
  progress: {
443
440
  width: 454,
@@ -446,35 +443,242 @@ var DEFAULTS = {
446
443
  max: 100,
447
444
  draggable: true,
448
445
  keyboard: true,
446
+ disabled: false,
447
+ valueSuffix: '%',
449
448
  edgeStyle: 'flow',
450
449
  quality: 'auto',
451
450
  renderer: 'auto',
452
- showCopy: true,
451
+ textRatio: 54,
452
+ showValue: true,
453
453
  respectReducedMotion: true
454
454
  }
455
455
  };
456
456
 
457
- /**
458
- * All user-facing copy lives here so wording/brand changes never require a
459
- * global search. Templates use {brand} {code} {name} placeholders.
457
+ /**
458
+ * Internal accessibility labels and small UI text. Since the copy API was
459
+ * removed (slots own the text area), these are no longer user-overridable.
460
+ * Templates use {brand} {code} {name} placeholders.
460
461
  */
461
462
  var COPY = {
462
463
  brandName: '画境观屿',
463
- dragLabel: 'DRAG',
464
464
  valueSuffix: '%',
465
465
  progressAria: '{brand} {code} 加载进度',
466
466
  capsuleAria: '打开 {name} 沉浸预览'
467
467
  };
468
468
 
469
- function hexToRgb01$1(hex) {
470
- var normalized = hex.replace('#', '');
471
- var value = Number.parseInt(normalized, 16);
469
+ /**
470
+ * Color helpers. `normalizeColor` converts any supported CSS color
471
+ * (hex / named / rgb() / rgba()) into a 6-digit hex string, so renderers can
472
+ * keep working with #rrggbb only. rgba() alpha is intentionally dropped:
473
+ * the WebGL shader has no per-color alpha channel, and the component is
474
+ * opaque by design — use component-level `opacity` for transparency.
475
+ */
476
+
477
+ var NAMED_COLORS = {
478
+ aliceblue: '#f0f8ff',
479
+ antiquewhite: '#faebd7',
480
+ aqua: '#00ffff',
481
+ aquamarine: '#7fffd4',
482
+ azure: '#f0ffff',
483
+ beige: '#f5f5dc',
484
+ bisque: '#ffe4c4',
485
+ black: '#000000',
486
+ blanchedalmond: '#ffebcd',
487
+ blue: '#0000ff',
488
+ blueviolet: '#8a2be2',
489
+ brown: '#a52a2a',
490
+ burlywood: '#deb887',
491
+ cadetblue: '#5f9ea0',
492
+ chartreuse: '#7fff00',
493
+ chocolate: '#d2691e',
494
+ coral: '#ff7f50',
495
+ cornflowerblue: '#6495ed',
496
+ cornsilk: '#fff8dc',
497
+ crimson: '#dc143c',
498
+ cyan: '#00ffff',
499
+ darkblue: '#00008b',
500
+ darkcyan: '#008b8b',
501
+ darkgoldenrod: '#b8860b',
502
+ darkgray: '#a9a9a9',
503
+ darkgreen: '#006400',
504
+ darkgrey: '#a9a9a9',
505
+ darkkhaki: '#bdb76b',
506
+ darkmagenta: '#8b008b',
507
+ darkolivegreen: '#556b2f',
508
+ darkorange: '#ff8c00',
509
+ darkorchid: '#9932cc',
510
+ darkred: '#8b0000',
511
+ darksalmon: '#e9967a',
512
+ darkseagreen: '#8fbc8f',
513
+ darkslateblue: '#483d8b',
514
+ darkslategray: '#2f4f4f',
515
+ darkslategrey: '#2f4f4f',
516
+ darkturquoise: '#00ced1',
517
+ darkviolet: '#9400d3',
518
+ deeppink: '#ff1493',
519
+ deepskyblue: '#00bfff',
520
+ dimgray: '#696969',
521
+ dimgrey: '#696969',
522
+ dodgerblue: '#1e90ff',
523
+ firebrick: '#b22222',
524
+ floralwhite: '#fffaf0',
525
+ forestgreen: '#228b22',
526
+ fuchsia: '#ff00ff',
527
+ gainsboro: '#dcdcdc',
528
+ ghostwhite: '#f8f8ff',
529
+ gold: '#ffd700',
530
+ goldenrod: '#daa520',
531
+ gray: '#808080',
532
+ green: '#008000',
533
+ greenyellow: '#adff2f',
534
+ grey: '#808080',
535
+ honeydew: '#f0fff0',
536
+ hotpink: '#ff69b4',
537
+ indianred: '#cd5c5c',
538
+ indigo: '#4b0082',
539
+ ivory: '#fffff0',
540
+ khaki: '#f0e68c',
541
+ lavender: '#e6e6fa',
542
+ lavenderblush: '#fff0f5',
543
+ lawngreen: '#7cfc00',
544
+ lemonchiffon: '#fffacd',
545
+ lightblue: '#add8e6',
546
+ lightcoral: '#f08080',
547
+ lightcyan: '#e0ffff',
548
+ lightgoldenrodyellow: '#fafad2',
549
+ lightgray: '#d3d3d3',
550
+ lightgreen: '#90ee90',
551
+ lightgrey: '#d3d3d3',
552
+ lightpink: '#ffb6c1',
553
+ lightsalmon: '#ffa07a',
554
+ lightseagreen: '#20b2aa',
555
+ lightskyblue: '#87cefa',
556
+ lightslategray: '#778899',
557
+ lightslategrey: '#778899',
558
+ lightsteelblue: '#b0c4de',
559
+ lightyellow: '#ffffe0',
560
+ lime: '#00ff00',
561
+ limegreen: '#32cd32',
562
+ linen: '#faf0e6',
563
+ magenta: '#ff00ff',
564
+ maroon: '#800000',
565
+ mediumaquamarine: '#66cdaa',
566
+ mediumblue: '#0000cd',
567
+ mediumorchid: '#ba55d3',
568
+ mediumpurple: '#9370db',
569
+ mediumseagreen: '#3cb371',
570
+ mediumslateblue: '#7b68ee',
571
+ mediumspringgreen: '#00fa9a',
572
+ mediumturquoise: '#48d1cc',
573
+ mediumvioletred: '#c71585',
574
+ midnightblue: '#191970',
575
+ mintcream: '#f5fffa',
576
+ mistyrose: '#ffe4e1',
577
+ moccasin: '#ffe4b5',
578
+ navajowhite: '#ffdead',
579
+ navy: '#000080',
580
+ oldlace: '#fdf5e6',
581
+ olive: '#808000',
582
+ olivedrab: '#6b8e23',
583
+ orange: '#ffa500',
584
+ orangered: '#ff4500',
585
+ orchid: '#da70d6',
586
+ palegoldenrod: '#eee8aa',
587
+ palegreen: '#98fb98',
588
+ paleturquoise: '#afeeee',
589
+ palevioletred: '#db7093',
590
+ papayawhip: '#ffefd5',
591
+ peachpuff: '#ffdab9',
592
+ peru: '#cd853f',
593
+ pink: '#ffc0cb',
594
+ plum: '#dda0dd',
595
+ powderblue: '#b0e0e6',
596
+ purple: '#800080',
597
+ rebeccapurple: '#663399',
598
+ red: '#ff0000',
599
+ rosybrown: '#bc8f8f',
600
+ royalblue: '#4169e1',
601
+ saddlebrown: '#8b4513',
602
+ salmon: '#fa8072',
603
+ sandybrown: '#f4a460',
604
+ seagreen: '#2e8b57',
605
+ seashell: '#fff5ee',
606
+ sienna: '#a0522d',
607
+ silver: '#c0c0c0',
608
+ skyblue: '#87ceeb',
609
+ slateblue: '#6a5acd',
610
+ slategray: '#708090',
611
+ slategrey: '#708090',
612
+ snow: '#fffafa',
613
+ springgreen: '#00ff7f',
614
+ steelblue: '#4682b4',
615
+ tan: '#d2b48c',
616
+ teal: '#008080',
617
+ thistle: '#d8bfd8',
618
+ tomato: '#ff6347',
619
+ turquoise: '#40e0d0',
620
+ violet: '#ee82ee',
621
+ wheat: '#f5deb3',
622
+ white: '#ffffff',
623
+ whitesmoke: '#f5f5f5',
624
+ yellow: '#ffff00',
625
+ yellowgreen: '#9acd32'
626
+ };
627
+ function clampChannel(value) {
628
+ return Math.min(255, Math.max(0, Math.round(value)));
629
+ }
630
+ function normalizeRgbArgs(args) {
631
+ var parts = args.split(/[,\s/]+/).filter(Boolean);
632
+ if (parts.length < 3) return null;
633
+ var to255 = function to255(value) {
634
+ if (typeof value !== 'string' || !value) return null;
635
+ if (value.endsWith('%')) return clampChannel(parseFloat(value) / 100 * 255);
636
+ var number = Number(value);
637
+ return Number.isFinite(number) ? clampChannel(number) : null;
638
+ };
639
+ var red = to255(parts[0]);
640
+ var green = to255(parts[1]);
641
+ var blue = to255(parts[2]);
642
+ if (red === null || green === null || blue === null) return null;
643
+ return "#".concat([red, green, blue].map(function (n) {
644
+ return n.toString(16).padStart(2, '0');
645
+ }).join(''));
646
+ }
647
+
648
+ /**
649
+ * Convert any supported CSS color into `#rrggbb`. Returns null when the
650
+ * value cannot be parsed. Supports: #rgb / #rrggbb (case-insensitive),
651
+ * CSS named colors, rgb() / rgba() with comma or modern space syntax,
652
+ * including percentages. Alpha in rgba() is ignored.
653
+ */
654
+ function normalizeColor(value) {
655
+ if (typeof value !== 'string') return null;
656
+ var input = value.trim();
657
+ if (!input) return null;
658
+ var lower = input.toLowerCase();
659
+ if (NAMED_COLORS[lower]) return NAMED_COLORS[lower];
660
+ if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(input)) {
661
+ var hex = input.slice(1).toLowerCase();
662
+ if (hex.length === 3) return "#".concat(hex.split('').map(function (c) {
663
+ return c + c;
664
+ }).join(''));
665
+ return "#".concat(hex);
666
+ }
667
+ var match = input.match(/^rgba?\((.*)\)$/i);
668
+ if (match) return normalizeRgbArgs(match[1]);
669
+ return null;
670
+ }
671
+ function hexToRgb01$1(color) {
672
+ var hex = normalizeColor(color);
673
+ if (!hex) return [0, 0, 0];
674
+ var value = Number.parseInt(hex.slice(1), 16);
472
675
  return [(value >> 16 & 255) / 255, (value >> 8 & 255) / 255, (value & 255) / 255];
473
676
  }
474
- function hexToRgba(hex) {
677
+ function hexToRgba(color) {
475
678
  var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
476
- var normalized = hex.replace('#', '');
477
- var value = Number.parseInt(normalized, 16);
679
+ var hex = normalizeColor(color);
680
+ if (!hex) return 'rgba(0, 0, 0, 0)';
681
+ var value = Number.parseInt(hex.slice(1), 16);
478
682
  var red = value >> 16 & 255;
479
683
  var green = value >> 8 & 255;
480
684
  var blue = value & 255;
@@ -555,6 +759,26 @@ var CosmicRenderer = /*#__PURE__*/function () {
555
759
  this.options.dprCap = cap;
556
760
  this.resize();
557
761
  }
762
+ }, {
763
+ key: "setMouseColor",
764
+ value: function setMouseColor(enabled) {
765
+ this.options.mouseColor = enabled !== false;
766
+ if (this.options.mouseColor) {
767
+ if (this.onPointerMove) return this;
768
+ _assertClassBrand(_CosmicRenderer_brand, this, _bindEvents).call(this);
769
+ return this;
770
+ }
771
+ if (this.onPointerMove) {
772
+ var target = this.eventTarget;
773
+ target.removeEventListener('pointermove', this.onPointerMove);
774
+ target.removeEventListener('pointerdown', this.onPointerMove);
775
+ target.removeEventListener('pointerleave', this.onPointerLeave);
776
+ this.onPointerMove = null;
777
+ this.onPointerLeave = null;
778
+ }
779
+ this.motionTarget = 0;
780
+ return this;
781
+ }
558
782
  }, {
559
783
  key: "randomize",
560
784
  value: function randomize() {
@@ -703,6 +927,8 @@ var FallbackRenderer = /*#__PURE__*/function () {
703
927
  var _this$canvas = this.canvas,
704
928
  width = _this$canvas.width,
705
929
  height = _this$canvas.height;
930
+ var t = time * (this.preset.speed || 1);
931
+ var phase = (this.preset.seed || 0) * 0.7;
706
932
  var gradient = ctx.createLinearGradient(0, 0, width, height);
707
933
  gradient.addColorStop(0, this.preset.colors[0]);
708
934
  gradient.addColorStop(0.38, this.preset.colors[1]);
@@ -712,8 +938,8 @@ var FallbackRenderer = /*#__PURE__*/function () {
712
938
  ctx.fillRect(0, 0, width, height);
713
939
  ctx.globalCompositeOperation = 'screen';
714
940
  for (var index = 0; index < 6; index += 1) {
715
- var x = (0.5 + 0.45 * Math.sin(time * 0.32 + index * 1.7)) * width;
716
- var y = (0.5 + 0.4 * Math.cos(time * 0.25 + index)) * height;
941
+ var x = (0.5 + 0.45 * Math.sin(t * 0.32 + index * 1.7 + phase)) * width;
942
+ var y = (0.5 + 0.4 * Math.cos(t * 0.25 + index + phase)) * height;
717
943
  var radius = Math.max(width, height) * (0.08 + index % 3 * 0.04);
718
944
  var glow = ctx.createRadialGradient(x, y, 0, x, y, radius);
719
945
  glow.addColorStop(0, rgb(this.preset.colors[(index + 1) % 4], 0.24));
@@ -737,7 +963,12 @@ var FallbackRenderer = /*#__PURE__*/function () {
737
963
  }
738
964
  }, {
739
965
  key: "randomize",
740
- value: function randomize() {}
966
+ value: function randomize() {
967
+ if (this.preset) this.preset.seed = Math.random() * 100;
968
+ }
969
+ }, {
970
+ key: "setMouseColor",
971
+ value: function setMouseColor() {}
741
972
  }, {
742
973
  key: "dispose",
743
974
  value: function dispose() {}
@@ -848,16 +1079,34 @@ function createVisibilityGuard(element) {
848
1079
  };
849
1080
  }
850
1081
 
851
- function prefersReducedMotion$1() {
1082
+ /**
1083
+ * Run a callback asynchronously, right after the current task and before the
1084
+ * next paint. Used for mount-time events (ready / error) so listeners that
1085
+ * are attached after create() still receive them. Falls back for legacy
1086
+ * browsers that lack queueMicrotask / Promise.
1087
+ */
1088
+ function nextTick(fn) {
1089
+ if (typeof queueMicrotask === 'function') {
1090
+ queueMicrotask(fn);
1091
+ } else if (typeof Promise !== 'undefined' && typeof Promise.resolve === 'function') {
1092
+ Promise.resolve().then(fn);
1093
+ } else {
1094
+ setTimeout(fn, 0);
1095
+ }
1096
+ }
1097
+
1098
+ function prefersReducedMotion$2() {
852
1099
  return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
853
1100
  }
854
1101
 
855
1102
  /**
856
- * Mount a cosmic (nebula) capsule into `container`.
857
- *
858
- * Options: preset (id/code/name or object), width, height (number=px or
859
- * string with px/%/vw/vh/em/rem), colors, seed, speed, quality, interactive,
860
- * respectReducedMotion, copy, cssVars.
1103
+ * Mount a cosmic (nebula) capsule into `container`.
1104
+ *
1105
+ * Options: preset (literary name), width, height (number=px or string with
1106
+ * px/%/vw/vh/em/rem), colors, seed, speed, textRatio (0-100, text region
1107
+ * width in percent), text (HTML string or DOM nodes for the text slot),
1108
+ * colorContent (HTML string or DOM nodes for the color slot), quality,
1109
+ * renderer, respectReducedMotion, mouseColor, cssVars.
861
1110
  */
862
1111
  function createCapsule(container) {
863
1112
  var _options$preset;
@@ -865,53 +1114,73 @@ function createCapsule(container) {
865
1114
  if (!container || typeof container.appendChild !== 'function') {
866
1115
  throw new Error('createCapsule: container element is required');
867
1116
  }
868
- var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : 'NC-01'));
1117
+ var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '初光'));
869
1118
  var merged = normalizeOptions(DEFAULTS.capsule, preset, options);
870
- var copy = _objectSpread2(_objectSpread2({}, COPY), merged.copy || {});
1119
+ var normalizedColors = merged.colors.map(normalizeColor);
1120
+ if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
1121
+ preset.seed = merged.seed;
1122
+ preset.speed = merged.speed;
1123
+ var customLabel = typeof options.label === 'string' && options.label ? options.label : null;
871
1124
  var root = document.createElement('div');
872
1125
  root.className = 'hj-capsule-root hj-capsule-cosmic';
873
1126
  root.dataset.group = preset.group;
874
1127
  root.dataset.mode = 'nebula';
875
1128
  root.dataset.theme = preset.theme || 'light';
876
- root.setAttribute('aria-label', copy.capsuleAria.replace('{name}', preset.name));
877
- var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
878
- var copyText = function copyText(key, fallback) {
879
- var value = copy[key];
880
- return value === undefined ? fallback : value;
1129
+ root.setAttribute('role', 'img');
1130
+ var updateAria = function updateAria() {
1131
+ root.setAttribute('aria-label', customLabel || COPY.capsuleAria.replace('{name}', preset.name));
881
1132
  };
882
- function buildCopyHtml() {
883
- var codeText = copyText('code', preset.code);
884
- var nameText = copyText('name', preset.name);
885
- var subtitleText = copyText('subtitle', preset.subtitle);
886
- var stateText = copyText('state', 'LIVE COSMIC STUDY');
887
- var html = '';
888
- if (codeText) html += "<span class=\"hj-capsule-code\">".concat(codeText, "</span>");
889
- if (nameText) html += "<span class=\"hj-capsule-name\">".concat(nameText, "</span>");
890
- if (subtitleText) html += "<span class=\"hj-capsule-brand\">".concat(subtitleText, "</span>");
891
- if (stateText) html += "<span class=\"hj-capsule-state\">".concat(stateText, "</span>");
892
- return html;
893
- }
894
- var copyLayer = document.createElement('div');
895
- copyLayer.className = 'hj-capsule-copy';
896
- var renderCopy = function renderCopy() {
897
- if (copyEnabled) copyLayer.innerHTML = buildCopyHtml();
898
- };
899
- renderCopy();
900
- var isHexColor = function isHexColor(value) {
901
- return typeof value === 'string' && /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(value);
1133
+ updateAria();
1134
+
1135
+ // Slot containers are always present but transparent by default: without
1136
+ // content they are invisible, so "no slot" behaves like the old
1137
+ // showCopy=false. They only provide geometry — no typography, padding or
1138
+ // background is imposed on user content (see docs: 插槽 CSS 约定).
1139
+ var fillContent = function fillContent(layer, content) {
1140
+ layer.innerHTML = '';
1141
+ if (content == null) return;
1142
+ if (typeof content === 'string') {
1143
+ layer.innerHTML = content;
1144
+ return;
1145
+ }
1146
+ var nodes = Array.isArray(content) ? content : [content];
1147
+ var _iterator = _createForOfIteratorHelper(nodes),
1148
+ _step;
1149
+ try {
1150
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
1151
+ var node = _step.value;
1152
+ if (node && typeof node.nodeType === 'number') layer.appendChild(node);
1153
+ }
1154
+ } catch (err) {
1155
+ _iterator.e(err);
1156
+ } finally {
1157
+ _iterator.f();
1158
+ }
902
1159
  };
903
- if (copy.background) {
904
- 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);
905
- }
906
- if (copy.color) root.style.setProperty('--hj-copy-color', copy.color);
1160
+ var textLayer = document.createElement('div');
1161
+ textLayer.className = 'hj-capsule-text hj-capsule-copy';
1162
+ var visualLayer = document.createElement('div');
1163
+ visualLayer.className = 'hj-capsule-visual';
1164
+ fillContent(textLayer, options.text);
1165
+ fillContent(visualLayer, options.colorContent);
907
1166
  var canvas = document.createElement('canvas');
908
1167
  canvas.className = 'hj-capsule-canvas';
909
1168
  canvas.setAttribute('aria-hidden', 'true');
910
- if (copyEnabled) root.appendChild(copyLayer);
1169
+ root.appendChild(textLayer);
1170
+ root.appendChild(visualLayer);
911
1171
  root.appendChild(canvas);
912
1172
  container.appendChild(root);
913
1173
  var emitter = createEmitter();
914
- var paused = merged.respectReducedMotion && prefersReducedMotion$1();
1174
+ var paused = merged.respectReducedMotion && prefersReducedMotion$2();
1175
+ var disposed = false;
1176
+ var dirty = {
1177
+ preset: false,
1178
+ seed: false,
1179
+ speed: false,
1180
+ colors: false,
1181
+ textRatio: false,
1182
+ cssVars: false
1183
+ };
915
1184
  var renderer;
916
1185
  var useWebgl = merged.renderer !== 'canvas2d';
917
1186
  if (useWebgl) {
@@ -921,8 +1190,11 @@ function createCapsule(container) {
921
1190
  });
922
1191
  } catch (error) {
923
1192
  renderer = new FallbackRenderer(canvas, merged);
924
- emitter.emit('error', {
925
- message: String(error && error.message ? error.message : error)
1193
+ nextTick(function () {
1194
+ if (disposed) return;
1195
+ emitter.emit('error', {
1196
+ message: String(error && error.message ? error.message : error)
1197
+ });
926
1198
  });
927
1199
  }
928
1200
  } else {
@@ -936,6 +1208,9 @@ function createCapsule(container) {
936
1208
  var name = _Object$keys[_i];
937
1209
  root.style.setProperty(name, vars[name]);
938
1210
  }
1211
+ if (merged.textRatio !== undefined) {
1212
+ root.style.setProperty('--hj-text-width', "".concat(merged.textRatio, "%"));
1213
+ }
939
1214
  renderer.resize();
940
1215
  };
941
1216
  applySize();
@@ -944,18 +1219,16 @@ function createCapsule(container) {
944
1219
  }) : null;
945
1220
  if (resizeObserver) resizeObserver.observe(root);else window.addEventListener('resize', renderer.resize);
946
1221
  var visibility = createVisibilityGuard(root);
947
- if (merged.interactive !== false) {
948
- root.addEventListener('pointerenter', function () {
949
- return emitter.emit('pointerenter', {
950
- preset: _objectSpread2({}, preset)
951
- });
1222
+ root.addEventListener('pointerenter', function () {
1223
+ return emitter.emit('pointerenter', {
1224
+ preset: _objectSpread2({}, preset)
952
1225
  });
953
- root.addEventListener('pointerleave', function () {
954
- return emitter.emit('pointerleave', {
955
- preset: _objectSpread2({}, preset)
956
- });
1226
+ });
1227
+ root.addEventListener('pointerleave', function () {
1228
+ return emitter.emit('pointerleave', {
1229
+ preset: _objectSpread2({}, preset)
957
1230
  });
958
- }
1231
+ });
959
1232
  root.addEventListener('click', function (event) {
960
1233
  emitter.emit('click', {
961
1234
  event: event,
@@ -987,13 +1260,16 @@ function createCapsule(container) {
987
1260
  }, function () {
988
1261
  return paused;
989
1262
  });
990
- emitter.emit('ready', {
991
- preset: _objectSpread2({}, preset)
1263
+ nextTick(function () {
1264
+ if (disposed) return;
1265
+ emitter.emit('ready', {
1266
+ preset: _objectSpread2({}, preset)
1267
+ });
992
1268
  });
993
- var syncCopy = function syncCopy() {
1269
+ var syncTheme = function syncTheme() {
994
1270
  root.dataset.mode = 'nebula';
995
1271
  root.dataset.theme = preset.theme || 'light';
996
- renderCopy();
1272
+ updateAria();
997
1273
  };
998
1274
  return {
999
1275
  element: root,
@@ -1003,9 +1279,12 @@ function createCapsule(container) {
1003
1279
  off: emitter.off,
1004
1280
  setPreset: function setPreset(ref) {
1005
1281
  var next = getPreset('capsule', ref);
1282
+ dirty.preset = true;
1006
1283
  Object.assign(preset, next);
1007
- renderer.setPreset(next);
1008
- syncCopy();
1284
+ var nextColors = preset.colors.map(normalizeColor);
1285
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
1286
+ renderer.setPreset(_objectSpread2({}, preset));
1287
+ syncTheme();
1009
1288
  renderer.resize();
1010
1289
  emitter.emit('presetchange', {
1011
1290
  preset: _objectSpread2({}, next)
@@ -1013,13 +1292,64 @@ function createCapsule(container) {
1013
1292
  return this;
1014
1293
  },
1015
1294
  setColors: function setColors(colors) {
1016
- if (!Array.isArray(colors) || colors.length !== 4) return this;
1017
- preset.colors = colors;
1295
+ var next = Array.isArray(colors) ? colors.map(normalizeColor) : [];
1296
+ if (next.length !== 4 || next.some(function (color) {
1297
+ return !color;
1298
+ })) return this;
1299
+ dirty.colors = true;
1300
+ preset.colors = next;
1018
1301
  renderer.setPreset(_objectSpread2(_objectSpread2({}, preset), {}, {
1019
- colors: colors
1302
+ colors: next
1020
1303
  }));
1021
1304
  return this;
1022
1305
  },
1306
+ setSeed: function setSeed(seed) {
1307
+ var value = Number(seed);
1308
+ if (!Number.isFinite(value)) return this;
1309
+ dirty.seed = true;
1310
+ preset.seed = value;
1311
+ renderer.setPreset(_objectSpread2({}, preset));
1312
+ return this;
1313
+ },
1314
+ setSpeed: function setSpeed(speed) {
1315
+ var value = Number(speed);
1316
+ if (!Number.isFinite(value)) return this;
1317
+ dirty.speed = true;
1318
+ preset.speed = value;
1319
+ renderer.setPreset(_objectSpread2({}, preset));
1320
+ return this;
1321
+ },
1322
+ setText: function setText(content) {
1323
+ fillContent(textLayer, content);
1324
+ return this;
1325
+ },
1326
+ setColorContent: function setColorContent(content) {
1327
+ fillContent(visualLayer, content);
1328
+ return this;
1329
+ },
1330
+ setTextRatio: function setTextRatio(ratio) {
1331
+ var value = Number(ratio);
1332
+ if (!Number.isFinite(value) || value < 0 || value > 100) return this;
1333
+ dirty.textRatio = true;
1334
+ merged.textRatio = value;
1335
+ root.style.setProperty('--hj-text-width', "".concat(value, "%"));
1336
+ return this;
1337
+ },
1338
+ setCssVars: function setCssVars(vars) {
1339
+ if (!vars || _typeof(vars) !== 'object') return this;
1340
+ dirty.cssVars = true;
1341
+ merged.cssVars = _objectSpread2(_objectSpread2({}, merged.cssVars || {}), vars);
1342
+ for (var _i2 = 0, _Object$keys2 = Object.keys(vars); _i2 < _Object$keys2.length; _i2++) {
1343
+ var name = _Object$keys2[_i2];
1344
+ root.style.setProperty(name, vars[name]);
1345
+ }
1346
+ return this;
1347
+ },
1348
+ setLabel: function setLabel(label) {
1349
+ customLabel = typeof label === 'string' && label ? label : null;
1350
+ updateAria();
1351
+ return this;
1352
+ },
1023
1353
  setSize: function setSize(width, height) {
1024
1354
  if (width !== undefined) merged.width = width;
1025
1355
  if (height !== undefined) merged.height = height;
@@ -1027,7 +1357,7 @@ function createCapsule(container) {
1027
1357
  return this;
1028
1358
  },
1029
1359
  randomize: function randomize() {
1030
- renderer.randomize();
1360
+ this.setSeed(Math.random() * 100);
1031
1361
  return this;
1032
1362
  },
1033
1363
  pause: function pause() {
@@ -1044,12 +1374,16 @@ function createCapsule(container) {
1044
1374
  return this;
1045
1375
  },
1046
1376
  dispose: function dispose() {
1377
+ disposed = true;
1047
1378
  unsubscribe();
1048
1379
  visibility.dispose();
1049
1380
  if (resizeObserver) resizeObserver.disconnect();else window.removeEventListener('resize', renderer.resize);
1050
1381
  renderer.dispose();
1051
1382
  root.remove();
1052
- }
1383
+ },
1384
+ textRatio: merged.textRatio,
1385
+ cssVars: merged.cssVars,
1386
+ dirty: dirty
1053
1387
  };
1054
1388
  }
1055
1389
 
@@ -1491,7 +1825,7 @@ function interpolate(template, values) {
1491
1825
  return values[key] !== undefined ? values[key] : '';
1492
1826
  });
1493
1827
  }
1494
- function prefersReducedMotion() {
1828
+ function prefersReducedMotion$1() {
1495
1829
  return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
1496
1830
  }
1497
1831
  var FLOW_PROFILES = {
@@ -1553,7 +1887,8 @@ var FLOW_PROFILES = {
1553
1887
  };
1554
1888
  var ProgressCapsuleController = /*#__PURE__*/function () {
1555
1889
  function ProgressCapsuleController(_ref) {
1556
- var _options$min,
1890
+ var _options$valueSuffix,
1891
+ _options$min,
1557
1892
  _options$max,
1558
1893
  _options$value,
1559
1894
  _this = this;
@@ -1563,7 +1898,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1563
1898
  preset = _ref.preset,
1564
1899
  emitter = _ref.emitter,
1565
1900
  options = _ref.options,
1566
- copy = _ref.copy;
1901
+ copy = _ref.copy,
1902
+ dirty = _ref.dirty;
1567
1903
  _classCallCheck(this, ProgressCapsuleController);
1568
1904
  this.root = root;
1569
1905
  this.canvas = canvas;
@@ -1572,6 +1908,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1572
1908
  this.emitter = emitter;
1573
1909
  this.options = options;
1574
1910
  this.copy = copy;
1911
+ this.dirty = dirty;
1912
+ this.valueSuffix = (_options$valueSuffix = options.valueSuffix) !== null && _options$valueSuffix !== void 0 ? _options$valueSuffix : copy.valueSuffix;
1575
1913
  this.profile = preset.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
1576
1914
  this.min = (_options$min = options.min) !== null && _options$min !== void 0 ? _options$min : 0;
1577
1915
  this.max = (_options$max = options.max) !== null && _options$max !== void 0 ? _options$max : 100;
@@ -1611,12 +1949,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1611
1949
  var rounded = Math.round(this.value);
1612
1950
  this.root.style.setProperty('--progress', this.value.toFixed(2));
1613
1951
  this.root.setAttribute('aria-valuenow', String(rounded));
1614
- this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.copy.valueSuffix));
1615
- this.valueElement.textContent = "".concat(rounded).concat(this.copy.valueSuffix);
1616
- if (!this.suppressEvents) this.emitter.emit('change', {
1617
- value: this.value,
1618
- source: source
1619
- });
1952
+ this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.valueSuffix));
1953
+ if (this.valueElement) this.valueElement.textContent = "".concat(rounded).concat(this.valueSuffix);
1954
+ if (!this.suppressEvents) {
1955
+ if (this.dirty) this.dirty.value = true;
1956
+ this.emitter.emit('change', {
1957
+ value: this.value,
1958
+ source: source
1959
+ });
1960
+ }
1961
+ }
1962
+ }, {
1963
+ key: "setValueSuffix",
1964
+ value: function setValueSuffix(suffix) {
1965
+ this.valueSuffix = String(suffix == null ? '' : suffix);
1966
+ var rounded = Math.round(this.value);
1967
+ if (this.valueElement) this.valueElement.textContent = "".concat(rounded).concat(this.valueSuffix);
1968
+ this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.valueSuffix));
1969
+ return this;
1620
1970
  }
1621
1971
  }, {
1622
1972
  key: "resizeCanvas",
@@ -1791,7 +2141,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1791
2141
  var width = this.width;
1792
2142
  var height = this.height;
1793
2143
  if (!ctx || width <= 0 || height <= 0) return;
1794
- var shoreline = width * (this.value / 100);
2144
+ var range = Math.max(this.max - this.min, 1);
2145
+ var shoreline = width * Math.min(Math.max((this.value - this.min) / range, 0), 1);
1795
2146
  var time = this.flowTime;
1796
2147
  var _this$preset$colors = _slicedToArray(this.preset.colors, 4),
1797
2148
  dark = _this$preset$colors[0],
@@ -1906,7 +2257,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1906
2257
  value: function updateFromPointer(event) {
1907
2258
  var bounds = this.root.getBoundingClientRect();
1908
2259
  var ratio = bounds.width > 0 ? (event.clientX - bounds.left) / bounds.width : 0;
1909
- this.setProgress(ratio * 100, 'drag');
2260
+ this.setProgress(this.min + ratio * (this.max - this.min), 'drag');
1910
2261
  }
1911
2262
  }, {
1912
2263
  key: "beginDrag",
@@ -1914,6 +2265,8 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1914
2265
  if (event.button !== undefined && event.button !== 0) return;
1915
2266
  event.preventDefault();
1916
2267
  this.dragging = true;
2268
+ this.pendingPointer = null;
2269
+ this._dragRaf = 0;
1917
2270
  this.root.classList.add('is-dragging');
1918
2271
  try {
1919
2272
  var _this$root$setPointer, _this$root;
@@ -1927,15 +2280,31 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1927
2280
  }, {
1928
2281
  key: "moveDrag",
1929
2282
  value: function moveDrag(event) {
2283
+ var _this2 = this;
1930
2284
  if (!this.dragging) return;
1931
2285
  event.preventDefault();
1932
- this.updateFromPointer(event);
2286
+ // rAF 合并:一帧最多一次 setProgress/change,视觉仍每帧更新。
2287
+ this.pendingPointer = event;
2288
+ if (this._dragRaf) return;
2289
+ this._dragRaf = requestAnimationFrame(function () {
2290
+ _this2._dragRaf = 0;
2291
+ var pending = _this2.pendingPointer;
2292
+ _this2.pendingPointer = null;
2293
+ if (pending) _this2.updateFromPointer(pending);
2294
+ });
1933
2295
  }
1934
2296
  }, {
1935
2297
  key: "endDrag",
1936
2298
  value: function endDrag(event) {
1937
2299
  if (!this.dragging) return;
1938
2300
  this.dragging = false;
2301
+ if (this._dragRaf) {
2302
+ cancelAnimationFrame(this._dragRaf);
2303
+ this._dragRaf = 0;
2304
+ }
2305
+ var pending = this.pendingPointer;
2306
+ this.pendingPointer = null;
2307
+ if (pending) this.updateFromPointer(pending);
1939
2308
  this.root.classList.remove('is-dragging');
1940
2309
  try {
1941
2310
  var _this$root$hasPointer, _this$root2;
@@ -1950,19 +2319,19 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1950
2319
  }, {
1951
2320
  key: "bindEvents",
1952
2321
  value: function bindEvents() {
1953
- var _this2 = this;
2322
+ var _this3 = this;
1954
2323
  if (this.options.draggable !== false) {
1955
2324
  this.handlers.pointerdown = function (event) {
1956
- return _this2.beginDrag(event);
2325
+ return _this3.beginDrag(event);
1957
2326
  };
1958
2327
  this.handlers.pointermove = function (event) {
1959
- return _this2.moveDrag(event);
2328
+ return _this3.moveDrag(event);
1960
2329
  };
1961
2330
  this.handlers.pointerup = function (event) {
1962
- return _this2.endDrag(event);
2331
+ return _this3.endDrag(event);
1963
2332
  };
1964
2333
  this.handlers.pointercancel = function (event) {
1965
- return _this2.endDrag(event);
2334
+ return _this3.endDrag(event);
1966
2335
  };
1967
2336
  this.root.addEventListener('pointerdown', this.handlers.pointerdown);
1968
2337
  this.root.addEventListener('pointermove', this.handlers.pointermove);
@@ -1971,23 +2340,24 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
1971
2340
  }
1972
2341
  if (this.options.keyboard !== false) {
1973
2342
  this.handlers.keydown = function (event) {
2343
+ var step = (_this3.max - _this3.min) * 0.02;
1974
2344
  var actions = {
1975
- ArrowLeft: -2,
1976
- ArrowDown: -2,
1977
- ArrowRight: 2,
1978
- ArrowUp: 2,
1979
- PageDown: -10,
1980
- PageUp: 10
2345
+ ArrowLeft: -step,
2346
+ ArrowDown: -step,
2347
+ ArrowRight: step,
2348
+ ArrowUp: step,
2349
+ PageDown: -step * 5,
2350
+ PageUp: step * 5
1981
2351
  };
1982
2352
  if (event.key === 'Home') {
1983
2353
  event.preventDefault();
1984
- _this2.setProgress(_this2.min, 'keyboard');
2354
+ _this3.setProgress(_this3.min, 'keyboard');
1985
2355
  } else if (event.key === 'End') {
1986
2356
  event.preventDefault();
1987
- _this2.setProgress(_this2.max, 'keyboard');
2357
+ _this3.setProgress(_this3.max, 'keyboard');
1988
2358
  } else if (actions[event.key]) {
1989
2359
  event.preventDefault();
1990
- _this2.setProgress(_this2.value + actions[event.key], 'keyboard');
2360
+ _this3.setProgress(_this3.value + actions[event.key], 'keyboard');
1991
2361
  } else {
1992
2362
  return;
1993
2363
  }
@@ -2024,6 +2394,7 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
2024
2394
  }, {
2025
2395
  key: "dispose",
2026
2396
  value: function dispose() {
2397
+ if (this._dragRaf) cancelAnimationFrame(this._dragRaf);
2027
2398
  if (this.resizeObserver) this.resizeObserver.disconnect();else window.removeEventListener('resize', this.resizeCanvas);
2028
2399
  for (var _i = 0, _Object$keys = Object.keys(this.handlers); _i < _Object$keys.length; _i++) {
2029
2400
  var name = _Object$keys[_i];
@@ -2036,11 +2407,14 @@ var ProgressCapsuleController = /*#__PURE__*/function () {
2036
2407
  }();
2037
2408
 
2038
2409
  /**
2039
- * Mount a fluid progress capsule into `container`.
2040
- *
2041
- * Options: preset (id/code/name or object), width, height, value, min, max,
2042
- * draggable, keyboard, colors, edgeStyle, quality,
2043
- * respectReducedMotion, copy, cssVars.
2410
+ * Mount a fluid progress capsule into `container`.
2411
+ *
2412
+ * Options: preset (id/code/name or object), width, height, value, min, max,
2413
+ * draggable, keyboard, colors, edgeStyle, textRatio (0-100, text region
2414
+ * width in percent), text (HTML string or DOM nodes for the text slot),
2415
+ * colorContent (HTML string or DOM nodes for the color slot),
2416
+ * showValue (show/hide the right-side percentage), quality,
2417
+ * respectReducedMotion, cssVars.
2044
2418
  */
2045
2419
  function createProgressCapsule(container) {
2046
2420
  var _options$preset, _merged$min, _merged$max;
@@ -2048,64 +2422,93 @@ function createProgressCapsule(container) {
2048
2422
  if (!container || typeof container.appendChild !== 'function') {
2049
2423
  throw new Error('createProgressCapsule: container element is required');
2050
2424
  }
2051
- var preset = _objectSpread2({}, getPreset('progress', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : 'NC-10'));
2425
+ var preset = _objectSpread2({}, getPreset('progress', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '星火'));
2052
2426
  var merged = normalizeOptions(DEFAULTS.progress, preset, options);
2053
- var copy = _objectSpread2(_objectSpread2({}, COPY), merged.copy || {});
2427
+ var normalizedColors = merged.colors.map(normalizeColor);
2428
+ if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
2429
+ preset.edgeStyle = merged.edgeStyle;
2430
+ var copy = COPY;
2431
+ var customLabel = typeof options.label === 'string' && options.label ? options.label : null;
2432
+ // Vue 的裸布尔属性(<ProgressCapsule disabled />)会传成空字符串,
2433
+ // 这里统一按 true 处理。
2434
+ var disabled = merged.disabled === true || merged.disabled === '' || merged.disabled === 'true';
2435
+ var effectiveDraggable = disabled ? false : merged.draggable !== false;
2436
+ var effectiveKeyboard = disabled ? false : merged.keyboard !== false;
2437
+ var dirty = {
2438
+ preset: false,
2439
+ colors: false,
2440
+ textRatio: false,
2441
+ cssVars: false,
2442
+ edgeStyle: false,
2443
+ value: false
2444
+ };
2054
2445
  var root = document.createElement('div');
2055
2446
  root.className = 'hj-capsule-root hj-progress-root';
2056
2447
  root.setAttribute('role', 'slider');
2057
2448
  root.setAttribute('tabindex', '0');
2058
- root.setAttribute('data-draggable', String(merged.draggable !== false));
2449
+ root.setAttribute('data-draggable', String(effectiveDraggable));
2450
+ if (disabled) {
2451
+ root.setAttribute('aria-disabled', 'true');
2452
+ root.classList.add('is-disabled');
2453
+ }
2059
2454
  root.setAttribute('aria-valuemin', String((_merged$min = merged.min) !== null && _merged$min !== void 0 ? _merged$min : 0));
2060
2455
  root.setAttribute('aria-valuemax', String((_merged$max = merged.max) !== null && _merged$max !== void 0 ? _merged$max : 100));
2061
2456
  root.setAttribute('aria-valuenow', String(preset.initialProgress));
2062
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
2063
- brand: copy.brandName,
2064
- code: preset.code,
2065
- name: preset.name
2066
- }));
2067
- if (merged.keyboard === false) root.setAttribute('tabindex', '-1');
2457
+ var updateAria = function updateAria() {
2458
+ root.setAttribute('aria-label', customLabel || interpolate(copy.progressAria, {
2459
+ brand: copy.brandName,
2460
+ code: preset.code,
2461
+ name: preset.name
2462
+ }));
2463
+ };
2464
+ updateAria();
2465
+ if (!effectiveKeyboard) root.setAttribute('tabindex', '-1');
2068
2466
  var canvas = document.createElement('canvas');
2069
2467
  canvas.className = 'hj-progress-canvas';
2070
2468
  canvas.setAttribute('aria-hidden', 'true');
2071
- var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
2072
- var copyText = function copyText(key, fallback) {
2073
- var value = copy[key];
2074
- return value === undefined ? fallback : value;
2075
- };
2076
- function buildCopyHtml() {
2077
- var html = '';
2078
- var brandText = copy.brandName || '';
2079
- var subtitleText = copyText('subtitle', preset.subtitle);
2080
- if (brandText) html += "<span class=\"hj-progress-name\">".concat(brandText, "</span>");
2081
- if (subtitleText) html += "<span class=\"hj-progress-subtitle\">".concat(subtitleText, "</span>");
2082
- return html;
2083
- }
2084
- var copyLayer = document.createElement('div');
2085
- copyLayer.className = 'hj-progress-copy';
2086
- var renderCopy = function renderCopy() {
2087
- if (copyEnabled) copyLayer.innerHTML = buildCopyHtml();
2469
+
2470
+ // Slot containers are always present but transparent by default; they only
2471
+ // provide geometry, never typography/padding/background (docs: 插槽 CSS 约定).
2472
+ var fillContent = function fillContent(layer, content) {
2473
+ layer.innerHTML = '';
2474
+ if (content == null) return;
2475
+ if (typeof content === 'string') {
2476
+ layer.innerHTML = content;
2477
+ return;
2478
+ }
2479
+ var nodes = Array.isArray(content) ? content : [content];
2480
+ var _iterator2 = _createForOfIteratorHelper(nodes),
2481
+ _step2;
2482
+ try {
2483
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
2484
+ var node = _step2.value;
2485
+ if (node && typeof node.nodeType === 'number') layer.appendChild(node);
2486
+ }
2487
+ } catch (err) {
2488
+ _iterator2.e(err);
2489
+ } finally {
2490
+ _iterator2.f();
2491
+ }
2088
2492
  };
2089
- renderCopy();
2090
- if (copy.background) {
2091
- root.style.setProperty('--hj-progress-copy-bg', copy.background);
2092
- root.style.setProperty('--hj-progress-copy-pad', '6px 12px');
2493
+ var textLayer = document.createElement('div');
2494
+ textLayer.className = 'hj-progress-text hj-progress-copy';
2495
+ var visualLayer = document.createElement('div');
2496
+ visualLayer.className = 'hj-progress-visual';
2497
+ fillContent(textLayer, options.text);
2498
+ fillContent(visualLayer, options.colorContent);
2499
+ var valueElement = merged.showValue === false ? null : document.createElement('div');
2500
+ if (valueElement) {
2501
+ valueElement.className = 'hj-progress-value';
2502
+ valueElement.setAttribute('aria-hidden', 'true');
2093
2503
  }
2094
- if (copy.color) root.style.setProperty('--hj-progress-copy-color', copy.color);
2095
- var valueElement = document.createElement('div');
2096
- valueElement.className = 'hj-progress-value';
2097
- valueElement.setAttribute('aria-hidden', 'true');
2098
- var dragLabel = document.createElement('span');
2099
- dragLabel.className = 'hj-progress-drag-label';
2100
- dragLabel.setAttribute('aria-hidden', 'true');
2101
- dragLabel.textContent = copy.dragLabel;
2102
2504
  root.appendChild(canvas);
2103
- if (copyEnabled) root.appendChild(copyLayer);
2104
- root.appendChild(valueElement);
2105
- root.appendChild(dragLabel);
2505
+ root.appendChild(textLayer);
2506
+ root.appendChild(visualLayer);
2507
+ if (valueElement) root.appendChild(valueElement);
2106
2508
  container.appendChild(root);
2107
2509
  var emitter = createEmitter();
2108
- var paused = merged.respectReducedMotion && prefersReducedMotion();
2510
+ var paused = merged.respectReducedMotion && prefersReducedMotion$1();
2511
+ var disposed = false;
2109
2512
  var applySize = function applySize() {
2110
2513
  root.style.width = parseSize(merged.width);
2111
2514
  root.style.height = parseSize(merged.height);
@@ -2114,6 +2517,9 @@ function createProgressCapsule(container) {
2114
2517
  var name = _Object$keys2[_i2];
2115
2518
  root.style.setProperty(name, vars[name]);
2116
2519
  }
2520
+ if (merged.textRatio !== undefined) {
2521
+ root.style.setProperty('--hj-text-width', "".concat(merged.textRatio, "%"));
2522
+ }
2117
2523
  };
2118
2524
  applySize();
2119
2525
  var controller = new ProgressCapsuleController({
@@ -2122,8 +2528,12 @@ function createProgressCapsule(container) {
2122
2528
  valueElement: valueElement,
2123
2529
  preset: preset,
2124
2530
  emitter: emitter,
2125
- options: merged,
2126
- copy: copy
2531
+ options: _objectSpread2(_objectSpread2({}, merged), {}, {
2532
+ draggable: effectiveDraggable,
2533
+ keyboard: effectiveKeyboard
2534
+ }),
2535
+ copy: copy,
2536
+ dirty: dirty
2127
2537
  });
2128
2538
  var overlay = null;
2129
2539
  if (merged.renderer !== 'canvas2d') {
@@ -2136,7 +2546,14 @@ function createProgressCapsule(container) {
2136
2546
  }
2137
2547
  });
2138
2548
  }
2139
- if (overlay) controller.webglActive = true;
2549
+ if (overlay) controller.webglActive = true;else if (merged.renderer !== 'canvas2d') {
2550
+ nextTick(function () {
2551
+ if (disposed) return;
2552
+ emitter.emit('error', {
2553
+ message: 'WebGL2 unavailable, using Canvas2D fallback'
2554
+ });
2555
+ });
2556
+ }
2140
2557
  var visibility = createVisibilityGuard(root);
2141
2558
  var flowTime = 0;
2142
2559
  var unsubscribe = subscribeScheduler(function (delta, now) {
@@ -2149,16 +2566,14 @@ function createProgressCapsule(container) {
2149
2566
  }, function () {
2150
2567
  return paused;
2151
2568
  });
2152
- emitter.emit('ready', {
2153
- preset: _objectSpread2({}, preset)
2569
+ nextTick(function () {
2570
+ if (disposed) return;
2571
+ emitter.emit('ready', {
2572
+ preset: _objectSpread2({}, preset)
2573
+ });
2154
2574
  });
2155
2575
  var syncDom = function syncDom() {
2156
- root.setAttribute('aria-label', interpolate(copy.progressAria, {
2157
- brand: copy.brandName,
2158
- code: preset.code,
2159
- name: preset.name
2160
- }));
2161
- renderCopy();
2576
+ updateAria();
2162
2577
  };
2163
2578
  return {
2164
2579
  element: root,
@@ -2180,8 +2595,11 @@ function createProgressCapsule(container) {
2180
2595
  },
2181
2596
  setPreset: function setPreset(ref) {
2182
2597
  var next = getPreset('progress', ref);
2598
+ dirty.preset = true;
2183
2599
  Object.assign(preset, next);
2184
- controller.preset = next;
2600
+ var nextColors = preset.colors.map(normalizeColor);
2601
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
2602
+ controller.preset = preset;
2185
2603
  controller.profile = next.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[next.id] || FLOW_PROFILES['visual-training'];
2186
2604
  controller.flowTime = stringSeed(next.id) * 31;
2187
2605
  controller.seed = stringSeed("".concat(next.id, "-reference")) * Math.PI * 2;
@@ -2191,7 +2609,7 @@ function createProgressCapsule(container) {
2191
2609
  overlay = attachProgressFlowOverlay({
2192
2610
  root: root,
2193
2611
  canvas: canvas,
2194
- preset: next,
2612
+ preset: preset,
2195
2613
  getProgress: function getProgress() {
2196
2614
  return controller.value;
2197
2615
  }
@@ -2200,14 +2618,74 @@ function createProgressCapsule(container) {
2200
2618
  controller.webglActive = Boolean(overlay);
2201
2619
  controller.resizeCanvas();
2202
2620
  emitter.emit('presetchange', {
2203
- preset: _objectSpread2({}, next)
2621
+ preset: _objectSpread2({}, preset)
2204
2622
  });
2205
2623
  return this;
2206
2624
  },
2625
+ setEdgeStyle: function setEdgeStyle(edgeStyle) {
2626
+ var value = String(edgeStyle || '').toLowerCase();
2627
+ if (value !== 'flow' && value !== 'tide') return this;
2628
+ dirty.edgeStyle = true;
2629
+ preset.edgeStyle = value;
2630
+ controller.profile = value === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
2631
+ if (overlay) {
2632
+ overlay.dispose();
2633
+ overlay = attachProgressFlowOverlay({
2634
+ root: root,
2635
+ canvas: canvas,
2636
+ preset: preset,
2637
+ getProgress: function getProgress() {
2638
+ return controller.value;
2639
+ }
2640
+ });
2641
+ }
2642
+ controller.webglActive = Boolean(overlay);
2643
+ controller.resizeCanvas();
2644
+ return this;
2645
+ },
2646
+ setText: function setText(content) {
2647
+ fillContent(textLayer, content);
2648
+ return this;
2649
+ },
2650
+ setColorContent: function setColorContent(content) {
2651
+ fillContent(visualLayer, content);
2652
+ return this;
2653
+ },
2654
+ setTextRatio: function setTextRatio(ratio) {
2655
+ var value = Number(ratio);
2656
+ if (!Number.isFinite(value) || value < 0 || value > 100) return this;
2657
+ dirty.textRatio = true;
2658
+ merged.textRatio = value;
2659
+ root.style.setProperty('--hj-text-width', "".concat(value, "%"));
2660
+ return this;
2661
+ },
2662
+ setCssVars: function setCssVars(vars) {
2663
+ if (!vars || _typeof(vars) !== 'object') return this;
2664
+ dirty.cssVars = true;
2665
+ merged.cssVars = _objectSpread2(_objectSpread2({}, merged.cssVars || {}), vars);
2666
+ for (var _i3 = 0, _Object$keys3 = Object.keys(vars); _i3 < _Object$keys3.length; _i3++) {
2667
+ var name = _Object$keys3[_i3];
2668
+ root.style.setProperty(name, vars[name]);
2669
+ }
2670
+ return this;
2671
+ },
2672
+ setLabel: function setLabel(label) {
2673
+ _readOnlyError("customLabel");
2674
+ updateAria();
2675
+ return this;
2676
+ },
2677
+ setValueSuffix: function setValueSuffix(suffix) {
2678
+ controller.setValueSuffix(suffix);
2679
+ return this;
2680
+ },
2207
2681
  setColors: function setColors(colors) {
2208
- if (!Array.isArray(colors) || colors.length !== 4) return this;
2209
- controller.setColors(colors);
2210
- if (overlay) overlay.setColors(colors);
2682
+ var next = Array.isArray(colors) ? colors.map(normalizeColor) : [];
2683
+ if (next.length !== 4 || next.some(function (color) {
2684
+ return !color;
2685
+ })) return this;
2686
+ dirty.colors = true;
2687
+ controller.setColors(next);
2688
+ if (overlay) overlay.setColors(next);
2211
2689
  controller.resizeCanvas();
2212
2690
  return this;
2213
2691
  },
@@ -2237,12 +2715,223 @@ function createProgressCapsule(container) {
2237
2715
  return this;
2238
2716
  },
2239
2717
  dispose: function dispose() {
2718
+ disposed = true;
2240
2719
  unsubscribe();
2241
2720
  visibility.dispose();
2242
2721
  if (overlay) overlay.dispose();
2243
2722
  controller.dispose();
2244
2723
  root.remove();
2724
+ },
2725
+ textRatio: merged.textRatio,
2726
+ cssVars: merged.cssVars,
2727
+ dirty: dirty
2728
+ };
2729
+ }
2730
+
2731
+ function prefersReducedMotion() {
2732
+ return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
2733
+ }
2734
+
2735
+ /**
2736
+ * Mount the cosmic (nebula) material as a background layer inside `host`.
2737
+ *
2738
+ * The layer is absolutely positioned and defaults to `z-index: -1`, so it
2739
+ * paints behind the host's in-flow content: text/buttons/images inside the
2740
+ * host sit on top with zero extra CSS. Host gets `position: relative;
2741
+ * isolation: isolate` automatically so the layer can never escape its box
2742
+ * (or break stacking outside it).
2743
+ *
2744
+ * Options: preset (id/code/name or object), colors, seed, speed, quality,
2745
+ * renderer, mouseColor, respectReducedMotion, opacity (0-1), fallbackColor
2746
+ * (true=preset base color, a hex string, or false to disable).
2747
+ */
2748
+ function createColorBackground(host) {
2749
+ var _options$preset;
2750
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2751
+ if (!host || typeof host.appendChild !== 'function') {
2752
+ throw new Error('createColorBackground: host element is required');
2753
+ }
2754
+ var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '初光'));
2755
+ var merged = normalizeOptions({
2756
+ quality: DEFAULTS.capsule.quality,
2757
+ renderer: DEFAULTS.capsule.renderer,
2758
+ respectReducedMotion: DEFAULTS.capsule.respectReducedMotion,
2759
+ mouseColor: true,
2760
+ opacity: 1,
2761
+ fallbackColor: true
2762
+ }, preset, options);
2763
+ var normalizedColors = merged.colors.map(normalizeColor);
2764
+ if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
2765
+ preset.seed = merged.seed;
2766
+ preset.speed = merged.speed;
2767
+ var computed = getComputedStyle(host);
2768
+ if (computed.position === 'static' || computed.position === '') {
2769
+ host.style.position = 'relative';
2770
+ }
2771
+ host.style.isolation = 'isolate';
2772
+ var layer = document.createElement('div');
2773
+ layer.className = 'dlc-color-layer';
2774
+ var syncLayerVars = function syncLayerVars() {
2775
+ layer.style.setProperty('--dlc-color-opacity', String(merged.opacity));
2776
+ var fallback = merged.fallbackColor === false || merged.fallbackColor == null ? 'transparent' : typeof merged.fallbackColor === 'string' ? merged.fallbackColor : preset.colors[0];
2777
+ layer.style.setProperty('--dlc-color-bg', fallback);
2778
+ };
2779
+ syncLayerVars();
2780
+ var canvas = document.createElement('canvas');
2781
+ canvas.className = 'dlc-color-canvas';
2782
+ canvas.setAttribute('aria-hidden', 'true');
2783
+ layer.appendChild(canvas);
2784
+ host.appendChild(layer);
2785
+ var emitter = createEmitter();
2786
+ var paused = merged.respectReducedMotion && prefersReducedMotion();
2787
+ var disposed = false;
2788
+ var dirty = {
2789
+ preset: false,
2790
+ seed: false,
2791
+ speed: false,
2792
+ colors: false,
2793
+ opacity: false,
2794
+ fallbackColor: false,
2795
+ mouseColor: false
2796
+ };
2797
+ var renderer;
2798
+ var useWebgl = merged.renderer !== 'canvas2d';
2799
+ if (useWebgl) {
2800
+ try {
2801
+ renderer = new CosmicRenderer(canvas, merged, {
2802
+ dprCap: dprCapFor(merged.quality),
2803
+ mouseColor: merged.mouseColor !== false,
2804
+ eventTarget: host
2805
+ });
2806
+ } catch (error) {
2807
+ renderer = new FallbackRenderer(canvas, merged);
2808
+ nextTick(function () {
2809
+ if (disposed) return;
2810
+ emitter.emit('error', {
2811
+ message: String(error && error.message ? error.message : error)
2812
+ });
2813
+ });
2245
2814
  }
2815
+ } else {
2816
+ renderer = new FallbackRenderer(canvas, merged);
2817
+ }
2818
+ var resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(function () {
2819
+ return renderer.resize();
2820
+ }) : null;
2821
+ if (resizeObserver) resizeObserver.observe(host);else window.addEventListener('resize', renderer.resize);
2822
+ var visibility = createVisibilityGuard(layer);
2823
+ var animationTime = 0;
2824
+ var unsubscribe = subscribeScheduler(function (delta) {
2825
+ animationTime += delta;
2826
+ if (visibility.isVisible()) renderer.draw(animationTime);
2827
+ }, function () {
2828
+ return paused;
2829
+ });
2830
+ nextTick(function () {
2831
+ if (disposed) return;
2832
+ emitter.emit('ready', {
2833
+ preset: _objectSpread2({}, preset)
2834
+ });
2835
+ });
2836
+ return {
2837
+ element: host,
2838
+ layer: layer,
2839
+ canvas: canvas,
2840
+ preset: preset,
2841
+ on: emitter.on,
2842
+ off: emitter.off,
2843
+ setPreset: function setPreset(ref) {
2844
+ var next = getPreset('capsule', ref);
2845
+ dirty.preset = true;
2846
+ Object.assign(preset, next);
2847
+ var nextColors = preset.colors.map(normalizeColor);
2848
+ if (nextColors.every(Boolean)) preset.colors = nextColors;
2849
+ renderer.setPreset(_objectSpread2({}, preset));
2850
+ renderer.resize();
2851
+ syncLayerVars();
2852
+ emitter.emit('presetchange', {
2853
+ preset: _objectSpread2({}, preset)
2854
+ });
2855
+ return this;
2856
+ },
2857
+ setColors: function setColors(colors) {
2858
+ var next = Array.isArray(colors) ? colors.map(normalizeColor) : [];
2859
+ if (next.length !== 4 || next.some(function (color) {
2860
+ return !color;
2861
+ })) return this;
2862
+ dirty.colors = true;
2863
+ preset.colors = next;
2864
+ renderer.setPreset(_objectSpread2(_objectSpread2({}, preset), {}, {
2865
+ colors: next
2866
+ }));
2867
+ syncLayerVars();
2868
+ return this;
2869
+ },
2870
+ setSeed: function setSeed(seed) {
2871
+ var value = Number(seed);
2872
+ if (!Number.isFinite(value)) return this;
2873
+ dirty.seed = true;
2874
+ preset.seed = value;
2875
+ renderer.setPreset(_objectSpread2({}, preset));
2876
+ return this;
2877
+ },
2878
+ setSpeed: function setSpeed(speed) {
2879
+ var value = Number(speed);
2880
+ if (!Number.isFinite(value)) return this;
2881
+ dirty.speed = true;
2882
+ preset.speed = value;
2883
+ renderer.setPreset(_objectSpread2({}, preset));
2884
+ return this;
2885
+ },
2886
+ setFallbackColor: function setFallbackColor(value) {
2887
+ dirty.fallbackColor = true;
2888
+ merged.fallbackColor = value;
2889
+ syncLayerVars();
2890
+ return this;
2891
+ },
2892
+ setMouseColor: function setMouseColor(value) {
2893
+ dirty.mouseColor = true;
2894
+ merged.mouseColor = value !== false;
2895
+ if (typeof renderer.setMouseColor === 'function') renderer.setMouseColor(merged.mouseColor);
2896
+ return this;
2897
+ },
2898
+ setQuality: function setQuality(quality) {
2899
+ merged.quality = quality;
2900
+ if (typeof renderer.setDprCap === 'function') renderer.setDprCap(dprCapFor(quality));
2901
+ return this;
2902
+ },
2903
+ setOpacity: function setOpacity(value) {
2904
+ var opacity = Number(value);
2905
+ if (!Number.isFinite(opacity)) return this;
2906
+ dirty.opacity = true;
2907
+ merged.opacity = Math.min(1, Math.max(0, opacity));
2908
+ layer.style.setProperty('--dlc-color-opacity', String(merged.opacity));
2909
+ return this;
2910
+ },
2911
+ randomize: function randomize() {
2912
+ this.setSeed(Math.random() * 100);
2913
+ return this;
2914
+ },
2915
+ pause: function pause() {
2916
+ paused = true;
2917
+ return this;
2918
+ },
2919
+ resume: function resume() {
2920
+ paused = false;
2921
+ return this;
2922
+ },
2923
+ dispose: function dispose() {
2924
+ disposed = true;
2925
+ unsubscribe();
2926
+ visibility.dispose();
2927
+ if (resizeObserver) resizeObserver.disconnect();else window.removeEventListener('resize', renderer.resize);
2928
+ renderer.dispose();
2929
+ layer.remove();
2930
+ },
2931
+ opacity: merged.opacity,
2932
+ fallbackColor: merged.fallbackColor,
2933
+ mouseColor: merged.mouseColor,
2934
+ dirty: dirty
2246
2935
  };
2247
2936
  }
2248
2937
 
@@ -2254,6 +2943,7 @@ function createProgressCapsule(container) {
2254
2943
 
2255
2944
  var CAPSULE_EVENTS = ['ready', 'error', 'click', 'pointerdown', 'pointerup', 'dblclick', 'pointerenter', 'pointerleave', 'presetchange'];
2256
2945
  var PROGRESS_EVENTS = ['ready', 'error', 'change', 'dragstart', 'dragend', 'presetchange'];
2946
+ var COLOR_EVENTS = ['ready', 'error', 'presetchange'];
2257
2947
  function hookEvents(controller, events, emit) {
2258
2948
  var _iterator = _createForOfIteratorHelper(events),
2259
2949
  _step;
@@ -2284,15 +2974,18 @@ function makeWrapper(_ref) {
2284
2974
  var internalMethods = {
2285
2975
  mountController: function mountController() {
2286
2976
  var _this = this;
2287
- this.controller = create(this.$el, this.$props);
2977
+ var extraState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2978
+ this.controller = create(this.$el, _objectSpread2(_objectSpread2({}, this.$props), extraState));
2288
2979
  hookEvents(this.controller, events, function (event, payload) {
2289
2980
  return _this.$emit(event, payload);
2290
2981
  });
2982
+ this.moveSlots();
2983
+ this.applyAttrs();
2291
2984
  },
2292
2985
  recreate: function recreate() {
2986
+ var extraState = this.runtimeState();
2293
2987
  if (this.controller) this.controller.dispose();
2294
- if (this.$el) this.$el.innerHTML = '';
2295
- this.mountController();
2988
+ this.mountController(extraState);
2296
2989
  },
2297
2990
  scheduleRecreate: function scheduleRecreate() {
2298
2991
  var _this2 = this;
@@ -2302,6 +2995,52 @@ function makeWrapper(_ref) {
2302
2995
  _this2._recreateQueued = false;
2303
2996
  _this2.recreate();
2304
2997
  });
2998
+ },
2999
+ moveSlots: function moveSlots() {
3000
+ if (!this.controller || !this.controller.element || !this.$el) return;
3001
+ var root = this.controller.element;
3002
+ var textLayer = root.querySelector('.hj-capsule-text, .hj-progress-text');
3003
+ var visualLayer = root.querySelector('.hj-capsule-visual, .hj-progress-visual');
3004
+ var move = function move(wrapper, layer) {
3005
+ if (!wrapper || !layer) return;
3006
+ for (var _i = 0, _Array$from = Array.from(wrapper.childNodes); _i < _Array$from.length; _i++) {
3007
+ var node = _Array$from[_i];
3008
+ layer.appendChild(node);
3009
+ }
3010
+ };
3011
+ var refs = this.$refs || {};
3012
+ move(refs.slotText, textLayer);
3013
+ move(refs.slotColor, visualLayer);
3014
+ },
3015
+ applyAttrs: function applyAttrs() {
3016
+ if (!this.controller || !this.controller.element || !this.$attrs) return;
3017
+ var root = this.controller.element;
3018
+ for (var _i2 = 0, _Object$keys = Object.keys(this.$attrs); _i2 < _Object$keys.length; _i2++) {
3019
+ var key = _Object$keys[_i2];
3020
+ if (key === 'class' || key === 'style') continue;
3021
+ var value = this.$attrs[key];
3022
+ if (value == null || value === false) root.removeAttribute(key);else root.setAttribute(key, String(value));
3023
+ }
3024
+ },
3025
+ runtimeState: function runtimeState() {
3026
+ var controller = this.controller;
3027
+ if (!controller || !controller.dirty) return {};
3028
+ var dirty = controller.dirty;
3029
+ var state = {};
3030
+ if (dirty.preset && controller.preset) state.preset = controller.preset.name;
3031
+ if (dirty.seed && controller.preset && controller.preset.seed !== undefined) state.seed = controller.preset.seed;
3032
+ if (dirty.speed && controller.preset && controller.preset.speed !== undefined) state.speed = controller.preset.speed;
3033
+ if (dirty.colors && controller.preset && Array.isArray(controller.preset.colors)) {
3034
+ state.colors = _toConsumableArray(controller.preset.colors);
3035
+ }
3036
+ if (dirty.textRatio && controller.textRatio !== undefined) state.textRatio = controller.textRatio;
3037
+ if (dirty.cssVars && controller.cssVars) state.cssVars = _objectSpread2({}, controller.cssVars);
3038
+ if (dirty.value && typeof controller.getValue === 'function') state.value = controller.getValue();
3039
+ if (dirty.edgeStyle && controller.preset) state.edgeStyle = controller.preset.edgeStyle;
3040
+ if (dirty.opacity) state.opacity = controller.opacity;
3041
+ if (dirty.fallbackColor) state.fallbackColor = controller.fallbackColor;
3042
+ if (dirty.mouseColor) state.mouseColor = controller.mouseColor;
3043
+ return state;
2305
3044
  }
2306
3045
  };
2307
3046
  return {
@@ -2309,6 +3048,7 @@ function makeWrapper(_ref) {
2309
3048
  props: props,
2310
3049
  emits: events,
2311
3050
  render: render,
3051
+ inheritAttrs: false,
2312
3052
  mounted: function mounted() {
2313
3053
  this.mountController();
2314
3054
  },
@@ -2318,6 +3058,10 @@ function makeWrapper(_ref) {
2318
3058
  beforeDestroy: function beforeDestroy() {
2319
3059
  if (this.controller) this.controller.dispose();
2320
3060
  },
3061
+ updated: function updated() {
3062
+ this.moveSlots();
3063
+ this.applyAttrs();
3064
+ },
2321
3065
  watch: _objectSpread2({
2322
3066
  preset: function preset(value) {
2323
3067
  if (value && this.controller) this.controller.setPreset(value);
@@ -2341,7 +3085,7 @@ function makeWrapper(_ref) {
2341
3085
  function makeCapsuleWrapper(createCapsule, render) {
2342
3086
  return makeWrapper({
2343
3087
  name: 'CosmicCapsule',
2344
- props: ['preset', 'width', 'height', 'colors', 'seed', 'speed', 'interactive', 'mouseColor', 'renderer', 'quality', 'respectReducedMotion', 'copy', 'cssVars'],
3088
+ props: ['preset', 'width', 'height', 'colors', 'seed', 'speed', 'textRatio', 'label', 'mouseColor', 'renderer', 'quality', 'respectReducedMotion', 'cssVars'],
2345
3089
  events: CAPSULE_EVENTS,
2346
3090
  create: createCapsule,
2347
3091
  render: render,
@@ -2349,21 +3093,23 @@ function makeCapsuleWrapper(createCapsule, render) {
2349
3093
  seed: function seed(value) {
2350
3094
  var seed = Number(value);
2351
3095
  if (this.controller && Number.isFinite(seed)) {
2352
- this.controller.setPreset(_objectSpread2(_objectSpread2({}, this.controller.preset), {}, {
2353
- seed: seed
2354
- }));
3096
+ this.controller.setSeed(seed);
2355
3097
  }
2356
3098
  },
2357
3099
  speed: function speed(value) {
2358
3100
  var speed = Number(value);
2359
3101
  if (this.controller && Number.isFinite(speed)) {
2360
- this.controller.setPreset(_objectSpread2(_objectSpread2({}, this.controller.preset), {}, {
2361
- speed: speed
2362
- }));
3102
+ this.controller.setSpeed(speed);
2363
3103
  }
2364
3104
  },
2365
- interactive: function interactive() {
2366
- this.scheduleRecreate();
3105
+ textRatio: function textRatio(value) {
3106
+ if (value !== undefined && this.controller) this.controller.setTextRatio(Number(value));
3107
+ },
3108
+ cssVars: function cssVars(value) {
3109
+ if (value && this.controller) this.controller.setCssVars(value);
3110
+ },
3111
+ label: function label(value) {
3112
+ if (this.controller) this.controller.setLabel(value);
2367
3113
  },
2368
3114
  mouseColor: function mouseColor() {
2369
3115
  this.scheduleRecreate();
@@ -2391,6 +3137,21 @@ function makeCapsuleWrapper(createCapsule, render) {
2391
3137
  setColors: function setColors(colors) {
2392
3138
  return this.controller && this.controller.setColors(colors);
2393
3139
  },
3140
+ setText: function setText(content) {
3141
+ return this.controller && this.controller.setText(content);
3142
+ },
3143
+ setColorContent: function setColorContent(content) {
3144
+ return this.controller && this.controller.setColorContent(content);
3145
+ },
3146
+ setTextRatio: function setTextRatio(ratio) {
3147
+ return this.controller && this.controller.setTextRatio(ratio);
3148
+ },
3149
+ setCssVars: function setCssVars(vars) {
3150
+ return this.controller && this.controller.setCssVars(vars);
3151
+ },
3152
+ setLabel: function setLabel(label) {
3153
+ return this.controller && this.controller.setLabel(label);
3154
+ },
2394
3155
  setQuality: function setQuality(quality) {
2395
3156
  return this.controller && this.controller.setQuality(quality);
2396
3157
  },
@@ -2403,7 +3164,7 @@ function makeCapsuleWrapper(createCapsule, render) {
2403
3164
  function makeProgressWrapper(createProgressCapsule, render) {
2404
3165
  return makeWrapper({
2405
3166
  name: 'ProgressCapsule',
2406
- props: ['preset', 'width', 'height', 'value', 'min', 'max', 'draggable', 'keyboard', 'edgeStyle', 'colors', 'quality', 'renderer', 'respectReducedMotion', 'copy', 'cssVars'],
3167
+ props: ['preset', 'width', 'height', 'value', 'min', 'max', 'draggable', 'keyboard', 'disabled', 'edgeStyle', 'colors', 'textRatio', 'label', 'showValue', 'valueSuffix', 'quality', 'renderer', 'respectReducedMotion', 'cssVars'],
2407
3168
  events: PROGRESS_EVENTS,
2408
3169
  create: createProgressCapsule,
2409
3170
  render: render,
@@ -2418,9 +3179,25 @@ function makeProgressWrapper(createProgressCapsule, render) {
2418
3179
  if (value !== undefined && this.controller) this.controller.setRange(this.controller.min, value);
2419
3180
  },
2420
3181
  edgeStyle: function edgeStyle(value) {
2421
- if (value && this.controller) this.controller.setPreset(_objectSpread2(_objectSpread2({}, this.controller.preset), {}, {
2422
- edgeStyle: value
2423
- }));
3182
+ if (value && this.controller) this.controller.setEdgeStyle(value);
3183
+ },
3184
+ textRatio: function textRatio(value) {
3185
+ if (value !== undefined && this.controller) this.controller.setTextRatio(Number(value));
3186
+ },
3187
+ cssVars: function cssVars(value) {
3188
+ if (value && this.controller) this.controller.setCssVars(value);
3189
+ },
3190
+ label: function label(value) {
3191
+ if (this.controller) this.controller.setLabel(value);
3192
+ },
3193
+ valueSuffix: function valueSuffix(value) {
3194
+ if (value !== undefined && this.controller) this.controller.setValueSuffix(value);
3195
+ },
3196
+ showValue: function showValue() {
3197
+ this.scheduleRecreate();
3198
+ },
3199
+ disabled: function disabled() {
3200
+ this.scheduleRecreate();
2424
3201
  },
2425
3202
  draggable: function draggable() {
2426
3203
  this.scheduleRecreate();
@@ -2460,6 +3237,24 @@ function makeProgressWrapper(createProgressCapsule, render) {
2460
3237
  setColors: function setColors(colors) {
2461
3238
  return this.controller && this.controller.setColors(colors);
2462
3239
  },
3240
+ setText: function setText(content) {
3241
+ return this.controller && this.controller.setText(content);
3242
+ },
3243
+ setColorContent: function setColorContent(content) {
3244
+ return this.controller && this.controller.setColorContent(content);
3245
+ },
3246
+ setTextRatio: function setTextRatio(ratio) {
3247
+ return this.controller && this.controller.setTextRatio(ratio);
3248
+ },
3249
+ setCssVars: function setCssVars(vars) {
3250
+ return this.controller && this.controller.setCssVars(vars);
3251
+ },
3252
+ setLabel: function setLabel(label) {
3253
+ return this.controller && this.controller.setLabel(label);
3254
+ },
3255
+ setValueSuffix: function setValueSuffix(suffix) {
3256
+ return this.controller && this.controller.setValueSuffix(suffix);
3257
+ },
2463
3258
  setQuality: function setQuality(quality) {
2464
3259
  return this.controller && this.controller.setQuality(quality);
2465
3260
  },
@@ -2469,15 +3264,104 @@ function makeProgressWrapper(createProgressCapsule, render) {
2469
3264
  }
2470
3265
  });
2471
3266
  }
3267
+ function makeColorWrapper(createColorBackground, render) {
3268
+ return makeWrapper({
3269
+ name: 'ColorBackground',
3270
+ props: ['preset', 'colors', 'seed', 'speed', 'quality', 'renderer', 'mouseColor', 'respectReducedMotion', 'opacity', 'fallbackColor'],
3271
+ events: COLOR_EVENTS,
3272
+ create: createColorBackground,
3273
+ render: render,
3274
+ watch: {
3275
+ seed: function seed(value) {
3276
+ var seed = Number(value);
3277
+ if (this.controller && Number.isFinite(seed)) this.controller.setSeed(seed);
3278
+ },
3279
+ speed: function speed(value) {
3280
+ var speed = Number(value);
3281
+ if (this.controller && Number.isFinite(speed)) this.controller.setSpeed(speed);
3282
+ },
3283
+ opacity: function opacity(value) {
3284
+ if (value !== undefined && this.controller) this.controller.setOpacity(Number(value));
3285
+ },
3286
+ fallbackColor: function fallbackColor(value) {
3287
+ if (this.controller) this.controller.setFallbackColor(value);
3288
+ },
3289
+ mouseColor: function mouseColor(value) {
3290
+ if (this.controller) this.controller.setMouseColor(value);
3291
+ },
3292
+ renderer: function renderer() {
3293
+ this.scheduleRecreate();
3294
+ },
3295
+ respectReducedMotion: function respectReducedMotion() {
3296
+ this.scheduleRecreate();
3297
+ }
3298
+ },
3299
+ methods: {
3300
+ setPreset: function setPreset(preset) {
3301
+ return this.controller && this.controller.setPreset(preset);
3302
+ },
3303
+ setColors: function setColors(colors) {
3304
+ return this.controller && this.controller.setColors(colors);
3305
+ },
3306
+ setSeed: function setSeed(seed) {
3307
+ return this.controller && this.controller.setSeed(seed);
3308
+ },
3309
+ setSpeed: function setSpeed(speed) {
3310
+ return this.controller && this.controller.setSpeed(speed);
3311
+ },
3312
+ setQuality: function setQuality(quality) {
3313
+ return this.controller && this.controller.setQuality(quality);
3314
+ },
3315
+ setOpacity: function setOpacity(value) {
3316
+ return this.controller && this.controller.setOpacity(value);
3317
+ },
3318
+ setFallbackColor: function setFallbackColor(value) {
3319
+ return this.controller && this.controller.setFallbackColor(value);
3320
+ },
3321
+ setMouseColor: function setMouseColor(value) {
3322
+ return this.controller && this.controller.setMouseColor(value);
3323
+ },
3324
+ randomize: function randomize() {
3325
+ return this.controller && this.controller.randomize();
3326
+ },
3327
+ pause: function pause() {
3328
+ return this.controller && this.controller.pause();
3329
+ },
3330
+ resume: function resume() {
3331
+ return this.controller && this.controller.resume();
3332
+ },
3333
+ getController: function getController() {
3334
+ return this.controller;
3335
+ }
3336
+ }
3337
+ });
3338
+ }
2472
3339
 
2473
- // Vue2 passes `h` (createElement) as the first argument to render.
3340
+ // Vue2 passes `h` (createElement) as the first argument to render. Slot
3341
+ // content is rendered into two marker wrappers, then moved into the
3342
+ // component's slot containers by the wrapper (moveSlots).
2474
3343
  var render = function render(h) {
2475
3344
  return h('div', {
2476
3345
  class: 'hj-vue-host'
2477
- });
3346
+ }, [h('div', {
3347
+ class: 'hj-vue-slot-text',
3348
+ ref: 'slotText'
3349
+ }, this.$slots.default), h('div', {
3350
+ class: 'hj-vue-slot-color',
3351
+ ref: 'slotColor'
3352
+ }, this.$slots.color)]);
3353
+ };
3354
+
3355
+ // Color 的宿主内容就是组件内容:直接放在 host 里,浮在背景层上方。
3356
+ var renderColor = function renderColor(h) {
3357
+ return h('div', {
3358
+ class: 'hj-vue-host'
3359
+ }, this.$slots.default);
2478
3360
  };
2479
3361
  var CosmicCapsule = makeCapsuleWrapper(createCapsule, render);
2480
3362
  var ProgressCapsule = makeProgressWrapper(createProgressCapsule, render);
3363
+ var ColorBackground = makeColorWrapper(createColorBackground, renderColor);
2481
3364
 
3365
+ exports.ColorBackground = ColorBackground;
2482
3366
  exports.CosmicCapsule = CosmicCapsule;
2483
3367
  exports.ProgressCapsule = ProgressCapsule;