awesome-speedometer-gauge 0.1.0

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 ADDED
@@ -0,0 +1,368 @@
1
+ # awesome-speedometer-gauge
2
+
3
+ A fully-featured **React KPI speedometer gauge** component. Five visual modes, animated needle/arc, threshold colour bands, dark/light/purple themes, optional live data fetching, tooltip, target marker, and a real-time flash effect — all in a single self-contained card widget.
4
+
5
+ ---
6
+
7
+ ## Features
8
+
9
+ - **5 gauge modes** — `standard` (half-dial with needle), `semicircle` (wide arc), `full` (360° dial), `arc` (270° gradient arc), `multiband` (coloured bands with dot marker)
10
+ - **Animated transitions** — smooth eased needle/arc animation on value changes via `requestAnimationFrame`
11
+ - **Real-time mode** — fast 220ms transitions + a flash effect when the value crosses a threshold band
12
+ - **Threshold colour bands** — supply any number of `{ value, color }` breakpoints; defaults to poor/warning/good traffic-light colours
13
+ - **Target marker** — optional secondary marker at a target value with its own colour
14
+ - **Three built-in themes** — `light`, `dark`, `purple`; all colours driven by CSS custom properties so you can override anything
15
+ - **Tooltip** — hover to reveal value, target, min, and max in a clean floating chip
16
+ - **Live data fetching** — pass an `apiEndpoint` URL and the component fetches, normalises, and merges JSON automatically
17
+ - **`data` prop shortcut** — pass a plain object or array directly to skip the fetch
18
+ - **CSS Module styles** — scoped styles with no global pollution; `style.css` is the only thing you need to import
19
+ - **ESM + CJS dual build** — works in Vite, Next.js, CRA, and any modern bundler
20
+ - **Zero runtime dependencies** beyond React
21
+
22
+ ---
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install awesome-speedometer-gauge
28
+ # or
29
+ yarn add awesome-speedometer-gauge
30
+ # or
31
+ pnpm add awesome-speedometer-gauge
32
+ ```
33
+
34
+ > **Peer dependencies** — React ≥ 18 and ReactDOM ≥ 18 must already be installed.
35
+
36
+ ---
37
+
38
+ ## Importing Styles
39
+
40
+ Import the stylesheet **once** at your app root:
41
+
42
+ ```js
43
+ import 'awesome-speedometer-gauge/style.css';
44
+ ```
45
+
46
+ For the full typographic effect, load this Google Font in your `index.html` `<head>`:
47
+
48
+ ```html
49
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
50
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
51
+ <link
52
+ href="https://fonts.googleapis.com/css2?family=Source+Sans+3:wght@400;500;600;700&display=swap"
53
+ rel="stylesheet"
54
+ />
55
+ ```
56
+
57
+ > Falls back to `"Segoe UI"` / `system-ui` without the font.
58
+
59
+ ---
60
+
61
+ ## Quick Start
62
+
63
+ ```jsx
64
+ import { AwesomeSpeedometerGauge } from 'awesome-speedometer-gauge';
65
+ import 'awesome-speedometer-gauge/style.css';
66
+
67
+ export default function App() {
68
+ return (
69
+ <AwesomeSpeedometerGauge
70
+ title="Server CPU"
71
+ value={72}
72
+ min={0}
73
+ max={100}
74
+ units="%"
75
+ />
76
+ );
77
+ }
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Props
83
+
84
+ | Prop | Type | Default | Description |
85
+ |---|---|---|---|
86
+ | `type` | `'standard' \| 'semicircle' \| 'full' \| 'arc' \| 'multiband'` | `'standard'` | Visual mode of the gauge. |
87
+ | `value` | `number` | — | Current value. Clamped to `[min, max]`. Can also come from `data` or `apiEndpoint`. |
88
+ | `min` | `number` | `0` | Minimum scale value. |
89
+ | `max` | `number` | `100` | Maximum scale value. |
90
+ | `target` | `number` | — | Optional target/goal value. Shown as a separate marker when `showTarget` is true. |
91
+ | `thresholds` | `Threshold[]` | auto | Array of `{ value, color, label? }` breakpoints sorted ascending. Defaults to 60/80/100 traffic-light bands. |
92
+ | `showTicks` | `boolean` | `true` | Show tick marks on the gauge arc. |
93
+ | `showValue` | `boolean` | `true` | Show the current value label inside the gauge SVG. |
94
+ | `showTarget` | `boolean` | `false` | Show the target marker and include target in the value label. |
95
+ | `animated` | `boolean` | `true` | Animate value changes with a 500ms eased transition. |
96
+ | `realtime` | `boolean` | `false` | Use a faster 220ms transition and flash the card when the threshold band changes. |
97
+ | `size` | `number` | `220` | SVG canvas size in px (width and height). |
98
+ | `thickness` | `number` | `18` | Arc stroke thickness in px. |
99
+ | `startAngle` | `number` | mode default | Arc start angle in degrees. Each mode has a sensible default. |
100
+ | `endAngle` | `number` | mode default | Arc end angle in degrees. |
101
+ | `units` | `string` | `''` | Unit label appended to the value (e.g. `'%'`, `'rpm'`, `'°C'`). |
102
+ | `title` | `string` | `'KPI Gauge'` | Card heading. |
103
+ | `subtitle` | `string` | `''` | Optional secondary line below the title. |
104
+ | `theme` | `'light' \| 'dark' \| 'purple'` | `'light'` | Built-in colour theme. |
105
+ | `data` | `object \| array` | — | Inline data object (or array whose first element is used). Merged with and overridden by direct props. |
106
+ | `apiEndpoint` | `string` | `'/gauge-data.json'` | URL to fetch gauge data from. Only used when `data` is not provided. |
107
+ | `className` | `string` | — | Additional CSS class on the root card element. |
108
+ | `style` | `object` | — | Inline styles on the root card element. |
109
+ | `onClick` | `(value: number) => void` | — | Called with the current value when the card is clicked. |
110
+
111
+ ### `Threshold` object
112
+
113
+ ```js
114
+ { value: 60, color: '#ef4444' }, // 0–60 → red
115
+ { value: 80, color: '#f59e0b' }, // 60–80 → amber
116
+ { value: 100, color: '#22c55e' }, // 80–100 → green
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Examples
122
+
123
+ ### Example 1 — All five modes side by side
124
+
125
+ ```jsx
126
+ import { AwesomeSpeedometerGauge } from 'awesome-speedometer-gauge';
127
+ import 'awesome-speedometer-gauge/style.css';
128
+
129
+ var thresholds = [
130
+ { value: 40, color: '#ef4444' },
131
+ { value: 70, color: '#f59e0b' },
132
+ { value: 100, color: '#22c55e' },
133
+ ];
134
+
135
+ var modes = ['standard', 'semicircle', 'full', 'arc', 'multiband'];
136
+
137
+ export default function AllModesDemo() {
138
+ return (
139
+ <div style={{ display: 'flex', flexWrap: 'wrap', gap: 24, padding: 32, background: '#f1f5f9' }}>
140
+ {modes.map(function(mode) {
141
+ return (
142
+ <AwesomeSpeedometerGauge
143
+ key={mode}
144
+ type={mode}
145
+ title={mode.charAt(0).toUpperCase() + mode.slice(1)}
146
+ subtitle="CPU Usage"
147
+ value={63}
148
+ min={0}
149
+ max={100}
150
+ units="%"
151
+ thresholds={thresholds}
152
+ size={200}
153
+ />
154
+ );
155
+ })}
156
+ </div>
157
+ );
158
+ }
159
+ ```
160
+
161
+ ---
162
+
163
+ ### Example 2 — Dark theme, real-time updates, target marker
164
+
165
+ Simulates a live-updating gauge that flashes when the value crosses a threshold band.
166
+
167
+ ```jsx
168
+ import { useState, useEffect } from 'react';
169
+ import { AwesomeSpeedometerGauge } from 'awesome-speedometer-gauge';
170
+ import 'awesome-speedometer-gauge/style.css';
171
+
172
+ var thresholds = [
173
+ { value: 50, color: '#22c55e' },
174
+ { value: 80, color: '#f59e0b' },
175
+ { value: 100, color: '#ef4444' },
176
+ ];
177
+
178
+ export default function RealtimeDemo() {
179
+ var [rpm, setRpm] = useState(3200);
180
+
181
+ useEffect(function() {
182
+ var id = setInterval(function() {
183
+ setRpm(function(prev) {
184
+ var delta = (Math.random() - 0.48) * 400;
185
+ return Math.round(Math.max(0, Math.min(8000, prev + delta)));
186
+ });
187
+ }, 1200);
188
+ return function() { clearInterval(id); };
189
+ }, []);
190
+
191
+ return (
192
+ <div style={{ padding: 40, background: '#0b1220', minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
193
+ <AwesomeSpeedometerGauge
194
+ type="standard"
195
+ theme="dark"
196
+ title="Engine RPM"
197
+ subtitle="Live telemetry"
198
+ value={rpm}
199
+ min={0}
200
+ max={8000}
201
+ units="rpm"
202
+ target={4500}
203
+ showTarget={true}
204
+ thresholds={thresholds}
205
+ realtime={true}
206
+ size={240}
207
+ thickness={20}
208
+ />
209
+ </div>
210
+ );
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ### Example 3 — Dashboard grid with `onClick`, custom thresholds, and mixed themes
217
+
218
+ ```jsx
219
+ import { useState } from 'react';
220
+ import { AwesomeSpeedometerGauge } from 'awesome-speedometer-gauge';
221
+ import 'awesome-speedometer-gauge/style.css';
222
+
223
+ var kpis = [
224
+ {
225
+ type: 'arc', theme: 'light', title: 'Conversion Rate', subtitle: 'Last 30 days',
226
+ value: 4.7, min: 0, max: 10, units: '%', target: 5, showTarget: true,
227
+ thresholds: [{ value: 3, color: '#ef4444' }, { value: 6, color: '#f59e0b' }, { value: 10, color: '#22c55e' }],
228
+ },
229
+ {
230
+ type: 'multiband', theme: 'dark', title: 'Memory Usage', subtitle: 'App server',
231
+ value: 71, min: 0, max: 100, units: '%',
232
+ thresholds: [{ value: 50, color: '#22c55e' }, { value: 80, color: '#f59e0b' }, { value: 100, color: '#ef4444' }],
233
+ },
234
+ {
235
+ type: 'semicircle', theme: 'purple', title: 'NPS Score', subtitle: 'Q2 2025',
236
+ value: 58, min: -100, max: 100, target: 50, showTarget: true,
237
+ thresholds: [{ value: 0, color: '#ef4444' }, { value: 50, color: '#f59e0b' }, { value: 100, color: '#22c55e' }],
238
+ },
239
+ {
240
+ type: 'full', theme: 'dark', title: 'Disk I/O', subtitle: 'Primary volume',
241
+ value: 340, min: 0, max: 500, units: 'MB/s',
242
+ thresholds: [{ value: 200, color: '#22c55e' }, { value: 400, color: '#f59e0b' }, { value: 500, color: '#ef4444' }],
243
+ },
244
+ ];
245
+
246
+ var overlayStyle = {
247
+ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)',
248
+ display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 100,
249
+ };
250
+
251
+ var popupStyle = {
252
+ background: '#fff', borderRadius: 16, padding: '32px 40px',
253
+ fontFamily: 'sans-serif', minWidth: 260, textAlign: 'center',
254
+ boxShadow: '0 20px 60px rgba(0,0,0,0.25)',
255
+ };
256
+
257
+ export default function DashboardDemo() {
258
+ var [clicked, setClicked] = useState(null);
259
+
260
+ return (
261
+ <div style={{ padding: 32, background: '#f1f5f9', minHeight: '100vh' }}>
262
+ <h2 style={{ fontFamily: 'sans-serif', marginBottom: 24, color: '#0f172a' }}>KPI Dashboard</h2>
263
+
264
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 20 }}>
265
+ {kpis.map(function(kpi, i) {
266
+ return (
267
+ <AwesomeSpeedometerGauge
268
+ key={i}
269
+ type={kpi.type}
270
+ theme={kpi.theme}
271
+ title={kpi.title}
272
+ subtitle={kpi.subtitle}
273
+ value={kpi.value}
274
+ min={kpi.min}
275
+ max={kpi.max}
276
+ units={kpi.units}
277
+ target={kpi.target}
278
+ showTarget={kpi.showTarget}
279
+ thresholds={kpi.thresholds}
280
+ animated={true}
281
+ size={210}
282
+ onClick={function(val) { setClicked({ title: kpi.title, value: val, units: kpi.units || '' }); }}
283
+ />
284
+ );
285
+ })}
286
+ </div>
287
+
288
+ {clicked && (
289
+ <div style={overlayStyle} onClick={function() { setClicked(null); }}>
290
+ <div style={popupStyle} onClick={function(e) { e.stopPropagation(); }}>
291
+ <div style={{ fontSize: 13, color: '#64748b', letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 8 }}>
292
+ {clicked.title}
293
+ </div>
294
+ <div style={{ fontSize: 52, fontWeight: 700, color: '#0f172a' }}>
295
+ {clicked.value}{clicked.units}
296
+ </div>
297
+ <button
298
+ onClick={function() { setClicked(null); }}
299
+ style={{ marginTop: 20, padding: '8px 24px', borderRadius: 8, border: 'none', background: '#0f172a', color: '#fff', cursor: 'pointer', fontSize: 13 }}
300
+ >
301
+ Close
302
+ </button>
303
+ </div>
304
+ </div>
305
+ )}
306
+ </div>
307
+ );
308
+ }
309
+ ```
310
+
311
+ ---
312
+
313
+ > **Note:** `AwesomeSpeedometerGauge.module.css` is bundled directly into `dist/esm/index.js` and `dist/cjs/index.js` by Vite's CSS Modules pipeline. You do **not** need to import it separately — only `style.css` needs an explicit import in your app.
314
+
315
+ ## CSS Custom Properties
316
+
317
+ All colours in the gauge are driven by CSS variables set on the `.gaugeCard` root element. Override them per-instance with the `style` prop or globally in your own CSS:
318
+
319
+ ```css
320
+ .my-gauge {
321
+ --gauge-progress: #6366f1; /* filled arc colour */
322
+ --gauge-track: #e2e8f0; /* background arc */
323
+ --gauge-needle: #1e293b; /* needle / dot marker */
324
+ --gauge-target: #f59e0b; /* target marker */
325
+ --gauge-range-poor: #ef4444;
326
+ --gauge-range-warning: #f59e0b;
327
+ --gauge-range-good: #22c55e;
328
+ --gauge-text: #0f172a;
329
+ --gauge-text-muted: #64748b;
330
+ --gauge-tick: #cbd5e1;
331
+ --gauge-surface: #ffffff;
332
+ --gauge-bg: #f6f7f9;
333
+ }
334
+ ```
335
+
336
+ Pass the class via the `className` prop:
337
+
338
+ ```jsx
339
+ <AwesomeSpeedometerGauge className="my-gauge" value={55} />
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Live Data Fetching
345
+
346
+ When `data` is not provided, the component fetches from `apiEndpoint`. The endpoint should return JSON matching the prop shape:
347
+
348
+ ```json
349
+ {
350
+ "value": 73,
351
+ "min": 0,
352
+ "max": 100,
353
+ "target": 80,
354
+ "units": "%",
355
+ "type": "standard",
356
+ "thresholds": [
357
+ { "value": 50, "color": "#ef4444" },
358
+ { "value": 75, "color": "#f59e0b" },
359
+ { "value": 100, "color": "#22c55e" }
360
+ ]
361
+ }
362
+ ```
363
+
364
+ An array response is also accepted — the first element is used. Direct props always override fetched values.
365
+
366
+ ## 📄 License
367
+
368
+ MIT
@@ -0,0 +1 @@
1
+ ._gaugeCard_6w996_1{--gauge-bg: #f6f7f9;--gauge-surface: #ffffff;--gauge-text: #0f172a;--gauge-text-muted: #64748b;--gauge-tick: #cbd5f5;--gauge-track: #e2e8f0;--gauge-progress: #22c55e;--gauge-needle: #0f172a;--gauge-target: #f59e0b;--gauge-range-poor: #ef4444;--gauge-range-warning: #f59e0b;--gauge-range-good: #22c55e;background:var(--gauge-surface);border-radius:18px;padding:18px 20px;box-shadow:0 12px 30px #0f172a14,0 0 18px color-mix(in srgb,var(--gauge-active) 35%,transparent);display:grid;gap:12px;font-family:"Source Sans 3",Segoe UI,system-ui,sans-serif;color:var(--gauge-text);position:relative;overflow:hidden}._gaugeCard_6w996_1:after{content:attr(data-tooltip);position:absolute;left:50%;bottom:14px;background:#0f172aeb;color:#f8fafc;padding:6px 10px;border-radius:8px;font-size:11px;font-weight:500;white-space:nowrap;opacity:0;transform:translate(-50%,6px);transition:opacity .15s ease,transform .15s ease;pointer-events:none;z-index:2}._gaugeCard_6w996_1[data-tooltip-open=true]:after{opacity:1;transform:translate(-50%)}._gaugeCard_6w996_1:hover{box-shadow:0 14px 34px #0f172a1a,0 0 28px color-mix(in srgb,var(--gauge-active) 50%,transparent)}._light_6w996_58{--gauge-bg: #f5f6fa;--gauge-surface: #ffffff;--gauge-text: #0f172a;--gauge-text-muted: #64748b;--gauge-tick: #cbd5f5;--gauge-track: #e2e8f0}._dark_6w996_67{--gauge-bg: #0b1220;--gauge-surface: #111827;--gauge-text: #e2e8f0;--gauge-text-muted: #94a3b8;--gauge-tick: #334155;--gauge-track: #1f2937;--gauge-needle: #e2e8f0}._purple_6w996_77{--gauge-bg: #1b1035;--gauge-surface: #221344;--gauge-text: #f8fafc;--gauge-text-muted: #cbd5f5;--gauge-tick: #4c1d95;--gauge-track: #312e81;--gauge-needle: #f8fafc}._dark_6w996_67._gaugeCard_6w996_1:after{background:#0f172af2}._purple_6w996_77._gaugeCard_6w996_1:after{background:#2c1454f2}._header_6w996_95{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}._title_6w996_102{font-size:16px;font-weight:600;letter-spacing:.2px}._subtitle_6w996_108{font-size:12px;color:var(--gauge-text-muted);margin-top:4px}._meta_6w996_114{text-align:right;font-size:20px;font-weight:700;color:var(--gauge-active);display:flex;align-items:baseline;gap:6px}._units_6w996_124{font-size:12px;font-weight:500;color:var(--gauge-text-muted)}._body_6w996_130{background:radial-gradient(circle at 50% 0%,var(--gauge-bg),transparent 65%);border-radius:16px;padding:8px 0 12px;display:grid;place-items:center}._gaugeStage_6w996_138{display:grid;place-items:center}._state_6w996_143{font-size:12px;color:var(--gauge-text-muted);padding:12px 0}._flash_6w996_149{animation:_gauge-flash_6w996_1 .3s ease-in-out}@keyframes _gauge-flash_6w996_1{0%{box-shadow:0 0 #22c55e00}50%{box-shadow:0 0 18px #22c55e59}to{box-shadow:0 0 #22c55e00}}._gaugeCard_6w996_1 svg text{font-family:"Source Sans 3",Segoe UI,system-ui,sans-serif;fill:var(--gauge-text)}._gaugeCard_6w996_1 svg ._gauge-value_6w996_170 text{fill:var(--gauge-text)}._gaugeCard_6w996_1 svg ._gauge-ticks_6w996_174 text{fill:var(--gauge-text-muted)}
@@ -0,0 +1,12 @@
1
+ {
2
+ "value": 72,
3
+ "min": 0,
4
+ "max": 100,
5
+ "target": 85,
6
+ "units": "%",
7
+ "thresholds": [
8
+ { "value": 60, "color": "var(--gauge-range-poor)", "label": "Poor" },
9
+ { "value": 80, "color": "var(--gauge-range-warning)", "label": "Average" },
10
+ { "value": 100, "color": "var(--gauge-range-good)", "label": "Good" }
11
+ ]
12
+ }
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),m=require("react"),je="_gaugeCard_6w996_1",Ae="_light_6w996_58",pe="_dark_6w996_67",be="_purple_6w996_77",_e="_header_6w996_95",we="_title_6w996_102",Me="_subtitle_6w996_108",ke="_meta_6w996_114",$e="_units_6w996_124",Ne="_body_6w996_130",Re="_gaugeStage_6w996_138",ze="_state_6w996_143",Se="_flash_6w996_149",p={gaugeCard:je,light:Ae,dark:pe,purple:be,header:_e,title:we,subtitle:Me,meta:ke,units:$e,body:Ne,gaugeStage:Re,state:ze,flash:Se,"gauge-flash":"_gauge-flash_6w996_1","gauge-value":"_gauge-value_6w996_170","gauge-ticks":"_gauge-ticks_6w996_174"},k=(e,t,a,o)=>{const r=(o-90)*(Math.PI/180);return{x:e+a*Math.cos(r),y:t+a*Math.sin(r)}},ee=(e,t,a,o,r)=>{const l=k(e,t,a,r),d=k(e,t,a,o),x=Math.abs(r-o)<=180?"0":"1";return["M",l.x,l.y,"A",a,a,0,x,0,d.x,d.y].join(" ")};function Te({cx:e,cy:t,radius:a,startAngle:o,endAngle:r,color:l,thickness:d}){const x=ee(e,t,a,o,r);return n.jsx("path",{d:x,fill:"none",stroke:l,strokeWidth:d,strokeLinecap:"round"})}const F=m.memo(Te);function Ve({cx:e,cy:t,radius:a,angle:o,color:r,width:l=3}){const d=k(e,t,a,o),x=k(e,t,10,o-90),f=k(e,t,10,o+90);return n.jsxs("g",{className:"gauge-needle","aria-hidden":"true",children:[n.jsx("path",{d:`M ${x.x} ${x.y} L ${d.x} ${d.y} L ${f.x} ${f.y} Z`,fill:r}),n.jsx("circle",{cx:e,cy:t,r:l*2,fill:r})]})}const de=m.memo(Ve);function Fe({ticks:e,color:t,labelColor:a,showLabels:o}){return n.jsx("g",{className:"gauge-ticks","aria-hidden":"true",children:e.map(r=>n.jsxs("g",{children:[n.jsx("line",{x1:r.outer.x,y1:r.outer.y,x2:r.inner.x,y2:r.inner.y,stroke:t,strokeWidth:"2"}),o&&n.jsx("text",{x:r.label.x,y:r.label.y,textAnchor:"middle",dominantBaseline:"middle",fill:a,fontSize:"10",children:Math.round(r.value)})]},r.value))})}const he=m.memo(Fe);function Ce({cx:e,cy:t,value:a,target:o,units:r,showTarget:l}){return n.jsxs("g",{className:"gauge-value","aria-hidden":"true",children:[n.jsxs("text",{x:e,y:t,textAnchor:"middle",dominantBaseline:"middle",fontSize:"20",children:[a,r?` ${r}`:""]}),l&&typeof o=="number"&&n.jsxs("text",{x:e,y:t+22,textAnchor:"middle",dominantBaseline:"middle",fontSize:"11",children:["Target ",o]})]})}const D=m.memo(Ce);function Ge({cx:e,cy:t,radius:a,angle:o,color:r}){const l=k(e,t,a,o);return n.jsx("circle",{cx:l.x,cy:l.y,r:"3",fill:r})}const te=m.memo(Ge),se=(e,t,a)=>Math.min(Math.max(e,t),a),me=(e,t,a)=>e+(t-e)*a,xe=(e,t,a)=>a===t?0:(e-t)/(a-t),R=(e,t,a,o,r)=>{const l=se(e,t,a),d=xe(l,t,a);return me(o,r,d)},Le=(e,t,a)=>{if(!Array.isArray(t)||t.length===0)return a;const o=[...t].filter(l=>typeof(l==null?void 0:l.value)=="number").sort((l,d)=>l.value-d.value),r=o.find(l=>e<=l.value)||o[o.length-1];return(r==null?void 0:r.color)||a},fe=(e,t,a)=>!Array.isArray(e)||e.length===0?[{value:t+(a-t)*.6,color:"var(--gauge-range-poor)"},{value:t+(a-t)*.8,color:"var(--gauge-range-warning)"},{value:a,color:"var(--gauge-range-good)"}]:e.map(o=>({value:typeof o.value=="number"?o.value:a,color:o.color||"var(--gauge-range-good)",label:o.label||""}));function I({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,tickCount:f=5,arcPadding:y=0}){return m.useMemo(()=>{const c=Number.isFinite(t)?t:0,s=Number.isFinite(a)?a:100,g=Number.isFinite(e)?e:c,u=se(g,c,s),v=Number.isFinite(o)?o:-90,j=Number.isFinite(r)?r:90,$=Number.isFinite(l)?l:200,z=Number.isFinite(d)?d:18,b=$/2,_=$/2,N=$/2,C=N-z,G=(N+C)/2,L=R(u,c,s,v,j),O=fe(x,c,s);let P=c;const K=O.map(S=>{const w=P,M=S.value;return P=M,{...S,startValue:w,endValue:M,startAngle:R(w,c,s,v,j),endAngle:R(M,c,s,v,j)}}),W=f>1?(s-c)/(f-1):0,B=Array.from({length:f},(S,w)=>{const M=c+W*w,i=R(M,c,s,v,j),Q=k(b,_,N-y,i),U=k(b,_,N-y-10,i),X=k(b,_,C-18,i);return{value:M,angle:i,outer:Q,inner:U,label:X}}),Z=ee(b,_,G,v,j),H=xe(u,c,s),E=R(u,c,s,v,j),J=ee(b,_,G,v,E);return{cx:b,cy:_,outerRadius:N,innerRadius:C,midRadius:G,value:u,valueAngle:L,startAngle:v,endAngle:j,arcPath:Z,progressPath:J,progressAngle:E,valueProgress:H,ranges:K,ticks:B,size:$,thickness:z}},[e,t,a,o,r,l,d,x,f,y])}function Pe({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,showTicks:f,showValue:y,showTarget:c,target:s,units:g}){const u=I({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,tickCount:6,arcPadding:2}),v=typeof s=="number"?R(s,u.min,u.max,u.startAngle,u.endAngle):null;return n.jsxs("svg",{width:u.size,height:u.size,viewBox:`0 0 ${u.size} ${u.size}`,children:[n.jsx("g",{className:"gauge-ranges",children:u.ranges.map(j=>n.jsx(F,{cx:u.cx,cy:u.cy,radius:u.midRadius,startAngle:j.startAngle,endAngle:j.endAngle,color:j.color,thickness:u.thickness},j.endValue))}),f&&n.jsx(he,{ticks:u.ticks,color:"var(--gauge-tick)",labelColor:"var(--gauge-text-muted)",showLabels:!0}),typeof v=="number"&&c&&n.jsx(te,{cx:u.cx,cy:u.cy,radius:u.outerRadius-4,angle:v,color:"var(--gauge-target)"}),n.jsx(de,{cx:u.cx,cy:u.cy,radius:u.innerRadius-4,angle:u.valueAngle,color:"var(--gauge-needle)"}),y&&n.jsx(D,{cx:u.cx,cy:u.cy+28,value:Math.round(u.value),target:s,units:g,showTarget:c})]})}const Be=m.memo(Pe);function Ee({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,showTicks:f,showValue:y,units:c}){const s=I({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,tickCount:4,arcPadding:4});return n.jsxs("svg",{width:s.size,height:s.size/1.2,viewBox:`0 0 ${s.size} ${s.size}`,children:[n.jsx("g",{className:"gauge-ranges",children:s.ranges.map(g=>n.jsx(F,{cx:s.cx,cy:s.cy,radius:s.midRadius,startAngle:g.startAngle,endAngle:g.endAngle,color:g.color,thickness:s.thickness},g.endValue))}),f&&n.jsx(he,{ticks:s.ticks,color:"var(--gauge-tick)",labelColor:"var(--gauge-text-muted)",showLabels:!1}),y&&n.jsx(D,{cx:s.cx,cy:s.cy+14,value:Math.round(s.value),units:c,showTarget:!1})]})}const qe=m.memo(Ee);function De({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,showValue:f,units:y}){const c=I({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,tickCount:8,arcPadding:0});return n.jsxs("svg",{width:c.size,height:c.size,viewBox:`0 0 ${c.size} ${c.size}`,children:[n.jsx("g",{className:"gauge-ranges",children:c.ranges.map(s=>n.jsx(F,{cx:c.cx,cy:c.cy,radius:c.midRadius,startAngle:s.startAngle,endAngle:s.endAngle,color:s.color,thickness:c.thickness},s.endValue))}),n.jsx(de,{cx:c.cx,cy:c.cy,radius:c.innerRadius-2,angle:c.valueAngle,color:"var(--gauge-needle)"}),f&&n.jsx(D,{cx:c.cx,cy:c.cy+24,value:Math.round(c.value),units:y,showTarget:!1})]})}const Ie=m.memo(De);function Oe({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,showValue:f,units:y,gradientId:c}){const s=I({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,tickCount:0,arcPadding:0});return n.jsxs("svg",{width:s.size,height:s.size,viewBox:`0 0 ${s.size} ${s.size}`,children:[c&&n.jsx("defs",{children:n.jsxs("linearGradient",{id:c,x1:"0%",y1:"0%",x2:"100%",y2:"0%",children:[n.jsx("stop",{offset:"0%",stopColor:"var(--gauge-range-poor)"}),n.jsx("stop",{offset:"55%",stopColor:"var(--gauge-range-warning)"}),n.jsx("stop",{offset:"100%",stopColor:"var(--gauge-range-good)"})]})}),n.jsx(F,{cx:s.cx,cy:s.cy,radius:s.midRadius,startAngle:s.startAngle,endAngle:s.endAngle,color:"var(--gauge-track)",thickness:s.thickness}),n.jsx(F,{cx:s.cx,cy:s.cy,radius:s.midRadius,startAngle:s.startAngle,endAngle:s.progressAngle,color:c?`url(#${c})`:"var(--gauge-progress)",thickness:s.thickness}),f&&n.jsx(D,{cx:s.cx,cy:s.cy+8,value:Math.round(s.value),units:y,showTarget:!1})]})}const Ke=m.memo(Oe);function We({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,showValue:f,units:y,target:c,showTarget:s}){const g=I({value:e,min:t,max:a,startAngle:o,endAngle:r,size:l,thickness:d,thresholds:x,tickCount:0,arcPadding:0}),u=typeof c=="number"?R(c,g.min,g.max,g.startAngle,g.endAngle):null;return n.jsxs("svg",{width:g.size,height:g.size,viewBox:`0 0 ${g.size} ${g.size}`,children:[n.jsx("g",{className:"gauge-ranges",children:g.ranges.map(v=>n.jsx(F,{cx:g.cx,cy:g.cy,radius:g.midRadius,startAngle:v.startAngle,endAngle:v.endAngle,color:v.color,thickness:g.thickness},v.endValue))}),n.jsx(te,{cx:g.cx,cy:g.cy,radius:g.outerRadius-4,angle:g.valueAngle,color:"var(--gauge-needle)"}),s&&typeof u=="number"&&n.jsx(te,{cx:g.cx,cy:g.cy,radius:g.outerRadius-4,angle:u,color:"var(--gauge-target)"}),f&&n.jsx(D,{cx:g.cx,cy:g.cy+8,value:Math.round(g.value),units:y,target:c,showTarget:s})]})}const Ze=m.memo(We),ie=()=>typeof performance<"u"?performance.now():Date.now();function He(e,{enabled:t,duration:a=500,easing:o}={}){const r=m.useRef(null),l=m.useRef(0),d=m.useRef(e),[x,f]=m.useState(e);return m.useEffect(()=>{if(!t)return f(e),d.current=e,()=>{};const y=d.current,c=ie();l.current=c;const s=typeof o=="function"?o:u=>1-Math.pow(1-u,3),g=()=>{const u=Math.min(1,(ie()-c)/a),v=me(y,e,s(u));f(v),u<1?r.current=requestAnimationFrame(g):d.current=e};return r.current=requestAnimationFrame(g),()=>{r.current&&cancelAnimationFrame(r.current)}},[e,t,a,o]),x}const Je=(...e)=>e.filter(Boolean).join(" "),Qe=null,ue={standard:{start:-90,end:90},semicircle:{start:-110,end:110},full:{start:0,end:360},arc:{start:-225,end:45},multiband:{start:-120,end:120}},ge=e=>e?Array.isArray(e)?e[0]||null:Array.isArray(e.data)?e.data[0]||null:typeof e=="object"?e:null:null,A=(e,t)=>e!==void 0?e:t,Ue=(e,t,a,o)=>{const r=fe(t,a,o);for(let l=0;l<r.length;l+=1)if(e<=r[l].value)return l;return r.length-1};function Xe({type:e="standard",value:t,min:a,max:o,target:r,thresholds:l,showTicks:d=!0,showValue:x=!0,showTarget:f=!1,animated:y=!0,realtime:c=!1,size:s=220,thickness:g=18,startAngle:u,endAngle:v,units:j="",data:$=Qe,apiEndpoint:z="/gauge-data.json",title:b="KPI Gauge",subtitle:_="",theme:N="light",className:C,style:G,onClick:L}){const[O,P]=m.useState(null),[K,W]=m.useState(!1),[B,Z]=m.useState(""),[H,E]=m.useState(!1),[J,S]=m.useState(!1),w=m.useRef(null),M=m.useCallback(async()=>{if(z){W(!0),Z("");try{const h=await fetch(z);if(!h.ok)throw new Error(`Request failed: ${h.status}`);const V=await h.json();P(ge(V))}catch(h){Z("Failed to load gauge data."),console.error("Failed to load gauge data",h)}finally{W(!1)}}},[z]);m.useEffect(()=>{if($){P(ge($));return}M()},[$,M]);const i=m.useMemo(()=>{const h=O||{},V=String(e||h.type||"standard").toLowerCase(),ne=ue[V]||ue.standard,ae=A(a,h.min),re=A(o,h.max),Y=Number.isFinite(ae)?ae:0,oe=Number.isFinite(re)?re:100,ce=A(t,h.value),ve=Number.isFinite(ce)?ce:Y,le=A(r,h.target),ye=Number.isFinite(le)?le:null;return{type:V,value:se(ve,Y,oe),min:Y,max:oe,target:ye,thresholds:A(l,h.thresholds),showTicks:A(d,h.showTicks??d),showValue:A(x,h.showValue??x),showTarget:A(f,h.showTarget??f),size:A(s,h.size??s),thickness:A(g,h.thickness??g),units:A(j,h.units??j),startAngle:A(u,h.startAngle??ne.start),endAngle:A(v,h.endAngle??ne.end)}},[O,e,a,o,t,r,l,d,x,f,s,g,j,u,v]),Q=He(i.value,{enabled:y||c,duration:c?220:500});m.useEffect(()=>{if(!c)return;const h=Ue(i.value,i.thresholds,i.min,i.max);if(w.current===null){w.current=h;return}if(w.current!==h){w.current=h,E(!0);const V=setTimeout(()=>E(!1),300);return()=>clearTimeout(V)}},[c,i.value,i.thresholds,i.min,i.max]);const U=Le(i.value,i.thresholds,"var(--gauge-range-good)"),X=m.useMemo(()=>{const h=[`Value: ${Math.round(i.value)}${i.units?` ${i.units}`:""}`,`Min: ${i.min}`,`Max: ${i.max}`];return typeof i.target=="number"&&h.splice(1,0,`Target: ${i.target}`),h.join(" • ")},[i.value,i.units,i.min,i.max,i.target]),q={value:Q,min:i.min,max:i.max,startAngle:i.startAngle,endAngle:i.endAngle,size:i.size,thickness:i.thickness,thresholds:i.thresholds,showTicks:i.showTicks,showValue:i.showValue,showTarget:i.showTarget,target:i.target,units:i.units},T=i.type;return n.jsxs("section",{className:Je(p.gaugeCard,p[N],H&&p.flash,C),style:{...G,"--gauge-active":U},onClick:()=>L==null?void 0:L(i.value),onMouseEnter:()=>S(!0),onMouseLeave:()=>S(!1),role:"figure","aria-label":b,"data-tooltip":X,"data-tooltip-open":J?"true":"false",children:[n.jsxs("header",{className:p.header,children:[n.jsxs("div",{children:[n.jsx("div",{className:p.title,children:b}),_&&n.jsx("div",{className:p.subtitle,children:_})]}),n.jsxs("div",{className:p.meta,children:[n.jsx("span",{children:Math.round(i.value)}),i.units&&n.jsx("span",{className:p.units,children:i.units})]})]}),n.jsxs("div",{className:p.body,children:[K&&n.jsx("div",{className:p.state,children:"Loading KPI..."}),B&&n.jsx("div",{className:p.state,children:B}),!K&&!B&&n.jsxs("div",{className:p.gaugeStage,children:[T==="semicircle"&&n.jsx(qe,{...q}),T==="full"&&n.jsx(Ie,{...q}),T==="arc"&&n.jsx(Ke,{...q,gradientId:"gaugeGradient"}),T==="multiband"&&n.jsx(Ze,{...q}),(T==="standard"||!T)&&n.jsx(Be,{...q})]})]})]})}exports.AwesomeSpeedometerGauge=Xe;
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -0,0 +1 @@
1
+ ._gaugeCard_6w996_1{--gauge-bg: #f6f7f9;--gauge-surface: #ffffff;--gauge-text: #0f172a;--gauge-text-muted: #64748b;--gauge-tick: #cbd5f5;--gauge-track: #e2e8f0;--gauge-progress: #22c55e;--gauge-needle: #0f172a;--gauge-target: #f59e0b;--gauge-range-poor: #ef4444;--gauge-range-warning: #f59e0b;--gauge-range-good: #22c55e;background:var(--gauge-surface);border-radius:18px;padding:18px 20px;box-shadow:0 12px 30px #0f172a14,0 0 18px color-mix(in srgb,var(--gauge-active) 35%,transparent);display:grid;gap:12px;font-family:"Source Sans 3",Segoe UI,system-ui,sans-serif;color:var(--gauge-text);position:relative;overflow:hidden}._gaugeCard_6w996_1:after{content:attr(data-tooltip);position:absolute;left:50%;bottom:14px;background:#0f172aeb;color:#f8fafc;padding:6px 10px;border-radius:8px;font-size:11px;font-weight:500;white-space:nowrap;opacity:0;transform:translate(-50%,6px);transition:opacity .15s ease,transform .15s ease;pointer-events:none;z-index:2}._gaugeCard_6w996_1[data-tooltip-open=true]:after{opacity:1;transform:translate(-50%)}._gaugeCard_6w996_1:hover{box-shadow:0 14px 34px #0f172a1a,0 0 28px color-mix(in srgb,var(--gauge-active) 50%,transparent)}._light_6w996_58{--gauge-bg: #f5f6fa;--gauge-surface: #ffffff;--gauge-text: #0f172a;--gauge-text-muted: #64748b;--gauge-tick: #cbd5f5;--gauge-track: #e2e8f0}._dark_6w996_67{--gauge-bg: #0b1220;--gauge-surface: #111827;--gauge-text: #e2e8f0;--gauge-text-muted: #94a3b8;--gauge-tick: #334155;--gauge-track: #1f2937;--gauge-needle: #e2e8f0}._purple_6w996_77{--gauge-bg: #1b1035;--gauge-surface: #221344;--gauge-text: #f8fafc;--gauge-text-muted: #cbd5f5;--gauge-tick: #4c1d95;--gauge-track: #312e81;--gauge-needle: #f8fafc}._dark_6w996_67._gaugeCard_6w996_1:after{background:#0f172af2}._purple_6w996_77._gaugeCard_6w996_1:after{background:#2c1454f2}._header_6w996_95{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}._title_6w996_102{font-size:16px;font-weight:600;letter-spacing:.2px}._subtitle_6w996_108{font-size:12px;color:var(--gauge-text-muted);margin-top:4px}._meta_6w996_114{text-align:right;font-size:20px;font-weight:700;color:var(--gauge-active);display:flex;align-items:baseline;gap:6px}._units_6w996_124{font-size:12px;font-weight:500;color:var(--gauge-text-muted)}._body_6w996_130{background:radial-gradient(circle at 50% 0%,var(--gauge-bg),transparent 65%);border-radius:16px;padding:8px 0 12px;display:grid;place-items:center}._gaugeStage_6w996_138{display:grid;place-items:center}._state_6w996_143{font-size:12px;color:var(--gauge-text-muted);padding:12px 0}._flash_6w996_149{animation:_gauge-flash_6w996_1 .3s ease-in-out}@keyframes _gauge-flash_6w996_1{0%{box-shadow:0 0 #22c55e00}50%{box-shadow:0 0 18px #22c55e59}to{box-shadow:0 0 #22c55e00}}._gaugeCard_6w996_1 svg text{font-family:"Source Sans 3",Segoe UI,system-ui,sans-serif;fill:var(--gauge-text)}._gaugeCard_6w996_1 svg ._gauge-value_6w996_170 text{fill:var(--gauge-text)}._gaugeCard_6w996_1 svg ._gauge-ticks_6w996_174 text{fill:var(--gauge-text-muted)}
@@ -0,0 +1,12 @@
1
+ {
2
+ "value": 72,
3
+ "min": 0,
4
+ "max": 100,
5
+ "target": 85,
6
+ "units": "%",
7
+ "thresholds": [
8
+ { "value": 60, "color": "var(--gauge-range-poor)", "label": "Poor" },
9
+ { "value": 80, "color": "var(--gauge-range-warning)", "label": "Average" },
10
+ { "value": 100, "color": "var(--gauge-range-good)", "label": "Good" }
11
+ ]
12
+ }
@@ -0,0 +1,754 @@
1
+ import { jsx as i, jsxs as x } from "react/jsx-runtime";
2
+ import b, { useMemo as ae, useRef as Q, useState as G, useEffect as se, useCallback as ke } from "react";
3
+ const Me = "_gaugeCard_6w996_1", $e = "_light_6w996_58", Ne = "_dark_6w996_67", ze = "_purple_6w996_77", Re = "_header_6w996_95", Te = "_title_6w996_102", Ve = "_subtitle_6w996_108", Fe = "_meta_6w996_114", Ce = "_units_6w996_124", Se = "_body_6w996_130", Ge = "_gaugeStage_6w996_138", Le = "_state_6w996_143", Be = "_flash_6w996_149", _ = {
4
+ gaugeCard: Me,
5
+ light: $e,
6
+ dark: Ne,
7
+ purple: ze,
8
+ header: Re,
9
+ title: Te,
10
+ subtitle: Ve,
11
+ meta: Fe,
12
+ units: Ce,
13
+ body: Se,
14
+ gaugeStage: Ge,
15
+ state: Le,
16
+ flash: Be,
17
+ "gauge-flash": "_gauge-flash_6w996_1",
18
+ "gauge-value": "_gauge-value_6w996_170",
19
+ "gauge-ticks": "_gauge-ticks_6w996_174"
20
+ }, N = (e, t, a, r) => {
21
+ const s = (r - 90) * (Math.PI / 180);
22
+ return {
23
+ x: e + a * Math.cos(s),
24
+ y: t + a * Math.sin(s)
25
+ };
26
+ }, re = (e, t, a, r, s) => {
27
+ const c = N(e, t, a, s), d = N(e, t, a, r), m = Math.abs(s - r) <= 180 ? "0" : "1";
28
+ return [
29
+ "M",
30
+ c.x,
31
+ c.y,
32
+ "A",
33
+ a,
34
+ a,
35
+ 0,
36
+ m,
37
+ 0,
38
+ d.x,
39
+ d.y
40
+ ].join(" ");
41
+ };
42
+ function Pe({ cx: e, cy: t, radius: a, startAngle: r, endAngle: s, color: c, thickness: d }) {
43
+ const m = re(e, t, a, r, s);
44
+ return /* @__PURE__ */ i(
45
+ "path",
46
+ {
47
+ d: m,
48
+ fill: "none",
49
+ stroke: c,
50
+ strokeWidth: d,
51
+ strokeLinecap: "round"
52
+ }
53
+ );
54
+ }
55
+ const L = b.memo(Pe);
56
+ function je({ cx: e, cy: t, radius: a, angle: r, color: s, width: c = 3 }) {
57
+ const d = N(e, t, a, r), m = N(e, t, 10, r - 90), f = N(e, t, 10, r + 90);
58
+ return /* @__PURE__ */ x("g", { className: "gauge-needle", "aria-hidden": "true", children: [
59
+ /* @__PURE__ */ i(
60
+ "path",
61
+ {
62
+ d: `M ${m.x} ${m.y} L ${d.x} ${d.y} L ${f.x} ${f.y} Z`,
63
+ fill: s
64
+ }
65
+ ),
66
+ /* @__PURE__ */ i("circle", { cx: e, cy: t, r: c * 2, fill: s })
67
+ ] });
68
+ }
69
+ const ye = b.memo(je);
70
+ function De({ ticks: e, color: t, labelColor: a, showLabels: r }) {
71
+ return /* @__PURE__ */ i("g", { className: "gauge-ticks", "aria-hidden": "true", children: e.map((s) => /* @__PURE__ */ x("g", { children: [
72
+ /* @__PURE__ */ i(
73
+ "line",
74
+ {
75
+ x1: s.outer.x,
76
+ y1: s.outer.y,
77
+ x2: s.inner.x,
78
+ y2: s.inner.y,
79
+ stroke: t,
80
+ strokeWidth: "2"
81
+ }
82
+ ),
83
+ r && /* @__PURE__ */ i(
84
+ "text",
85
+ {
86
+ x: s.label.x,
87
+ y: s.label.y,
88
+ textAnchor: "middle",
89
+ dominantBaseline: "middle",
90
+ fill: a,
91
+ fontSize: "10",
92
+ children: Math.round(s.value)
93
+ }
94
+ )
95
+ ] }, s.value)) });
96
+ }
97
+ const xe = b.memo(De);
98
+ function Ee({ cx: e, cy: t, value: a, target: r, units: s, showTarget: c }) {
99
+ return /* @__PURE__ */ x("g", { className: "gauge-value", "aria-hidden": "true", children: [
100
+ /* @__PURE__ */ x(
101
+ "text",
102
+ {
103
+ x: e,
104
+ y: t,
105
+ textAnchor: "middle",
106
+ dominantBaseline: "middle",
107
+ fontSize: "20",
108
+ children: [
109
+ a,
110
+ s ? ` ${s}` : ""
111
+ ]
112
+ }
113
+ ),
114
+ c && typeof r == "number" && /* @__PURE__ */ x(
115
+ "text",
116
+ {
117
+ x: e,
118
+ y: t + 22,
119
+ textAnchor: "middle",
120
+ dominantBaseline: "middle",
121
+ fontSize: "11",
122
+ children: [
123
+ "Target ",
124
+ r
125
+ ]
126
+ }
127
+ )
128
+ ] });
129
+ }
130
+ const K = b.memo(Ee);
131
+ function qe({ cx: e, cy: t, radius: a, angle: r, color: s }) {
132
+ const c = N(e, t, a, r);
133
+ return /* @__PURE__ */ i("circle", { cx: c.x, cy: c.y, r: "3", fill: s });
134
+ }
135
+ const oe = b.memo(qe), ce = (e, t, a) => Math.min(Math.max(e, t), a), Ae = (e, t, a) => e + (t - e) * a, pe = (e, t, a) => a === t ? 0 : (e - t) / (a - t), T = (e, t, a, r, s) => {
136
+ const c = ce(e, t, a), d = pe(c, t, a);
137
+ return Ae(r, s, d);
138
+ }, Ie = (e, t, a) => {
139
+ if (!Array.isArray(t) || t.length === 0) return a;
140
+ const r = [...t].filter((c) => typeof (c == null ? void 0 : c.value) == "number").sort((c, d) => c.value - d.value), s = r.find((c) => e <= c.value) || r[r.length - 1];
141
+ return (s == null ? void 0 : s.color) || a;
142
+ }, _e = (e, t, a) => !Array.isArray(e) || e.length === 0 ? [
143
+ { value: t + (a - t) * 0.6, color: "var(--gauge-range-poor)" },
144
+ { value: t + (a - t) * 0.8, color: "var(--gauge-range-warning)" },
145
+ { value: a, color: "var(--gauge-range-good)" }
146
+ ] : e.map((r) => ({
147
+ value: typeof r.value == "number" ? r.value : a,
148
+ color: r.color || "var(--gauge-range-good)",
149
+ label: r.label || ""
150
+ }));
151
+ function O({
152
+ value: e,
153
+ min: t,
154
+ max: a,
155
+ startAngle: r,
156
+ endAngle: s,
157
+ size: c,
158
+ thickness: d,
159
+ thresholds: m,
160
+ tickCount: f = 5,
161
+ arcPadding: y = 0
162
+ }) {
163
+ return ae(() => {
164
+ const o = Number.isFinite(t) ? t : 0, n = Number.isFinite(a) ? a : 100, g = Number.isFinite(e) ? e : o, u = ce(g, o, n), v = Number.isFinite(r) ? r : -90, A = Number.isFinite(s) ? s : 90, z = Number.isFinite(c) ? c : 200, V = Number.isFinite(d) ? d : 18, w = z / 2, k = z / 2, R = z / 2, B = R - V, P = (R + B) / 2, j = T(u, o, n, v, A), W = _e(m, o, n);
165
+ let D = o;
166
+ const Z = W.map((F) => {
167
+ const M = D, $ = F.value;
168
+ return D = $, {
169
+ ...F,
170
+ startValue: M,
171
+ endValue: $,
172
+ startAngle: T(M, o, n, v, A),
173
+ endAngle: T($, o, n, v, A)
174
+ };
175
+ }), H = f > 1 ? (n - o) / (f - 1) : 0, E = Array.from({ length: f }, (F, M) => {
176
+ const $ = o + H * M, l = T($, o, n, v, A), Y = N(w, k, R - y, l), ee = N(w, k, R - y - 10, l), te = N(w, k, B - 18, l);
177
+ return { value: $, angle: l, outer: Y, inner: ee, label: te };
178
+ }), J = re(w, k, P, v, A), U = pe(u, o, n), q = T(u, o, n, v, A), X = re(w, k, P, v, q);
179
+ return {
180
+ cx: w,
181
+ cy: k,
182
+ outerRadius: R,
183
+ innerRadius: B,
184
+ midRadius: P,
185
+ value: u,
186
+ valueAngle: j,
187
+ startAngle: v,
188
+ endAngle: A,
189
+ arcPath: J,
190
+ progressPath: X,
191
+ progressAngle: q,
192
+ valueProgress: U,
193
+ ranges: Z,
194
+ ticks: E,
195
+ size: z,
196
+ thickness: V
197
+ };
198
+ }, [
199
+ e,
200
+ t,
201
+ a,
202
+ r,
203
+ s,
204
+ c,
205
+ d,
206
+ m,
207
+ f,
208
+ y
209
+ ]);
210
+ }
211
+ function Ke({
212
+ value: e,
213
+ min: t,
214
+ max: a,
215
+ startAngle: r,
216
+ endAngle: s,
217
+ size: c,
218
+ thickness: d,
219
+ thresholds: m,
220
+ showTicks: f,
221
+ showValue: y,
222
+ showTarget: o,
223
+ target: n,
224
+ units: g
225
+ }) {
226
+ const u = O({
227
+ value: e,
228
+ min: t,
229
+ max: a,
230
+ startAngle: r,
231
+ endAngle: s,
232
+ size: c,
233
+ thickness: d,
234
+ thresholds: m,
235
+ tickCount: 6,
236
+ arcPadding: 2
237
+ }), v = typeof n == "number" ? T(n, u.min, u.max, u.startAngle, u.endAngle) : null;
238
+ return /* @__PURE__ */ x("svg", { width: u.size, height: u.size, viewBox: `0 0 ${u.size} ${u.size}`, children: [
239
+ /* @__PURE__ */ i("g", { className: "gauge-ranges", children: u.ranges.map((A) => /* @__PURE__ */ i(
240
+ L,
241
+ {
242
+ cx: u.cx,
243
+ cy: u.cy,
244
+ radius: u.midRadius,
245
+ startAngle: A.startAngle,
246
+ endAngle: A.endAngle,
247
+ color: A.color,
248
+ thickness: u.thickness
249
+ },
250
+ A.endValue
251
+ )) }),
252
+ f && /* @__PURE__ */ i(
253
+ xe,
254
+ {
255
+ ticks: u.ticks,
256
+ color: "var(--gauge-tick)",
257
+ labelColor: "var(--gauge-text-muted)",
258
+ showLabels: !0
259
+ }
260
+ ),
261
+ typeof v == "number" && o && /* @__PURE__ */ i(
262
+ oe,
263
+ {
264
+ cx: u.cx,
265
+ cy: u.cy,
266
+ radius: u.outerRadius - 4,
267
+ angle: v,
268
+ color: "var(--gauge-target)"
269
+ }
270
+ ),
271
+ /* @__PURE__ */ i(
272
+ ye,
273
+ {
274
+ cx: u.cx,
275
+ cy: u.cy,
276
+ radius: u.innerRadius - 4,
277
+ angle: u.valueAngle,
278
+ color: "var(--gauge-needle)"
279
+ }
280
+ ),
281
+ y && /* @__PURE__ */ i(
282
+ K,
283
+ {
284
+ cx: u.cx,
285
+ cy: u.cy + 28,
286
+ value: Math.round(u.value),
287
+ target: n,
288
+ units: g,
289
+ showTarget: o
290
+ }
291
+ )
292
+ ] });
293
+ }
294
+ const Oe = b.memo(Ke);
295
+ function We({
296
+ value: e,
297
+ min: t,
298
+ max: a,
299
+ startAngle: r,
300
+ endAngle: s,
301
+ size: c,
302
+ thickness: d,
303
+ thresholds: m,
304
+ showTicks: f,
305
+ showValue: y,
306
+ units: o
307
+ }) {
308
+ const n = O({
309
+ value: e,
310
+ min: t,
311
+ max: a,
312
+ startAngle: r,
313
+ endAngle: s,
314
+ size: c,
315
+ thickness: d,
316
+ thresholds: m,
317
+ tickCount: 4,
318
+ arcPadding: 4
319
+ });
320
+ return /* @__PURE__ */ x("svg", { width: n.size, height: n.size / 1.2, viewBox: `0 0 ${n.size} ${n.size}`, children: [
321
+ /* @__PURE__ */ i("g", { className: "gauge-ranges", children: n.ranges.map((g) => /* @__PURE__ */ i(
322
+ L,
323
+ {
324
+ cx: n.cx,
325
+ cy: n.cy,
326
+ radius: n.midRadius,
327
+ startAngle: g.startAngle,
328
+ endAngle: g.endAngle,
329
+ color: g.color,
330
+ thickness: n.thickness
331
+ },
332
+ g.endValue
333
+ )) }),
334
+ f && /* @__PURE__ */ i(
335
+ xe,
336
+ {
337
+ ticks: n.ticks,
338
+ color: "var(--gauge-tick)",
339
+ labelColor: "var(--gauge-text-muted)",
340
+ showLabels: !1
341
+ }
342
+ ),
343
+ y && /* @__PURE__ */ i(
344
+ K,
345
+ {
346
+ cx: n.cx,
347
+ cy: n.cy + 14,
348
+ value: Math.round(n.value),
349
+ units: o,
350
+ showTarget: !1
351
+ }
352
+ )
353
+ ] });
354
+ }
355
+ const Ze = b.memo(We);
356
+ function He({
357
+ value: e,
358
+ min: t,
359
+ max: a,
360
+ startAngle: r,
361
+ endAngle: s,
362
+ size: c,
363
+ thickness: d,
364
+ thresholds: m,
365
+ showValue: f,
366
+ units: y
367
+ }) {
368
+ const o = O({
369
+ value: e,
370
+ min: t,
371
+ max: a,
372
+ startAngle: r,
373
+ endAngle: s,
374
+ size: c,
375
+ thickness: d,
376
+ thresholds: m,
377
+ tickCount: 8,
378
+ arcPadding: 0
379
+ });
380
+ return /* @__PURE__ */ x("svg", { width: o.size, height: o.size, viewBox: `0 0 ${o.size} ${o.size}`, children: [
381
+ /* @__PURE__ */ i("g", { className: "gauge-ranges", children: o.ranges.map((n) => /* @__PURE__ */ i(
382
+ L,
383
+ {
384
+ cx: o.cx,
385
+ cy: o.cy,
386
+ radius: o.midRadius,
387
+ startAngle: n.startAngle,
388
+ endAngle: n.endAngle,
389
+ color: n.color,
390
+ thickness: o.thickness
391
+ },
392
+ n.endValue
393
+ )) }),
394
+ /* @__PURE__ */ i(
395
+ ye,
396
+ {
397
+ cx: o.cx,
398
+ cy: o.cy,
399
+ radius: o.innerRadius - 2,
400
+ angle: o.valueAngle,
401
+ color: "var(--gauge-needle)"
402
+ }
403
+ ),
404
+ f && /* @__PURE__ */ i(
405
+ K,
406
+ {
407
+ cx: o.cx,
408
+ cy: o.cy + 24,
409
+ value: Math.round(o.value),
410
+ units: y,
411
+ showTarget: !1
412
+ }
413
+ )
414
+ ] });
415
+ }
416
+ const Je = b.memo(He);
417
+ function Qe({
418
+ value: e,
419
+ min: t,
420
+ max: a,
421
+ startAngle: r,
422
+ endAngle: s,
423
+ size: c,
424
+ thickness: d,
425
+ thresholds: m,
426
+ showValue: f,
427
+ units: y,
428
+ gradientId: o
429
+ }) {
430
+ const n = O({
431
+ value: e,
432
+ min: t,
433
+ max: a,
434
+ startAngle: r,
435
+ endAngle: s,
436
+ size: c,
437
+ thickness: d,
438
+ thresholds: m,
439
+ tickCount: 0,
440
+ arcPadding: 0
441
+ });
442
+ return /* @__PURE__ */ x("svg", { width: n.size, height: n.size, viewBox: `0 0 ${n.size} ${n.size}`, children: [
443
+ o && /* @__PURE__ */ i("defs", { children: /* @__PURE__ */ x("linearGradient", { id: o, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [
444
+ /* @__PURE__ */ i("stop", { offset: "0%", stopColor: "var(--gauge-range-poor)" }),
445
+ /* @__PURE__ */ i("stop", { offset: "55%", stopColor: "var(--gauge-range-warning)" }),
446
+ /* @__PURE__ */ i("stop", { offset: "100%", stopColor: "var(--gauge-range-good)" })
447
+ ] }) }),
448
+ /* @__PURE__ */ i(
449
+ L,
450
+ {
451
+ cx: n.cx,
452
+ cy: n.cy,
453
+ radius: n.midRadius,
454
+ startAngle: n.startAngle,
455
+ endAngle: n.endAngle,
456
+ color: "var(--gauge-track)",
457
+ thickness: n.thickness
458
+ }
459
+ ),
460
+ /* @__PURE__ */ i(
461
+ L,
462
+ {
463
+ cx: n.cx,
464
+ cy: n.cy,
465
+ radius: n.midRadius,
466
+ startAngle: n.startAngle,
467
+ endAngle: n.progressAngle,
468
+ color: o ? `url(#${o})` : "var(--gauge-progress)",
469
+ thickness: n.thickness
470
+ }
471
+ ),
472
+ f && /* @__PURE__ */ i(
473
+ K,
474
+ {
475
+ cx: n.cx,
476
+ cy: n.cy + 8,
477
+ value: Math.round(n.value),
478
+ units: y,
479
+ showTarget: !1
480
+ }
481
+ )
482
+ ] });
483
+ }
484
+ const Ue = b.memo(Qe);
485
+ function Xe({
486
+ value: e,
487
+ min: t,
488
+ max: a,
489
+ startAngle: r,
490
+ endAngle: s,
491
+ size: c,
492
+ thickness: d,
493
+ thresholds: m,
494
+ showValue: f,
495
+ units: y,
496
+ target: o,
497
+ showTarget: n
498
+ }) {
499
+ const g = O({
500
+ value: e,
501
+ min: t,
502
+ max: a,
503
+ startAngle: r,
504
+ endAngle: s,
505
+ size: c,
506
+ thickness: d,
507
+ thresholds: m,
508
+ tickCount: 0,
509
+ arcPadding: 0
510
+ }), u = typeof o == "number" ? T(o, g.min, g.max, g.startAngle, g.endAngle) : null;
511
+ return /* @__PURE__ */ x("svg", { width: g.size, height: g.size, viewBox: `0 0 ${g.size} ${g.size}`, children: [
512
+ /* @__PURE__ */ i("g", { className: "gauge-ranges", children: g.ranges.map((v) => /* @__PURE__ */ i(
513
+ L,
514
+ {
515
+ cx: g.cx,
516
+ cy: g.cy,
517
+ radius: g.midRadius,
518
+ startAngle: v.startAngle,
519
+ endAngle: v.endAngle,
520
+ color: v.color,
521
+ thickness: g.thickness
522
+ },
523
+ v.endValue
524
+ )) }),
525
+ /* @__PURE__ */ i(
526
+ oe,
527
+ {
528
+ cx: g.cx,
529
+ cy: g.cy,
530
+ radius: g.outerRadius - 4,
531
+ angle: g.valueAngle,
532
+ color: "var(--gauge-needle)"
533
+ }
534
+ ),
535
+ n && typeof u == "number" && /* @__PURE__ */ i(
536
+ oe,
537
+ {
538
+ cx: g.cx,
539
+ cy: g.cy,
540
+ radius: g.outerRadius - 4,
541
+ angle: u,
542
+ color: "var(--gauge-target)"
543
+ }
544
+ ),
545
+ f && /* @__PURE__ */ i(
546
+ K,
547
+ {
548
+ cx: g.cx,
549
+ cy: g.cy + 8,
550
+ value: Math.round(g.value),
551
+ units: y,
552
+ target: o,
553
+ showTarget: n
554
+ }
555
+ )
556
+ ] });
557
+ }
558
+ const Ye = b.memo(Xe), me = () => typeof performance < "u" ? performance.now() : Date.now();
559
+ function et(e, { enabled: t, duration: a = 500, easing: r } = {}) {
560
+ const s = Q(null), c = Q(0), d = Q(e), [m, f] = G(e);
561
+ return se(() => {
562
+ if (!t)
563
+ return f(e), d.current = e, () => {
564
+ };
565
+ const y = d.current, o = me();
566
+ c.current = o;
567
+ const n = typeof r == "function" ? r : (u) => 1 - Math.pow(1 - u, 3), g = () => {
568
+ const u = Math.min(1, (me() - o) / a), v = Ae(y, e, n(u));
569
+ f(v), u < 1 ? s.current = requestAnimationFrame(g) : d.current = e;
570
+ };
571
+ return s.current = requestAnimationFrame(g), () => {
572
+ s.current && cancelAnimationFrame(s.current);
573
+ };
574
+ }, [e, t, a, r]), m;
575
+ }
576
+ const tt = (...e) => e.filter(Boolean).join(" "), nt = null, fe = {
577
+ standard: { start: -90, end: 90 },
578
+ semicircle: { start: -110, end: 110 },
579
+ full: { start: 0, end: 360 },
580
+ arc: { start: -225, end: 45 },
581
+ multiband: { start: -120, end: 120 }
582
+ }, ve = (e) => e ? Array.isArray(e) ? e[0] || null : Array.isArray(e.data) ? e.data[0] || null : typeof e == "object" ? e : null : null, p = (e, t) => e !== void 0 ? e : t, at = (e, t, a, r) => {
583
+ const s = _e(t, a, r);
584
+ for (let c = 0; c < s.length; c += 1)
585
+ if (e <= s[c].value) return c;
586
+ return s.length - 1;
587
+ };
588
+ function ot({
589
+ type: e = "standard",
590
+ value: t,
591
+ min: a,
592
+ max: r,
593
+ target: s,
594
+ thresholds: c,
595
+ showTicks: d = !0,
596
+ showValue: m = !0,
597
+ showTarget: f = !1,
598
+ animated: y = !0,
599
+ realtime: o = !1,
600
+ size: n = 220,
601
+ thickness: g = 18,
602
+ startAngle: u,
603
+ endAngle: v,
604
+ units: A = "",
605
+ data: z = nt,
606
+ apiEndpoint: V = "/gauge-data.json",
607
+ title: w = "KPI Gauge",
608
+ subtitle: k = "",
609
+ theme: R = "light",
610
+ className: B,
611
+ style: P,
612
+ onClick: j
613
+ }) {
614
+ const [W, D] = G(null), [Z, H] = G(!1), [E, J] = G(""), [U, q] = G(!1), [X, F] = G(!1), M = Q(null), $ = ke(async () => {
615
+ if (V) {
616
+ H(!0), J("");
617
+ try {
618
+ const h = await fetch(V);
619
+ if (!h.ok)
620
+ throw new Error(`Request failed: ${h.status}`);
621
+ const S = await h.json();
622
+ D(ve(S));
623
+ } catch (h) {
624
+ J("Failed to load gauge data."), console.error("Failed to load gauge data", h);
625
+ } finally {
626
+ H(!1);
627
+ }
628
+ }
629
+ }, [V]);
630
+ se(() => {
631
+ if (z) {
632
+ D(ve(z));
633
+ return;
634
+ }
635
+ $();
636
+ }, [z, $]);
637
+ const l = ae(() => {
638
+ const h = W || {}, S = String(e || h.type || "standard").toLowerCase(), le = fe[S] || fe.standard, ie = p(a, h.min), ue = p(r, h.max), ne = Number.isFinite(ie) ? ie : 0, ge = Number.isFinite(ue) ? ue : 100, de = p(t, h.value), be = Number.isFinite(de) ? de : ne, he = p(s, h.target), we = Number.isFinite(he) ? he : null;
639
+ return {
640
+ type: S,
641
+ value: ce(be, ne, ge),
642
+ min: ne,
643
+ max: ge,
644
+ target: we,
645
+ thresholds: p(c, h.thresholds),
646
+ showTicks: p(d, h.showTicks ?? d),
647
+ showValue: p(m, h.showValue ?? m),
648
+ showTarget: p(f, h.showTarget ?? f),
649
+ size: p(n, h.size ?? n),
650
+ thickness: p(g, h.thickness ?? g),
651
+ units: p(A, h.units ?? A),
652
+ startAngle: p(u, h.startAngle ?? le.start),
653
+ endAngle: p(v, h.endAngle ?? le.end)
654
+ };
655
+ }, [
656
+ W,
657
+ e,
658
+ a,
659
+ r,
660
+ t,
661
+ s,
662
+ c,
663
+ d,
664
+ m,
665
+ f,
666
+ n,
667
+ g,
668
+ A,
669
+ u,
670
+ v
671
+ ]), Y = et(l.value, {
672
+ enabled: y || o,
673
+ duration: o ? 220 : 500
674
+ });
675
+ se(() => {
676
+ if (!o) return;
677
+ const h = at(l.value, l.thresholds, l.min, l.max);
678
+ if (M.current === null) {
679
+ M.current = h;
680
+ return;
681
+ }
682
+ if (M.current !== h) {
683
+ M.current = h, q(!0);
684
+ const S = setTimeout(() => q(!1), 300);
685
+ return () => clearTimeout(S);
686
+ }
687
+ }, [o, l.value, l.thresholds, l.min, l.max]);
688
+ const ee = Ie(
689
+ l.value,
690
+ l.thresholds,
691
+ "var(--gauge-range-good)"
692
+ ), te = ae(() => {
693
+ const h = [
694
+ `Value: ${Math.round(l.value)}${l.units ? ` ${l.units}` : ""}`,
695
+ `Min: ${l.min}`,
696
+ `Max: ${l.max}`
697
+ ];
698
+ return typeof l.target == "number" && h.splice(1, 0, `Target: ${l.target}`), h.join(" • ");
699
+ }, [l.value, l.units, l.min, l.max, l.target]), I = {
700
+ value: Y,
701
+ min: l.min,
702
+ max: l.max,
703
+ startAngle: l.startAngle,
704
+ endAngle: l.endAngle,
705
+ size: l.size,
706
+ thickness: l.thickness,
707
+ thresholds: l.thresholds,
708
+ showTicks: l.showTicks,
709
+ showValue: l.showValue,
710
+ showTarget: l.showTarget,
711
+ target: l.target,
712
+ units: l.units
713
+ }, C = l.type;
714
+ return /* @__PURE__ */ x(
715
+ "section",
716
+ {
717
+ className: tt(_.gaugeCard, _[R], U && _.flash, B),
718
+ style: { ...P, "--gauge-active": ee },
719
+ onClick: () => j == null ? void 0 : j(l.value),
720
+ onMouseEnter: () => F(!0),
721
+ onMouseLeave: () => F(!1),
722
+ role: "figure",
723
+ "aria-label": w,
724
+ "data-tooltip": te,
725
+ "data-tooltip-open": X ? "true" : "false",
726
+ children: [
727
+ /* @__PURE__ */ x("header", { className: _.header, children: [
728
+ /* @__PURE__ */ x("div", { children: [
729
+ /* @__PURE__ */ i("div", { className: _.title, children: w }),
730
+ k && /* @__PURE__ */ i("div", { className: _.subtitle, children: k })
731
+ ] }),
732
+ /* @__PURE__ */ x("div", { className: _.meta, children: [
733
+ /* @__PURE__ */ i("span", { children: Math.round(l.value) }),
734
+ l.units && /* @__PURE__ */ i("span", { className: _.units, children: l.units })
735
+ ] })
736
+ ] }),
737
+ /* @__PURE__ */ x("div", { className: _.body, children: [
738
+ Z && /* @__PURE__ */ i("div", { className: _.state, children: "Loading KPI..." }),
739
+ E && /* @__PURE__ */ i("div", { className: _.state, children: E }),
740
+ !Z && !E && /* @__PURE__ */ x("div", { className: _.gaugeStage, children: [
741
+ C === "semicircle" && /* @__PURE__ */ i(Ze, { ...I }),
742
+ C === "full" && /* @__PURE__ */ i(Je, { ...I }),
743
+ C === "arc" && /* @__PURE__ */ i(Ue, { ...I, gradientId: "gaugeGradient" }),
744
+ C === "multiband" && /* @__PURE__ */ i(Ye, { ...I }),
745
+ (C === "standard" || !C) && /* @__PURE__ */ i(Oe, { ...I })
746
+ ] })
747
+ ] })
748
+ ]
749
+ }
750
+ );
751
+ }
752
+ export {
753
+ ot as AwesomeSpeedometerGauge
754
+ };
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
package/dist/style.css ADDED
@@ -0,0 +1,32 @@
1
+ :root {
2
+ font-family: "Source Sans 3", "Segoe UI", system-ui, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+ color: #0f172a;
6
+ background-color: #f1f5f9;
7
+ font-synthesis: none;
8
+ text-rendering: optimizeLegibility;
9
+ -webkit-font-smoothing: antialiased;
10
+ -moz-osx-font-smoothing: grayscale;
11
+ }
12
+
13
+ a {
14
+ font-weight: 500;
15
+ color: inherit;
16
+ text-decoration: none;
17
+ }
18
+
19
+ a:hover {
20
+ color: #2563eb;
21
+ }
22
+
23
+ body {
24
+ margin: 0;
25
+ min-width: 320px;
26
+ min-height: 100vh;
27
+ background: linear-gradient(180deg, #f8fafc 0%, #e2e8f0 100%);
28
+ }
29
+
30
+ * {
31
+ box-sizing: border-box;
32
+ }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "awesome-speedometer-gauge",
3
+ "private": false,
4
+ "version": "0.1.0",
5
+ "description": "A fully-featured React KPI speedometer gauge with 5 visual modes (Standard, SemiCircle, FullCircle, Arc, MultiBand), animated needle, threshold colour bands, dark/light/purple themes, and live data fetching.",
6
+ "type": "module",
7
+ "main": "./dist/cjs/index.js",
8
+ "module": "./dist/esm/index.js",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/esm/index.js",
12
+ "require": "./dist/cjs/index.js"
13
+ },
14
+ "./style.css": "./dist/style.css"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "sideEffects": [
20
+ "*.css"
21
+ ],
22
+ "scripts": {
23
+ "build": "npm run build:esm && npm run build:cjs && npm run build:css",
24
+ "build:esm": "vite build --mode esm",
25
+ "build:cjs": "vite build --mode cjs",
26
+ "build:css": "node -e \"require('fs').copyFileSync('src/style.css','dist/style.css')\"",
27
+ "dev": "vite",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "keywords": [
31
+ "react",
32
+ "gauge",
33
+ "speedometer",
34
+ "kpi",
35
+ "dashboard",
36
+ "chart",
37
+ "arc",
38
+ "needle",
39
+ "animation",
40
+ "component"
41
+ ],
42
+ "author": "Pravinkumar Dabade",
43
+ "license": "MIT",
44
+ "peerDependencies": {
45
+ "react": ">=18.0.0",
46
+ "react-dom": ">=18.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^25.5.0",
50
+ "@vitejs/plugin-react": "^4.3.4",
51
+ "vite": "^6.0.5"
52
+ }
53
+ }