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.
@@ -0,0 +1,875 @@
1
+ # Using Gaugeit.js effectively
2
+
3
+ This guide is written for an AI that must generate working Gaugeit.js 0.1.1
4
+ integration code without guessing. It focuses on selecting the correct distribution,
5
+ creating and updating gauges, integrating lifecycle ownership, and avoiding the most
6
+ common package and browser mistakes.
7
+
8
+ For individual option fields, read `options-reference.md`. For complete copy-ready
9
+ files, read `integration-recipes.md`.
10
+
11
+ ## Fast decision tree
12
+
13
+ Use this decision order:
14
+
15
+ 1. **React application?**
16
+ - Import the component from `gaugeit.js/react`.
17
+ - Import `gaugeit.js/css` once.
18
+ - Keep frequently recreated option objects stable with `useMemo`.
19
+ - Use a ref when imperative instance methods are needed.
20
+
21
+ 2. **Bundler or native ESM application?**
22
+ - Import from `gaugeit.js`.
23
+ - Import `gaugeit.js/css`.
24
+ - In a browser without a package resolver, import `dist/gaugeit.esm.js` by URL and
25
+ include `dist/gaugeit.css`.
26
+
27
+ 3. **CommonJS application?**
28
+ - `require('gaugeit.js')`.
29
+ - Ensure the application also loads or bundles the CSS.
30
+
31
+ 4. **Plain HTML with two cacheable files?**
32
+ - Include `gaugeit.min.css`.
33
+ - Include `gaugeit.umd.min.js`.
34
+ - Use the global `Gaugeit`.
35
+
36
+ 5. **Plain HTML that must use one JavaScript file?**
37
+ - Include `gaugeit.standalone.min.js`.
38
+ - Do not add separate Gaugeit CSS unless intentionally overriding it.
39
+ - Use the global `Gaugeit`.
40
+
41
+ 6. **PHP or Composer-managed server-rendered application?**
42
+ - Install `kasperi/gaugeit-js`.
43
+ - Run `vendor/bin/gaugeit-install-assets`.
44
+ - Include the copied CSS and UMD bundle from a public path.
45
+ - Render normal host elements and initialize in browser JavaScript.
46
+
47
+ 7. **Declarative custom element?**
48
+ - Load a normal Gaugeit distribution.
49
+ - Call `Gaugeit.defineGaugeitElement()` or import
50
+ `defineGaugeitElement` from `gaugeit.js/web-component`.
51
+ - Use `<gauge-it>` attributes.
52
+
53
+ 8. **Declarative data attributes?**
54
+ - Add `data-gaugeit`.
55
+ - Load a normal Gaugeit distribution.
56
+ - Call `Gaugeit.autoMount()` after the elements exist.
57
+
58
+ ## Package and distribution matrix
59
+
60
+ | Environment | JavaScript | CSS | API name |
61
+ | --- | --- | --- | --- |
62
+ | npm ESM | `gaugeit.js` | `gaugeit.js/css` | named exports or default `Gaugeit` |
63
+ | npm CommonJS | `require('gaugeit.js')` | load separately | returned exports |
64
+ | npm React | `gaugeit.js/react` | `gaugeit.js/css` | component `Gaugeit` |
65
+ | npm custom element | `gaugeit.js/web-component` | `gaugeit.js/css` | `defineGaugeitElement` |
66
+ | Browser UMD | `dist/gaugeit.umd.min.js` | `dist/gaugeit.min.css` | `window.Gaugeit` |
67
+ | Browser standalone | `dist/gaugeit.standalone.min.js` | embedded | `window.Gaugeit` |
68
+ | Browser ESM | `dist/gaugeit.esm.js` | `dist/gaugeit.css` | module exports |
69
+ | Composer | copied UMD and CSS | copied CSS | `window.Gaugeit` |
70
+
71
+ The UMD build does **not** inject CSS. The standalone build injects canonical CSS once
72
+ using the stable `#gaugeit-styles` marker.
73
+
74
+ ## Installation
75
+
76
+ ### npm
77
+
78
+ ```bash
79
+ npm install gaugeit.js@0.1.1
80
+ ```
81
+
82
+ Recommended ESM usage:
83
+
84
+ ```js
85
+ import { createGauge } from 'gaugeit.js';
86
+ import 'gaugeit.js/css';
87
+
88
+ const gauge = createGauge('#speed', {
89
+ type: 'arc',
90
+ min: 0,
91
+ max: 240,
92
+ value: 88
93
+ });
94
+ ```
95
+
96
+ Default-object usage:
97
+
98
+ ```js
99
+ import Gaugeit from 'gaugeit.js';
100
+ import 'gaugeit.js/css';
101
+
102
+ const gauge = Gaugeit.createGauge('#speed', {
103
+ type: 'classic',
104
+ value: 42
105
+ });
106
+ ```
107
+
108
+ ### CommonJS
109
+
110
+ ```js
111
+ const { createGauge } = require('gaugeit.js');
112
+
113
+ const gauge = createGauge(document.querySelector('#speed'), {
114
+ type: 'line-scale',
115
+ value: 42
116
+ });
117
+ ```
118
+
119
+ CommonJS resolves the JavaScript entry. CSS still belongs to the consuming application's
120
+ asset pipeline or page.
121
+
122
+ ### Native browser ESM
123
+
124
+ ```html
125
+ <link rel="stylesheet" href="./dist/gaugeit.css">
126
+ <div id="temperature"></div>
127
+
128
+ <script type="module">
129
+ import { createGauge } from './dist/gaugeit.esm.js';
130
+
131
+ createGauge('#temperature', {
132
+ type: 'classic',
133
+ min: -20,
134
+ max: 120,
135
+ value: 68
136
+ });
137
+ </script>
138
+ ```
139
+
140
+ A native browser cannot resolve the bare package specifier `gaugeit.js` unless an
141
+ import map, bundler, or server-side package resolver is present.
142
+
143
+ ### UMD with separate CSS
144
+
145
+ ```html
146
+ <link rel="stylesheet" href="./dist/gaugeit.min.css">
147
+
148
+ <div id="score"></div>
149
+
150
+ <script src="./dist/gaugeit.umd.min.js"></script>
151
+ <script>
152
+ const gauge = Gaugeit.createGauge('#score', {
153
+ type: 'arc',
154
+ min: 0,
155
+ max: 100,
156
+ value: 64
157
+ });
158
+ </script>
159
+ ```
160
+
161
+ The global name is exactly `Gaugeit`. It is not `GaugeIt`, `GaugeIT`, or `gaugeit`.
162
+
163
+ ### Standalone one-file browser build
164
+
165
+ ```html
166
+ <div id="score"></div>
167
+
168
+ <script src="./dist/gaugeit.standalone.min.js"></script>
169
+ <script>
170
+ Gaugeit.createGauge('#score', {
171
+ type: 'classic',
172
+ value: 64
173
+ });
174
+ </script>
175
+ ```
176
+
177
+ Standalone is appropriate when one JavaScript file is more important than separately
178
+ cacheable CSS. It contains the same public API as UMD.
179
+
180
+ ### jsDelivr
181
+
182
+ Use exact versions in production:
183
+
184
+ ```html
185
+ <link
186
+ rel="stylesheet"
187
+ href="https://cdn.jsdelivr.net/npm/gaugeit.js@0.1.1/dist/gaugeit.min.css"
188
+ >
189
+ <script
190
+ src="https://cdn.jsdelivr.net/npm/gaugeit.js@0.1.1/dist/gaugeit.umd.min.js"
191
+ ></script>
192
+ ```
193
+
194
+ One-file form:
195
+
196
+ ```html
197
+ <script
198
+ src="https://cdn.jsdelivr.net/npm/gaugeit.js@0.1.1/dist/gaugeit.standalone.min.js"
199
+ ></script>
200
+ ```
201
+
202
+ ### UNPKG
203
+
204
+ ```html
205
+ <link
206
+ rel="stylesheet"
207
+ href="https://unpkg.com/gaugeit.js@0.1.1/dist/gaugeit.min.css"
208
+ >
209
+ <script
210
+ src="https://unpkg.com/gaugeit.js@0.1.1/dist/gaugeit.umd.min.js"
211
+ ></script>
212
+ ```
213
+
214
+ One-file form:
215
+
216
+ ```html
217
+ <script
218
+ src="https://unpkg.com/gaugeit.js@0.1.1/dist/gaugeit.standalone.min.js"
219
+ ></script>
220
+ ```
221
+
222
+ Do not omit the version in production examples. An unpinned CDN URL may change after a
223
+ new release.
224
+
225
+ ### Composer
226
+
227
+ ```bash
228
+ composer require kasperi/gaugeit-js:^0.1
229
+ vendor/bin/gaugeit-install-assets public/assets/vendor/gaugeit
230
+ ```
231
+
232
+ Default installed assets:
233
+
234
+ ```text
235
+ gaugeit.umd.min.js
236
+ gaugeit.min.css
237
+ ```
238
+
239
+ Other modes:
240
+
241
+ ```bash
242
+ vendor/bin/gaugeit-install-assets --standalone public/assets/vendor/gaugeit
243
+ vendor/bin/gaugeit-install-assets --all public/assets/vendor/gaugeit
244
+ vendor/bin/gaugeit-install-assets --clean public/assets/vendor/gaugeit
245
+ ```
246
+
247
+ `--clean` removes only known Gaugeit.js assets from the destination. It preserves
248
+ unrelated files. Composer consumers use prebuilt assets and do not need Node.js.
249
+
250
+ Gaugeit.js does not write into an application's public directory automatically during
251
+ dependency installation. The consuming project owns the explicit asset-copy command.
252
+
253
+ ## Built-in types
254
+
255
+ Use one of these exact names:
256
+
257
+ | Type | Geometry family | Intended use |
258
+ | --- | --- | --- |
259
+ | `arc` | radial | lightweight semicircular zones and pointer |
260
+ | `classic` | radial | framed vintage analog instrument |
261
+ | `heritage-round` | radial | circular glass-fronted 270-degree instrument |
262
+ | `line-scale` | radial | dense configurable tick-focused scale |
263
+ | `classic-linear` | linear | framed straight scale with moving indicator |
264
+ | `classic-linear-zero` | linear | signed straight scale with fixed zero marker |
265
+ | `center-zero` | radial | signed heritage dial around a center reference |
266
+ | `rolling-tape` | tape | moving numeric strip behind a fixed reference line |
267
+
268
+ Do not infer geometry solely from the visual name. The selected type supplies the
269
+ correct geometry mode and layer family.
270
+
271
+ ## Minimal creation
272
+
273
+ The target may be an element or a CSS selector:
274
+
275
+ ```js
276
+ const gauge = Gaugeit.createGauge('#gauge', {
277
+ type: 'arc',
278
+ value: 72
279
+ });
280
+ ```
281
+
282
+ Equivalent element form:
283
+
284
+ ```js
285
+ const host = document.querySelector('#gauge');
286
+ const gauge = Gaugeit.createGauge(host, {
287
+ type: 'arc',
288
+ value: 72
289
+ });
290
+ ```
291
+
292
+ The target must exist before creation. Creating another managed gauge on the same host
293
+ destroys the previous managed instance.
294
+
295
+ ## A practical configuration pattern
296
+
297
+ ```js
298
+ const gauge = Gaugeit.createGauge('#engine-load', {
299
+ type: 'arc',
300
+ min: 0,
301
+ max: 100,
302
+ value: 38,
303
+ zones: [
304
+ { min: 0, max: 60, color: '#22c55e' },
305
+ { min: 60, max: 85, color: '#facc15' },
306
+ { min: 85, max: 100, color: '#ef4444' }
307
+ ],
308
+ readout: {
309
+ title: {
310
+ visible: true,
311
+ text: 'ENGINE LOAD'
312
+ },
313
+ value: {
314
+ visible: true,
315
+ suffix: '%'
316
+ }
317
+ },
318
+ accessibility: {
319
+ label: 'Engine load',
320
+ valueText: (value) => `${Math.round(value)} percent`
321
+ }
322
+ });
323
+ ```
324
+
325
+ Prefer normal option objects over DOM manipulation of generated SVG.
326
+
327
+ ## Updating values
328
+
329
+ Use `setValue()` for ordinary numeric updates:
330
+
331
+ ```js
332
+ gauge.setValue(76);
333
+ gauge.setValue(18, {
334
+ duration: 1400,
335
+ easing: 'easeInOutCubic'
336
+ });
337
+ gauge.setValue(50, {
338
+ animate: false
339
+ });
340
+ ```
341
+
342
+ `set()` is an alias:
343
+
344
+ ```js
345
+ gauge.set(64);
346
+ ```
347
+
348
+ Do not call `updateOptions({ value })` for a high-frequency value stream unless the
349
+ configuration must also be rebuilt. `setValue()` updates dynamic controllers without
350
+ re-rendering static layers.
351
+
352
+ ## Updating options
353
+
354
+ Deep-merge a partial patch:
355
+
356
+ ```js
357
+ gauge.updateOptions({
358
+ pointer: {
359
+ type: 'line',
360
+ color: '#dc2626'
361
+ },
362
+ labels: {
363
+ fractionDigits: 1
364
+ }
365
+ });
366
+ ```
367
+
368
+ `setOptions()` is an alias for `updateOptions()`.
369
+
370
+ Replace all earlier instance overrides:
371
+
372
+ ```js
373
+ gauge.replaceOptions({
374
+ type: 'classic',
375
+ min: 0,
376
+ max: 100,
377
+ value: 42
378
+ });
379
+ ```
380
+
381
+ Arrays are replaced, not concatenated. Therefore:
382
+
383
+ ```js
384
+ gauge.updateOptions({
385
+ zones: [
386
+ { min: 0, max: 100, color: '#22c55e' }
387
+ ]
388
+ });
389
+ ```
390
+
391
+ replaces the previous complete zone list.
392
+
393
+ When `updateOptions()` or `replaceOptions()` includes `value`, the value is applied
394
+ immediately by default. Pass `{ animateToValue: true }` as the second argument to
395
+ animate after the rebuild:
396
+
397
+ ```js
398
+ gauge.updateOptions(
399
+ {
400
+ value: 90,
401
+ pointer: { color: '#dc2626' }
402
+ },
403
+ {
404
+ animateToValue: true
405
+ }
406
+ );
407
+ ```
408
+
409
+ ## Reading values
410
+
411
+ ```js
412
+ const requested = gauge.getValue();
413
+ const displayed = gauge.getDisplayedValue();
414
+ ```
415
+
416
+ - `getValue()` returns the stable requested target.
417
+ - `getDisplayedValue()` returns the current animated base value.
418
+ - Neither method returns the jittered pointer-only visual value.
419
+
420
+ ## Lifecycle
421
+
422
+ ```js
423
+ gauge.pause();
424
+ gauge.resume();
425
+ gauge.refresh();
426
+ gauge.destroy();
427
+ ```
428
+
429
+ - `pause()` stops active animation and jitter work.
430
+ - `resume()` continues pending visual work without counting paused time.
431
+ - `refresh()` rebuilds the gauge from current options. Use it after relevant fonts,
432
+ CSS variables, or external plugin state changes.
433
+ - `destroy()` releases animation frames, observers, listeners, controller resources,
434
+ and generated content.
435
+
436
+ Do not call instance methods after `destroy()`.
437
+
438
+ ## Overflow behavior
439
+
440
+ ```js
441
+ overflow: 'clamp'
442
+ ```
443
+
444
+ - `clamp`: incoming values are constrained to `min ... max`.
445
+ - `expand`: an incoming out-of-range value expands the configured range and re-renders.
446
+ - `allow`: stores and renders out-of-range values without changing the configured
447
+ range; display clamping is disabled.
448
+
449
+ Use `clamp` unless the application explicitly needs one of the other contracts.
450
+
451
+ ## Inversion
452
+
453
+ ```js
454
+ invert: true
455
+ ```
456
+
457
+ Inversion reverses visual direction without changing the numeric definitions. Zones
458
+ remain attached to their numeric values. Do not reverse zone arrays or swap their
459
+ numeric endpoints to implement inversion.
460
+
461
+ ## Responsive layout
462
+
463
+ Default layout is intrinsic and responsive:
464
+
465
+ ```js
466
+ layout: {
467
+ mode: 'intrinsic',
468
+ padding: 8,
469
+ includeGeometry: true
470
+ },
471
+ responsive: true
472
+ ```
473
+
474
+ The host should have an available width. Gaugeit.js applies responsive SVG sizing and
475
+ calculates a content-aware viewBox.
476
+
477
+ For a fixed-size card area, constrain the host with CSS and use contain mode:
478
+
479
+ ```css
480
+ .dashboard-gauge {
481
+ width: 320px;
482
+ height: 220px;
483
+ }
484
+ ```
485
+
486
+ ```js
487
+ Gaugeit.createGauge('.dashboard-gauge', {
488
+ type: 'heritage-round',
489
+ layout: {
490
+ mode: 'contain'
491
+ }
492
+ });
493
+ ```
494
+
495
+ Do not set only a zero or collapsed parent size and expect SVG to invent page layout.
496
+
497
+ ## Readouts
498
+
499
+ The readout group is enabled by default, but individual parts are not all visible:
500
+
501
+ ```js
502
+ readout: {
503
+ visible: true,
504
+ title: {
505
+ visible: true,
506
+ text: 'PRESSURE'
507
+ },
508
+ value: {
509
+ visible: true,
510
+ fractionDigits: 1
511
+ },
512
+ unit: {
513
+ visible: true,
514
+ text: 'bar'
515
+ }
516
+ }
517
+ ```
518
+
519
+ `readout.visible: true` alone does not enable `title`, `value`, or `unit`.
520
+
521
+ ## Lights
522
+
523
+ Every built-in type includes the shared light layer. A partial object inherits shared
524
+ defaults:
525
+
526
+ ```js
527
+ light: {
528
+ visible: true
529
+ }
530
+ ```
531
+
532
+ A threshold light:
533
+
534
+ ```js
535
+ light: {
536
+ visible: true,
537
+ color: 'red',
538
+ trigger: {
539
+ mode: 'above',
540
+ source: 'target',
541
+ value: 85
542
+ }
543
+ }
544
+ ```
545
+
546
+ Trigger sources:
547
+
548
+ - `target`: stable requested value; default and usually best for warnings;
549
+ - `displayed`: current animated base value;
550
+ - `pointer`: animated value plus visual jitter.
551
+
552
+ Effect interaction:
553
+
554
+ - blink takes precedence over pulse;
555
+ - flicker may overlay blink or pulse;
556
+ - pulse and flicker run only while the light is active;
557
+ - reduced-motion preference suppresses the motion effects;
558
+ - `glowRadius` is independent from lamp `radius` in 0.1.1;
559
+ - `glowOpacity` is independent from illuminated-lens `opacity`.
560
+
561
+ For a deterministic steady light, disable all motion:
562
+
563
+ ```js
564
+ light: {
565
+ visible: true,
566
+ glow: true,
567
+ pulse: false,
568
+ blink: false,
569
+ flicker: false,
570
+ trigger: {
571
+ mode: 'manual'
572
+ },
573
+ on: true
574
+ }
575
+ ```
576
+
577
+ ## Data-attribute mounting
578
+
579
+ ```html
580
+ <div
581
+ data-gaugeit
582
+ data-gaugeit-type="arc"
583
+ data-gaugeit-min="0"
584
+ data-gaugeit-max="100"
585
+ data-gaugeit-value="63"
586
+ data-gaugeit-options='{"animation":{"startFrom":"value"}}'
587
+ ></div>
588
+
589
+ <script src="./dist/gaugeit.umd.min.js"></script>
590
+ <script>
591
+ Gaugeit.autoMount();
592
+ </script>
593
+ ```
594
+
595
+ Supported dataset fields are translated into normal options. The JSON in
596
+ `data-gaugeit-options` must be valid JSON, not JavaScript object syntax. Auto-mounting
597
+ is duplicate-safe.
598
+
599
+ A custom selector and root are supported:
600
+
601
+ ```js
602
+ Gaugeit.autoMount('[data-dashboard-gauge]', document.querySelector('#dashboard'));
603
+ ```
604
+
605
+ Managed-instance helpers:
606
+
607
+ ```js
608
+ const host = document.querySelector('#gauge');
609
+ const instance = Gaugeit.getMountedGauge(host);
610
+ const existed = Gaugeit.unmountGauge(host);
611
+ ```
612
+
613
+ ## Custom element
614
+
615
+ ```html
616
+ <script src="./dist/gaugeit.umd.min.js"></script>
617
+ <script>
618
+ Gaugeit.defineGaugeitElement();
619
+ </script>
620
+
621
+ <gauge-it
622
+ type="classic"
623
+ min="0"
624
+ max="240"
625
+ value="88"
626
+ options='{"readout":{"title":{"visible":true,"text":"VOLTAGE"}}}'
627
+ ></gauge-it>
628
+ ```
629
+
630
+ Observed attributes are `value`, `min`, `max`, `type`, and `options`. Attribute changes
631
+ replace the complete declarative option object. The element destroys its instance when
632
+ disconnected.
633
+
634
+ With npm:
635
+
636
+ ```js
637
+ import { defineGaugeitElement } from 'gaugeit.js/web-component';
638
+ import 'gaugeit.js/css';
639
+
640
+ defineGaugeitElement();
641
+ ```
642
+
643
+ ## React
644
+
645
+ ```jsx
646
+ import { useMemo, useState } from 'react';
647
+ import Gaugeit from 'gaugeit.js/react';
648
+ import 'gaugeit.js/css';
649
+
650
+ export default function LoadGauge() {
651
+ const [value, setValue] = useState(62);
652
+
653
+ const options = useMemo(() => ({
654
+ type: 'arc',
655
+ min: 0,
656
+ max: 100,
657
+ zones: [
658
+ { min: 0, max: 60, color: '#22c55e' },
659
+ { min: 60, max: 85, color: '#facc15' },
660
+ { min: 85, max: 100, color: '#ef4444' }
661
+ ]
662
+ }), []);
663
+
664
+ return (
665
+ <Gaugeit
666
+ value={value}
667
+ options={options}
668
+ className="load-gauge"
669
+ />
670
+ );
671
+ }
672
+ ```
673
+
674
+ React owns the host element. Gaugeit.js owns only the generated content inside it. The
675
+ adapter:
676
+
677
+ - creates an instance on mount;
678
+ - replaces the complete options object when `options` identity changes;
679
+ - keeps explicit `value` authoritative;
680
+ - forwards a ref to the live `Gauge` instance;
681
+ - destroys the instance on unmount.
682
+
683
+ Do not import the source adapter by repository-relative path from an installed package.
684
+ Use `gaugeit.js/react`.
685
+
686
+ ## Laravel Blade
687
+
688
+ After Composer asset installation, a Blade page may include:
689
+
690
+ ```blade
691
+ @push('styles')
692
+ <link
693
+ rel="stylesheet"
694
+ href="{{ asset('assets/vendor/gaugeit/gaugeit.min.css') }}"
695
+ >
696
+ @endpush
697
+
698
+ <div
699
+ id="pressure-gauge"
700
+ data-gauge-options='@json([
701
+ "type" => "classic",
702
+ "min" => 0,
703
+ "max" => 10,
704
+ "value" => $pressure,
705
+ ])'
706
+ ></div>
707
+
708
+ @push('scripts')
709
+ <script src="{{ asset('assets/vendor/gaugeit/gaugeit.umd.min.js') }}"></script>
710
+ <script>
711
+ document.addEventListener('DOMContentLoaded', () => {
712
+ const host = document.querySelector('#pressure-gauge');
713
+ const options = JSON.parse(host.dataset.gaugeOptions);
714
+ Gaugeit.createGauge(host, options);
715
+ });
716
+ </script>
717
+ @endpush
718
+ ```
719
+
720
+ The PHP layer emits data. Browser JavaScript creates the SVG gauge.
721
+
722
+ ## Twig
723
+
724
+ ```twig
725
+ <link
726
+ rel="stylesheet"
727
+ href="{{ asset('assets/vendor/gaugeit/gaugeit.min.css') }}"
728
+ >
729
+
730
+ <div
731
+ id="temperature-gauge"
732
+ data-options="{{ {
733
+ type: 'classic',
734
+ min: -20,
735
+ max: 120,
736
+ value: temperature
737
+ }|json_encode|e('html_attr') }}"
738
+ ></div>
739
+
740
+ <script src="{{ asset('assets/vendor/gaugeit/gaugeit.umd.min.js') }}"></script>
741
+ <script>
742
+ const host = document.querySelector('#temperature-gauge');
743
+ Gaugeit.createGauge(host, JSON.parse(host.dataset.options));
744
+ </script>
745
+ ```
746
+
747
+ Escape JSON for an HTML attribute. Do not place unescaped application data directly
748
+ inside executable JavaScript.
749
+
750
+ ## Plain PHP
751
+
752
+ ```php
753
+ <?php
754
+ $options = [
755
+ 'type' => 'arc',
756
+ 'min' => 0,
757
+ 'max' => 100,
758
+ 'value' => $value,
759
+ ];
760
+ ?>
761
+
762
+ <link rel="stylesheet" href="/assets/vendor/gaugeit/gaugeit.min.css">
763
+
764
+ <div
765
+ id="status-gauge"
766
+ data-options="<?= htmlspecialchars(
767
+ json_encode($options, JSON_THROW_ON_ERROR),
768
+ ENT_QUOTES,
769
+ 'UTF-8'
770
+ ) ?>"
771
+ ></div>
772
+
773
+ <script src="/assets/vendor/gaugeit/gaugeit.umd.min.js"></script>
774
+ <script>
775
+ const host = document.querySelector('#status-gauge');
776
+ Gaugeit.createGauge(host, JSON.parse(host.dataset.options));
777
+ </script>
778
+ ```
779
+
780
+ ## DOM events
781
+
782
+ Events are dispatched from the host element:
783
+
784
+ ```js
785
+ const host = document.querySelector('#gauge');
786
+
787
+ host.addEventListener('gaugeit:change', (event) => {
788
+ console.log(event.detail.value);
789
+ });
790
+
791
+ host.addEventListener('gaugeit:settled', (event) => {
792
+ console.log(event.detail.displayedValue);
793
+ });
794
+ ```
795
+
796
+ Available event names:
797
+
798
+ ```text
799
+ gaugeit:render
800
+ gaugeit:change
801
+ gaugeit:displaychange
802
+ gaugeit:animationstart
803
+ gaugeit:animationend
804
+ gaugeit:settled
805
+ gaugeit:typechange
806
+ gaugeit:pause
807
+ gaugeit:resume
808
+ gaugeit:destroy
809
+ ```
810
+
811
+ Use namespaced events instead of global callbacks.
812
+
813
+ ## Custom types
814
+
815
+ Register a type before creating instances that use it:
816
+
817
+ ```js
818
+ Gaugeit.registerGaugeType('compact-status', {
819
+ description: 'Compact dashboard status gauge.',
820
+ defaults: {
821
+ geometry: {
822
+ width: 260,
823
+ height: 150,
824
+ centerX: 130,
825
+ centerY: 132,
826
+ startAngle: 200,
827
+ endAngle: 340
828
+ },
829
+ pointer: {
830
+ type: 'arrow',
831
+ length: 75,
832
+ width: 6
833
+ }
834
+ },
835
+ layers: [
836
+ Gaugeit.layers.face,
837
+ Gaugeit.layers.zones,
838
+ Gaugeit.layers.ticks,
839
+ Gaugeit.layers.labels,
840
+ Gaugeit.layers.light,
841
+ Gaugeit.layers.readout,
842
+ Gaugeit.layers.pointer
843
+ ]
844
+ });
845
+ ```
846
+
847
+ Layer order is paint order. In the example, the pointer is last so it paints above the
848
+ readout.
849
+
850
+ ## Accessibility
851
+
852
+ Always provide a meaningful label for production gauges:
853
+
854
+ ```js
855
+ accessibility: {
856
+ label: 'Battery charge',
857
+ description: 'Remaining charge in the main battery.',
858
+ valueText: (value) => `${Math.round(value)} percent`
859
+ }
860
+ ```
861
+
862
+ The generated root uses `role="meter"` and updates `aria-valuemin`,
863
+ `aria-valuemax`, `aria-valuenow`, and optional `aria-valuetext`.
864
+
865
+ A visually decorative gauge still needs an intentional accessibility decision. Do not
866
+ silently remove meter semantics from the library.
867
+
868
+ ## Browser support assumptions
869
+
870
+ Gaugeit.js uses modern browser APIs and targets ES2018-compatible runtime behavior.
871
+ When generating code for an older environment, do not mutate Gaugeit.js source
872
+ arbitrarily. Add an application-level transpilation or compatibility plan.
873
+
874
+ The optional `test:chromium` development command expects a globally available
875
+ `chromium` executable. That requirement does not apply to normal library consumers.