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 +51 -27
- package/SECURITY.md +2 -2
- package/dist/gaugeit.cjs +158 -104
- package/dist/gaugeit.cjs.map +3 -3
- package/dist/gaugeit.css +32 -20
- package/dist/gaugeit.d.ts +17 -0
- package/dist/gaugeit.esm.js +158 -104
- package/dist/gaugeit.esm.js.map +3 -3
- package/dist/gaugeit.esm.min.js +2 -2
- package/dist/gaugeit.esm.min.js.map +3 -3
- package/dist/gaugeit.min.cjs +2 -2
- package/dist/gaugeit.min.cjs.map +3 -3
- package/dist/gaugeit.min.css +1 -1
- package/dist/gaugeit.standalone.js +159 -105
- package/dist/gaugeit.standalone.js.map +3 -3
- package/dist/gaugeit.standalone.min.js +35 -23
- package/dist/gaugeit.standalone.min.js.map +3 -3
- package/dist/gaugeit.umd.js +158 -104
- package/dist/gaugeit.umd.js.map +3 -3
- package/dist/gaugeit.umd.min.js +2 -2
- package/dist/gaugeit.umd.min.js.map +3 -3
- package/dist/manifest.json +20 -20
- package/docs/ai/ai-full.md +5097 -0
- package/docs/ai/contributor-guide.md +928 -0
- package/docs/ai/index.md +73 -0
- package/docs/ai/integration-recipes.md +1117 -0
- package/docs/ai/library-usage.md +875 -0
- package/docs/ai/options-reference.md +1107 -0
- package/docs/ai/troubleshooting.md +1024 -0
- package/docs/api.md +34 -7
- package/docs/architecture.md +10 -2
- package/docs/creating-gauge-types.md +2 -1
- package/docs/development.md +2 -2
- package/docs/framework-integration.md +2 -2
- package/package.json +1 -1
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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:
|
|
466
|
+
x: 93,
|
|
470
467
|
y: 110,
|
|
471
|
-
radius:
|
|
472
|
-
|
|
468
|
+
radius: 8,
|
|
469
|
+
glowRadius: 20,
|
|
470
|
+
glowSharpness: 0,
|
|
471
|
+
glowOpacity: 0.15,
|
|
472
|
+
color: 'red',
|
|
473
473
|
offColor: '#f3ead6',
|
|
474
|
-
pulse:
|
|
475
|
-
blink:
|
|
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. `
|
|
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.
|
|
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
|
|
497
|
-
`light.visible`
|
|
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.
|
|
879
|
-
`kasperi/gaugeit-js
|
|
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
|
-
|
|
883
|
-
|
|
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
package/dist/gaugeit.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Gaugeit.js v0.1.
|
|
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
|
|
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:
|
|
1322
|
+
x: 93,
|
|
1317
1323
|
y: 110,
|
|
1318
1324
|
radius: 8,
|
|
1319
|
-
|
|
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:
|
|
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: "
|
|
1347
|
+
mode: "below",
|
|
1334
1348
|
source: "target",
|
|
1335
|
-
value:
|
|
1349
|
+
value: 15,
|
|
1336
1350
|
min: 0,
|
|
1337
|
-
max:
|
|
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,
|
|
1642
|
-
light.y = finiteNumber(light.y,
|
|
1643
|
-
light.radius = Math.max(1, finiteNumber(light.radius,
|
|
1644
|
-
light.
|
|
1645
|
-
light.
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
light.
|
|
1650
|
-
light.
|
|
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
|
|
1654
|
-
light.pulseInterval = Math.max(400, finiteNumber(light.pulseInterval,
|
|
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,
|
|
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 :
|
|
1659
|
-
light.trigger.source = VALID_LIGHT_TRIGGER_SOURCES.has(light.trigger.source) ? light.trigger.source :
|
|
1660
|
-
light.trigger.value = finiteNumber(light.trigger.value,
|
|
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 : "
|
|
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.
|
|
2835
|
+
createGlowFilter(glowFilterId, light.glowRadius, light.glowSharpness),
|
|
2786
2836
|
createBulbGradient(onGradientId, {
|
|
2787
|
-
center:
|
|
2788
|
-
highlight: palette.
|
|
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
|
-
|
|
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
|
-
|
|
2844
|
-
glowFilterId,
|
|
2845
|
-
sparkleOpacity: 0.72,
|
|
2893
|
+
sparkleOpacity: 0.26,
|
|
2846
2894
|
shadeOpacity: 0.1
|
|
2847
2895
|
});
|
|
2848
|
-
|
|
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.
|
|
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:
|
|
3022
|
+
highlight: custom,
|
|
2924
3023
|
glow: custom,
|
|
2925
3024
|
rim: custom
|
|
2926
3025
|
};
|
|
2927
3026
|
}
|
|
2928
|
-
function createGlowFilter(id,
|
|
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:
|
|
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.
|
|
4722
|
+
var VERSION = "0.1.1";
|
|
4669
4723
|
var Gaugeit = Object.freeze({
|
|
4670
4724
|
VERSION,
|
|
4671
4725
|
Gauge,
|