@5even7/dlc-ui 0.2.3 → 0.2.5

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.mjs CHANGED
@@ -177,9 +177,13 @@ function getPreset(kind, ref) {
177
177
  const list = kind === 'capsule' ? CAPSULE_PRESETS : kind === 'progress' ? PROGRESS_PRESETS : null;
178
178
  if (!list) throw new Error(`Unknown preset kind: ${kind} (use "capsule" or "progress")`);
179
179
  const key = String(ref).trim().toLowerCase();
180
- const found = list.find(
181
- (preset) => preset.name.toLowerCase() === key
182
- );
180
+ let found = null;
181
+ for (let index = 0; index < list.length; index += 1) {
182
+ if (list[index].name.toLowerCase() === key) {
183
+ found = list[index];
184
+ break;
185
+ }
186
+ }
183
187
  if (!found) throw new Error(`Unknown ${kind} preset: ${ref}`);
184
188
  return found;
185
189
  }
@@ -198,9 +202,8 @@ const DEFAULTS = {
198
202
  width: 454,
199
203
  height: 104,
200
204
  min: 0,
201
- max: 100,
205
+ max: 100,
202
206
  draggable: true,
203
- keyboard: true,
204
207
  disabled: false,
205
208
  readonly: false,
206
209
  valueSuffix: '%',
@@ -393,7 +396,7 @@ function normalizeRgbArgs(args) {
393
396
  if (parts.length < 3) return null;
394
397
  const to255 = (value) => {
395
398
  if (typeof value !== 'string' || !value) return null;
396
- if (value.endsWith('%')) return clampChannel((parseFloat(value) / 100) * 255);
399
+ if (value.charAt(value.length - 1) === '%') return clampChannel((parseFloat(value) / 100) * 255);
397
400
  const number = Number(value);
398
401
  return Number.isFinite(number) ? clampChannel(number) : null;
399
402
  };
@@ -401,7 +404,11 @@ function normalizeRgbArgs(args) {
401
404
  const green = to255(parts[1]);
402
405
  const blue = to255(parts[2]);
403
406
  if (red === null || green === null || blue === null) return null;
404
- return `#${[red, green, blue].map((n) => n.toString(16).padStart(2, '0')).join('')}`;
407
+ const hex = (n) => {
408
+ const text = n.toString(16);
409
+ return text.length === 1 ? `0${text}` : text;
410
+ };
411
+ return `#${hex(red)}${hex(green)}${hex(blue)}`;
405
412
  }
406
413
 
407
414
  /**
@@ -758,12 +765,13 @@ function rgb(color, alpha = 1) {
758
765
  }
759
766
 
760
767
  class FallbackRenderer {
761
- constructor(canvas, preset) {
762
- this.canvas = canvas;
763
- this.preset = preset;
764
- this.context = canvas.getContext('2d');
765
- this.visible = true;
766
- }
768
+ constructor(canvas, preset) {
769
+ this.canvas = canvas;
770
+ this.preset = preset;
771
+ this.context = canvas.getContext('2d');
772
+ this.visible = true;
773
+ this.timePhase = 0;
774
+ }
767
775
 
768
776
  resize() {
769
777
  const rect = this.canvas.getBoundingClientRect();
@@ -779,7 +787,7 @@ class FallbackRenderer {
779
787
  drawNebula(time) {
780
788
  const ctx = this.context;
781
789
  const { width, height } = this.canvas;
782
- const t = time * (this.preset.speed || 1);
790
+ const t = (time + this.timePhase) * (this.preset.speed || 1);
783
791
  const phase = (this.preset.seed || 0) * 0.7;
784
792
  const gradient = ctx.createLinearGradient(0, 0, width, height);
785
793
  gradient.addColorStop(0, this.preset.colors[0]);
@@ -814,7 +822,10 @@ class FallbackRenderer {
814
822
  }
815
823
 
816
824
  randomize() {
817
- if (this.preset) this.preset.seed = Math.random() * 100;
825
+ if (this.preset) {
826
+ this.preset.seed = Math.random() * 100;
827
+ this.timePhase = Math.random() * Math.PI * 2;
828
+ }
818
829
  }
819
830
  setMouseColor() {}
820
831
  dispose() {}
@@ -1040,10 +1051,9 @@ function createCapsule(container, options = {}) {
1040
1051
  for (const name of Object.keys(vars)) root.style.setProperty(name, vars[name]);
1041
1052
  if (merged.textRatio !== undefined) {
1042
1053
  root.style.setProperty('--hj-text-width', `${merged.textRatio}%`);
1043
- const userMinWidth = merged.cssVars && merged.cssVars['--hj-text-min-width'];
1044
- if (merged.textRatio === 0) root.style.setProperty('--hj-text-min-width', '0');
1045
- else if (userMinWidth) root.style.setProperty('--hj-text-min-width', userMinWidth);
1046
- else root.style.removeProperty('--hj-text-min-width');
1054
+ // textRatio 是文字区宽度的唯一权威值:min-width 会阻止其缩小到
1055
+ // 164px 以下(--hj-copy-min-width 的历史默认),这里强制归零。
1056
+ root.style.setProperty('--hj-text-min-width', '0');
1047
1057
  }
1048
1058
  renderer.resize();
1049
1059
  };
@@ -1142,10 +1152,7 @@ function createCapsule(container, options = {}) {
1142
1152
  dirty.textRatio = true;
1143
1153
  merged.textRatio = value;
1144
1154
  root.style.setProperty('--hj-text-width', `${value}%`);
1145
- const userMinWidth = merged.cssVars && merged.cssVars['--hj-text-min-width'];
1146
- if (value === 0) root.style.setProperty('--hj-text-min-width', '0');
1147
- else if (userMinWidth) root.style.setProperty('--hj-text-min-width', userMinWidth);
1148
- else root.style.removeProperty('--hj-text-min-width');
1155
+ root.style.setProperty('--hj-text-min-width', '0');
1149
1156
  return this;
1150
1157
  },
1151
1158
  setCssVars(vars) {
@@ -1161,11 +1168,17 @@ function createCapsule(container, options = {}) {
1161
1168
  return this;
1162
1169
  },
1163
1170
  setSize(width, height) {
1164
- if (width !== undefined) merged.width = width;
1165
- if (height !== undefined) merged.height = height;
1166
- applySize();
1167
- return this;
1168
- },
1171
+ if (width !== undefined) {
1172
+ parseSize(width); // 非法尺寸直接抛错前先校验,避免污染内部状态
1173
+ merged.width = width;
1174
+ }
1175
+ if (height !== undefined) {
1176
+ parseSize(height);
1177
+ merged.height = height;
1178
+ }
1179
+ applySize();
1180
+ return this;
1181
+ },
1169
1182
  randomize() {
1170
1183
  this.setSeed(Math.random() * 100);
1171
1184
  return this;
@@ -1192,8 +1205,8 @@ function createCapsule(container, options = {}) {
1192
1205
  renderer.dispose();
1193
1206
  root.remove();
1194
1207
  },
1195
- textRatio: merged.textRatio,
1196
- cssVars: merged.cssVars,
1208
+ get textRatio() { return merged.textRatio; },
1209
+ get cssVars() { return merged.cssVars; },
1197
1210
  dirty
1198
1211
  };
1199
1212
  }
@@ -1678,13 +1691,17 @@ const PALETTES = {
1678
1691
  'tide': ['#0a2239', '#2e9bff', '#7fe3ff', '#eaf9ff']
1679
1692
  };
1680
1693
 
1681
- function drawCloud(context, x, y, radiusX, radiusY, color, alpha) {
1682
- context.save();
1683
- context.translate(x, y);
1684
- context.scale(1, radiusY / radiusX);
1685
- const gradient = context.createRadialGradient(0, 0, 0, 0, 0, radiusX);
1686
- gradient.addColorStop(0, `${color}${Math.round(alpha * 255).toString(16).padStart(2, '0')}`);
1687
- gradient.addColorStop(0.46, `${color}${Math.round(alpha * 0.42 * 255).toString(16).padStart(2, '0')}`);
1694
+ function drawCloud(context, x, y, radiusX, radiusY, color, alpha) {
1695
+ context.save();
1696
+ context.translate(x, y);
1697
+ context.scale(1, radiusY / radiusX);
1698
+ const gradient = context.createRadialGradient(0, 0, 0, 0, 0, radiusX);
1699
+ const alphaHex = (value) => {
1700
+ const text = Math.round(value).toString(16);
1701
+ return text.length === 1 ? `0${text}` : text;
1702
+ };
1703
+ gradient.addColorStop(0, `${color}${alphaHex(alpha * 255)}`);
1704
+ gradient.addColorStop(0.46, `${color}${alphaHex(alpha * 0.42 * 255)}`);
1688
1705
  gradient.addColorStop(1, `${color}00`);
1689
1706
  context.fillStyle = gradient;
1690
1707
  context.fillRect(-radiusX, -radiusX, radiusX * 2, radiusX * 2);
@@ -2114,9 +2131,14 @@ class ProgressCapsuleController {
2114
2131
  ctx.restore();
2115
2132
  }
2116
2133
 
2117
- setRange(min, max) {
2118
- this.min = min;
2119
- this.max = max;
2134
+ setRange(min, max) {
2135
+ if (min > max) {
2136
+ const swap = min;
2137
+ min = max;
2138
+ max = swap;
2139
+ }
2140
+ this.min = min;
2141
+ this.max = max;
2120
2142
  const clamped = clamp(this.value, this.min, this.max);
2121
2143
  if (clamped !== this.value) this.setProgress(clamped, 'prop');
2122
2144
  }
@@ -2311,33 +2333,7 @@ class ProgressCapsuleController {
2311
2333
  this.root.addEventListener('pointercancel', this.handlers.pointercancel);
2312
2334
  }
2313
2335
 
2314
- if (this.options.keyboard !== false) {
2315
- this.handlers.keydown = (event) => {
2316
- const step = (this.max - this.min) * 0.02;
2317
- const actions = {
2318
- ArrowLeft: -step,
2319
- ArrowDown: -step,
2320
- ArrowRight: step,
2321
- ArrowUp: step,
2322
- PageDown: -step * 5,
2323
- PageUp: step * 5
2324
- };
2325
- if (event.key === 'Home') {
2326
- event.preventDefault();
2327
- this.setProgress(this.min, 'keyboard');
2328
- } else if (event.key === 'End') {
2329
- event.preventDefault();
2330
- this.setProgress(this.max, 'keyboard');
2331
- } else if (actions[event.key]) {
2332
- event.preventDefault();
2333
- this.setProgress(this.value + actions[event.key], 'keyboard');
2334
- } else {
2335
- return;
2336
- }
2337
- };
2338
- this.root.addEventListener('keydown', this.handlers.keydown);
2339
- }
2340
- }
2336
+ }
2341
2337
 
2342
2338
  update(delta, paused) {
2343
2339
  if (!paused) this.flowTime += delta;
@@ -2375,7 +2371,7 @@ class ProgressCapsuleController {
2375
2371
  * Mount a fluid progress capsule into `container`.
2376
2372
  *
2377
2373
  * Options: preset (id/code/name or object), width, height, value, min, max,
2378
- * draggable, keyboard, colors, edgeStyle, textRatio (0-100, text region
2374
+ * draggable, colors, edgeStyle, textRatio (0-100, text region
2379
2375
  * width in percent), text (HTML string or DOM nodes for the text slot),
2380
2376
  * colorContent (HTML string or DOM nodes for the color slot),
2381
2377
  * showValue (show/hide the right-side percentage), quality,
@@ -2388,6 +2384,11 @@ function createProgressCapsule(container, options = {}) {
2388
2384
 
2389
2385
  const preset = { ...getPreset('progress', options.preset ?? '星火') };
2390
2386
  const merged = normalizeOptions(DEFAULTS.progress, preset, options);
2387
+ if (merged.min > merged.max) {
2388
+ const swap = merged.min;
2389
+ merged.min = merged.max;
2390
+ merged.max = swap;
2391
+ }
2391
2392
  const normalizedColors = merged.colors.map(normalizeColor);
2392
2393
  if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
2393
2394
  preset.edgeStyle = merged.edgeStyle;
@@ -2399,7 +2400,6 @@ function createProgressCapsule(container, options = {}) {
2399
2400
  const readonly = merged.readonly === true || merged.readonly === '' || merged.readonly === 'true';
2400
2401
  const locked = disabled || readonly;
2401
2402
  const effectiveDraggable = locked ? false : merged.draggable !== false;
2402
- const effectiveKeyboard = locked ? false : merged.keyboard !== false;
2403
2403
  const dirty = {
2404
2404
  preset: false,
2405
2405
  colors: false,
@@ -2412,7 +2412,6 @@ function createProgressCapsule(container, options = {}) {
2412
2412
  const root = document.createElement('div');
2413
2413
  root.className = 'hj-capsule-root hj-progress-root';
2414
2414
  root.setAttribute('role', 'slider');
2415
- root.setAttribute('tabindex', '0');
2416
2415
  root.setAttribute('data-draggable', String(effectiveDraggable));
2417
2416
  if (disabled) {
2418
2417
  root.setAttribute('aria-disabled', 'true');
@@ -2422,6 +2421,7 @@ function createProgressCapsule(container, options = {}) {
2422
2421
  root.setAttribute('aria-readonly', 'true');
2423
2422
  root.classList.add('is-readonly');
2424
2423
  }
2424
+ if (locked) root.setAttribute('tabindex', '-1');
2425
2425
  root.setAttribute('aria-valuemin', String(merged.min ?? 0));
2426
2426
  root.setAttribute('aria-valuemax', String(merged.max ?? 100));
2427
2427
  root.setAttribute('aria-valuenow', String(preset.initialProgress));
@@ -2432,8 +2432,6 @@ function createProgressCapsule(container, options = {}) {
2432
2432
  );
2433
2433
  };
2434
2434
  updateAria();
2435
- if (!effectiveKeyboard) root.setAttribute('tabindex', '-1');
2436
-
2437
2435
  const canvas = document.createElement('canvas');
2438
2436
  canvas.className = 'hj-progress-canvas';
2439
2437
  canvas.setAttribute('aria-hidden', 'true');
@@ -2495,7 +2493,7 @@ function createProgressCapsule(container, options = {}) {
2495
2493
  valueElement,
2496
2494
  preset,
2497
2495
  emitter,
2498
- options: { ...merged, draggable: effectiveDraggable, keyboard: effectiveKeyboard },
2496
+ options: { ...merged, draggable: effectiveDraggable },
2499
2497
  copy,
2500
2498
  dirty
2501
2499
  });
@@ -2636,10 +2634,16 @@ function createProgressCapsule(container, options = {}) {
2636
2634
  controller.resizeCanvas();
2637
2635
  return this;
2638
2636
  },
2639
- setSize(width, height) {
2640
- if (width !== undefined) merged.width = width;
2641
- if (height !== undefined) merged.height = height;
2642
- applySize();
2637
+ setSize(width, height) {
2638
+ if (width !== undefined) {
2639
+ parseSize(width);
2640
+ merged.width = width;
2641
+ }
2642
+ if (height !== undefined) {
2643
+ parseSize(height);
2644
+ merged.height = height;
2645
+ }
2646
+ applySize();
2643
2647
  controller.resizeCanvas();
2644
2648
  return this;
2645
2649
  },
@@ -2669,8 +2673,8 @@ function createProgressCapsule(container, options = {}) {
2669
2673
  controller.dispose();
2670
2674
  root.remove();
2671
2675
  },
2672
- textRatio: merged.textRatio,
2673
- cssVars: merged.cssVars,
2676
+ get textRatio() { return merged.textRatio; },
2677
+ get cssVars() { return merged.cssVars; },
2674
2678
  dirty
2675
2679
  };
2676
2680
  }
@@ -2890,9 +2894,9 @@ function createColorBackground(host, options = {}) {
2890
2894
  renderer.dispose();
2891
2895
  layer.remove();
2892
2896
  },
2893
- opacity: merged.opacity,
2894
- fallbackColor: merged.fallbackColor,
2895
- mouseColor: merged.mouseColor,
2897
+ get opacity() { return merged.opacity; },
2898
+ get fallbackColor() { return merged.fallbackColor; },
2899
+ get mouseColor() { return merged.mouseColor; },
2896
2900
  dirty
2897
2901
  };
2898
2902
  }
@@ -2928,6 +2932,9 @@ function makeWrapper({ name, props, events, create, render, methods, watch }) {
2928
2932
  const extraState = this.runtimeState();
2929
2933
  if (this.controller) this.controller.dispose();
2930
2934
  this.mountController(extraState);
2935
+ // 结构属性连续变化时,插槽内容可能在重建后才被 Vue 写入容器,
2936
+ // 补一次搬运确保不丢。
2937
+ this.$nextTick(() => this.moveSlots());
2931
2938
  },
2932
2939
  scheduleRecreate() {
2933
2940
  if (this._recreateQueued) return;
@@ -3077,7 +3084,7 @@ function makeProgressWrapper(createProgressCapsule, render) {
3077
3084
  name: 'ProgressCapsule',
3078
3085
  props: [
3079
3086
  'preset', 'width', 'height', 'value', 'min', 'max',
3080
- 'draggable', 'keyboard', 'disabled', 'readonly', 'edgeStyle', 'colors', 'textRatio', 'label', 'showValue', 'valueSuffix',
3087
+ 'draggable', 'disabled', 'readonly', 'edgeStyle', 'colors', 'textRatio', 'label', 'showValue', 'valueSuffix',
3081
3088
  'quality', 'renderer', 'respectReducedMotion', 'cssVars'
3082
3089
  ],
3083
3090
  events: PROGRESS_EVENTS,
@@ -3120,9 +3127,6 @@ function makeProgressWrapper(createProgressCapsule, render) {
3120
3127
  draggable() {
3121
3128
  this.scheduleRecreate();
3122
3129
  },
3123
- keyboard() {
3124
- this.scheduleRecreate();
3125
- },
3126
3130
  renderer() {
3127
3131
  this.scheduleRecreate();
3128
3132
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5even7/dlc-ui",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/types/index.d.ts CHANGED
@@ -59,7 +59,6 @@ export interface ProgressOptions {
59
59
  min?: number;
60
60
  max?: number;
61
61
  draggable?: boolean;
62
- keyboard?: boolean;
63
62
  disabled?: boolean;
64
63
  readonly?: boolean;
65
64
  valueSuffix?: string;
@@ -181,7 +180,7 @@ export declare function getPreset(kind: 'capsule' | 'progress', ref: string): Ca
181
180
 
182
181
  export declare const DEFAULTS: {
183
182
  capsule: Required<Pick<CapsuleOptions, 'width' | 'height' | 'quality' | 'respectReducedMotion' | 'mouseColor' | 'renderer' | 'textRatio'>>;
184
- progress: Required<Pick<ProgressOptions, 'width' | 'height' | 'min' | 'max' | 'draggable' | 'keyboard' | 'disabled' | 'readonly' | 'valueSuffix' | 'edgeStyle' | 'quality' | 'respectReducedMotion' | 'renderer' | 'textRatio' | 'showValue'>>;
183
+ progress: Required<Pick<ProgressOptions, 'width' | 'height' | 'min' | 'max' | 'draggable' | 'disabled' | 'readonly' | 'valueSuffix' | 'edgeStyle' | 'quality' | 'respectReducedMotion' | 'renderer' | 'textRatio' | 'showValue'>>;
185
184
  };
186
185
 
187
186
  export declare const COPY: Copy;