{"_id":"gradient-spin","name":"gradient-spin","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"gradient-spin","version":"0.1.0","description":"A zero-dependency React matrix loading spinner — a grid of cells swept by a gradient wavefront (arrow, diagonal, snake, ripple). One CSS keyframe, compositor-only, no CSS import.","type":"module","packageManager":"pnpm@11.3.0","sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"build":"tsup && node scripts/add-use-client.mjs","dev":"tsup --watch","typecheck":"tsc --noEmit","smoke:pack":"node scripts/smoke-pack.mjs","release:check":"npm run typecheck && npm run smoke:pack && npm pack --dry-run","prepack":"npm run build","prepublishOnly":"npm run release:check"},"keywords":["react","spinner","loader","loading","gradient","grid","matrix","animation","heatgrid","css-animation"],"author":{"name":"ziye"},"license":"MIT","homepage":"https://github.com/BIAsia/gradient-spin#readme","repository":{"type":"git","url":"git+https://github.com/BIAsia/gradient-spin.git"},"bugs":{"url":"https://github.com/BIAsia/gradient-spin/issues"},"peerDependencies":{"react":">=18"},"devDependencies":{"@types/react":"^19.0.0","playwright-core":"^1.61.0","react":"^19.0.0","tsup":"^8.3.0","typescript":"^5.5.0"},"gitHead":"6deabb4842e58e4e2acdecd1ec4954e4f823128f","_id":"gradient-spin@0.1.0","_nodeVersion":"26.0.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-pFUvO/ib5cPbWqGpitnjXJPKaM+oYFoCpM5rmwPl1GyHe+v8j5Z81SnAgNHL8hV3a+Uq2HTeFoDa+4GvbrPMYQ==","shasum":"3ae08bc695385afd197b9878272213dfc8065e37","tarball":"https://registry.npmjs.org/gradient-spin/-/gradient-spin-0.1.0.tgz","fileCount":7,"unpackedSize":32071,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIG5UHI8flZ4qwzzMdNqRekQtBOdccrMpiyH+x5dCepkqAiEAvmxPFBE4la9VRA/7KKMGc1vf/jW+Lxq1sph7cK2qLm8="}]},"_npmUser":{"name":"lzybiasia","email":"lzybiasia@gmail.com"},"directories":{},"maintainers":[{"name":"lzybiasia","email":"lzybiasia@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/gradient-spin_0.1.0_1783519012295_0.8606694223384133"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-08T13:56:52.243Z","0.1.0":"2026-07-08T13:56:52.436Z","modified":"2026-07-08T13:56:52.577Z"},"maintainers":[{"name":"lzybiasia","email":"lzybiasia@gmail.com"}],"description":"A zero-dependency React matrix loading spinner — a grid of cells swept by a gradient wavefront (arrow, diagonal, snake, ripple). One CSS keyframe, compositor-only, no CSS import.","homepage":"https://github.com/BIAsia/gradient-spin#readme","keywords":["react","spinner","loader","loading","gradient","grid","matrix","animation","heatgrid","css-animation"],"repository":{"type":"git","url":"git+https://github.com/BIAsia/gradient-spin.git"},"author":{"name":"ziye"},"bugs":{"url":"https://github.com/BIAsia/gradient-spin/issues"},"license":"MIT","readme":"# gradient-spin\n\nA zero-dependency React matrix loading spinner — a grid of cells swept by a\ngradient wavefront. The cousin of a progress bar's shimmer: cells light up in\n**arrow / diagonal / snake / ripple** patterns, colored by a multi-stop\ngradient sampled in OKLab.\n\n**Live demo → [gradient-spin.vercel.app](https://gradient-spin.vercel.app)**\n· Sister library: [gradient-shimmer](https://github.com/BIAsia/gradient-shimmer)\n(same gradient palettes, for text).\n\n## Why\n\n- **One CSS keyframe, compositor-only.** Every cell shares a single\n  opacity-only animation with a negative per-cell delay (delay = distance\n  function over the grid). The spinner keeps ticking even while the main\n  thread is busy with the work you're waiting for — exactly when a spinner\n  matters.\n- **Steady-state mount.** Negative delays mean the loop is already mid-flight\n  on first paint: no fill-in ramp.\n- **Gradient-true cells.** Colors are sampled from the gradient in **OKLab**\n  (straight sRGB lerp detours through gray). Map it top→bottom like a\n  backdrop (`colorBy=\"row\"`, the default) or give every cell a unique sample\n  along the wave path (`colorBy=\"path\"`).\n- **No CSS import.** Styles are injected once at runtime (`useInsertionEffect`,\n  id-deduped). No Tailwind, no setup, zero runtime dependencies.\n- **Accessible.** `role=\"status\"` + `aria-label`; freezes to a static\n  mid-state under `prefers-reduced-motion`.\n\n## Install\n\n```sh\nnpm i gradient-spin\n```\n\n## Usage\n\n```tsx\nimport { GradientSpin } from \"gradient-spin\"\n\n// Defaults: 3×3, 4px cells, 750ms, \"sunrise\" gradient, arrow-up wave.\n<GradientSpin />\n\n// A chat feed's \"loading older messages\" strip:\n<GradientSpin gradient=\"bay\" pattern=\"snake\" label=\"Loading older messages\" />\n\n// Custom gradient stops:\n<GradientSpin\n  gradient={[\n    { color: \"#B6D3EF\", position: 0 },\n    { color: \"#F888A0\", position: 1 },\n  ]}\n  rows={5}\n  cols={7}\n/>\n```\n\n## Props\n\n| Prop                   | Type                                        | Default      |\n| ---------------------- | ------------------------------------------- | ------------ |\n| `gradient`             | preset name \\| `GradientStop[]`             | `\"sunrise\"`  |\n| `pattern`              | `\"arrow-up\" \\| \"diagonal\" \\| \"snake\" \\| \"ripple\"` | `\"arrow-up\"` |\n| `rows`                 | `number`                                    | `3`          |\n| `cols`                 | `number`                                    | `3`          |\n| `cellSize`             | `number` (px)                               | `4`          |\n| `cellGap`              | `number` (px)                               | `2`          |\n| `cellRadius`           | `number` (px)                               | `1`          |\n| `period`               | `number` (ms per sweep)                     | `750`        |\n| `dim`                  | `number` (0..1 resting opacity)             | `0.1`        |\n| `colorBy`              | `\"path\" \\| \"row\"`                           | `\"row\"`      |\n| `label`                | `string` (aria-label)                       | `\"Loading\"`  |\n| `respectReducedMotion` | `boolean`                                   | `true`       |\n\nPlus any `HTMLAttributes<HTMLSpanElement>` — `className`, `style`, etc.\n\n**Presets** (shared with gradient-shimmer): `sunrise` · `bubble` · `peach` ·\n`tonic` · `mint` · `spring` · `twilight` · `bay`. Exported as\n`gradientPresets`; the OKLab sampler is exported as `sampleGradient(stops, t)`.\n\n## How the patterns work\n\nEach pattern is a distance function `d(row, col)`; cells at equal distance\nform the wavefront, and a cell's animation delay is `-(d / (max + 1)) ×\nperiod`:\n\n- **arrow-up** — chevron fold across the center column: `(rows−1−row) + |col−center|`\n- **ripple** — Chebyshev distance from the center (expanding square rings)\n- **diagonal** & **snake** — travel patterns (anti-diagonal `row + col`;\n  boustrophedon path from the bottom-left). Their distance is tiled into\n  repeating bands (`d % SCROLL_BAND`) so the wave scrolls seamlessly and loops\n  without teleporting from one corner back to the other.\n\n## Development\n\n```sh\npnpm install\npnpm --dir site dev   # demo site at localhost:3021, aliased to library source\npnpm build            # tsup → dist (ESM + CJS + dts)\npnpm smoke:pack       # pack the tarball into a temp React 18 consumer\n```\n\n## License\n\nMIT © [ziye](https://x.com/mona_biasia)\n","readmeFilename":"README.md","_rev":"1-91a167faac9253b7690704dafa855412"}