@digilogiclabs/saas-factory-ui 2.7.1 → 2.8.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.mjs CHANGED
@@ -31910,32 +31910,26 @@ function BracketGenerator({
31910
31910
  const autoPlay = useCallback45(() => {
31911
31911
  if (simulating) {
31912
31912
  if (autoRef.current) clearTimeout(autoRef.current);
31913
+ autoRef.current = null;
31913
31914
  setSimulating(false);
31914
31915
  return;
31915
31916
  }
31916
31917
  setSimulating(true);
31917
- const tick = () => {
31918
- setBracketState((prev) => {
31919
- const next = prev.matches.find((m) => m.a && m.b && !m.winner);
31920
- if (!next) {
31921
- setSimulating(false);
31922
- return prev;
31923
- }
31924
- const completed = simulateMatch(next);
31925
- if (!completed) return prev;
31926
- let matches = prev.matches.map(
31927
- (m) => m.id === completed.id ? completed : m
31928
- );
31929
- matches = propagateWinner(matches, completed);
31930
- const finalMatch = matches.find((m) => m.round === prev.rounds - 1);
31931
- const champion = finalMatch?.winner || null;
31932
- if (!champion) autoRef.current = setTimeout(tick, simulateDelayMs);
31933
- else setSimulating(false);
31934
- return { ...prev, matches, champion };
31935
- });
31918
+ simulateNext();
31919
+ }, [simulating, simulateNext]);
31920
+ useEffect55(() => {
31921
+ if (!simulating) return;
31922
+ const hasNext = bracketState.matches.some((m) => m.a && m.b && !m.winner);
31923
+ if (bracketState.champion || !hasNext) {
31924
+ setSimulating(false);
31925
+ return;
31926
+ }
31927
+ autoRef.current = setTimeout(simulateNext, simulateDelayMs);
31928
+ return () => {
31929
+ if (autoRef.current) clearTimeout(autoRef.current);
31930
+ autoRef.current = null;
31936
31931
  };
31937
- tick();
31938
- }, [simulating, simulateDelayMs]);
31932
+ }, [simulating, bracketState, simulateDelayMs, simulateNext]);
31939
31933
  const advanceWinner = useCallback45(
31940
31934
  (matchId, winnerSlot) => {
31941
31935
  setBracketState((prev) => {
@@ -39770,8 +39764,8 @@ function RosterImport({
39770
39764
  maxNames,
39771
39765
  maxFileBytes,
39772
39766
  onClose: () => setOpen(false),
39773
- onImport: (names) => {
39774
- onImport(names);
39767
+ onImport: (names, info) => {
39768
+ onImport(names, info);
39775
39769
  setOpen(false);
39776
39770
  }
39777
39771
  }
@@ -39837,6 +39831,11 @@ function RosterImportModal({
39837
39831
  }),
39838
39832
  [table, column, skipHeader, maxNames]
39839
39833
  );
39834
+ const extractedTotal = useMemo36(
39835
+ () => extractRoster(table, { column, skipHeader }),
39836
+ [table, column, skipHeader]
39837
+ );
39838
+ const trimmedCount = Math.max(0, extractedTotal.length - extracted.length);
39840
39839
  const handleFile = useCallback52(
39841
39840
  async (e) => {
39842
39841
  setFileError(null);
@@ -40214,7 +40213,10 @@ function RosterImportModal({
40214
40213
  "button",
40215
40214
  {
40216
40215
  type: "button",
40217
- onClick: () => onImport(extracted),
40216
+ onClick: () => onImport(extracted, {
40217
+ trimmedCount,
40218
+ totalCount: extractedTotal.length
40219
+ }),
40218
40220
  disabled: !canImport,
40219
40221
  style: primaryBtn(!canImport),
40220
40222
  children: confirmLabel
@@ -40418,6 +40420,19 @@ function IconUsers({ size = 40 }) {
40418
40420
  }
40419
40421
  );
40420
40422
  }
40423
+ function mergeNames(prev, incoming, max) {
40424
+ const seen = new Set(prev.map((n) => n.toLowerCase()));
40425
+ const room = Math.max(0, max - prev.length);
40426
+ const deduped = [];
40427
+ for (const n of incoming) {
40428
+ const key = n.toLowerCase();
40429
+ if (seen.has(key)) continue;
40430
+ seen.add(key);
40431
+ deduped.push(n);
40432
+ if (deduped.length >= room) break;
40433
+ }
40434
+ return deduped.length > 0 ? [...prev, ...deduped] : prev;
40435
+ }
40421
40436
  function splitIntoTeams(names, count2) {
40422
40437
  const shuffled = shuffle(names);
40423
40438
  const teams = Array.from({ length: count2 }, () => []);
@@ -40491,29 +40506,14 @@ function TeamGenerator({
40491
40506
  const trimmed = input.trim();
40492
40507
  if (!trimmed) return;
40493
40508
  const newNames = trimmed.split(/[,\n]+/).map((n) => n.trim()).filter((n) => n.length > 0);
40494
- setNames((prev) => {
40495
- const room = Math.max(0, maxPlayers - prev.length);
40496
- return [...prev, ...newNames.slice(0, room)];
40497
- });
40509
+ setNames((prev) => mergeNames(prev, newNames, maxPlayers));
40498
40510
  setInput("");
40499
40511
  inputRef.current?.focus();
40500
40512
  }, [input, maxPlayers]);
40501
40513
  const importNames = useCallback53(
40502
40514
  (incoming) => {
40503
40515
  if (incoming.length === 0) return;
40504
- setNames((prev) => {
40505
- const seen = new Set(prev.map((n) => n.toLowerCase()));
40506
- const room = Math.max(0, maxPlayers - prev.length);
40507
- const deduped = [];
40508
- for (const n of incoming) {
40509
- const key = n.toLowerCase();
40510
- if (seen.has(key)) continue;
40511
- seen.add(key);
40512
- deduped.push(n);
40513
- if (deduped.length >= room) break;
40514
- }
40515
- return deduped.length > 0 ? [...prev, ...deduped] : prev;
40516
- });
40516
+ setNames((prev) => mergeNames(prev, incoming, maxPlayers));
40517
40517
  },
40518
40518
  [maxPlayers]
40519
40519
  );
@@ -41138,7 +41138,7 @@ function RoundRobinScheduler({
41138
41138
  useEffect64(() => {
41139
41139
  onTeamsChange?.(teams);
41140
41140
  }, [teams, onTeamsChange]);
41141
- const mergeNames = useCallback54(
41141
+ const mergeNames2 = useCallback54(
41142
41142
  (prev, incoming) => {
41143
41143
  const existing = new Set(prev.map((t) => t.toLowerCase()));
41144
41144
  const next = [...prev];
@@ -41164,20 +41164,20 @@ function RoundRobinScheduler({
41164
41164
  const names = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
41165
41165
  if (names.length === 0) return;
41166
41166
  if (!gateDiscard("add")) return;
41167
- setTeams((prev) => mergeNames(prev, names));
41167
+ setTeams((prev) => mergeNames2(prev, names));
41168
41168
  setInput("");
41169
41169
  setRounds([]);
41170
41170
  },
41171
- [mergeNames, gateDiscard]
41171
+ [mergeNames2, gateDiscard]
41172
41172
  );
41173
41173
  const importTeams = useCallback54(
41174
41174
  (incoming) => {
41175
41175
  if (incoming.length === 0) return;
41176
41176
  if (!gateDiscard("import")) return;
41177
- setTeams((prev) => mergeNames(prev, incoming));
41177
+ setTeams((prev) => mergeNames2(prev, incoming));
41178
41178
  setRounds([]);
41179
41179
  },
41180
- [mergeNames, gateDiscard]
41180
+ [mergeNames2, gateDiscard]
41181
41181
  );
41182
41182
  const handleKeyDown = useCallback54(
41183
41183
  (e) => {
@@ -41682,6 +41682,8 @@ function Scoreboard({
41682
41682
  onBeforeReset,
41683
41683
  onBeforeNewGame,
41684
41684
  nameMaxLength,
41685
+ scoreMin = -9999,
41686
+ scoreMax = 9999,
41685
41687
  labels,
41686
41688
  ariaLabel = "Scoreboard",
41687
41689
  className
@@ -41725,11 +41727,19 @@ function Scoreboard({
41725
41727
  useEffect65(() => {
41726
41728
  onTeamsChange?.(teams);
41727
41729
  }, [teams, onTeamsChange]);
41728
- const updateScore = useCallback55((index, delta) => {
41729
- setTeams(
41730
- (prev) => prev.map((t, i) => i === index ? { ...t, score: t.score + delta } : t)
41731
- );
41732
- }, []);
41730
+ const updateScore = useCallback55(
41731
+ (index, delta) => {
41732
+ setTeams(
41733
+ (prev) => prev.map(
41734
+ (t, i) => i === index ? {
41735
+ ...t,
41736
+ score: Math.min(scoreMax, Math.max(scoreMin, t.score + delta))
41737
+ } : t
41738
+ )
41739
+ );
41740
+ },
41741
+ [scoreMin, scoreMax]
41742
+ );
41733
41743
  const updateName = useCallback55((index, name) => {
41734
41744
  setTeams((prev) => prev.map((t, i) => i === index ? { ...t, name } : t));
41735
41745
  }, []);