@digilogiclabs/saas-factory-ui 2.0.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.
- package/dist/index.d.mts +46 -4
- package/dist/index.d.ts +46 -4
- package/dist/index.js +131 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +131 -7
- package/dist/index.mjs.map +1 -1
- package/dist/web/index.d.mts +46 -4
- package/dist/web/index.d.ts +46 -4
- package/dist/web/index.js +131 -7
- package/dist/web/index.js.map +1 -1
- package/dist/web/index.mjs +131 -7
- package/dist/web/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -31237,9 +31237,26 @@ function standardSeeding(participants) {
|
|
|
31237
31237
|
const sorted = [...participants].sort(
|
|
31238
31238
|
(a, b) => (a.seed ?? 999) - (b.seed ?? 999)
|
|
31239
31239
|
);
|
|
31240
|
+
const n = sorted.length;
|
|
31240
31241
|
const pairs = [];
|
|
31241
|
-
|
|
31242
|
-
|
|
31242
|
+
if (n < 2 || (n & n - 1) !== 0) {
|
|
31243
|
+
for (let i = 0; i + 1 < n; i += 2) {
|
|
31244
|
+
pairs.push([sorted[i], sorted[i + 1]]);
|
|
31245
|
+
}
|
|
31246
|
+
return pairs;
|
|
31247
|
+
}
|
|
31248
|
+
let order = [1, 2];
|
|
31249
|
+
while (order.length < n) {
|
|
31250
|
+
const total = order.length * 2 + 1;
|
|
31251
|
+
const next = [];
|
|
31252
|
+
for (const r of order) {
|
|
31253
|
+
next.push(r);
|
|
31254
|
+
next.push(total - r);
|
|
31255
|
+
}
|
|
31256
|
+
order = next;
|
|
31257
|
+
}
|
|
31258
|
+
for (let i = 0; i < order.length; i += 2) {
|
|
31259
|
+
pairs.push([sorted[order[i] - 1], sorted[order[i + 1] - 1]]);
|
|
31243
31260
|
}
|
|
31244
31261
|
return pairs;
|
|
31245
31262
|
}
|
|
@@ -31593,6 +31610,7 @@ function BracketGenerator({
|
|
|
31593
31610
|
theme: theme5 = "blue",
|
|
31594
31611
|
darkMode,
|
|
31595
31612
|
seedingStrategy = "standard",
|
|
31613
|
+
resumeMatches,
|
|
31596
31614
|
onMatchComplete,
|
|
31597
31615
|
onChampion,
|
|
31598
31616
|
onStateChange,
|
|
@@ -31671,6 +31689,47 @@ function BracketGenerator({
|
|
|
31671
31689
|
);
|
|
31672
31690
|
const [miniMapHidden, setMiniMapHidden] = useState71(false);
|
|
31673
31691
|
const miniMapDragRef = useRef40(false);
|
|
31692
|
+
const resumeRef = useRef40(resumeMatches);
|
|
31693
|
+
const hydrateFromResume = useCallback45(() => {
|
|
31694
|
+
const resume = resumeRef.current;
|
|
31695
|
+
if (!resume?.length) return null;
|
|
31696
|
+
const n = effectiveParticipants.length;
|
|
31697
|
+
if (n < 2 || (n & n - 1) !== 0) return null;
|
|
31698
|
+
const rounds = Math.log2(n);
|
|
31699
|
+
if (resume.length !== n - 1) return null;
|
|
31700
|
+
const byId = new Map(effectiveParticipants.map((p) => [p.id, p]));
|
|
31701
|
+
const resolve = (id) => {
|
|
31702
|
+
if (!id) return null;
|
|
31703
|
+
const found = byId.get(id);
|
|
31704
|
+
if (found) return found;
|
|
31705
|
+
if (id.startsWith("__bye_")) {
|
|
31706
|
+
return { id, name: "BYE", seed: 999, isBye: true };
|
|
31707
|
+
}
|
|
31708
|
+
return void 0;
|
|
31709
|
+
};
|
|
31710
|
+
const matches = [];
|
|
31711
|
+
for (const rm of resume) {
|
|
31712
|
+
if (rm.round < 0 || rm.round >= rounds) return null;
|
|
31713
|
+
const a = resolve(rm.aId);
|
|
31714
|
+
const b = resolve(rm.bId);
|
|
31715
|
+
const winner = resolve(rm.winnerId);
|
|
31716
|
+
if (a === void 0 || b === void 0 || winner === void 0)
|
|
31717
|
+
return null;
|
|
31718
|
+
matches.push({
|
|
31719
|
+
id: rm.id,
|
|
31720
|
+
round: rm.round,
|
|
31721
|
+
slot: rm.slot,
|
|
31722
|
+
a,
|
|
31723
|
+
b,
|
|
31724
|
+
scoreA: rm.scoreA,
|
|
31725
|
+
scoreB: rm.scoreB,
|
|
31726
|
+
winner
|
|
31727
|
+
});
|
|
31728
|
+
}
|
|
31729
|
+
matches.sort((x, y) => x.round - y.round || x.slot - y.slot);
|
|
31730
|
+
const finalMatch = matches.find((m) => m.round === rounds - 1);
|
|
31731
|
+
return { matches, rounds, champion: finalMatch?.winner ?? null };
|
|
31732
|
+
}, [effectiveParticipants]);
|
|
31674
31733
|
const seedBracket = useCallback45(() => {
|
|
31675
31734
|
const { matches, rounds } = buildBracket(
|
|
31676
31735
|
effectiveParticipants,
|
|
@@ -31781,12 +31840,47 @@ function BracketGenerator({
|
|
|
31781
31840
|
onStateChange?.(next);
|
|
31782
31841
|
prevBracketStateRef.current = next;
|
|
31783
31842
|
}, [bracketState, onMatchComplete, onChampion, onStateChange]);
|
|
31843
|
+
const structuralKey = useMemo29(
|
|
31844
|
+
() => `${seedingStrategy}|${effectiveParticipants.map((p) => `${p.id}:${p.seed ?? ""}`).join(",")}`,
|
|
31845
|
+
[effectiveParticipants, seedingStrategy]
|
|
31846
|
+
);
|
|
31847
|
+
const seededKeyRef = useRef40(null);
|
|
31848
|
+
useEffect55(() => {
|
|
31849
|
+
if (seededKeyRef.current === structuralKey) {
|
|
31850
|
+
setBracketState((prev) => {
|
|
31851
|
+
if (!prev.matches.length) return prev;
|
|
31852
|
+
const byId = new Map(effectiveParticipants.map((p) => [p.id, p]));
|
|
31853
|
+
const swap = (p) => p && !p.isBye ? byId.get(p.id) ?? p : p;
|
|
31854
|
+
let changed = false;
|
|
31855
|
+
const matches = prev.matches.map((m) => {
|
|
31856
|
+
const a = swap(m.a);
|
|
31857
|
+
const b = swap(m.b);
|
|
31858
|
+
const winner = swap(m.winner);
|
|
31859
|
+
if (a === m.a && b === m.b && winner === m.winner) return m;
|
|
31860
|
+
changed = true;
|
|
31861
|
+
return { ...m, a, b, winner };
|
|
31862
|
+
});
|
|
31863
|
+
if (!changed) return prev;
|
|
31864
|
+
return { ...prev, matches, champion: swap(prev.champion) };
|
|
31865
|
+
});
|
|
31866
|
+
return;
|
|
31867
|
+
}
|
|
31868
|
+
seededKeyRef.current = structuralKey;
|
|
31869
|
+
if (autoRef.current) clearTimeout(autoRef.current);
|
|
31870
|
+
setSimulating(false);
|
|
31871
|
+
const resumed = hydrateFromResume();
|
|
31872
|
+
resumeRef.current = void 0;
|
|
31873
|
+
if (resumed) {
|
|
31874
|
+
setBracketState(resumed);
|
|
31875
|
+
} else {
|
|
31876
|
+
seedBracket();
|
|
31877
|
+
}
|
|
31878
|
+
}, [structuralKey, effectiveParticipants, hydrateFromResume, seedBracket]);
|
|
31784
31879
|
useEffect55(() => {
|
|
31785
|
-
seedBracket();
|
|
31786
31880
|
return () => {
|
|
31787
31881
|
if (autoRef.current) clearTimeout(autoRef.current);
|
|
31788
31882
|
};
|
|
31789
|
-
}, [
|
|
31883
|
+
}, []);
|
|
31790
31884
|
useLayoutEffect2(() => {
|
|
31791
31885
|
if (contentSize.w > 0) {
|
|
31792
31886
|
const timer = setTimeout(fit, 50);
|
|
@@ -40569,6 +40663,27 @@ function generateSchedule(teams, roundLabel) {
|
|
|
40569
40663
|
}
|
|
40570
40664
|
return rounds;
|
|
40571
40665
|
}
|
|
40666
|
+
function hydrateResumeRounds(resume, teams) {
|
|
40667
|
+
if (!resume?.length || teams.length < 2) return [];
|
|
40668
|
+
const expected = teams.length % 2 === 0 ? teams.length - 1 : teams.length;
|
|
40669
|
+
if (resume.length !== expected) return [];
|
|
40670
|
+
const roster = new Set(teams.map((t) => t.toLowerCase()));
|
|
40671
|
+
for (const round of resume) {
|
|
40672
|
+
for (const m of round.matchups) {
|
|
40673
|
+
for (const side of [m.home, m.away]) {
|
|
40674
|
+
if (side !== BYE_TOKEN && !roster.has(side.toLowerCase())) return [];
|
|
40675
|
+
}
|
|
40676
|
+
}
|
|
40677
|
+
}
|
|
40678
|
+
return resume.map((round) => ({
|
|
40679
|
+
label: round.label,
|
|
40680
|
+
matchups: round.matchups.map((m) => ({
|
|
40681
|
+
home: m.home,
|
|
40682
|
+
away: m.away,
|
|
40683
|
+
isBye: m.home === BYE_TOKEN || m.away === BYE_TOKEN
|
|
40684
|
+
}))
|
|
40685
|
+
}));
|
|
40686
|
+
}
|
|
40572
40687
|
var DEFAULT_LABELS4 = {
|
|
40573
40688
|
inputPlaceholder: "Team or player name (comma-separated for batch)",
|
|
40574
40689
|
addButton: "Add",
|
|
@@ -40589,6 +40704,7 @@ function RoundRobinScheduler({
|
|
|
40589
40704
|
darkMode,
|
|
40590
40705
|
minTeams = 3,
|
|
40591
40706
|
defaultTeams = [],
|
|
40707
|
+
resumeRounds,
|
|
40592
40708
|
onTeamsChange,
|
|
40593
40709
|
onGenerate,
|
|
40594
40710
|
labels,
|
|
@@ -40602,7 +40718,9 @@ function RoundRobinScheduler({
|
|
|
40602
40718
|
const L = { ...DEFAULT_LABELS4, ...labels };
|
|
40603
40719
|
const [teams, setTeams] = useState80(defaultTeams);
|
|
40604
40720
|
const [input, setInput] = useState80("");
|
|
40605
|
-
const [rounds, setRounds] = useState80(
|
|
40721
|
+
const [rounds, setRounds] = useState80(
|
|
40722
|
+
() => hydrateResumeRounds(resumeRounds, defaultTeams)
|
|
40723
|
+
);
|
|
40606
40724
|
const inputRef = useRef49(null);
|
|
40607
40725
|
useEffect64(() => {
|
|
40608
40726
|
onTeamsChange?.(teams);
|
|
@@ -41128,6 +41246,8 @@ function Scoreboard({
|
|
|
41128
41246
|
maxTeams = 8,
|
|
41129
41247
|
scoreButtons = [-1, 1, 5, 10],
|
|
41130
41248
|
defaultTeams,
|
|
41249
|
+
initialRound = 1,
|
|
41250
|
+
initialHistory,
|
|
41131
41251
|
onTeamsChange,
|
|
41132
41252
|
onRoundAdvance,
|
|
41133
41253
|
onNewGame,
|
|
@@ -41143,8 +41263,12 @@ function Scoreboard({
|
|
|
41143
41263
|
const [teams, setTeams] = useState81(
|
|
41144
41264
|
() => defaultTeams && defaultTeams.length >= minTeams ? defaultTeams.slice(0, maxTeams) : createDefaultTeams(seedCount, L.teamNamePrefix)
|
|
41145
41265
|
);
|
|
41146
|
-
const [round, setRound] = useState81(
|
|
41147
|
-
|
|
41266
|
+
const [round, setRound] = useState81(
|
|
41267
|
+
() => Number.isFinite(initialRound) ? Math.max(1, Math.floor(initialRound)) : 1
|
|
41268
|
+
);
|
|
41269
|
+
const [history, setHistory] = useState81(
|
|
41270
|
+
() => initialHistory && initialHistory.length > 0 ? initialHistory.slice() : []
|
|
41271
|
+
);
|
|
41148
41272
|
const [historyOpen, setHistoryOpen] = useState81(false);
|
|
41149
41273
|
const rootRef = useRef50(null);
|
|
41150
41274
|
const [containerWidth, setContainerWidth] = useState81(0);
|