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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gaugeit.js is a lightweight, dependency-free, extensible analog gauge library built with native SVG, JavaScript, and a small optional CSS file.
4
4
 
5
- The first release includes eight gauge types:
5
+ Gaugeit.js includes eight gauge types:
6
6
 
7
7
  - `arc`: a clean semicircular gauge with configurable colored or transparent sectors;
8
8
  - `classic`: a framed, white, old-style instrument meter;
@@ -15,10 +15,7 @@ The first release includes eight gauge types:
15
15
 
16
16
  The runtime has no image, jQuery, canvas, or framework dependency. It can be used from a classic `<script>` tag, an ES module, a custom element, React, Twig, Blade, or another server-rendered application.
17
17
 
18
- > **Current release:** `0.1.0`
19
- >
20
- > Source code, prebuilt distributions, documentation, examples, and package
21
- > metadata are maintained in this repository.
18
+ > **Current release:** `0.1.1`
22
19
 
23
20
  ## Why SVG
24
21
 
@@ -97,7 +94,7 @@ The standalone and separate-file builds are generated from the same canonical
97
94
  ## npm installation
98
95
 
99
96
  ```bash
100
- npm install gaugeit.js@0.1.0
97
+ npm install gaugeit.js@0.1.1
101
98
  ```
102
99
 
103
100
  ```js
@@ -126,10 +123,10 @@ Use exact versions in production. CDN consumers need no installation or compilat
126
123
  ```html
127
124
  <link
128
125
  rel="stylesheet"
129
- href="https://cdn.jsdelivr.net/npm/gaugeit.js@0.1.0/dist/gaugeit.min.css"
126
+ href="https://cdn.jsdelivr.net/npm/gaugeit.js@0.1.1/dist/gaugeit.min.css"
130
127
  >
131
128
  <script
132
- src="https://cdn.jsdelivr.net/npm/gaugeit.js@0.1.0/dist/gaugeit.umd.min.js"
129
+ src="https://cdn.jsdelivr.net/npm/gaugeit.js@0.1.1/dist/gaugeit.umd.min.js"
133
130
  ></script>
134
131
  ```
135
132
 
@@ -137,7 +134,7 @@ Use exact versions in production. CDN consumers need no installation or compilat
137
134
 
138
135
  ```html
139
136
  <script
140
- src="https://cdn.jsdelivr.net/npm/gaugeit.js@0.1.0/dist/gaugeit.standalone.min.js"
137
+ src="https://cdn.jsdelivr.net/npm/gaugeit.js@0.1.1/dist/gaugeit.standalone.min.js"
141
138
  ></script>
142
139
  ```
143
140
 
@@ -146,15 +143,15 @@ Use exact versions in production. CDN consumers need no installation or compilat
146
143
  ```html
147
144
  <link
148
145
  rel="stylesheet"
149
- href="https://unpkg.com/gaugeit.js@0.1.0/dist/gaugeit.min.css"
146
+ href="https://unpkg.com/gaugeit.js@0.1.1/dist/gaugeit.min.css"
150
147
  >
151
148
  <script
152
- src="https://unpkg.com/gaugeit.js@0.1.0/dist/gaugeit.umd.min.js"
149
+ src="https://unpkg.com/gaugeit.js@0.1.1/dist/gaugeit.umd.min.js"
153
150
  ></script>
154
151
  ```
155
152
 
156
153
  The UNPKG one-file equivalent is
157
- `https://unpkg.com/gaugeit.js@0.1.0/dist/gaugeit.standalone.min.js`.
154
+ `https://unpkg.com/gaugeit.js@0.1.1/dist/gaugeit.standalone.min.js`.
158
155
 
159
156
  ## Built-in gauge gallery
160
157
 
@@ -466,14 +463,22 @@ createGauge('#fuel', {
466
463
  value: 12,
467
464
  light: {
468
465
  visible: true,
469
- x: 108,
466
+ x: 93,
470
467
  y: 110,
471
- radius: 10,
472
- color: 'amber',
468
+ radius: 8,
469
+ glowRadius: 20,
470
+ glowSharpness: 0,
471
+ glowOpacity: 0.15,
472
+ color: 'red',
473
473
  offColor: '#f3ead6',
474
- pulse: true,
475
- blink: true,
474
+ pulse: false,
475
+ blink: false,
476
476
  blinkInterval: 1000,
477
+ flicker: true,
478
+ flickerIntensity: 0.1,
479
+ flickerGlowRadius: 0.1,
480
+ flickerMinInterval: 45,
481
+ flickerMaxInterval: 140,
477
482
  trigger: { mode: 'below', source: 'target', value: 15 }
478
483
  }
479
484
  });
@@ -483,18 +488,39 @@ Built-in palettes are `red`, `green`, `blue`, `amber`, `yellow`, `orange`,
483
488
  `white`, `halogen`, `cyan`, and `brown`. Use `customColor` for an application-specific
484
489
  active color. The unlit lamp deliberately uses a softly diffused cream lens rather than
485
490
  a black bulb; `offColor`, `offEdgeColor`, `bezelColor`, and `bezelHighlightColor` can
486
- customize that hardware appearance. `pulse` adds a deliberately subtle steady-light
491
+ customize that hardware appearance. `radius` controls the physical lamp while
492
+ `glowRadius` controls the halo independently and defaults to `20`. Set it to `null` to
493
+ derive the halo radius from `radius * 1.82`. `glowSharpness` controls the halo blur:
494
+ `0` uses a soft Gaussian glow, while `1` removes blur for a completely sharp
495
+ edge. Intermediate values reduce the blur continuously. `glowOpacity` controls only the
496
+ halo and defaults to `0.15`, independently from the illuminated lens `opacity`.
497
+ The halo is painted below the opaque lamp hardware, so it becomes visible beyond the
498
+ lamp edges instead of covering the lens. `pulse` adds a deliberately subtle steady-light
487
499
  breathing effect. `blink` alternates the complete illuminated and unlit lens states, so
488
500
  the dark half-cycle looks exactly like the normal switched-off lamp rather than a faded
489
- transparent bulb. Trigger modes are `manual`, `below`, `above`, and `between`. The trigger source
501
+ transparent bulb. Blink takes precedence if both blink and pulse are enabled.
502
+ `flicker` adds rapid random changes to the amount of emitted light. `flickerIntensity`
503
+ sets the maximum random loss from full light: `0` is steady and `1` may momentarily
504
+ reach the real unlit-lens appearance. It never darkens the lit lens toward black.
505
+ `flickerGlowRadius` independently varies the halo radius by a relative plus/minus amount:
506
+ with `glowRadius: 20`, the default `0.1` produces radii between 18 and 22.
507
+ Each change waits a random duration between `flickerMinInterval` and
508
+ `flickerMaxInterval`. Flicker is independent and may be combined with
509
+ either pulse or blink. Flicker is enabled by default, but has no visual effect while the
510
+ lamp is hidden or inactive. Trigger modes are `manual`, `below`, `above`, and `between`. The trigger source
490
511
  defaults to `target`, so a low-value lamp does not flash merely because a startup
491
512
  animation begins at the minimum. Use `displayed` to follow the animated readout value
492
513
  or `pointer` to include visual jitter. For linear gauges, `light.y` follows the same
493
514
  positive-up coordinate convention as the linear axis.
494
515
 
516
+ `opacity` controls only the illuminated lens layered over an always-opaque unlit lens.
517
+ The physical lamp and bezel therefore remain fully visible even at `opacity: 0`;
518
+ `glowOpacity` remains the separate control for the halo.
519
+
495
520
  Custom types can opt in with `Gaugeit.layers.light`; all built-in types already include
496
- the layer and provide a sensible type-specific fallback position while keeping
497
- `light.visible` false.
521
+ the layer and use the same shared light defaults. The lamp remains disabled until
522
+ `light.visible` is true. The interactive `example.html` explicitly enables blink and
523
+ disables flicker for its heritage-round demonstration.
498
524
 
499
525
  ## Intrinsic dimensions and host sizing
500
526
 
@@ -875,13 +901,11 @@ Gaugeit.js/
875
901
 
876
902
  ## Release metadata
877
903
 
878
- Version `0.1.0` uses the npm package name `gaugeit.js`, Composer package name
879
- `kasperi/gaugeit-js`, and source repository
880
- `https://github.com/kasperikoski/gaugeit.js`. Author metadata identifies Kasperi Koski.
904
+ Version: `0.1.1`. npm package: `gaugeit.js`. Composer package:
905
+ `kasperi/gaugeit-js`. Repository: `https://github.com/kasperikoski/gaugeit.js`.
881
906
 
882
- The build and CI workflows validate release artifacts but never publish, tag, or create
883
- remote releases automatically. Publishing to GitHub, npm, and Packagist remains an
884
- explicit maintainer action.
907
+ Build and CI workflows validate release artifacts. Publishing to GitHub, npm, and
908
+ Packagist is a manual maintainer action.
885
909
 
886
910
  ## Contributing and security
887
911
 
package/SECURITY.md CHANGED
@@ -5,8 +5,8 @@
5
5
  Security updates are provided for the latest published Gaugeit.js release.
6
6
 
7
7
  | Version | Supported |
8
- | --- | --- |
9
- | 0.1.x | Yes |
8
+ | ------- | --------- |
9
+ | 0.1.x | Yes |
10
10
 
11
11
  ## Reporting a vulnerability
12
12
 
package/dist/gaugeit.cjs CHANGED
@@ -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
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -867,7 +867,13 @@ function includeLight(bounds, options) {
867
867
  if (!light?.visible) return;
868
868
  const point = resolveLightPosition(light, options);
869
869
  const radius = Math.max(1, finiteNumber(light.radius, 8));
870
- const halo = light.glow ? radius * 2.96 : radius;
870
+ const glowRadius = Math.max(0, finiteNumber(light.glowRadius, radius * 1.82));
871
+ const flickerGlowRadius = light.flicker ? Math.min(1, Math.max(0, finiteNumber(light.flickerGlowRadius, 0))) : 0;
872
+ const maximumGlowRadius = glowRadius * (1 + flickerGlowRadius);
873
+ const glowSharpness = Math.min(1, Math.max(0, finiteNumber(light.glowSharpness, 0)));
874
+ const maximumBlur = glowRadius > 0 ? Math.max(1.4, glowRadius * 0.38) : 0;
875
+ const glowBlur = maximumBlur * (1 - glowSharpness);
876
+ const halo = light.glow ? maximumGlowRadius + glowBlur * 3 + (maximumGlowRadius > 0 ? 1e-9 : 0) : radius;
871
877
  const bezel = radius + Math.max(1.5, radius * 0.18);
872
878
  const extent = Math.max(halo, bezel);
873
879
  includeRect(bounds, point.x - extent, point.y - extent, extent * 2, extent * 2);
@@ -1313,28 +1319,36 @@ var BASE_DEFAULTS = Object.freeze({
1313
1319
  },
1314
1320
  light: {
1315
1321
  visible: false,
1316
- x: 160,
1322
+ x: 93,
1317
1323
  y: 110,
1318
1324
  radius: 8,
1319
- color: "amber",
1325
+ glowRadius: 20,
1326
+ glowSharpness: 0,
1327
+ color: "red",
1320
1328
  customColor: "",
1321
1329
  offColor: "#f3ead6",
1322
1330
  offEdgeColor: "#817768",
1323
1331
  bezelColor: "#4b5563",
1324
1332
  bezelHighlightColor: "#f8fafc",
1325
1333
  opacity: 1,
1334
+ glowOpacity: 0.15,
1326
1335
  on: false,
1327
1336
  glow: true,
1328
- pulse: true,
1337
+ pulse: false,
1329
1338
  pulseInterval: 2600,
1330
1339
  blink: false,
1331
1340
  blinkInterval: 1e3,
1341
+ flicker: true,
1342
+ flickerIntensity: 0.1,
1343
+ flickerGlowRadius: 0.1,
1344
+ flickerMinInterval: 45,
1345
+ flickerMaxInterval: 140,
1332
1346
  trigger: {
1333
- mode: "manual",
1347
+ mode: "below",
1334
1348
  source: "target",
1335
- value: 0,
1349
+ value: 15,
1336
1350
  min: 0,
1337
- max: 0
1351
+ max: 15
1338
1352
  }
1339
1353
  },
1340
1354
  readout: {
@@ -1637,27 +1651,63 @@ function validateTape(tape) {
1637
1651
  tape.colorByZone = tape.colorByZone === true;
1638
1652
  }
1639
1653
  function validateLight(light) {
1654
+ const defaults2 = BASE_DEFAULTS.light;
1640
1655
  light.visible = light.visible === true;
1641
- light.x = finiteNumber(light.x, 160);
1642
- light.y = finiteNumber(light.y, 110);
1643
- light.radius = Math.max(1, finiteNumber(light.radius, 8));
1644
- light.color = VALID_LIGHT_COLORS.has(light.color) ? light.color : "amber";
1645
- light.customColor = light.customColor === null || light.customColor === void 0 ? "" : String(light.customColor).trim();
1646
- light.offColor = normalizeColor(light.offColor, "#f3ead6");
1647
- light.offEdgeColor = normalizeColor(light.offEdgeColor, "#817768");
1648
- light.bezelColor = normalizeColor(light.bezelColor, "#4b5563");
1649
- light.bezelHighlightColor = normalizeColor(light.bezelHighlightColor, "#f8fafc");
1650
- light.opacity = Math.min(1, Math.max(0, finiteNumber(light.opacity, 1)));
1656
+ light.x = finiteNumber(light.x, defaults2.x);
1657
+ light.y = finiteNumber(light.y, defaults2.y);
1658
+ light.radius = Math.max(1, finiteNumber(light.radius, defaults2.radius));
1659
+ light.glowRadius = light.glowRadius === null || light.glowRadius === void 0 ? light.radius * 1.82 : Math.max(0, finiteNumber(light.glowRadius, defaults2.glowRadius));
1660
+ light.glowSharpness = Math.min(
1661
+ 1,
1662
+ Math.max(0, finiteNumber(light.glowSharpness, defaults2.glowSharpness))
1663
+ );
1664
+ light.color = VALID_LIGHT_COLORS.has(light.color) ? light.color : defaults2.color;
1665
+ light.customColor = light.customColor === null || light.customColor === void 0 ? defaults2.customColor : String(light.customColor).trim();
1666
+ light.offColor = normalizeColor(light.offColor, defaults2.offColor);
1667
+ light.offEdgeColor = normalizeColor(light.offEdgeColor, defaults2.offEdgeColor);
1668
+ light.bezelColor = normalizeColor(light.bezelColor, defaults2.bezelColor);
1669
+ light.bezelHighlightColor = normalizeColor(
1670
+ light.bezelHighlightColor,
1671
+ defaults2.bezelHighlightColor
1672
+ );
1673
+ light.opacity = Math.min(1, Math.max(0, finiteNumber(light.opacity, defaults2.opacity)));
1674
+ light.glowOpacity = Math.min(
1675
+ 1,
1676
+ Math.max(0, finiteNumber(light.glowOpacity, defaults2.glowOpacity))
1677
+ );
1651
1678
  light.on = light.on === true;
1652
1679
  light.glow = light.glow !== false;
1653
- light.pulse = light.pulse !== false;
1654
- light.pulseInterval = Math.max(400, finiteNumber(light.pulseInterval, 2600));
1680
+ light.pulse = light.pulse === true;
1681
+ light.pulseInterval = Math.max(400, finiteNumber(light.pulseInterval, defaults2.pulseInterval));
1655
1682
  light.blink = light.blink === true;
1656
- light.blinkInterval = Math.max(100, finiteNumber(light.blinkInterval, 1e3));
1683
+ light.blinkInterval = Math.max(100, finiteNumber(light.blinkInterval, defaults2.blinkInterval));
1684
+ light.flicker = light.flicker === true;
1685
+ light.flickerIntensity = Math.min(
1686
+ 1,
1687
+ Math.max(0, finiteNumber(light.flickerIntensity, defaults2.flickerIntensity))
1688
+ );
1689
+ light.flickerGlowRadius = Math.min(
1690
+ 1,
1691
+ Math.max(0, finiteNumber(light.flickerGlowRadius, defaults2.flickerGlowRadius))
1692
+ );
1693
+ light.flickerMinInterval = Math.max(
1694
+ 16,
1695
+ finiteNumber(light.flickerMinInterval, defaults2.flickerMinInterval)
1696
+ );
1697
+ light.flickerMaxInterval = Math.max(
1698
+ 16,
1699
+ finiteNumber(light.flickerMaxInterval, defaults2.flickerMaxInterval)
1700
+ );
1701
+ if (light.flickerMaxInterval < light.flickerMinInterval) {
1702
+ [light.flickerMinInterval, light.flickerMaxInterval] = [
1703
+ light.flickerMaxInterval,
1704
+ light.flickerMinInterval
1705
+ ];
1706
+ }
1657
1707
  light.trigger = isPlainObject(light.trigger) ? light.trigger : {};
1658
- light.trigger.mode = VALID_LIGHT_TRIGGER_MODES.has(light.trigger.mode) ? light.trigger.mode : "manual";
1659
- light.trigger.source = VALID_LIGHT_TRIGGER_SOURCES.has(light.trigger.source) ? light.trigger.source : "target";
1660
- light.trigger.value = finiteNumber(light.trigger.value, 0);
1708
+ light.trigger.mode = VALID_LIGHT_TRIGGER_MODES.has(light.trigger.mode) ? light.trigger.mode : defaults2.trigger.mode;
1709
+ light.trigger.source = VALID_LIGHT_TRIGGER_SOURCES.has(light.trigger.source) ? light.trigger.source : defaults2.trigger.source;
1710
+ light.trigger.value = finiteNumber(light.trigger.value, defaults2.trigger.value);
1661
1711
  light.trigger.min = finiteNumber(light.trigger.min, light.trigger.value);
1662
1712
  light.trigger.max = finiteNumber(light.trigger.max, light.trigger.value);
1663
1713
  if (light.trigger.max < light.trigger.min) {
@@ -2775,17 +2825,17 @@ var lightLayer = {
2775
2825
  if (!light?.visible) return null;
2776
2826
  const { x, y } = resolveLightPosition(light, options);
2777
2827
  const palette = resolvePalette(light);
2778
- const colorName = Object.prototype.hasOwnProperty.call(LIGHT_PALETTES, light.color) ? light.color : "amber";
2828
+ const colorName = Object.prototype.hasOwnProperty.call(LIGHT_PALETTES, light.color) ? light.color : "red";
2779
2829
  const glowFilterId = `${renderer.id}-light-glow`;
2780
2830
  const onGradientId = `${renderer.id}-light-on`;
2781
2831
  const offGradientId = `${renderer.id}-light-off`;
2782
2832
  const bezelGradientId = `${renderer.id}-light-bezel`;
2783
2833
  const defs = svgElement("defs");
2784
2834
  defs.append(
2785
- createGlowFilter(glowFilterId, light.radius),
2835
+ createGlowFilter(glowFilterId, light.glowRadius, light.glowSharpness),
2786
2836
  createBulbGradient(onGradientId, {
2787
- center: "#ffffff",
2788
- highlight: palette.highlight,
2837
+ center: palette.highlight,
2838
+ highlight: palette.core,
2789
2839
  middle: palette.core,
2790
2840
  edge: palette.rim
2791
2841
  }),
@@ -2808,6 +2858,8 @@ var lightLayer = {
2808
2858
  lamp.style.setProperty("--gaugeit-light-blink-duration", `${light.blinkInterval}ms`);
2809
2859
  lamp.style.setProperty("--gaugeit-light-pulse-duration", `${light.pulseInterval}ms`);
2810
2860
  lamp.style.setProperty("--gaugeit-light-opacity", String(light.opacity));
2861
+ lamp.style.setProperty("--gaugeit-light-on-opacity", String(light.opacity));
2862
+ lamp.style.setProperty("--gaugeit-light-glow-opacity", String(light.glowOpacity));
2811
2863
  const bezel = svgElement("circle", {
2812
2864
  class: "gaugeit__light-bezel",
2813
2865
  cx: 0,
@@ -2830,9 +2882,7 @@ var lightLayer = {
2830
2882
  radius: light.radius,
2831
2883
  gradientId: offGradientId,
2832
2884
  edgeColor: light.offEdgeColor,
2833
- glowColor: null,
2834
- glowFilterId: null,
2835
- sparkleOpacity: 0.58,
2885
+ sparkleOpacity: 0.24,
2836
2886
  shadeOpacity: 0.14
2837
2887
  });
2838
2888
  const onVisual = createLampVisual({
@@ -2840,26 +2890,72 @@ var lightLayer = {
2840
2890
  radius: light.radius,
2841
2891
  gradientId: onGradientId,
2842
2892
  edgeColor: palette.rim,
2843
- glowColor: palette.glow,
2844
- glowFilterId,
2845
- sparkleOpacity: 0.72,
2893
+ sparkleOpacity: 0.26,
2846
2894
  shadeOpacity: 0.1
2847
2895
  });
2848
- lamp.append(bezel, bezelHighlight, offVisual, onVisual);
2896
+ const glowVisual = createGlowVisual({
2897
+ radius: light.glowRadius,
2898
+ color: palette.glow,
2899
+ filterId: glowFilterId
2900
+ });
2901
+ lamp.append(glowVisual, bezel, bezelHighlight, offVisual, onVisual);
2849
2902
  group.append(lamp);
2903
+ const glowElement = glowVisual.querySelector(".gaugeit__light-glow");
2904
+ let flickerTimer = null;
2850
2905
  return {
2851
2906
  update(value, state = {}) {
2852
2907
  const sample = resolveTriggerSample(light.trigger?.source, value, state);
2853
2908
  const active = lightIsActive(light, sample);
2854
2909
  const blinking = active && light.blink;
2855
2910
  const pulsing = active && light.pulse && !blinking;
2911
+ const flickering = active && light.flicker && (light.flickerIntensity > 0 || light.flickerGlowRadius > 0) && !prefersReducedMotion();
2856
2912
  lamp.classList.toggle("is-on", active);
2857
2913
  lamp.classList.toggle("is-blinking", blinking);
2858
2914
  lamp.classList.toggle("is-pulsing", pulsing);
2915
+ lamp.classList.toggle("is-flickering", flickering);
2859
2916
  lamp.classList.toggle("has-glow", light.glow);
2860
2917
  lamp.setAttribute("data-gaugeit-light-state", active ? "on" : "off");
2918
+ setFlickerRunning(flickering);
2919
+ },
2920
+ destroy() {
2921
+ stopFlicker();
2861
2922
  }
2862
2923
  };
2924
+ function setFlickerRunning(enabled) {
2925
+ if (!enabled) {
2926
+ stopFlicker();
2927
+ return;
2928
+ }
2929
+ if (flickerTimer !== null) return;
2930
+ updateFlicker();
2931
+ scheduleFlicker();
2932
+ }
2933
+ function scheduleFlicker() {
2934
+ const delay = randomBetween(light.flickerMinInterval, light.flickerMaxInterval);
2935
+ flickerTimer = setTimeout(() => {
2936
+ flickerTimer = null;
2937
+ updateFlicker();
2938
+ scheduleFlicker();
2939
+ }, delay);
2940
+ }
2941
+ function updateFlicker() {
2942
+ const lightLevel = 1 - Math.random() * light.flickerIntensity;
2943
+ const onOpacity = light.opacity * lightLevel;
2944
+ const glowOpacity = light.glowOpacity * lightLevel;
2945
+ lamp.style.setProperty("--gaugeit-light-on-opacity", onOpacity.toFixed(3));
2946
+ lamp.style.setProperty("--gaugeit-light-glow-opacity", glowOpacity.toFixed(3));
2947
+ if (glowElement) {
2948
+ const variation = randomBetween(-light.flickerGlowRadius, light.flickerGlowRadius);
2949
+ glowElement.setAttribute("r", String(light.glowRadius * (1 + variation)));
2950
+ }
2951
+ }
2952
+ function stopFlicker() {
2953
+ if (flickerTimer !== null) clearTimeout(flickerTimer);
2954
+ flickerTimer = null;
2955
+ lamp.style.setProperty("--gaugeit-light-on-opacity", String(light.opacity));
2956
+ lamp.style.setProperty("--gaugeit-light-glow-opacity", String(light.glowOpacity));
2957
+ if (glowElement) glowElement.setAttribute("r", String(light.glowRadius));
2958
+ }
2863
2959
  }
2864
2960
  };
2865
2961
  function createLampVisual({
@@ -2867,8 +2963,6 @@ function createLampVisual({
2867
2963
  radius,
2868
2964
  gradientId,
2869
2965
  edgeColor,
2870
- glowColor,
2871
- glowFilterId,
2872
2966
  sparkleOpacity,
2873
2967
  shadeOpacity
2874
2968
  }) {
@@ -2876,16 +2970,6 @@ function createLampVisual({
2876
2970
  class: `gaugeit__light-emission gaugeit__light-emission--${state}`,
2877
2971
  "data-gaugeit-light-visual": state
2878
2972
  });
2879
- if (glowColor && glowFilterId) {
2880
- visual.append(svgElement("circle", {
2881
- class: "gaugeit__light-glow",
2882
- cx: 0,
2883
- cy: 0,
2884
- r: radius * 1.82,
2885
- fill: glowColor,
2886
- filter: `url(#${glowFilterId})`
2887
- }));
2888
- }
2889
2973
  visual.append(
2890
2974
  svgElement("circle", {
2891
2975
  class: `gaugeit__light-bulb gaugeit__light-bulb--${state}`,
@@ -2914,18 +2998,33 @@ function createLampVisual({
2914
2998
  );
2915
2999
  return visual;
2916
3000
  }
3001
+ function createGlowVisual({ radius, color, filterId }) {
3002
+ const visual = svgElement("g", {
3003
+ class: "gaugeit__light-glow-emission",
3004
+ "data-gaugeit-light-visual": "glow"
3005
+ });
3006
+ visual.append(svgElement("circle", {
3007
+ class: "gaugeit__light-glow",
3008
+ cx: 0,
3009
+ cy: 0,
3010
+ r: radius,
3011
+ fill: color,
3012
+ filter: `url(#${filterId})`
3013
+ }));
3014
+ return visual;
3015
+ }
2917
3016
  function resolvePalette(light) {
2918
- const named = LIGHT_PALETTES[light.color] || LIGHT_PALETTES.amber;
3017
+ const named = LIGHT_PALETTES[light.color] || LIGHT_PALETTES.red;
2919
3018
  const custom = String(light.customColor || "").trim();
2920
3019
  if (!custom) return named;
2921
3020
  return {
2922
3021
  core: custom,
2923
- highlight: "#ffffff",
3022
+ highlight: custom,
2924
3023
  glow: custom,
2925
3024
  rim: custom
2926
3025
  };
2927
3026
  }
2928
- function createGlowFilter(id, radius) {
3027
+ function createGlowFilter(id, glowRadius, sharpness) {
2929
3028
  const filter = svgElement("filter", {
2930
3029
  id,
2931
3030
  x: "-120%",
@@ -2933,11 +3032,18 @@ function createGlowFilter(id, radius) {
2933
3032
  width: "340%",
2934
3033
  height: "340%"
2935
3034
  });
3035
+ const maximumBlur = Math.max(1.4, glowRadius * 0.38);
2936
3036
  filter.append(svgElement("feGaussianBlur", {
2937
- stdDeviation: Math.max(1.4, radius * 0.38)
3037
+ stdDeviation: maximumBlur * (1 - sharpness)
2938
3038
  }));
2939
3039
  return filter;
2940
3040
  }
3041
+ function randomBetween(min, max) {
3042
+ return min + Math.random() * (max - min);
3043
+ }
3044
+ function prefersReducedMotion() {
3045
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
3046
+ }
2941
3047
  function createBulbGradient(id, colors) {
2942
3048
  const gradient = svgElement("radialGradient", {
2943
3049
  id,
@@ -3025,13 +3131,6 @@ var arcGaugeType = {
3025
3131
  width: 8,
3026
3132
  cap: { radius: 7, stackOrder: "above" }
3027
3133
  },
3028
- light: {
3029
- visible: false,
3030
- x: 160,
3031
- y: 142,
3032
- radius: 7,
3033
- color: "amber"
3034
- },
3035
3134
  readout: {
3036
3135
  title: { visible: false, x: "auto", y: 35 },
3037
3136
  value: { visible: false, x: 160, y: 130, fontSize: 30 },
@@ -3120,13 +3219,6 @@ var classicGaugeType = {
3120
3219
  strokeWidth: 2
3121
3220
  }
3122
3221
  },
3123
- light: {
3124
- visible: false,
3125
- x: 112,
3126
- y: 112,
3127
- radius: 8,
3128
- color: "amber"
3129
- },
3130
3222
  readout: {
3131
3223
  title: {
3132
3224
  visible: true,
@@ -3218,13 +3310,6 @@ var lineScaleGaugeType = {
3218
3310
  strokeWidth: 2
3219
3311
  }
3220
3312
  },
3221
- light: {
3222
- visible: false,
3223
- x: 160,
3224
- y: 151,
3225
- radius: 7,
3226
- color: "amber"
3227
- },
3228
3313
  readout: {
3229
3314
  title: { visible: false, x: "auto", y: 140 },
3230
3315
  value: { visible: false, x: 160, y: 220, fontSize: 33 },
@@ -3311,16 +3396,6 @@ var heritageRoundGaugeType = {
3311
3396
  strokeWidth: 2
3312
3397
  }
3313
3398
  },
3314
- light: {
3315
- visible: false,
3316
- x: 108,
3317
- y: 110,
3318
- radius: 10,
3319
- color: "amber",
3320
- blink: false,
3321
- blinkInterval: 1e3,
3322
- trigger: { mode: "below", source: "target", value: 15, min: 0, max: 15 }
3323
- },
3324
3399
  readout: {
3325
3400
  title: {
3326
3401
  visible: true,
@@ -3849,13 +3924,6 @@ var classicLinearDefaults = {
3849
3924
  strokeWidth: 1.2
3850
3925
  }
3851
3926
  },
3852
- light: {
3853
- visible: false,
3854
- x: 72,
3855
- y: 60,
3856
- radius: 8,
3857
- color: "amber"
3858
- },
3859
3927
  readout: {
3860
3928
  title: {
3861
3929
  visible: true,
@@ -4088,13 +4156,6 @@ var centerZeroGaugeType = {
4088
4156
  strokeWidth: 2
4089
4157
  }
4090
4158
  },
4091
- light: {
4092
- visible: false,
4093
- x: 112,
4094
- y: 205,
4095
- radius: 8,
4096
- color: "amber"
4097
- },
4098
4159
  readout: {
4099
4160
  title: {
4100
4161
  visible: true,
@@ -4444,13 +4505,6 @@ var rollingTapeGaugeType = {
4444
4505
  { min: 20, max: 80, color: "transparent" },
4445
4506
  { min: 80, max: 100, color: "#15803d" }
4446
4507
  ],
4447
- light: {
4448
- visible: false,
4449
- x: 72,
4450
- y: 46,
4451
- radius: 8,
4452
- color: "amber"
4453
- },
4454
4508
  readout: {
4455
4509
  title: {
4456
4510
  visible: true,
@@ -4665,7 +4719,7 @@ var geometry = Object.freeze({
4665
4719
  resolveLightPosition
4666
4720
  });
4667
4721
  var types = builtInTypes;
4668
- var VERSION = "0.1.0";
4722
+ var VERSION = "0.1.1";
4669
4723
  var Gaugeit = Object.freeze({
4670
4724
  VERSION,
4671
4725
  Gauge,