modern-loaders 1.0.0 → 1.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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 suman
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -1,115 +1,360 @@
1
- # @sumanrana/modern-loaders
1
+ <div align="center">
2
2
 
3
- 10 modern, colorful, animated loaders for React. Pure CSS animations behind a typed
4
- component API — **zero runtime dependencies**, ~2 kB JS + ~1.7 kB CSS gzipped.
3
+ # modern-loaders
4
+
5
+ **100 colorful, animated loaders for React.**
6
+
7
+ Pure CSS motion behind one typed component — no runtime dependencies, no SVG, no images.
8
+
9
+ [![npm](https://img.shields.io/npm/v/modern-loaders?color=6366f1&label=npm)](https://www.npmjs.com/package/modern-loaders)
10
+ [![size](https://img.shields.io/bundlephobia/minzip/modern-loaders?color=ec4899&label=gzipped)](https://bundlephobia.com/package/modern-loaders)
11
+ [![types](https://img.shields.io/npm/types/modern-loaders?color=22d3ee)](https://www.npmjs.com/package/modern-loaders)
12
+ [![license](https://img.shields.io/npm/l/modern-loaders?color=8b5cf6)](./LICENSE)
13
+
14
+ </div>
15
+
16
+ ---
5
17
 
6
18
  ```bash
7
- npm i @sumanrana/modern-loaders
19
+ npm i modern-loaders
8
20
  ```
9
21
 
10
22
  ```tsx
11
- import { Loader } from "@sumanrana/modern-loaders";
23
+ import { Loader } from "modern-loaders";
12
24
 
13
25
  <Loader />
14
26
  <Loader variant="wave" size={72} speed={0.8} colors={["#f97316", "#ef4444", "#a855f7"]} />
15
27
  ```
16
28
 
17
- The CSS ships inside the bundle and injects itself — there is no separate stylesheet import.
18
- (If your setup strips side-effect imports, `import "@sumanrana/modern-loaders/styles.css"`.)
29
+ That is the whole setup. **The stylesheet is bundled and injects itself** — no CSS import to
30
+ remember, nothing to configure in Vite, Next.js, CRA, or Tailwind.
19
31
 
20
- ## Props
32
+ <sub>If your bundler strips side-effect imports, add <code>import "modern-loaders/styles.css"</code>.</sub>
21
33
 
22
- | prop | type | default | notes |
23
- |-----------|--------------------|-------------|--------------------------------------------------------------|
24
- | `variant` | `LoaderVariant` | `"aurora"` | one of the 10 below |
25
- | `size` | `number \| string` | `48` | a number means pixels |
26
- | `speed` | `number \| string` | `1` | a number means seconds |
27
- | `colors` | `string[]` | Nebula | 1–3 colors; fewer are cycled, so one color gives a monochrome loader |
28
- | `label` | `string \| null` | `"Loading"` | screen-reader text; `null` marks the loader decorative (`aria-hidden`) |
34
+ ## Why this one
29
35
 
30
- Any other `div` prop (`className`, `style`, `id`, data-attributes…) passes straight through.
36
+ - **100 variants across 10 families** spinners, dots, bars, shapes, progress, grids, pulses, organic, skeletons, and dimensional.
37
+ - **Three props to learn.** `size`, `speed`, `colors`. Everything else has a sensible default.
38
+ - **Zero dependencies.** ~2 kB of JS. All motion is CSS keyframes, so it runs off the main thread.
39
+ - **Fully typed.** `variant` autocompletes every id, and a typo is a compile error.
40
+ - **Accessible by default.** Each loader is a labelled `role="status"` and honours `prefers-reduced-motion`.
41
+ - **Themeable without a build step.** Every value is a CSS custom property you can override.
31
42
 
32
- ## The 10 variants
43
+ ## Usage
33
44
 
34
- | variant | look |
35
- |------------|-----------------------------------------------|
36
- | `aurora` | multi-color conic sweep with a soft glow |
37
- | `orbit` | three-color comet trail |
38
- | `rings` | sonar pulses in three hues |
39
- | `wave` | rainbow dots riding a sine |
40
- | `bars` | gradient equalizer |
41
- | `blob` | morphing gradient squircle |
42
- | `cube` | 3D flip, a gradient per face |
43
- | `spiral` | two arcs spinning opposite directions |
44
- | `bar` | indeterminate gradient progress track |
45
- | `grid` | 3×3 cells pulsing on a diagonal |
45
+ ### Props
46
46
 
47
- Each also has a named export, so `<Aurora size={64} />` works as well as
48
- `<Loader variant="aurora" size={64} />`. `LOADER_VARIANTS` is exported as a readonly
49
- tuple if you want to map over them.
47
+ | prop | type | default | description |
48
+ |---|---|---|---|
49
+ | `variant` | `LoaderVariant` | `"aurora"` | Which loader to render any of the 100 ids below. |
50
+ | `size` | `number \| string` | `48` | Overall size. A number means pixels; strings pass through (`"3rem"`). |
51
+ | `speed` | `number \| string` | `1` | Base duration. A number means seconds; lower is faster. |
52
+ | `colors` | `string[]` | indigo / pink / cyan | One to three colors. Fewer are cycled, so a single color gives a clean monochrome loader. |
53
+ | `label` | `string \| null` | `"Loading"` | Screen-reader text. Pass `null` to mark the loader decorative. |
50
54
 
51
- ## Styling
55
+ Every other `div` prop — `className`, `style`, `id`, `onClick`, `data-*` — passes straight through.
52
56
 
53
- Everything is driven by CSS custom properties, so you can theme without the `colors` prop:
57
+ ### Which loader should I use?
54
58
 
55
- ```css
56
- .my-loader { --c1: #6366f1; --c2: #ec4899; --c3: #22d3ee; --size: 64px; --speed: .9s; }
57
- ```
59
+ | situation | reach for | why |
60
+ |---|---|---|
61
+ | Page or section loading | **Skeletons** | Shows the layout arriving. Beats a spinner on perceived speed. |
62
+ | Button or inline action | **Dots**, or a spinner at `size={16}` | Fits the line box without shifting text. |
63
+ | Upload, install, multi-step work | **Progress** | Says "work is moving", not just "wait". |
64
+ | Live, polling, listening | **Pulses** | Reads as a heartbeat rather than a block. |
65
+ | Splash, empty state, 404 | **Shapes**, **Organic**, **Dimensional** | Personality is worth the pixels here. |
58
66
 
59
- `--track` (the muted rail behind `bar`) derives from `--c1` via `color-mix()`; override it
60
- for a different tint. Under `prefers-reduced-motion: reduce` every animation slows to one
61
- calm 4s linear cycle rather than freezing — a stopped loader reads as a broken app.
67
+ ### Recipes
62
68
 
63
- ## Development
69
+ **A button that keeps its width while loading**
64
70
 
65
- ```bash
66
- npm run dev # demo playground at localhost:5173
67
- npm run build # typecheck + emit dist/ (ESM + CJS + .d.ts + CSS)
68
- npm run typecheck
71
+ ```tsx
72
+ <button disabled={busy}>
73
+ {busy
74
+ ? <Loader variant="dots" size={16} colors={["currentColor"]} label={null} />
75
+ : "Save"}
76
+ </button>
69
77
  ```
70
78
 
71
- ## Publishing the package
79
+ `colors={["currentColor"]}` inherits the button's own text color. `label={null}` stops screen
80
+ readers announcing "Loading" twice when the button already conveys it.
72
81
 
73
- The scope in `name` must be one your npm account owns. Check first:
82
+ **A skeleton shaped like the thing you're waiting for**
74
83
 
75
- ```bash
76
- npm whoami # your username
77
- npm view @sumanrana/modern-loaders # 404 = the name is free
84
+ ```tsx
85
+ {isLoading ? <Loader variant="sk-card" size={64} /> : <ArticleCard {...article} />}
78
86
  ```
79
87
 
80
- If the scope isn't yours, change `name` to `@<your-npm-user>/react-modern-loaders`
81
- (or an unscoped name that's still free), then:
88
+ **A full-page overlay**
82
89
 
83
- ```bash
84
- npm login
85
- npm publish --access public # required for scoped packages
90
+ ```tsx
91
+ <div style={{ position: "fixed", inset: 0, display: "grid", placeItems: "center" }}>
92
+ <Loader variant="aurora" size={80} label="Loading your dashboard" />
93
+ </div>
86
94
  ```
87
95
 
88
- `prepublishOnly` runs the build, and `files` limits the tarball to `dist/` + this README.
96
+ **Build your own picker** the manifest is exported:
89
97
 
90
- ## Deploying the demo
98
+ ```tsx
99
+ import { VARIANTS, Loader } from "modern-loaders";
91
100
 
92
- ```bash
93
- npm run build:demo # dist-demo/
94
- npm run preview:demo # check it locally
101
+ VARIANTS.filter(v => v.group === "Skeletons")
102
+ .map(v => <Loader key={v.id} variant={v.id} />);
95
103
  ```
96
104
 
97
- Then push `dist-demo/` to any static host:
105
+ ## All 100 variants
98
106
 
99
- ```bash
100
- npx vercel deploy dist-demo --prod
101
- npx netlify-cli deploy --dir dist-demo --prod
102
- npx wrangler pages deploy dist-demo
107
+ Expand a family to see its variants. Every id maps to a `.ldr--<id>` CSS class.
108
+
109
+ <details>
110
+ <summary><b>Spinners</b> · 10 Rings and arcs — the classic shape, modernised.</summary>
111
+
112
+ | variant | what it looks like |
113
+ |---|---|
114
+ | `aurora` | multi-color conic sweep with a soft glow |
115
+ | `spiral` | two arcs spinning opposite directions |
116
+ | `ring-dash` | a dashed ring drawing itself |
117
+ | `ring-gap` | solid ring with a travelling gap |
118
+ | `comet` | gradient tail chasing a bright head |
119
+ | `arc-trio` | three nested arcs at different speeds |
120
+ | `halo` | still ring with a glow orbiting it |
121
+ | `sweep` | radar-style cone sweeping a disc |
122
+ | `dot-ring` | eight dots fading around a circle |
123
+ | `petal` | radiating rounded blades, iOS-style but colorful |
124
+
125
+ </details>
126
+
127
+ <details>
128
+ <summary><b>Dots</b> · 10 — Small, quiet, and good inline with text.</summary>
129
+
130
+ | variant | what it looks like |
131
+ |---|---|
132
+ | `wave` | rainbow dots riding a sine |
133
+ | `orbit` | three-color comet trail |
134
+ | `bounce` | three dots with squash on landing |
135
+ | `fade-dots` | three dots handing off opacity |
136
+ | `pulse-dots` | three dots breathing in sequence |
137
+ | `typing` | chat-bubble typing indicator |
138
+ | `chase` | six dots circling with a scale pulse |
139
+ | `snake` | dots sliding along a track |
140
+ | `swap` | two dots trading places |
141
+ | `juggle` | three dots arcing over each other |
142
+
143
+ </details>
144
+
145
+ <details>
146
+ <summary><b>Bars</b> · 10 — Equalizer-style motion with a strong rhythm.</summary>
147
+
148
+ | variant | what it looks like |
149
+ |---|---|
150
+ | `bars` | gradient equalizer |
151
+ | `ladder` | bars lighting up bottom to top |
152
+ | `stretch` | bars scaling from the centre with a color shift |
153
+ | `flip-bars` | bars flipping on the X axis |
154
+ | `slide-bars` | stacked bars sliding sideways |
155
+ | `drop-bars` | bars falling and rebounding |
156
+ | `meter` | signal-strength staircase |
157
+ | `wave-bars` | seven bars translating through a sine |
158
+ | `split-bars` | pairs opening away from the centre |
159
+ | `scan-bars` | a highlight sweeping across a static row |
160
+
161
+ </details>
162
+
163
+ <details>
164
+ <summary><b>Shapes</b> · 10 — Geometry that morphs, folds, and turns.</summary>
165
+
166
+ | variant | what it looks like |
167
+ |---|---|
168
+ | `blob` | morphing gradient squircle |
169
+ | `cube` | 3D flip, a gradient per face |
170
+ | `triangle` | spinning gradient triangle |
171
+ | `hexagon` | hexagon pulsing and turning |
172
+ | `diamond` | rotated square breathing |
173
+ | `star` | five-point star turning |
174
+ | `squircle` | square relaxing into a circle |
175
+ | `folding` | four quadrants folding away in turn |
176
+ | `pentagon` | pentagon rocking on its base |
177
+ | `shape-shift` | square ↔ circle with a hue sweep |
178
+
179
+ </details>
180
+
181
+ <details>
182
+ <summary><b>Progress</b> · 10 — Wide, indeterminate tracks for page and upload states.</summary>
183
+
184
+ | variant | what it looks like |
185
+ |---|---|
186
+ | `bar` | indeterminate runner |
187
+ | `bar-stripes` | barber-pole fill |
188
+ | `bar-dual` | two runners passing each other |
189
+ | `bar-segments` | discrete blocks filling in turn |
190
+ | `bar-pill` | a pill bouncing wall to wall |
191
+ | `bar-glow` | runner with a light bloom |
192
+ | `bar-wave` | gradient sliding under a fixed window |
193
+ | `bar-dots` | dots marching along a rail |
194
+ | `bar-snake` | thin runner that stretches and contracts |
195
+ | `bar-fill` | repeatedly filling left to right |
196
+
197
+ </details>
198
+
199
+ <details>
200
+ <summary><b>Grids</b> · 10 — Cell fields that pulse, flip, and cascade.</summary>
201
+
202
+ | variant | what it looks like |
203
+ |---|---|
204
+ | `grid` | 3x3 cells pulsing on a diagonal |
205
+ | `checker` | alternating cells trading places |
206
+ | `cascade` | a wave rolling from the top-left corner |
207
+ | `tiles` | cells flipping like a split-flap board |
208
+ | `pixel` | 4x4 field blinking in scattered order |
209
+ | `matrix` | rows sweeping downward |
210
+ | `mosaic` | cells cycling through the palette |
211
+ | `ripple-grid` | a pulse spreading from the centre cell |
212
+ | `domino` | cells tipping over one after another |
213
+ | `sparkle` | cells twinkling at different sizes |
214
+
215
+ </details>
216
+
217
+ <details>
218
+ <summary><b>Pulses</b> · 10 — Expanding rings for live, waiting, or listening states.</summary>
219
+
220
+ | variant | what it looks like |
221
+ |---|---|
222
+ | `rings` | sonar pulses in three hues |
223
+ | `radar` | sweeping cone over a ring |
224
+ | `sonar` | filled discs expanding outward |
225
+ | `echo` | rings that expand then snap back |
226
+ | `shockwave` | a ring that thins as it grows |
227
+ | `bloom` | soft gradient discs blooming open |
228
+ | `droplet` | a dot falling into its own ripple |
229
+ | `concentric` | three static rings breathing together |
230
+ | `aura` | a soft glow breathing behind a core |
231
+ | `beacon` | steady dot with an expanding halo |
232
+
233
+ </details>
234
+
235
+ <details>
236
+ <summary><b>Organic</b> · 10 — Playful, physical motion with personality.</summary>
237
+
238
+ | variant | what it looks like |
239
+ |---|---|
240
+ | `heart` | a heartbeat: a rotated square with two round lobes |
241
+ | `moon` | a crescent turning through its phases |
242
+ | `sun` | a core with rays reaching out |
243
+ | `flame` | a flickering teardrop |
244
+ | `bubble` | bubbles rising and popping |
245
+ | `jelly` | squash and stretch |
246
+ | `spring` | a coil compressing and releasing |
247
+ | `float` | an orb bobbing over its shadow |
248
+ | `leaf` | a teardrop tumbling as it turns |
249
+ | `windmill` | four blades turning together |
250
+
251
+ </details>
252
+
253
+ <details>
254
+ <summary><b>Skeletons</b> · 10 — Content-shaped placeholders — use these over spinners for page loads.</summary>
255
+
256
+ | variant | what it looks like |
257
+ |---|---|
258
+ | `shimmer` | a single sweeping block |
259
+ | `sk-text` | three lines of copy |
260
+ | `sk-card` | thumbnail with two lines beside it |
261
+ | `sk-avatar` | a circle and a name line |
262
+ | `sk-image` | a framed image placeholder |
263
+ | `sk-list` | stacked rows with leading bullets |
264
+ | `sk-table` | a header row above body rows |
265
+ | `sk-chip` | a row of tag placeholders |
266
+ | `sk-paragraph` | four lines of body copy |
267
+ | `sk-media` | a 16:9 block with a caption under it |
268
+
269
+ </details>
270
+
271
+ <details>
272
+ <summary><b>Dimensional</b> · 10 — Depth, 3D rotation, and orbital motion.</summary>
273
+
274
+ | variant | what it looks like |
275
+ |---|---|
276
+ | `helix` | two strands weaving past each other |
277
+ | `pendulum` | a Newton's cradle |
278
+ | `atom` | electron shells around a nucleus |
279
+ | `gyro` | nested rings turning on different axes |
280
+ | `coil` | stacked rings travelling down a spring |
281
+ | `vortex` | arcs drawn into a funnel |
282
+ | `prism` | three gradient triangles orbiting a centre |
283
+ | `torus` | a ring tumbling in 3D |
284
+ | `cylinder` | stacked ellipses rolling downward |
285
+ | `galaxy` | dots spiralling out from the core |
286
+
287
+ </details>
288
+
289
+ ## Theming
290
+
291
+ The `colors` prop covers most cases. For anything else, override the custom properties — they
292
+ cascade, so one rule themes a whole subtree:
293
+
294
+ ```css
295
+ .dashboard {
296
+ --c1: #6366f1; /* primary */
297
+ --c2: #ec4899; /* secondary */
298
+ --c3: #22d3ee; /* tertiary */
299
+ --size: 64px; /* box size */
300
+ --speed: .9s; /* base duration */
301
+
302
+ --track: #1e1e2e; /* rail behind progress bars */
303
+ --grad: linear-gradient(90deg, var(--c1), var(--c3)); /* shared gradient */
304
+ }
103
305
  ```
104
306
 
105
- For GitHub Pages the site lives under `/<repo>/`, so build with a matching base:
307
+ `--track` and `--grad` derive from `--c1`–`--c3` automatically; set them directly for finer control.
106
308
 
107
- ```bash
108
- DEMO_BASE=/loader/ npm run build:demo
109
- npx gh-pages -d dist-demo # or push dist-demo to a gh-pages branch
309
+ ## Accessibility
310
+
311
+ - Each loader renders as `role="status"` with `aria-label`, so assistive tech announces it once.
312
+ - A decorative loader — one sitting beside visible "Loading…" text — should take `label={null}`,
313
+ which switches it to `aria-hidden` and prevents a double announcement.
314
+ - Under `prefers-reduced-motion: reduce`, every animation slows to a single calm 4s linear cycle
315
+ rather than stopping. A frozen loader reads as a crashed app, which is worse than gentle motion.
316
+
317
+ ## Bundle size
318
+
319
+ | | raw | gzipped |
320
+ |---|---|---|
321
+ | JS | ~7 kB | **~2 kB** |
322
+ | CSS (all 100 variants) | ~58 kB | **~8 kB** |
323
+
324
+ One caveat, stated plainly: **the CSS is not tree-shakeable.** Class-based styles cannot be
325
+ dead-code eliminated, so importing a single variant still ships the sheet for all 100. That is a
326
+ fair trade for most apps. If you need only a handful and every kilobyte counts, copy the specific
327
+ `.ldr--*` blocks out of [`src/styles/`](./src/styles) into your own CSS and skip the package.
328
+
329
+ ## Named exports
330
+
331
+ `Loader` is the main export. The original ten also have wrappers, kept for backward compatibility
332
+ with 1.0.x:
333
+
334
+ ```tsx
335
+ import { Aurora, Orbit, Rings, Wave, Bars, Blob, Cube, Spiral, Bar, Grid } from "modern-loaders";
110
336
  ```
111
337
 
338
+ The other 90 are reached with `<Loader variant="…" />`. A hundred named exports would bloat the
339
+ API surface for no real gain.
340
+
112
341
  ## Browser support
113
342
 
114
- Uses `mask`, `color-mix()`, and `aspect-ratio`: Chrome 111+, Safari 16.2+, Firefox 113+.
115
- Older browsers degrade to solid shapes rather than breaking.
343
+ Chrome 111+ · Safari 16.2+ · Firefox 113+ — the floor is set by `color-mix()`, alongside `mask`,
344
+ `aspect-ratio`, and `clip-path`. Older browsers degrade to solid shapes rather than breaking.
345
+
346
+ ## Development
347
+
348
+ ```bash
349
+ npm run dev # demo gallery: search, family tabs, live palette / size / speed controls
350
+ npm run build # typecheck, then emit dist/ (ESM + CJS + .d.ts + CSS)
351
+ npm run build:demo # static demo site → dist-demo/
352
+ ```
353
+
354
+ Adding a variant takes two edits: a `.ldr--<id>` block in `src/styles/`, and a row in
355
+ [`src/variants.ts`](./src/variants.ts). The component, the types, and the demo all read from that
356
+ one manifest.
357
+
358
+ ## License
359
+
360
+ ISC © suman
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require('./index.css');const r=require("react/jsx-runtime"),g=["aurora","orbit","rings","wave","bars","blob","cube","spiral","bar","grid"],j={aurora:0,orbit:3,rings:3,wave:5,bars:5,blob:0,cube:2,spiral:0,bar:0,grid:9},o=(a,s)=>typeof a=="number"?`${a}${s}`:a;function t({variant:a="aurora",size:s=48,speed:b=1,colors:i,label:e="Loading",className:u,style:d,...c}){const n={"--size":o(s,"px"),"--speed":o(b,"s")};i!=null&&i.length&&(n["--c1"]=i[0],n["--c2"]=i[1%i.length],n["--c3"]=i[2%i.length]);const v=j[a];return r.jsx("div",{...c,className:["ldr",`ldr--${a}`,u].filter(Boolean).join(" "),style:{...n,...d},role:e?"status":void 0,"aria-label":e??void 0,"aria-hidden":e?void 0:!0,children:Array.from({length:v},(y,l)=>r.jsx("span",{},l))})}const x=a=>r.jsx(t,{variant:"aurora",...a}),p=a=>r.jsx(t,{variant:"orbit",...a}),A=a=>r.jsx(t,{variant:"rings",...a}),B=a=>r.jsx(t,{variant:"wave",...a}),L=a=>r.jsx(t,{variant:"bars",...a}),R=a=>r.jsx(t,{variant:"blob",...a}),S=a=>r.jsx(t,{variant:"cube",...a}),f=a=>r.jsx(t,{variant:"spiral",...a}),h=a=>r.jsx(t,{variant:"bar",...a}),m=a=>r.jsx(t,{variant:"grid",...a});exports.Aurora=x;exports.Bar=h;exports.Bars=L;exports.Blob=R;exports.Cube=S;exports.Grid=m;exports.LOADER_VARIANTS=g;exports.Loader=t;exports.Orbit=p;exports.Rings=A;exports.Spiral=f;exports.Wave=B;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require('./index.css');const e=require("react/jsx-runtime"),n=[{id:"aurora",label:"Aurora",group:"Spinners",cells:0},{id:"spiral",label:"Spiral",group:"Spinners",cells:0},{id:"ring-dash",label:"Ring Dash",group:"Spinners",cells:0},{id:"ring-gap",label:"Ring Gap",group:"Spinners",cells:0},{id:"comet",label:"Comet",group:"Spinners",cells:1},{id:"arc-trio",label:"Arc Trio",group:"Spinners",cells:3},{id:"halo",label:"Halo",group:"Spinners",cells:1},{id:"sweep",label:"Sweep",group:"Spinners",cells:0},{id:"dot-ring",label:"Dot Ring",group:"Spinners",cells:8},{id:"petal",label:"Petal",group:"Spinners",cells:8},{id:"wave",label:"Wave",group:"Dots",cells:5},{id:"orbit",label:"Orbit",group:"Dots",cells:3},{id:"bounce",label:"Bounce",group:"Dots",cells:3},{id:"fade-dots",label:"Fade Dots",group:"Dots",cells:3},{id:"pulse-dots",label:"Pulse Dots",group:"Dots",cells:3},{id:"typing",label:"Typing",group:"Dots",cells:3},{id:"chase",label:"Chase",group:"Dots",cells:6},{id:"snake",label:"Snake",group:"Dots",cells:5},{id:"swap",label:"Swap",group:"Dots",cells:2},{id:"juggle",label:"Juggle",group:"Dots",cells:3},{id:"bars",label:"Bars",group:"Bars",cells:5},{id:"ladder",label:"Ladder",group:"Bars",cells:4},{id:"stretch",label:"Stretch",group:"Bars",cells:5},{id:"flip-bars",label:"Flip Bars",group:"Bars",cells:5},{id:"slide-bars",label:"Slide Bars",group:"Bars",cells:3},{id:"drop-bars",label:"Drop Bars",group:"Bars",cells:5},{id:"meter",label:"Meter",group:"Bars",cells:5},{id:"wave-bars",label:"Wave Bars",group:"Bars",cells:7},{id:"split-bars",label:"Split Bars",group:"Bars",cells:4},{id:"scan-bars",label:"Scan Bars",group:"Bars",cells:6},{id:"blob",label:"Blob",group:"Shapes",cells:0},{id:"cube",label:"Cube",group:"Shapes",cells:2},{id:"triangle",label:"Triangle",group:"Shapes",cells:0},{id:"hexagon",label:"Hexagon",group:"Shapes",cells:0},{id:"diamond",label:"Diamond",group:"Shapes",cells:0},{id:"star",label:"Star",group:"Shapes",cells:0},{id:"squircle",label:"Squircle",group:"Shapes",cells:0},{id:"folding",label:"Folding",group:"Shapes",cells:4},{id:"pentagon",label:"Pentagon",group:"Shapes",cells:0},{id:"shape-shift",label:"Shape Shift",group:"Shapes",cells:0},{id:"bar",label:"Bar",group:"Progress",cells:0},{id:"bar-stripes",label:"Bar Stripes",group:"Progress",cells:0},{id:"bar-dual",label:"Bar Dual",group:"Progress",cells:0},{id:"bar-segments",label:"Bar Segments",group:"Progress",cells:5},{id:"bar-pill",label:"Bar Pill",group:"Progress",cells:0},{id:"bar-glow",label:"Bar Glow",group:"Progress",cells:0},{id:"bar-wave",label:"Bar Wave",group:"Progress",cells:0},{id:"bar-dots",label:"Bar Dots",group:"Progress",cells:5},{id:"bar-snake",label:"Bar Snake",group:"Progress",cells:0},{id:"bar-fill",label:"Bar Fill",group:"Progress",cells:0},{id:"grid",label:"Grid",group:"Grids",cells:9},{id:"checker",label:"Checker",group:"Grids",cells:9},{id:"cascade",label:"Cascade",group:"Grids",cells:9},{id:"tiles",label:"Tiles",group:"Grids",cells:9},{id:"pixel",label:"Pixel",group:"Grids",cells:16},{id:"matrix",label:"Matrix",group:"Grids",cells:9},{id:"mosaic",label:"Mosaic",group:"Grids",cells:9},{id:"ripple-grid",label:"Ripple Grid",group:"Grids",cells:9},{id:"domino",label:"Domino",group:"Grids",cells:9},{id:"sparkle",label:"Sparkle",group:"Grids",cells:9},{id:"rings",label:"Rings",group:"Pulses",cells:3},{id:"radar",label:"Radar",group:"Pulses",cells:2},{id:"sonar",label:"Sonar",group:"Pulses",cells:3},{id:"echo",label:"Echo",group:"Pulses",cells:3},{id:"shockwave",label:"Shockwave",group:"Pulses",cells:2},{id:"bloom",label:"Bloom",group:"Pulses",cells:3},{id:"droplet",label:"Droplet",group:"Pulses",cells:2},{id:"concentric",label:"Concentric",group:"Pulses",cells:3},{id:"aura",label:"Aura",group:"Pulses",cells:1},{id:"beacon",label:"Beacon",group:"Pulses",cells:2},{id:"heart",label:"Heart",group:"Organic",cells:0},{id:"moon",label:"Moon",group:"Organic",cells:0},{id:"sun",label:"Sun",group:"Organic",cells:8},{id:"flame",label:"Flame",group:"Organic",cells:0},{id:"bubble",label:"Bubble",group:"Organic",cells:3},{id:"jelly",label:"Jelly",group:"Organic",cells:0},{id:"spring",label:"Spring",group:"Organic",cells:0},{id:"float",label:"Float",group:"Organic",cells:1},{id:"leaf",label:"Leaf",group:"Organic",cells:0},{id:"windmill",label:"Windmill",group:"Organic",cells:4},{id:"shimmer",label:"Shimmer",group:"Skeletons",cells:0},{id:"sk-text",label:"Text",group:"Skeletons",cells:3},{id:"sk-card",label:"Card",group:"Skeletons",cells:3},{id:"sk-avatar",label:"Avatar",group:"Skeletons",cells:2},{id:"sk-image",label:"Image",group:"Skeletons",cells:0},{id:"sk-list",label:"List",group:"Skeletons",cells:3},{id:"sk-table",label:"Table",group:"Skeletons",cells:4},{id:"sk-chip",label:"Chips",group:"Skeletons",cells:3},{id:"sk-paragraph",label:"Paragraph",group:"Skeletons",cells:4},{id:"sk-media",label:"Media",group:"Skeletons",cells:2},{id:"helix",label:"Helix",group:"Dimensional",cells:8},{id:"pendulum",label:"Pendulum",group:"Dimensional",cells:5},{id:"atom",label:"Atom",group:"Dimensional",cells:3},{id:"gyro",label:"Gyro",group:"Dimensional",cells:3},{id:"coil",label:"Coil",group:"Dimensional",cells:5},{id:"vortex",label:"Vortex",group:"Dimensional",cells:4},{id:"prism",label:"Prism",group:"Dimensional",cells:3},{id:"torus",label:"Torus",group:"Dimensional",cells:0},{id:"cylinder",label:"Cylinder",group:"Dimensional",cells:4},{id:"galaxy",label:"Galaxy",group:"Dimensional",cells:6}],b=[{name:"Spinners",description:"Rings and arcs — the classic shape, modernised."},{name:"Dots",description:"Small, quiet, and good inline with text."},{name:"Bars",description:"Equalizer-style motion with a strong rhythm."},{name:"Shapes",description:"Geometry that morphs, folds, and turns."},{name:"Progress",description:"Wide, indeterminate tracks for page and upload states."},{name:"Grids",description:"Cell fields that pulse, flip, and cascade."},{name:"Pulses",description:"Expanding rings for live, waiting, or listening states."},{name:"Organic",description:"Playful, physical motion with personality."},{name:"Skeletons",description:"Content-shaped placeholders — use these over spinners for page loads."},{name:"Dimensional",description:"Depth, 3D rotation, and orbital motion."}],m=n.map(l=>l.id),S=Object.fromEntries(n.map(l=>[l.id,l.cells])),d=(l,i)=>typeof l=="number"?`${l}${i}`:l;function s({variant:l="aurora",size:i=48,speed:p=1,colors:a,label:o="Loading",className:c,style:g,...t}){const r={"--size":d(i,"px"),"--speed":d(p,"s")};return a!=null&&a.length&&(r["--c1"]=a[0],r["--c2"]=a[1%a.length],r["--c3"]=a[2%a.length]),e.jsx("div",{...t,className:["ldr",`ldr--${l}`,c].filter(Boolean).join(" "),style:{...r,...g},role:o?"status":void 0,"aria-label":o??void 0,"aria-hidden":o?void 0:!0,children:Array.from({length:S[l]??0},(O,u)=>e.jsx("span",{},u))})}const h=l=>e.jsx(s,{variant:"aurora",...l}),B=l=>e.jsx(s,{variant:"orbit",...l}),D=l=>e.jsx(s,{variant:"rings",...l}),P=l=>e.jsx(s,{variant:"wave",...l}),k=l=>e.jsx(s,{variant:"bars",...l}),x=l=>e.jsx(s,{variant:"blob",...l}),v=l=>e.jsx(s,{variant:"cube",...l}),f=l=>e.jsx(s,{variant:"spiral",...l}),G=l=>e.jsx(s,{variant:"bar",...l}),y=l=>e.jsx(s,{variant:"grid",...l});exports.Aurora=h;exports.Bar=G;exports.Bars=k;exports.Blob=x;exports.Cube=v;exports.GROUPS=b;exports.Grid=y;exports.LOADER_VARIANTS=m;exports.Loader=s;exports.Orbit=B;exports.Rings=D;exports.Spiral=f;exports.VARIANTS=n;exports.Wave=P;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/Loader.tsx"],"sourcesContent":["import type { CSSProperties, HTMLAttributes } from \"react\";\nimport \"./loaders.css\";\n\nexport const LOADER_VARIANTS = [\n \"aurora\",\n \"orbit\",\n \"rings\",\n \"wave\",\n \"bars\",\n \"blob\",\n \"cube\",\n \"spiral\",\n \"bar\",\n \"grid\",\n] as const;\n\nexport type LoaderVariant = (typeof LOADER_VARIANTS)[number];\n\n/** How many <span> children each variant's CSS expects. */\nconst CELLS: Record<LoaderVariant, number> = {\n aurora: 0,\n orbit: 3,\n rings: 3,\n wave: 5,\n bars: 5,\n blob: 0,\n cube: 2,\n spiral: 0,\n bar: 0,\n grid: 9,\n};\n\nexport interface LoaderProps extends Omit<HTMLAttributes<HTMLDivElement>, \"color\"> {\n /** Which loader to render. @default \"aurora\" */\n variant?: LoaderVariant;\n /** Box size. A number is treated as pixels. @default 48 */\n size?: number | string;\n /** Base animation duration. A number is treated as seconds. @default 1 */\n speed?: number | string;\n /**\n * One to three colors. Fewer than three are cycled, so a single color still\n * produces a coherent (monochrome) loader.\n */\n colors?: string[];\n /** Announced to screen readers. Pass `null` to render the loader as decorative. */\n label?: string | null;\n}\n\nconst unit = (v: number | string | undefined, suffix: string) =>\n typeof v === \"number\" ? `${v}${suffix}` : v;\n\nexport function Loader({\n variant = \"aurora\",\n size = 48,\n speed = 1,\n colors,\n label = \"Loading\",\n className,\n style,\n ...rest\n}: LoaderProps) {\n const vars: CSSProperties & Record<string, string | undefined> = {\n \"--size\": unit(size, \"px\"),\n \"--speed\": unit(speed, \"s\"),\n };\n\n if (colors?.length) {\n // Cycle whatever was given across the three slots the CSS reads.\n vars[\"--c1\"] = colors[0];\n vars[\"--c2\"] = colors[1 % colors.length];\n vars[\"--c3\"] = colors[2 % colors.length];\n }\n\n const cells = CELLS[variant];\n\n return (\n <div\n {...rest}\n className={[\"ldr\", `ldr--${variant}`, className].filter(Boolean).join(\" \")}\n style={{ ...vars, ...style }}\n role={label ? \"status\" : undefined}\n aria-label={label ?? undefined}\n aria-hidden={label ? undefined : true}\n >\n {Array.from({ length: cells }, (_, i) => (\n <span key={i} />\n ))}\n </div>\n );\n}\n\n/** Convenience wrappers, so `<Aurora />` works as well as `<Loader variant=\"aurora\" />`. */\ntype VariantProps = Omit<LoaderProps, \"variant\">;\n\nexport const Aurora = (p: VariantProps) => <Loader variant=\"aurora\" {...p} />;\nexport const Orbit = (p: VariantProps) => <Loader variant=\"orbit\" {...p} />;\nexport const Rings = (p: VariantProps) => <Loader variant=\"rings\" {...p} />;\nexport const Wave = (p: VariantProps) => <Loader variant=\"wave\" {...p} />;\nexport const Bars = (p: VariantProps) => <Loader variant=\"bars\" {...p} />;\nexport const Blob = (p: VariantProps) => <Loader variant=\"blob\" {...p} />;\nexport const Cube = (p: VariantProps) => <Loader variant=\"cube\" {...p} />;\nexport const Spiral = (p: VariantProps) => <Loader variant=\"spiral\" {...p} />;\nexport const Bar = (p: VariantProps) => <Loader variant=\"bar\" {...p} />;\nexport const Grid = (p: VariantProps) => <Loader variant=\"grid\" {...p} />;\n"],"names":["LOADER_VARIANTS","CELLS","unit","v","suffix","Loader","variant","size","speed","colors","label","className","style","rest","vars","cells","jsx","_","i","Aurora","p","Orbit","Rings","Wave","Bars","Blob","Cube","Spiral","Bar","Grid"],"mappings":"qHAGaA,EAAkB,CAC7B,SACA,QACA,QACA,OACA,OACA,OACA,OACA,SACA,MACA,MACF,EAKMC,EAAuC,CAC3C,OAAQ,EACR,MAAO,EACP,MAAO,EACP,KAAM,EACN,KAAM,EACN,KAAM,EACN,KAAM,EACN,OAAQ,EACR,IAAK,EACL,KAAM,CACR,EAkBMC,EAAO,CAACC,EAAgCC,IAC5C,OAAOD,GAAM,SAAW,GAAGA,CAAC,GAAGC,CAAM,GAAKD,EAErC,SAASE,EAAO,CACrB,QAAAC,EAAU,SACV,KAAAC,EAAO,GACP,MAAAC,EAAQ,EACR,OAAAC,EACA,MAAAC,EAAQ,UACR,UAAAC,EACA,MAAAC,EACA,GAAGC,CACL,EAAgB,CACd,MAAMC,EAA2D,CAC/D,SAAUZ,EAAKK,EAAM,IAAI,EACzB,UAAWL,EAAKM,EAAO,GAAG,CAAA,EAGxBC,GAAA,MAAAA,EAAQ,SAEVK,EAAK,MAAM,EAAIL,EAAO,CAAC,EACvBK,EAAK,MAAM,EAAIL,EAAO,EAAIA,EAAO,MAAM,EACvCK,EAAK,MAAM,EAAIL,EAAO,EAAIA,EAAO,MAAM,GAGzC,MAAMM,EAAQd,EAAMK,CAAO,EAE3B,OACEU,EAAAA,IAAC,MAAA,CACE,GAAGH,EACJ,UAAW,CAAC,MAAO,QAAQP,CAAO,GAAIK,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EACzE,MAAO,CAAE,GAAGG,EAAM,GAAGF,CAAA,EACrB,KAAMF,EAAQ,SAAW,OACzB,aAAYA,GAAS,OACrB,cAAaA,EAAQ,OAAY,GAEhC,SAAA,MAAM,KAAK,CAAE,OAAQK,CAAA,EAAS,CAACE,EAAGC,IACjCF,EAAAA,IAAC,OAAA,CAAA,EAAUE,CAAG,CACf,CAAA,CAAA,CAGP,CAKO,MAAMC,EAAUC,GAAoBJ,MAACX,GAAO,QAAQ,SAAU,GAAGe,CAAA,CAAG,EAC9DC,EAAUD,GAAoBJ,MAACX,GAAO,QAAQ,QAAU,GAAGe,CAAA,CAAG,EAC9DE,EAAUF,GAAoBJ,MAACX,GAAO,QAAQ,QAAU,GAAGe,CAAA,CAAG,EAC9DG,EAAUH,GAAoBJ,MAACX,GAAO,QAAQ,OAAU,GAAGe,CAAA,CAAG,EAC9DI,EAAUJ,GAAoBJ,MAACX,GAAO,QAAQ,OAAU,GAAGe,CAAA,CAAG,EAC9DK,EAAUL,GAAoBJ,MAACX,GAAO,QAAQ,OAAU,GAAGe,CAAA,CAAG,EAC9DM,EAAUN,GAAoBJ,MAACX,GAAO,QAAQ,OAAU,GAAGe,CAAA,CAAG,EAC9DO,EAAUP,GAAoBJ,MAACX,GAAO,QAAQ,SAAU,GAAGe,CAAA,CAAG,EAC9DQ,EAAUR,GAAoBJ,MAACX,GAAO,QAAQ,MAAU,GAAGe,CAAA,CAAG,EAC9DS,EAAUT,GAAoBJ,MAACX,GAAO,QAAQ,OAAU,GAAGe,CAAA,CAAG"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/variants.ts","../src/Loader.tsx"],"sourcesContent":["/**\n * The single source of truth for every loader.\n * `id` must match a `.ldr--<id>` class in ./styles, and `cells` is how many\n * <span> children that variant's CSS expects.\n */\nexport const VARIANTS = [\n // ---- Spinners ----\n { id: \"aurora\", label: \"Aurora\", group: \"Spinners\", cells: 0 },\n { id: \"spiral\", label: \"Spiral\", group: \"Spinners\", cells: 0 },\n { id: \"ring-dash\", label: \"Ring Dash\", group: \"Spinners\", cells: 0 },\n { id: \"ring-gap\", label: \"Ring Gap\", group: \"Spinners\", cells: 0 },\n { id: \"comet\", label: \"Comet\", group: \"Spinners\", cells: 1 },\n { id: \"arc-trio\", label: \"Arc Trio\", group: \"Spinners\", cells: 3 },\n { id: \"halo\", label: \"Halo\", group: \"Spinners\", cells: 1 },\n { id: \"sweep\", label: \"Sweep\", group: \"Spinners\", cells: 0 },\n { id: \"dot-ring\", label: \"Dot Ring\", group: \"Spinners\", cells: 8 },\n { id: \"petal\", label: \"Petal\", group: \"Spinners\", cells: 8 },\n // ---- Dots ----\n { id: \"wave\", label: \"Wave\", group: \"Dots\", cells: 5 },\n { id: \"orbit\", label: \"Orbit\", group: \"Dots\", cells: 3 },\n { id: \"bounce\", label: \"Bounce\", group: \"Dots\", cells: 3 },\n { id: \"fade-dots\", label: \"Fade Dots\", group: \"Dots\", cells: 3 },\n { id: \"pulse-dots\", label: \"Pulse Dots\", group: \"Dots\", cells: 3 },\n { id: \"typing\", label: \"Typing\", group: \"Dots\", cells: 3 },\n { id: \"chase\", label: \"Chase\", group: \"Dots\", cells: 6 },\n { id: \"snake\", label: \"Snake\", group: \"Dots\", cells: 5 },\n { id: \"swap\", label: \"Swap\", group: \"Dots\", cells: 2 },\n { id: \"juggle\", label: \"Juggle\", group: \"Dots\", cells: 3 },\n // ---- Bars ----\n { id: \"bars\", label: \"Bars\", group: \"Bars\", cells: 5 },\n { id: \"ladder\", label: \"Ladder\", group: \"Bars\", cells: 4 },\n { id: \"stretch\", label: \"Stretch\", group: \"Bars\", cells: 5 },\n { id: \"flip-bars\", label: \"Flip Bars\", group: \"Bars\", cells: 5 },\n { id: \"slide-bars\", label: \"Slide Bars\", group: \"Bars\", cells: 3 },\n { id: \"drop-bars\", label: \"Drop Bars\", group: \"Bars\", cells: 5 },\n { id: \"meter\", label: \"Meter\", group: \"Bars\", cells: 5 },\n { id: \"wave-bars\", label: \"Wave Bars\", group: \"Bars\", cells: 7 },\n { id: \"split-bars\", label: \"Split Bars\", group: \"Bars\", cells: 4 },\n { id: \"scan-bars\", label: \"Scan Bars\", group: \"Bars\", cells: 6 },\n // ---- Shapes ----\n { id: \"blob\", label: \"Blob\", group: \"Shapes\", cells: 0 },\n { id: \"cube\", label: \"Cube\", group: \"Shapes\", cells: 2 },\n { id: \"triangle\", label: \"Triangle\", group: \"Shapes\", cells: 0 },\n { id: \"hexagon\", label: \"Hexagon\", group: \"Shapes\", cells: 0 },\n { id: \"diamond\", label: \"Diamond\", group: \"Shapes\", cells: 0 },\n { id: \"star\", label: \"Star\", group: \"Shapes\", cells: 0 },\n { id: \"squircle\", label: \"Squircle\", group: \"Shapes\", cells: 0 },\n { id: \"folding\", label: \"Folding\", group: \"Shapes\", cells: 4 },\n { id: \"pentagon\", label: \"Pentagon\", group: \"Shapes\", cells: 0 },\n { id: \"shape-shift\", label: \"Shape Shift\", group: \"Shapes\", cells: 0 },\n // ---- Progress ----\n { id: \"bar\", label: \"Bar\", group: \"Progress\", cells: 0 },\n { id: \"bar-stripes\", label: \"Bar Stripes\", group: \"Progress\", cells: 0 },\n { id: \"bar-dual\", label: \"Bar Dual\", group: \"Progress\", cells: 0 },\n { id: \"bar-segments\", label: \"Bar Segments\", group: \"Progress\", cells: 5 },\n { id: \"bar-pill\", label: \"Bar Pill\", group: \"Progress\", cells: 0 },\n { id: \"bar-glow\", label: \"Bar Glow\", group: \"Progress\", cells: 0 },\n { id: \"bar-wave\", label: \"Bar Wave\", group: \"Progress\", cells: 0 },\n { id: \"bar-dots\", label: \"Bar Dots\", group: \"Progress\", cells: 5 },\n { id: \"bar-snake\", label: \"Bar Snake\", group: \"Progress\", cells: 0 },\n { id: \"bar-fill\", label: \"Bar Fill\", group: \"Progress\", cells: 0 },\n // ---- Grids ----\n { id: \"grid\", label: \"Grid\", group: \"Grids\", cells: 9 },\n { id: \"checker\", label: \"Checker\", group: \"Grids\", cells: 9 },\n { id: \"cascade\", label: \"Cascade\", group: \"Grids\", cells: 9 },\n { id: \"tiles\", label: \"Tiles\", group: \"Grids\", cells: 9 },\n { id: \"pixel\", label: \"Pixel\", group: \"Grids\", cells: 16 },\n { id: \"matrix\", label: \"Matrix\", group: \"Grids\", cells: 9 },\n { id: \"mosaic\", label: \"Mosaic\", group: \"Grids\", cells: 9 },\n { id: \"ripple-grid\", label: \"Ripple Grid\", group: \"Grids\", cells: 9 },\n { id: \"domino\", label: \"Domino\", group: \"Grids\", cells: 9 },\n { id: \"sparkle\", label: \"Sparkle\", group: \"Grids\", cells: 9 },\n // ---- Pulses ----\n { id: \"rings\", label: \"Rings\", group: \"Pulses\", cells: 3 },\n { id: \"radar\", label: \"Radar\", group: \"Pulses\", cells: 2 },\n { id: \"sonar\", label: \"Sonar\", group: \"Pulses\", cells: 3 },\n { id: \"echo\", label: \"Echo\", group: \"Pulses\", cells: 3 },\n { id: \"shockwave\", label: \"Shockwave\", group: \"Pulses\", cells: 2 },\n { id: \"bloom\", label: \"Bloom\", group: \"Pulses\", cells: 3 },\n { id: \"droplet\", label: \"Droplet\", group: \"Pulses\", cells: 2 },\n { id: \"concentric\", label: \"Concentric\", group: \"Pulses\", cells: 3 },\n { id: \"aura\", label: \"Aura\", group: \"Pulses\", cells: 1 },\n { id: \"beacon\", label: \"Beacon\", group: \"Pulses\", cells: 2 },\n // ---- Organic ----\n { id: \"heart\", label: \"Heart\", group: \"Organic\", cells: 0 },\n { id: \"moon\", label: \"Moon\", group: \"Organic\", cells: 0 },\n { id: \"sun\", label: \"Sun\", group: \"Organic\", cells: 8 },\n { id: \"flame\", label: \"Flame\", group: \"Organic\", cells: 0 },\n { id: \"bubble\", label: \"Bubble\", group: \"Organic\", cells: 3 },\n { id: \"jelly\", label: \"Jelly\", group: \"Organic\", cells: 0 },\n { id: \"spring\", label: \"Spring\", group: \"Organic\", cells: 0 },\n { id: \"float\", label: \"Float\", group: \"Organic\", cells: 1 },\n { id: \"leaf\", label: \"Leaf\", group: \"Organic\", cells: 0 },\n { id: \"windmill\", label: \"Windmill\", group: \"Organic\", cells: 4 },\n // ---- Skeletons ----\n { id: \"shimmer\", label: \"Shimmer\", group: \"Skeletons\", cells: 0 },\n { id: \"sk-text\", label: \"Text\", group: \"Skeletons\", cells: 3 },\n { id: \"sk-card\", label: \"Card\", group: \"Skeletons\", cells: 3 },\n { id: \"sk-avatar\", label: \"Avatar\", group: \"Skeletons\", cells: 2 },\n { id: \"sk-image\", label: \"Image\", group: \"Skeletons\", cells: 0 },\n { id: \"sk-list\", label: \"List\", group: \"Skeletons\", cells: 3 },\n { id: \"sk-table\", label: \"Table\", group: \"Skeletons\", cells: 4 },\n { id: \"sk-chip\", label: \"Chips\", group: \"Skeletons\", cells: 3 },\n { id: \"sk-paragraph\", label: \"Paragraph\", group: \"Skeletons\", cells: 4 },\n { id: \"sk-media\", label: \"Media\", group: \"Skeletons\", cells: 2 },\n // ---- Dimensional ----\n { id: \"helix\", label: \"Helix\", group: \"Dimensional\", cells: 8 },\n { id: \"pendulum\", label: \"Pendulum\", group: \"Dimensional\", cells: 5 },\n { id: \"atom\", label: \"Atom\", group: \"Dimensional\", cells: 3 },\n { id: \"gyro\", label: \"Gyro\", group: \"Dimensional\", cells: 3 },\n { id: \"coil\", label: \"Coil\", group: \"Dimensional\", cells: 5 },\n { id: \"vortex\", label: \"Vortex\", group: \"Dimensional\", cells: 4 },\n { id: \"prism\", label: \"Prism\", group: \"Dimensional\", cells: 3 },\n { id: \"torus\", label: \"Torus\", group: \"Dimensional\", cells: 0 },\n { id: \"cylinder\", label: \"Cylinder\", group: \"Dimensional\", cells: 4 },\n { id: \"galaxy\", label: \"Galaxy\", group: \"Dimensional\", cells: 6 },\n] as const;\n\nexport const GROUPS = [\n { name: \"Spinners\", description: \"Rings and arcs — the classic shape, modernised.\" },\n { name: \"Dots\", description: \"Small, quiet, and good inline with text.\" },\n { name: \"Bars\", description: \"Equalizer-style motion with a strong rhythm.\" },\n { name: \"Shapes\", description: \"Geometry that morphs, folds, and turns.\" },\n { name: \"Progress\", description: \"Wide, indeterminate tracks for page and upload states.\" },\n { name: \"Grids\", description: \"Cell fields that pulse, flip, and cascade.\" },\n { name: \"Pulses\", description: \"Expanding rings for live, waiting, or listening states.\" },\n { name: \"Organic\", description: \"Playful, physical motion with personality.\" },\n { name: \"Skeletons\", description: \"Content-shaped placeholders — use these over spinners for page loads.\" },\n { name: \"Dimensional\", description: \"Depth, 3D rotation, and orbital motion.\" },\n] as const;\n\nexport type LoaderVariant = (typeof VARIANTS)[number][\"id\"];\nexport type LoaderGroup = (typeof GROUPS)[number][\"name\"];\nexport type VariantMeta = (typeof VARIANTS)[number];\n","import type { CSSProperties, HTMLAttributes } from \"react\";\nimport { VARIANTS, type LoaderVariant } from \"./variants\";\nimport \"./loaders.css\";\n\nexport { VARIANTS, GROUPS } from \"./variants\";\nexport type { LoaderVariant, LoaderGroup, VariantMeta } from \"./variants\";\n\n/** Every variant id, in display order. */\nexport const LOADER_VARIANTS = VARIANTS.map((v) => v.id) as readonly LoaderVariant[];\n\n/** How many <span> children each variant's CSS expects. */\nconst CELLS = Object.fromEntries(VARIANTS.map((v) => [v.id, v.cells])) as Record<\n LoaderVariant,\n number\n>;\n\nexport interface LoaderProps extends Omit<HTMLAttributes<HTMLDivElement>, \"color\"> {\n /** Which loader to render. @default \"aurora\" */\n variant?: LoaderVariant;\n /** Box size. A number is treated as pixels. @default 48 */\n size?: number | string;\n /** Base animation duration. A number is treated as seconds. @default 1 */\n speed?: number | string;\n /**\n * One to three colors. Fewer than three are cycled, so a single color still\n * produces a coherent (monochrome) loader.\n */\n colors?: string[];\n /** Announced to screen readers. Pass `null` to render the loader as decorative. */\n label?: string | null;\n}\n\nconst unit = (v: number | string | undefined, suffix: string) =>\n typeof v === \"number\" ? `${v}${suffix}` : v;\n\nexport function Loader({\n variant = \"aurora\",\n size = 48,\n speed = 1,\n colors,\n label = \"Loading\",\n className,\n style,\n ...rest\n}: LoaderProps) {\n const vars: CSSProperties & Record<string, string | undefined> = {\n \"--size\": unit(size, \"px\"),\n \"--speed\": unit(speed, \"s\"),\n };\n\n if (colors?.length) {\n // Cycle whatever was given across the three slots the CSS reads.\n vars[\"--c1\"] = colors[0];\n vars[\"--c2\"] = colors[1 % colors.length];\n vars[\"--c3\"] = colors[2 % colors.length];\n }\n\n return (\n <div\n {...rest}\n className={[\"ldr\", `ldr--${variant}`, className].filter(Boolean).join(\" \")}\n style={{ ...vars, ...style }}\n role={label ? \"status\" : undefined}\n aria-label={label ?? undefined}\n aria-hidden={label ? undefined : true}\n >\n {Array.from({ length: CELLS[variant] ?? 0 }, (_, i) => (\n <span key={i} />\n ))}\n </div>\n );\n}\n\n/**\n * Named wrappers for the original ten variants, kept for backward compatibility\n * with 1.0.x. The other 90 are reached through `<Loader variant=\"…\" />` — a hundred\n * named exports would bloat the API surface for no real gain.\n */\ntype VariantProps = Omit<LoaderProps, \"variant\">;\n\nexport const Aurora = (p: VariantProps) => <Loader variant=\"aurora\" {...p} />;\nexport const Orbit = (p: VariantProps) => <Loader variant=\"orbit\" {...p} />;\nexport const Rings = (p: VariantProps) => <Loader variant=\"rings\" {...p} />;\nexport const Wave = (p: VariantProps) => <Loader variant=\"wave\" {...p} />;\nexport const Bars = (p: VariantProps) => <Loader variant=\"bars\" {...p} />;\nexport const Blob = (p: VariantProps) => <Loader variant=\"blob\" {...p} />;\nexport const Cube = (p: VariantProps) => <Loader variant=\"cube\" {...p} />;\nexport const Spiral = (p: VariantProps) => <Loader variant=\"spiral\" {...p} />;\nexport const Bar = (p: VariantProps) => <Loader variant=\"bar\" {...p} />;\nexport const Grid = (p: VariantProps) => <Loader variant=\"grid\" {...p} />;\n"],"names":["VARIANTS","GROUPS","LOADER_VARIANTS","v","CELLS","unit","suffix","Loader","variant","size","speed","colors","label","className","style","rest","vars","jsx","_","i","Aurora","p","Orbit","Rings","Wave","Bars","Blob","Cube","Spiral","Bar","Grid"],"mappings":"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"}