@digilogiclabs/saas-factory-ui 2.7.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/index.d.mts
CHANGED
|
@@ -4706,6 +4706,17 @@ interface DiceRollerProps {
|
|
|
4706
4706
|
showHistory?: boolean;
|
|
4707
4707
|
/** Max entries in the history strip. Default 8. */
|
|
4708
4708
|
historyMax?: number;
|
|
4709
|
+
/**
|
|
4710
|
+
* Seed the history strip from a persisted session — newest first, the
|
|
4711
|
+
* same entries consumers capture from `onRoll`. One-shot: read on
|
|
4712
|
+
* mount, ignored afterwards; clamped to `historyMax`. Only the strip is
|
|
4713
|
+
* seeded — the dice arena and result chips stay in their pre-roll state
|
|
4714
|
+
* (a settled pose can't be faithfully reproduced).
|
|
4715
|
+
*/
|
|
4716
|
+
initialHistory?: Array<{
|
|
4717
|
+
vals: number[];
|
|
4718
|
+
total: number;
|
|
4719
|
+
}>;
|
|
4709
4720
|
/**
|
|
4710
4721
|
* Imperative handle — assign a ref and call `rollRef.current?.()`
|
|
4711
4722
|
* to trigger a roll from outside the component. Works with any
|
|
@@ -4749,7 +4760,7 @@ declare function d6LandingRotation(value: number): {
|
|
|
4749
4760
|
x: number;
|
|
4750
4761
|
y: number;
|
|
4751
4762
|
};
|
|
4752
|
-
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;
|
|
4763
|
+
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;
|
|
4753
4764
|
declare namespace DiceRoller {
|
|
4754
4765
|
var displayName: string;
|
|
4755
4766
|
}
|
|
@@ -4927,6 +4938,25 @@ interface CoinFlipperProps {
|
|
|
4927
4938
|
showHistory?: boolean;
|
|
4928
4939
|
/** Max entries in history. Default 20. */
|
|
4929
4940
|
historyMax?: number;
|
|
4941
|
+
/**
|
|
4942
|
+
* Seed the history strip from a persisted session — newest first, the
|
|
4943
|
+
* results consumers capture from `onFlip`. One-shot: read on mount,
|
|
4944
|
+
* ignored afterwards; clamped to `historyMax`. The coin face stays in
|
|
4945
|
+
* its pre-flip pose.
|
|
4946
|
+
*/
|
|
4947
|
+
initialHistory?: CoinResult[];
|
|
4948
|
+
/**
|
|
4949
|
+
* Seed the H/T counters from a persisted session. Kept separate from
|
|
4950
|
+
* `initialHistory` because stats count ALL flips while the history
|
|
4951
|
+
* strip is capped at `historyMax`. One-shot: read on mount. When
|
|
4952
|
+
* omitted alongside `initialHistory`, the counters are derived from the
|
|
4953
|
+
* seeded strip instead (a lower bound if the strip was capped) — the
|
|
4954
|
+
* history panel only renders while the counters are non-zero.
|
|
4955
|
+
*/
|
|
4956
|
+
initialStats?: {
|
|
4957
|
+
heads: number;
|
|
4958
|
+
tails: number;
|
|
4959
|
+
};
|
|
4930
4960
|
/** Imperative handle — call `flipRef.current?.()` to flip externally. */
|
|
4931
4961
|
flipRef?: MutableRefObject<(() => void) | null>;
|
|
4932
4962
|
/** Accessible label. */
|
|
@@ -4934,7 +4964,7 @@ interface CoinFlipperProps {
|
|
|
4934
4964
|
/** CSS class on root element. */
|
|
4935
4965
|
className?: string;
|
|
4936
4966
|
}
|
|
4937
|
-
declare function CoinFlipper({ theme, darkMode, size, autoFlip, onFlip, trigger, label, headsLabel, tailsLabel, showHistory, historyMax, flipRef, ariaLabel, className, }: CoinFlipperProps): react_jsx_runtime.JSX.Element;
|
|
4967
|
+
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;
|
|
4938
4968
|
|
|
4939
4969
|
interface RandomPlayerParticipant {
|
|
4940
4970
|
/** Stable identifier — required for keying and winner equality. */
|
|
@@ -5040,6 +5070,17 @@ interface RandomPlayerPickerProps {
|
|
|
5040
5070
|
label?: string;
|
|
5041
5071
|
/** Pop each winner from the pool after reveal. Default false. */
|
|
5042
5072
|
removeWinners?: boolean;
|
|
5073
|
+
/**
|
|
5074
|
+
* Resume a draft from a persisted session: participant ids already
|
|
5075
|
+
* drawn, newest first (the history consumers capture from `onPick`).
|
|
5076
|
+
* One-shot: read on mount, ignored afterwards. Only applied when
|
|
5077
|
+
* `removeWinners` is true — the drawn participants are removed from the
|
|
5078
|
+
* starting pool, seeded into the pick history, and the newest one is
|
|
5079
|
+
* shown on the winner card. Fail-closed: if any id doesn't resolve
|
|
5080
|
+
* against `participants` (or ids repeat), the whole seed is ignored
|
|
5081
|
+
* rather than half-restoring a stale draft.
|
|
5082
|
+
*/
|
|
5083
|
+
initialDrawnIds?: string[];
|
|
5043
5084
|
/** Spin animation duration in ms. Default 5000. */
|
|
5044
5085
|
spinDuration?: number;
|
|
5045
5086
|
/** Lower bound on full revolutions. Default 4. */
|
|
@@ -5129,7 +5170,7 @@ interface RandomPlayerPickerProps {
|
|
|
5129
5170
|
/** Accessible label for the wheel root. */
|
|
5130
5171
|
ariaLabel?: string;
|
|
5131
5172
|
}
|
|
5132
|
-
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;
|
|
5173
|
+
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;
|
|
5133
5174
|
|
|
5134
5175
|
type HeroBannerTransition = "fade" | "slide" | "zoom" | "blur" | "reveal" | "push";
|
|
5135
5176
|
type HeroBannerImageFilter = "none" | "cinematic" | "dramatic" | "cool" | "warm" | "desaturated" | "noir" | "vibrant";
|
|
@@ -5792,6 +5833,15 @@ interface RoundRobinSchedulerProps {
|
|
|
5792
5833
|
onTeamsChange?: (teams: string[]) => void;
|
|
5793
5834
|
/** Called when a new schedule is generated. */
|
|
5794
5835
|
onGenerate?: (rounds: RoundRobinRound[]) => void;
|
|
5836
|
+
/**
|
|
5837
|
+
* Gate for roster edits (add / import / remove / shuffle / clear) that
|
|
5838
|
+
* would discard a generated schedule. Called synchronously BEFORE the
|
|
5839
|
+
* edit, and only while a schedule is on screen; return `false` to abort
|
|
5840
|
+
* the edit and keep the schedule (e.g. after a declined
|
|
5841
|
+
* `window.confirm`). Absent = edits discard the schedule silently, as
|
|
5842
|
+
* before. Explicit "Generate Schedule" regenerations are never gated.
|
|
5843
|
+
*/
|
|
5844
|
+
onBeforeScheduleDiscard?: (action: "add" | "import" | "remove" | "shuffle" | "clear") => boolean;
|
|
5795
5845
|
/** Localized / customized labels. */
|
|
5796
5846
|
labels?: RoundRobinLabels;
|
|
5797
5847
|
/** Accessible label on the root region. */
|
|
@@ -5802,7 +5852,7 @@ interface RoundRobinSchedulerProps {
|
|
|
5802
5852
|
* roster from a spreadsheet. Default `true`. */
|
|
5803
5853
|
enableImport?: boolean;
|
|
5804
5854
|
}
|
|
5805
|
-
declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
|
|
5855
|
+
declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, onBeforeScheduleDiscard, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
|
|
5806
5856
|
declare namespace RoundRobinScheduler {
|
|
5807
5857
|
var displayName: string;
|
|
5808
5858
|
}
|
|
@@ -5866,6 +5916,14 @@ interface ScoreboardProps {
|
|
|
5866
5916
|
* `onRoundAdvance` MUST clear that state here or their saved copy
|
|
5867
5917
|
* diverges from the screen. */
|
|
5868
5918
|
onReset?: () => void;
|
|
5919
|
+
/** Gate for the built-in Reset button. Called synchronously BEFORE any
|
|
5920
|
+
* state is cleared; return `false` to abort (e.g. after a declined
|
|
5921
|
+
* `window.confirm` when recorded rounds would be discarded). Absent =
|
|
5922
|
+
* Reset applies immediately, as before. */
|
|
5923
|
+
onBeforeReset?: () => boolean;
|
|
5924
|
+
/** Gate for the built-in New Game button — same contract as
|
|
5925
|
+
* `onBeforeReset`. */
|
|
5926
|
+
onBeforeNewGame?: () => boolean;
|
|
5869
5927
|
/** Max characters accepted in a team-name input. Unlimited by default. */
|
|
5870
5928
|
nameMaxLength?: number;
|
|
5871
5929
|
/** Localized / customized labels. */
|
|
@@ -5875,7 +5933,7 @@ interface ScoreboardProps {
|
|
|
5875
5933
|
/** CSS class on root element. */
|
|
5876
5934
|
className?: string;
|
|
5877
5935
|
}
|
|
5878
|
-
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;
|
|
5936
|
+
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;
|
|
5879
5937
|
declare namespace Scoreboard {
|
|
5880
5938
|
var displayName: string;
|
|
5881
5939
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4706,6 +4706,17 @@ interface DiceRollerProps {
|
|
|
4706
4706
|
showHistory?: boolean;
|
|
4707
4707
|
/** Max entries in the history strip. Default 8. */
|
|
4708
4708
|
historyMax?: number;
|
|
4709
|
+
/**
|
|
4710
|
+
* Seed the history strip from a persisted session — newest first, the
|
|
4711
|
+
* same entries consumers capture from `onRoll`. One-shot: read on
|
|
4712
|
+
* mount, ignored afterwards; clamped to `historyMax`. Only the strip is
|
|
4713
|
+
* seeded — the dice arena and result chips stay in their pre-roll state
|
|
4714
|
+
* (a settled pose can't be faithfully reproduced).
|
|
4715
|
+
*/
|
|
4716
|
+
initialHistory?: Array<{
|
|
4717
|
+
vals: number[];
|
|
4718
|
+
total: number;
|
|
4719
|
+
}>;
|
|
4709
4720
|
/**
|
|
4710
4721
|
* Imperative handle — assign a ref and call `rollRef.current?.()`
|
|
4711
4722
|
* to trigger a roll from outside the component. Works with any
|
|
@@ -4749,7 +4760,7 @@ declare function d6LandingRotation(value: number): {
|
|
|
4749
4760
|
x: number;
|
|
4750
4761
|
y: number;
|
|
4751
4762
|
};
|
|
4752
|
-
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;
|
|
4763
|
+
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;
|
|
4753
4764
|
declare namespace DiceRoller {
|
|
4754
4765
|
var displayName: string;
|
|
4755
4766
|
}
|
|
@@ -4927,6 +4938,25 @@ interface CoinFlipperProps {
|
|
|
4927
4938
|
showHistory?: boolean;
|
|
4928
4939
|
/** Max entries in history. Default 20. */
|
|
4929
4940
|
historyMax?: number;
|
|
4941
|
+
/**
|
|
4942
|
+
* Seed the history strip from a persisted session — newest first, the
|
|
4943
|
+
* results consumers capture from `onFlip`. One-shot: read on mount,
|
|
4944
|
+
* ignored afterwards; clamped to `historyMax`. The coin face stays in
|
|
4945
|
+
* its pre-flip pose.
|
|
4946
|
+
*/
|
|
4947
|
+
initialHistory?: CoinResult[];
|
|
4948
|
+
/**
|
|
4949
|
+
* Seed the H/T counters from a persisted session. Kept separate from
|
|
4950
|
+
* `initialHistory` because stats count ALL flips while the history
|
|
4951
|
+
* strip is capped at `historyMax`. One-shot: read on mount. When
|
|
4952
|
+
* omitted alongside `initialHistory`, the counters are derived from the
|
|
4953
|
+
* seeded strip instead (a lower bound if the strip was capped) — the
|
|
4954
|
+
* history panel only renders while the counters are non-zero.
|
|
4955
|
+
*/
|
|
4956
|
+
initialStats?: {
|
|
4957
|
+
heads: number;
|
|
4958
|
+
tails: number;
|
|
4959
|
+
};
|
|
4930
4960
|
/** Imperative handle — call `flipRef.current?.()` to flip externally. */
|
|
4931
4961
|
flipRef?: MutableRefObject<(() => void) | null>;
|
|
4932
4962
|
/** Accessible label. */
|
|
@@ -4934,7 +4964,7 @@ interface CoinFlipperProps {
|
|
|
4934
4964
|
/** CSS class on root element. */
|
|
4935
4965
|
className?: string;
|
|
4936
4966
|
}
|
|
4937
|
-
declare function CoinFlipper({ theme, darkMode, size, autoFlip, onFlip, trigger, label, headsLabel, tailsLabel, showHistory, historyMax, flipRef, ariaLabel, className, }: CoinFlipperProps): react_jsx_runtime.JSX.Element;
|
|
4967
|
+
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;
|
|
4938
4968
|
|
|
4939
4969
|
interface RandomPlayerParticipant {
|
|
4940
4970
|
/** Stable identifier — required for keying and winner equality. */
|
|
@@ -5040,6 +5070,17 @@ interface RandomPlayerPickerProps {
|
|
|
5040
5070
|
label?: string;
|
|
5041
5071
|
/** Pop each winner from the pool after reveal. Default false. */
|
|
5042
5072
|
removeWinners?: boolean;
|
|
5073
|
+
/**
|
|
5074
|
+
* Resume a draft from a persisted session: participant ids already
|
|
5075
|
+
* drawn, newest first (the history consumers capture from `onPick`).
|
|
5076
|
+
* One-shot: read on mount, ignored afterwards. Only applied when
|
|
5077
|
+
* `removeWinners` is true — the drawn participants are removed from the
|
|
5078
|
+
* starting pool, seeded into the pick history, and the newest one is
|
|
5079
|
+
* shown on the winner card. Fail-closed: if any id doesn't resolve
|
|
5080
|
+
* against `participants` (or ids repeat), the whole seed is ignored
|
|
5081
|
+
* rather than half-restoring a stale draft.
|
|
5082
|
+
*/
|
|
5083
|
+
initialDrawnIds?: string[];
|
|
5043
5084
|
/** Spin animation duration in ms. Default 5000. */
|
|
5044
5085
|
spinDuration?: number;
|
|
5045
5086
|
/** Lower bound on full revolutions. Default 4. */
|
|
@@ -5129,7 +5170,7 @@ interface RandomPlayerPickerProps {
|
|
|
5129
5170
|
/** Accessible label for the wheel root. */
|
|
5130
5171
|
ariaLabel?: string;
|
|
5131
5172
|
}
|
|
5132
|
-
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;
|
|
5173
|
+
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;
|
|
5133
5174
|
|
|
5134
5175
|
type HeroBannerTransition = "fade" | "slide" | "zoom" | "blur" | "reveal" | "push";
|
|
5135
5176
|
type HeroBannerImageFilter = "none" | "cinematic" | "dramatic" | "cool" | "warm" | "desaturated" | "noir" | "vibrant";
|
|
@@ -5792,6 +5833,15 @@ interface RoundRobinSchedulerProps {
|
|
|
5792
5833
|
onTeamsChange?: (teams: string[]) => void;
|
|
5793
5834
|
/** Called when a new schedule is generated. */
|
|
5794
5835
|
onGenerate?: (rounds: RoundRobinRound[]) => void;
|
|
5836
|
+
/**
|
|
5837
|
+
* Gate for roster edits (add / import / remove / shuffle / clear) that
|
|
5838
|
+
* would discard a generated schedule. Called synchronously BEFORE the
|
|
5839
|
+
* edit, and only while a schedule is on screen; return `false` to abort
|
|
5840
|
+
* the edit and keep the schedule (e.g. after a declined
|
|
5841
|
+
* `window.confirm`). Absent = edits discard the schedule silently, as
|
|
5842
|
+
* before. Explicit "Generate Schedule" regenerations are never gated.
|
|
5843
|
+
*/
|
|
5844
|
+
onBeforeScheduleDiscard?: (action: "add" | "import" | "remove" | "shuffle" | "clear") => boolean;
|
|
5795
5845
|
/** Localized / customized labels. */
|
|
5796
5846
|
labels?: RoundRobinLabels;
|
|
5797
5847
|
/** Accessible label on the root region. */
|
|
@@ -5802,7 +5852,7 @@ interface RoundRobinSchedulerProps {
|
|
|
5802
5852
|
* roster from a spreadsheet. Default `true`. */
|
|
5803
5853
|
enableImport?: boolean;
|
|
5804
5854
|
}
|
|
5805
|
-
declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
|
|
5855
|
+
declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, onBeforeScheduleDiscard, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
|
|
5806
5856
|
declare namespace RoundRobinScheduler {
|
|
5807
5857
|
var displayName: string;
|
|
5808
5858
|
}
|
|
@@ -5866,6 +5916,14 @@ interface ScoreboardProps {
|
|
|
5866
5916
|
* `onRoundAdvance` MUST clear that state here or their saved copy
|
|
5867
5917
|
* diverges from the screen. */
|
|
5868
5918
|
onReset?: () => void;
|
|
5919
|
+
/** Gate for the built-in Reset button. Called synchronously BEFORE any
|
|
5920
|
+
* state is cleared; return `false` to abort (e.g. after a declined
|
|
5921
|
+
* `window.confirm` when recorded rounds would be discarded). Absent =
|
|
5922
|
+
* Reset applies immediately, as before. */
|
|
5923
|
+
onBeforeReset?: () => boolean;
|
|
5924
|
+
/** Gate for the built-in New Game button — same contract as
|
|
5925
|
+
* `onBeforeReset`. */
|
|
5926
|
+
onBeforeNewGame?: () => boolean;
|
|
5869
5927
|
/** Max characters accepted in a team-name input. Unlimited by default. */
|
|
5870
5928
|
nameMaxLength?: number;
|
|
5871
5929
|
/** Localized / customized labels. */
|
|
@@ -5875,7 +5933,7 @@ interface ScoreboardProps {
|
|
|
5875
5933
|
/** CSS class on root element. */
|
|
5876
5934
|
className?: string;
|
|
5877
5935
|
}
|
|
5878
|
-
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;
|
|
5936
|
+
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;
|
|
5879
5937
|
declare namespace Scoreboard {
|
|
5880
5938
|
var displayName: string;
|
|
5881
5939
|
}
|
package/dist/index.js
CHANGED
|
@@ -30710,6 +30710,7 @@ function DiceRoller({
|
|
|
30710
30710
|
iconEmoji = "\u{1F3B2}",
|
|
30711
30711
|
showHistory = false,
|
|
30712
30712
|
historyMax = 8,
|
|
30713
|
+
initialHistory,
|
|
30713
30714
|
rollRef,
|
|
30714
30715
|
arenaHeight: arenaHeightProp,
|
|
30715
30716
|
hideResults = false,
|
|
@@ -30721,7 +30722,9 @@ function DiceRoller({
|
|
|
30721
30722
|
const dark = useDarkMode(darkMode);
|
|
30722
30723
|
const [rolling, setRolling] = (0, import_react68.useState)(false);
|
|
30723
30724
|
const [results, setResults] = (0, import_react68.useState)(null);
|
|
30724
|
-
const [history, setHistory] = (0, import_react68.useState)(
|
|
30725
|
+
const [history, setHistory] = (0, import_react68.useState)(
|
|
30726
|
+
() => initialHistory && initialHistory.length > 0 ? initialHistory.slice(0, historyMax) : []
|
|
30727
|
+
);
|
|
30725
30728
|
const dieWrapperRefs = (0, import_react68.useRef)([]);
|
|
30726
30729
|
const cubeRefs = (0, import_react68.useRef)([]);
|
|
30727
30730
|
const shadowRefs = (0, import_react68.useRef)([]);
|
|
@@ -30895,7 +30898,10 @@ function DiceRoller({
|
|
|
30895
30898
|
defaultPositions,
|
|
30896
30899
|
half
|
|
30897
30900
|
]);
|
|
30901
|
+
const prevSidesRef = (0, import_react68.useRef)(sides);
|
|
30898
30902
|
(0, import_react68.useEffect)(() => {
|
|
30903
|
+
if (prevSidesRef.current === sides) return;
|
|
30904
|
+
prevSidesRef.current = sides;
|
|
30899
30905
|
setHistory([]);
|
|
30900
30906
|
}, [sides]);
|
|
30901
30907
|
const roll = (0, import_react68.useCallback)(() => {
|
|
@@ -32964,6 +32970,8 @@ function CoinFlipper({
|
|
|
32964
32970
|
tailsLabel = "Tails",
|
|
32965
32971
|
showHistory = false,
|
|
32966
32972
|
historyMax = 20,
|
|
32973
|
+
initialHistory,
|
|
32974
|
+
initialStats,
|
|
32967
32975
|
flipRef,
|
|
32968
32976
|
ariaLabel,
|
|
32969
32977
|
className = ""
|
|
@@ -32972,8 +32980,23 @@ function CoinFlipper({
|
|
|
32972
32980
|
const tc = typeof theme5 === "string" ? PRESETS3[theme5] || PRESETS3.gold : theme5;
|
|
32973
32981
|
const [result, setResult] = (0, import_react70.useState)(null);
|
|
32974
32982
|
const [flipping, setFlipping] = (0, import_react70.useState)(false);
|
|
32975
|
-
const [history, setHistory] = (0, import_react70.useState)(
|
|
32976
|
-
|
|
32983
|
+
const [history, setHistory] = (0, import_react70.useState)(
|
|
32984
|
+
() => initialHistory && initialHistory.length > 0 ? initialHistory.slice(0, historyMax).map((result2, i) => ({ result: result2, id: -(i + 1) })) : []
|
|
32985
|
+
);
|
|
32986
|
+
const [stats, setStats] = (0, import_react70.useState)(() => {
|
|
32987
|
+
if (initialStats) {
|
|
32988
|
+
return {
|
|
32989
|
+
heads: Math.max(0, Math.floor(initialStats.heads)),
|
|
32990
|
+
tails: Math.max(0, Math.floor(initialStats.tails))
|
|
32991
|
+
};
|
|
32992
|
+
}
|
|
32993
|
+
if (initialHistory && initialHistory.length > 0) {
|
|
32994
|
+
const seeded = initialHistory.slice(0, historyMax);
|
|
32995
|
+
const heads = seeded.filter((r) => r === "heads").length;
|
|
32996
|
+
return { heads, tails: seeded.length - heads };
|
|
32997
|
+
}
|
|
32998
|
+
return { heads: 0, tails: 0 };
|
|
32999
|
+
});
|
|
32977
33000
|
const flipIdRef = (0, import_react70.useRef)(0);
|
|
32978
33001
|
const coinRef = (0, import_react70.useRef)(null);
|
|
32979
33002
|
const shadowRef = (0, import_react70.useRef)(null);
|
|
@@ -33885,6 +33908,23 @@ function ReelStage({
|
|
|
33885
33908
|
}
|
|
33886
33909
|
);
|
|
33887
33910
|
}
|
|
33911
|
+
function computeDraftSeed(participants, drawnIds, removeWinners) {
|
|
33912
|
+
if (!removeWinners || !drawnIds || drawnIds.length === 0) return null;
|
|
33913
|
+
if (new Set(drawnIds).size !== drawnIds.length) return null;
|
|
33914
|
+
const byId = new Map(participants.map((p) => [p.id, p]));
|
|
33915
|
+
const drawn = [];
|
|
33916
|
+
for (const id of drawnIds) {
|
|
33917
|
+
const p = byId.get(id);
|
|
33918
|
+
if (!p) return null;
|
|
33919
|
+
drawn.push(p);
|
|
33920
|
+
}
|
|
33921
|
+
const drawnSet = new Set(drawnIds);
|
|
33922
|
+
return {
|
|
33923
|
+
pool: participants.filter((p) => !drawnSet.has(p.id)),
|
|
33924
|
+
// Same cap as the live history (see the pop/promote paths).
|
|
33925
|
+
history: drawn.slice(0, 20)
|
|
33926
|
+
};
|
|
33927
|
+
}
|
|
33888
33928
|
function RandomPlayerPicker({
|
|
33889
33929
|
participants,
|
|
33890
33930
|
mode = "wheel",
|
|
@@ -33899,6 +33939,7 @@ function RandomPlayerPicker({
|
|
|
33899
33939
|
trigger = "button",
|
|
33900
33940
|
label = "Spin",
|
|
33901
33941
|
removeWinners = false,
|
|
33942
|
+
initialDrawnIds,
|
|
33902
33943
|
spinDuration = 5e3,
|
|
33903
33944
|
minRevolutions = 4,
|
|
33904
33945
|
maxRevolutions = 7,
|
|
@@ -33925,12 +33966,21 @@ function RandomPlayerPicker({
|
|
|
33925
33966
|
const reducedMotion = usePrefersReducedMotion();
|
|
33926
33967
|
const intensityCfg = INTENSITY_CONFIG[intensity];
|
|
33927
33968
|
const physicsDriven = intensity === "dramatic" && !reducedMotion;
|
|
33928
|
-
const [
|
|
33969
|
+
const [draftSeed] = (0, import_react71.useState)(
|
|
33970
|
+
() => computeDraftSeed(participants, initialDrawnIds, removeWinners)
|
|
33971
|
+
);
|
|
33972
|
+
const [pool, setPool] = (0, import_react71.useState)(
|
|
33973
|
+
draftSeed ? draftSeed.pool : participants
|
|
33974
|
+
);
|
|
33929
33975
|
const [rotation, setRotation] = (0, import_react71.useState)(0);
|
|
33930
33976
|
const [reelY, setReelY] = (0, import_react71.useState)(0);
|
|
33931
33977
|
const [spinning, setSpinning] = (0, import_react71.useState)(false);
|
|
33932
|
-
const [winner, setWinner] = (0, import_react71.useState)(
|
|
33933
|
-
|
|
33978
|
+
const [winner, setWinner] = (0, import_react71.useState)(
|
|
33979
|
+
draftSeed ? draftSeed.history[0] ?? null : null
|
|
33980
|
+
);
|
|
33981
|
+
const [history, setHistory] = (0, import_react71.useState)(
|
|
33982
|
+
draftSeed ? draftSeed.history : []
|
|
33983
|
+
);
|
|
33934
33984
|
const [revealKey, setRevealKey] = (0, import_react71.useState)(0);
|
|
33935
33985
|
const [particles, setParticles] = (0, import_react71.useState)([]);
|
|
33936
33986
|
const winnerTimer = (0, import_react71.useRef)(null);
|
|
@@ -33942,7 +33992,9 @@ function RandomPlayerPicker({
|
|
|
33942
33992
|
const tickAudioRef = (0, import_react71.useRef)(null);
|
|
33943
33993
|
const winAudioRef = (0, import_react71.useRef)(null);
|
|
33944
33994
|
const containerRef = (0, import_react71.useRef)(null);
|
|
33945
|
-
const prevIdsRef = (0, import_react71.useRef)(
|
|
33995
|
+
const prevIdsRef = (0, import_react71.useRef)(
|
|
33996
|
+
draftSeed ? participants.map((p) => p.id).join("|") : ""
|
|
33997
|
+
);
|
|
33946
33998
|
const wheelSvgRef = (0, import_react71.useRef)(null);
|
|
33947
33999
|
const reelTapeRef = (0, import_react71.useRef)(null);
|
|
33948
34000
|
const rafRef = (0, import_react71.useRef)(null);
|
|
@@ -41065,6 +41117,7 @@ function RoundRobinScheduler({
|
|
|
41065
41117
|
resumeRounds,
|
|
41066
41118
|
onTeamsChange,
|
|
41067
41119
|
onGenerate,
|
|
41120
|
+
onBeforeScheduleDiscard,
|
|
41068
41121
|
labels,
|
|
41069
41122
|
ariaLabel = "Round robin scheduler",
|
|
41070
41123
|
className,
|
|
@@ -41100,23 +41153,29 @@ function RoundRobinScheduler({
|
|
|
41100
41153
|
},
|
|
41101
41154
|
[maxTeams, nameMaxLength]
|
|
41102
41155
|
);
|
|
41156
|
+
const gateDiscard = (0, import_react77.useCallback)(
|
|
41157
|
+
(action) => rounds.length === 0 || !onBeforeScheduleDiscard || onBeforeScheduleDiscard(action),
|
|
41158
|
+
[rounds.length, onBeforeScheduleDiscard]
|
|
41159
|
+
);
|
|
41103
41160
|
const addTeams = (0, import_react77.useCallback)(
|
|
41104
41161
|
(raw) => {
|
|
41105
41162
|
const names = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
41106
41163
|
if (names.length === 0) return;
|
|
41164
|
+
if (!gateDiscard("add")) return;
|
|
41107
41165
|
setTeams((prev) => mergeNames(prev, names));
|
|
41108
41166
|
setInput("");
|
|
41109
41167
|
setRounds([]);
|
|
41110
41168
|
},
|
|
41111
|
-
[mergeNames]
|
|
41169
|
+
[mergeNames, gateDiscard]
|
|
41112
41170
|
);
|
|
41113
41171
|
const importTeams = (0, import_react77.useCallback)(
|
|
41114
41172
|
(incoming) => {
|
|
41115
41173
|
if (incoming.length === 0) return;
|
|
41174
|
+
if (!gateDiscard("import")) return;
|
|
41116
41175
|
setTeams((prev) => mergeNames(prev, incoming));
|
|
41117
41176
|
setRounds([]);
|
|
41118
41177
|
},
|
|
41119
|
-
[mergeNames]
|
|
41178
|
+
[mergeNames, gateDiscard]
|
|
41120
41179
|
);
|
|
41121
41180
|
const handleKeyDown = (0, import_react77.useCallback)(
|
|
41122
41181
|
(e) => {
|
|
@@ -41127,10 +41186,14 @@ function RoundRobinScheduler({
|
|
|
41127
41186
|
},
|
|
41128
41187
|
[addTeams, input]
|
|
41129
41188
|
);
|
|
41130
|
-
const removeTeam = (0, import_react77.useCallback)(
|
|
41131
|
-
|
|
41132
|
-
|
|
41133
|
-
|
|
41189
|
+
const removeTeam = (0, import_react77.useCallback)(
|
|
41190
|
+
(idx) => {
|
|
41191
|
+
if (!gateDiscard("remove")) return;
|
|
41192
|
+
setTeams((prev) => prev.filter((_, i) => i !== idx));
|
|
41193
|
+
setRounds([]);
|
|
41194
|
+
},
|
|
41195
|
+
[gateDiscard]
|
|
41196
|
+
);
|
|
41134
41197
|
const handleGenerate = (0, import_react77.useCallback)(() => {
|
|
41135
41198
|
if (teams.length < minTeams) return;
|
|
41136
41199
|
const result = generateSchedule(teams, L.roundLabel);
|
|
@@ -41138,15 +41201,17 @@ function RoundRobinScheduler({
|
|
|
41138
41201
|
onGenerate?.(result);
|
|
41139
41202
|
}, [teams, minTeams, L.roundLabel, onGenerate]);
|
|
41140
41203
|
const handleShuffle = (0, import_react77.useCallback)(() => {
|
|
41204
|
+
if (!gateDiscard("shuffle")) return;
|
|
41141
41205
|
setTeams((prev) => shuffle(prev));
|
|
41142
41206
|
setRounds([]);
|
|
41143
|
-
}, []);
|
|
41207
|
+
}, [gateDiscard]);
|
|
41144
41208
|
const handleClear = (0, import_react77.useCallback)(() => {
|
|
41209
|
+
if (!gateDiscard("clear")) return;
|
|
41145
41210
|
setTeams([]);
|
|
41146
41211
|
setRounds([]);
|
|
41147
41212
|
setInput("");
|
|
41148
41213
|
inputRef.current?.focus();
|
|
41149
|
-
}, []);
|
|
41214
|
+
}, [gateDiscard]);
|
|
41150
41215
|
const canGenerate = teams.length >= minTeams;
|
|
41151
41216
|
const rootStyle = {
|
|
41152
41217
|
borderRadius: 16,
|
|
@@ -41607,6 +41672,8 @@ function Scoreboard({
|
|
|
41607
41672
|
onRoundAdvance,
|
|
41608
41673
|
onNewGame,
|
|
41609
41674
|
onReset,
|
|
41675
|
+
onBeforeReset,
|
|
41676
|
+
onBeforeNewGame,
|
|
41610
41677
|
nameMaxLength,
|
|
41611
41678
|
labels,
|
|
41612
41679
|
ariaLabel = "Scoreboard",
|
|
@@ -41678,19 +41745,21 @@ function Scoreboard({
|
|
|
41678
41745
|
[minTeams]
|
|
41679
41746
|
);
|
|
41680
41747
|
const resetScores = (0, import_react78.useCallback)(() => {
|
|
41748
|
+
if (onBeforeReset && !onBeforeReset()) return;
|
|
41681
41749
|
setTeams((prev) => prev.map((t) => ({ ...t, score: 0 })));
|
|
41682
41750
|
setRound(1);
|
|
41683
41751
|
setHistory([]);
|
|
41684
41752
|
setHistoryOpen(false);
|
|
41685
41753
|
onReset?.();
|
|
41686
|
-
}, [onReset]);
|
|
41754
|
+
}, [onReset, onBeforeReset]);
|
|
41687
41755
|
const newGame = (0, import_react78.useCallback)(() => {
|
|
41756
|
+
if (onBeforeNewGame && !onBeforeNewGame()) return;
|
|
41688
41757
|
setTeams(createDefaultTeams(seedCount, L.teamNamePrefix));
|
|
41689
41758
|
setRound(1);
|
|
41690
41759
|
setHistory([]);
|
|
41691
41760
|
setHistoryOpen(false);
|
|
41692
41761
|
onNewGame?.();
|
|
41693
|
-
}, [seedCount, L.teamNamePrefix, onNewGame]);
|
|
41762
|
+
}, [seedCount, L.teamNamePrefix, onNewGame, onBeforeNewGame]);
|
|
41694
41763
|
const nextRound = (0, import_react78.useCallback)(() => {
|
|
41695
41764
|
const snapshot = {
|
|
41696
41765
|
round,
|