loading-games 1.0.0 → 1.0.1
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 +172 -0
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# ⚡ loading-games
|
|
2
|
+
|
|
3
|
+
> A zero-friction JavaScript library that turns long loading states into playable mini-games — so users engage instead of abandoning.
|
|
4
|
+
|
|
5
|
+
[](https://npmjs.com/package/loading-games)
|
|
6
|
+
[](https://bundlephobia.com/package/loading-games)
|
|
7
|
+
[](./LICENSE)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`loading-games` is a lightweight, **zero-dependency** JavaScript library that lets developers drop playable mini-games into any loading state with a single line of code. When a fetch call, file upload, AI generation, or heavy computation takes longer than expected, instead of showing a spinner users get a fully playable game — and the session continues the moment loading completes.
|
|
12
|
+
|
|
13
|
+
**The Namco idea, finally open-sourced for the web.**
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### React
|
|
20
|
+
```jsx
|
|
21
|
+
import { LoadingGame } from 'loading-games/react'
|
|
22
|
+
|
|
23
|
+
<LoadingGame
|
|
24
|
+
game="snake"
|
|
25
|
+
active={isLoading}
|
|
26
|
+
theme={{ primary: '#6366F1', background: '#0F0F0F' }}
|
|
27
|
+
onScore={(score) => console.log(score)}
|
|
28
|
+
onComplete={() => setShowResult(true)}
|
|
29
|
+
/>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Vanilla JS / Web Component
|
|
33
|
+
```html
|
|
34
|
+
<loading-game game="flappy" active="true"></loading-game>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import 'loading-games'
|
|
39
|
+
|
|
40
|
+
const game = document.querySelector('loading-game')
|
|
41
|
+
game.setAttribute('active', 'true') // start
|
|
42
|
+
game.removeAttribute('active') // stop
|
|
43
|
+
game.theme = { primary: '#E94560', background: '#0F0F0F' }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Vue 3
|
|
47
|
+
```vue
|
|
48
|
+
<script setup>
|
|
49
|
+
import { LoadingGame } from 'loading-games/vue'
|
|
50
|
+
import { ref } from 'vue'
|
|
51
|
+
const isLoading = ref(true)
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<template>
|
|
55
|
+
<LoadingGame game="snake" :active="isLoading" @complete="isLoading = false" />
|
|
56
|
+
</template>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Svelte
|
|
60
|
+
```svelte
|
|
61
|
+
<script>
|
|
62
|
+
import 'loading-games'
|
|
63
|
+
let active = true
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<loading-game game="snake" active={active ? 'true' : undefined}
|
|
67
|
+
on:lg:complete={() => active = false} />
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm install loading-games
|
|
76
|
+
# or
|
|
77
|
+
yarn add loading-games
|
|
78
|
+
# or
|
|
79
|
+
pnpm add loading-games
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**CLI scaffolding (auto-detects framework):**
|
|
83
|
+
```bash
|
|
84
|
+
npx loading-games init
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Games (v1.0)
|
|
90
|
+
|
|
91
|
+
| Game | Controls | Bundle | Status |
|
|
92
|
+
|------|----------|--------|--------|
|
|
93
|
+
| `snake` | Arrow keys / swipe / D-pad | ~4 kB | ✅ Complete |
|
|
94
|
+
| `flappy` | Spacebar / tap | ~5 kB | ✅ Complete |
|
|
95
|
+
| `memory-cards` | Mouse / tap / keyboard | ~4 kB | ✅ Complete |
|
|
96
|
+
| `whack-a-mole` | Mouse / tap / keys 1-9 | ~4 kB | ✅ Complete |
|
|
97
|
+
| `brick-breaker` | Mouse / touch drag | ~6 kB | 🔲 Stub (v1.1) |
|
|
98
|
+
| `2048` | Arrow keys / swipe | ~5 kB | 🔲 Stub (v1.1) |
|
|
99
|
+
| `wordle-lite` | Keyboard / virtual kb | ~7 kB | 🔲 Stub (v1.1) |
|
|
100
|
+
| `asteroids` | Arrow keys + space | ~8 kB | 🔲 Stub (v1.1) |
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Configuration
|
|
105
|
+
|
|
106
|
+
| Prop | Type | Default | Description |
|
|
107
|
+
|------|------|---------|-------------|
|
|
108
|
+
| `game` | `GameName \| 'random'` | `'random'` | Which game to render |
|
|
109
|
+
| `active` | `boolean` | `false` | Starts/stops the game |
|
|
110
|
+
| `theme` | `ThemeObject` | auto-detect | Colors: primary, background, surface, text, accent |
|
|
111
|
+
| `size` | `'sm' \| 'md' \| 'lg' \| 'full'` | `'md'` | Preset sizes. `'full'` overlays viewport |
|
|
112
|
+
| `delay` | `number` (ms) | `800` | Wait before showing game (prevents flash) |
|
|
113
|
+
| `minDisplay` | `number` (ms) | `0` | Minimum display time once shown |
|
|
114
|
+
| `exitAnimation` | `'fade' \| 'slide' \| 'none'` | `'fade'` | How the game disappears |
|
|
115
|
+
| `saveScores` | `boolean` | `true` | Persists personal bests in localStorage |
|
|
116
|
+
| `namespace` | `string` | `undefined` | Scopes score storage per instance |
|
|
117
|
+
| `onScore` | `(score: Score) => void` | — | Fires on every score change |
|
|
118
|
+
| `onGameOver` | `(result: Result) => void` | — | Fires when a game round ends |
|
|
119
|
+
| `onError` | `(err: Error) => void` | — | Fires on loading error; exits game immediately |
|
|
120
|
+
| `onComplete` | `() => void` | — | Fires when exit animation finishes (game fully removed) |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Theming
|
|
125
|
+
|
|
126
|
+
Priority order (highest first):
|
|
127
|
+
1. Explicit `theme` prop/attribute
|
|
128
|
+
2. CSS variables on `:root` — `--lg-primary`, `--lg-background`, `--lg-surface`, `--lg-text`, `--lg-accent`
|
|
129
|
+
3. System `prefers-color-scheme` detection
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Performance Budget
|
|
134
|
+
|
|
135
|
+
- **Core entry point:** < 8 kB gzipped
|
|
136
|
+
- **Per game chunk:** < 10 kB gzipped
|
|
137
|
+
- **Lazy loading:** Games fetched only on first `active=true`
|
|
138
|
+
- **Zero runtime dependencies**
|
|
139
|
+
- **60fps target:** `requestAnimationFrame` only, no DOM thrashing
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Accessibility
|
|
144
|
+
|
|
145
|
+
- `role="application"` + `aria-label` on every canvas
|
|
146
|
+
- Skip link ("Skip game, wait for loading") — always first tab stop
|
|
147
|
+
- `prefers-reduced-motion`: static animated pattern fallback
|
|
148
|
+
- WCAG AA contrast in all default themes
|
|
149
|
+
- Auto-pause on `document.visibilityState = 'hidden'`
|
|
150
|
+
- Virtual D-pad on touch for keyboard-dependent games
|
|
151
|
+
- Min 44×44px tap zones (WCAG 2.5.5 AAA)
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Roadmap
|
|
156
|
+
|
|
157
|
+
| Phase | Timeline | Scope |
|
|
158
|
+
|-------|----------|-------|
|
|
159
|
+
| **v1.0** | Week 1–6 | Core lib, 8 games, React/Vue/Svelte, TypeScript, demo site, PH launch |
|
|
160
|
+
| **v1.1** | Week 7–10 | Custom game plugin API, shared leaderboard, Angular wrapper |
|
|
161
|
+
| **v1.2** | Week 11–14 | Analytics hook, WCAG AA certification, 3 community games |
|
|
162
|
+
| **v2.0** | Month 4+ | Multiplayer scores, game marketplace, React Native (Expo) |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Contributing
|
|
167
|
+
|
|
168
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for game contribution guidelines and the game template.
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loading-games",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Playable mini-games that replace loading spinners",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"files": [
|
|
49
|
-
"dist"
|
|
49
|
+
"dist",
|
|
50
|
+
"README.md"
|
|
50
51
|
],
|
|
51
52
|
"sideEffects": [
|
|
52
53
|
"src/index.ts",
|