@digilogiclabs/saas-factory-ui 1.16.1 → 1.16.3

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.js CHANGED
@@ -30304,44 +30304,53 @@ function simulateDice(arenaW, arenaH, diceSize, starts, numDice) {
30304
30304
  const collisionDist = diceSize * 1.05;
30305
30305
  const bodies = [];
30306
30306
  for (let i = 0; i < numDice; i++) {
30307
- const s = starts[i] ?? { x: arenaW / 2, y: arenaH / 2 };
30307
+ const s = starts[i] ?? { x: arenaW / 2, y: minY };
30308
30308
  bodies.push({
30309
- x: clamp(s.x + (Math.random() - 0.5) * arenaW * 0.25, minX, maxX),
30310
- y: clamp(s.y + (Math.random() - 0.5) * arenaH * 0.25, minY, maxY),
30311
- // Minimum baseline velocity so small arenas still bounce visibly
30312
- // instead of drifting a few pixels. The `|| 1` guard makes sure
30313
- // we never get a near-zero initial velocity from `random - 0.5`.
30314
- vx: (Math.sign(Math.random() - 0.5) || 1) * (0.5 + Math.random() * 0.5) * arenaW * 1.4,
30315
- vy: (Math.sign(Math.random() - 0.5) || 1) * (0.5 + Math.random() * 0.5) * arenaH * 1.6
30309
+ x: clamp(s.x + (Math.random() - 0.5) * arenaW * 0.2, minX, maxX),
30310
+ y: clamp(minY + Math.random() * 8, minY, maxY),
30311
+ vx: (Math.sign(Math.random() - 0.5) || 1) * (0.35 + Math.random() * 0.55) * arenaW * 1.2,
30312
+ // Always downward initially this is the "drop" feel.
30313
+ vy: (0.25 + Math.random() * 0.4) * arenaH * 2.2
30316
30314
  });
30317
30315
  }
30318
- const steps = 32;
30319
- const dt = 2 / steps;
30320
- const friction = 0.9;
30316
+ const steps = 40;
30317
+ const dt = 2.4 / steps;
30318
+ const friction = 0.93;
30321
30319
  const wallRestitution = -0.72;
30322
30320
  const diceRestitution = 0.8;
30321
+ const gravity = arenaH * 0.9;
30323
30322
  const frames = [];
30323
+ const bounceScaleX = new Array(numDice).fill(1);
30324
+ const bounceScaleY = new Array(numDice).fill(1);
30324
30325
  for (let s = 0; s < steps; s++) {
30325
30326
  for (const b of bodies) {
30327
+ b.vy += gravity * dt;
30326
30328
  b.x += b.vx * dt;
30327
30329
  b.y += b.vy * dt;
30328
30330
  }
30329
- for (const b of bodies) {
30331
+ for (let i = 0; i < numDice; i++) {
30332
+ const b = bodies[i];
30330
30333
  if (b.x <= minX) {
30331
30334
  b.x = minX;
30332
30335
  b.vx *= wallRestitution;
30333
- }
30334
- if (b.x >= maxX) {
30336
+ bounceScaleX[i] = 0.78;
30337
+ bounceScaleY[i] = 1.14;
30338
+ } else if (b.x >= maxX) {
30335
30339
  b.x = maxX;
30336
30340
  b.vx *= wallRestitution;
30341
+ bounceScaleX[i] = 0.78;
30342
+ bounceScaleY[i] = 1.14;
30337
30343
  }
30338
30344
  if (b.y <= minY) {
30339
30345
  b.y = minY;
30340
30346
  b.vy *= wallRestitution;
30341
- }
30342
- if (b.y >= maxY) {
30347
+ bounceScaleY[i] = 0.78;
30348
+ bounceScaleX[i] = 1.14;
30349
+ } else if (b.y >= maxY) {
30343
30350
  b.y = maxY;
30344
30351
  b.vy *= wallRestitution;
30352
+ bounceScaleY[i] = 0.78;
30353
+ bounceScaleX[i] = 1.14;
30345
30354
  }
30346
30355
  }
30347
30356
  for (let i = 0; i < numDice; i++) {
@@ -30367,6 +30376,10 @@ function simulateDice(arenaW, arenaH, diceSize, starts, numDice) {
30367
30376
  a.vy += impulse * ny;
30368
30377
  b.vx -= impulse * nx;
30369
30378
  b.vy -= impulse * ny;
30379
+ bounceScaleX[i] = 0.88;
30380
+ bounceScaleY[i] = 1.08;
30381
+ bounceScaleX[j] = 0.88;
30382
+ bounceScaleY[j] = 1.08;
30370
30383
  }
30371
30384
  }
30372
30385
  }
@@ -30379,7 +30392,18 @@ function simulateDice(arenaW, arenaH, diceSize, starts, numDice) {
30379
30392
  b.x = clamp(b.x, minX, maxX);
30380
30393
  b.y = clamp(b.y, minY, maxY);
30381
30394
  }
30382
- frames.push(bodies.map((b) => ({ x: b.x, y: b.y })));
30395
+ for (let i = 0; i < numDice; i++) {
30396
+ bounceScaleX[i] += (1 - bounceScaleX[i]) * 0.35;
30397
+ bounceScaleY[i] += (1 - bounceScaleY[i]) * 0.35;
30398
+ }
30399
+ frames.push(
30400
+ bodies.map((b, i) => ({
30401
+ x: b.x,
30402
+ y: b.y,
30403
+ sx: bounceScaleX[i],
30404
+ sy: bounceScaleY[i]
30405
+ }))
30406
+ );
30383
30407
  }
30384
30408
  return frames;
30385
30409
  }
@@ -30500,10 +30524,38 @@ function DiceRoller({
30500
30524
  const [rolling, setRolling] = (0, import_react66.useState)(false);
30501
30525
  const [results, setResults] = (0, import_react66.useState)(null);
30502
30526
  const [history, setHistory] = (0, import_react66.useState)([]);
30503
- const [rotations, setRotations] = (0, import_react66.useState)(
30504
- () => Array.from({ length: MAX_COUNT }, () => ({ x: 0, y: 0, z: 0, tr: true }))
30505
- );
30506
- const [positions, setPositions] = (0, import_react66.useState)(null);
30527
+ const dieWrapperRefs = (0, import_react66.useRef)([]);
30528
+ const cubeRefs = (0, import_react66.useRef)([]);
30529
+ const shadowRefs = (0, import_react66.useRef)([]);
30530
+ const currentPositionsRef = (0, import_react66.useRef)(null);
30531
+ const rollingRef = (0, import_react66.useRef)(false);
30532
+ const dieSetters = (0, import_react66.useRef)([]);
30533
+ const cubeSetters = (0, import_react66.useRef)([]);
30534
+ const shadowSetters = (0, import_react66.useRef)([]);
30535
+ const getDieSetter = (i) => {
30536
+ if (!dieSetters.current[i]) {
30537
+ dieSetters.current[i] = (el) => {
30538
+ dieWrapperRefs.current[i] = el;
30539
+ };
30540
+ }
30541
+ return dieSetters.current[i];
30542
+ };
30543
+ const getCubeSetter = (i) => {
30544
+ if (!cubeSetters.current[i]) {
30545
+ cubeSetters.current[i] = (el) => {
30546
+ cubeRefs.current[i] = el;
30547
+ };
30548
+ }
30549
+ return cubeSetters.current[i];
30550
+ };
30551
+ const getShadowSetter = (i) => {
30552
+ if (!shadowSetters.current[i]) {
30553
+ shadowSetters.current[i] = (el) => {
30554
+ shadowRefs.current[i] = el;
30555
+ };
30556
+ }
30557
+ return shadowSetters.current[i];
30558
+ };
30507
30559
  const timersRef = (0, import_react66.useRef)([]);
30508
30560
  const rafHandleRef = (0, import_react66.useRef)(null);
30509
30561
  const arenaRef = (0, import_react66.useRef)(null);
@@ -30574,15 +30626,54 @@ function DiceRoller({
30574
30626
  })),
30575
30627
  []
30576
30628
  );
30629
+ const writeDiePosition = (0, import_react66.useCallback)(
30630
+ (i, x, y, sx = 1, sy = 1) => {
30631
+ const el = dieWrapperRefs.current[i];
30632
+ if (!el) return;
30633
+ el.style.transform = `translate3d(${x - half}px, ${y - half}px, 0) scale3d(${sx}, ${sy}, 1)`;
30634
+ },
30635
+ [half]
30636
+ );
30637
+ const writeCubeRotation = (0, import_react66.useCallback)(
30638
+ (i, rx, ry, rz, withTransition) => {
30639
+ const el = cubeRefs.current[i];
30640
+ if (!el) return;
30641
+ el.style.transition = withTransition ? "transform 0.95s cubic-bezier(0.12,0.8,0.22,1)" : "none";
30642
+ el.style.transform = `rotateX(${rx}deg) rotateY(${ry}deg) rotateZ(${rz}deg)`;
30643
+ },
30644
+ []
30645
+ );
30577
30646
  (0, import_react66.useEffect)(() => {
30647
+ const w = arenaRef.current?.offsetWidth ?? arena.w;
30648
+ const h = arenaRef.current?.offsetHeight ?? arenaHeight;
30649
+ if (w === 0 || h === 0) return;
30650
+ const initial = defaultPositions(w, h, clampedCount);
30651
+ currentPositionsRef.current = initial;
30652
+ for (let i = 0; i < clampedCount; i++) {
30653
+ const pos = initial[i];
30654
+ const el = dieWrapperRefs.current[i];
30655
+ if (el) {
30656
+ el.style.transition = "transform 0.35s cubic-bezier(0.25,0.46,0.45,0.94)";
30657
+ el.style.transform = `translate3d(${pos.x - half}px, ${pos.y - half}px, 0) scale3d(1, 1, 1)`;
30658
+ }
30659
+ const cube = cubeRefs.current[i];
30660
+ if (cube) {
30661
+ cube.style.transition = "none";
30662
+ cube.style.transform = "rotateX(0deg) rotateY(0deg) rotateZ(0deg)";
30663
+ }
30664
+ }
30578
30665
  setResults(null);
30579
- setPositions(null);
30580
- setRotations(
30581
- Array.from({ length: MAX_COUNT }, () => ({ x: 0, y: 0, z: 0, tr: true }))
30582
- );
30583
- }, [clampedCount, effectiveSize]);
30666
+ }, [
30667
+ clampedCount,
30668
+ effectiveSize,
30669
+ arena.w,
30670
+ arenaHeight,
30671
+ defaultPositions,
30672
+ half
30673
+ ]);
30584
30674
  const roll = (0, import_react66.useCallback)(() => {
30585
- if (rolling) return;
30675
+ if (rollingRef.current) return;
30676
+ rollingRef.current = true;
30586
30677
  setRolling(true);
30587
30678
  const vals = Array.from(
30588
30679
  { length: clampedCount },
@@ -30590,21 +30681,29 @@ function DiceRoller({
30590
30681
  );
30591
30682
  timersRef.current.forEach((t) => clearTimeout(t));
30592
30683
  timersRef.current = [];
30684
+ if (rafHandleRef.current != null) {
30685
+ cancelAnimationFrame(rafHandleRef.current);
30686
+ rafHandleRef.current = null;
30687
+ }
30593
30688
  const w = arenaRef.current?.offsetWidth ?? 400;
30594
30689
  const h = arenaRef.current?.offsetHeight ?? 260;
30595
- const starts = positions ?? defaultPositions(w, h, clampedCount);
30690
+ const starts = currentPositionsRef.current ?? defaultPositions(w, h, clampedCount);
30596
30691
  if (reducedMotion) {
30597
- setPositions(defaultPositions(w, h, clampedCount));
30598
- setRotations((prev) => {
30599
- const n = [...prev];
30600
- for (let i = 0; i < clampedCount; i++) {
30601
- const tgt = SHOW_ROT[vals[i]];
30602
- n[i] = { x: tgt.x, y: tgt.y, z: 0, tr: false };
30692
+ const final = defaultPositions(w, h, clampedCount);
30693
+ currentPositionsRef.current = final;
30694
+ for (let i = 0; i < clampedCount; i++) {
30695
+ const p = final[i];
30696
+ const el = dieWrapperRefs.current[i];
30697
+ if (el) {
30698
+ el.style.transition = "transform 0.2s ease-out";
30699
+ el.style.transform = `translate3d(${p.x - half}px, ${p.y - half}px, 0) scale3d(1, 1, 1)`;
30603
30700
  }
30604
- return n;
30605
- });
30701
+ const tgt = SHOW_ROT[vals[i]];
30702
+ writeCubeRotation(i, tgt.x, tgt.y, 0, true);
30703
+ }
30606
30704
  setResults(vals);
30607
30705
  setRolling(false);
30706
+ rollingRef.current = false;
30608
30707
  const total2 = vals.reduce((a, b) => a + b, 0);
30609
30708
  onRoll?.(vals, total2);
30610
30709
  if (showHistory) {
@@ -30613,24 +30712,24 @@ function DiceRoller({
30613
30712
  return;
30614
30713
  }
30615
30714
  const frames = simulateDice(w, h, effectiveSize, starts, clampedCount);
30616
- setRotations((prev) => {
30617
- const n = [...prev];
30618
- for (let i = 0; i < clampedCount; i++) {
30619
- n[i] = {
30620
- x: (Math.random() - 0.5) * 720,
30621
- y: (Math.random() - 0.5) * 720,
30622
- z: (Math.random() - 0.5) * 720,
30623
- tr: false
30624
- };
30625
- }
30626
- return n;
30627
- });
30715
+ for (let i = 0; i < clampedCount; i++) {
30716
+ writeCubeRotation(
30717
+ i,
30718
+ (Math.random() - 0.5) * 720,
30719
+ (Math.random() - 0.5) * 720,
30720
+ (Math.random() - 0.5) * 720,
30721
+ false
30722
+ );
30723
+ const el = dieWrapperRefs.current[i];
30724
+ if (el) el.style.transition = "none";
30725
+ const shadow = shadowRefs.current[i];
30726
+ if (shadow) shadow.style.opacity = "0.2";
30727
+ }
30728
+ if (dieWrapperRefs.current[0]) {
30729
+ dieWrapperRefs.current[0].offsetHeight;
30730
+ }
30628
30731
  const playbackMs = TUMBLE_MS;
30629
30732
  const startTime = typeof performance !== "undefined" ? performance.now() : Date.now();
30630
- if (rafHandleRef.current != null) {
30631
- cancelAnimationFrame(rafHandleRef.current);
30632
- rafHandleRef.current = null;
30633
- }
30634
30733
  const tick = (now) => {
30635
30734
  const elapsed = now - startTime;
30636
30735
  const progress = Math.max(0, Math.min(1, elapsed / playbackMs));
@@ -30638,34 +30737,46 @@ function DiceRoller({
30638
30737
  frames.length - 1,
30639
30738
  Math.floor(progress * frames.length)
30640
30739
  );
30641
- setPositions(frames[idx].slice(0, clampedCount));
30740
+ const frame = frames[idx];
30741
+ if (frame) {
30742
+ for (let i = 0; i < clampedCount; i++) {
30743
+ const p = frame[i];
30744
+ if (p) writeDiePosition(i, p.x, p.y, p.sx, p.sy);
30745
+ }
30746
+ currentPositionsRef.current = frame.slice(0, clampedCount).map((f) => ({
30747
+ x: f.x,
30748
+ y: f.y
30749
+ }));
30750
+ }
30642
30751
  if (progress < 1) {
30643
30752
  rafHandleRef.current = requestAnimationFrame(tick);
30644
30753
  } else {
30645
30754
  rafHandleRef.current = null;
30755
+ for (let i = 0; i < clampedCount; i++) {
30756
+ const el = dieWrapperRefs.current[i];
30757
+ if (el)
30758
+ el.style.transition = "transform 0.35s cubic-bezier(0.25,0.46,0.45,0.94)";
30759
+ const shadow = shadowRefs.current[i];
30760
+ if (shadow) shadow.style.opacity = "0.85";
30761
+ }
30646
30762
  }
30647
30763
  };
30648
30764
  rafHandleRef.current = requestAnimationFrame(tick);
30649
30765
  requestAnimationFrame(() => {
30650
30766
  requestAnimationFrame(() => {
30651
- setRotations((prev) => {
30652
- const n = [...prev];
30653
- for (let i = 0; i < clampedCount; i++) {
30654
- const tgt = SHOW_ROT[vals[i]];
30655
- n[i] = {
30656
- x: tgt.x + (Math.random() > 0.5 ? 720 : -720),
30657
- y: tgt.y,
30658
- z: (Math.random() > 0.5 ? 1 : -1) * 360,
30659
- tr: true
30660
- };
30661
- }
30662
- return n;
30663
- });
30767
+ for (let i = 0; i < clampedCount; i++) {
30768
+ const tgt = SHOW_ROT[vals[i]];
30769
+ const lx = tgt.x + (Math.random() > 0.5 ? 720 : -720);
30770
+ const ly = tgt.y;
30771
+ const lz = (Math.random() > 0.5 ? 1 : -1) * 360;
30772
+ writeCubeRotation(i, lx, ly, lz, true);
30773
+ }
30664
30774
  });
30665
30775
  });
30666
30776
  const settleTimer = setTimeout(() => {
30667
30777
  setResults(vals);
30668
30778
  setRolling(false);
30779
+ rollingRef.current = false;
30669
30780
  const total2 = vals.reduce((a, b) => a + b, 0);
30670
30781
  onRoll?.(vals, total2);
30671
30782
  if (showHistory) {
@@ -30674,13 +30785,14 @@ function DiceRoller({
30674
30785
  }, SETTLE_MS);
30675
30786
  timersRef.current.push(settleTimer);
30676
30787
  }, [
30677
- rolling,
30678
30788
  clampedCount,
30679
- positions,
30680
30789
  defaultPositions,
30681
30790
  effectiveSize,
30791
+ half,
30682
30792
  reducedMotion,
30683
30793
  onRoll,
30794
+ writeCubeRotation,
30795
+ writeDiePosition,
30684
30796
  showHistory,
30685
30797
  historyMax
30686
30798
  ]);
@@ -30706,7 +30818,6 @@ function DiceRoller({
30706
30818
  },
30707
30819
  []
30708
30820
  );
30709
- const activePositions = positions ?? defaultPositions(arena.w, arenaHeight, clampedCount);
30710
30821
  const total = results ? results.reduce((a, b) => a + b, 0) : null;
30711
30822
  return /* @__PURE__ */ (0, import_jsx_runtime114.jsxs)(
30712
30823
  "div",
@@ -30734,27 +30845,20 @@ function DiceRoller({
30734
30845
  cursor: trigger === "click" ? "pointer" : void 0
30735
30846
  },
30736
30847
  children: Array.from({ length: clampedCount }, (_, d) => {
30737
- const rot = rotations[d] ?? { x: 0, y: 0, z: 0, tr: true };
30738
- const pos = activePositions[d] ?? {
30739
- x: arena.w / 2,
30740
- y: arenaHeight / 2
30741
- };
30742
- const translate = `translate3d(${pos.x - half}px, ${pos.y - half}px, 0)`;
30743
30848
  return /* @__PURE__ */ (0, import_jsx_runtime114.jsxs)(
30744
30849
  "div",
30745
30850
  {
30851
+ ref: getDieSetter(d),
30746
30852
  style: {
30747
30853
  position: "absolute",
30748
30854
  left: 0,
30749
30855
  top: 0,
30750
30856
  width: effectiveSize,
30751
30857
  height: effectiveSize,
30752
- transform: translate,
30753
30858
  // Parent must preserve 3D so the inner cube's rotateX/Y/Z
30754
30859
  // still renders with depth — otherwise adding a transform
30755
30860
  // to the wrapper would flatten its children into 2D.
30756
30861
  transformStyle: "preserve-3d",
30757
- transition: rolling ? "transform 0.04s linear" : "transform 0.35s cubic-bezier(0.25,0.46,0.45,0.94)",
30758
30862
  willChange: "transform",
30759
30863
  zIndex: 2,
30760
30864
  perspective: 700
@@ -30763,6 +30867,7 @@ function DiceRoller({
30763
30867
  /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
30764
30868
  "div",
30765
30869
  {
30870
+ ref: getShadowSetter(d),
30766
30871
  style: {
30767
30872
  position: "absolute",
30768
30873
  bottom: -6,
@@ -30772,7 +30877,7 @@ function DiceRoller({
30772
30877
  background: `radial-gradient(ellipse,${colors.shadow} 0%,transparent 70%)`,
30773
30878
  borderRadius: "50%",
30774
30879
  pointerEvents: "none",
30775
- opacity: rolling ? 0.2 : 0.85,
30880
+ opacity: 0.85,
30776
30881
  transition: "opacity 0.3s"
30777
30882
  }
30778
30883
  }
@@ -30780,13 +30885,12 @@ function DiceRoller({
30780
30885
  /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
30781
30886
  "div",
30782
30887
  {
30888
+ ref: getCubeSetter(d),
30783
30889
  style: {
30784
30890
  width: "100%",
30785
30891
  height: "100%",
30786
30892
  position: "relative",
30787
30893
  transformStyle: "preserve-3d",
30788
- transition: rot.tr ? "transform 0.95s cubic-bezier(0.12,0.8,0.22,1)" : "none",
30789
- transform: `rotateX(${rot.x}deg) rotateY(${rot.y}deg) rotateZ(${rot.z}deg)`,
30790
30894
  willChange: "transform"
30791
30895
  },
30792
30896
  children: [1, 2, 3, 4, 5, 6].map((val, fi) => /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(