@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/index.mjs
CHANGED
|
@@ -33500,6 +33500,11 @@ var WEDGE_PALETTE = [
|
|
|
33500
33500
|
];
|
|
33501
33501
|
var DEFAULT_EASING = "cubic-bezier(0.25, 0.46, 0.45, 0.94)";
|
|
33502
33502
|
var DRAMATIC_EASING = "cubic-bezier(0.39, 0.575, 0.565, 1)";
|
|
33503
|
+
var PHYSICS_DECAY_K = 4;
|
|
33504
|
+
function physicsRampDown(t) {
|
|
33505
|
+
return (1 - Math.exp(-PHYSICS_DECAY_K * t)) / (1 - Math.exp(-PHYSICS_DECAY_K));
|
|
33506
|
+
}
|
|
33507
|
+
var REEL_LEAD_IN = 32;
|
|
33503
33508
|
var INTENSITY_CONFIG = {
|
|
33504
33509
|
subtle: {
|
|
33505
33510
|
particles: 14,
|
|
@@ -33571,6 +33576,9 @@ function ReelStage({
|
|
|
33571
33576
|
winner,
|
|
33572
33577
|
spinning,
|
|
33573
33578
|
reelY,
|
|
33579
|
+
displayY,
|
|
33580
|
+
cssTransition,
|
|
33581
|
+
tapeRef,
|
|
33574
33582
|
reelVisibleRows,
|
|
33575
33583
|
reelRowHeight,
|
|
33576
33584
|
size,
|
|
@@ -33594,17 +33602,16 @@ function ReelStage({
|
|
|
33594
33602
|
const stripHeight = reelVisibleRows * reelRowHeight;
|
|
33595
33603
|
const centerOffsetPx = (reelVisibleRows - 1) / 2 * reelRowHeight;
|
|
33596
33604
|
const P = pool.length;
|
|
33597
|
-
const leadIn = 32;
|
|
33598
33605
|
const tapeRows = Math.max(
|
|
33599
|
-
reelVisibleRows +
|
|
33600
|
-
Math.ceil((reelY + stripHeight) / reelRowHeight) +
|
|
33606
|
+
reelVisibleRows + REEL_LEAD_IN + 1,
|
|
33607
|
+
Math.ceil((reelY + stripHeight) / reelRowHeight) + REEL_LEAD_IN + 1
|
|
33601
33608
|
);
|
|
33602
33609
|
const tape = Array.from({ length: tapeRows }, (_, i) => {
|
|
33603
|
-
const poolIdx = P === 0 ? 0 : ((i -
|
|
33610
|
+
const poolIdx = P === 0 ? 0 : ((i - REEL_LEAD_IN) % P + P) % P;
|
|
33604
33611
|
return pool[poolIdx];
|
|
33605
33612
|
});
|
|
33606
|
-
const effectiveY =
|
|
33607
|
-
const transition = spinning ? `transform ${reducedMotion ? 250 : Math.round(spinDuration * intensityCfg.durationMult)}ms ${intensityCfg.easing}` : "none";
|
|
33613
|
+
const effectiveY = displayY + REEL_LEAD_IN * reelRowHeight;
|
|
33614
|
+
const transition = spinning && cssTransition ? `transform ${reducedMotion ? 250 : Math.round(spinDuration * intensityCfg.durationMult)}ms ${intensityCfg.easing}` : "none";
|
|
33608
33615
|
return /* @__PURE__ */ jsxs89(
|
|
33609
33616
|
"div",
|
|
33610
33617
|
{
|
|
@@ -33649,6 +33656,7 @@ function ReelStage({
|
|
|
33649
33656
|
) : /* @__PURE__ */ jsx117(
|
|
33650
33657
|
"div",
|
|
33651
33658
|
{
|
|
33659
|
+
ref: tapeRef,
|
|
33652
33660
|
"aria-hidden": "true",
|
|
33653
33661
|
style: {
|
|
33654
33662
|
position: "absolute",
|
|
@@ -33864,6 +33872,9 @@ function RandomPlayerPicker({
|
|
|
33864
33872
|
showStats = true,
|
|
33865
33873
|
renderWinner,
|
|
33866
33874
|
spinRef,
|
|
33875
|
+
resetRef,
|
|
33876
|
+
onPoolChange,
|
|
33877
|
+
draftCompleteCaption = "Draft complete \u2014 reset to spin again",
|
|
33867
33878
|
intensity = "normal",
|
|
33868
33879
|
enableHaptics = false,
|
|
33869
33880
|
tickSoundUrl,
|
|
@@ -33878,6 +33889,7 @@ function RandomPlayerPicker({
|
|
|
33878
33889
|
const dark = useDarkMode(darkMode);
|
|
33879
33890
|
const reducedMotion = usePrefersReducedMotion();
|
|
33880
33891
|
const intensityCfg = INTENSITY_CONFIG[intensity];
|
|
33892
|
+
const physicsDriven = intensity === "dramatic" && !reducedMotion;
|
|
33881
33893
|
const [pool, setPool] = useState73(participants);
|
|
33882
33894
|
const [rotation, setRotation] = useState73(0);
|
|
33883
33895
|
const [reelY, setReelY] = useState73(0);
|
|
@@ -33896,6 +33908,11 @@ function RandomPlayerPicker({
|
|
|
33896
33908
|
const winAudioRef = useRef42(null);
|
|
33897
33909
|
const containerRef = useRef42(null);
|
|
33898
33910
|
const prevIdsRef = useRef42("");
|
|
33911
|
+
const wheelSvgRef = useRef42(null);
|
|
33912
|
+
const reelTapeRef = useRef42(null);
|
|
33913
|
+
const rafRef = useRef42(null);
|
|
33914
|
+
const visualRotationRef = useRef42(null);
|
|
33915
|
+
const visualReelYRef = useRef42(null);
|
|
33899
33916
|
useEffect57(() => {
|
|
33900
33917
|
if (typeof window === "undefined" || !tickSoundUrl) {
|
|
33901
33918
|
tickAudioRef.current = null;
|
|
@@ -33949,6 +33966,12 @@ function RandomPlayerPicker({
|
|
|
33949
33966
|
clearTimeout(popTimer.current);
|
|
33950
33967
|
popTimer.current = null;
|
|
33951
33968
|
}
|
|
33969
|
+
if (rafRef.current) {
|
|
33970
|
+
cancelAnimationFrame(rafRef.current);
|
|
33971
|
+
rafRef.current = null;
|
|
33972
|
+
}
|
|
33973
|
+
visualRotationRef.current = null;
|
|
33974
|
+
visualReelYRef.current = null;
|
|
33952
33975
|
pendingPopIdxRef.current = null;
|
|
33953
33976
|
setSpinning(false);
|
|
33954
33977
|
setPool(participants);
|
|
@@ -34060,7 +34083,56 @@ function RandomPlayerPicker({
|
|
|
34060
34083
|
} else {
|
|
34061
34084
|
setRotation(finalRotation);
|
|
34062
34085
|
}
|
|
34063
|
-
|
|
34086
|
+
const fireTick = () => {
|
|
34087
|
+
onTick?.();
|
|
34088
|
+
const ta = tickAudioRef.current;
|
|
34089
|
+
if (ta) {
|
|
34090
|
+
try {
|
|
34091
|
+
ta.currentTime = 0;
|
|
34092
|
+
void ta.play().catch(() => {
|
|
34093
|
+
});
|
|
34094
|
+
} catch {
|
|
34095
|
+
}
|
|
34096
|
+
}
|
|
34097
|
+
};
|
|
34098
|
+
if (physicsDriven) {
|
|
34099
|
+
const from = mode === "reel" ? activeReelY : activeRotation;
|
|
34100
|
+
const to = mode === "reel" ? finalReelY : finalRotation;
|
|
34101
|
+
const crossUnit = mode === "reel" ? reelRowHeight : activeAnglePerWedge * 180 / Math.PI;
|
|
34102
|
+
if (mode === "reel") visualReelYRef.current = from;
|
|
34103
|
+
else visualRotationRef.current = from;
|
|
34104
|
+
let crossings = 0;
|
|
34105
|
+
const t0 = performance.now();
|
|
34106
|
+
const step = (now) => {
|
|
34107
|
+
const t = Math.min(1, (now - t0) / effectiveDuration);
|
|
34108
|
+
const value = from + (to - from) * physicsRampDown(t);
|
|
34109
|
+
if (mode === "reel") {
|
|
34110
|
+
visualReelYRef.current = value;
|
|
34111
|
+
const el = reelTapeRef.current;
|
|
34112
|
+
if (el) {
|
|
34113
|
+
el.style.transform = `translateY(${-(value + REEL_LEAD_IN * reelRowHeight)}px)`;
|
|
34114
|
+
}
|
|
34115
|
+
} else {
|
|
34116
|
+
visualRotationRef.current = value;
|
|
34117
|
+
const el = wheelSvgRef.current;
|
|
34118
|
+
if (el) el.style.transform = `rotate(${value}deg)`;
|
|
34119
|
+
}
|
|
34120
|
+
const crossed = Math.floor(Math.abs(value - from) / crossUnit);
|
|
34121
|
+
if (crossed > crossings) {
|
|
34122
|
+
crossings = crossed;
|
|
34123
|
+
fireTick();
|
|
34124
|
+
}
|
|
34125
|
+
if (t < 1) {
|
|
34126
|
+
rafRef.current = requestAnimationFrame(step);
|
|
34127
|
+
} else {
|
|
34128
|
+
rafRef.current = null;
|
|
34129
|
+
visualRotationRef.current = null;
|
|
34130
|
+
visualReelYRef.current = null;
|
|
34131
|
+
}
|
|
34132
|
+
};
|
|
34133
|
+
rafRef.current = requestAnimationFrame(step);
|
|
34134
|
+
}
|
|
34135
|
+
if (!physicsDriven && (onTick || tickAudioRef.current) && !reducedMotion) {
|
|
34064
34136
|
const wedges = mode === "reel" ? Math.max(1, reelRevRows + targetRowOffset) : (() => {
|
|
34065
34137
|
const totalDelta = deltaMod + revolutions * 360;
|
|
34066
34138
|
const wedgeDeg = activeAnglePerWedge * 180 / Math.PI;
|
|
@@ -34078,16 +34150,7 @@ function RandomPlayerPicker({
|
|
|
34078
34150
|
const eased = 1 - Math.pow(1 - progress, 3);
|
|
34079
34151
|
const interval = startInterval + (endInterval - startInterval) * eased;
|
|
34080
34152
|
tickInterval.current = setTimeout(() => {
|
|
34081
|
-
|
|
34082
|
-
const ta = tickAudioRef.current;
|
|
34083
|
-
if (ta) {
|
|
34084
|
-
try {
|
|
34085
|
-
ta.currentTime = 0;
|
|
34086
|
-
void ta.play().catch(() => {
|
|
34087
|
-
});
|
|
34088
|
-
} catch {
|
|
34089
|
-
}
|
|
34090
|
-
}
|
|
34153
|
+
fireTick();
|
|
34091
34154
|
elapsed += interval;
|
|
34092
34155
|
schedule();
|
|
34093
34156
|
}, interval);
|
|
@@ -34147,7 +34210,7 @@ function RandomPlayerPicker({
|
|
|
34147
34210
|
pendingPopIdxRef.current = null;
|
|
34148
34211
|
if (!removeWinnersRef.current) return;
|
|
34149
34212
|
setPool((p) => p.filter((_, i) => i !== finalWinnerIdx));
|
|
34150
|
-
setWinner(null);
|
|
34213
|
+
if (activePool.length - 1 >= 2) setWinner(null);
|
|
34151
34214
|
setRotation(0);
|
|
34152
34215
|
setReelY(0);
|
|
34153
34216
|
}, 2800);
|
|
@@ -34170,6 +34233,7 @@ function RandomPlayerPicker({
|
|
|
34170
34233
|
maxRevolutions,
|
|
34171
34234
|
history,
|
|
34172
34235
|
reducedMotion,
|
|
34236
|
+
physicsDriven,
|
|
34173
34237
|
enableHaptics,
|
|
34174
34238
|
intensityCfg.particles,
|
|
34175
34239
|
intensityCfg.durationMult,
|
|
@@ -34181,12 +34245,20 @@ function RandomPlayerPicker({
|
|
|
34181
34245
|
if (spinRef && spinRef.current === spin) spinRef.current = null;
|
|
34182
34246
|
};
|
|
34183
34247
|
}, [spin, spinRef]);
|
|
34248
|
+
const onPoolChangeRef = useRef42(onPoolChange);
|
|
34249
|
+
useEffect57(() => {
|
|
34250
|
+
onPoolChangeRef.current = onPoolChange;
|
|
34251
|
+
});
|
|
34252
|
+
useEffect57(() => {
|
|
34253
|
+
onPoolChangeRef.current?.(pool);
|
|
34254
|
+
}, [pool]);
|
|
34184
34255
|
useEffect57(
|
|
34185
34256
|
() => () => {
|
|
34186
34257
|
if (winnerTimer.current) clearTimeout(winnerTimer.current);
|
|
34187
34258
|
if (particleTimer.current) clearTimeout(particleTimer.current);
|
|
34188
34259
|
if (popTimer.current) clearTimeout(popTimer.current);
|
|
34189
34260
|
if (tickInterval.current) clearTimeout(tickInterval.current);
|
|
34261
|
+
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
|
34190
34262
|
},
|
|
34191
34263
|
[]
|
|
34192
34264
|
);
|
|
@@ -34216,6 +34288,12 @@ function RandomPlayerPicker({
|
|
|
34216
34288
|
clearTimeout(popTimer.current);
|
|
34217
34289
|
popTimer.current = null;
|
|
34218
34290
|
}
|
|
34291
|
+
if (rafRef.current) {
|
|
34292
|
+
cancelAnimationFrame(rafRef.current);
|
|
34293
|
+
rafRef.current = null;
|
|
34294
|
+
}
|
|
34295
|
+
visualRotationRef.current = null;
|
|
34296
|
+
visualReelYRef.current = null;
|
|
34219
34297
|
pendingPopIdxRef.current = null;
|
|
34220
34298
|
setSpinning(false);
|
|
34221
34299
|
setPool(participants);
|
|
@@ -34225,9 +34303,17 @@ function RandomPlayerPicker({
|
|
|
34225
34303
|
setReelY(0);
|
|
34226
34304
|
setParticles([]);
|
|
34227
34305
|
}, [participants]);
|
|
34306
|
+
useEffect57(() => {
|
|
34307
|
+
if (resetRef) resetRef.current = reset;
|
|
34308
|
+
return () => {
|
|
34309
|
+
if (resetRef && resetRef.current === reset) resetRef.current = null;
|
|
34310
|
+
};
|
|
34311
|
+
}, [reset, resetRef]);
|
|
34228
34312
|
const isIdle = n < 2;
|
|
34313
|
+
const drainedByDraft = isIdle && participants.length >= 2;
|
|
34314
|
+
const effectiveIdleCaption = drainedByDraft ? draftCompleteCaption : placeholderCaption;
|
|
34229
34315
|
const placeholderDiscColor = dark ? "#2a3344" : "#e2e8f0";
|
|
34230
|
-
if (isIdle && placeholderMode === "message") {
|
|
34316
|
+
if (isIdle && !drainedByDraft && placeholderMode === "message") {
|
|
34231
34317
|
return /* @__PURE__ */ jsx117(
|
|
34232
34318
|
"div",
|
|
34233
34319
|
{
|
|
@@ -34249,6 +34335,8 @@ function RandomPlayerPicker({
|
|
|
34249
34335
|
const shakeKeyframe = `rppShake_${intensity}`;
|
|
34250
34336
|
const glowKeyframe = `rppGlow_${intensity}`;
|
|
34251
34337
|
const pulseKeyframe = `rppPulse_${intensity}`;
|
|
34338
|
+
const displayRotation = visualRotationRef.current ?? rotation;
|
|
34339
|
+
const displayReelY = visualReelYRef.current ?? reelY;
|
|
34252
34340
|
return /* @__PURE__ */ jsxs89(
|
|
34253
34341
|
"div",
|
|
34254
34342
|
{
|
|
@@ -34295,13 +34383,33 @@ function RandomPlayerPicker({
|
|
|
34295
34383
|
[data-rpp-anim] { animation: none !important; }
|
|
34296
34384
|
}
|
|
34297
34385
|
` }),
|
|
34298
|
-
|
|
34386
|
+
isIdle && placeholderMode === "message" ? (
|
|
34387
|
+
/* Drained draft in "message" mode — compact box in the wheel's
|
|
34388
|
+
place; the winner card / stats / controls / history below stay
|
|
34389
|
+
mounted so the endgame isn't a dead end. */
|
|
34390
|
+
/* @__PURE__ */ jsx117(
|
|
34391
|
+
"div",
|
|
34392
|
+
{
|
|
34393
|
+
style: {
|
|
34394
|
+
padding: "2rem 1rem",
|
|
34395
|
+
textAlign: "center",
|
|
34396
|
+
color: c.dim,
|
|
34397
|
+
borderRadius: 12,
|
|
34398
|
+
border: `1px dashed ${c.border}`
|
|
34399
|
+
},
|
|
34400
|
+
children: effectiveIdleCaption
|
|
34401
|
+
}
|
|
34402
|
+
)
|
|
34403
|
+
) : mode === "reel" ? /* @__PURE__ */ jsx117(
|
|
34299
34404
|
ReelStage,
|
|
34300
34405
|
{
|
|
34301
34406
|
pool,
|
|
34302
34407
|
winner,
|
|
34303
34408
|
spinning,
|
|
34304
34409
|
reelY,
|
|
34410
|
+
displayY: displayReelY,
|
|
34411
|
+
cssTransition: !physicsDriven,
|
|
34412
|
+
tapeRef: reelTapeRef,
|
|
34305
34413
|
reelVisibleRows,
|
|
34306
34414
|
reelRowHeight,
|
|
34307
34415
|
size,
|
|
@@ -34310,7 +34418,7 @@ function RandomPlayerPicker({
|
|
|
34310
34418
|
dark,
|
|
34311
34419
|
isIdle,
|
|
34312
34420
|
placeholderMode,
|
|
34313
|
-
placeholderCaption,
|
|
34421
|
+
placeholderCaption: effectiveIdleCaption,
|
|
34314
34422
|
placeholderDiscColor,
|
|
34315
34423
|
spinDuration,
|
|
34316
34424
|
intensityCfg,
|
|
@@ -34367,6 +34475,7 @@ function RandomPlayerPicker({
|
|
|
34367
34475
|
/* @__PURE__ */ jsxs89(
|
|
34368
34476
|
"svg",
|
|
34369
34477
|
{
|
|
34478
|
+
ref: wheelSvgRef,
|
|
34370
34479
|
width: size,
|
|
34371
34480
|
height: size,
|
|
34372
34481
|
"aria-hidden": "true",
|
|
@@ -34375,8 +34484,8 @@ function RandomPlayerPicker({
|
|
|
34375
34484
|
top: 36,
|
|
34376
34485
|
left: 0,
|
|
34377
34486
|
transformOrigin: `${cx}px ${cy}px`,
|
|
34378
|
-
transform: `rotate(${
|
|
34379
|
-
transition: spinning ? `transform ${reducedMotion ? 250 : Math.round(spinDuration * intensityCfg.durationMult)}ms ${intensityCfg.easing}` : "none",
|
|
34487
|
+
transform: `rotate(${displayRotation}deg)`,
|
|
34488
|
+
transition: spinning && !physicsDriven ? `transform ${reducedMotion ? 250 : Math.round(spinDuration * intensityCfg.durationMult)}ms ${intensityCfg.easing}` : "none",
|
|
34380
34489
|
filter: `drop-shadow(0 8px 28px ${dark ? "rgba(0,0,0,0.55)" : "rgba(0,0,0,0.15)"})`
|
|
34381
34490
|
},
|
|
34382
34491
|
children: [
|
|
@@ -34529,7 +34638,7 @@ function RandomPlayerPicker({
|
|
|
34529
34638
|
pointerEvents: "none",
|
|
34530
34639
|
zIndex: 3
|
|
34531
34640
|
},
|
|
34532
|
-
children:
|
|
34641
|
+
children: effectiveIdleCaption
|
|
34533
34642
|
}
|
|
34534
34643
|
),
|
|
34535
34644
|
particles.map((p) => /* @__PURE__ */ jsx117(
|
|
@@ -40246,8 +40355,10 @@ function TeamGenerator({
|
|
|
40246
40355
|
minPlayersPerTeam = 2,
|
|
40247
40356
|
maxPlayers = Number.POSITIVE_INFINITY,
|
|
40248
40357
|
defaultNames = [],
|
|
40358
|
+
defaultTeams,
|
|
40249
40359
|
onNamesChange,
|
|
40250
40360
|
onGenerate,
|
|
40361
|
+
onTeamsChange,
|
|
40251
40362
|
onTeamCountChange,
|
|
40252
40363
|
labels,
|
|
40253
40364
|
ariaLabel = "Team generator",
|
|
@@ -40262,12 +40373,17 @@ function TeamGenerator({
|
|
|
40262
40373
|
const [names, setNames] = useState79(defaultNames);
|
|
40263
40374
|
const [input, setInput] = useState79("");
|
|
40264
40375
|
const [teamCount, setTeamCount] = useState79(initialCount);
|
|
40265
|
-
const [teams, setTeams] = useState79(
|
|
40376
|
+
const [teams, setTeams] = useState79(
|
|
40377
|
+
defaultTeams && defaultTeams.length > 0 ? defaultTeams : null
|
|
40378
|
+
);
|
|
40266
40379
|
const inputRef = useRef48(null);
|
|
40267
40380
|
const minNames = teamCount * minPlayersPerTeam;
|
|
40268
40381
|
useEffect63(() => {
|
|
40269
40382
|
onNamesChange?.(names);
|
|
40270
40383
|
}, [names, onNamesChange]);
|
|
40384
|
+
useEffect63(() => {
|
|
40385
|
+
onTeamsChange?.(teams);
|
|
40386
|
+
}, [teams, onTeamsChange]);
|
|
40271
40387
|
const addName = useCallback53(() => {
|
|
40272
40388
|
const trimmed = input.trim();
|
|
40273
40389
|
if (!trimmed) return;
|