gaugeit.js 0.1.0 → 0.1.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/gaugeit.css CHANGED
@@ -115,7 +115,6 @@ gauge-it {
115
115
  --gaugeit-light-off: #3f2d12;
116
116
  --gaugeit-light-opacity: 1;
117
117
  pointer-events: none;
118
- opacity: var(--gaugeit-light-opacity);
119
118
  }
120
119
 
121
120
  .gaugeit__light--red {
@@ -198,26 +197,31 @@ gauge-it {
198
197
  --gaugeit-light-off: #332617;
199
198
  }
200
199
 
201
- .gaugeit__light-emission {
200
+ .gaugeit__light-emission,
201
+ .gaugeit__light-glow-emission {
202
202
  pointer-events: none;
203
203
  transition: opacity 150ms ease;
204
204
  }
205
205
 
206
206
  .gaugeit__light-emission--off {
207
- opacity: var(--gaugeit-light-opacity, 1);
207
+ opacity: 1;
208
208
  }
209
209
 
210
210
  .gaugeit__light-emission--on {
211
211
  opacity: 0;
212
212
  }
213
213
 
214
+ .gaugeit__light-glow-emission {
215
+ opacity: 0;
216
+ }
217
+
214
218
  .gaugeit__light-glow {
215
- opacity: 0.76;
219
+ opacity: 1;
216
220
  transform-box: fill-box;
217
221
  transform-origin: center;
218
222
  }
219
223
 
220
- .gaugeit__light:not(.has-glow) .gaugeit__light-glow {
224
+ .gaugeit__light:not(.has-glow) .gaugeit__light-glow-emission {
221
225
  display: none;
222
226
  }
223
227
 
@@ -235,18 +239,23 @@ gauge-it {
235
239
  transition: filter 150ms ease;
236
240
  }
237
241
 
238
- .gaugeit__light.is-on:not(.is-blinking) .gaugeit__light-emission--off {
239
- opacity: 0;
242
+ .gaugeit__light.is-on:not(.is-blinking) .gaugeit__light-emission--on {
243
+ opacity: var(--gaugeit-light-on-opacity, var(--gaugeit-light-opacity, 1));
240
244
  }
241
245
 
242
- .gaugeit__light.is-on:not(.is-blinking) .gaugeit__light-emission--on {
243
- opacity: var(--gaugeit-light-opacity, 1);
246
+ .gaugeit__light.is-on:not(.is-blinking) .gaugeit__light-glow-emission {
247
+ opacity: var(--gaugeit-light-glow-opacity, 0.15);
244
248
  }
245
249
 
246
250
  .gaugeit__light.is-on .gaugeit__light-bulb--on {
247
251
  filter: saturate(1.08) brightness(1.05);
248
252
  }
249
253
 
254
+ .gaugeit__light.is-flickering .gaugeit__light-emission--on,
255
+ .gaugeit__light.is-flickering .gaugeit__light-glow-emission {
256
+ transition: opacity 24ms linear;
257
+ }
258
+
250
259
  .gaugeit__light.is-pulsing .gaugeit__light-glow {
251
260
  animation: gaugeit-light-pulse-glow var(--gaugeit-light-pulse-duration, 2600ms) ease-in-out infinite;
252
261
  }
@@ -259,8 +268,8 @@ gauge-it {
259
268
  animation: gaugeit-light-blink-on var(--gaugeit-light-blink-duration, 1000ms) step-end infinite;
260
269
  }
261
270
 
262
- .gaugeit__light.is-on.is-blinking .gaugeit__light-emission--off {
263
- animation: gaugeit-light-blink-off var(--gaugeit-light-blink-duration, 1000ms) step-end infinite;
271
+ .gaugeit__light.is-on.is-blinking .gaugeit__light-glow-emission {
272
+ animation: gaugeit-light-blink-glow var(--gaugeit-light-blink-duration, 1000ms) step-end infinite;
264
273
  }
265
274
 
266
275
  @keyframes gaugeit-light-pulse-glow {
@@ -274,27 +283,30 @@ gauge-it {
274
283
  }
275
284
 
276
285
  @keyframes gaugeit-light-blink-on {
277
- 0%, 48% { opacity: var(--gaugeit-light-opacity, 1); }
286
+ 0%, 48% { opacity: var(--gaugeit-light-on-opacity, var(--gaugeit-light-opacity, 1)); }
278
287
  49%, 100% { opacity: 0; }
279
288
  }
280
289
 
281
- @keyframes gaugeit-light-blink-off {
282
- 0%, 48% { opacity: 0; }
283
- 49%, 100% { opacity: var(--gaugeit-light-opacity, 1); }
290
+ @keyframes gaugeit-light-blink-glow {
291
+ 0%, 48% { opacity: var(--gaugeit-light-glow-opacity, 0.15); }
292
+ 49%, 100% { opacity: 0; }
284
293
  }
285
294
 
286
295
  @media (prefers-reduced-motion: reduce) {
287
- .gaugeit__light.is-blinking .gaugeit__light-emission,
296
+ .gaugeit__light.is-blinking .gaugeit__light-emission--on,
297
+ .gaugeit__light.is-blinking .gaugeit__light-glow-emission,
298
+ .gaugeit__light.is-flickering .gaugeit__light-emission--on,
299
+ .gaugeit__light.is-flickering .gaugeit__light-glow-emission,
288
300
  .gaugeit__light.is-pulsing .gaugeit__light-glow,
289
301
  .gaugeit__light.is-pulsing .gaugeit__light-bulb--on {
290
302
  animation: none;
291
303
  }
292
304
 
293
- .gaugeit__light.is-on.is-blinking .gaugeit__light-emission--off {
294
- opacity: 0;
305
+ .gaugeit__light.is-on.is-blinking .gaugeit__light-emission--on {
306
+ opacity: var(--gaugeit-light-on-opacity, var(--gaugeit-light-opacity, 1));
295
307
  }
296
308
 
297
- .gaugeit__light.is-on.is-blinking .gaugeit__light-emission--on {
298
- opacity: var(--gaugeit-light-opacity, 1);
309
+ .gaugeit__light.is-on.is-blinking .gaugeit__light-glow-emission {
310
+ opacity: var(--gaugeit-light-glow-opacity, 0.15);
299
311
  }
300
312
  }
package/dist/gaugeit.d.ts CHANGED
@@ -46,6 +46,10 @@ export interface GaugeLightOptions {
46
46
  x?: number;
47
47
  y?: number;
48
48
  radius?: number;
49
+ /** Glow-circle radius. Defaults to 20; null derives it from radius * 1.82. */
50
+ glowRadius?: number | null;
51
+ /** Glow blur from 0 (soft Gaussian glow) to 1 (completely sharp). */
52
+ glowSharpness?: number;
49
53
  color?: GaugeLightColor;
50
54
  customColor?: string;
51
55
  /** Cream-toned unlit lens color. */
@@ -54,7 +58,10 @@ export interface GaugeLightOptions {
54
58
  offEdgeColor?: string;
55
59
  bezelColor?: string;
56
60
  bezelHighlightColor?: string;
61
+ /** Illuminated-lens opacity; the unlit physical lamp and bezel remain visible. */
57
62
  opacity?: number;
63
+ /** Glow-only opacity; independent from the illuminated lens opacity. Defaults to 0.15. */
64
+ glowOpacity?: number;
58
65
  on?: boolean;
59
66
  glow?: boolean;
60
67
  /** Enables a very subtle steady-light breathing effect. */
@@ -62,6 +69,16 @@ export interface GaugeLightOptions {
62
69
  pulseInterval?: number;
63
70
  blink?: boolean;
64
71
  blinkInterval?: number;
72
+ /** Adds fast randomized brightness variation; compatible with pulse and blink. */
73
+ flicker?: boolean;
74
+ /** Maximum randomized light loss, from 0 (steady) to 1 (may switch fully off). Defaults to 0.1. */
75
+ flickerIntensity?: number;
76
+ /** Maximum relative glow-radius variation, from 0 to 1. Defaults to 0.1. */
77
+ flickerGlowRadius?: number;
78
+ /** Shortest delay between brightness changes in milliseconds. */
79
+ flickerMinInterval?: number;
80
+ /** Longest delay between brightness changes in milliseconds. */
81
+ flickerMaxInterval?: number;
65
82
  trigger?: {
66
83
  mode?: GaugeLightTriggerMode;
67
84
  /** Value stream used by threshold evaluation. Defaults to the requested target value. */
@@ -1,4 +1,4 @@
1
- /*! Gaugeit.js v0.1.0 | MIT License | https://github.com/kasperikoski/gaugeit.js#readme */
1
+ /*! Gaugeit.js v0.1.1 | MIT License | https://github.com/kasperikoski/gaugeit.js#readme */
2
2
 
3
3
  // src/core/utils.js
4
4
  function isPlainObject(value) {
@@ -838,7 +838,13 @@ function includeLight(bounds, options) {
838
838
  if (!(light == null ? void 0 : light.visible)) return;
839
839
  const point = resolveLightPosition(light, options);
840
840
  const radius = Math.max(1, finiteNumber(light.radius, 8));
841
- const halo = light.glow ? radius * 2.96 : radius;
841
+ const glowRadius = Math.max(0, finiteNumber(light.glowRadius, radius * 1.82));
842
+ const flickerGlowRadius = light.flicker ? Math.min(1, Math.max(0, finiteNumber(light.flickerGlowRadius, 0))) : 0;
843
+ const maximumGlowRadius = glowRadius * (1 + flickerGlowRadius);
844
+ const glowSharpness = Math.min(1, Math.max(0, finiteNumber(light.glowSharpness, 0)));
845
+ const maximumBlur = glowRadius > 0 ? Math.max(1.4, glowRadius * 0.38) : 0;
846
+ const glowBlur = maximumBlur * (1 - glowSharpness);
847
+ const halo = light.glow ? maximumGlowRadius + glowBlur * 3 + (maximumGlowRadius > 0 ? 1e-9 : 0) : radius;
842
848
  const bezel = radius + Math.max(1.5, radius * 0.18);
843
849
  const extent = Math.max(halo, bezel);
844
850
  includeRect(bounds, point.x - extent, point.y - extent, extent * 2, extent * 2);
@@ -1284,28 +1290,36 @@ var BASE_DEFAULTS = Object.freeze({
1284
1290
  },
1285
1291
  light: {
1286
1292
  visible: false,
1287
- x: 160,
1293
+ x: 93,
1288
1294
  y: 110,
1289
1295
  radius: 8,
1290
- color: "amber",
1296
+ glowRadius: 20,
1297
+ glowSharpness: 0,
1298
+ color: "red",
1291
1299
  customColor: "",
1292
1300
  offColor: "#f3ead6",
1293
1301
  offEdgeColor: "#817768",
1294
1302
  bezelColor: "#4b5563",
1295
1303
  bezelHighlightColor: "#f8fafc",
1296
1304
  opacity: 1,
1305
+ glowOpacity: 0.15,
1297
1306
  on: false,
1298
1307
  glow: true,
1299
- pulse: true,
1308
+ pulse: false,
1300
1309
  pulseInterval: 2600,
1301
1310
  blink: false,
1302
1311
  blinkInterval: 1e3,
1312
+ flicker: true,
1313
+ flickerIntensity: 0.1,
1314
+ flickerGlowRadius: 0.1,
1315
+ flickerMinInterval: 45,
1316
+ flickerMaxInterval: 140,
1303
1317
  trigger: {
1304
- mode: "manual",
1318
+ mode: "below",
1305
1319
  source: "target",
1306
- value: 0,
1320
+ value: 15,
1307
1321
  min: 0,
1308
- max: 0
1322
+ max: 15
1309
1323
  }
1310
1324
  },
1311
1325
  readout: {
@@ -1608,27 +1622,63 @@ function validateTape(tape) {
1608
1622
  tape.colorByZone = tape.colorByZone === true;
1609
1623
  }
1610
1624
  function validateLight(light) {
1625
+ const defaults2 = BASE_DEFAULTS.light;
1611
1626
  light.visible = light.visible === true;
1612
- light.x = finiteNumber(light.x, 160);
1613
- light.y = finiteNumber(light.y, 110);
1614
- light.radius = Math.max(1, finiteNumber(light.radius, 8));
1615
- light.color = VALID_LIGHT_COLORS.has(light.color) ? light.color : "amber";
1616
- light.customColor = light.customColor === null || light.customColor === void 0 ? "" : String(light.customColor).trim();
1617
- light.offColor = normalizeColor(light.offColor, "#f3ead6");
1618
- light.offEdgeColor = normalizeColor(light.offEdgeColor, "#817768");
1619
- light.bezelColor = normalizeColor(light.bezelColor, "#4b5563");
1620
- light.bezelHighlightColor = normalizeColor(light.bezelHighlightColor, "#f8fafc");
1621
- light.opacity = Math.min(1, Math.max(0, finiteNumber(light.opacity, 1)));
1627
+ light.x = finiteNumber(light.x, defaults2.x);
1628
+ light.y = finiteNumber(light.y, defaults2.y);
1629
+ light.radius = Math.max(1, finiteNumber(light.radius, defaults2.radius));
1630
+ light.glowRadius = light.glowRadius === null || light.glowRadius === void 0 ? light.radius * 1.82 : Math.max(0, finiteNumber(light.glowRadius, defaults2.glowRadius));
1631
+ light.glowSharpness = Math.min(
1632
+ 1,
1633
+ Math.max(0, finiteNumber(light.glowSharpness, defaults2.glowSharpness))
1634
+ );
1635
+ light.color = VALID_LIGHT_COLORS.has(light.color) ? light.color : defaults2.color;
1636
+ light.customColor = light.customColor === null || light.customColor === void 0 ? defaults2.customColor : String(light.customColor).trim();
1637
+ light.offColor = normalizeColor(light.offColor, defaults2.offColor);
1638
+ light.offEdgeColor = normalizeColor(light.offEdgeColor, defaults2.offEdgeColor);
1639
+ light.bezelColor = normalizeColor(light.bezelColor, defaults2.bezelColor);
1640
+ light.bezelHighlightColor = normalizeColor(
1641
+ light.bezelHighlightColor,
1642
+ defaults2.bezelHighlightColor
1643
+ );
1644
+ light.opacity = Math.min(1, Math.max(0, finiteNumber(light.opacity, defaults2.opacity)));
1645
+ light.glowOpacity = Math.min(
1646
+ 1,
1647
+ Math.max(0, finiteNumber(light.glowOpacity, defaults2.glowOpacity))
1648
+ );
1622
1649
  light.on = light.on === true;
1623
1650
  light.glow = light.glow !== false;
1624
- light.pulse = light.pulse !== false;
1625
- light.pulseInterval = Math.max(400, finiteNumber(light.pulseInterval, 2600));
1651
+ light.pulse = light.pulse === true;
1652
+ light.pulseInterval = Math.max(400, finiteNumber(light.pulseInterval, defaults2.pulseInterval));
1626
1653
  light.blink = light.blink === true;
1627
- light.blinkInterval = Math.max(100, finiteNumber(light.blinkInterval, 1e3));
1654
+ light.blinkInterval = Math.max(100, finiteNumber(light.blinkInterval, defaults2.blinkInterval));
1655
+ light.flicker = light.flicker === true;
1656
+ light.flickerIntensity = Math.min(
1657
+ 1,
1658
+ Math.max(0, finiteNumber(light.flickerIntensity, defaults2.flickerIntensity))
1659
+ );
1660
+ light.flickerGlowRadius = Math.min(
1661
+ 1,
1662
+ Math.max(0, finiteNumber(light.flickerGlowRadius, defaults2.flickerGlowRadius))
1663
+ );
1664
+ light.flickerMinInterval = Math.max(
1665
+ 16,
1666
+ finiteNumber(light.flickerMinInterval, defaults2.flickerMinInterval)
1667
+ );
1668
+ light.flickerMaxInterval = Math.max(
1669
+ 16,
1670
+ finiteNumber(light.flickerMaxInterval, defaults2.flickerMaxInterval)
1671
+ );
1672
+ if (light.flickerMaxInterval < light.flickerMinInterval) {
1673
+ [light.flickerMinInterval, light.flickerMaxInterval] = [
1674
+ light.flickerMaxInterval,
1675
+ light.flickerMinInterval
1676
+ ];
1677
+ }
1628
1678
  light.trigger = isPlainObject(light.trigger) ? light.trigger : {};
1629
- light.trigger.mode = VALID_LIGHT_TRIGGER_MODES.has(light.trigger.mode) ? light.trigger.mode : "manual";
1630
- light.trigger.source = VALID_LIGHT_TRIGGER_SOURCES.has(light.trigger.source) ? light.trigger.source : "target";
1631
- light.trigger.value = finiteNumber(light.trigger.value, 0);
1679
+ light.trigger.mode = VALID_LIGHT_TRIGGER_MODES.has(light.trigger.mode) ? light.trigger.mode : defaults2.trigger.mode;
1680
+ light.trigger.source = VALID_LIGHT_TRIGGER_SOURCES.has(light.trigger.source) ? light.trigger.source : defaults2.trigger.source;
1681
+ light.trigger.value = finiteNumber(light.trigger.value, defaults2.trigger.value);
1632
1682
  light.trigger.min = finiteNumber(light.trigger.min, light.trigger.value);
1633
1683
  light.trigger.max = finiteNumber(light.trigger.max, light.trigger.value);
1634
1684
  if (light.trigger.max < light.trigger.min) {
@@ -2749,17 +2799,17 @@ var lightLayer = {
2749
2799
  if (!(light == null ? void 0 : light.visible)) return null;
2750
2800
  const { x, y } = resolveLightPosition(light, options);
2751
2801
  const palette = resolvePalette(light);
2752
- const colorName = Object.prototype.hasOwnProperty.call(LIGHT_PALETTES, light.color) ? light.color : "amber";
2802
+ const colorName = Object.prototype.hasOwnProperty.call(LIGHT_PALETTES, light.color) ? light.color : "red";
2753
2803
  const glowFilterId = `${renderer.id}-light-glow`;
2754
2804
  const onGradientId = `${renderer.id}-light-on`;
2755
2805
  const offGradientId = `${renderer.id}-light-off`;
2756
2806
  const bezelGradientId = `${renderer.id}-light-bezel`;
2757
2807
  const defs = svgElement("defs");
2758
2808
  defs.append(
2759
- createGlowFilter(glowFilterId, light.radius),
2809
+ createGlowFilter(glowFilterId, light.glowRadius, light.glowSharpness),
2760
2810
  createBulbGradient(onGradientId, {
2761
- center: "#ffffff",
2762
- highlight: palette.highlight,
2811
+ center: palette.highlight,
2812
+ highlight: palette.core,
2763
2813
  middle: palette.core,
2764
2814
  edge: palette.rim
2765
2815
  }),
@@ -2782,6 +2832,8 @@ var lightLayer = {
2782
2832
  lamp.style.setProperty("--gaugeit-light-blink-duration", `${light.blinkInterval}ms`);
2783
2833
  lamp.style.setProperty("--gaugeit-light-pulse-duration", `${light.pulseInterval}ms`);
2784
2834
  lamp.style.setProperty("--gaugeit-light-opacity", String(light.opacity));
2835
+ lamp.style.setProperty("--gaugeit-light-on-opacity", String(light.opacity));
2836
+ lamp.style.setProperty("--gaugeit-light-glow-opacity", String(light.glowOpacity));
2785
2837
  const bezel = svgElement("circle", {
2786
2838
  class: "gaugeit__light-bezel",
2787
2839
  cx: 0,
@@ -2804,9 +2856,7 @@ var lightLayer = {
2804
2856
  radius: light.radius,
2805
2857
  gradientId: offGradientId,
2806
2858
  edgeColor: light.offEdgeColor,
2807
- glowColor: null,
2808
- glowFilterId: null,
2809
- sparkleOpacity: 0.58,
2859
+ sparkleOpacity: 0.24,
2810
2860
  shadeOpacity: 0.14
2811
2861
  });
2812
2862
  const onVisual = createLampVisual({
@@ -2814,13 +2864,18 @@ var lightLayer = {
2814
2864
  radius: light.radius,
2815
2865
  gradientId: onGradientId,
2816
2866
  edgeColor: palette.rim,
2817
- glowColor: palette.glow,
2818
- glowFilterId,
2819
- sparkleOpacity: 0.72,
2867
+ sparkleOpacity: 0.26,
2820
2868
  shadeOpacity: 0.1
2821
2869
  });
2822
- lamp.append(bezel, bezelHighlight, offVisual, onVisual);
2870
+ const glowVisual = createGlowVisual({
2871
+ radius: light.glowRadius,
2872
+ color: palette.glow,
2873
+ filterId: glowFilterId
2874
+ });
2875
+ lamp.append(glowVisual, bezel, bezelHighlight, offVisual, onVisual);
2823
2876
  group.append(lamp);
2877
+ const glowElement = glowVisual.querySelector(".gaugeit__light-glow");
2878
+ let flickerTimer = null;
2824
2879
  return {
2825
2880
  update(value, state = {}) {
2826
2881
  var _a;
@@ -2828,13 +2883,54 @@ var lightLayer = {
2828
2883
  const active = lightIsActive(light, sample);
2829
2884
  const blinking = active && light.blink;
2830
2885
  const pulsing = active && light.pulse && !blinking;
2886
+ const flickering = active && light.flicker && (light.flickerIntensity > 0 || light.flickerGlowRadius > 0) && !prefersReducedMotion();
2831
2887
  lamp.classList.toggle("is-on", active);
2832
2888
  lamp.classList.toggle("is-blinking", blinking);
2833
2889
  lamp.classList.toggle("is-pulsing", pulsing);
2890
+ lamp.classList.toggle("is-flickering", flickering);
2834
2891
  lamp.classList.toggle("has-glow", light.glow);
2835
2892
  lamp.setAttribute("data-gaugeit-light-state", active ? "on" : "off");
2893
+ setFlickerRunning(flickering);
2894
+ },
2895
+ destroy() {
2896
+ stopFlicker();
2836
2897
  }
2837
2898
  };
2899
+ function setFlickerRunning(enabled) {
2900
+ if (!enabled) {
2901
+ stopFlicker();
2902
+ return;
2903
+ }
2904
+ if (flickerTimer !== null) return;
2905
+ updateFlicker();
2906
+ scheduleFlicker();
2907
+ }
2908
+ function scheduleFlicker() {
2909
+ const delay = randomBetween(light.flickerMinInterval, light.flickerMaxInterval);
2910
+ flickerTimer = setTimeout(() => {
2911
+ flickerTimer = null;
2912
+ updateFlicker();
2913
+ scheduleFlicker();
2914
+ }, delay);
2915
+ }
2916
+ function updateFlicker() {
2917
+ const lightLevel = 1 - Math.random() * light.flickerIntensity;
2918
+ const onOpacity = light.opacity * lightLevel;
2919
+ const glowOpacity = light.glowOpacity * lightLevel;
2920
+ lamp.style.setProperty("--gaugeit-light-on-opacity", onOpacity.toFixed(3));
2921
+ lamp.style.setProperty("--gaugeit-light-glow-opacity", glowOpacity.toFixed(3));
2922
+ if (glowElement) {
2923
+ const variation = randomBetween(-light.flickerGlowRadius, light.flickerGlowRadius);
2924
+ glowElement.setAttribute("r", String(light.glowRadius * (1 + variation)));
2925
+ }
2926
+ }
2927
+ function stopFlicker() {
2928
+ if (flickerTimer !== null) clearTimeout(flickerTimer);
2929
+ flickerTimer = null;
2930
+ lamp.style.setProperty("--gaugeit-light-on-opacity", String(light.opacity));
2931
+ lamp.style.setProperty("--gaugeit-light-glow-opacity", String(light.glowOpacity));
2932
+ if (glowElement) glowElement.setAttribute("r", String(light.glowRadius));
2933
+ }
2838
2934
  }
2839
2935
  };
2840
2936
  function createLampVisual({
@@ -2842,8 +2938,6 @@ function createLampVisual({
2842
2938
  radius,
2843
2939
  gradientId,
2844
2940
  edgeColor,
2845
- glowColor,
2846
- glowFilterId,
2847
2941
  sparkleOpacity,
2848
2942
  shadeOpacity
2849
2943
  }) {
@@ -2851,16 +2945,6 @@ function createLampVisual({
2851
2945
  class: `gaugeit__light-emission gaugeit__light-emission--${state}`,
2852
2946
  "data-gaugeit-light-visual": state
2853
2947
  });
2854
- if (glowColor && glowFilterId) {
2855
- visual.append(svgElement("circle", {
2856
- class: "gaugeit__light-glow",
2857
- cx: 0,
2858
- cy: 0,
2859
- r: radius * 1.82,
2860
- fill: glowColor,
2861
- filter: `url(#${glowFilterId})`
2862
- }));
2863
- }
2864
2948
  visual.append(
2865
2949
  svgElement("circle", {
2866
2950
  class: `gaugeit__light-bulb gaugeit__light-bulb--${state}`,
@@ -2889,18 +2973,33 @@ function createLampVisual({
2889
2973
  );
2890
2974
  return visual;
2891
2975
  }
2976
+ function createGlowVisual({ radius, color, filterId }) {
2977
+ const visual = svgElement("g", {
2978
+ class: "gaugeit__light-glow-emission",
2979
+ "data-gaugeit-light-visual": "glow"
2980
+ });
2981
+ visual.append(svgElement("circle", {
2982
+ class: "gaugeit__light-glow",
2983
+ cx: 0,
2984
+ cy: 0,
2985
+ r: radius,
2986
+ fill: color,
2987
+ filter: `url(#${filterId})`
2988
+ }));
2989
+ return visual;
2990
+ }
2892
2991
  function resolvePalette(light) {
2893
- const named = LIGHT_PALETTES[light.color] || LIGHT_PALETTES.amber;
2992
+ const named = LIGHT_PALETTES[light.color] || LIGHT_PALETTES.red;
2894
2993
  const custom = String(light.customColor || "").trim();
2895
2994
  if (!custom) return named;
2896
2995
  return {
2897
2996
  core: custom,
2898
- highlight: "#ffffff",
2997
+ highlight: custom,
2899
2998
  glow: custom,
2900
2999
  rim: custom
2901
3000
  };
2902
3001
  }
2903
- function createGlowFilter(id, radius) {
3002
+ function createGlowFilter(id, glowRadius, sharpness) {
2904
3003
  const filter = svgElement("filter", {
2905
3004
  id,
2906
3005
  x: "-120%",
@@ -2908,11 +3007,18 @@ function createGlowFilter(id, radius) {
2908
3007
  width: "340%",
2909
3008
  height: "340%"
2910
3009
  });
3010
+ const maximumBlur = Math.max(1.4, glowRadius * 0.38);
2911
3011
  filter.append(svgElement("feGaussianBlur", {
2912
- stdDeviation: Math.max(1.4, radius * 0.38)
3012
+ stdDeviation: maximumBlur * (1 - sharpness)
2913
3013
  }));
2914
3014
  return filter;
2915
3015
  }
3016
+ function randomBetween(min, max) {
3017
+ return min + Math.random() * (max - min);
3018
+ }
3019
+ function prefersReducedMotion() {
3020
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
3021
+ }
2916
3022
  function createBulbGradient(id, colors) {
2917
3023
  const gradient = svgElement("radialGradient", {
2918
3024
  id,
@@ -3000,13 +3106,6 @@ var arcGaugeType = {
3000
3106
  width: 8,
3001
3107
  cap: { radius: 7, stackOrder: "above" }
3002
3108
  },
3003
- light: {
3004
- visible: false,
3005
- x: 160,
3006
- y: 142,
3007
- radius: 7,
3008
- color: "amber"
3009
- },
3010
3109
  readout: {
3011
3110
  title: { visible: false, x: "auto", y: 35 },
3012
3111
  value: { visible: false, x: 160, y: 130, fontSize: 30 },
@@ -3095,13 +3194,6 @@ var classicGaugeType = {
3095
3194
  strokeWidth: 2
3096
3195
  }
3097
3196
  },
3098
- light: {
3099
- visible: false,
3100
- x: 112,
3101
- y: 112,
3102
- radius: 8,
3103
- color: "amber"
3104
- },
3105
3197
  readout: {
3106
3198
  title: {
3107
3199
  visible: true,
@@ -3193,13 +3285,6 @@ var lineScaleGaugeType = {
3193
3285
  strokeWidth: 2
3194
3286
  }
3195
3287
  },
3196
- light: {
3197
- visible: false,
3198
- x: 160,
3199
- y: 151,
3200
- radius: 7,
3201
- color: "amber"
3202
- },
3203
3288
  readout: {
3204
3289
  title: { visible: false, x: "auto", y: 140 },
3205
3290
  value: { visible: false, x: 160, y: 220, fontSize: 33 },
@@ -3286,16 +3371,6 @@ var heritageRoundGaugeType = {
3286
3371
  strokeWidth: 2
3287
3372
  }
3288
3373
  },
3289
- light: {
3290
- visible: false,
3291
- x: 108,
3292
- y: 110,
3293
- radius: 10,
3294
- color: "amber",
3295
- blink: false,
3296
- blinkInterval: 1e3,
3297
- trigger: { mode: "below", source: "target", value: 15, min: 0, max: 15 }
3298
- },
3299
3374
  readout: {
3300
3375
  title: {
3301
3376
  visible: true,
@@ -3826,13 +3901,6 @@ var classicLinearDefaults = {
3826
3901
  strokeWidth: 1.2
3827
3902
  }
3828
3903
  },
3829
- light: {
3830
- visible: false,
3831
- x: 72,
3832
- y: 60,
3833
- radius: 8,
3834
- color: "amber"
3835
- },
3836
3904
  readout: {
3837
3905
  title: {
3838
3906
  visible: true,
@@ -4067,13 +4135,6 @@ var centerZeroGaugeType = {
4067
4135
  strokeWidth: 2
4068
4136
  }
4069
4137
  },
4070
- light: {
4071
- visible: false,
4072
- x: 112,
4073
- y: 205,
4074
- radius: 8,
4075
- color: "amber"
4076
- },
4077
4138
  readout: {
4078
4139
  title: {
4079
4140
  visible: true,
@@ -4423,13 +4484,6 @@ var rollingTapeGaugeType = {
4423
4484
  { min: 20, max: 80, color: "transparent" },
4424
4485
  { min: 80, max: 100, color: "#15803d" }
4425
4486
  ],
4426
- light: {
4427
- visible: false,
4428
- x: 72,
4429
- y: 46,
4430
- radius: 8,
4431
- color: "amber"
4432
- },
4433
4487
  readout: {
4434
4488
  title: {
4435
4489
  visible: true,
@@ -4644,7 +4698,7 @@ var geometry = Object.freeze({
4644
4698
  resolveLightPosition
4645
4699
  });
4646
4700
  var types = builtInTypes;
4647
- var VERSION = "0.1.0";
4701
+ var VERSION = "0.1.1";
4648
4702
  var Gaugeit = Object.freeze({
4649
4703
  VERSION,
4650
4704
  Gauge,