@digilogiclabs/saas-factory-ui 2.3.0 → 2.5.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.
@@ -5162,7 +5162,9 @@ declare function TiltCard({ accent, accentSecondary, topLabel, icon, title, subt
5162
5162
  * - Three trigger modes: built-in button / click anywhere / external
5163
5163
  * imperative handle via `rollRef.current()`
5164
5164
  * - Optional roll history strip
5165
- * - Honors `prefers-reduced-motion` (skips physics animation)
5165
+ * - Deliberately tumbles even under `prefers-reduced-motion` a dice
5166
+ * roll is a safe animation and skipping it leaves no feedback at all
5167
+ * (see the note inside `roll()`)
5166
5168
  * - Zero Tailwind dependency — all styles inline
5167
5169
  *
5168
5170
  * Ported to TypeScript and generalized for saas-factory-ui from a
@@ -5584,14 +5586,37 @@ interface RandomPlayerPickerProps {
5584
5586
  renderWinner?: (winner: RandomPlayerParticipant) => ReactNode;
5585
5587
  /** Imperative handle. `spinRef.current?.()` triggers a spin. */
5586
5588
  spinRef?: MutableRefObject<(() => void) | null>;
5589
+ /**
5590
+ * Imperative reset handle. `resetRef.current?.()` restores the pool to
5591
+ * the full `participants` list and clears history/winner — the escape
5592
+ * hatch for consumers that hide the built-in controls
5593
+ * (`showControls={false}`) but still need a "reset draft" affordance
5594
+ * once draft-mode pops drain the pool.
5595
+ */
5596
+ resetRef?: MutableRefObject<(() => void) | null>;
5597
+ /**
5598
+ * Fired whenever the internal pool changes (mount, structural sync,
5599
+ * draft-mode pop, spin-again flush, reset). Draft-mode consumers use
5600
+ * this to mirror the live pool — e.g. to disable an external spin
5601
+ * trigger when the pool drains below 2 instead of presenting a dead
5602
+ * button, and to offer a reset once the draft completes.
5603
+ */
5604
+ onPoolChange?: (pool: RandomPlayerParticipant[]) => void;
5605
+ /**
5606
+ * Caption shown in place of `placeholderCaption` when draft-mode pops
5607
+ * drain the pool below 2 while the roster itself still has 2+ members.
5608
+ * Default: "Draft complete — reset to spin again".
5609
+ */
5610
+ draftCompleteCaption?: string;
5587
5611
  /**
5588
5612
  * Visual intensity preset. Default "normal".
5589
- * - "subtle" / "normal": current behavior — shorter spins, standard
5590
- * ease-out curve.
5591
- * - "dramatic": physics-like spin 2.5× duration, inertia-style
5592
- * curve so motion continues through the full duration with a slow
5593
- * winding-down tail, +12 extra revolutions, plus more
5594
- * particles/glow/shake on reveal.
5613
+ * - "subtle" / "normal": shorter spins, standard CSS ease-out curve.
5614
+ * - "dramatic": physics-driven spin — 2.5× duration, rAF-driven
5615
+ * exponential velocity decay (v ∝ e^(-4t)) that keeps the wheel
5616
+ * visibly winding down through the FULL duration and lands exactly
5617
+ * at the end, +12 extra revolutions, ticks fired on actual
5618
+ * wedge/row crossings, plus more particles/glow/shake on reveal.
5619
+ * Falls back to a 250ms CSS settle under prefers-reduced-motion.
5595
5620
  */
5596
5621
  intensity?: RandomPlayerIntensity;
5597
5622
  /**
@@ -5634,7 +5659,7 @@ interface RandomPlayerPickerProps {
5634
5659
  /** Accessible label for the wheel root. */
5635
5660
  ariaLabel?: string;
5636
5661
  }
5637
- declare function RandomPlayerPicker({ participants, mode, reelVisibleRows, reelRowHeight, theme, darkMode, size, onPick, onSpinStart, onTick, trigger, label, removeWinners, spinDuration, minRevolutions, maxRevolutions, showHistory, showControls, showStats, renderWinner, spinRef, intensity, enableHaptics, tickSoundUrl, winSoundUrl, soundVolume, placeholderMode, placeholderCaption, className, style, ariaLabel, }: RandomPlayerPickerProps): react_jsx_runtime.JSX.Element;
5662
+ 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;
5638
5663
 
5639
5664
  type HeroBannerTransition = "fade" | "slide" | "zoom" | "blur" | "reveal" | "push";
5640
5665
  type HeroBannerImageFilter = "none" | "cinematic" | "dramatic" | "cool" | "warm" | "desaturated" | "noir" | "vibrant";
@@ -6200,10 +6225,20 @@ interface TeamGeneratorProps {
6200
6225
  maxPlayers?: number;
6201
6226
  /** Initial roster. Uncontrolled — the component manages names internally. */
6202
6227
  defaultNames?: string[];
6228
+ /** Initial generated teams (e.g. restored from a saved session).
6229
+ * Uncontrolled — the component takes over after mount. An empty array
6230
+ * is treated as "no teams". */
6231
+ defaultTeams?: string[][];
6203
6232
  /** Called whenever the name pool changes. */
6204
6233
  onNamesChange?: (names: string[]) => void;
6205
6234
  /** Called whenever teams are (re)generated. */
6206
6235
  onGenerate?: (teams: string[][]) => void;
6236
+ /** Called whenever the generated teams change for ANY reason — a
6237
+ * (re)generation, or invalidation to `null` when a player is removed,
6238
+ * the pool is cleared, or the team count changes. Unlike `onGenerate`,
6239
+ * this mirrors the full lifecycle of the on-screen split so hosts can
6240
+ * persist it and restore via `defaultTeams`. */
6241
+ onTeamsChange?: (teams: string[][] | null) => void;
6207
6242
  /** Called whenever the team count selection changes. */
6208
6243
  onTeamCountChange?: (count: number) => void;
6209
6244
  /** Localized / customized labels. */
@@ -6216,7 +6251,7 @@ interface TeamGeneratorProps {
6216
6251
  * CSV / TSV roster from a spreadsheet. Default `true`. */
6217
6252
  enableImport?: boolean;
6218
6253
  }
6219
- declare function TeamGenerator({ theme, darkMode, teamCountOptions, defaultTeamCount, minPlayersPerTeam, maxPlayers, defaultNames, onNamesChange, onGenerate, onTeamCountChange, labels, ariaLabel, className, enableImport, }: TeamGeneratorProps): react_jsx_runtime.JSX.Element;
6254
+ declare function TeamGenerator({ theme, darkMode, teamCountOptions, defaultTeamCount, minPlayersPerTeam, maxPlayers, defaultNames, defaultTeams, onNamesChange, onGenerate, onTeamsChange, onTeamCountChange, labels, ariaLabel, className, enableImport, }: TeamGeneratorProps): react_jsx_runtime.JSX.Element;
6220
6255
  declare namespace TeamGenerator {
6221
6256
  var displayName: string;
6222
6257
  }
@@ -6264,6 +6299,14 @@ interface RoundRobinSchedulerProps {
6264
6299
  darkMode?: boolean;
6265
6300
  /** Minimum teams required to generate a schedule. Default 3. */
6266
6301
  minTeams?: number;
6302
+ /** Maximum roster size. Adds/imports beyond this are ignored. Unlimited
6303
+ * by default — consumers persisting the roster against a capped schema
6304
+ * should set this to the schema cap. */
6305
+ maxTeams?: number;
6306
+ /** Max characters per team name. Longer typed/imported names are
6307
+ * truncated (matching native input maxLength paste behavior).
6308
+ * Unlimited by default. */
6309
+ nameMaxLength?: number;
6267
6310
  /** Initial roster. Uncontrolled. */
6268
6311
  defaultTeams?: string[];
6269
6312
  /**
@@ -6289,7 +6332,7 @@ interface RoundRobinSchedulerProps {
6289
6332
  * roster from a spreadsheet. Default `true`. */
6290
6333
  enableImport?: boolean;
6291
6334
  }
6292
- declare function RoundRobinScheduler({ theme, darkMode, minTeams, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
6335
+ declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
6293
6336
  declare namespace RoundRobinScheduler {
6294
6337
  var displayName: string;
6295
6338
  }
@@ -6348,6 +6391,13 @@ interface ScoreboardProps {
6348
6391
  onRoundAdvance?: (snapshot: ScoreboardRoundSnapshot) => void;
6349
6392
  /** Called when the user presses "New Game". */
6350
6393
  onNewGame?: () => void;
6394
+ /** Called when the user presses "Reset" (scores zeroed, round counter and
6395
+ * history cleared, names kept). Consumers persisting round/history via
6396
+ * `onRoundAdvance` MUST clear that state here or their saved copy
6397
+ * diverges from the screen. */
6398
+ onReset?: () => void;
6399
+ /** Max characters accepted in a team-name input. Unlimited by default. */
6400
+ nameMaxLength?: number;
6351
6401
  /** Localized / customized labels. */
6352
6402
  labels?: ScoreboardLabels;
6353
6403
  /** Accessible label on the root region. */
@@ -6355,7 +6405,7 @@ interface ScoreboardProps {
6355
6405
  /** CSS class on root element. */
6356
6406
  className?: string;
6357
6407
  }
6358
- declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
6408
+ 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;
6359
6409
  declare namespace Scoreboard {
6360
6410
  var displayName: string;
6361
6411
  }
@@ -5162,7 +5162,9 @@ declare function TiltCard({ accent, accentSecondary, topLabel, icon, title, subt
5162
5162
  * - Three trigger modes: built-in button / click anywhere / external
5163
5163
  * imperative handle via `rollRef.current()`
5164
5164
  * - Optional roll history strip
5165
- * - Honors `prefers-reduced-motion` (skips physics animation)
5165
+ * - Deliberately tumbles even under `prefers-reduced-motion` a dice
5166
+ * roll is a safe animation and skipping it leaves no feedback at all
5167
+ * (see the note inside `roll()`)
5166
5168
  * - Zero Tailwind dependency — all styles inline
5167
5169
  *
5168
5170
  * Ported to TypeScript and generalized for saas-factory-ui from a
@@ -5584,14 +5586,37 @@ interface RandomPlayerPickerProps {
5584
5586
  renderWinner?: (winner: RandomPlayerParticipant) => ReactNode;
5585
5587
  /** Imperative handle. `spinRef.current?.()` triggers a spin. */
5586
5588
  spinRef?: MutableRefObject<(() => void) | null>;
5589
+ /**
5590
+ * Imperative reset handle. `resetRef.current?.()` restores the pool to
5591
+ * the full `participants` list and clears history/winner — the escape
5592
+ * hatch for consumers that hide the built-in controls
5593
+ * (`showControls={false}`) but still need a "reset draft" affordance
5594
+ * once draft-mode pops drain the pool.
5595
+ */
5596
+ resetRef?: MutableRefObject<(() => void) | null>;
5597
+ /**
5598
+ * Fired whenever the internal pool changes (mount, structural sync,
5599
+ * draft-mode pop, spin-again flush, reset). Draft-mode consumers use
5600
+ * this to mirror the live pool — e.g. to disable an external spin
5601
+ * trigger when the pool drains below 2 instead of presenting a dead
5602
+ * button, and to offer a reset once the draft completes.
5603
+ */
5604
+ onPoolChange?: (pool: RandomPlayerParticipant[]) => void;
5605
+ /**
5606
+ * Caption shown in place of `placeholderCaption` when draft-mode pops
5607
+ * drain the pool below 2 while the roster itself still has 2+ members.
5608
+ * Default: "Draft complete — reset to spin again".
5609
+ */
5610
+ draftCompleteCaption?: string;
5587
5611
  /**
5588
5612
  * Visual intensity preset. Default "normal".
5589
- * - "subtle" / "normal": current behavior — shorter spins, standard
5590
- * ease-out curve.
5591
- * - "dramatic": physics-like spin 2.5× duration, inertia-style
5592
- * curve so motion continues through the full duration with a slow
5593
- * winding-down tail, +12 extra revolutions, plus more
5594
- * particles/glow/shake on reveal.
5613
+ * - "subtle" / "normal": shorter spins, standard CSS ease-out curve.
5614
+ * - "dramatic": physics-driven spin — 2.5× duration, rAF-driven
5615
+ * exponential velocity decay (v ∝ e^(-4t)) that keeps the wheel
5616
+ * visibly winding down through the FULL duration and lands exactly
5617
+ * at the end, +12 extra revolutions, ticks fired on actual
5618
+ * wedge/row crossings, plus more particles/glow/shake on reveal.
5619
+ * Falls back to a 250ms CSS settle under prefers-reduced-motion.
5595
5620
  */
5596
5621
  intensity?: RandomPlayerIntensity;
5597
5622
  /**
@@ -5634,7 +5659,7 @@ interface RandomPlayerPickerProps {
5634
5659
  /** Accessible label for the wheel root. */
5635
5660
  ariaLabel?: string;
5636
5661
  }
5637
- declare function RandomPlayerPicker({ participants, mode, reelVisibleRows, reelRowHeight, theme, darkMode, size, onPick, onSpinStart, onTick, trigger, label, removeWinners, spinDuration, minRevolutions, maxRevolutions, showHistory, showControls, showStats, renderWinner, spinRef, intensity, enableHaptics, tickSoundUrl, winSoundUrl, soundVolume, placeholderMode, placeholderCaption, className, style, ariaLabel, }: RandomPlayerPickerProps): react_jsx_runtime.JSX.Element;
5662
+ 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;
5638
5663
 
5639
5664
  type HeroBannerTransition = "fade" | "slide" | "zoom" | "blur" | "reveal" | "push";
5640
5665
  type HeroBannerImageFilter = "none" | "cinematic" | "dramatic" | "cool" | "warm" | "desaturated" | "noir" | "vibrant";
@@ -6200,10 +6225,20 @@ interface TeamGeneratorProps {
6200
6225
  maxPlayers?: number;
6201
6226
  /** Initial roster. Uncontrolled — the component manages names internally. */
6202
6227
  defaultNames?: string[];
6228
+ /** Initial generated teams (e.g. restored from a saved session).
6229
+ * Uncontrolled — the component takes over after mount. An empty array
6230
+ * is treated as "no teams". */
6231
+ defaultTeams?: string[][];
6203
6232
  /** Called whenever the name pool changes. */
6204
6233
  onNamesChange?: (names: string[]) => void;
6205
6234
  /** Called whenever teams are (re)generated. */
6206
6235
  onGenerate?: (teams: string[][]) => void;
6236
+ /** Called whenever the generated teams change for ANY reason — a
6237
+ * (re)generation, or invalidation to `null` when a player is removed,
6238
+ * the pool is cleared, or the team count changes. Unlike `onGenerate`,
6239
+ * this mirrors the full lifecycle of the on-screen split so hosts can
6240
+ * persist it and restore via `defaultTeams`. */
6241
+ onTeamsChange?: (teams: string[][] | null) => void;
6207
6242
  /** Called whenever the team count selection changes. */
6208
6243
  onTeamCountChange?: (count: number) => void;
6209
6244
  /** Localized / customized labels. */
@@ -6216,7 +6251,7 @@ interface TeamGeneratorProps {
6216
6251
  * CSV / TSV roster from a spreadsheet. Default `true`. */
6217
6252
  enableImport?: boolean;
6218
6253
  }
6219
- declare function TeamGenerator({ theme, darkMode, teamCountOptions, defaultTeamCount, minPlayersPerTeam, maxPlayers, defaultNames, onNamesChange, onGenerate, onTeamCountChange, labels, ariaLabel, className, enableImport, }: TeamGeneratorProps): react_jsx_runtime.JSX.Element;
6254
+ declare function TeamGenerator({ theme, darkMode, teamCountOptions, defaultTeamCount, minPlayersPerTeam, maxPlayers, defaultNames, defaultTeams, onNamesChange, onGenerate, onTeamsChange, onTeamCountChange, labels, ariaLabel, className, enableImport, }: TeamGeneratorProps): react_jsx_runtime.JSX.Element;
6220
6255
  declare namespace TeamGenerator {
6221
6256
  var displayName: string;
6222
6257
  }
@@ -6264,6 +6299,14 @@ interface RoundRobinSchedulerProps {
6264
6299
  darkMode?: boolean;
6265
6300
  /** Minimum teams required to generate a schedule. Default 3. */
6266
6301
  minTeams?: number;
6302
+ /** Maximum roster size. Adds/imports beyond this are ignored. Unlimited
6303
+ * by default — consumers persisting the roster against a capped schema
6304
+ * should set this to the schema cap. */
6305
+ maxTeams?: number;
6306
+ /** Max characters per team name. Longer typed/imported names are
6307
+ * truncated (matching native input maxLength paste behavior).
6308
+ * Unlimited by default. */
6309
+ nameMaxLength?: number;
6267
6310
  /** Initial roster. Uncontrolled. */
6268
6311
  defaultTeams?: string[];
6269
6312
  /**
@@ -6289,7 +6332,7 @@ interface RoundRobinSchedulerProps {
6289
6332
  * roster from a spreadsheet. Default `true`. */
6290
6333
  enableImport?: boolean;
6291
6334
  }
6292
- declare function RoundRobinScheduler({ theme, darkMode, minTeams, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
6335
+ declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
6293
6336
  declare namespace RoundRobinScheduler {
6294
6337
  var displayName: string;
6295
6338
  }
@@ -6348,6 +6391,13 @@ interface ScoreboardProps {
6348
6391
  onRoundAdvance?: (snapshot: ScoreboardRoundSnapshot) => void;
6349
6392
  /** Called when the user presses "New Game". */
6350
6393
  onNewGame?: () => void;
6394
+ /** Called when the user presses "Reset" (scores zeroed, round counter and
6395
+ * history cleared, names kept). Consumers persisting round/history via
6396
+ * `onRoundAdvance` MUST clear that state here or their saved copy
6397
+ * diverges from the screen. */
6398
+ onReset?: () => void;
6399
+ /** Max characters accepted in a team-name input. Unlimited by default. */
6400
+ nameMaxLength?: number;
6351
6401
  /** Localized / customized labels. */
6352
6402
  labels?: ScoreboardLabels;
6353
6403
  /** Accessible label on the root region. */
@@ -6355,7 +6405,7 @@ interface ScoreboardProps {
6355
6405
  /** CSS class on root element. */
6356
6406
  className?: string;
6357
6407
  }
6358
- declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
6408
+ 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;
6359
6409
  declare namespace Scoreboard {
6360
6410
  var displayName: string;
6361
6411
  }