unicode-animations 0.1.0 → 0.1.2
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 +151 -0
- package/package.json +8 -2
- package/scripts/postinstall.js +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# unicode-animations
|
|
2
|
+
|
|
3
|
+
Unicode spinner animations as raw frame data — no dependencies, works everywhere.
|
|
4
|
+
|
|
5
|
+
## Preview
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
braille ⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏
|
|
9
|
+
arc ◜ ◠ ◝ ◞ ◡ ◟
|
|
10
|
+
halfmoon ◐ ◓ ◑ ◒
|
|
11
|
+
blocks ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▇ ▆ ▅ ▄ ▃ ▂
|
|
12
|
+
line | / — \
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install unicode-animations
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
// ESM
|
|
25
|
+
import spinners from 'unicode-animations';
|
|
26
|
+
|
|
27
|
+
// CJS
|
|
28
|
+
const spinners = require('unicode-animations');
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Each spinner is a `{ frames: string[], interval: number }` object.
|
|
32
|
+
|
|
33
|
+
## Terminal example
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import spinners from 'unicode-animations';
|
|
37
|
+
|
|
38
|
+
const { frames, interval } = spinners.braille;
|
|
39
|
+
let i = 0;
|
|
40
|
+
|
|
41
|
+
const timer = setInterval(() => {
|
|
42
|
+
process.stdout.write(`\r${frames[i++ % frames.length]} Loading...`);
|
|
43
|
+
}, interval);
|
|
44
|
+
|
|
45
|
+
// Stop after 3s
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
clearInterval(timer);
|
|
48
|
+
process.stdout.write('\r✔ Done! \n');
|
|
49
|
+
}, 3000);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Browser example
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
import spinners from 'unicode-animations';
|
|
56
|
+
|
|
57
|
+
const el = document.getElementById('spinner');
|
|
58
|
+
const { frames, interval } = spinners.arc;
|
|
59
|
+
let i = 0;
|
|
60
|
+
|
|
61
|
+
setInterval(() => {
|
|
62
|
+
el.textContent = frames[i++ % frames.length];
|
|
63
|
+
}, interval);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## All spinners
|
|
67
|
+
|
|
68
|
+
### Classic braille
|
|
69
|
+
|
|
70
|
+
| Name | Preview | Interval |
|
|
71
|
+
|------|---------|----------|
|
|
72
|
+
| `braille` | `⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏` | 80ms |
|
|
73
|
+
| `braillewave` | `⠁⠂⠄⡀⢀⠠⠐⠈` → `⠂⠄⡀⢀⠠⠐⠈⠁` | 100ms |
|
|
74
|
+
| `dna` | `⠋⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄` → `⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠠` | 80ms |
|
|
75
|
+
|
|
76
|
+
### Grid animations (braille)
|
|
77
|
+
|
|
78
|
+
| Name | Frames | Interval |
|
|
79
|
+
|------|--------|----------|
|
|
80
|
+
| `scan` | 10 | 70ms |
|
|
81
|
+
| `rain` | 12 | 100ms |
|
|
82
|
+
| `scanline` | 6 | 120ms |
|
|
83
|
+
| `pulse` | 5 | 180ms |
|
|
84
|
+
| `snake` | 16 | 80ms |
|
|
85
|
+
| `sparkle` | 6 | 150ms |
|
|
86
|
+
| `cascade` | 12 | 60ms |
|
|
87
|
+
| `columns` | 26 | 60ms |
|
|
88
|
+
| `orbit` | 8 | 100ms |
|
|
89
|
+
| `breathe` | 17 | 100ms |
|
|
90
|
+
| `waverows` | 16 | 90ms |
|
|
91
|
+
| `checkerboard` | 4 | 250ms |
|
|
92
|
+
| `helix` | 16 | 80ms |
|
|
93
|
+
| `fillsweep` | 11 | 100ms |
|
|
94
|
+
| `diagswipe` | 16 | 60ms |
|
|
95
|
+
|
|
96
|
+
### Non-braille classics
|
|
97
|
+
|
|
98
|
+
| Name | Preview | Interval |
|
|
99
|
+
|------|---------|----------|
|
|
100
|
+
| `arc` | `◜ ◠ ◝ ◞ ◡ ◟` | 100ms |
|
|
101
|
+
| `halfmoon` | `◐ ◓ ◑ ◒` | 180ms |
|
|
102
|
+
| `line` | `\| / — \` | 100ms |
|
|
103
|
+
| `blocks` | `▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▇ ▆ ▅ ▄ ▃ ▂` | 100ms |
|
|
104
|
+
|
|
105
|
+
## Custom spinners
|
|
106
|
+
|
|
107
|
+
Create your own braille spinners using the grid utilities:
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
import { gridToBraille, makeGrid } from 'unicode-animations';
|
|
111
|
+
|
|
112
|
+
// Create a 4-row × 4-col grid
|
|
113
|
+
const grid = makeGrid(4, 4);
|
|
114
|
+
grid[0][0] = true;
|
|
115
|
+
grid[1][1] = true;
|
|
116
|
+
grid[2][2] = true;
|
|
117
|
+
grid[3][3] = true;
|
|
118
|
+
|
|
119
|
+
console.log(gridToBraille(grid)); // diagonal braille pattern
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`makeGrid(rows, cols)` returns a `boolean[][]`. Set cells to `true` to raise dots. `gridToBraille(grid)` converts it to a braille string (2 dot-columns per character).
|
|
123
|
+
|
|
124
|
+
## API
|
|
125
|
+
|
|
126
|
+
### `Spinner`
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
interface Spinner {
|
|
130
|
+
readonly frames: readonly string[];
|
|
131
|
+
readonly interval: number;
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Exports from `'unicode-animations'`
|
|
136
|
+
|
|
137
|
+
| Export | Type |
|
|
138
|
+
|--------|------|
|
|
139
|
+
| `default` / `spinners` | `Record<BrailleSpinnerName, Spinner>` |
|
|
140
|
+
| `gridToBraille(grid)` | `(boolean[][]) => string` |
|
|
141
|
+
| `makeGrid(rows, cols)` | `(number, number) => boolean[][]` |
|
|
142
|
+
| `Spinner` | TypeScript interface |
|
|
143
|
+
| `BrailleSpinnerName` | Union type of all 22 spinner names |
|
|
144
|
+
|
|
145
|
+
### Exports from `'unicode-animations/braille'`
|
|
146
|
+
|
|
147
|
+
Same as above — the main entrypoint re-exports everything from the braille module.
|
|
148
|
+
|
|
149
|
+
## License
|
|
150
|
+
|
|
151
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unicode-animations",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Unicode spinner animations as raw frame data",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -16,12 +16,18 @@
|
|
|
16
16
|
"main": "./dist/index.cjs",
|
|
17
17
|
"module": "./dist/index.js",
|
|
18
18
|
"types": "./dist/index.d.ts",
|
|
19
|
-
"files": ["dist"],
|
|
19
|
+
"files": ["dist", "scripts"],
|
|
20
20
|
"sideEffects": false,
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "tsup",
|
|
23
|
+
"postinstall": "node scripts/postinstall.js",
|
|
23
24
|
"prepublishOnly": "npm run build"
|
|
24
25
|
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/gunnargray-dev/unicode-animations.git"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/gunnargray-dev/unicode-animations",
|
|
25
31
|
"keywords": ["braille", "spinner", "unicode", "animation", "loading", "cli", "terminal"],
|
|
26
32
|
"license": "MIT",
|
|
27
33
|
"devDependencies": {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Postinstall animation — showcases a few spinners side-by-side for ~1.5s
|
|
4
|
+
// Skips gracefully in CI or non-interactive environments
|
|
5
|
+
|
|
6
|
+
// npm 7+ pipes lifecycle script stdio, so isTTY is always false.
|
|
7
|
+
// Use stderr (usually still connected to terminal) for the animation.
|
|
8
|
+
// Skip in CI or when there's genuinely no terminal.
|
|
9
|
+
const ci = process.env.CI || process.env.CONTINUOUS_INTEGRATION || process.env.GITHUB_ACTIONS;
|
|
10
|
+
const out = process.stderr.isTTY ? process.stderr : process.stdout.isTTY ? process.stdout : null;
|
|
11
|
+
if (ci || !out) process.exit(0);
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const DURATION = 1500;
|
|
15
|
+
const INTERVAL = 80;
|
|
16
|
+
|
|
17
|
+
// Inline a few single-char spinners to avoid importing dist (may not exist yet)
|
|
18
|
+
const spinners = [
|
|
19
|
+
{ frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] }, // braille
|
|
20
|
+
{ frames: ['◜', '◠', '◝', '◞', '◡', '◟'] }, // arc
|
|
21
|
+
{ frames: ['◐', '◓', '◑', '◒'] }, // halfmoon
|
|
22
|
+
{ frames: ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█', '▇', '▆', '▅', '▄', '▃', '▂'] }, // blocks
|
|
23
|
+
{ frames: ['|', '/', '—', '\\'] }, // line
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const hide = '\x1B[?25l';
|
|
27
|
+
const show = '\x1B[?25h';
|
|
28
|
+
const clearLine = '\x1B[2K\r';
|
|
29
|
+
const bold = '\x1B[1m';
|
|
30
|
+
const green = '\x1B[32m';
|
|
31
|
+
const reset = '\x1B[0m';
|
|
32
|
+
|
|
33
|
+
out.write(hide);
|
|
34
|
+
|
|
35
|
+
const cleanup = () => out.write(show);
|
|
36
|
+
process.on('SIGINT', () => { cleanup(); process.exit(0); });
|
|
37
|
+
|
|
38
|
+
let tick = 0;
|
|
39
|
+
const start = Date.now();
|
|
40
|
+
|
|
41
|
+
const timer = setInterval(() => {
|
|
42
|
+
if (Date.now() - start >= DURATION) {
|
|
43
|
+
clearInterval(timer);
|
|
44
|
+
const done = `${clearLine} ${green}${bold}✔${reset} ${bold}unicode-animations${reset} — 22 spinners ready\n`;
|
|
45
|
+
out.write(done);
|
|
46
|
+
cleanup();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const chars = spinners.map(s => s.frames[tick % s.frames.length]);
|
|
51
|
+
out.write(`${clearLine} ${chars.join(' ')}`);
|
|
52
|
+
tick++;
|
|
53
|
+
}, INTERVAL);
|
|
54
|
+
} catch {
|
|
55
|
+
// Never block install
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|