@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.
package/dist/index.d.mts CHANGED
@@ -4626,7 +4626,9 @@ declare function TiltCard({ accent, accentSecondary, topLabel, icon, title, subt
4626
4626
  * - Three trigger modes: built-in button / click anywhere / external
4627
4627
  * imperative handle via `rollRef.current()`
4628
4628
  * - Optional roll history strip
4629
- * - Honors `prefers-reduced-motion` (skips physics animation)
4629
+ * - Deliberately tumbles even under `prefers-reduced-motion` a dice
4630
+ * roll is a safe animation and skipping it leaves no feedback at all
4631
+ * (see the note inside `roll()`)
4630
4632
  * - Zero Tailwind dependency — all styles inline
4631
4633
  *
4632
4634
  * Ported to TypeScript and generalized for saas-factory-ui from a
@@ -5048,14 +5050,37 @@ interface RandomPlayerPickerProps {
5048
5050
  renderWinner?: (winner: RandomPlayerParticipant) => ReactNode;
5049
5051
  /** Imperative handle. `spinRef.current?.()` triggers a spin. */
5050
5052
  spinRef?: MutableRefObject<(() => void) | null>;
5053
+ /**
5054
+ * Imperative reset handle. `resetRef.current?.()` restores the pool to
5055
+ * the full `participants` list and clears history/winner — the escape
5056
+ * hatch for consumers that hide the built-in controls
5057
+ * (`showControls={false}`) but still need a "reset draft" affordance
5058
+ * once draft-mode pops drain the pool.
5059
+ */
5060
+ resetRef?: MutableRefObject<(() => void) | null>;
5061
+ /**
5062
+ * Fired whenever the internal pool changes (mount, structural sync,
5063
+ * draft-mode pop, spin-again flush, reset). Draft-mode consumers use
5064
+ * this to mirror the live pool — e.g. to disable an external spin
5065
+ * trigger when the pool drains below 2 instead of presenting a dead
5066
+ * button, and to offer a reset once the draft completes.
5067
+ */
5068
+ onPoolChange?: (pool: RandomPlayerParticipant[]) => void;
5069
+ /**
5070
+ * Caption shown in place of `placeholderCaption` when draft-mode pops
5071
+ * drain the pool below 2 while the roster itself still has 2+ members.
5072
+ * Default: "Draft complete — reset to spin again".
5073
+ */
5074
+ draftCompleteCaption?: string;
5051
5075
  /**
5052
5076
  * Visual intensity preset. Default "normal".
5053
- * - "subtle" / "normal": current behavior — shorter spins, standard
5054
- * ease-out curve.
5055
- * - "dramatic": physics-like spin 2.5× duration, inertia-style
5056
- * curve so motion continues through the full duration with a slow
5057
- * winding-down tail, +12 extra revolutions, plus more
5058
- * particles/glow/shake on reveal.
5077
+ * - "subtle" / "normal": shorter spins, standard CSS ease-out curve.
5078
+ * - "dramatic": physics-driven spin — 2.5× duration, rAF-driven
5079
+ * exponential velocity decay (v ∝ e^(-4t)) that keeps the wheel
5080
+ * visibly winding down through the FULL duration and lands exactly
5081
+ * at the end, +12 extra revolutions, ticks fired on actual
5082
+ * wedge/row crossings, plus more particles/glow/shake on reveal.
5083
+ * Falls back to a 250ms CSS settle under prefers-reduced-motion.
5059
5084
  */
5060
5085
  intensity?: RandomPlayerIntensity;
5061
5086
  /**
@@ -5098,7 +5123,7 @@ interface RandomPlayerPickerProps {
5098
5123
  /** Accessible label for the wheel root. */
5099
5124
  ariaLabel?: string;
5100
5125
  }
5101
- 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;
5126
+ 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;
5102
5127
 
5103
5128
  type HeroBannerTransition = "fade" | "slide" | "zoom" | "blur" | "reveal" | "push";
5104
5129
  type HeroBannerImageFilter = "none" | "cinematic" | "dramatic" | "cool" | "warm" | "desaturated" | "noir" | "vibrant";
@@ -5664,10 +5689,20 @@ interface TeamGeneratorProps {
5664
5689
  maxPlayers?: number;
5665
5690
  /** Initial roster. Uncontrolled — the component manages names internally. */
5666
5691
  defaultNames?: string[];
5692
+ /** Initial generated teams (e.g. restored from a saved session).
5693
+ * Uncontrolled — the component takes over after mount. An empty array
5694
+ * is treated as "no teams". */
5695
+ defaultTeams?: string[][];
5667
5696
  /** Called whenever the name pool changes. */
5668
5697
  onNamesChange?: (names: string[]) => void;
5669
5698
  /** Called whenever teams are (re)generated. */
5670
5699
  onGenerate?: (teams: string[][]) => void;
5700
+ /** Called whenever the generated teams change for ANY reason — a
5701
+ * (re)generation, or invalidation to `null` when a player is removed,
5702
+ * the pool is cleared, or the team count changes. Unlike `onGenerate`,
5703
+ * this mirrors the full lifecycle of the on-screen split so hosts can
5704
+ * persist it and restore via `defaultTeams`. */
5705
+ onTeamsChange?: (teams: string[][] | null) => void;
5671
5706
  /** Called whenever the team count selection changes. */
5672
5707
  onTeamCountChange?: (count: number) => void;
5673
5708
  /** Localized / customized labels. */
@@ -5680,7 +5715,7 @@ interface TeamGeneratorProps {
5680
5715
  * CSV / TSV roster from a spreadsheet. Default `true`. */
5681
5716
  enableImport?: boolean;
5682
5717
  }
5683
- declare function TeamGenerator({ theme, darkMode, teamCountOptions, defaultTeamCount, minPlayersPerTeam, maxPlayers, defaultNames, onNamesChange, onGenerate, onTeamCountChange, labels, ariaLabel, className, enableImport, }: TeamGeneratorProps): react_jsx_runtime.JSX.Element;
5718
+ 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;
5684
5719
  declare namespace TeamGenerator {
5685
5720
  var displayName: string;
5686
5721
  }
@@ -5728,6 +5763,14 @@ interface RoundRobinSchedulerProps {
5728
5763
  darkMode?: boolean;
5729
5764
  /** Minimum teams required to generate a schedule. Default 3. */
5730
5765
  minTeams?: number;
5766
+ /** Maximum roster size. Adds/imports beyond this are ignored. Unlimited
5767
+ * by default — consumers persisting the roster against a capped schema
5768
+ * should set this to the schema cap. */
5769
+ maxTeams?: number;
5770
+ /** Max characters per team name. Longer typed/imported names are
5771
+ * truncated (matching native input maxLength paste behavior).
5772
+ * Unlimited by default. */
5773
+ nameMaxLength?: number;
5731
5774
  /** Initial roster. Uncontrolled. */
5732
5775
  defaultTeams?: string[];
5733
5776
  /**
@@ -5753,7 +5796,7 @@ interface RoundRobinSchedulerProps {
5753
5796
  * roster from a spreadsheet. Default `true`. */
5754
5797
  enableImport?: boolean;
5755
5798
  }
5756
- declare function RoundRobinScheduler({ theme, darkMode, minTeams, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
5799
+ declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
5757
5800
  declare namespace RoundRobinScheduler {
5758
5801
  var displayName: string;
5759
5802
  }
@@ -5812,6 +5855,13 @@ interface ScoreboardProps {
5812
5855
  onRoundAdvance?: (snapshot: ScoreboardRoundSnapshot) => void;
5813
5856
  /** Called when the user presses "New Game". */
5814
5857
  onNewGame?: () => void;
5858
+ /** Called when the user presses "Reset" (scores zeroed, round counter and
5859
+ * history cleared, names kept). Consumers persisting round/history via
5860
+ * `onRoundAdvance` MUST clear that state here or their saved copy
5861
+ * diverges from the screen. */
5862
+ onReset?: () => void;
5863
+ /** Max characters accepted in a team-name input. Unlimited by default. */
5864
+ nameMaxLength?: number;
5815
5865
  /** Localized / customized labels. */
5816
5866
  labels?: ScoreboardLabels;
5817
5867
  /** Accessible label on the root region. */
@@ -5819,7 +5869,7 @@ interface ScoreboardProps {
5819
5869
  /** CSS class on root element. */
5820
5870
  className?: string;
5821
5871
  }
5822
- declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
5872
+ 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;
5823
5873
  declare namespace Scoreboard {
5824
5874
  var displayName: string;
5825
5875
  }
package/dist/index.d.ts CHANGED
@@ -4626,7 +4626,9 @@ declare function TiltCard({ accent, accentSecondary, topLabel, icon, title, subt
4626
4626
  * - Three trigger modes: built-in button / click anywhere / external
4627
4627
  * imperative handle via `rollRef.current()`
4628
4628
  * - Optional roll history strip
4629
- * - Honors `prefers-reduced-motion` (skips physics animation)
4629
+ * - Deliberately tumbles even under `prefers-reduced-motion` a dice
4630
+ * roll is a safe animation and skipping it leaves no feedback at all
4631
+ * (see the note inside `roll()`)
4630
4632
  * - Zero Tailwind dependency — all styles inline
4631
4633
  *
4632
4634
  * Ported to TypeScript and generalized for saas-factory-ui from a
@@ -5048,14 +5050,37 @@ interface RandomPlayerPickerProps {
5048
5050
  renderWinner?: (winner: RandomPlayerParticipant) => ReactNode;
5049
5051
  /** Imperative handle. `spinRef.current?.()` triggers a spin. */
5050
5052
  spinRef?: MutableRefObject<(() => void) | null>;
5053
+ /**
5054
+ * Imperative reset handle. `resetRef.current?.()` restores the pool to
5055
+ * the full `participants` list and clears history/winner — the escape
5056
+ * hatch for consumers that hide the built-in controls
5057
+ * (`showControls={false}`) but still need a "reset draft" affordance
5058
+ * once draft-mode pops drain the pool.
5059
+ */
5060
+ resetRef?: MutableRefObject<(() => void) | null>;
5061
+ /**
5062
+ * Fired whenever the internal pool changes (mount, structural sync,
5063
+ * draft-mode pop, spin-again flush, reset). Draft-mode consumers use
5064
+ * this to mirror the live pool — e.g. to disable an external spin
5065
+ * trigger when the pool drains below 2 instead of presenting a dead
5066
+ * button, and to offer a reset once the draft completes.
5067
+ */
5068
+ onPoolChange?: (pool: RandomPlayerParticipant[]) => void;
5069
+ /**
5070
+ * Caption shown in place of `placeholderCaption` when draft-mode pops
5071
+ * drain the pool below 2 while the roster itself still has 2+ members.
5072
+ * Default: "Draft complete — reset to spin again".
5073
+ */
5074
+ draftCompleteCaption?: string;
5051
5075
  /**
5052
5076
  * Visual intensity preset. Default "normal".
5053
- * - "subtle" / "normal": current behavior — shorter spins, standard
5054
- * ease-out curve.
5055
- * - "dramatic": physics-like spin 2.5× duration, inertia-style
5056
- * curve so motion continues through the full duration with a slow
5057
- * winding-down tail, +12 extra revolutions, plus more
5058
- * particles/glow/shake on reveal.
5077
+ * - "subtle" / "normal": shorter spins, standard CSS ease-out curve.
5078
+ * - "dramatic": physics-driven spin — 2.5× duration, rAF-driven
5079
+ * exponential velocity decay (v ∝ e^(-4t)) that keeps the wheel
5080
+ * visibly winding down through the FULL duration and lands exactly
5081
+ * at the end, +12 extra revolutions, ticks fired on actual
5082
+ * wedge/row crossings, plus more particles/glow/shake on reveal.
5083
+ * Falls back to a 250ms CSS settle under prefers-reduced-motion.
5059
5084
  */
5060
5085
  intensity?: RandomPlayerIntensity;
5061
5086
  /**
@@ -5098,7 +5123,7 @@ interface RandomPlayerPickerProps {
5098
5123
  /** Accessible label for the wheel root. */
5099
5124
  ariaLabel?: string;
5100
5125
  }
5101
- 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;
5126
+ 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;
5102
5127
 
5103
5128
  type HeroBannerTransition = "fade" | "slide" | "zoom" | "blur" | "reveal" | "push";
5104
5129
  type HeroBannerImageFilter = "none" | "cinematic" | "dramatic" | "cool" | "warm" | "desaturated" | "noir" | "vibrant";
@@ -5664,10 +5689,20 @@ interface TeamGeneratorProps {
5664
5689
  maxPlayers?: number;
5665
5690
  /** Initial roster. Uncontrolled — the component manages names internally. */
5666
5691
  defaultNames?: string[];
5692
+ /** Initial generated teams (e.g. restored from a saved session).
5693
+ * Uncontrolled — the component takes over after mount. An empty array
5694
+ * is treated as "no teams". */
5695
+ defaultTeams?: string[][];
5667
5696
  /** Called whenever the name pool changes. */
5668
5697
  onNamesChange?: (names: string[]) => void;
5669
5698
  /** Called whenever teams are (re)generated. */
5670
5699
  onGenerate?: (teams: string[][]) => void;
5700
+ /** Called whenever the generated teams change for ANY reason — a
5701
+ * (re)generation, or invalidation to `null` when a player is removed,
5702
+ * the pool is cleared, or the team count changes. Unlike `onGenerate`,
5703
+ * this mirrors the full lifecycle of the on-screen split so hosts can
5704
+ * persist it and restore via `defaultTeams`. */
5705
+ onTeamsChange?: (teams: string[][] | null) => void;
5671
5706
  /** Called whenever the team count selection changes. */
5672
5707
  onTeamCountChange?: (count: number) => void;
5673
5708
  /** Localized / customized labels. */
@@ -5680,7 +5715,7 @@ interface TeamGeneratorProps {
5680
5715
  * CSV / TSV roster from a spreadsheet. Default `true`. */
5681
5716
  enableImport?: boolean;
5682
5717
  }
5683
- declare function TeamGenerator({ theme, darkMode, teamCountOptions, defaultTeamCount, minPlayersPerTeam, maxPlayers, defaultNames, onNamesChange, onGenerate, onTeamCountChange, labels, ariaLabel, className, enableImport, }: TeamGeneratorProps): react_jsx_runtime.JSX.Element;
5718
+ 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;
5684
5719
  declare namespace TeamGenerator {
5685
5720
  var displayName: string;
5686
5721
  }
@@ -5728,6 +5763,14 @@ interface RoundRobinSchedulerProps {
5728
5763
  darkMode?: boolean;
5729
5764
  /** Minimum teams required to generate a schedule. Default 3. */
5730
5765
  minTeams?: number;
5766
+ /** Maximum roster size. Adds/imports beyond this are ignored. Unlimited
5767
+ * by default — consumers persisting the roster against a capped schema
5768
+ * should set this to the schema cap. */
5769
+ maxTeams?: number;
5770
+ /** Max characters per team name. Longer typed/imported names are
5771
+ * truncated (matching native input maxLength paste behavior).
5772
+ * Unlimited by default. */
5773
+ nameMaxLength?: number;
5731
5774
  /** Initial roster. Uncontrolled. */
5732
5775
  defaultTeams?: string[];
5733
5776
  /**
@@ -5753,7 +5796,7 @@ interface RoundRobinSchedulerProps {
5753
5796
  * roster from a spreadsheet. Default `true`. */
5754
5797
  enableImport?: boolean;
5755
5798
  }
5756
- declare function RoundRobinScheduler({ theme, darkMode, minTeams, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
5799
+ declare function RoundRobinScheduler({ theme, darkMode, minTeams, maxTeams, nameMaxLength, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
5757
5800
  declare namespace RoundRobinScheduler {
5758
5801
  var displayName: string;
5759
5802
  }
@@ -5812,6 +5855,13 @@ interface ScoreboardProps {
5812
5855
  onRoundAdvance?: (snapshot: ScoreboardRoundSnapshot) => void;
5813
5856
  /** Called when the user presses "New Game". */
5814
5857
  onNewGame?: () => void;
5858
+ /** Called when the user presses "Reset" (scores zeroed, round counter and
5859
+ * history cleared, names kept). Consumers persisting round/history via
5860
+ * `onRoundAdvance` MUST clear that state here or their saved copy
5861
+ * diverges from the screen. */
5862
+ onReset?: () => void;
5863
+ /** Max characters accepted in a team-name input. Unlimited by default. */
5864
+ nameMaxLength?: number;
5815
5865
  /** Localized / customized labels. */
5816
5866
  labels?: ScoreboardLabels;
5817
5867
  /** Accessible label on the root region. */
@@ -5819,7 +5869,7 @@ interface ScoreboardProps {
5819
5869
  /** CSS class on root element. */
5820
5870
  className?: string;
5821
5871
  }
5822
- declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
5872
+ 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;
5823
5873
  declare namespace Scoreboard {
5824
5874
  var displayName: string;
5825
5875
  }