@limrun/ui 0.17.0-rc.1 → 0.17.0-rc.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.
Files changed (80) hide show
  1. package/README.md +18 -3
  2. package/dist/{GLTFLoader-DW6wpvyR.mjs → GLTFLoader-B4nnixLv.mjs} +1 -1
  3. package/dist/{GLTFLoader-BKnsBFsj.js → GLTFLoader-GATLvS0U.js} +1 -1
  4. package/dist/components/duo-fold-motion.d.ts +1 -1
  5. package/dist/components/duo-view.d.ts +5 -1
  6. package/dist/{duo-frame-DjfA4gG-.js → duo-frame-CfBILL32.js} +2 -2
  7. package/dist/{duo-frame-BzyYljix.mjs → duo-frame-F3hwc09B.mjs} +406 -406
  8. package/dist/duo-view-BsdKpp8d.mjs +662 -0
  9. package/dist/duo-view-Cy8kBdg9.js +1 -0
  10. package/dist/index.cjs +1 -1
  11. package/dist/index.css +1 -1
  12. package/dist/index.js +2 -2
  13. package/dist/lite.cjs +1 -1
  14. package/dist/lite.js +1 -1
  15. package/dist/{remote-control-CQjSEVDF.mjs → remote-control-BAmNHDdv.mjs} +109 -108
  16. package/dist/{remote-control-DVRXfCR2.js → remote-control-F3h8U5pg.js} +1 -1
  17. package/package.json +5 -1
  18. package/dist/demo.d.ts +0 -1
  19. package/dist/duo-view-COZg8ieG.js +0 -1
  20. package/dist/duo-view-o1yxIzxu.mjs +0 -654
  21. package/index.html +0 -199
  22. package/src/assets/Apple_logo_white.svg +0 -4
  23. package/src/assets/android_boot.gif +0 -0
  24. package/src/assets/android_boot.webp +0 -0
  25. package/src/assets/iphone16pro_black.webp +0 -0
  26. package/src/assets/iphone16pro_black_bg.webp +0 -0
  27. package/src/assets/iphone16pro_black_landscape.webp +0 -0
  28. package/src/assets/iphone16pro_black_landscape_bg.webp +0 -0
  29. package/src/assets/pixel9_black.webp +0 -0
  30. package/src/assets/pixel9_black_landscape.webp +0 -0
  31. package/src/assets/pixel_tablet_landscape.webp +0 -0
  32. package/src/assets/pixel_tablet_portrait.webp +0 -0
  33. package/src/components/device-install/index.ts +0 -1
  34. package/src/components/duo-button-hinge.test.tsx +0 -138
  35. package/src/components/duo-button-hinge.ts +0 -75
  36. package/src/components/duo-controls.tsx +0 -142
  37. package/src/components/duo-flat-frame.tsx +0 -145
  38. package/src/components/duo-flat-geometry.test.ts +0 -63
  39. package/src/components/duo-flat-geometry.ts +0 -97
  40. package/src/components/duo-fold-motion.test.tsx +0 -245
  41. package/src/components/duo-fold-motion.tsx +0 -192
  42. package/src/components/duo-fold-renderer.test.ts +0 -29
  43. package/src/components/duo-fold-renderer.ts +0 -397
  44. package/src/components/duo-fold-timing.test.ts +0 -44
  45. package/src/components/duo-fold-timing.ts +0 -9
  46. package/src/components/duo-frame.tsx +0 -579
  47. package/src/components/duo-hardware.test.ts +0 -61
  48. package/src/components/duo-hardware.ts +0 -61
  49. package/src/components/duo-model.test.ts +0 -243
  50. package/src/components/duo-model.ts +0 -607
  51. package/src/components/duo-screen-handoff.ts +0 -52
  52. package/src/components/duo-view.test.tsx +0 -104
  53. package/src/components/duo-view.tsx +0 -315
  54. package/src/components/inspect-overlay.css +0 -223
  55. package/src/components/inspect-overlay.tsx +0 -437
  56. package/src/components/remote-control-framed.tsx +0 -14
  57. package/src/components/remote-control.css +0 -441
  58. package/src/components/remote-control.test.ts +0 -34
  59. package/src/components/remote-control.tsx +0 -3989
  60. package/src/core/ax-fetcher.test.ts +0 -418
  61. package/src/core/ax-fetcher.ts +0 -387
  62. package/src/core/ax-tree.test.ts +0 -491
  63. package/src/core/ax-tree.ts +0 -416
  64. package/src/core/camera.test.ts +0 -155
  65. package/src/core/camera.ts +0 -133
  66. package/src/core/constants.ts +0 -344
  67. package/src/core/duo.test.ts +0 -142
  68. package/src/core/duo.ts +0 -156
  69. package/src/core/webrtc-messages.ts +0 -148
  70. package/src/demo.tsx +0 -283
  71. package/src/frame-assets.ts +0 -22
  72. package/src/hooks/index.ts +0 -1
  73. package/src/index.ts +0 -29
  74. package/src/lite.test.ts +0 -30
  75. package/src/lite.ts +0 -30
  76. package/src/vite-env.d.ts +0 -1
  77. package/tsconfig.json +0 -26
  78. package/tsconfig.node.json +0 -26
  79. package/vite.config.ts +0 -35
  80. package/vitest.config.ts +0 -24
@@ -0,0 +1,662 @@
1
+ import { jsx as o, jsxs as v, Fragment as R } from "react/jsx-runtime";
2
+ import nt, { useId as Z, useState as H, useRef as M, useEffect as W, useCallback as ot, useLayoutEffect as it, Suspense as at, lazy as st } from "react";
3
+ import { H as ct, D as G, h as dt, i as z, j as ut } from "./remote-control-BAmNHDdv.mjs";
4
+ function lt(t, n, r) {
5
+ const [c, a] = H(t), i = M({ nativeAngle: t, send: n, failed: r });
6
+ i.current = { nativeAngle: t, send: n, failed: r };
7
+ const l = M(void 0), m = M(!1), u = M(null);
8
+ return W(() => (u.current = new ct(
9
+ async (p) => {
10
+ await i.current.send(p), l.current === p && (l.current = void 0);
11
+ },
12
+ (p) => {
13
+ l.current = void 0, i.current.failed(String(p)), a(i.current.nativeAngle);
14
+ }
15
+ ), () => u.current?.stop()), []), W(() => {
16
+ !m.current && l.current === void 0 && a(t);
17
+ }, [t]), { angle: c, changeAngle: (p) => {
18
+ i.current.failed(void 0), l.current = p, a(p), u.current?.set(p);
19
+ }, interacting: m };
20
+ }
21
+ function ht({
22
+ angle: t,
23
+ changeAngle: n,
24
+ interacting: r,
25
+ rotate: c,
26
+ onFold: a,
27
+ foldTarget: i,
28
+ onHingeDrag: l,
29
+ children: m
30
+ }) {
31
+ const u = Z();
32
+ return /* @__PURE__ */ v("div", { className: "rc-duo-controls", onPointerDown: (d) => d.stopPropagation(), children: [
33
+ /* @__PURE__ */ v("div", { className: "rc-duo-hinge", children: [
34
+ /* @__PURE__ */ o("button", { className: "rc-duo-fold", onClick: a ?? (() => n(t < 90 ? 180 : 0)), children: (i ?? t) < 90 ? "Unfold" : "Fold" }),
35
+ /* @__PURE__ */ o("label", { htmlFor: u, children: "Hinge" }),
36
+ /* @__PURE__ */ o(
37
+ "input",
38
+ {
39
+ id: u,
40
+ type: "range",
41
+ min: 0,
42
+ max: 180,
43
+ step: 1,
44
+ value: t,
45
+ onPointerDown: (d) => {
46
+ l?.(), r.current = !0, d.currentTarget.setPointerCapture(d.pointerId);
47
+ },
48
+ onPointerUp: () => {
49
+ r.current = !1;
50
+ },
51
+ onPointerCancel: () => {
52
+ r.current = !1;
53
+ },
54
+ onLostPointerCapture: () => {
55
+ r.current = !1;
56
+ },
57
+ onChange: (d) => n(Number(d.target.value))
58
+ }
59
+ ),
60
+ /* @__PURE__ */ v("output", { children: [
61
+ Math.round(t),
62
+ "°"
63
+ ] }),
64
+ /* @__PURE__ */ o("button", { className: "rc-duo-rotate", "aria-label": "Rotate device", title: "Rotate device", onClick: c, children: /* @__PURE__ */ v(
65
+ "svg",
66
+ {
67
+ viewBox: "0 0 24 24",
68
+ width: "18",
69
+ height: "18",
70
+ fill: "none",
71
+ stroke: "currentColor",
72
+ strokeWidth: "1.6",
73
+ "aria-hidden": "true",
74
+ children: [
75
+ /* @__PURE__ */ o("rect", { x: "7", y: "3", width: "10", height: "18", rx: "2" }),
76
+ /* @__PURE__ */ o("path", { d: "M3 9a9 9 0 0 1 3-5M3 4v5h5M21 15a9 9 0 0 1-3 5m3 0v-5h-5" })
77
+ ]
78
+ }
79
+ ) })
80
+ ] }),
81
+ m && /* @__PURE__ */ o("div", { className: "rc-duo-views", "aria-label": "Device view", children: m })
82
+ ] });
83
+ }
84
+ function ft({ button: t }) {
85
+ return /* @__PURE__ */ o(
86
+ "svg",
87
+ {
88
+ viewBox: "0 0 24 24",
89
+ width: "24",
90
+ height: "24",
91
+ fill: "none",
92
+ stroke: "currentColor",
93
+ strokeWidth: "1.7",
94
+ strokeLinecap: "round",
95
+ strokeLinejoin: "round",
96
+ "aria-hidden": "true",
97
+ children: t === "side" ? /* @__PURE__ */ v(R, { children: [
98
+ /* @__PURE__ */ o("rect", { x: "6", y: "10", width: "12", height: "11", rx: "2" }),
99
+ /* @__PURE__ */ o("path", { d: "M8 10V7a4 4 0 0 1 8 0v3" })
100
+ ] }) : /* @__PURE__ */ v(R, { children: [
101
+ /* @__PURE__ */ o("path", { d: "M3 9h4l5-5v16l-5-5H3zM17 12h5" }),
102
+ t === "volumeUp" && /* @__PURE__ */ o("path", { d: "M19.5 9.5v5" })
103
+ ] })
104
+ }
105
+ );
106
+ }
107
+ function X(t, n, r, c, a, i) {
108
+ return "M" + (t + a) + "," + n + "H" + (t + r - i) + "a" + i + "," + i + " 0 0 1 " + i + "," + i + "V" + (n + c - i) + "a" + i + "," + i + " 0 0 1 " + -i + "," + i + "H" + (t + a) + "a" + a + "," + a + " 0 0 1 " + -a + "," + -a + "V" + (n + a) + "a" + a + "," + a + " 0 0 1 " + a + "," + -a + "Z";
109
+ }
110
+ function J({ inner: t, width: n, height: r }) {
111
+ const c = Z().replace(/:/g, ""), a = t ? 8.4 : 1.25, i = 8.4;
112
+ return /* @__PURE__ */ v("svg", { className: "rc-duo-flat-frame", viewBox: "0 0 " + n + " " + r, "aria-hidden": "true", children: [
113
+ /* @__PURE__ */ v("defs", { children: [
114
+ /* @__PURE__ */ v("linearGradient", { id: c + "-silver", x1: "0", y1: "0", x2: "1", y2: "1", children: [
115
+ /* @__PURE__ */ o("stop", { offset: "0", stopColor: "#62676b" }),
116
+ /* @__PURE__ */ o("stop", { offset: "0.035", stopColor: "#f9faf9" }),
117
+ /* @__PURE__ */ o("stop", { offset: "0.11", stopColor: "#b0b4b6" }),
118
+ /* @__PURE__ */ o("stop", { offset: "0.31", stopColor: "#fdfefd" }),
119
+ /* @__PURE__ */ o("stop", { offset: "0.43", stopColor: "#797f84" }),
120
+ /* @__PURE__ */ o("stop", { offset: "0.51", stopColor: "#e8eaea" }),
121
+ /* @__PURE__ */ o("stop", { offset: "0.7", stopColor: "#979da1" }),
122
+ /* @__PURE__ */ o("stop", { offset: "0.87", stopColor: "#fafbf9" }),
123
+ /* @__PURE__ */ o("stop", { offset: "1", stopColor: "#5f676c" })
124
+ ] }),
125
+ /* @__PURE__ */ v("linearGradient", { id: c + "-spine", children: [
126
+ /* @__PURE__ */ o("stop", { stopColor: "#4a5154" }),
127
+ /* @__PURE__ */ o("stop", { offset: "0.16", stopColor: "#d6d9d9" }),
128
+ /* @__PURE__ */ o("stop", { offset: "0.4", stopColor: "#f8f9f7" }),
129
+ /* @__PURE__ */ o("stop", { offset: "0.62", stopColor: "#a2a8ab" }),
130
+ /* @__PURE__ */ o("stop", { offset: "0.83", stopColor: "#e4e7e5" }),
131
+ /* @__PURE__ */ o("stop", { offset: "1", stopColor: "#666e72" })
132
+ ] })
133
+ ] }),
134
+ !t && /* @__PURE__ */ v(R, { children: [
135
+ /* @__PURE__ */ o(
136
+ "rect",
137
+ {
138
+ x: "-2.3",
139
+ y: "0.7",
140
+ width: "3.3",
141
+ height: r - 1.4,
142
+ rx: "0.85",
143
+ fill: "url(#" + c + "-spine)",
144
+ stroke: "#8b9296",
145
+ strokeWidth: "0.15"
146
+ }
147
+ ),
148
+ /* @__PURE__ */ o("path", { d: "M-.6 2V" + (r - 2), stroke: "#f5f6f4", strokeWidth: "0.22" })
149
+ ] }),
150
+ /* @__PURE__ */ o(
151
+ "path",
152
+ {
153
+ d: X(0, 0, n, r, a, i),
154
+ fill: "url(#" + c + "-silver)",
155
+ stroke: "#696f72",
156
+ strokeWidth: "0.24"
157
+ }
158
+ ),
159
+ /* @__PURE__ */ o(
160
+ "path",
161
+ {
162
+ d: X(0.48, 0.48, n - 0.96, r - 0.96, Math.max(0.5, a - 0.48), i - 0.48),
163
+ fill: "none",
164
+ stroke: "#ffffff",
165
+ strokeOpacity: "0.85",
166
+ strokeWidth: "0.2"
167
+ }
168
+ ),
169
+ /* @__PURE__ */ o(
170
+ "path",
171
+ {
172
+ d: X(1.12, 1.12, n - 2.24, r - 2.24, t ? 7.15 : 0.65, 7.15),
173
+ fill: "#090b0d",
174
+ stroke: "#34393c",
175
+ strokeWidth: "0.2"
176
+ }
177
+ ),
178
+ [n - 16, t ? 19 : 16].map((l) => /* @__PURE__ */ o(nt.Fragment, { children: /* @__PURE__ */ o(
179
+ "path",
180
+ {
181
+ d: "M" + l + ",0.17v0.82M" + l + "," + (r - 1) + "v0.82",
182
+ stroke: "#b1b2ac",
183
+ strokeWidth: "1.1"
184
+ }
185
+ ) }, l)),
186
+ t && [0, r - 0.6].map((l) => /* @__PURE__ */ o(
187
+ "rect",
188
+ {
189
+ x: n / 2 - 2.2,
190
+ y: l,
191
+ width: "4.4",
192
+ height: "0.6",
193
+ rx: "0.18",
194
+ fill: "url(#" + c + "-spine)",
195
+ stroke: "#697074",
196
+ strokeWidth: "0.14"
197
+ },
198
+ l
199
+ )),
200
+ /* @__PURE__ */ o(
201
+ "path",
202
+ {
203
+ d: "M" + (n - 0.1) + ",20h-.9m.9," + (r - 40) + "h-.9",
204
+ stroke: "#b1b2ac",
205
+ strokeWidth: "1.05"
206
+ }
207
+ )
208
+ ] });
209
+ }
210
+ function mt(t, n, r, c) {
211
+ const a = G.width / (t ? 1 : 2), i = G.height, l = t ? 157.5 : 77.1, m = t ? 110.8 : 112.2, u = (n + (t ? 3 : 0)) % 4, d = Math.max(
212
+ 0,
213
+ Math.min(
214
+ (r - 120) / (u % 2 ? i : a),
215
+ (c - 120) / (u % 2 ? a : i)
216
+ )
217
+ ), p = (h, w) => {
218
+ h = (h - a / 2) * d, w = (w - i / 2) * d;
219
+ const C = u === 1 ? { x: -w, y: h } : u === 2 ? { x: -h, y: -w } : u === 3 ? { x: w, y: -h } : { x: h, y: w };
220
+ return { x: C.x + r / 2, y: C.y + c / 2 };
221
+ }, F = (u % 2 ? i : a) * d, P = (u % 2 ? a : i) * d, N = {
222
+ min: { x: (r - F) / 2, y: (c - P) / 2 },
223
+ max: { x: (r + F) / 2, y: (c + P) / 2 }
224
+ }, y = [
225
+ { button: "volumeDown", x: a - 37, y: -0.32, width: 9.5, height: 0.65, edge: "top" },
226
+ { button: "volumeUp", x: a - 25, y: -0.32, width: 9.5, height: 0.65, edge: "top" },
227
+ { button: "side", x: a + 0.35, y: i / 2 - 21, width: 0.7, height: 13, edge: "right" }
228
+ ], g = ["top", "right", "bottom", "left"], x = y.map((h) => {
229
+ const w = g[(g.indexOf(h.edge) + u) % 4], C = p(h.x, h.y);
230
+ return w === "top" && (C.y = N.min.y - 28), w === "bottom" && (C.y = N.max.y + 28), w === "left" && (C.x = N.min.x - 28), w === "right" && (C.x = N.max.x + 28), { button: h.button, edge: w, ...C, targetX: C.x, targetY: C.y };
231
+ }), f = x.filter((h) => h.button !== "side"), b = u % 2 ? "y" : "x";
232
+ f.sort((h, w) => h[b] - w[b]);
233
+ const S = u % 2 ? "targetY" : "targetX";
234
+ if (f[1][b] - f[0][b] < 44) {
235
+ const h = (f[0][b] + f[1][b]) / 2;
236
+ f[0][S] = h - 22, f[1][S] = h + 22;
237
+ }
238
+ return {
239
+ bodyWidth: a,
240
+ bodyHeight: i,
241
+ screenWidth: l,
242
+ screenHeight: m,
243
+ scale: d,
244
+ turns: u,
245
+ buttons: y,
246
+ guides: x,
247
+ rect: N,
248
+ iconSize: Math.min(pt(N), 12 * d)
249
+ };
250
+ }
251
+ function pt(t) {
252
+ return Math.max(12, Math.min(24, Math.max(t.max.x - t.min.x, t.max.y - t.min.y) / 24));
253
+ }
254
+ function gt(t, n, r) {
255
+ return [
256
+ ["top", r.min.y - n, t, r.min.x, r.max.x],
257
+ ["bottom", n - r.max.y, t, r.min.x, r.max.x],
258
+ ["left", r.min.x - t, n, r.min.y, r.max.y],
259
+ ["right", t - r.max.x, n, r.min.y, r.max.y]
260
+ ].filter(
261
+ ([, a, i, l, m]) => a >= -7 && a <= 52 && i >= l - 12 && i <= m + 12
262
+ ).sort((a, i) => Math.abs(a[1]) - Math.abs(i[1]))[0]?.[0];
263
+ }
264
+ function Y(t) {
265
+ if (!t || t.readyState < 2 || !t.videoWidth || !t.videoHeight) return;
266
+ const n = Math.min(1, 1024 / Math.max(t.videoWidth, t.videoHeight)), r = document.createElement("canvas");
267
+ try {
268
+ const c = r.getContext("2d");
269
+ return c ? (r.width = Math.round(t.videoWidth * n), r.height = Math.round(t.videoHeight * n), c.drawImage(t, 0, 0, r.width, r.height), r) : void 0;
270
+ } catch {
271
+ return;
272
+ }
273
+ }
274
+ function yt(t, n) {
275
+ let r = !1, c;
276
+ const a = (d) => {
277
+ r || (u(), n(d));
278
+ }, i = () => {
279
+ if (r) return;
280
+ const d = Y(t);
281
+ d && a(d);
282
+ }, l = () => {
283
+ c = void 0, i(), r || (c = t?.requestVideoFrameCallback?.(l));
284
+ }, m = setTimeout(() => a(void 0), 2500);
285
+ c = t?.requestVideoFrameCallback?.(l), t?.addEventListener("loadeddata", i), !t?.requestVideoFrameCallback && t && t.readyState >= 2 && i();
286
+ function u() {
287
+ r = !0, clearTimeout(m), c !== void 0 && t?.cancelVideoFrameCallback(c), t?.removeEventListener("loadeddata", i);
288
+ }
289
+ return u;
290
+ }
291
+ function bt(t, n, r, c, a = !0) {
292
+ const i = M(void 0), l = M(c), m = M({ inner: n, frame: r });
293
+ m.current = { inner: n, frame: r };
294
+ const [u, d] = H(), p = M(void 0), F = M(void 0), P = ot(() => {
295
+ clearTimeout(F.current), p.current = void 0, d(void 0);
296
+ }, []), N = (y) => {
297
+ if (!a || y === n) {
298
+ P();
299
+ return;
300
+ }
301
+ if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches || p.current) return;
302
+ const g = Y(t.current);
303
+ if (!g) return;
304
+ const x = m.current;
305
+ p.current = { from: x, to: x, before: g, ready: !1 }, d(p.current), F.current = setTimeout(P, 5e3);
306
+ };
307
+ return W(() => () => clearTimeout(F.current), []), it(() => {
308
+ const y = i.current, g = { inner: n, frame: r };
309
+ i.current = g;
310
+ const x = l.current !== c;
311
+ if (l.current = c, !y) return;
312
+ const f = Math.abs(y.frame.rect.min.x + y.frame.rect.max.x - r.rect.min.x - r.rect.max.x) > 0.5 || Math.abs(y.frame.rect.min.y + y.frame.rect.max.y - r.rect.min.y - r.rect.max.y) > 0.5;
313
+ if (!a || f || x) {
314
+ P();
315
+ return;
316
+ }
317
+ if (y.inner === n || (d(void 0), !y.frame.scale || !r.scale) || window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return;
318
+ const b = p.current?.before ?? Y(t.current), S = p.current?.from ?? y;
319
+ clearTimeout(F.current), p.current = void 0, b && d({ from: S, to: g, before: b, ready: !1 });
320
+ }, [n, r.scale, r.turns, r.rect.min.x, r.rect.min.y, c, a]), W(() => {
321
+ if (!u || u.from.inner === n) return;
322
+ const y = yt(t.current, (f) => {
323
+ f ? d((b) => b && { ...b, to: m.current, after: f, ready: !0 }) : P();
324
+ }), g = window.matchMedia?.("(prefers-reduced-motion: reduce)"), x = () => {
325
+ g?.matches && d(void 0);
326
+ };
327
+ return g?.addEventListener("change", x), () => {
328
+ y(), g?.removeEventListener("change", x);
329
+ };
330
+ }, [u?.from, n]), { motion: u, finish: P, prepare: N };
331
+ }
332
+ function vt({ pose: t, image: n, scale: r }) {
333
+ const { bodyWidth: c, bodyHeight: a, screenWidth: i, screenHeight: l } = t.frame, m = i * r, u = l * r;
334
+ return /* @__PURE__ */ v("div", { className: "rc-duo-fold-still", style: { width: c * r, height: a * r }, children: [
335
+ /* @__PURE__ */ o(J, { inner: t.inner, width: c, height: a }),
336
+ /* @__PURE__ */ o(
337
+ "div",
338
+ {
339
+ className: "rc-duo-flat-screen",
340
+ style: {
341
+ width: m,
342
+ height: u,
343
+ left: (c - i) * r / 2,
344
+ top: (a - l) * r / 2,
345
+ borderRadius: t.inner ? 5.3 * r : [0.8, 6.6, 6.6, 0.8].map((d) => d * r + "px").join(" ")
346
+ },
347
+ children: n && /* @__PURE__ */ o(
348
+ "canvas",
349
+ {
350
+ ref: (d) => {
351
+ d && (d.width = n.width, d.height = n.height, d.getContext("2d")?.drawImage(n, 0, 0));
352
+ },
353
+ style: {
354
+ width: t.inner ? u : m,
355
+ height: t.inner ? m : u,
356
+ transform: `translate(-50%, -50%) rotate(${t.inner ? 90 : 0}deg)`
357
+ }
358
+ }
359
+ )
360
+ }
361
+ )
362
+ ] });
363
+ }
364
+ function xt({ motion: t, onFinish: n }) {
365
+ const r = M(null), [c, a] = H(!1);
366
+ return W(() => {
367
+ if (a(!1), !t.ready) return;
368
+ let i = !1, l;
369
+ return import("./duo-fold-renderer-BXejNHcY.mjs").then(({ renderFold: m }) => {
370
+ i || !r.current || (l = m(r.current, t, n), a(!0));
371
+ }).catch(() => {
372
+ i || n();
373
+ }), () => {
374
+ i = !0, l?.();
375
+ };
376
+ }, [t.ready, t.from, n]), /* @__PURE__ */ v(R, { children: [
377
+ !c && /* @__PURE__ */ o(
378
+ "div",
379
+ {
380
+ className: "rc-duo-fold-hold",
381
+ "aria-hidden": "true",
382
+ style: {
383
+ width: t.from.frame.bodyWidth * t.from.frame.scale,
384
+ height: t.from.frame.bodyHeight * t.from.frame.scale,
385
+ transform: `translate(-50%, -50%) rotate(${t.from.frame.turns * 90}deg)`
386
+ },
387
+ children: /* @__PURE__ */ o(vt, { pose: t.from, image: t.before, scale: t.from.frame.scale })
388
+ }
389
+ ),
390
+ /* @__PURE__ */ o(
391
+ "canvas",
392
+ {
393
+ ref: r,
394
+ className: "rc-duo-fold-canvas",
395
+ "aria-hidden": "true",
396
+ style: { visibility: c ? "visible" : "hidden" }
397
+ }
398
+ )
399
+ ] });
400
+ }
401
+ const wt = st(() => import("./duo-frame-F3hwc09B.mjs").then((t) => t.ac));
402
+ function Mt(t) {
403
+ const [n, r] = H("2d");
404
+ return /* @__PURE__ */ v("div", { className: "rc-duo-view", children: [
405
+ t.showFrame !== !1 && n === "3d" ? /* @__PURE__ */ o(at, { fallback: /* @__PURE__ */ o(A, { ...t }), children: /* @__PURE__ */ o(wt, { ...t }) }) : /* @__PURE__ */ o(A, { ...t }),
406
+ t.showFrame !== !1 && /* @__PURE__ */ v("div", { className: "rc-duo-mode", role: "group", "aria-label": "Device rendering", children: [
407
+ /* @__PURE__ */ o("button", { type: "button", "aria-pressed": n === "2d", onClick: () => r("2d"), children: "2D" }),
408
+ /* @__PURE__ */ o("button", { type: "button", "aria-pressed": n === "3d", onClick: () => r("3d"), children: "3D" })
409
+ ] })
410
+ ] });
411
+ }
412
+ function A(t) {
413
+ const n = t.showFrame !== !1, r = M(null), c = M(null), a = M(t);
414
+ a.current = t;
415
+ const [i, l] = H({ width: 0, height: 0 }), [m, u] = H(), [d, p] = H(), [F, P] = H(), [N, y] = H(), g = M(void 0), x = M(null), f = t.state.displays.find(
416
+ (e) => e.id === (t.state.angleDegrees < 90 ? "outer" : "inner")
417
+ ), b = f?.id === "inner" ? t.inner : t.outer, S = f?.orientation === 2 ? 2 : f?.orientation === 3 ? 1 : f?.orientation === 4 ? 3 : 0, h = f?.id === "inner", w = { portrait: 0, pud: 2, "landscape-left": 3, "landscape-right": 1 }[t.state.orientation], C = n ? (w + (h ? 1 : 0)) % 4 : S, k = mt(h, C, i.width, i.height), U = n ? k.screenWidth : (h ? f?.height : f?.width) ?? 1, V = n ? k.screenHeight : (h ? f?.width : f?.height) ?? 1, T = n ? k.bodyWidth : U, E = n ? k.bodyHeight : V, D = n ? k.scale : Math.max(
418
+ 0,
419
+ Math.min(
420
+ i.width / (k.turns % 2 ? E : T),
421
+ i.height / (k.turns % 2 ? T : E)
422
+ )
423
+ ), B = U * D, K = V * D;
424
+ W(() => {
425
+ const e = new ResizeObserver(([s]) => {
426
+ s && l({ width: s.contentRect.width, height: s.contentRect.height });
427
+ });
428
+ return r.current && e.observe(r.current), () => e.disconnect();
429
+ }, []), W(() => {
430
+ const e = c.current;
431
+ if (!e || !b) return;
432
+ const s = () => {
433
+ e.srcObject !== b.srcObject && (e.srcObject = b.srcObject), e.play().catch(() => {
434
+ }), t.outer?.pause(), t.inner?.pause();
435
+ };
436
+ return s(), b.addEventListener("loadedmetadata", s), () => {
437
+ b.removeEventListener("loadedmetadata", s), e.pause(), e.srcObject = null;
438
+ for (const j of [t.outer, t.inner]) j?.play().catch(() => {
439
+ });
440
+ };
441
+ }, [b, t.outer, t.inner]);
442
+ const {
443
+ motion: I,
444
+ finish: _,
445
+ prepare: Q
446
+ } = bt(c, h, k, t.state.orientation, n), { angle: tt, changeAngle: et, interacting: rt } = lt(
447
+ t.state.angleDegrees,
448
+ async (e) => {
449
+ Q(e >= 90);
450
+ try {
451
+ await t.setAngle(e);
452
+ } catch (s) {
453
+ throw _(), s;
454
+ }
455
+ },
456
+ u
457
+ ), O = () => {
458
+ if (!g.current) return;
459
+ const { screenId: e, x: s, y: j } = g.current;
460
+ a.current.touch(1, e, s, j), g.current = void 0;
461
+ };
462
+ W(() => {
463
+ x.current = new dt(
464
+ (s, j) => a.current.button(s, j),
465
+ (s) => u(String(s))
466
+ );
467
+ const e = () => {
468
+ O(), x.current?.release(), y(void 0);
469
+ };
470
+ return window.addEventListener("blur", e), () => {
471
+ e(), window.removeEventListener("blur", e);
472
+ };
473
+ }, []), W(() => {
474
+ O();
475
+ }, [f?.screenId, C]);
476
+ const L = () => {
477
+ x.current?.release(), y(void 0);
478
+ }, $ = (e) => ({
479
+ onPointerDown: (s) => {
480
+ I || s.button !== 0 || (s.currentTarget.setPointerCapture(s.pointerId), x.current?.press(e), y(e));
481
+ },
482
+ onPointerUp: L,
483
+ onPointerCancel: L,
484
+ onLostPointerCapture: L,
485
+ onBlur: L,
486
+ onPointerEnter: () => P(e),
487
+ onPointerLeave: () => P(void 0),
488
+ onFocus: () => p(k.guides.find((s) => s.button === e)?.edge),
489
+ onKeyDown: (s) => {
490
+ I || (s.key === "Enter" || s.key === " ") && (s.preventDefault(), s.repeat || (x.current?.press(e), y(e)));
491
+ },
492
+ onKeyUp: (s) => {
493
+ (s.key === "Enter" || s.key === " ") && (s.preventDefault(), L());
494
+ }
495
+ }), q = (e) => {
496
+ const s = e.currentTarget.getBoundingClientRect();
497
+ return ut(
498
+ (e.clientX - s.left) / s.width,
499
+ (e.clientY - s.top) / s.height,
500
+ C
501
+ );
502
+ };
503
+ return /* @__PURE__ */ v("div", { className: n ? "rc-duo" : "rc-duo rc-duo-frameless", children: [
504
+ /* @__PURE__ */ v(
505
+ "div",
506
+ {
507
+ ref: r,
508
+ className: "rc-duo-flat-stage",
509
+ "data-folding": !!I,
510
+ "aria-busy": !!I,
511
+ onPointerMove: (e) => {
512
+ if (!n) return;
513
+ const s = e.currentTarget.getBoundingClientRect();
514
+ p(gt(e.clientX - s.left, e.clientY - s.top, k.rect));
515
+ },
516
+ onPointerLeave: () => {
517
+ p(void 0), P(void 0);
518
+ },
519
+ children: [
520
+ /* @__PURE__ */ v(
521
+ "div",
522
+ {
523
+ className: "rc-duo-flat-device",
524
+ "data-display": h ? "inner" : "outer",
525
+ style: {
526
+ width: T * D,
527
+ height: E * D,
528
+ transform: "translate(-50%, -50%) rotate(" + k.turns * 90 + "deg)"
529
+ },
530
+ children: [
531
+ n && /* @__PURE__ */ o(J, { inner: h, width: T, height: E }),
532
+ /* @__PURE__ */ o(
533
+ "div",
534
+ {
535
+ className: "rc-duo-flat-screen",
536
+ role: "application",
537
+ "aria-label": "iPhone Duo 2D simulator",
538
+ tabIndex: 0,
539
+ style: {
540
+ width: B,
541
+ height: K,
542
+ left: (T - U) / 2 * D,
543
+ top: (E - V) / 2 * D,
544
+ borderRadius: n ? h ? 5.3 * D : [0.8, 6.6, 6.6, 0.8].map((e) => e * D + "px").join(" ") : 0
545
+ },
546
+ onKeyDown: I ? void 0 : t.onKeyDown,
547
+ onKeyUp: t.onKeyUp,
548
+ onPointerDown: (e) => {
549
+ if (I || g.current || e.button !== 0 || !f) return;
550
+ e.currentTarget.focus({ preventScroll: !0 }), e.currentTarget.setPointerCapture(e.pointerId);
551
+ const s = q(e);
552
+ g.current = { pointer: e.pointerId, screenId: f.screenId, ...s }, t.touch(0, f.screenId, s.x, s.y);
553
+ },
554
+ onPointerMove: (e) => {
555
+ if (g.current?.pointer !== e.pointerId) return;
556
+ const s = q(e);
557
+ Object.assign(g.current, s), t.touch(2, g.current.screenId, s.x, s.y);
558
+ },
559
+ onPointerUp: (e) => {
560
+ g.current?.pointer === e.pointerId && O();
561
+ },
562
+ onPointerCancel: O,
563
+ onLostPointerCapture: O,
564
+ children: /* @__PURE__ */ o(
565
+ "video",
566
+ {
567
+ ref: c,
568
+ autoPlay: !0,
569
+ muted: !0,
570
+ playsInline: !0,
571
+ style: {
572
+ width: h ? K : B,
573
+ height: h ? B : K,
574
+ transform: "translate(-50%, -50%) rotate(" + (h ? 90 : 0) + "deg)"
575
+ }
576
+ }
577
+ )
578
+ }
579
+ ),
580
+ n && k.buttons.map((e) => /* @__PURE__ */ o(
581
+ "button",
582
+ {
583
+ type: "button",
584
+ className: "rc-duo-physical",
585
+ "data-duo-button": e.button,
586
+ "data-edge": e.edge,
587
+ "data-highlighted": F === e.button,
588
+ "data-pressed": N === e.button,
589
+ "aria-label": z[e.button] + " physical button",
590
+ title: z[e.button],
591
+ style: {
592
+ left: e.x * D,
593
+ top: e.y * D,
594
+ width: e.edge === "top" ? Math.max(28, e.width * D) : 28,
595
+ height: e.edge === "top" ? 28 : Math.max(28, e.height * D)
596
+ },
597
+ ...$(e.button),
598
+ children: /* @__PURE__ */ o(
599
+ "span",
600
+ {
601
+ style: { width: Math.max(2, e.width * D), height: Math.max(2, e.height * D) }
602
+ }
603
+ )
604
+ },
605
+ e.button
606
+ ))
607
+ ]
608
+ }
609
+ ),
610
+ n && k.guides.map((e) => /* @__PURE__ */ o(
611
+ "button",
612
+ {
613
+ type: "button",
614
+ className: "rc-duo-hardware",
615
+ "data-duo-button": e.button,
616
+ "data-visible": d === e.edge,
617
+ "data-pressed": N === e.button,
618
+ "aria-label": z[e.button],
619
+ title: z[e.button],
620
+ style: {
621
+ left: e.targetX,
622
+ top: e.targetY,
623
+ "--duo-hardware-icon-size": `${k.iconSize}px`,
624
+ "--duo-hardware-icon-x": `${e.x - e.targetX}px`,
625
+ "--duo-hardware-icon-y": `${e.y - e.targetY}px`
626
+ },
627
+ ...$(e.button),
628
+ children: /* @__PURE__ */ o(ft, { button: e.button })
629
+ },
630
+ e.button
631
+ )),
632
+ I && /* @__PURE__ */ o(xt, { motion: I, onFinish: _ })
633
+ ]
634
+ }
635
+ ),
636
+ n && /* @__PURE__ */ o(
637
+ ht,
638
+ {
639
+ angle: tt,
640
+ changeAngle: et,
641
+ interacting: rt,
642
+ rotate: () => {
643
+ t.setOrientation(t.state.orientation === "portrait" ? "landscape-left" : "portrait").catch((e) => u(String(e)));
644
+ },
645
+ children: /* @__PURE__ */ o("span", { className: "rc-duo-view-label", children: "Front view" })
646
+ }
647
+ ),
648
+ m && /* @__PURE__ */ o("div", { role: "alert", className: "rc-duo-error", children: m })
649
+ ] });
650
+ }
651
+ const Pt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
652
+ __proto__: null,
653
+ default: Mt
654
+ }, Symbol.toStringTag, { value: "Module" }));
655
+ export {
656
+ ft as D,
657
+ ht as a,
658
+ Pt as d,
659
+ gt as f,
660
+ pt as h,
661
+ lt as u
662
+ };