@digilogiclabs/saas-factory-ui 2.8.1 → 2.9.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.js CHANGED
@@ -562,6 +562,7 @@ __export(index_exports, {
562
562
  audioAppTabs: () => audioAppTabs,
563
563
  audioPlayerVariants: () => audioPlayerVariants,
564
564
  breadcrumbsVariants: () => breadcrumbsVariants,
565
+ buildPolyhedron: () => buildPolyhedron,
565
566
  cn: () => cn,
566
567
  commonValidators: () => commonValidators,
567
568
  containerVariants: () => containerVariants2,
@@ -30532,17 +30533,192 @@ function d6LandingRotation(value) {
30532
30533
  y: Math.abs(p.y) === 180 ? 180 : -p.y || 0
30533
30534
  };
30534
30535
  }
30535
- var POLY_SHAPES = {
30536
- 4: { points: "50,8 93,86 7,86", textY: 62, fontScale: 0.3 },
30537
- 8: { points: "50,4 96,50 50,96 4,50", textY: 51, fontScale: 0.33 },
30538
- 10: { points: "50,4 93,44 50,96 7,44", textY: 47, fontScale: 0.3 },
30539
- 12: { points: "50,4 95,37 78,93 22,93 5,37", textY: 54, fontScale: 0.33 },
30540
- 20: {
30541
- points: "50,3 91,26 91,74 50,97 9,74 9,26",
30542
- textY: 51,
30543
- fontScale: 0.33
30536
+ var PHI = (1 + Math.sqrt(5)) / 2;
30537
+ var dot3 = (a, b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
30538
+ var cross3 = (a, b) => [
30539
+ a[1] * b[2] - a[2] * b[1],
30540
+ a[2] * b[0] - a[0] * b[2],
30541
+ a[0] * b[1] - a[1] * b[0]
30542
+ ];
30543
+ var sub3 = (a, b) => [
30544
+ a[0] - b[0],
30545
+ a[1] - b[1],
30546
+ a[2] - b[2]
30547
+ ];
30548
+ var scale3 = (a, s) => [a[0] * s, a[1] * s, a[2] * s];
30549
+ var len3 = (a) => Math.hypot(a[0], a[1], a[2]);
30550
+ var norm3 = (a) => scale3(a, 1 / len3(a));
30551
+ function rotateAround(p, axis, angle) {
30552
+ const cosA = Math.cos(angle);
30553
+ const sinA = Math.sin(angle);
30554
+ const t1 = scale3(p, cosA);
30555
+ const t2 = scale3(cross3(axis, p), sinA);
30556
+ const t3 = scale3(axis, dot3(axis, p) * (1 - cosA));
30557
+ return [t1[0] + t2[0] + t3[0], t1[1] + t2[1] + t3[1], t1[2] + t2[2] + t3[2]];
30558
+ }
30559
+ function rotationTo(from, to) {
30560
+ const c = dot3(from, to);
30561
+ if (c > 1 - 1e-9) return (p) => p;
30562
+ const axis = c < -1 + 1e-9 ? norm3(
30563
+ Math.abs(from[0]) < 0.9 ? cross3(from, [1, 0, 0]) : cross3(from, [0, 1, 0])
30564
+ ) : norm3(cross3(from, to));
30565
+ const angle = Math.acos(Math.max(-1, Math.min(1, c)));
30566
+ return (p) => rotateAround(p, axis, angle);
30567
+ }
30568
+ function solidVertices(sides) {
30569
+ switch (sides) {
30570
+ case 4:
30571
+ return [
30572
+ [1, 1, 1],
30573
+ [1, -1, -1],
30574
+ [-1, 1, -1],
30575
+ [-1, -1, 1]
30576
+ ];
30577
+ case 8:
30578
+ return [
30579
+ [1, 0, 0],
30580
+ [-1, 0, 0],
30581
+ [0, 1, 0],
30582
+ [0, -1, 0],
30583
+ [0, 0, 1],
30584
+ [0, 0, -1]
30585
+ ];
30586
+ case 10: {
30587
+ const h = 0.15;
30588
+ const cos36 = Math.cos(Math.PI / 5);
30589
+ const zApex = 2 * h / (1 - cos36) * cos36 + h;
30590
+ const verts = [
30591
+ [0, 0, zApex],
30592
+ [0, 0, -zApex]
30593
+ ];
30594
+ for (let k = 0; k < 10; k++) {
30595
+ const a = k * Math.PI / 5;
30596
+ verts.push([Math.cos(a), Math.sin(a), k % 2 === 0 ? h : -h]);
30597
+ }
30598
+ return verts;
30599
+ }
30600
+ case 12: {
30601
+ const v = [];
30602
+ for (const sx of [1, -1])
30603
+ for (const sy of [1, -1])
30604
+ for (const sz of [1, -1]) v.push([sx, sy, sz]);
30605
+ const b = 1 / PHI;
30606
+ for (const s1 of [1, -1])
30607
+ for (const s2 of [1, -1]) {
30608
+ v.push([0, s1 * b, s2 * PHI]);
30609
+ v.push([s1 * b, s2 * PHI, 0]);
30610
+ v.push([s2 * PHI, 0, s1 * b]);
30611
+ }
30612
+ return v;
30613
+ }
30614
+ case 20: {
30615
+ const v = [];
30616
+ for (const s1 of [1, -1])
30617
+ for (const s2 of [1, -1]) {
30618
+ v.push([0, s1, s2 * PHI]);
30619
+ v.push([s1, s2 * PHI, 0]);
30620
+ v.push([s2 * PHI, 0, s1]);
30621
+ }
30622
+ return v;
30623
+ }
30544
30624
  }
30545
- };
30625
+ }
30626
+ function computeFaces(verts) {
30627
+ const faces = [];
30628
+ const seen = /* @__PURE__ */ new Set();
30629
+ for (let i = 0; i < verts.length; i++)
30630
+ for (let j = i + 1; j < verts.length; j++)
30631
+ for (let k = j + 1; k < verts.length; k++) {
30632
+ let n = cross3(sub3(verts[j], verts[i]), sub3(verts[k], verts[i]));
30633
+ if (len3(n) < 1e-9) continue;
30634
+ n = norm3(n);
30635
+ let d = dot3(n, verts[i]);
30636
+ if (d < 0) {
30637
+ n = scale3(n, -1);
30638
+ d = -d;
30639
+ }
30640
+ if (verts.some((p) => dot3(n, p) > d + 1e-4)) continue;
30641
+ const ids = verts.flatMap(
30642
+ (p, idx) => Math.abs(dot3(n, p) - d) < 1e-4 ? [idx] : []
30643
+ );
30644
+ const key = ids.join(",");
30645
+ if (seen.has(key)) continue;
30646
+ seen.add(key);
30647
+ faces.push({ normal: n, ids });
30648
+ }
30649
+ return faces;
30650
+ }
30651
+ var polyhedronCache = /* @__PURE__ */ new Map();
30652
+ function buildPolyhedron(sides) {
30653
+ const cached = polyhedronCache.get(sides);
30654
+ if (cached) return cached;
30655
+ let verts = solidVertices(sides);
30656
+ const rough = computeFaces(verts);
30657
+ const front = rough.reduce(
30658
+ (best, f) => f.normal[2] > best.normal[2] + 1e-9 ? f : best
30659
+ );
30660
+ const rot = rotationTo(front.normal, [0, 0, 1]);
30661
+ verts = verts.map(rot);
30662
+ const rMax = Math.max(...verts.map(len3));
30663
+ verts = verts.map((p) => scale3(p, 1 / rMax));
30664
+ const raw = computeFaces(verts);
30665
+ const built = raw.map((f) => {
30666
+ const faceVerts = f.ids.map((i) => verts[i]);
30667
+ const centroid = scale3(
30668
+ faceVerts.reduce((a, b) => [a[0] + b[0], a[1] + b[1], a[2] + b[2]]),
30669
+ 1 / faceVerts.length
30670
+ );
30671
+ const w = f.normal;
30672
+ let vRaw = sub3([0, 1, 0], scale3(w, w[1]));
30673
+ if (len3(vRaw) < 1e-6) vRaw = sub3([0, 0, 1], scale3(w, w[2]));
30674
+ const v = norm3(vRaw);
30675
+ const u = cross3(v, w);
30676
+ const pts = faceVerts.map((p) => [
30677
+ dot3(sub3(p, centroid), u),
30678
+ dot3(sub3(p, centroid), v)
30679
+ ]).sort((a, b) => Math.atan2(a[1], a[0]) - Math.atan2(b[1], b[0]));
30680
+ return { normal: w, centroid, u, v, pts, value: 0 };
30681
+ });
30682
+ built.sort((a, b) => b.normal[2] - a.normal[2]);
30683
+ const oppOf = (i) => built.findIndex((g) => dot3(built[i].normal, g.normal) < -0.9999);
30684
+ const pool = [];
30685
+ for (let v2 = 1; v2 < sides; v2++) pool.push(v2);
30686
+ built[0].value = sides;
30687
+ const opp0 = oppOf(0);
30688
+ if (opp0 >= 0) {
30689
+ built[opp0].value = 1;
30690
+ pool.splice(pool.indexOf(1), 1);
30691
+ }
30692
+ for (let i = 1; i < built.length; i++) {
30693
+ if (built[i].value !== 0) continue;
30694
+ const v2 = pool.shift();
30695
+ built[i].value = v2;
30696
+ const j = oppOf(i);
30697
+ if (j >= 0 && built[j].value === 0) {
30698
+ built[j].value = sides + 1 - v2;
30699
+ pool.splice(pool.indexOf(sides + 1 - v2), 1);
30700
+ }
30701
+ }
30702
+ const faceRadius = Math.max(
30703
+ ...built.flatMap((f) => f.pts.map(([x, y]) => Math.hypot(x, y)))
30704
+ );
30705
+ const edgeDist = (pts) => Math.min(
30706
+ ...pts.map((p1, i2) => {
30707
+ const p2 = pts[(i2 + 1) % pts.length];
30708
+ const dx = p2[0] - p1[0];
30709
+ const dy = p2[1] - p1[1];
30710
+ const t = Math.max(
30711
+ 0,
30712
+ Math.min(1, -(p1[0] * dx + p1[1] * dy) / (dx * dx + dy * dy))
30713
+ );
30714
+ return Math.hypot(p1[0] + t * dx, p1[1] + t * dy);
30715
+ })
30716
+ );
30717
+ const faceInradius = Math.min(...built.map((f) => edgeDist(f.pts)));
30718
+ const result = { faces: built, faceRadius, faceInradius };
30719
+ polyhedronCache.set(sides, result);
30720
+ return result;
30721
+ }
30546
30722
  function formatDieValue(v, sides) {
30547
30723
  return sides > 8 && (v === 6 || v === 9) ? `${v}.` : String(v);
30548
30724
  }
@@ -30767,6 +30943,7 @@ function DiceRoller({
30767
30943
  }
30768
30944
  return numeralSetters.current[i];
30769
30945
  };
30946
+ const sheenGradientId = (0, import_react68.useId)();
30770
30947
  const timersRef = (0, import_react68.useRef)([]);
30771
30948
  const rafHandleRef = (0, import_react68.useRef)(null);
30772
30949
  const arenaRef = (0, import_react68.useRef)(null);
@@ -31152,57 +31329,97 @@ function DiceRoller({
31152
31329
  },
31153
31330
  val
31154
31331
  )) : (() => {
31155
- const shape = POLY_SHAPES[sides];
31332
+ const geo = buildPolyhedron(sides);
31333
+ const R = effectiveSize / 2;
31334
+ const S = Math.ceil(geo.faceRadius * R * 2) + 6;
31335
+ const fontSize = geo.faceInradius * R * 1.15;
31156
31336
  const shown = results?.[d] ?? sides;
31157
- const cardFaceStyle = {
31158
- position: "absolute",
31159
- inset: 0,
31160
- display: "block",
31161
- overflow: "visible",
31162
- backfaceVisibility: "hidden"
31163
- };
31164
- return /* @__PURE__ */ (0, import_jsx_runtime114.jsxs)(import_jsx_runtime114.Fragment, { children: [
31165
- /* @__PURE__ */ (0, import_jsx_runtime114.jsxs)(
31337
+ return /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(import_jsx_runtime114.Fragment, { children: geo.faces.map((f, fi) => {
31338
+ const m = `matrix3d(${f.u[0]},${f.u[1]},${f.u[2]},0,${f.v[0]},${f.v[1]},${f.v[2]},0,${f.normal[0]},${f.normal[1]},${f.normal[2]},0,${f.centroid[0] * R},${f.centroid[1] * R},${f.centroid[2] * R},1)`;
31339
+ const gid = `${sheenGradientId}-${d}-${fi}`;
31340
+ const pts = f.pts.map(
31341
+ ([x, y]) => `${(x * R + S / 2).toFixed(2)},${(y * R + S / 2).toFixed(2)}`
31342
+ ).join(" ");
31343
+ return /* @__PURE__ */ (0, import_jsx_runtime114.jsxs)(
31166
31344
  "svg",
31167
31345
  {
31168
- viewBox: "0 0 100 100",
31169
- width: "100%",
31170
- height: "100%",
31171
- style: cardFaceStyle,
31346
+ width: S,
31347
+ height: S,
31348
+ viewBox: `0 0 ${S} ${S}`,
31349
+ style: {
31350
+ position: "absolute",
31351
+ left: "50%",
31352
+ top: "50%",
31353
+ marginLeft: -S / 2,
31354
+ marginTop: -S / 2,
31355
+ overflow: "visible",
31356
+ transform: m,
31357
+ // Convex solid: a face is either front-
31358
+ // facing or hidden behind nearer faces,
31359
+ // so hiding backfaces is both correct
31360
+ // and the mirrored-numeral guard.
31361
+ backfaceVisibility: "hidden"
31362
+ },
31172
31363
  "aria-hidden": "true",
31173
31364
  children: [
31174
- /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
31175
- "polygon",
31365
+ /* @__PURE__ */ (0, import_jsx_runtime114.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime114.jsxs)(
31366
+ "radialGradient",
31176
31367
  {
31177
- points: shape.points,
31178
- fill: colors.face,
31179
- stroke: colors.faceBorder,
31180
- strokeWidth: 2.5,
31181
- strokeLinejoin: "round",
31182
- style: { transition: "fill 0.3s, stroke 0.3s" }
31368
+ id: gid,
31369
+ cx: "32%",
31370
+ cy: "26%",
31371
+ r: "80%",
31372
+ children: [
31373
+ /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
31374
+ "stop",
31375
+ {
31376
+ offset: "0%",
31377
+ stopColor: "#fff",
31378
+ stopOpacity: "0.38"
31379
+ }
31380
+ ),
31381
+ /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
31382
+ "stop",
31383
+ {
31384
+ offset: "55%",
31385
+ stopColor: "#fff",
31386
+ stopOpacity: "0.08"
31387
+ }
31388
+ ),
31389
+ /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
31390
+ "stop",
31391
+ {
31392
+ offset: "100%",
31393
+ stopColor: "#fff",
31394
+ stopOpacity: "0"
31395
+ }
31396
+ )
31397
+ ]
31183
31398
  }
31184
- ),
31399
+ ) }),
31185
31400
  /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
31186
31401
  "polygon",
31187
31402
  {
31188
- points: shape.points,
31189
- fill: "none",
31403
+ points: pts,
31404
+ fill: colors.face,
31190
31405
  stroke: colors.faceBorder,
31191
31406
  strokeWidth: 1.5,
31192
31407
  strokeLinejoin: "round",
31193
- opacity: 0.55,
31194
- transform: "translate(50 50) scale(0.76) translate(-50 -50)"
31408
+ style: {
31409
+ transition: "fill 0.3s, stroke 0.3s"
31410
+ }
31195
31411
  }
31196
31412
  ),
31413
+ /* @__PURE__ */ (0, import_jsx_runtime114.jsx)("polygon", { points: pts, fill: `url(#${gid})` }),
31197
31414
  /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
31198
31415
  "text",
31199
31416
  {
31200
- ref: getNumeralSetter(d),
31201
- x: 50,
31202
- y: shape.textY,
31417
+ ref: fi === 0 ? getNumeralSetter(d) : void 0,
31418
+ x: S / 2,
31419
+ y: S / 2,
31203
31420
  textAnchor: "middle",
31204
31421
  dominantBaseline: "central",
31205
- fontSize: 100 * shape.fontScale,
31422
+ fontSize,
31206
31423
  fontWeight: 800,
31207
31424
  fill: colors.pip,
31208
31425
  style: {
@@ -31210,59 +31427,17 @@ function DiceRoller({
31210
31427
  transition: "fill 0.3s",
31211
31428
  userSelect: "none"
31212
31429
  },
31213
- children: formatDieValue(shown, sides)
31430
+ children: formatDieValue(
31431
+ fi === 0 ? shown : f.value,
31432
+ sides
31433
+ )
31214
31434
  }
31215
31435
  )
31216
31436
  ]
31217
- }
31218
- ),
31219
- /* @__PURE__ */ (0, import_jsx_runtime114.jsxs)(
31220
- "svg",
31221
- {
31222
- viewBox: "0 0 100 100",
31223
- width: "100%",
31224
- height: "100%",
31225
- style: {
31226
- ...cardFaceStyle,
31227
- transform: "rotateY(180deg)"
31228
- },
31229
- "aria-hidden": "true",
31230
- children: [
31231
- /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
31232
- "polygon",
31233
- {
31234
- points: shape.points,
31235
- fill: colors.face,
31236
- stroke: colors.faceBorder,
31237
- strokeWidth: 2.5,
31238
- strokeLinejoin: "round",
31239
- style: { transition: "fill 0.3s, stroke 0.3s" }
31240
- }
31241
- ),
31242
- /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
31243
- "polygon",
31244
- {
31245
- points: shape.points,
31246
- fill: "none",
31247
- stroke: colors.faceBorder,
31248
- strokeWidth: 1.5,
31249
- strokeLinejoin: "round",
31250
- opacity: 0.55,
31251
- transform: "translate(50 50) scale(0.76) translate(-50 -50)"
31252
- }
31253
- ),
31254
- /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
31255
- "polygon",
31256
- {
31257
- points: shape.points,
31258
- fill: "#000",
31259
- opacity: 0.14
31260
- }
31261
- )
31262
- ]
31263
- }
31264
- )
31265
- ] });
31437
+ },
31438
+ fi
31439
+ );
31440
+ }) });
31266
31441
  })()
31267
31442
  }
31268
31443
  )