@digilogiclabs/saas-factory-ui 2.1.0 → 2.2.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.
@@ -6227,6 +6227,15 @@ interface RoundRobinSchedulerProps {
6227
6227
  minTeams?: number;
6228
6228
  /** Initial roster. Uncontrolled. */
6229
6229
  defaultTeams?: string[];
6230
+ /**
6231
+ * Resume a previously generated schedule (the rounds consumers persist
6232
+ * from `onGenerate`). One-shot: read on mount, ignored afterwards.
6233
+ * Applied only when the round count matches what the current
6234
+ * `defaultTeams` roster would generate and every non-BYE name resolves
6235
+ * against that roster; otherwise ignored (empty schedule, as if the
6236
+ * prop were omitted). Does NOT re-emit `onGenerate`.
6237
+ */
6238
+ resumeRounds?: RoundRobinRound[];
6230
6239
  /** Called whenever the team roster changes. */
6231
6240
  onTeamsChange?: (teams: string[]) => void;
6232
6241
  /** Called when a new schedule is generated. */
@@ -6241,7 +6250,7 @@ interface RoundRobinSchedulerProps {
6241
6250
  * roster from a spreadsheet. Default `true`. */
6242
6251
  enableImport?: boolean;
6243
6252
  }
6244
- declare function RoundRobinScheduler({ theme, darkMode, minTeams, defaultTeams, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
6253
+ declare function RoundRobinScheduler({ theme, darkMode, minTeams, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
6245
6254
  declare namespace RoundRobinScheduler {
6246
6255
  var displayName: string;
6247
6256
  }
@@ -6287,6 +6296,13 @@ interface ScoreboardProps {
6287
6296
  /** Optional initial team state — name/score pairs. Overrides initialTeamCount
6288
6297
  * if provided. */
6289
6298
  defaultTeams?: ScoreboardTeam[];
6299
+ /** Resume the round counter from a persisted session. One-shot: read on
6300
+ * mount, ignored afterwards. Clamped to a minimum of 1. Default 1. */
6301
+ initialRound?: number;
6302
+ /** Resume prior round snapshots (the values consumers persist from
6303
+ * `onRoundAdvance`) from a persisted session. One-shot: read on mount,
6304
+ * ignored afterwards. Default empty. */
6305
+ initialHistory?: ScoreboardRoundSnapshot[];
6290
6306
  /** Called every time scores or names change. */
6291
6307
  onTeamsChange?: (teams: ScoreboardTeam[]) => void;
6292
6308
  /** Called with the snapshot when Next Round is pressed. */
@@ -6300,7 +6316,7 @@ interface ScoreboardProps {
6300
6316
  /** CSS class on root element. */
6301
6317
  className?: string;
6302
6318
  }
6303
- declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, onTeamsChange, onRoundAdvance, onNewGame, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
6319
+ declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
6304
6320
  declare namespace Scoreboard {
6305
6321
  var displayName: string;
6306
6322
  }
@@ -6227,6 +6227,15 @@ interface RoundRobinSchedulerProps {
6227
6227
  minTeams?: number;
6228
6228
  /** Initial roster. Uncontrolled. */
6229
6229
  defaultTeams?: string[];
6230
+ /**
6231
+ * Resume a previously generated schedule (the rounds consumers persist
6232
+ * from `onGenerate`). One-shot: read on mount, ignored afterwards.
6233
+ * Applied only when the round count matches what the current
6234
+ * `defaultTeams` roster would generate and every non-BYE name resolves
6235
+ * against that roster; otherwise ignored (empty schedule, as if the
6236
+ * prop were omitted). Does NOT re-emit `onGenerate`.
6237
+ */
6238
+ resumeRounds?: RoundRobinRound[];
6230
6239
  /** Called whenever the team roster changes. */
6231
6240
  onTeamsChange?: (teams: string[]) => void;
6232
6241
  /** Called when a new schedule is generated. */
@@ -6241,7 +6250,7 @@ interface RoundRobinSchedulerProps {
6241
6250
  * roster from a spreadsheet. Default `true`. */
6242
6251
  enableImport?: boolean;
6243
6252
  }
6244
- declare function RoundRobinScheduler({ theme, darkMode, minTeams, defaultTeams, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
6253
+ declare function RoundRobinScheduler({ theme, darkMode, minTeams, defaultTeams, resumeRounds, onTeamsChange, onGenerate, labels, ariaLabel, className, enableImport, }: RoundRobinSchedulerProps): react_jsx_runtime.JSX.Element;
6245
6254
  declare namespace RoundRobinScheduler {
6246
6255
  var displayName: string;
6247
6256
  }
@@ -6287,6 +6296,13 @@ interface ScoreboardProps {
6287
6296
  /** Optional initial team state — name/score pairs. Overrides initialTeamCount
6288
6297
  * if provided. */
6289
6298
  defaultTeams?: ScoreboardTeam[];
6299
+ /** Resume the round counter from a persisted session. One-shot: read on
6300
+ * mount, ignored afterwards. Clamped to a minimum of 1. Default 1. */
6301
+ initialRound?: number;
6302
+ /** Resume prior round snapshots (the values consumers persist from
6303
+ * `onRoundAdvance`) from a persisted session. One-shot: read on mount,
6304
+ * ignored afterwards. Default empty. */
6305
+ initialHistory?: ScoreboardRoundSnapshot[];
6290
6306
  /** Called every time scores or names change. */
6291
6307
  onTeamsChange?: (teams: ScoreboardTeam[]) => void;
6292
6308
  /** Called with the snapshot when Next Round is pressed. */
@@ -6300,7 +6316,7 @@ interface ScoreboardProps {
6300
6316
  /** CSS class on root element. */
6301
6317
  className?: string;
6302
6318
  }
6303
- declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, onTeamsChange, onRoundAdvance, onNewGame, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
6319
+ declare function Scoreboard({ theme, darkMode, initialTeamCount, minTeams, maxTeams, scoreButtons, defaultTeams, initialRound, initialHistory, onTeamsChange, onRoundAdvance, onNewGame, labels, ariaLabel, className, }: ScoreboardProps): react_jsx_runtime.JSX.Element;
6304
6320
  declare namespace Scoreboard {
6305
6321
  var displayName: string;
6306
6322
  }
package/dist/web/index.js CHANGED
@@ -40298,6 +40298,27 @@ function generateSchedule(teams, roundLabel) {
40298
40298
  }
40299
40299
  return rounds;
40300
40300
  }
40301
+ function hydrateResumeRounds(resume, teams) {
40302
+ if (!resume?.length || teams.length < 2) return [];
40303
+ const expected = teams.length % 2 === 0 ? teams.length - 1 : teams.length;
40304
+ if (resume.length !== expected) return [];
40305
+ const roster = new Set(teams.map((t) => t.toLowerCase()));
40306
+ for (const round of resume) {
40307
+ for (const m of round.matchups) {
40308
+ for (const side of [m.home, m.away]) {
40309
+ if (side !== BYE_TOKEN && !roster.has(side.toLowerCase())) return [];
40310
+ }
40311
+ }
40312
+ }
40313
+ return resume.map((round) => ({
40314
+ label: round.label,
40315
+ matchups: round.matchups.map((m) => ({
40316
+ home: m.home,
40317
+ away: m.away,
40318
+ isBye: m.home === BYE_TOKEN || m.away === BYE_TOKEN
40319
+ }))
40320
+ }));
40321
+ }
40301
40322
  var DEFAULT_LABELS4 = {
40302
40323
  inputPlaceholder: "Team or player name (comma-separated for batch)",
40303
40324
  addButton: "Add",
@@ -40318,6 +40339,7 @@ function RoundRobinScheduler({
40318
40339
  darkMode,
40319
40340
  minTeams = 3,
40320
40341
  defaultTeams = [],
40342
+ resumeRounds,
40321
40343
  onTeamsChange,
40322
40344
  onGenerate,
40323
40345
  labels,
@@ -40331,7 +40353,9 @@ function RoundRobinScheduler({
40331
40353
  const L = { ...DEFAULT_LABELS4, ...labels };
40332
40354
  const [teams, setTeams] = (0, import_react79.useState)(defaultTeams);
40333
40355
  const [input, setInput] = (0, import_react79.useState)("");
40334
- const [rounds, setRounds] = (0, import_react79.useState)([]);
40356
+ const [rounds, setRounds] = (0, import_react79.useState)(
40357
+ () => hydrateResumeRounds(resumeRounds, defaultTeams)
40358
+ );
40335
40359
  const inputRef = (0, import_react79.useRef)(null);
40336
40360
  (0, import_react79.useEffect)(() => {
40337
40361
  onTeamsChange?.(teams);
@@ -40852,6 +40876,8 @@ function Scoreboard({
40852
40876
  maxTeams = 8,
40853
40877
  scoreButtons = [-1, 1, 5, 10],
40854
40878
  defaultTeams,
40879
+ initialRound = 1,
40880
+ initialHistory,
40855
40881
  onTeamsChange,
40856
40882
  onRoundAdvance,
40857
40883
  onNewGame,
@@ -40867,8 +40893,12 @@ function Scoreboard({
40867
40893
  const [teams, setTeams] = (0, import_react80.useState)(
40868
40894
  () => defaultTeams && defaultTeams.length >= minTeams ? defaultTeams.slice(0, maxTeams) : createDefaultTeams(seedCount, L.teamNamePrefix)
40869
40895
  );
40870
- const [round, setRound] = (0, import_react80.useState)(1);
40871
- const [history, setHistory] = (0, import_react80.useState)([]);
40896
+ const [round, setRound] = (0, import_react80.useState)(
40897
+ () => Number.isFinite(initialRound) ? Math.max(1, Math.floor(initialRound)) : 1
40898
+ );
40899
+ const [history, setHistory] = (0, import_react80.useState)(
40900
+ () => initialHistory && initialHistory.length > 0 ? initialHistory.slice() : []
40901
+ );
40872
40902
  const [historyOpen, setHistoryOpen] = (0, import_react80.useState)(false);
40873
40903
  const rootRef = (0, import_react80.useRef)(null);
40874
40904
  const [containerWidth, setContainerWidth] = (0, import_react80.useState)(0);