@digilogiclabs/saas-factory-ui 2.6.0 → 2.7.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/dist/index.d.mts +63 -5
- package/dist/index.d.ts +63 -5
- package/dist/index.js +86 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -17
- package/dist/index.mjs.map +1 -1
- package/dist/web/index.d.mts +63 -5
- package/dist/web/index.d.ts +63 -5
- package/dist/web/index.js +86 -17
- package/dist/web/index.js.map +1 -1
- package/dist/web/index.mjs +86 -17
- package/dist/web/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/web/index.d.mts
CHANGED
|
@@ -5242,6 +5242,17 @@ interface DiceRollerProps {
|
|
|
5242
5242
|
showHistory?: boolean;
|
|
5243
5243
|
/** Max entries in the history strip. Default 8. */
|
|
5244
5244
|
historyMax?: number;
|
|
5245
|
+
/**
|
|
5246
|
+
* Seed the history strip from a persisted session — newest first, the
|
|
5247
|
+
* same entries consumers capture from `onRoll`. One-shot: read on
|
|
5248
|
+
* mount, ignored afterwards; clamped to `historyMax`. Only the strip is
|
|
5249
|
+
* seeded — the dice arena and result chips stay in their pre-roll state
|
|
5250
|
+
* (a settled pose can't be faithfully reproduced).
|
|
5251
|
+
*/
|
|
5252
|
+
initialHistory?: Array<{
|
|
5253
|
+
vals: number[];
|
|
5254
|
+
total: number;
|
|
5255
|
+
}>;
|
|
5245
5256
|
/**
|
|
5246
5257
|
* Imperative handle — assign a ref and call `rollRef.current?.()`
|
|
5247
5258
|
* to trigger a roll from outside the component. Works with any
|
|
@@ -5285,7 +5296,7 @@ declare function d6LandingRotation(value: number): {
|
|
|
5285
5296
|
x: number;
|
|
5286
5297
|
y: number;
|
|
5287
5298
|
};
|
|
5288
|
-
declare function DiceRoller({ count, sides, theme, darkMode, size, minSize, responsive, autoRoll, onRoll, trigger, label, iconEmoji, showHistory, historyMax, rollRef, arenaHeight: arenaHeightProp, hideResults, className, style, ariaLabel, }: DiceRollerProps): ReactNode;
|
|
5299
|
+
declare function DiceRoller({ count, sides, theme, darkMode, size, minSize, responsive, autoRoll, onRoll, trigger, label, iconEmoji, showHistory, historyMax, initialHistory, rollRef, arenaHeight: arenaHeightProp, hideResults, className, style, ariaLabel, }: DiceRollerProps): ReactNode;
|
|
5289
5300
|
declare namespace DiceRoller {
|
|
5290
5301
|
var displayName: string;
|
|
5291
5302
|
}
|
|
@@ -5463,6 +5474,25 @@ interface CoinFlipperProps {
|
|
|
5463
5474
|
showHistory?: boolean;
|
|
5464
5475
|
/** Max entries in history. Default 20. */
|
|
5465
5476
|
historyMax?: number;
|
|
5477
|
+
/**
|
|
5478
|
+
* Seed the history strip from a persisted session — newest first, the
|
|
5479
|
+
* results consumers capture from `onFlip`. One-shot: read on mount,
|
|
5480
|
+
* ignored afterwards; clamped to `historyMax`. The coin face stays in
|
|
5481
|
+
* its pre-flip pose.
|
|
5482
|
+
*/
|
|
5483
|
+
initialHistory?: CoinResult[];
|
|
5484
|
+
/**
|
|
5485
|
+
* Seed the H/T counters from a persisted session. Kept separate from
|
|
5486
|
+
* `initialHistory` because stats count ALL flips while the history
|
|
5487
|
+
* strip is capped at `historyMax`. One-shot: read on mount. When
|
|
5488
|
+
* omitted alongside `initialHistory`, the counters are derived from the
|
|
5489
|
+
* seeded strip instead (a lower bound if the strip was capped) — the
|
|
5490
|
+
* history panel only renders while the counters are non-zero.
|
|
5491
|
+
*/
|
|
5492
|
+
initialStats?: {
|
|
5493
|
+
heads: number;
|
|
5494
|
+
tails: number;
|
|
5495
|
+
};
|
|
5466
5496
|
/** Imperative handle — call `flipRef.current?.()` to flip externally. */
|
|
5467
5497
|
flipRef?: MutableRefObject<(() => void) | null>;
|
|
5468
5498
|
/** Accessible label. */
|
|
@@ -5470,7 +5500,7 @@ interface CoinFlipperProps {
|
|
|
5470
5500
|
/** CSS class on root element. */
|
|
5471
5501
|
className?: string;
|
|
5472
5502
|
}
|
|
5473
|
-
declare function CoinFlipper({ theme, darkMode, size, autoFlip, onFlip, trigger, label, headsLabel, tailsLabel, showHistory, historyMax, flipRef, ariaLabel, className, }: CoinFlipperProps): react_jsx_runtime.JSX.Element;
|
|
5503
|
+
declare function CoinFlipper({ theme, darkMode, size, autoFlip, onFlip, trigger, label, headsLabel, tailsLabel, showHistory, historyMax, initialHistory, initialStats, flipRef, ariaLabel, className, }: CoinFlipperProps): react_jsx_runtime.JSX.Element;
|
|
5474
5504
|
|
|
5475
5505
|
interface RandomPlayerParticipant {
|
|
5476
5506
|
/** Stable identifier — required for keying and winner equality. */
|
|
@@ -5576,6 +5606,17 @@ interface RandomPlayerPickerProps {
|
|
|
5576
5606
|
label?: string;
|
|
5577
5607
|
/** Pop each winner from the pool after reveal. Default false. */
|
|
5578
5608
|
removeWinners?: boolean;
|
|
5609
|
+
/**
|
|
5610
|
+
* Resume a draft from a persisted session: participant ids already
|
|
5611
|
+
* drawn, newest first (the history consumers capture from `onPick`).
|
|
5612
|
+
* One-shot: read on mount, ignored afterwards. Only applied when
|
|
5613
|
+
* `removeWinners` is true — the drawn participants are removed from the
|
|
5614
|
+
* starting pool, seeded into the pick history, and the newest one is
|
|
5615
|
+
* shown on the winner card. Fail-closed: if any id doesn't resolve
|
|
5616
|
+
* against `participants` (or ids repeat), the whole seed is ignored
|
|
5617
|
+
* rather than half-restoring a stale draft.
|
|
5618
|
+
*/
|
|
5619
|
+
initialDrawnIds?: string[];
|
|
5579
5620
|
/** Spin animation duration in ms. Default 5000. */
|
|
5580
5621
|
spinDuration?: number;
|
|
5581
5622
|
/** Lower bound on full revolutions. Default 4. */
|
|
@@ -5665,7 +5706,7 @@ interface RandomPlayerPickerProps {
|
|
|
5665
5706
|
/** Accessible label for the wheel root. */
|
|
5666
5707
|
ariaLabel?: string;
|
|
5667
5708
|
}
|
|
5668
|
-
declare function RandomPlayerPicker({ participants, mode, reelVisibleRows, reelRowHeight, theme, darkMode, size, onPick, onSpinStart, onTick, trigger, label, removeWinners, spinDuration, minRevolutions, maxRevolutions, showHistory, showControls, showStats, renderWinner, spinRef, resetRef, onPoolChange, draftCompleteCaption, intensity, enableHaptics, tickSoundUrl, winSoundUrl, soundVolume, placeholderMode, placeholderCaption, className, style, ariaLabel, }: RandomPlayerPickerProps): react_jsx_runtime.JSX.Element;
|
|
5709
|
+
declare function RandomPlayerPicker({ participants, mode, reelVisibleRows, reelRowHeight, theme, darkMode, size, onPick, onSpinStart, onTick, trigger, label, removeWinners, initialDrawnIds, spinDuration, minRevolutions, maxRevolutions, showHistory, showControls, showStats, renderWinner, spinRef, resetRef, onPoolChange, draftCompleteCaption, intensity, enableHaptics, tickSoundUrl, winSoundUrl, soundVolume, placeholderMode, placeholderCaption, className, style, ariaLabel, }: RandomPlayerPickerProps): react_jsx_runtime.JSX.Element;
|
|
5669
5710
|
|
|
5670
5711
|
type HeroBannerTransition = "fade" | "slide" | "zoom" | "blur" | "reveal" | "push";
|
|
5671
5712
|
type HeroBannerImageFilter = "none" | "cinematic" | "dramatic" | "cool" | "warm" | "desaturated" | "noir" | "vibrant";
|
|
@@ -6328,6 +6369,15 @@ interface RoundRobinSchedulerProps {
|
|
|
6328
6369
|
onTeamsChange?: (teams: string[]) => void;
|
|
6329
6370
|
/** Called when a new schedule is generated. */
|
|
6330
6371
|
onGenerate?: (rounds: RoundRobinRound[]) => void;
|
|
6372
|
+
/**
|
|
6373
|
+
* Gate for roster edits (add / import / remove / shuffle / clear) that
|
|
6374
|
+
* would discard a generated schedule. Called synchronously BEFORE the
|
|
6375
|
+
* edit, and only while a schedule is on screen; return `false` to abort
|
|
6376
|
+
* the edit and keep the schedule (e.g. after a declined
|
|
6377
|
+
* `window.confirm`). Absent = edits discard the schedule silently, as
|
|
6378
|
+
* before. Explicit "Generate Schedule" regenerations are never gated.
|
|
6379
|
+
*/
|
|
6380
|
+
onBeforeScheduleDiscard?: (action: "add" | "import" | "remove" | "shuffle" | "clear") => boolean;
|
|
6331
6381
|
/** Localized / customized labels. */
|
|
6332
6382
|
labels?: RoundRobinLabels;
|
|
6333
6383
|
/** Accessible label on the root region. */
|
|
@@ -6338,7 +6388,7 @@ interface RoundRobinSchedulerProps {
|
|
|
6338
6388
|
* roster from a spreadsheet. Default `true`. */
|
|
6339
6389
|
enableImport?: boolean;
|
|
6340
6390
|
}
|
|
6341
|
-
declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
|
|
6391
|
+
declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, onBeforeScheduleDiscard, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
|
|
6342
6392
|
declare namespace RoundRobinScheduler {
|
|
6343
6393
|
var displayName: string;
|
|
6344
6394
|
}
|
|
@@ -6402,6 +6452,14 @@ interface ScoreboardProps {
|
|
|
6402
6452
|
* `onRoundAdvance` MUST clear that state here or their saved copy
|
|
6403
6453
|
* diverges from the screen. */
|
|
6404
6454
|
onReset?: () => void;
|
|
6455
|
+
/** Gate for the built-in Reset button. Called synchronously BEFORE any
|
|
6456
|
+
* state is cleared; return `false` to abort (e.g. after a declined
|
|
6457
|
+
* `window.confirm` when recorded rounds would be discarded). Absent =
|
|
6458
|
+
* Reset applies immediately, as before. */
|
|
6459
|
+
onBeforeReset?: () => boolean;
|
|
6460
|
+
/** Gate for the built-in New Game button — same contract as
|
|
6461
|
+
* `onBeforeReset`. */
|
|
6462
|
+
onBeforeNewGame?: () => boolean;
|
|
6405
6463
|
/** Max characters accepted in a team-name input. Unlimited by default. */
|
|
6406
6464
|
nameMaxLength?: number;
|
|
6407
6465
|
/** Localized / customized labels. */
|
|
@@ -6411,7 +6469,7 @@ interface ScoreboardProps {
|
|
|
6411
6469
|
/** CSS class on root element. */
|
|
6412
6470
|
className?: string;
|
|
6413
6471
|
}
|
|
6414
|
-
declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, onReset, nameMaxLength, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
|
|
6472
|
+
declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, onReset, onBeforeReset, onBeforeNewGame, nameMaxLength, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
|
|
6415
6473
|
declare namespace Scoreboard {
|
|
6416
6474
|
var displayName: string;
|
|
6417
6475
|
}
|
package/dist/web/index.d.ts
CHANGED
|
@@ -5242,6 +5242,17 @@ interface DiceRollerProps {
|
|
|
5242
5242
|
showHistory?: boolean;
|
|
5243
5243
|
/** Max entries in the history strip. Default 8. */
|
|
5244
5244
|
historyMax?: number;
|
|
5245
|
+
/**
|
|
5246
|
+
* Seed the history strip from a persisted session — newest first, the
|
|
5247
|
+
* same entries consumers capture from `onRoll`. One-shot: read on
|
|
5248
|
+
* mount, ignored afterwards; clamped to `historyMax`. Only the strip is
|
|
5249
|
+
* seeded — the dice arena and result chips stay in their pre-roll state
|
|
5250
|
+
* (a settled pose can't be faithfully reproduced).
|
|
5251
|
+
*/
|
|
5252
|
+
initialHistory?: Array<{
|
|
5253
|
+
vals: number[];
|
|
5254
|
+
total: number;
|
|
5255
|
+
}>;
|
|
5245
5256
|
/**
|
|
5246
5257
|
* Imperative handle — assign a ref and call `rollRef.current?.()`
|
|
5247
5258
|
* to trigger a roll from outside the component. Works with any
|
|
@@ -5285,7 +5296,7 @@ declare function d6LandingRotation(value: number): {
|
|
|
5285
5296
|
x: number;
|
|
5286
5297
|
y: number;
|
|
5287
5298
|
};
|
|
5288
|
-
declare function DiceRoller({ count, sides, theme, darkMode, size, minSize, responsive, autoRoll, onRoll, trigger, label, iconEmoji, showHistory, historyMax, rollRef, arenaHeight: arenaHeightProp, hideResults, className, style, ariaLabel, }: DiceRollerProps): ReactNode;
|
|
5299
|
+
declare function DiceRoller({ count, sides, theme, darkMode, size, minSize, responsive, autoRoll, onRoll, trigger, label, iconEmoji, showHistory, historyMax, initialHistory, rollRef, arenaHeight: arenaHeightProp, hideResults, className, style, ariaLabel, }: DiceRollerProps): ReactNode;
|
|
5289
5300
|
declare namespace DiceRoller {
|
|
5290
5301
|
var displayName: string;
|
|
5291
5302
|
}
|
|
@@ -5463,6 +5474,25 @@ interface CoinFlipperProps {
|
|
|
5463
5474
|
showHistory?: boolean;
|
|
5464
5475
|
/** Max entries in history. Default 20. */
|
|
5465
5476
|
historyMax?: number;
|
|
5477
|
+
/**
|
|
5478
|
+
* Seed the history strip from a persisted session — newest first, the
|
|
5479
|
+
* results consumers capture from `onFlip`. One-shot: read on mount,
|
|
5480
|
+
* ignored afterwards; clamped to `historyMax`. The coin face stays in
|
|
5481
|
+
* its pre-flip pose.
|
|
5482
|
+
*/
|
|
5483
|
+
initialHistory?: CoinResult[];
|
|
5484
|
+
/**
|
|
5485
|
+
* Seed the H/T counters from a persisted session. Kept separate from
|
|
5486
|
+
* `initialHistory` because stats count ALL flips while the history
|
|
5487
|
+
* strip is capped at `historyMax`. One-shot: read on mount. When
|
|
5488
|
+
* omitted alongside `initialHistory`, the counters are derived from the
|
|
5489
|
+
* seeded strip instead (a lower bound if the strip was capped) — the
|
|
5490
|
+
* history panel only renders while the counters are non-zero.
|
|
5491
|
+
*/
|
|
5492
|
+
initialStats?: {
|
|
5493
|
+
heads: number;
|
|
5494
|
+
tails: number;
|
|
5495
|
+
};
|
|
5466
5496
|
/** Imperative handle — call `flipRef.current?.()` to flip externally. */
|
|
5467
5497
|
flipRef?: MutableRefObject<(() => void) | null>;
|
|
5468
5498
|
/** Accessible label. */
|
|
@@ -5470,7 +5500,7 @@ interface CoinFlipperProps {
|
|
|
5470
5500
|
/** CSS class on root element. */
|
|
5471
5501
|
className?: string;
|
|
5472
5502
|
}
|
|
5473
|
-
declare function CoinFlipper({ theme, darkMode, size, autoFlip, onFlip, trigger, label, headsLabel, tailsLabel, showHistory, historyMax, flipRef, ariaLabel, className, }: CoinFlipperProps): react_jsx_runtime.JSX.Element;
|
|
5503
|
+
declare function CoinFlipper({ theme, darkMode, size, autoFlip, onFlip, trigger, label, headsLabel, tailsLabel, showHistory, historyMax, initialHistory, initialStats, flipRef, ariaLabel, className, }: CoinFlipperProps): react_jsx_runtime.JSX.Element;
|
|
5474
5504
|
|
|
5475
5505
|
interface RandomPlayerParticipant {
|
|
5476
5506
|
/** Stable identifier — required for keying and winner equality. */
|
|
@@ -5576,6 +5606,17 @@ interface RandomPlayerPickerProps {
|
|
|
5576
5606
|
label?: string;
|
|
5577
5607
|
/** Pop each winner from the pool after reveal. Default false. */
|
|
5578
5608
|
removeWinners?: boolean;
|
|
5609
|
+
/**
|
|
5610
|
+
* Resume a draft from a persisted session: participant ids already
|
|
5611
|
+
* drawn, newest first (the history consumers capture from `onPick`).
|
|
5612
|
+
* One-shot: read on mount, ignored afterwards. Only applied when
|
|
5613
|
+
* `removeWinners` is true — the drawn participants are removed from the
|
|
5614
|
+
* starting pool, seeded into the pick history, and the newest one is
|
|
5615
|
+
* shown on the winner card. Fail-closed: if any id doesn't resolve
|
|
5616
|
+
* against `participants` (or ids repeat), the whole seed is ignored
|
|
5617
|
+
* rather than half-restoring a stale draft.
|
|
5618
|
+
*/
|
|
5619
|
+
initialDrawnIds?: string[];
|
|
5579
5620
|
/** Spin animation duration in ms. Default 5000. */
|
|
5580
5621
|
spinDuration?: number;
|
|
5581
5622
|
/** Lower bound on full revolutions. Default 4. */
|
|
@@ -5665,7 +5706,7 @@ interface RandomPlayerPickerProps {
|
|
|
5665
5706
|
/** Accessible label for the wheel root. */
|
|
5666
5707
|
ariaLabel?: string;
|
|
5667
5708
|
}
|
|
5668
|
-
declare function RandomPlayerPicker({ participants, mode, reelVisibleRows, reelRowHeight, theme, darkMode, size, onPick, onSpinStart, onTick, trigger, label, removeWinners, spinDuration, minRevolutions, maxRevolutions, showHistory, showControls, showStats, renderWinner, spinRef, resetRef, onPoolChange, draftCompleteCaption, intensity, enableHaptics, tickSoundUrl, winSoundUrl, soundVolume, placeholderMode, placeholderCaption, className, style, ariaLabel, }: RandomPlayerPickerProps): react_jsx_runtime.JSX.Element;
|
|
5709
|
+
declare function RandomPlayerPicker({ participants, mode, reelVisibleRows, reelRowHeight, theme, darkMode, size, onPick, onSpinStart, onTick, trigger, label, removeWinners, initialDrawnIds, spinDuration, minRevolutions, maxRevolutions, showHistory, showControls, showStats, renderWinner, spinRef, resetRef, onPoolChange, draftCompleteCaption, intensity, enableHaptics, tickSoundUrl, winSoundUrl, soundVolume, placeholderMode, placeholderCaption, className, style, ariaLabel, }: RandomPlayerPickerProps): react_jsx_runtime.JSX.Element;
|
|
5669
5710
|
|
|
5670
5711
|
type HeroBannerTransition = "fade" | "slide" | "zoom" | "blur" | "reveal" | "push";
|
|
5671
5712
|
type HeroBannerImageFilter = "none" | "cinematic" | "dramatic" | "cool" | "warm" | "desaturated" | "noir" | "vibrant";
|
|
@@ -6328,6 +6369,15 @@ interface RoundRobinSchedulerProps {
|
|
|
6328
6369
|
onTeamsChange?: (teams: string[]) => void;
|
|
6329
6370
|
/** Called when a new schedule is generated. */
|
|
6330
6371
|
onGenerate?: (rounds: RoundRobinRound[]) => void;
|
|
6372
|
+
/**
|
|
6373
|
+
* Gate for roster edits (add / import / remove / shuffle / clear) that
|
|
6374
|
+
* would discard a generated schedule. Called synchronously BEFORE the
|
|
6375
|
+
* edit, and only while a schedule is on screen; return `false` to abort
|
|
6376
|
+
* the edit and keep the schedule (e.g. after a declined
|
|
6377
|
+
* `window.confirm`). Absent = edits discard the schedule silently, as
|
|
6378
|
+
* before. Explicit "Generate Schedule" regenerations are never gated.
|
|
6379
|
+
*/
|
|
6380
|
+
onBeforeScheduleDiscard?: (action: "add" | "import" | "remove" | "shuffle" | "clear") => boolean;
|
|
6331
6381
|
/** Localized / customized labels. */
|
|
6332
6382
|
labels?: RoundRobinLabels;
|
|
6333
6383
|
/** Accessible label on the root region. */
|
|
@@ -6338,7 +6388,7 @@ interface RoundRobinSchedulerProps {
|
|
|
6338
6388
|
* roster from a spreadsheet. Default `true`. */
|
|
6339
6389
|
enableImport?: boolean;
|
|
6340
6390
|
}
|
|
6341
|
-
declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
|
|
6391
|
+
declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, onBeforeScheduleDiscard, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
|
|
6342
6392
|
declare namespace RoundRobinScheduler {
|
|
6343
6393
|
var displayName: string;
|
|
6344
6394
|
}
|
|
@@ -6402,6 +6452,14 @@ interface ScoreboardProps {
|
|
|
6402
6452
|
* `onRoundAdvance` MUST clear that state here or their saved copy
|
|
6403
6453
|
* diverges from the screen. */
|
|
6404
6454
|
onReset?: () => void;
|
|
6455
|
+
/** Gate for the built-in Reset button. Called synchronously BEFORE any
|
|
6456
|
+
* state is cleared; return `false` to abort (e.g. after a declined
|
|
6457
|
+
* `window.confirm` when recorded rounds would be discarded). Absent =
|
|
6458
|
+
* Reset applies immediately, as before. */
|
|
6459
|
+
onBeforeReset?: () => boolean;
|
|
6460
|
+
/** Gate for the built-in New Game button — same contract as
|
|
6461
|
+
* `onBeforeReset`. */
|
|
6462
|
+
onBeforeNewGame?: () => boolean;
|
|
6405
6463
|
/** Max characters accepted in a team-name input. Unlimited by default. */
|
|
6406
6464
|
nameMaxLength?: number;
|
|
6407
6465
|
/** Localized / customized labels. */
|
|
@@ -6411,7 +6469,7 @@ interface ScoreboardProps {
|
|
|
6411
6469
|
/** CSS class on root element. */
|
|
6412
6470
|
className?: string;
|
|
6413
6471
|
}
|
|
6414
|
-
declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, onReset, nameMaxLength, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
|
|
6472
|
+
declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, onReset, onBeforeReset, onBeforeNewGame, nameMaxLength, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
|
|
6415
6473
|
declare namespace Scoreboard {
|
|
6416
6474
|
var displayName: string;
|
|
6417
6475
|
}
|
package/dist/web/index.js
CHANGED
|
@@ -30539,6 +30539,7 @@ function DiceRoller({
|
|
|
30539
30539
|
iconEmoji = "\u{1F3B2}",
|
|
30540
30540
|
showHistory = false,
|
|
30541
30541
|
historyMax = 8,
|
|
30542
|
+
initialHistory,
|
|
30542
30543
|
rollRef,
|
|
30543
30544
|
arenaHeight: arenaHeightProp,
|
|
30544
30545
|
hideResults = false,
|
|
@@ -30550,7 +30551,9 @@ function DiceRoller({
|
|
|
30550
30551
|
const dark = useDarkMode(darkMode);
|
|
30551
30552
|
const [rolling, setRolling] = (0, import_react69.useState)(false);
|
|
30552
30553
|
const [results, setResults] = (0, import_react69.useState)(null);
|
|
30553
|
-
const [history, setHistory] = (0, import_react69.useState)(
|
|
30554
|
+
const [history, setHistory] = (0, import_react69.useState)(
|
|
30555
|
+
() => initialHistory && initialHistory.length > 0 ? initialHistory.slice(0, historyMax) : []
|
|
30556
|
+
);
|
|
30554
30557
|
const dieWrapperRefs = (0, import_react69.useRef)([]);
|
|
30555
30558
|
const cubeRefs = (0, import_react69.useRef)([]);
|
|
30556
30559
|
const shadowRefs = (0, import_react69.useRef)([]);
|
|
@@ -30724,7 +30727,10 @@ function DiceRoller({
|
|
|
30724
30727
|
defaultPositions,
|
|
30725
30728
|
half
|
|
30726
30729
|
]);
|
|
30730
|
+
const prevSidesRef = (0, import_react69.useRef)(sides);
|
|
30727
30731
|
(0, import_react69.useEffect)(() => {
|
|
30732
|
+
if (prevSidesRef.current === sides) return;
|
|
30733
|
+
prevSidesRef.current = sides;
|
|
30728
30734
|
setHistory([]);
|
|
30729
30735
|
}, [sides]);
|
|
30730
30736
|
const roll = (0, import_react69.useCallback)(() => {
|
|
@@ -32793,6 +32799,8 @@ function CoinFlipper({
|
|
|
32793
32799
|
tailsLabel = "Tails",
|
|
32794
32800
|
showHistory = false,
|
|
32795
32801
|
historyMax = 20,
|
|
32802
|
+
initialHistory,
|
|
32803
|
+
initialStats,
|
|
32796
32804
|
flipRef,
|
|
32797
32805
|
ariaLabel,
|
|
32798
32806
|
className = ""
|
|
@@ -32801,8 +32809,23 @@ function CoinFlipper({
|
|
|
32801
32809
|
const tc = typeof theme5 === "string" ? PRESETS3[theme5] || PRESETS3.gold : theme5;
|
|
32802
32810
|
const [result, setResult] = (0, import_react71.useState)(null);
|
|
32803
32811
|
const [flipping, setFlipping] = (0, import_react71.useState)(false);
|
|
32804
|
-
const [history, setHistory] = (0, import_react71.useState)(
|
|
32805
|
-
|
|
32812
|
+
const [history, setHistory] = (0, import_react71.useState)(
|
|
32813
|
+
() => initialHistory && initialHistory.length > 0 ? initialHistory.slice(0, historyMax).map((result2, i) => ({ result: result2, id: -(i + 1) })) : []
|
|
32814
|
+
);
|
|
32815
|
+
const [stats, setStats] = (0, import_react71.useState)(() => {
|
|
32816
|
+
if (initialStats) {
|
|
32817
|
+
return {
|
|
32818
|
+
heads: Math.max(0, Math.floor(initialStats.heads)),
|
|
32819
|
+
tails: Math.max(0, Math.floor(initialStats.tails))
|
|
32820
|
+
};
|
|
32821
|
+
}
|
|
32822
|
+
if (initialHistory && initialHistory.length > 0) {
|
|
32823
|
+
const seeded = initialHistory.slice(0, historyMax);
|
|
32824
|
+
const heads = seeded.filter((r) => r === "heads").length;
|
|
32825
|
+
return { heads, tails: seeded.length - heads };
|
|
32826
|
+
}
|
|
32827
|
+
return { heads: 0, tails: 0 };
|
|
32828
|
+
});
|
|
32806
32829
|
const flipIdRef = (0, import_react71.useRef)(0);
|
|
32807
32830
|
const coinRef = (0, import_react71.useRef)(null);
|
|
32808
32831
|
const shadowRef = (0, import_react71.useRef)(null);
|
|
@@ -33731,6 +33754,23 @@ function ReelStage({
|
|
|
33731
33754
|
}
|
|
33732
33755
|
);
|
|
33733
33756
|
}
|
|
33757
|
+
function computeDraftSeed(participants, drawnIds, removeWinners) {
|
|
33758
|
+
if (!removeWinners || !drawnIds || drawnIds.length === 0) return null;
|
|
33759
|
+
if (new Set(drawnIds).size !== drawnIds.length) return null;
|
|
33760
|
+
const byId = new Map(participants.map((p) => [p.id, p]));
|
|
33761
|
+
const drawn = [];
|
|
33762
|
+
for (const id of drawnIds) {
|
|
33763
|
+
const p = byId.get(id);
|
|
33764
|
+
if (!p) return null;
|
|
33765
|
+
drawn.push(p);
|
|
33766
|
+
}
|
|
33767
|
+
const drawnSet = new Set(drawnIds);
|
|
33768
|
+
return {
|
|
33769
|
+
pool: participants.filter((p) => !drawnSet.has(p.id)),
|
|
33770
|
+
// Same cap as the live history (see the pop/promote paths).
|
|
33771
|
+
history: drawn.slice(0, 20)
|
|
33772
|
+
};
|
|
33773
|
+
}
|
|
33734
33774
|
function RandomPlayerPicker({
|
|
33735
33775
|
participants,
|
|
33736
33776
|
mode = "wheel",
|
|
@@ -33745,6 +33785,7 @@ function RandomPlayerPicker({
|
|
|
33745
33785
|
trigger = "button",
|
|
33746
33786
|
label = "Spin",
|
|
33747
33787
|
removeWinners = false,
|
|
33788
|
+
initialDrawnIds,
|
|
33748
33789
|
spinDuration = 5e3,
|
|
33749
33790
|
minRevolutions = 4,
|
|
33750
33791
|
maxRevolutions = 7,
|
|
@@ -33771,12 +33812,21 @@ function RandomPlayerPicker({
|
|
|
33771
33812
|
const reducedMotion = usePrefersReducedMotion();
|
|
33772
33813
|
const intensityCfg = INTENSITY_CONFIG[intensity];
|
|
33773
33814
|
const physicsDriven = intensity === "dramatic" && !reducedMotion;
|
|
33774
|
-
const [
|
|
33815
|
+
const [draftSeed] = (0, import_react73.useState)(
|
|
33816
|
+
() => computeDraftSeed(participants, initialDrawnIds, removeWinners)
|
|
33817
|
+
);
|
|
33818
|
+
const [pool, setPool] = (0, import_react73.useState)(
|
|
33819
|
+
draftSeed ? draftSeed.pool : participants
|
|
33820
|
+
);
|
|
33775
33821
|
const [rotation, setRotation] = (0, import_react73.useState)(0);
|
|
33776
33822
|
const [reelY, setReelY] = (0, import_react73.useState)(0);
|
|
33777
33823
|
const [spinning, setSpinning] = (0, import_react73.useState)(false);
|
|
33778
|
-
const [winner, setWinner] = (0, import_react73.useState)(
|
|
33779
|
-
|
|
33824
|
+
const [winner, setWinner] = (0, import_react73.useState)(
|
|
33825
|
+
draftSeed ? draftSeed.history[0] ?? null : null
|
|
33826
|
+
);
|
|
33827
|
+
const [history, setHistory] = (0, import_react73.useState)(
|
|
33828
|
+
draftSeed ? draftSeed.history : []
|
|
33829
|
+
);
|
|
33780
33830
|
const [revealKey, setRevealKey] = (0, import_react73.useState)(0);
|
|
33781
33831
|
const [particles, setParticles] = (0, import_react73.useState)([]);
|
|
33782
33832
|
const winnerTimer = (0, import_react73.useRef)(null);
|
|
@@ -33788,7 +33838,9 @@ function RandomPlayerPicker({
|
|
|
33788
33838
|
const tickAudioRef = (0, import_react73.useRef)(null);
|
|
33789
33839
|
const winAudioRef = (0, import_react73.useRef)(null);
|
|
33790
33840
|
const containerRef = (0, import_react73.useRef)(null);
|
|
33791
|
-
const prevIdsRef = (0, import_react73.useRef)(
|
|
33841
|
+
const prevIdsRef = (0, import_react73.useRef)(
|
|
33842
|
+
draftSeed ? participants.map((p) => p.id).join("|") : ""
|
|
33843
|
+
);
|
|
33792
33844
|
const wheelSvgRef = (0, import_react73.useRef)(null);
|
|
33793
33845
|
const reelTapeRef = (0, import_react73.useRef)(null);
|
|
33794
33846
|
const rafRef = (0, import_react73.useRef)(null);
|
|
@@ -40706,6 +40758,7 @@ function RoundRobinScheduler({
|
|
|
40706
40758
|
resumeRounds,
|
|
40707
40759
|
onTeamsChange,
|
|
40708
40760
|
onGenerate,
|
|
40761
|
+
onBeforeScheduleDiscard,
|
|
40709
40762
|
labels,
|
|
40710
40763
|
ariaLabel = "Round robin scheduler",
|
|
40711
40764
|
className,
|
|
@@ -40741,23 +40794,29 @@ function RoundRobinScheduler({
|
|
|
40741
40794
|
},
|
|
40742
40795
|
[maxTeams, nameMaxLength]
|
|
40743
40796
|
);
|
|
40797
|
+
const gateDiscard = (0, import_react79.useCallback)(
|
|
40798
|
+
(action) => rounds.length === 0 || !onBeforeScheduleDiscard || onBeforeScheduleDiscard(action),
|
|
40799
|
+
[rounds.length, onBeforeScheduleDiscard]
|
|
40800
|
+
);
|
|
40744
40801
|
const addTeams = (0, import_react79.useCallback)(
|
|
40745
40802
|
(raw) => {
|
|
40746
40803
|
const names = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
40747
40804
|
if (names.length === 0) return;
|
|
40805
|
+
if (!gateDiscard("add")) return;
|
|
40748
40806
|
setTeams((prev) => mergeNames(prev, names));
|
|
40749
40807
|
setInput("");
|
|
40750
40808
|
setRounds([]);
|
|
40751
40809
|
},
|
|
40752
|
-
[mergeNames]
|
|
40810
|
+
[mergeNames, gateDiscard]
|
|
40753
40811
|
);
|
|
40754
40812
|
const importTeams = (0, import_react79.useCallback)(
|
|
40755
40813
|
(incoming) => {
|
|
40756
40814
|
if (incoming.length === 0) return;
|
|
40815
|
+
if (!gateDiscard("import")) return;
|
|
40757
40816
|
setTeams((prev) => mergeNames(prev, incoming));
|
|
40758
40817
|
setRounds([]);
|
|
40759
40818
|
},
|
|
40760
|
-
[mergeNames]
|
|
40819
|
+
[mergeNames, gateDiscard]
|
|
40761
40820
|
);
|
|
40762
40821
|
const handleKeyDown = (0, import_react79.useCallback)(
|
|
40763
40822
|
(e) => {
|
|
@@ -40768,10 +40827,14 @@ function RoundRobinScheduler({
|
|
|
40768
40827
|
},
|
|
40769
40828
|
[addTeams, input]
|
|
40770
40829
|
);
|
|
40771
|
-
const removeTeam = (0, import_react79.useCallback)(
|
|
40772
|
-
|
|
40773
|
-
|
|
40774
|
-
|
|
40830
|
+
const removeTeam = (0, import_react79.useCallback)(
|
|
40831
|
+
(idx) => {
|
|
40832
|
+
if (!gateDiscard("remove")) return;
|
|
40833
|
+
setTeams((prev) => prev.filter((_, i) => i !== idx));
|
|
40834
|
+
setRounds([]);
|
|
40835
|
+
},
|
|
40836
|
+
[gateDiscard]
|
|
40837
|
+
);
|
|
40775
40838
|
const handleGenerate = (0, import_react79.useCallback)(() => {
|
|
40776
40839
|
if (teams.length < minTeams) return;
|
|
40777
40840
|
const result = generateSchedule(teams, L.roundLabel);
|
|
@@ -40779,15 +40842,17 @@ function RoundRobinScheduler({
|
|
|
40779
40842
|
onGenerate?.(result);
|
|
40780
40843
|
}, [teams, minTeams, L.roundLabel, onGenerate]);
|
|
40781
40844
|
const handleShuffle = (0, import_react79.useCallback)(() => {
|
|
40845
|
+
if (!gateDiscard("shuffle")) return;
|
|
40782
40846
|
setTeams((prev) => shuffle(prev));
|
|
40783
40847
|
setRounds([]);
|
|
40784
|
-
}, []);
|
|
40848
|
+
}, [gateDiscard]);
|
|
40785
40849
|
const handleClear = (0, import_react79.useCallback)(() => {
|
|
40850
|
+
if (!gateDiscard("clear")) return;
|
|
40786
40851
|
setTeams([]);
|
|
40787
40852
|
setRounds([]);
|
|
40788
40853
|
setInput("");
|
|
40789
40854
|
inputRef.current?.focus();
|
|
40790
|
-
}, []);
|
|
40855
|
+
}, [gateDiscard]);
|
|
40791
40856
|
const canGenerate = teams.length >= minTeams;
|
|
40792
40857
|
const rootStyle = {
|
|
40793
40858
|
borderRadius: 16,
|
|
@@ -41248,6 +41313,8 @@ function Scoreboard({
|
|
|
41248
41313
|
onRoundAdvance,
|
|
41249
41314
|
onNewGame,
|
|
41250
41315
|
onReset,
|
|
41316
|
+
onBeforeReset,
|
|
41317
|
+
onBeforeNewGame,
|
|
41251
41318
|
nameMaxLength,
|
|
41252
41319
|
labels,
|
|
41253
41320
|
ariaLabel = "Scoreboard",
|
|
@@ -41319,19 +41386,21 @@ function Scoreboard({
|
|
|
41319
41386
|
[minTeams]
|
|
41320
41387
|
);
|
|
41321
41388
|
const resetScores = (0, import_react80.useCallback)(() => {
|
|
41389
|
+
if (onBeforeReset && !onBeforeReset()) return;
|
|
41322
41390
|
setTeams((prev) => prev.map((t) => ({ ...t, score: 0 })));
|
|
41323
41391
|
setRound(1);
|
|
41324
41392
|
setHistory([]);
|
|
41325
41393
|
setHistoryOpen(false);
|
|
41326
41394
|
onReset?.();
|
|
41327
|
-
}, [onReset]);
|
|
41395
|
+
}, [onReset, onBeforeReset]);
|
|
41328
41396
|
const newGame = (0, import_react80.useCallback)(() => {
|
|
41397
|
+
if (onBeforeNewGame && !onBeforeNewGame()) return;
|
|
41329
41398
|
setTeams(createDefaultTeams(seedCount, L.teamNamePrefix));
|
|
41330
41399
|
setRound(1);
|
|
41331
41400
|
setHistory([]);
|
|
41332
41401
|
setHistoryOpen(false);
|
|
41333
41402
|
onNewGame?.();
|
|
41334
|
-
}, [seedCount, L.teamNamePrefix, onNewGame]);
|
|
41403
|
+
}, [seedCount, L.teamNamePrefix, onNewGame, onBeforeNewGame]);
|
|
41335
41404
|
const nextRound = (0, import_react80.useCallback)(() => {
|
|
41336
41405
|
const snapshot = {
|
|
41337
41406
|
round,
|