react-raffle-picker 0.2.0 → 0.2.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 +20 -18
- package/dist/index.cjs +24 -4
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +24 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://i.ibb.co/
|
|
2
|
+
<img src="https://i.ibb.co/yB50hJTv/logo-nbg.png" alt="react-raffle-picker logo placeholder" width="160" />
|
|
3
3
|
|
|
4
4
|
<h1>react-raffle-picker</h1>
|
|
5
5
|
|
|
@@ -69,7 +69,7 @@ This means:
|
|
|
69
69
|
```tsx
|
|
70
70
|
import { RafflePick } from 'react-raffle-picker'
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
;<RafflePick min={1} max={100} interval={100} inertia onSelect={(v) => console.log(v)}>
|
|
73
73
|
<RafflePick.Value animation="roll" className="my-value" />
|
|
74
74
|
<RafflePick.Button startLabel="Pick" stopLabel="Stop" />
|
|
75
75
|
</RafflePick>
|
|
@@ -79,7 +79,7 @@ import { RafflePick } from 'react-raffle-picker'
|
|
|
79
79
|
|
|
80
80
|
The library is headless — no global stylesheet is required for `Value`, `Button`, or `Countdown`. You bring your own CSS.
|
|
81
81
|
|
|
82
|
-
For the **slot reel** (`<RafflePick.Slots>`), a minimal stylesheet
|
|
82
|
+
For the **slot reel** (`<RafflePick.Slots>`), a minimal stylesheet _is_ required to make the column animate. Two ways to load it:
|
|
83
83
|
|
|
84
84
|
1. **Auto-injected at runtime** — `<RafflePick.Slots>` injects a `<style data-rrp-slot-base>` tag into `document.head` on first mount. No action needed in CSR apps.
|
|
85
85
|
2. **Static import** (recommended for SSR / strict CSP / full control):
|
|
@@ -96,21 +96,21 @@ For the **slot reel** (`<RafflePick.Slots>`), a minimal stylesheet *is* required
|
|
|
96
96
|
|
|
97
97
|
Provides context. Renders an optional wrapper element (`as` prop, default `'div'`).
|
|
98
98
|
|
|
99
|
-
| Prop
|
|
100
|
-
|
|
|
101
|
-
| `min`, `max`
|
|
102
|
-
| `items`
|
|
103
|
-
| `interval`
|
|
104
|
-
| `random`
|
|
105
|
-
| `inertia`
|
|
106
|
-
| `autoStart`
|
|
107
|
-
| `initialValue` | `number \| string`
|
|
108
|
-
| `finalValue` | `number \| string`
|
|
109
|
-
| `onSelect`
|
|
110
|
-
| `as`
|
|
111
|
-
| `className`
|
|
112
|
-
| `style`
|
|
113
|
-
| `children`
|
|
99
|
+
| Prop | Type | Default | Notes |
|
|
100
|
+
| -------------- | --------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
101
|
+
| `min`, `max` | `number` | `1`, `100` | Numeric range. Ignored if `items` provided. |
|
|
102
|
+
| `items` | `string[]` | — | Switches to item mode (cycles through names). |
|
|
103
|
+
| `interval` | `number` (ms, clamped ≥ 50) | `100` | Tick speed. |
|
|
104
|
+
| `random` | `boolean` | `true` | Random pick vs sequential. |
|
|
105
|
+
| `inertia` | `boolean` | `false` | Soft start / soft stop ramp. |
|
|
106
|
+
| `autoStart` | `boolean` | `true` | Begin cycling on mount. |
|
|
107
|
+
| `initialValue` | `number \| string` | — | Starting display before first run. Number for `min`/`max` mode, string for `items` mode. For `<Slots>`, each character seeds the corresponding reel. |
|
|
108
|
+
| `finalValue` | `number \| string` | — | Forces settle to land on this value. Cycle still appears random; only final freeze is rigged. For `<Slots>`, each character is the final char of the corresponding reel. |
|
|
109
|
+
| `onSelect` | `(value) => void` | — | Fires once per round on freeze. |
|
|
110
|
+
| `as` | `ElementType` | `'div'` | Wrapper tag. |
|
|
111
|
+
| `className` | `string` | — | Wrapper class. |
|
|
112
|
+
| `style` | `CSSProperties` | — | Wrapper style. |
|
|
113
|
+
| `children` | `ReactNode` | — | Sub-components. |
|
|
114
114
|
|
|
115
115
|
### `<RafflePick.Value>`
|
|
116
116
|
|
|
@@ -153,6 +153,8 @@ Schedules auto-freeze after `seconds`. Renders an SVG ring + numeric label by de
|
|
|
153
153
|
|
|
154
154
|
Independent multi-reel slot machine. Each reel ticks on its own and stops with a stagger.
|
|
155
155
|
|
|
156
|
+
`initialValue` (root prop) seeds reels char-by-char before the first run. `finalValue` rigs the freeze so each reel lands on the corresponding character — useful for predetermined winners or scripted demos.
|
|
157
|
+
|
|
156
158
|
| Prop | Type | Default | Notes |
|
|
157
159
|
| -------------------------------------------------- | -------------------------- | -------------- | -------------------------------------------- |
|
|
158
160
|
| `length` | `number` | `3` | Number of reels. |
|
package/dist/index.cjs
CHANGED
|
@@ -258,6 +258,8 @@ function RafflePickRoot({ items, min = 1, max = 100, interval = 100, random = tr
|
|
|
258
258
|
inertia,
|
|
259
259
|
hasItems,
|
|
260
260
|
initialIndex,
|
|
261
|
+
initialValue,
|
|
262
|
+
finalValue,
|
|
261
263
|
valueRef,
|
|
262
264
|
displayValue,
|
|
263
265
|
subscribe,
|
|
@@ -272,6 +274,8 @@ function RafflePickRoot({ items, min = 1, max = 100, interval = 100, random = tr
|
|
|
272
274
|
inertia,
|
|
273
275
|
hasItems,
|
|
274
276
|
initialIndex,
|
|
277
|
+
initialValue,
|
|
278
|
+
finalValue,
|
|
275
279
|
displayValue,
|
|
276
280
|
subscribe,
|
|
277
281
|
start,
|
|
@@ -456,7 +460,19 @@ const makeRefs = () => ({
|
|
|
456
460
|
});
|
|
457
461
|
function RafflePickSlots({ length = 3, chars = "0123456789", spinInterval = 80, staggerMs = 220, className, slotClassName, style, slotStyle, onResult }) {
|
|
458
462
|
injectSlotStyles();
|
|
459
|
-
const { phase } = useRaffleContext("RafflePick.Slots");
|
|
463
|
+
const { phase, initialValue, finalValue } = useRaffleContext("RafflePick.Slots");
|
|
464
|
+
const initialChars = (0, react.useMemo)(() => {
|
|
465
|
+
const seed = typeof initialValue === "string" ? initialValue : "";
|
|
466
|
+
return Array.from({ length }, (_, i) => seed[i] ?? "");
|
|
467
|
+
}, [initialValue, length]);
|
|
468
|
+
const finalChars = (0, react.useMemo)(() => {
|
|
469
|
+
if (typeof finalValue !== "string") return null;
|
|
470
|
+
return Array.from({ length }, (_, i) => finalValue[i] ?? "");
|
|
471
|
+
}, [finalValue, length]);
|
|
472
|
+
const finalCharsRef = (0, react.useRef)(finalChars);
|
|
473
|
+
(0, react.useEffect)(() => {
|
|
474
|
+
finalCharsRef.current = finalChars;
|
|
475
|
+
}, [finalChars]);
|
|
460
476
|
const slotsRef = (0, react.useRef)([]);
|
|
461
477
|
const stopTimersRef = (0, react.useRef)([]);
|
|
462
478
|
const finalRef = (0, react.useRef)([]);
|
|
@@ -514,6 +530,8 @@ function RafflePickSlots({ length = 3, chars = "0123456789", spinInterval = 80,
|
|
|
514
530
|
for (let i = 0; i < length; i++) {
|
|
515
531
|
const id = setTimeout(() => {
|
|
516
532
|
const s = slotsRef.current[i];
|
|
533
|
+
const forced = finalCharsRef.current?.[i];
|
|
534
|
+
if (forced) writeSlot(s, s.currChar, forced, forced);
|
|
517
535
|
s.stopped = true;
|
|
518
536
|
if (s.root) s.root.setAttribute("data-stopped", "");
|
|
519
537
|
finalRef.current[i] = s.currChar;
|
|
@@ -529,17 +547,19 @@ function RafflePickSlots({ length = 3, chars = "0123456789", spinInterval = 80,
|
|
|
529
547
|
]);
|
|
530
548
|
(0, react.useEffect)(() => {
|
|
531
549
|
if (phase !== "idle") return;
|
|
532
|
-
const
|
|
550
|
+
const fallback = pool[0] ?? "";
|
|
533
551
|
for (let i = 0; i < length; i++) {
|
|
534
552
|
const s = slotsRef.current[i];
|
|
553
|
+
const c = initialChars[i] || fallback;
|
|
535
554
|
s.stopped = true;
|
|
536
555
|
writeSlot(s, c, c, c);
|
|
537
|
-
if (s.root) s.root.
|
|
556
|
+
if (s.root) s.root.setAttribute("data-stopped", "");
|
|
538
557
|
}
|
|
539
558
|
}, [
|
|
540
559
|
phase,
|
|
541
560
|
length,
|
|
542
|
-
pool
|
|
561
|
+
pool,
|
|
562
|
+
initialChars
|
|
543
563
|
]);
|
|
544
564
|
const cls = (0, react.useMemo)(() => joinClassNames("rrp-slots", className), [className]);
|
|
545
565
|
const slotCls = (0, react.useMemo)(() => joinClassNames("rrp-slot", slotClassName), [slotClassName]);
|
package/dist/index.d.cts
CHANGED
|
@@ -135,6 +135,8 @@ interface RaffleContextValue {
|
|
|
135
135
|
inertia: boolean;
|
|
136
136
|
hasItems: boolean;
|
|
137
137
|
initialIndex: number;
|
|
138
|
+
initialValue?: RafflePickValue$1;
|
|
139
|
+
finalValue?: RafflePickValue$1;
|
|
138
140
|
valueRef: RefObject<number>;
|
|
139
141
|
displayValue: (index: number) => RafflePickValue$1;
|
|
140
142
|
subscribe: (fn: (value: number) => void) => () => void;
|
package/dist/index.d.mts
CHANGED
|
@@ -135,6 +135,8 @@ interface RaffleContextValue {
|
|
|
135
135
|
inertia: boolean;
|
|
136
136
|
hasItems: boolean;
|
|
137
137
|
initialIndex: number;
|
|
138
|
+
initialValue?: RafflePickValue$1;
|
|
139
|
+
finalValue?: RafflePickValue$1;
|
|
138
140
|
valueRef: RefObject<number>;
|
|
139
141
|
displayValue: (index: number) => RafflePickValue$1;
|
|
140
142
|
subscribe: (fn: (value: number) => void) => () => void;
|
package/dist/index.mjs
CHANGED
|
@@ -257,6 +257,8 @@ function RafflePickRoot({ items, min = 1, max = 100, interval = 100, random = tr
|
|
|
257
257
|
inertia,
|
|
258
258
|
hasItems,
|
|
259
259
|
initialIndex,
|
|
260
|
+
initialValue,
|
|
261
|
+
finalValue,
|
|
260
262
|
valueRef,
|
|
261
263
|
displayValue,
|
|
262
264
|
subscribe,
|
|
@@ -271,6 +273,8 @@ function RafflePickRoot({ items, min = 1, max = 100, interval = 100, random = tr
|
|
|
271
273
|
inertia,
|
|
272
274
|
hasItems,
|
|
273
275
|
initialIndex,
|
|
276
|
+
initialValue,
|
|
277
|
+
finalValue,
|
|
274
278
|
displayValue,
|
|
275
279
|
subscribe,
|
|
276
280
|
start,
|
|
@@ -455,7 +459,19 @@ const makeRefs = () => ({
|
|
|
455
459
|
});
|
|
456
460
|
function RafflePickSlots({ length = 3, chars = "0123456789", spinInterval = 80, staggerMs = 220, className, slotClassName, style, slotStyle, onResult }) {
|
|
457
461
|
injectSlotStyles();
|
|
458
|
-
const { phase } = useRaffleContext("RafflePick.Slots");
|
|
462
|
+
const { phase, initialValue, finalValue } = useRaffleContext("RafflePick.Slots");
|
|
463
|
+
const initialChars = useMemo(() => {
|
|
464
|
+
const seed = typeof initialValue === "string" ? initialValue : "";
|
|
465
|
+
return Array.from({ length }, (_, i) => seed[i] ?? "");
|
|
466
|
+
}, [initialValue, length]);
|
|
467
|
+
const finalChars = useMemo(() => {
|
|
468
|
+
if (typeof finalValue !== "string") return null;
|
|
469
|
+
return Array.from({ length }, (_, i) => finalValue[i] ?? "");
|
|
470
|
+
}, [finalValue, length]);
|
|
471
|
+
const finalCharsRef = useRef(finalChars);
|
|
472
|
+
useEffect(() => {
|
|
473
|
+
finalCharsRef.current = finalChars;
|
|
474
|
+
}, [finalChars]);
|
|
459
475
|
const slotsRef = useRef([]);
|
|
460
476
|
const stopTimersRef = useRef([]);
|
|
461
477
|
const finalRef = useRef([]);
|
|
@@ -513,6 +529,8 @@ function RafflePickSlots({ length = 3, chars = "0123456789", spinInterval = 80,
|
|
|
513
529
|
for (let i = 0; i < length; i++) {
|
|
514
530
|
const id = setTimeout(() => {
|
|
515
531
|
const s = slotsRef.current[i];
|
|
532
|
+
const forced = finalCharsRef.current?.[i];
|
|
533
|
+
if (forced) writeSlot(s, s.currChar, forced, forced);
|
|
516
534
|
s.stopped = true;
|
|
517
535
|
if (s.root) s.root.setAttribute("data-stopped", "");
|
|
518
536
|
finalRef.current[i] = s.currChar;
|
|
@@ -528,17 +546,19 @@ function RafflePickSlots({ length = 3, chars = "0123456789", spinInterval = 80,
|
|
|
528
546
|
]);
|
|
529
547
|
useEffect(() => {
|
|
530
548
|
if (phase !== "idle") return;
|
|
531
|
-
const
|
|
549
|
+
const fallback = pool[0] ?? "";
|
|
532
550
|
for (let i = 0; i < length; i++) {
|
|
533
551
|
const s = slotsRef.current[i];
|
|
552
|
+
const c = initialChars[i] || fallback;
|
|
534
553
|
s.stopped = true;
|
|
535
554
|
writeSlot(s, c, c, c);
|
|
536
|
-
if (s.root) s.root.
|
|
555
|
+
if (s.root) s.root.setAttribute("data-stopped", "");
|
|
537
556
|
}
|
|
538
557
|
}, [
|
|
539
558
|
phase,
|
|
540
559
|
length,
|
|
541
|
-
pool
|
|
560
|
+
pool,
|
|
561
|
+
initialChars
|
|
542
562
|
]);
|
|
543
563
|
const cls = useMemo(() => joinClassNames("rrp-slots", className), [className]);
|
|
544
564
|
const slotCls = useMemo(() => joinClassNames("rrp-slot", slotClassName), [slotClassName]);
|