@adiakys/feeling-lucky 0.0.0-stage → 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.
Files changed (119) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +211 -2
  3. package/dist/config/resolve.d.ts +4 -0
  4. package/dist/config/types.d.ts +56 -0
  5. package/dist/de-Cp-ILcpM.js +452 -0
  6. package/dist/developer/panel.d.ts +60 -0
  7. package/dist/developer/rig.d.ts +2 -0
  8. package/dist/developer/settings.d.ts +29 -0
  9. package/dist/engine/awards.d.ts +12 -0
  10. package/dist/engine/cards.d.ts +44 -0
  11. package/dist/engine/cashout.d.ts +32 -0
  12. package/dist/engine/outcome.d.ts +13 -0
  13. package/dist/engine/pachinko.d.ts +58 -0
  14. package/dist/engine/random.d.ts +6 -0
  15. package/dist/engine/rig.d.ts +28 -0
  16. package/dist/engine/roulette.d.ts +53 -0
  17. package/dist/engine/scratch.d.ts +40 -0
  18. package/dist/engine/slot.d.ts +19 -0
  19. package/dist/engine/themes.d.ts +30 -0
  20. package/dist/engine/tiers.d.ts +64 -0
  21. package/dist/engine/wheel.d.ts +47 -0
  22. package/dist/es-DHZIstf4.js +452 -0
  23. package/dist/feeling-lucky.iife.js +1478 -0
  24. package/dist/feeling-lucky.js +63 -0
  25. package/dist/fr-BPFoerSF.js +452 -0
  26. package/dist/games/blackjack/blackjack.d.ts +47 -0
  27. package/dist/games/cards/card.d.ts +5 -0
  28. package/dist/games/cards/table.d.ts +8 -0
  29. package/dist/games/holdem/holdem.d.ts +27 -0
  30. package/dist/games/index.d.ts +9 -0
  31. package/dist/games/pachinko/pachinko.d.ts +53 -0
  32. package/dist/games/roulette/roulette.d.ts +63 -0
  33. package/dist/games/roulette/table.d.ts +19 -0
  34. package/dist/games/roulette/track.d.ts +18 -0
  35. package/dist/games/roulette/wheel.d.ts +9 -0
  36. package/dist/games/scratch/covers.d.ts +3 -0
  37. package/dist/games/scratch/double.d.ts +3 -0
  38. package/dist/games/scratch/forever.d.ts +3 -0
  39. package/dist/games/scratch/scratch.d.ts +39 -0
  40. package/dist/games/slot/breakaway.d.ts +32 -0
  41. package/dist/games/slot/machine.d.ts +18 -0
  42. package/dist/games/slot/slot.d.ts +32 -0
  43. package/dist/games/slot/takeoff.d.ts +28 -0
  44. package/dist/games/wheel/coin.d.ts +19 -0
  45. package/dist/games/wheel/face.d.ts +18 -0
  46. package/dist/games/wheel/hunt.d.ts +15 -0
  47. package/dist/games/wheel/wheel.d.ts +64 -0
  48. package/dist/i18n-CihzHMU5.js +484 -0
  49. package/dist/index.d.ts +4 -0
  50. package/dist/it-B95CFDto.js +452 -0
  51. package/dist/locales/de/cards.d.ts +68 -0
  52. package/dist/locales/de/developer.d.ts +67 -0
  53. package/dist/locales/de/index.d.ts +2 -0
  54. package/dist/locales/de/pachinko.d.ts +26 -0
  55. package/dist/locales/de/room.d.ts +84 -0
  56. package/dist/locales/de/roulette.d.ts +77 -0
  57. package/dist/locales/de/scratch.d.ts +56 -0
  58. package/dist/locales/de/slot.d.ts +61 -0
  59. package/dist/locales/de/wheel.d.ts +45 -0
  60. package/dist/locales/en/cards.d.ts +68 -0
  61. package/dist/locales/en/developer.d.ts +67 -0
  62. package/dist/locales/en/index.d.ts +2 -0
  63. package/dist/locales/en/pachinko.d.ts +26 -0
  64. package/dist/locales/en/room.d.ts +84 -0
  65. package/dist/locales/en/roulette.d.ts +77 -0
  66. package/dist/locales/en/scratch.d.ts +56 -0
  67. package/dist/locales/en/slot.d.ts +61 -0
  68. package/dist/locales/en/wheel.d.ts +45 -0
  69. package/dist/locales/es/cards.d.ts +68 -0
  70. package/dist/locales/es/developer.d.ts +67 -0
  71. package/dist/locales/es/index.d.ts +2 -0
  72. package/dist/locales/es/pachinko.d.ts +26 -0
  73. package/dist/locales/es/room.d.ts +84 -0
  74. package/dist/locales/es/roulette.d.ts +77 -0
  75. package/dist/locales/es/scratch.d.ts +56 -0
  76. package/dist/locales/es/slot.d.ts +61 -0
  77. package/dist/locales/es/wheel.d.ts +45 -0
  78. package/dist/locales/fr/cards.d.ts +68 -0
  79. package/dist/locales/fr/developer.d.ts +67 -0
  80. package/dist/locales/fr/index.d.ts +2 -0
  81. package/dist/locales/fr/pachinko.d.ts +26 -0
  82. package/dist/locales/fr/room.d.ts +84 -0
  83. package/dist/locales/fr/roulette.d.ts +77 -0
  84. package/dist/locales/fr/scratch.d.ts +56 -0
  85. package/dist/locales/fr/slot.d.ts +61 -0
  86. package/dist/locales/fr/wheel.d.ts +45 -0
  87. package/dist/locales/index.d.ts +7 -0
  88. package/dist/locales/it/cards.d.ts +68 -0
  89. package/dist/locales/it/developer.d.ts +67 -0
  90. package/dist/locales/it/index.d.ts +2 -0
  91. package/dist/locales/it/pachinko.d.ts +26 -0
  92. package/dist/locales/it/room.d.ts +84 -0
  93. package/dist/locales/it/roulette.d.ts +77 -0
  94. package/dist/locales/it/scratch.d.ts +56 -0
  95. package/dist/locales/it/slot.d.ts +61 -0
  96. package/dist/locales/it/wheel.d.ts +45 -0
  97. package/dist/locales/merge.d.ts +2 -0
  98. package/dist/merge-iGSNfZkz.js +10 -0
  99. package/dist/mount-BxDaFww2.js +7034 -0
  100. package/dist/panel-D1hKmQL7.js +530 -0
  101. package/dist/room/boost.d.ts +2 -0
  102. package/dist/room/certificate.d.ts +22 -0
  103. package/dist/room/chips.d.ts +21 -0
  104. package/dist/room/lobby.d.ts +44 -0
  105. package/dist/room/mount.d.ts +6 -0
  106. package/dist/room/room.d.ts +70 -0
  107. package/dist/room/stage.d.ts +17 -0
  108. package/dist/room/theme.d.ts +15 -0
  109. package/dist/runtime/context.d.ts +33 -0
  110. package/dist/runtime/element.d.ts +15 -0
  111. package/dist/runtime/fx.d.ts +43 -0
  112. package/dist/runtime/i18n.d.ts +8 -0
  113. package/dist/runtime/icons.d.ts +2 -0
  114. package/dist/runtime/motion.d.ts +2 -0
  115. package/dist/runtime/signal.d.ts +6 -0
  116. package/dist/runtime/sound.d.ts +11 -0
  117. package/dist/signal-CAveEGrG.js +19 -0
  118. package/dist/styles/index.d.ts +1 -0
  119. package/package.json +56 -4
package/README.md CHANGED
@@ -1,3 +1,212 @@
1
- # Temporary Holding Version
1
+ # feeling-lucky
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A casino room for any web app: players try their luck on classic casino games and win the prizes you configure.
4
+
5
+ **[Live demo](https://adiakys.github.io/feeling-lucky/)**: Ctrl+Shift+L in the room opens the developer menu.
6
+
7
+ - **Framework-free:** a single entry point that works with React, Angular, Vue or plain HTML.
8
+ - **No runtime dependencies:** built with [Lit](https://lit.dev) and [Lucide](https://lucide.dev) icons, both bundled.
9
+ - **Isolated:** the room lives in a shadow root mounted on `body`, so the host's CSS never reaches it and its CSS never leaks out.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install @adiakys/feeling-lucky
15
+ ```
16
+
17
+ Without a bundler, the IIFE build exposes a global:
18
+
19
+ ```html
20
+ <script src="https://cdn.jsdelivr.net/npm/@adiakys/feeling-lucky/dist/feeling-lucky.iife.js"></script>
21
+ <script>
22
+ const lucky = FeelingLucky.createFeelingLucky({ prizes: [/* … */] });
23
+ </script>
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ```ts
29
+ import { createFeelingLucky } from '@adiakys/feeling-lucky';
30
+
31
+ const lucky = createFeelingLucky({
32
+ prizes: [
33
+ {
34
+ id: 'pro',
35
+ name: 'Pro',
36
+ icon: '/icons/pro.svg',
37
+ variants: [
38
+ { tier: 'small', label: '7 days', short: '7D' },
39
+ { tier: 'big', label: '1 year', short: '1Y' },
40
+ ],
41
+ },
42
+ { id: 'basic', name: 'Basic', icon: '/icons/basic.svg' },
43
+ ],
44
+ onWin: (win) => console.log(win),
45
+ });
46
+
47
+ button.addEventListener('click', (event) => lucky.open({ from: event.currentTarget }));
48
+ ```
49
+
50
+ | Method | |
51
+ |---|---|
52
+ | `open({ from? })` | Opens the room, growing out of `from` (an element or `{ x, y }`) |
53
+ | `close()` | Closes the room |
54
+ | `update(config)` | Merges a partial config |
55
+ | `destroy()` | Removes the room and its listeners |
56
+
57
+ ## Config
58
+
59
+ Every field takes a value, a function, or a function returning a Promise.
60
+
61
+ | Field | Type | Default |
62
+ |---|---|---|
63
+ | `prizes` | `Prize[]`, 1 to n | required |
64
+ | `locale` | language code, e.g. `'it'` or `'pt-BR'` | follows the host page, see [Languages](#languages) |
65
+ | `messages` | `{ [locale]: Messages }`: new languages, or overrides of the built-in ones | none |
66
+ | `logo` | image URL of your brand mark, on the certificate, the wheel's hub and the scratch card | a clover |
67
+ | `player` | `{ name, avatar? }`, shown at the card tables | anonymous seat |
68
+ | `onWin` | `(win: Win) => void` | none |
69
+ | `onClaim` | `(win: Win) => Promise<void>`; shows **Claim** on the certificate | no claim button |
70
+ | `developer` | `true` or `{ passwordHash? }`: enables the developer menu (Ctrl+Shift+L), behind a password when the hash is given | disabled |
71
+
72
+ ```ts
73
+ interface Prize {
74
+ id: string;
75
+ name: string;
76
+ icon: string; // image URL
77
+ color?: string; // chip colour
78
+ variants?: Variant[] | ((tier: PrizeTier) => Variant | Promise<Variant>);
79
+ }
80
+
81
+ type PrizeTier = 'small' | 'big' | 'jackpot';
82
+
83
+ interface Variant {
84
+ tier: PrizeTier;
85
+ label: string; // certificate: "7 days"
86
+ short?: string; // game boards: "7D"
87
+ details?: { label: string; value: string }[];
88
+ }
89
+
90
+ interface Win {
91
+ prize: Prize;
92
+ variant: Variant | null; // null: the full prize
93
+ tier: PrizeTier;
94
+ game: GameId;
95
+ }
96
+ ```
97
+
98
+ ### Prizes and variants
99
+
100
+ - **Every play draws a tier first** (`none`, `small`, `big` or `jackpot`), then the game stages it.
101
+ - **Variants are optional.** A prize without variants is won in full, whatever the tier.
102
+ - **Board labels:** game boards (wheel segments, pachinko pockets, cash-out steps, scratch tickets) show the variants' `short` labels.
103
+ - **Tier symbol fallback:** a prize without variants, or with a variants function, shows the tier symbol on the board instead. Its variant is revealed on the certificate.
104
+ - **No signing or issuing.** `onClaim` hands the win to the host, which does whatever claiming means for it, e.g. closing the room and opening its own page, prefilled from the variant.
105
+ - **Your own fields:** variants can carry fields of yours. The win hands back the very object you gave, typed as yours:
106
+
107
+ ```ts
108
+ interface Plan extends Variant {
109
+ months: number;
110
+ }
111
+
112
+ const lucky = createFeelingLucky<Plan>({
113
+ prizes: [{ id: 'pro', name: 'Pro', icon: '/pro.svg', variants: [{ tier: 'big', label: '1 year', months: 12 }] }],
114
+ onClaim: async (win) => {
115
+ lucky.close();
116
+ router.push(`/redeem/${win.prize.id}?months=${win.variant?.months ?? 'all'}`);
117
+ },
118
+ });
119
+ ```
120
+
121
+ ### Developer menu
122
+
123
+ Ctrl+Shift+L in the room opens a password-gated panel that forces outcomes, themes and bonuses, for demos and testing. Without `passwordHash` it opens without a password. With it, only the password's SHA-256 hex goes in the config; checking it needs a secure context (https or localhost):
124
+
125
+ ```bash
126
+ printf '%s' 'my password' | sha256sum
127
+ ```
128
+
129
+ ## Languages
130
+
131
+ Every text, game names included, comes from the locale. Built in: `en`, `it`, `es`, `fr`, `de`. English ships with the library; the others load on demand, only when the room speaks them.
132
+
133
+ - **Default locale:** without `locale`, the room follows `<html lang>` and switches when the host app changes it, falling back to `navigator.language`.
134
+ - **Matching:** `pt-BR` uses `pt-BR`, then `pt`, then `en`.
135
+ - **New languages:** add them through `messages`. Missing keys fall back to `en`.
136
+
137
+ ```ts
138
+ import { createFeelingLucky, en } from '@adiakys/feeling-lucky';
139
+
140
+ createFeelingLucky({
141
+ prizes,
142
+ messages: {
143
+ pt: { ...en, room: 'Sala de jogos' /* … */ },
144
+ it: { games: { wheel: { name: 'Ruota d’oro' } } },
145
+ },
146
+ });
147
+ ```
148
+
149
+ ## Games
150
+
151
+ | Room | Games |
152
+ |---|---|
153
+ | Main hall | Grand Wheel (Prize Hunt, Heads or Tails, Pachinko bonus), Roulette, Slot, Pachinko, Scratch card |
154
+ | Salon Privé | Blackjack, Texas Hold'em, single player against the house |
155
+
156
+ - **Bonus of the day:** one main-hall game per day, the same for everyone, gets its own variant and boosted odds:
157
+ - Storm Roulette
158
+ - Booster on the Grand Wheel
159
+ - Takeoff or Breakaway in place of the slot
160
+ - Double Luck or Forever in place of the scratch card
161
+ - colour Pachinko
162
+ - **Room themes:** Christmas, Halloween, Easter and August, taken from the calendar.
163
+
164
+ ## Structure
165
+
166
+ ```
167
+ src/
168
+ index.ts public API
169
+ config/ config types, defaults
170
+ engine/ outcomes, no DOM
171
+ runtime/ i18n, icons, sound, fx
172
+ room/ room, lobby, certificate
173
+ games/ one folder per game:
174
+ wheel, roulette, slot, pachinko,
175
+ scratch, blackjack, holdem
176
+ developer/ developer menu, lazy
177
+ styles/ CSS per area
178
+ locales/ en, it, es, fr, de
179
+ playground/ demo with sample prizes
180
+ tests/ unit (engine), e2e
181
+ ```
182
+
183
+ ### Rules
184
+
185
+ - **`engine/` decides every outcome** and never touches the DOM. Games only stage what it decides.
186
+ - **Rig seam:** the developer menu reaches the outcomes only through `engine/rig` (`decide(key, context, draw)`). Games don't know it exists.
187
+ - **Lit elements render into the room's shadow root, not into their own.** One stylesheet styles the whole room.
188
+ - **Every text lives in `locales/`.** Icons are inline SVG.
189
+
190
+ ## Development
191
+
192
+ ```bash
193
+ npm install
194
+ npm run dev # playground
195
+ npm test # unit tests
196
+ npm run test:e2e # one smoke test per game
197
+ npm run typecheck
198
+ npm run build # dist/: ESM + IIFE
199
+ npm run build:demo # site/: the playground, as on GitHub Pages
200
+ ```
201
+
202
+ ## Release
203
+
204
+ Bump `version` in `package.json`, then push a `v<version>` tag. The release workflow:
205
+ - runs the checks;
206
+ - publishes the package to npm;
207
+ - attaches the packed `.tgz` to a GitHub release;
208
+ - deploys the playground to GitHub Pages.
209
+
210
+ ## License
211
+
212
+ [GPL-3.0-or-later](LICENSE)
@@ -0,0 +1,4 @@
1
+ import type { FeelingLuckyConfig, Resolvable } from './types';
2
+ import type { RoomConfig } from '../room/room';
3
+ export declare const resolve: <T>(value: Resolvable<T>) => Promise<T>;
4
+ export declare function resolveConfig(config: FeelingLuckyConfig): Promise<RoomConfig>;
@@ -0,0 +1,56 @@
1
+ export type Tier = 'none' | 'small' | 'big' | 'jackpot';
2
+ export type PrizeTier = Exclude<Tier, 'none'>;
3
+ export type GameId = 'wheel' | 'slot' | 'roulette' | 'pachinko' | 'scratch' | 'blackjack' | 'holdem';
4
+ export type Resolvable<T> = T | (() => T | Promise<T>);
5
+ export interface Variant {
6
+ tier: PrizeTier;
7
+ label: string;
8
+ short?: string;
9
+ details?: {
10
+ label: string;
11
+ value: string;
12
+ }[];
13
+ }
14
+ export interface Prize<V extends Variant = Variant> {
15
+ id: string;
16
+ name: string;
17
+ icon: string;
18
+ color?: string;
19
+ variants?: V[] | ((tier: PrizeTier) => V | Promise<V>);
20
+ }
21
+ export interface Win<V extends Variant = Variant> {
22
+ prize: Prize<V>;
23
+ variant: V | null;
24
+ tier: PrizeTier;
25
+ game: GameId;
26
+ }
27
+ export interface Player {
28
+ name: string;
29
+ avatar?: string;
30
+ }
31
+ export type Messages = {
32
+ [key: string]: string | Messages;
33
+ };
34
+ export interface FeelingLuckyConfig<V extends Variant = Variant> {
35
+ prizes: Resolvable<Prize<V>[]>;
36
+ locale?: Resolvable<string>;
37
+ messages?: Resolvable<Record<string, Messages>>;
38
+ player?: Resolvable<Player>;
39
+ logo?: Resolvable<string>;
40
+ onWin?: (win: Win<V>) => void;
41
+ onClaim?: (win: Win<V>) => Promise<void>;
42
+ developer?: Resolvable<boolean | {
43
+ passwordHash?: string;
44
+ }>;
45
+ }
46
+ export interface FeelingLucky<V extends Variant = Variant> {
47
+ open(options?: {
48
+ from?: Element | {
49
+ x: number;
50
+ y: number;
51
+ };
52
+ }): void;
53
+ close(): void;
54
+ update(config: Partial<FeelingLuckyConfig<V>>): void;
55
+ destroy(): void;
56
+ }