@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/web/index.js CHANGED
@@ -497,6 +497,7 @@ __export(index_exports, {
497
497
  audioAppTabs: () => audioAppTabs,
498
498
  audioPlayerVariants: () => audioPlayerVariants,
499
499
  breadcrumbsVariants: () => breadcrumbsVariants,
500
+ buildPolyhedron: () => buildPolyhedron,
500
501
  cn: () => cn,
501
502
  commonValidators: () => commonValidators,
502
503
  containerVariants: () => containerVariants2,
@@ -30361,17 +30362,192 @@ function d6LandingRotation(value) {
30361
30362
  y: Math.abs(p.y) === 180 ? 180 : -p.y || 0
30362
30363
  };
30363
30364
  }
30364
- var POLY_SHAPES = {
30365
- 4: { points: "50,8 93,86 7,86", textY: 62, fontScale: 0.3 },
30366
- 8: { points: "50,4 96,50 50,96 4,50", textY: 51, fontScale: 0.33 },
30367
- 10: { points: "50,4 93,44 50,96 7,44", textY: 47, fontScale: 0.3 },
30368
- 12: { points: "50,4 95,37 78,93 22,93 5,37", textY: 54, fontScale: 0.33 },
30369
- 20: {
30370
- points: "50,3 91,26 91,74 50,97 9,74 9,26",
30371
- textY: 51,
30372
- fontScale: 0.33
30365
+ var PHI = (1 + Math.sqrt(5)) / 2;
30366
+ var dot3 = (a, b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
30367
+ var cross3 = (a, b) => [
30368
+ a[1] * b[2] - a[2] * b[1],
30369
+ a[2] * b[0] - a[0] * b[2],
30370
+ a[0] * b[1] - a[1] * b[0]
30371
+ ];
30372
+ var sub3 = (a, b) => [
30373
+ a[0] - b[0],
30374
+ a[1] - b[1],
30375
+ a[2] - b[2]
30376
+ ];
30377
+ var scale3 = (a, s) => [a[0] * s, a[1] * s, a[2] * s];
30378
+ var len3 = (a) => Math.hypot(a[0], a[1], a[2]);
30379
+ var norm3 = (a) => scale3(a, 1 / len3(a));
30380
+ function rotateAround(p, axis, angle) {
30381
+ const cosA = Math.cos(angle);
30382
+ const sinA = Math.sin(angle);
30383
+ const t1 = scale3(p, cosA);
30384
+ const t2 = scale3(cross3(axis, p), sinA);
30385
+ const t3 = scale3(axis, dot3(axis, p) * (1 - cosA));
30386
+ return [t1[0] + t2[0] + t3[0], t1[1] + t2[1] + t3[1], t1[2] + t2[2] + t3[2]];
30387
+ }
30388
+ function rotationTo(from, to) {
30389
+ const c = dot3(from, to);
30390
+ if (c > 1 - 1e-9) return (p) => p;
30391
+ const axis = c < -1 + 1e-9 ? norm3(
30392
+ Math.abs(from[0]) < 0.9 ? cross3(from, [1, 0, 0]) : cross3(from, [0, 1, 0])
30393
+ ) : norm3(cross3(from, to));
30394
+ const angle = Math.acos(Math.max(-1, Math.min(1, c)));
30395
+ return (p) => rotateAround(p, axis, angle);
30396
+ }
30397
+ function solidVertices(sides) {
30398
+ switch (sides) {
30399
+ case 4:
30400
+ return [
30401
+ [1, 1, 1],
30402
+ [1, -1, -1],
30403
+ [-1, 1, -1],
30404
+ [-1, -1, 1]
30405
+ ];
30406
+ case 8:
30407
+ return [
30408
+ [1, 0, 0],
30409
+ [-1, 0, 0],
30410
+ [0, 1, 0],
30411
+ [0, -1, 0],
30412
+ [0, 0, 1],
30413
+ [0, 0, -1]
30414
+ ];
30415
+ case 10: {
30416
+ const h = 0.15;
30417
+ const cos36 = Math.cos(Math.PI / 5);
30418
+ const zApex = 2 * h / (1 - cos36) * cos36 + h;
30419
+ const verts = [
30420
+ [0, 0, zApex],
30421
+ [0, 0, -zApex]
30422
+ ];
30423
+ for (let k = 0; k < 10; k++) {
30424
+ const a = k * Math.PI / 5;
30425
+ verts.push([Math.cos(a), Math.sin(a), k % 2 === 0 ? h : -h]);
30426
+ }
30427
+ return verts;
30428
+ }
30429
+ case 12: {
30430
+ const v = [];
30431
+ for (const sx of [1, -1])
30432
+ for (const sy of [1, -1])
30433
+ for (const sz of [1, -1]) v.push([sx, sy, sz]);
30434
+ const b = 1 / PHI;
30435
+ for (const s1 of [1, -1])
30436
+ for (const s2 of [1, -1]) {
30437
+ v.push([0, s1 * b, s2 * PHI]);
30438
+ v.push([s1 * b, s2 * PHI, 0]);
30439
+ v.push([s2 * PHI, 0, s1 * b]);
30440
+ }
30441
+ return v;
30442
+ }
30443
+ case 20: {
30444
+ const v = [];
30445
+ for (const s1 of [1, -1])
30446
+ for (const s2 of [1, -1]) {
30447
+ v.push([0, s1, s2 * PHI]);
30448
+ v.push([s1, s2 * PHI, 0]);
30449
+ v.push([s2 * PHI, 0, s1]);
30450
+ }
30451
+ return v;
30452
+ }
30373
30453
  }
30374
- };
30454
+ }
30455
+ function computeFaces(verts) {
30456
+ const faces = [];
30457
+ const seen = /* @__PURE__ */ new Set();
30458
+ for (let i = 0; i < verts.length; i++)
30459
+ for (let j = i + 1; j < verts.length; j++)
30460
+ for (let k = j + 1; k < verts.length; k++) {
30461
+ let n = cross3(sub3(verts[j], verts[i]), sub3(verts[k], verts[i]));
30462
+ if (len3(n) < 1e-9) continue;
30463
+ n = norm3(n);
30464
+ let d = dot3(n, verts[i]);
30465
+ if (d < 0) {
30466
+ n = scale3(n, -1);
30467
+ d = -d;
30468
+ }
30469
+ if (verts.some((p) => dot3(n, p) > d + 1e-4)) continue;
30470
+ const ids = verts.flatMap(
30471
+ (p, idx) => Math.abs(dot3(n, p) - d) < 1e-4 ? [idx] : []
30472
+ );
30473
+ const key = ids.join(",");
30474
+ if (seen.has(key)) continue;
30475
+ seen.add(key);
30476
+ faces.push({ normal: n, ids });
30477
+ }
30478
+ return faces;
30479
+ }
30480
+ var polyhedronCache = /* @__PURE__ */ new Map();
30481
+ function buildPolyhedron(sides) {
30482
+ const cached = polyhedronCache.get(sides);
30483
+ if (cached) return cached;
30484
+ let verts = solidVertices(sides);
30485
+ const rough = computeFaces(verts);
30486
+ const front = rough.reduce(
30487
+ (best, f) => f.normal[2] > best.normal[2] + 1e-9 ? f : best
30488
+ );
30489
+ const rot = rotationTo(front.normal, [0, 0, 1]);
30490
+ verts = verts.map(rot);
30491
+ const rMax = Math.max(...verts.map(len3));
30492
+ verts = verts.map((p) => scale3(p, 1 / rMax));
30493
+ const raw = computeFaces(verts);
30494
+ const built = raw.map((f) => {
30495
+ const faceVerts = f.ids.map((i) => verts[i]);
30496
+ const centroid = scale3(
30497
+ faceVerts.reduce((a, b) => [a[0] + b[0], a[1] + b[1], a[2] + b[2]]),
30498
+ 1 / faceVerts.length
30499
+ );
30500
+ const w = f.normal;
30501
+ let vRaw = sub3([0, 1, 0], scale3(w, w[1]));
30502
+ if (len3(vRaw) < 1e-6) vRaw = sub3([0, 0, 1], scale3(w, w[2]));
30503
+ const v = norm3(vRaw);
30504
+ const u = cross3(v, w);
30505
+ const pts = faceVerts.map((p) => [
30506
+ dot3(sub3(p, centroid), u),
30507
+ dot3(sub3(p, centroid), v)
30508
+ ]).sort((a, b) => Math.atan2(a[1], a[0]) - Math.atan2(b[1], b[0]));
30509
+ return { normal: w, centroid, u, v, pts, value: 0 };
30510
+ });
30511
+ built.sort((a, b) => b.normal[2] - a.normal[2]);
30512
+ const oppOf = (i) => built.findIndex((g) => dot3(built[i].normal, g.normal) < -0.9999);
30513
+ const pool = [];
30514
+ for (let v2 = 1; v2 < sides; v2++) pool.push(v2);
30515
+ built[0].value = sides;
30516
+ const opp0 = oppOf(0);
30517
+ if (opp0 >= 0) {
30518
+ built[opp0].value = 1;
30519
+ pool.splice(pool.indexOf(1), 1);
30520
+ }
30521
+ for (let i = 1; i < built.length; i++) {
30522
+ if (built[i].value !== 0) continue;
30523
+ const v2 = pool.shift();
30524
+ built[i].value = v2;
30525
+ const j = oppOf(i);
30526
+ if (j >= 0 && built[j].value === 0) {
30527
+ built[j].value = sides + 1 - v2;
30528
+ pool.splice(pool.indexOf(sides + 1 - v2), 1);
30529
+ }
30530
+ }
30531
+ const faceRadius = Math.max(
30532
+ ...built.flatMap((f) => f.pts.map(([x, y]) => Math.hypot(x, y)))
30533
+ );
30534
+ const edgeDist = (pts) => Math.min(
30535
+ ...pts.map((p1, i2) => {
30536
+ const p2 = pts[(i2 + 1) % pts.length];
30537
+ const dx = p2[0] - p1[0];
30538
+ const dy = p2[1] - p1[1];
30539
+ const t = Math.max(
30540
+ 0,
30541
+ Math.min(1, -(p1[0] * dx + p1[1] * dy) / (dx * dx + dy * dy))
30542
+ );
30543
+ return Math.hypot(p1[0] + t * dx, p1[1] + t * dy);
30544
+ })
30545
+ );
30546
+ const faceInradius = Math.min(...built.map((f) => edgeDist(f.pts)));
30547
+ const result = { faces: built, faceRadius, faceInradius };
30548
+ polyhedronCache.set(sides, result);
30549
+ return result;
30550
+ }
30375
30551
  function formatDieValue(v, sides) {
30376
30552
  return sides > 8 && (v === 6 || v === 9) ? `${v}.` : String(v);
30377
30553
  }
@@ -30596,6 +30772,7 @@ function DiceRoller({
30596
30772
  }
30597
30773
  return numeralSetters.current[i];
30598
30774
  };
30775
+ const sheenGradientId = (0, import_react69.useId)();
30599
30776
  const timersRef = (0, import_react69.useRef)([]);
30600
30777
  const rafHandleRef = (0, import_react69.useRef)(null);
30601
30778
  const arenaRef = (0, import_react69.useRef)(null);
@@ -30981,57 +31158,97 @@ function DiceRoller({
30981
31158
  },
30982
31159
  val
30983
31160
  )) : (() => {
30984
- const shape = POLY_SHAPES[sides];
31161
+ const geo = buildPolyhedron(sides);
31162
+ const R = effectiveSize / 2;
31163
+ const S = Math.ceil(geo.faceRadius * R * 2) + 6;
31164
+ const fontSize = geo.faceInradius * R * 1.15;
30985
31165
  const shown = results?.[d] ?? sides;
30986
- const cardFaceStyle = {
30987
- position: "absolute",
30988
- inset: 0,
30989
- display: "block",
30990
- overflow: "visible",
30991
- backfaceVisibility: "hidden"
30992
- };
30993
- return /* @__PURE__ */ (0, import_jsx_runtime113.jsxs)(import_jsx_runtime113.Fragment, { children: [
30994
- /* @__PURE__ */ (0, import_jsx_runtime113.jsxs)(
31166
+ return /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(import_jsx_runtime113.Fragment, { children: geo.faces.map((f, fi) => {
31167
+ 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)`;
31168
+ const gid = `${sheenGradientId}-${d}-${fi}`;
31169
+ const pts = f.pts.map(
31170
+ ([x, y]) => `${(x * R + S / 2).toFixed(2)},${(y * R + S / 2).toFixed(2)}`
31171
+ ).join(" ");
31172
+ return /* @__PURE__ */ (0, import_jsx_runtime113.jsxs)(
30995
31173
  "svg",
30996
31174
  {
30997
- viewBox: "0 0 100 100",
30998
- width: "100%",
30999
- height: "100%",
31000
- style: cardFaceStyle,
31175
+ width: S,
31176
+ height: S,
31177
+ viewBox: `0 0 ${S} ${S}`,
31178
+ style: {
31179
+ position: "absolute",
31180
+ left: "50%",
31181
+ top: "50%",
31182
+ marginLeft: -S / 2,
31183
+ marginTop: -S / 2,
31184
+ overflow: "visible",
31185
+ transform: m,
31186
+ // Convex solid: a face is either front-
31187
+ // facing or hidden behind nearer faces,
31188
+ // so hiding backfaces is both correct
31189
+ // and the mirrored-numeral guard.
31190
+ backfaceVisibility: "hidden"
31191
+ },
31001
31192
  "aria-hidden": "true",
31002
31193
  children: [
31003
- /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
31004
- "polygon",
31194
+ /* @__PURE__ */ (0, import_jsx_runtime113.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime113.jsxs)(
31195
+ "radialGradient",
31005
31196
  {
31006
- points: shape.points,
31007
- fill: colors.face,
31008
- stroke: colors.faceBorder,
31009
- strokeWidth: 2.5,
31010
- strokeLinejoin: "round",
31011
- style: { transition: "fill 0.3s, stroke 0.3s" }
31197
+ id: gid,
31198
+ cx: "32%",
31199
+ cy: "26%",
31200
+ r: "80%",
31201
+ children: [
31202
+ /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
31203
+ "stop",
31204
+ {
31205
+ offset: "0%",
31206
+ stopColor: "#fff",
31207
+ stopOpacity: "0.38"
31208
+ }
31209
+ ),
31210
+ /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
31211
+ "stop",
31212
+ {
31213
+ offset: "55%",
31214
+ stopColor: "#fff",
31215
+ stopOpacity: "0.08"
31216
+ }
31217
+ ),
31218
+ /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
31219
+ "stop",
31220
+ {
31221
+ offset: "100%",
31222
+ stopColor: "#fff",
31223
+ stopOpacity: "0"
31224
+ }
31225
+ )
31226
+ ]
31012
31227
  }
31013
- ),
31228
+ ) }),
31014
31229
  /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
31015
31230
  "polygon",
31016
31231
  {
31017
- points: shape.points,
31018
- fill: "none",
31232
+ points: pts,
31233
+ fill: colors.face,
31019
31234
  stroke: colors.faceBorder,
31020
31235
  strokeWidth: 1.5,
31021
31236
  strokeLinejoin: "round",
31022
- opacity: 0.55,
31023
- transform: "translate(50 50) scale(0.76) translate(-50 -50)"
31237
+ style: {
31238
+ transition: "fill 0.3s, stroke 0.3s"
31239
+ }
31024
31240
  }
31025
31241
  ),
31242
+ /* @__PURE__ */ (0, import_jsx_runtime113.jsx)("polygon", { points: pts, fill: `url(#${gid})` }),
31026
31243
  /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
31027
31244
  "text",
31028
31245
  {
31029
- ref: getNumeralSetter(d),
31030
- x: 50,
31031
- y: shape.textY,
31246
+ ref: fi === 0 ? getNumeralSetter(d) : void 0,
31247
+ x: S / 2,
31248
+ y: S / 2,
31032
31249
  textAnchor: "middle",
31033
31250
  dominantBaseline: "central",
31034
- fontSize: 100 * shape.fontScale,
31251
+ fontSize,
31035
31252
  fontWeight: 800,
31036
31253
  fill: colors.pip,
31037
31254
  style: {
@@ -31039,59 +31256,17 @@ function DiceRoller({
31039
31256
  transition: "fill 0.3s",
31040
31257
  userSelect: "none"
31041
31258
  },
31042
- children: formatDieValue(shown, sides)
31259
+ children: formatDieValue(
31260
+ fi === 0 ? shown : f.value,
31261
+ sides
31262
+ )
31043
31263
  }
31044
31264
  )
31045
31265
  ]
31046
- }
31047
- ),
31048
- /* @__PURE__ */ (0, import_jsx_runtime113.jsxs)(
31049
- "svg",
31050
- {
31051
- viewBox: "0 0 100 100",
31052
- width: "100%",
31053
- height: "100%",
31054
- style: {
31055
- ...cardFaceStyle,
31056
- transform: "rotateY(180deg)"
31057
- },
31058
- "aria-hidden": "true",
31059
- children: [
31060
- /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
31061
- "polygon",
31062
- {
31063
- points: shape.points,
31064
- fill: colors.face,
31065
- stroke: colors.faceBorder,
31066
- strokeWidth: 2.5,
31067
- strokeLinejoin: "round",
31068
- style: { transition: "fill 0.3s, stroke 0.3s" }
31069
- }
31070
- ),
31071
- /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
31072
- "polygon",
31073
- {
31074
- points: shape.points,
31075
- fill: "none",
31076
- stroke: colors.faceBorder,
31077
- strokeWidth: 1.5,
31078
- strokeLinejoin: "round",
31079
- opacity: 0.55,
31080
- transform: "translate(50 50) scale(0.76) translate(-50 -50)"
31081
- }
31082
- ),
31083
- /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
31084
- "polygon",
31085
- {
31086
- points: shape.points,
31087
- fill: "#000",
31088
- opacity: 0.14
31089
- }
31090
- )
31091
- ]
31092
- }
31093
- )
31094
- ] });
31266
+ },
31267
+ fi
31268
+ );
31269
+ }) });
31095
31270
  })()
31096
31271
  }
31097
31272
  )