@digilogiclabs/saas-factory-ui 2.4.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 +41 -8
- package/dist/index.d.ts +41 -8
- package/dist/index.js +141 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +141 -25
- package/dist/index.mjs.map +1 -1
- package/dist/web/index.d.mts +41 -8
- package/dist/web/index.d.ts +41 -8
- package/dist/web/index.js +141 -25
- package/dist/web/index.js.map +1 -1
- package/dist/web/index.mjs +141 -25
- package/dist/web/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/web/index.mjs
CHANGED
|
@@ -33405,6 +33405,11 @@ var WEDGE_PALETTE = [
|
|
|
33405
33405
|
];
|
|
33406
33406
|
var DEFAULT_EASING = "cubic-bezier(0.25, 0.46, 0.45, 0.94)";
|
|
33407
33407
|
var DRAMATIC_EASING = "cubic-bezier(0.39, 0.575, 0.565, 1)";
|
|
33408
|
+
var PHYSICS_DECAY_K = 4;
|
|
33409
|
+
function physicsRampDown(t) {
|
|
33410
|
+
return (1 - Math.exp(-PHYSICS_DECAY_K * t)) / (1 - Math.exp(-PHYSICS_DECAY_K));
|
|
33411
|
+
}
|
|
33412
|
+
var REEL_LEAD_IN = 32;
|
|
33408
33413
|
var INTENSITY_CONFIG = {
|
|
33409
33414
|
subtle: {
|
|
33410
33415
|
particles: 14,
|
|
@@ -33476,6 +33481,9 @@ function ReelStage({
|
|
|
33476
33481
|
winner,
|
|
33477
33482
|
spinning,
|
|
33478
33483
|
reelY,
|
|
33484
|
+
displayY,
|
|
33485
|
+
cssTransition,
|
|
33486
|
+
tapeRef,
|
|
33479
33487
|
reelVisibleRows,
|
|
33480
33488
|
reelRowHeight,
|
|
33481
33489
|
size,
|
|
@@ -33499,17 +33507,16 @@ function ReelStage({
|
|
|
33499
33507
|
const stripHeight = reelVisibleRows * reelRowHeight;
|
|
33500
33508
|
const centerOffsetPx = (reelVisibleRows - 1) / 2 * reelRowHeight;
|
|
33501
33509
|
const P = pool.length;
|
|
33502
|
-
const leadIn = 32;
|
|
33503
33510
|
const tapeRows = Math.max(
|
|
33504
|
-
reelVisibleRows +
|
|
33505
|
-
Math.ceil((reelY + stripHeight) / reelRowHeight) +
|
|
33511
|
+
reelVisibleRows + REEL_LEAD_IN + 1,
|
|
33512
|
+
Math.ceil((reelY + stripHeight) / reelRowHeight) + REEL_LEAD_IN + 1
|
|
33506
33513
|
);
|
|
33507
33514
|
const tape = Array.from({ length: tapeRows }, (_, i) => {
|
|
33508
|
-
const poolIdx = P === 0 ? 0 : ((i -
|
|
33515
|
+
const poolIdx = P === 0 ? 0 : ((i - REEL_LEAD_IN) % P + P) % P;
|
|
33509
33516
|
return pool[poolIdx];
|
|
33510
33517
|
});
|
|
33511
|
-
const effectiveY =
|
|
33512
|
-
const transition = spinning ? `transform ${reducedMotion ? 250 : Math.round(spinDuration * intensityCfg.durationMult)}ms ${intensityCfg.easing}` : "none";
|
|
33518
|
+
const effectiveY = displayY + REEL_LEAD_IN * reelRowHeight;
|
|
33519
|
+
const transition = spinning && cssTransition ? `transform ${reducedMotion ? 250 : Math.round(spinDuration * intensityCfg.durationMult)}ms ${intensityCfg.easing}` : "none";
|
|
33513
33520
|
return /* @__PURE__ */ jsxs89(
|
|
33514
33521
|
"div",
|
|
33515
33522
|
{
|
|
@@ -33554,6 +33561,7 @@ function ReelStage({
|
|
|
33554
33561
|
) : /* @__PURE__ */ jsx116(
|
|
33555
33562
|
"div",
|
|
33556
33563
|
{
|
|
33564
|
+
ref: tapeRef,
|
|
33557
33565
|
"aria-hidden": "true",
|
|
33558
33566
|
style: {
|
|
33559
33567
|
position: "absolute",
|
|
@@ -33769,6 +33777,9 @@ function RandomPlayerPicker({
|
|
|
33769
33777
|
showStats = true,
|
|
33770
33778
|
renderWinner,
|
|
33771
33779
|
spinRef,
|
|
33780
|
+
resetRef,
|
|
33781
|
+
onPoolChange,
|
|
33782
|
+
draftCompleteCaption = "Draft complete \u2014 reset to spin again",
|
|
33772
33783
|
intensity = "normal",
|
|
33773
33784
|
enableHaptics = false,
|
|
33774
33785
|
tickSoundUrl,
|
|
@@ -33783,6 +33794,7 @@ function RandomPlayerPicker({
|
|
|
33783
33794
|
const dark = useDarkMode(darkMode);
|
|
33784
33795
|
const reducedMotion = usePrefersReducedMotion();
|
|
33785
33796
|
const intensityCfg = INTENSITY_CONFIG[intensity];
|
|
33797
|
+
const physicsDriven = intensity === "dramatic" && !reducedMotion;
|
|
33786
33798
|
const [pool, setPool] = useState70(participants);
|
|
33787
33799
|
const [rotation, setRotation] = useState70(0);
|
|
33788
33800
|
const [reelY, setReelY] = useState70(0);
|
|
@@ -33801,6 +33813,11 @@ function RandomPlayerPicker({
|
|
|
33801
33813
|
const winAudioRef = useRef43(null);
|
|
33802
33814
|
const containerRef = useRef43(null);
|
|
33803
33815
|
const prevIdsRef = useRef43("");
|
|
33816
|
+
const wheelSvgRef = useRef43(null);
|
|
33817
|
+
const reelTapeRef = useRef43(null);
|
|
33818
|
+
const rafRef = useRef43(null);
|
|
33819
|
+
const visualRotationRef = useRef43(null);
|
|
33820
|
+
const visualReelYRef = useRef43(null);
|
|
33804
33821
|
useEffect55(() => {
|
|
33805
33822
|
if (typeof window === "undefined" || !tickSoundUrl) {
|
|
33806
33823
|
tickAudioRef.current = null;
|
|
@@ -33854,6 +33871,12 @@ function RandomPlayerPicker({
|
|
|
33854
33871
|
clearTimeout(popTimer.current);
|
|
33855
33872
|
popTimer.current = null;
|
|
33856
33873
|
}
|
|
33874
|
+
if (rafRef.current) {
|
|
33875
|
+
cancelAnimationFrame(rafRef.current);
|
|
33876
|
+
rafRef.current = null;
|
|
33877
|
+
}
|
|
33878
|
+
visualRotationRef.current = null;
|
|
33879
|
+
visualReelYRef.current = null;
|
|
33857
33880
|
pendingPopIdxRef.current = null;
|
|
33858
33881
|
setSpinning(false);
|
|
33859
33882
|
setPool(participants);
|
|
@@ -33965,7 +33988,56 @@ function RandomPlayerPicker({
|
|
|
33965
33988
|
} else {
|
|
33966
33989
|
setRotation(finalRotation);
|
|
33967
33990
|
}
|
|
33968
|
-
|
|
33991
|
+
const fireTick = () => {
|
|
33992
|
+
onTick?.();
|
|
33993
|
+
const ta = tickAudioRef.current;
|
|
33994
|
+
if (ta) {
|
|
33995
|
+
try {
|
|
33996
|
+
ta.currentTime = 0;
|
|
33997
|
+
void ta.play().catch(() => {
|
|
33998
|
+
});
|
|
33999
|
+
} catch {
|
|
34000
|
+
}
|
|
34001
|
+
}
|
|
34002
|
+
};
|
|
34003
|
+
if (physicsDriven) {
|
|
34004
|
+
const from = mode === "reel" ? activeReelY : activeRotation;
|
|
34005
|
+
const to = mode === "reel" ? finalReelY : finalRotation;
|
|
34006
|
+
const crossUnit = mode === "reel" ? reelRowHeight : activeAnglePerWedge * 180 / Math.PI;
|
|
34007
|
+
if (mode === "reel") visualReelYRef.current = from;
|
|
34008
|
+
else visualRotationRef.current = from;
|
|
34009
|
+
let crossings = 0;
|
|
34010
|
+
const t0 = performance.now();
|
|
34011
|
+
const step = (now) => {
|
|
34012
|
+
const t = Math.min(1, (now - t0) / effectiveDuration);
|
|
34013
|
+
const value = from + (to - from) * physicsRampDown(t);
|
|
34014
|
+
if (mode === "reel") {
|
|
34015
|
+
visualReelYRef.current = value;
|
|
34016
|
+
const el = reelTapeRef.current;
|
|
34017
|
+
if (el) {
|
|
34018
|
+
el.style.transform = `translateY(${-(value + REEL_LEAD_IN * reelRowHeight)}px)`;
|
|
34019
|
+
}
|
|
34020
|
+
} else {
|
|
34021
|
+
visualRotationRef.current = value;
|
|
34022
|
+
const el = wheelSvgRef.current;
|
|
34023
|
+
if (el) el.style.transform = `rotate(${value}deg)`;
|
|
34024
|
+
}
|
|
34025
|
+
const crossed = Math.floor(Math.abs(value - from) / crossUnit);
|
|
34026
|
+
if (crossed > crossings) {
|
|
34027
|
+
crossings = crossed;
|
|
34028
|
+
fireTick();
|
|
34029
|
+
}
|
|
34030
|
+
if (t < 1) {
|
|
34031
|
+
rafRef.current = requestAnimationFrame(step);
|
|
34032
|
+
} else {
|
|
34033
|
+
rafRef.current = null;
|
|
34034
|
+
visualRotationRef.current = null;
|
|
34035
|
+
visualReelYRef.current = null;
|
|
34036
|
+
}
|
|
34037
|
+
};
|
|
34038
|
+
rafRef.current = requestAnimationFrame(step);
|
|
34039
|
+
}
|
|
34040
|
+
if (!physicsDriven && (onTick || tickAudioRef.current) && !reducedMotion) {
|
|
33969
34041
|
const wedges = mode === "reel" ? Math.max(1, reelRevRows + targetRowOffset) : (() => {
|
|
33970
34042
|
const totalDelta = deltaMod + revolutions * 360;
|
|
33971
34043
|
const wedgeDeg = activeAnglePerWedge * 180 / Math.PI;
|
|
@@ -33983,16 +34055,7 @@ function RandomPlayerPicker({
|
|
|
33983
34055
|
const eased = 1 - Math.pow(1 - progress, 3);
|
|
33984
34056
|
const interval = startInterval + (endInterval - startInterval) * eased;
|
|
33985
34057
|
tickInterval.current = setTimeout(() => {
|
|
33986
|
-
|
|
33987
|
-
const ta = tickAudioRef.current;
|
|
33988
|
-
if (ta) {
|
|
33989
|
-
try {
|
|
33990
|
-
ta.currentTime = 0;
|
|
33991
|
-
void ta.play().catch(() => {
|
|
33992
|
-
});
|
|
33993
|
-
} catch {
|
|
33994
|
-
}
|
|
33995
|
-
}
|
|
34058
|
+
fireTick();
|
|
33996
34059
|
elapsed += interval;
|
|
33997
34060
|
schedule();
|
|
33998
34061
|
}, interval);
|
|
@@ -34052,7 +34115,7 @@ function RandomPlayerPicker({
|
|
|
34052
34115
|
pendingPopIdxRef.current = null;
|
|
34053
34116
|
if (!removeWinnersRef.current) return;
|
|
34054
34117
|
setPool((p) => p.filter((_, i) => i !== finalWinnerIdx));
|
|
34055
|
-
setWinner(null);
|
|
34118
|
+
if (activePool.length - 1 >= 2) setWinner(null);
|
|
34056
34119
|
setRotation(0);
|
|
34057
34120
|
setReelY(0);
|
|
34058
34121
|
}, 2800);
|
|
@@ -34075,6 +34138,7 @@ function RandomPlayerPicker({
|
|
|
34075
34138
|
maxRevolutions,
|
|
34076
34139
|
history,
|
|
34077
34140
|
reducedMotion,
|
|
34141
|
+
physicsDriven,
|
|
34078
34142
|
enableHaptics,
|
|
34079
34143
|
intensityCfg.particles,
|
|
34080
34144
|
intensityCfg.durationMult,
|
|
@@ -34086,12 +34150,20 @@ function RandomPlayerPicker({
|
|
|
34086
34150
|
if (spinRef && spinRef.current === spin) spinRef.current = null;
|
|
34087
34151
|
};
|
|
34088
34152
|
}, [spin, spinRef]);
|
|
34153
|
+
const onPoolChangeRef = useRef43(onPoolChange);
|
|
34154
|
+
useEffect55(() => {
|
|
34155
|
+
onPoolChangeRef.current = onPoolChange;
|
|
34156
|
+
});
|
|
34157
|
+
useEffect55(() => {
|
|
34158
|
+
onPoolChangeRef.current?.(pool);
|
|
34159
|
+
}, [pool]);
|
|
34089
34160
|
useEffect55(
|
|
34090
34161
|
() => () => {
|
|
34091
34162
|
if (winnerTimer.current) clearTimeout(winnerTimer.current);
|
|
34092
34163
|
if (particleTimer.current) clearTimeout(particleTimer.current);
|
|
34093
34164
|
if (popTimer.current) clearTimeout(popTimer.current);
|
|
34094
34165
|
if (tickInterval.current) clearTimeout(tickInterval.current);
|
|
34166
|
+
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
|
34095
34167
|
},
|
|
34096
34168
|
[]
|
|
34097
34169
|
);
|
|
@@ -34121,6 +34193,12 @@ function RandomPlayerPicker({
|
|
|
34121
34193
|
clearTimeout(popTimer.current);
|
|
34122
34194
|
popTimer.current = null;
|
|
34123
34195
|
}
|
|
34196
|
+
if (rafRef.current) {
|
|
34197
|
+
cancelAnimationFrame(rafRef.current);
|
|
34198
|
+
rafRef.current = null;
|
|
34199
|
+
}
|
|
34200
|
+
visualRotationRef.current = null;
|
|
34201
|
+
visualReelYRef.current = null;
|
|
34124
34202
|
pendingPopIdxRef.current = null;
|
|
34125
34203
|
setSpinning(false);
|
|
34126
34204
|
setPool(participants);
|
|
@@ -34130,9 +34208,17 @@ function RandomPlayerPicker({
|
|
|
34130
34208
|
setReelY(0);
|
|
34131
34209
|
setParticles([]);
|
|
34132
34210
|
}, [participants]);
|
|
34211
|
+
useEffect55(() => {
|
|
34212
|
+
if (resetRef) resetRef.current = reset;
|
|
34213
|
+
return () => {
|
|
34214
|
+
if (resetRef && resetRef.current === reset) resetRef.current = null;
|
|
34215
|
+
};
|
|
34216
|
+
}, [reset, resetRef]);
|
|
34133
34217
|
const isIdle = n < 2;
|
|
34218
|
+
const drainedByDraft = isIdle && participants.length >= 2;
|
|
34219
|
+
const effectiveIdleCaption = drainedByDraft ? draftCompleteCaption : placeholderCaption;
|
|
34134
34220
|
const placeholderDiscColor = dark ? "#2a3344" : "#e2e8f0";
|
|
34135
|
-
if (isIdle && placeholderMode === "message") {
|
|
34221
|
+
if (isIdle && !drainedByDraft && placeholderMode === "message") {
|
|
34136
34222
|
return /* @__PURE__ */ jsx116(
|
|
34137
34223
|
"div",
|
|
34138
34224
|
{
|
|
@@ -34154,6 +34240,8 @@ function RandomPlayerPicker({
|
|
|
34154
34240
|
const shakeKeyframe = `rppShake_${intensity}`;
|
|
34155
34241
|
const glowKeyframe = `rppGlow_${intensity}`;
|
|
34156
34242
|
const pulseKeyframe = `rppPulse_${intensity}`;
|
|
34243
|
+
const displayRotation = visualRotationRef.current ?? rotation;
|
|
34244
|
+
const displayReelY = visualReelYRef.current ?? reelY;
|
|
34157
34245
|
return /* @__PURE__ */ jsxs89(
|
|
34158
34246
|
"div",
|
|
34159
34247
|
{
|
|
@@ -34200,13 +34288,33 @@ function RandomPlayerPicker({
|
|
|
34200
34288
|
[data-rpp-anim] { animation: none !important; }
|
|
34201
34289
|
}
|
|
34202
34290
|
` }),
|
|
34203
|
-
|
|
34291
|
+
isIdle && placeholderMode === "message" ? (
|
|
34292
|
+
/* Drained draft in "message" mode — compact box in the wheel's
|
|
34293
|
+
place; the winner card / stats / controls / history below stay
|
|
34294
|
+
mounted so the endgame isn't a dead end. */
|
|
34295
|
+
/* @__PURE__ */ jsx116(
|
|
34296
|
+
"div",
|
|
34297
|
+
{
|
|
34298
|
+
style: {
|
|
34299
|
+
padding: "2rem 1rem",
|
|
34300
|
+
textAlign: "center",
|
|
34301
|
+
color: c.dim,
|
|
34302
|
+
borderRadius: 12,
|
|
34303
|
+
border: `1px dashed ${c.border}`
|
|
34304
|
+
},
|
|
34305
|
+
children: effectiveIdleCaption
|
|
34306
|
+
}
|
|
34307
|
+
)
|
|
34308
|
+
) : mode === "reel" ? /* @__PURE__ */ jsx116(
|
|
34204
34309
|
ReelStage,
|
|
34205
34310
|
{
|
|
34206
34311
|
pool,
|
|
34207
34312
|
winner,
|
|
34208
34313
|
spinning,
|
|
34209
34314
|
reelY,
|
|
34315
|
+
displayY: displayReelY,
|
|
34316
|
+
cssTransition: !physicsDriven,
|
|
34317
|
+
tapeRef: reelTapeRef,
|
|
34210
34318
|
reelVisibleRows,
|
|
34211
34319
|
reelRowHeight,
|
|
34212
34320
|
size,
|
|
@@ -34215,7 +34323,7 @@ function RandomPlayerPicker({
|
|
|
34215
34323
|
dark,
|
|
34216
34324
|
isIdle,
|
|
34217
34325
|
placeholderMode,
|
|
34218
|
-
placeholderCaption,
|
|
34326
|
+
placeholderCaption: effectiveIdleCaption,
|
|
34219
34327
|
placeholderDiscColor,
|
|
34220
34328
|
spinDuration,
|
|
34221
34329
|
intensityCfg,
|
|
@@ -34272,6 +34380,7 @@ function RandomPlayerPicker({
|
|
|
34272
34380
|
/* @__PURE__ */ jsxs89(
|
|
34273
34381
|
"svg",
|
|
34274
34382
|
{
|
|
34383
|
+
ref: wheelSvgRef,
|
|
34275
34384
|
width: size,
|
|
34276
34385
|
height: size,
|
|
34277
34386
|
"aria-hidden": "true",
|
|
@@ -34280,8 +34389,8 @@ function RandomPlayerPicker({
|
|
|
34280
34389
|
top: 36,
|
|
34281
34390
|
left: 0,
|
|
34282
34391
|
transformOrigin: `${cx}px ${cy}px`,
|
|
34283
|
-
transform: `rotate(${
|
|
34284
|
-
transition: spinning ? `transform ${reducedMotion ? 250 : Math.round(spinDuration * intensityCfg.durationMult)}ms ${intensityCfg.easing}` : "none",
|
|
34392
|
+
transform: `rotate(${displayRotation}deg)`,
|
|
34393
|
+
transition: spinning && !physicsDriven ? `transform ${reducedMotion ? 250 : Math.round(spinDuration * intensityCfg.durationMult)}ms ${intensityCfg.easing}` : "none",
|
|
34285
34394
|
filter: `drop-shadow(0 8px 28px ${dark ? "rgba(0,0,0,0.55)" : "rgba(0,0,0,0.15)"})`
|
|
34286
34395
|
},
|
|
34287
34396
|
children: [
|
|
@@ -34434,7 +34543,7 @@ function RandomPlayerPicker({
|
|
|
34434
34543
|
pointerEvents: "none",
|
|
34435
34544
|
zIndex: 3
|
|
34436
34545
|
},
|
|
34437
|
-
children:
|
|
34546
|
+
children: effectiveIdleCaption
|
|
34438
34547
|
}
|
|
34439
34548
|
),
|
|
34440
34549
|
particles.map((p) => /* @__PURE__ */ jsx116(
|
|
@@ -39946,8 +40055,10 @@ function TeamGenerator({
|
|
|
39946
40055
|
minPlayersPerTeam = 2,
|
|
39947
40056
|
maxPlayers = Number.POSITIVE_INFINITY,
|
|
39948
40057
|
defaultNames = [],
|
|
40058
|
+
defaultTeams,
|
|
39949
40059
|
onNamesChange,
|
|
39950
40060
|
onGenerate,
|
|
40061
|
+
onTeamsChange,
|
|
39951
40062
|
onTeamCountChange,
|
|
39952
40063
|
labels,
|
|
39953
40064
|
ariaLabel = "Team generator",
|
|
@@ -39962,12 +40073,17 @@ function TeamGenerator({
|
|
|
39962
40073
|
const [names, setNames] = useState76(defaultNames);
|
|
39963
40074
|
const [input, setInput] = useState76("");
|
|
39964
40075
|
const [teamCount, setTeamCount] = useState76(initialCount);
|
|
39965
|
-
const [teams, setTeams] = useState76(
|
|
40076
|
+
const [teams, setTeams] = useState76(
|
|
40077
|
+
defaultTeams && defaultTeams.length > 0 ? defaultTeams : null
|
|
40078
|
+
);
|
|
39966
40079
|
const inputRef = useRef49(null);
|
|
39967
40080
|
const minNames = teamCount * minPlayersPerTeam;
|
|
39968
40081
|
useEffect61(() => {
|
|
39969
40082
|
onNamesChange?.(names);
|
|
39970
40083
|
}, [names, onNamesChange]);
|
|
40084
|
+
useEffect61(() => {
|
|
40085
|
+
onTeamsChange?.(teams);
|
|
40086
|
+
}, [teams, onTeamsChange]);
|
|
39971
40087
|
const addName = useCallback50(() => {
|
|
39972
40088
|
const trimmed = input.trim();
|
|
39973
40089
|
if (!trimmed) return;
|