not-a-spinner 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,186 @@
1
+ # not-a-spinner
2
+
3
+ > Because modern AI doesn't spin, it thinks.
4
+
5
+ A lightweight React component that replaces loading spinners with rotating AI-style thinking phrases. Ships with 210+ built-in phrases across 7 languages, 4 animation styles, and optional LLM-generated messages.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install not-a-spinner
11
+ # or
12
+ yarn add not-a-spinner
13
+ # or
14
+ pnpm add not-a-spinner
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ **1. Import the CSS once** (in your root layout or entry point):
20
+
21
+ ```tsx
22
+ import "not-a-spinner/styles.css"
23
+ ```
24
+
25
+ **2. Use the component:**
26
+
27
+ ```tsx
28
+ "use client"
29
+ import { NotASpinner } from "not-a-spinner"
30
+
31
+ export function MyLoader() {
32
+ return <NotASpinner />
33
+ }
34
+ ```
35
+
36
+ That's it. You get rotating English phrases with a fade animation and pulsing dots.
37
+
38
+ ## Examples
39
+
40
+ ```tsx
41
+ // Different animations
42
+ <NotASpinner animation="fade" /> // crossfade (default)
43
+ <NotASpinner animation="typewriter" /> // character-by-character with cursor
44
+ <NotASpinner animation="slide" /> // slide up transition
45
+ <NotASpinner animation="blur" /> // blur in/out
46
+
47
+ // Sizes
48
+ <NotASpinner size="sm" />
49
+ <NotASpinner size="default" />
50
+ <NotASpinner size="lg" />
51
+
52
+ // Languages (30 phrases each)
53
+ <NotASpinner locale="en" /> // English (default)
54
+ <NotASpinner locale="zh" /> // 中文
55
+ <NotASpinner locale="ja" /> // 日本語
56
+ <NotASpinner locale="es" /> // Español
57
+ <NotASpinner locale="fr" /> // Français
58
+ <NotASpinner locale="de" /> // Deutsch
59
+ <NotASpinner locale="ko" /> // 한국어
60
+
61
+ // Custom messages
62
+ <NotASpinner messages={["Crunching numbers", "Consulting the oracle", "Almost there"]} />
63
+
64
+ // Disable dots
65
+ <NotASpinner dots={false} />
66
+
67
+ // Faster rotation (ms)
68
+ <NotASpinner interval={1500} />
69
+
70
+ // Combine options
71
+ <NotASpinner animation="typewriter" locale="ja" size="lg" dots={false} />
72
+ ```
73
+
74
+ ## Props
75
+
76
+ | Prop | Type | Default | Description |
77
+ |------|------|---------|-------------|
78
+ | `animation` | `"fade" \| "typewriter" \| "slide" \| "blur"` | `"fade"` | Text transition style |
79
+ | `size` | `"sm" \| "default" \| "lg"` | `"default"` | Font size |
80
+ | `locale` | `"en" \| "zh" \| "ja" \| "es" \| "fr" \| "de" \| "ko"` | `"en"` | Built-in phrase language |
81
+ | `messages` | `string[]` | — | Custom phrases (overrides locale) |
82
+ | `fetchPhrase` | `() => Promise<string>` | — | Async phrase fetcher for LLM integration |
83
+ | `interval` | `number` | `3000` | Rotation speed in ms |
84
+ | `dots` | `boolean` | `true` | Show trailing `...` |
85
+ | `className` | `string` | — | Additional CSS classes (merged via `cn()`) |
86
+
87
+ ## LLM-Generated Phrases
88
+
89
+ Generate fresh phrases on the fly using OpenAI or Anthropic.
90
+
91
+ **1. Create a server route:**
92
+
93
+ ```ts
94
+ // app/api/thinking/route.ts
95
+ import { createThinkingHandler } from "not-a-spinner/server"
96
+
97
+ const handler = createThinkingHandler({
98
+ provider: "openai", // or "anthropic"
99
+ apiKey: process.env.OPENAI_API_KEY!,
100
+ model: "gpt-4o-mini", // optional
101
+ locale: "en", // optional
102
+ })
103
+
104
+ export const POST = handler
105
+ ```
106
+
107
+ **2. Connect to the component:**
108
+
109
+ ```tsx
110
+ "use client"
111
+ import { NotASpinner, createOpenAIFetcher } from "not-a-spinner"
112
+
113
+ const fetchPhrase = createOpenAIFetcher("/api/thinking")
114
+
115
+ export function MyLoader() {
116
+ return <NotASpinner fetchPhrase={fetchPhrase} animation="typewriter" />
117
+ }
118
+ ```
119
+
120
+ The component starts with built-in phrases immediately and mixes in LLM-generated ones as they arrive. If the API fails, it silently falls back to local phrases.
121
+
122
+ ### Custom Prompt
123
+
124
+ ```ts
125
+ const handler = createThinkingHandler({
126
+ provider: "anthropic",
127
+ apiKey: process.env.ANTHROPIC_API_KEY!,
128
+ systemPrompt: `You generate short, sarcastic loading messages for a developer tool.
129
+ Keep it under 40 characters. Be dry and witty. Output only the phrase.`,
130
+ })
131
+ ```
132
+
133
+ ### Built-in Default Prompt
134
+
135
+ The default prompt instructs the LLM to generate short, funny, nerdy loading messages (under 50 characters) matching the tone of phrases like "Reticulating splines" and "Downloading more RAM". It auto-appends locale-specific instructions with example phrases in each language.
136
+
137
+ ### Bring Your Own Fetcher
138
+
139
+ Skip the server helper entirely — pass any `() => Promise<string>`:
140
+
141
+ ```tsx
142
+ <NotASpinner
143
+ fetchPhrase={async () => {
144
+ const res = await fetch("/your-own-api")
145
+ const data = await res.json()
146
+ return data.text
147
+ }}
148
+ />
149
+ ```
150
+
151
+ ## Styling
152
+
153
+ The component ships pre-compiled CSS with `nas-` prefixed classes — **no Tailwind required**. But if you use Tailwind, you can override styles via `className`:
154
+
155
+ ```tsx
156
+ <NotASpinner className="text-blue-500 text-xl" />
157
+ ```
158
+
159
+ To customize the base color globally, set the CSS variable:
160
+
161
+ ```css
162
+ :root {
163
+ --nas-color: #8b5cf6;
164
+ }
165
+ ```
166
+
167
+ ## Sample Phrases
168
+
169
+ **English**: "Reticulating splines", "Asking the rubber duck", "Downloading more RAM", "Bribing the cache fairy"
170
+
171
+ **中文**: "让AI再想想", "正在炼丹", "正在解开薛定谔的Bug", "偷偷查看答案中"
172
+
173
+ **日本語**: "AIが悩んでいます", "ピクセルを磨き中", "もうちょっと待ってね"
174
+
175
+ **한국어**: "AI가 고민 중", "바쁜 척하는 중", "거의 거의 다 됐어요"
176
+
177
+ Each locale includes 30 curated phrases.
178
+
179
+ ## Requirements
180
+
181
+ - React 18+
182
+ - For LLM features: OpenAI or Anthropic API key
183
+
184
+ ## License
185
+
186
+ MIT