@digilogiclabs/saas-factory-ui 2.7.1 → 2.8.1

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.
@@ -30759,17 +30759,13 @@ function DiceRoller({
30759
30759
  const starts = currentPositionsRef.current ?? defaultPositions(w, h, clampedCount);
30760
30760
  const frames = simulateDice(w, h, effectiveSize, starts, clampedCount);
30761
30761
  for (let i = 0; i < clampedCount; i++) {
30762
- if (sides === 6) {
30763
- writeCubeRotation(
30764
- i,
30765
- (Math.random() - 0.5) * 720,
30766
- (Math.random() - 0.5) * 720,
30767
- (Math.random() - 0.5) * 720,
30768
- false
30769
- );
30770
- } else {
30771
- writeCubeRotation(i, 0, 0, (Math.random() - 0.5) * 720, false);
30772
- }
30762
+ writeCubeRotation(
30763
+ i,
30764
+ (Math.random() - 0.5) * 720,
30765
+ (Math.random() - 0.5) * 720,
30766
+ (Math.random() - 0.5) * 720,
30767
+ false
30768
+ );
30773
30769
  const el = dieWrapperRefs.current[i];
30774
30770
  if (el) el.style.transition = "none";
30775
30771
  const shadow = shadowRefs.current[i];
@@ -30830,8 +30826,10 @@ function DiceRoller({
30830
30826
  const lz = (Math.random() > 0.5 ? 1 : -1) * 360;
30831
30827
  writeCubeRotation(i, lx, ly, lz, true, tilt);
30832
30828
  } else {
30829
+ const lx = (Math.random() > 0.5 ? 1 : -1) * 720;
30830
+ const ly = (Math.random() > 0.5 ? 1 : -1) * 360;
30833
30831
  const lz = (Math.random() > 0.5 ? 1 : -1) * 720 + tilt;
30834
- writeCubeRotation(i, 0, 0, lz, true);
30832
+ writeCubeRotation(i, lx, ly, lz, true);
30835
30833
  }
30836
30834
  }
30837
30835
  });
@@ -30990,60 +30988,115 @@ function DiceRoller({
30990
30988
  )) : (() => {
30991
30989
  const shape = POLY_SHAPES[sides];
30992
30990
  const shown = results?.[d] ?? sides;
30993
- return /* @__PURE__ */ jsxs86(
30994
- "svg",
30995
- {
30996
- viewBox: "0 0 100 100",
30997
- width: "100%",
30998
- height: "100%",
30999
- style: { display: "block", overflow: "visible" },
31000
- "aria-hidden": "true",
31001
- children: [
31002
- /* @__PURE__ */ jsx113(
31003
- "polygon",
31004
- {
31005
- points: shape.points,
31006
- fill: colors.face,
31007
- stroke: colors.faceBorder,
31008
- strokeWidth: 2.5,
31009
- strokeLinejoin: "round",
31010
- style: { transition: "fill 0.3s, stroke 0.3s" }
31011
- }
31012
- ),
31013
- /* @__PURE__ */ jsx113(
31014
- "polygon",
31015
- {
31016
- points: shape.points,
31017
- fill: "none",
31018
- stroke: colors.faceBorder,
31019
- strokeWidth: 1.5,
31020
- strokeLinejoin: "round",
31021
- opacity: 0.55,
31022
- transform: "translate(50 50) scale(0.76) translate(-50 -50)"
31023
- }
31024
- ),
31025
- /* @__PURE__ */ jsx113(
31026
- "text",
31027
- {
31028
- ref: getNumeralSetter(d),
31029
- x: 50,
31030
- y: shape.textY,
31031
- textAnchor: "middle",
31032
- dominantBaseline: "central",
31033
- fontSize: 100 * shape.fontScale,
31034
- fontWeight: 800,
31035
- fill: colors.pip,
31036
- style: {
31037
- fontVariantNumeric: "tabular-nums",
31038
- transition: "fill 0.3s",
31039
- userSelect: "none"
31040
- },
31041
- children: formatDieValue(shown, sides)
31042
- }
31043
- )
31044
- ]
31045
- }
31046
- );
30991
+ const cardFaceStyle = {
30992
+ position: "absolute",
30993
+ inset: 0,
30994
+ display: "block",
30995
+ overflow: "visible",
30996
+ backfaceVisibility: "hidden"
30997
+ };
30998
+ return /* @__PURE__ */ jsxs86(Fragment30, { children: [
30999
+ /* @__PURE__ */ jsxs86(
31000
+ "svg",
31001
+ {
31002
+ viewBox: "0 0 100 100",
31003
+ width: "100%",
31004
+ height: "100%",
31005
+ style: cardFaceStyle,
31006
+ "aria-hidden": "true",
31007
+ children: [
31008
+ /* @__PURE__ */ jsx113(
31009
+ "polygon",
31010
+ {
31011
+ points: shape.points,
31012
+ fill: colors.face,
31013
+ stroke: colors.faceBorder,
31014
+ strokeWidth: 2.5,
31015
+ strokeLinejoin: "round",
31016
+ style: { transition: "fill 0.3s, stroke 0.3s" }
31017
+ }
31018
+ ),
31019
+ /* @__PURE__ */ jsx113(
31020
+ "polygon",
31021
+ {
31022
+ points: shape.points,
31023
+ fill: "none",
31024
+ stroke: colors.faceBorder,
31025
+ strokeWidth: 1.5,
31026
+ strokeLinejoin: "round",
31027
+ opacity: 0.55,
31028
+ transform: "translate(50 50) scale(0.76) translate(-50 -50)"
31029
+ }
31030
+ ),
31031
+ /* @__PURE__ */ jsx113(
31032
+ "text",
31033
+ {
31034
+ ref: getNumeralSetter(d),
31035
+ x: 50,
31036
+ y: shape.textY,
31037
+ textAnchor: "middle",
31038
+ dominantBaseline: "central",
31039
+ fontSize: 100 * shape.fontScale,
31040
+ fontWeight: 800,
31041
+ fill: colors.pip,
31042
+ style: {
31043
+ fontVariantNumeric: "tabular-nums",
31044
+ transition: "fill 0.3s",
31045
+ userSelect: "none"
31046
+ },
31047
+ children: formatDieValue(shown, sides)
31048
+ }
31049
+ )
31050
+ ]
31051
+ }
31052
+ ),
31053
+ /* @__PURE__ */ jsxs86(
31054
+ "svg",
31055
+ {
31056
+ viewBox: "0 0 100 100",
31057
+ width: "100%",
31058
+ height: "100%",
31059
+ style: {
31060
+ ...cardFaceStyle,
31061
+ transform: "rotateY(180deg)"
31062
+ },
31063
+ "aria-hidden": "true",
31064
+ children: [
31065
+ /* @__PURE__ */ jsx113(
31066
+ "polygon",
31067
+ {
31068
+ points: shape.points,
31069
+ fill: colors.face,
31070
+ stroke: colors.faceBorder,
31071
+ strokeWidth: 2.5,
31072
+ strokeLinejoin: "round",
31073
+ style: { transition: "fill 0.3s, stroke 0.3s" }
31074
+ }
31075
+ ),
31076
+ /* @__PURE__ */ jsx113(
31077
+ "polygon",
31078
+ {
31079
+ points: shape.points,
31080
+ fill: "none",
31081
+ stroke: colors.faceBorder,
31082
+ strokeWidth: 1.5,
31083
+ strokeLinejoin: "round",
31084
+ opacity: 0.55,
31085
+ transform: "translate(50 50) scale(0.76) translate(-50 -50)"
31086
+ }
31087
+ ),
31088
+ /* @__PURE__ */ jsx113(
31089
+ "polygon",
31090
+ {
31091
+ points: shape.points,
31092
+ fill: "#000",
31093
+ opacity: 0.14
31094
+ }
31095
+ )
31096
+ ]
31097
+ }
31098
+ )
31099
+ ] });
31047
31100
  })()
31048
31101
  }
31049
31102
  )
@@ -31798,32 +31851,26 @@ function BracketGenerator({
31798
31851
  const autoPlay = useCallback42(() => {
31799
31852
  if (simulating) {
31800
31853
  if (autoRef.current) clearTimeout(autoRef.current);
31854
+ autoRef.current = null;
31801
31855
  setSimulating(false);
31802
31856
  return;
31803
31857
  }
31804
31858
  setSimulating(true);
31805
- const tick = () => {
31806
- setBracketState((prev) => {
31807
- const next = prev.matches.find((m) => m.a && m.b && !m.winner);
31808
- if (!next) {
31809
- setSimulating(false);
31810
- return prev;
31811
- }
31812
- const completed = simulateMatch(next);
31813
- if (!completed) return prev;
31814
- let matches = prev.matches.map(
31815
- (m) => m.id === completed.id ? completed : m
31816
- );
31817
- matches = propagateWinner(matches, completed);
31818
- const finalMatch = matches.find((m) => m.round === prev.rounds - 1);
31819
- const champion = finalMatch?.winner || null;
31820
- if (!champion) autoRef.current = setTimeout(tick, simulateDelayMs);
31821
- else setSimulating(false);
31822
- return { ...prev, matches, champion };
31823
- });
31859
+ simulateNext();
31860
+ }, [simulating, simulateNext]);
31861
+ useEffect52(() => {
31862
+ if (!simulating) return;
31863
+ const hasNext = bracketState.matches.some((m) => m.a && m.b && !m.winner);
31864
+ if (bracketState.champion || !hasNext) {
31865
+ setSimulating(false);
31866
+ return;
31867
+ }
31868
+ autoRef.current = setTimeout(simulateNext, simulateDelayMs);
31869
+ return () => {
31870
+ if (autoRef.current) clearTimeout(autoRef.current);
31871
+ autoRef.current = null;
31824
31872
  };
31825
- tick();
31826
- }, [simulating, simulateDelayMs]);
31873
+ }, [simulating, bracketState, simulateDelayMs, simulateNext]);
31827
31874
  const advanceWinner = useCallback42(
31828
31875
  (matchId, winnerSlot) => {
31829
31876
  setBracketState((prev) => {
@@ -39470,8 +39517,8 @@ function RosterImport({
39470
39517
  maxNames,
39471
39518
  maxFileBytes,
39472
39519
  onClose: () => setOpen(false),
39473
- onImport: (names) => {
39474
- onImport(names);
39520
+ onImport: (names, info) => {
39521
+ onImport(names, info);
39475
39522
  setOpen(false);
39476
39523
  }
39477
39524
  }
@@ -39537,6 +39584,11 @@ function RosterImportModal({
39537
39584
  }),
39538
39585
  [table, column, skipHeader, maxNames]
39539
39586
  );
39587
+ const extractedTotal = useMemo34(
39588
+ () => extractRoster(table, { column, skipHeader }),
39589
+ [table, column, skipHeader]
39590
+ );
39591
+ const trimmedCount = Math.max(0, extractedTotal.length - extracted.length);
39540
39592
  const handleFile = useCallback49(
39541
39593
  async (e) => {
39542
39594
  setFileError(null);
@@ -39914,7 +39966,10 @@ function RosterImportModal({
39914
39966
  "button",
39915
39967
  {
39916
39968
  type: "button",
39917
- onClick: () => onImport(extracted),
39969
+ onClick: () => onImport(extracted, {
39970
+ trimmedCount,
39971
+ totalCount: extractedTotal.length
39972
+ }),
39918
39973
  disabled: !canImport,
39919
39974
  style: primaryBtn(!canImport),
39920
39975
  children: confirmLabel
@@ -40118,6 +40173,19 @@ function IconUsers({ size = 40 }) {
40118
40173
  }
40119
40174
  );
40120
40175
  }
40176
+ function mergeNames(prev, incoming, max) {
40177
+ const seen = new Set(prev.map((n) => n.toLowerCase()));
40178
+ const room = Math.max(0, max - prev.length);
40179
+ const deduped = [];
40180
+ for (const n of incoming) {
40181
+ const key = n.toLowerCase();
40182
+ if (seen.has(key)) continue;
40183
+ seen.add(key);
40184
+ deduped.push(n);
40185
+ if (deduped.length >= room) break;
40186
+ }
40187
+ return deduped.length > 0 ? [...prev, ...deduped] : prev;
40188
+ }
40121
40189
  function splitIntoTeams(names, count2) {
40122
40190
  const shuffled = shuffle(names);
40123
40191
  const teams = Array.from({ length: count2 }, () => []);
@@ -40191,29 +40259,14 @@ function TeamGenerator({
40191
40259
  const trimmed = input.trim();
40192
40260
  if (!trimmed) return;
40193
40261
  const newNames = trimmed.split(/[,\n]+/).map((n) => n.trim()).filter((n) => n.length > 0);
40194
- setNames((prev) => {
40195
- const room = Math.max(0, maxPlayers - prev.length);
40196
- return [...prev, ...newNames.slice(0, room)];
40197
- });
40262
+ setNames((prev) => mergeNames(prev, newNames, maxPlayers));
40198
40263
  setInput("");
40199
40264
  inputRef.current?.focus();
40200
40265
  }, [input, maxPlayers]);
40201
40266
  const importNames = useCallback50(
40202
40267
  (incoming) => {
40203
40268
  if (incoming.length === 0) return;
40204
- setNames((prev) => {
40205
- const seen = new Set(prev.map((n) => n.toLowerCase()));
40206
- const room = Math.max(0, maxPlayers - prev.length);
40207
- const deduped = [];
40208
- for (const n of incoming) {
40209
- const key = n.toLowerCase();
40210
- if (seen.has(key)) continue;
40211
- seen.add(key);
40212
- deduped.push(n);
40213
- if (deduped.length >= room) break;
40214
- }
40215
- return deduped.length > 0 ? [...prev, ...deduped] : prev;
40216
- });
40269
+ setNames((prev) => mergeNames(prev, incoming, maxPlayers));
40217
40270
  },
40218
40271
  [maxPlayers]
40219
40272
  );
@@ -40838,7 +40891,7 @@ function RoundRobinScheduler({
40838
40891
  useEffect62(() => {
40839
40892
  onTeamsChange?.(teams);
40840
40893
  }, [teams, onTeamsChange]);
40841
- const mergeNames = useCallback51(
40894
+ const mergeNames2 = useCallback51(
40842
40895
  (prev, incoming) => {
40843
40896
  const existing = new Set(prev.map((t) => t.toLowerCase()));
40844
40897
  const next = [...prev];
@@ -40864,20 +40917,20 @@ function RoundRobinScheduler({
40864
40917
  const names = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
40865
40918
  if (names.length === 0) return;
40866
40919
  if (!gateDiscard("add")) return;
40867
- setTeams((prev) => mergeNames(prev, names));
40920
+ setTeams((prev) => mergeNames2(prev, names));
40868
40921
  setInput("");
40869
40922
  setRounds([]);
40870
40923
  },
40871
- [mergeNames, gateDiscard]
40924
+ [mergeNames2, gateDiscard]
40872
40925
  );
40873
40926
  const importTeams = useCallback51(
40874
40927
  (incoming) => {
40875
40928
  if (incoming.length === 0) return;
40876
40929
  if (!gateDiscard("import")) return;
40877
- setTeams((prev) => mergeNames(prev, incoming));
40930
+ setTeams((prev) => mergeNames2(prev, incoming));
40878
40931
  setRounds([]);
40879
40932
  },
40880
- [mergeNames, gateDiscard]
40933
+ [mergeNames2, gateDiscard]
40881
40934
  );
40882
40935
  const handleKeyDown = useCallback51(
40883
40936
  (e) => {
@@ -41382,6 +41435,8 @@ function Scoreboard({
41382
41435
  onBeforeReset,
41383
41436
  onBeforeNewGame,
41384
41437
  nameMaxLength,
41438
+ scoreMin = -9999,
41439
+ scoreMax = 9999,
41385
41440
  labels,
41386
41441
  ariaLabel = "Scoreboard",
41387
41442
  className
@@ -41425,11 +41480,19 @@ function Scoreboard({
41425
41480
  useEffect63(() => {
41426
41481
  onTeamsChange?.(teams);
41427
41482
  }, [teams, onTeamsChange]);
41428
- const updateScore = useCallback52((index, delta) => {
41429
- setTeams(
41430
- (prev) => prev.map((t, i) => i === index ? { ...t, score: t.score + delta } : t)
41431
- );
41432
- }, []);
41483
+ const updateScore = useCallback52(
41484
+ (index, delta) => {
41485
+ setTeams(
41486
+ (prev) => prev.map(
41487
+ (t, i) => i === index ? {
41488
+ ...t,
41489
+ score: Math.min(scoreMax, Math.max(scoreMin, t.score + delta))
41490
+ } : t
41491
+ )
41492
+ );
41493
+ },
41494
+ [scoreMin, scoreMax]
41495
+ );
41433
41496
  const updateName = useCallback52((index, name) => {
41434
41497
  setTeams((prev) => prev.map((t, i) => i === index ? { ...t, name } : t));
41435
41498
  }, []);