@limrun/ui 0.17.0-rc.1 → 0.17.0-rc.2

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 (83) hide show
  1. package/README.md +18 -3
  2. package/dist/{GLTFLoader-DW6wpvyR.mjs → GLTFLoader-Cami_vza.mjs} +1 -1
  3. package/dist/{GLTFLoader-BKnsBFsj.js → GLTFLoader-DeCLxW_q.js} +1 -1
  4. package/dist/components/duo-fold-motion.d.ts +1 -1
  5. package/dist/components/duo-loading.d.ts +8 -0
  6. package/dist/components/duo-view.d.ts +6 -1
  7. package/dist/{duo-frame-BzyYljix.mjs → duo-frame-Cmw4p2uN.mjs} +414 -414
  8. package/dist/{duo-frame-DjfA4gG-.js → duo-frame-iMtrvx_a.js} +18 -18
  9. package/dist/duo-view-BAh-w2Kz.js +1 -0
  10. package/dist/duo-view-D9Ae00rj.mjs +512 -0
  11. package/dist/index.cjs +1 -1
  12. package/dist/index.css +1 -1
  13. package/dist/index.js +2 -2
  14. package/dist/lite.cjs +1 -1
  15. package/dist/lite.js +1 -1
  16. package/dist/remote-control-B2jZpf3c.js +1 -0
  17. package/dist/remote-control-DiddxS8l.mjs +2883 -0
  18. package/package.json +5 -1
  19. package/dist/demo.d.ts +0 -1
  20. package/dist/duo-view-COZg8ieG.js +0 -1
  21. package/dist/duo-view-o1yxIzxu.mjs +0 -654
  22. package/dist/remote-control-CQjSEVDF.mjs +0 -2673
  23. package/dist/remote-control-DVRXfCR2.js +0 -1
  24. package/index.html +0 -199
  25. package/src/assets/Apple_logo_white.svg +0 -4
  26. package/src/assets/android_boot.gif +0 -0
  27. package/src/assets/android_boot.webp +0 -0
  28. package/src/assets/iphone16pro_black.webp +0 -0
  29. package/src/assets/iphone16pro_black_bg.webp +0 -0
  30. package/src/assets/iphone16pro_black_landscape.webp +0 -0
  31. package/src/assets/iphone16pro_black_landscape_bg.webp +0 -0
  32. package/src/assets/pixel9_black.webp +0 -0
  33. package/src/assets/pixel9_black_landscape.webp +0 -0
  34. package/src/assets/pixel_tablet_landscape.webp +0 -0
  35. package/src/assets/pixel_tablet_portrait.webp +0 -0
  36. package/src/components/device-install/index.ts +0 -1
  37. package/src/components/duo-button-hinge.test.tsx +0 -138
  38. package/src/components/duo-button-hinge.ts +0 -75
  39. package/src/components/duo-controls.tsx +0 -142
  40. package/src/components/duo-flat-frame.tsx +0 -145
  41. package/src/components/duo-flat-geometry.test.ts +0 -63
  42. package/src/components/duo-flat-geometry.ts +0 -97
  43. package/src/components/duo-fold-motion.test.tsx +0 -245
  44. package/src/components/duo-fold-motion.tsx +0 -192
  45. package/src/components/duo-fold-renderer.test.ts +0 -29
  46. package/src/components/duo-fold-renderer.ts +0 -397
  47. package/src/components/duo-fold-timing.test.ts +0 -44
  48. package/src/components/duo-fold-timing.ts +0 -9
  49. package/src/components/duo-frame.tsx +0 -579
  50. package/src/components/duo-hardware.test.ts +0 -61
  51. package/src/components/duo-hardware.ts +0 -61
  52. package/src/components/duo-model.test.ts +0 -243
  53. package/src/components/duo-model.ts +0 -607
  54. package/src/components/duo-screen-handoff.ts +0 -52
  55. package/src/components/duo-view.test.tsx +0 -104
  56. package/src/components/duo-view.tsx +0 -315
  57. package/src/components/inspect-overlay.css +0 -223
  58. package/src/components/inspect-overlay.tsx +0 -437
  59. package/src/components/remote-control-framed.tsx +0 -14
  60. package/src/components/remote-control.css +0 -441
  61. package/src/components/remote-control.test.ts +0 -34
  62. package/src/components/remote-control.tsx +0 -3989
  63. package/src/core/ax-fetcher.test.ts +0 -418
  64. package/src/core/ax-fetcher.ts +0 -387
  65. package/src/core/ax-tree.test.ts +0 -491
  66. package/src/core/ax-tree.ts +0 -416
  67. package/src/core/camera.test.ts +0 -155
  68. package/src/core/camera.ts +0 -133
  69. package/src/core/constants.ts +0 -344
  70. package/src/core/duo.test.ts +0 -142
  71. package/src/core/duo.ts +0 -156
  72. package/src/core/webrtc-messages.ts +0 -148
  73. package/src/demo.tsx +0 -283
  74. package/src/frame-assets.ts +0 -22
  75. package/src/hooks/index.ts +0 -1
  76. package/src/index.ts +0 -29
  77. package/src/lite.test.ts +0 -30
  78. package/src/lite.ts +0 -30
  79. package/src/vite-env.d.ts +0 -1
  80. package/tsconfig.json +0 -26
  81. package/tsconfig.node.json +0 -26
  82. package/vite.config.ts +0 -35
  83. package/vitest.config.ts +0 -24
@@ -1,441 +0,0 @@
1
- .rc-container {
2
- position: relative;
3
- display: flex;
4
- align-items: center;
5
- justify-content: center;
6
- box-sizing: border-box;
7
- isolation: isolate;
8
-
9
- touch-action: none;
10
- width: 100%;
11
- height: 100%;
12
- }
13
-
14
- .rc-phone-frame {
15
- position: relative;
16
- z-index: 30;
17
- display: block;
18
- pointer-events: none;
19
- user-select: none;
20
- width: auto;
21
- height: auto;
22
- max-width: 100%;
23
- max-height: 100%;
24
- }
25
-
26
- .rc-phone-frame-ios {
27
- z-index: 10;
28
- }
29
-
30
- .rc-video {
31
- position: absolute;
32
- z-index: 20;
33
- outline: none;
34
- pointer-events: none;
35
- cursor: none;
36
- background-color: black;
37
- object-fit: contain;
38
- object-position: center center;
39
- inset: 0;
40
-
41
- top: 50%;
42
- left: 50%;
43
- transform: translate(-50%, -50%);
44
- right: auto;
45
- bottom: auto;
46
- }
47
-
48
- .rc-video-frameless {
49
- position: relative;
50
- top: auto;
51
- left: auto;
52
- transform: none;
53
- max-width: 100%;
54
- max-height: 100%;
55
- }
56
-
57
- .rc-video-loading {
58
- aspect-ratio: 9 / 19.5;
59
- }
60
-
61
- .rc-touch-indicator {
62
- position: absolute;
63
- z-index: 40;
64
- width: 40px;
65
- height: 40px;
66
- border-radius: 50%;
67
- transform: translate(-50%, -50%);
68
- pointer-events: none;
69
- background: rgba(255, 255, 255, 0.35);
70
- border: 2px solid rgba(255, 255, 255, 0.6);
71
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
72
- will-change: transform, left, top;
73
- }
74
-
75
- .rc-retry-button {
76
- position: absolute;
77
- z-index: 50;
78
- top: 50%;
79
- left: 50%;
80
- transform: translate(-50%, -50%);
81
- border: 0;
82
- border-radius: 9999px;
83
- padding: 10px 16px;
84
- background: rgba(255, 255, 255, 0.92);
85
- color: #111827;
86
- font: inherit;
87
- font-weight: 600;
88
- cursor: pointer;
89
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
90
- }
91
-
92
- .rc-retry-button:hover {
93
- background: #ffffff;
94
- }
95
-
96
- .rc-retry-button:focus-visible {
97
- outline: 2px solid #2563eb;
98
- outline-offset: 2px;
99
- }
100
-
101
- .rc-terminated {
102
- position: absolute;
103
- z-index: 50;
104
- top: 50%;
105
- left: 50%;
106
- transform: translate(-50%, -50%);
107
- display: flex;
108
- flex-direction: column;
109
- align-items: center;
110
- gap: 4px;
111
- max-width: 240px;
112
- padding: 12px 18px;
113
- border-radius: 16px;
114
- text-align: center;
115
- font: inherit;
116
- background: rgba(255, 255, 255, 0.92);
117
- color: #111827;
118
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
119
- }
120
-
121
- .rc-terminated-title {
122
- font: inherit;
123
- font-weight: 600;
124
- }
125
-
126
- .rc-terminated-message {
127
- font: inherit;
128
- font-size: 0.8125rem;
129
- line-height: 1.3;
130
- color: #6b7280;
131
- }
132
-
133
- .rc-duo-view {
134
- position: absolute;
135
- inset: 0;
136
- }
137
- .rc-duo-mode {
138
- position: absolute;
139
- top: 12px;
140
- right: 16px;
141
- z-index: 3;
142
- display: flex;
143
- gap: 2px;
144
- padding: 3px;
145
- background: #fff;
146
- border: 1px solid #d9dde4;
147
- border-radius: 10px;
148
- }
149
- .rc-duo-mode button {
150
- border: 0;
151
- border-radius: 7px;
152
- padding: 7px 13px;
153
- font: 12px system-ui;
154
- color: #29313e;
155
- background: transparent;
156
- cursor: pointer;
157
- }
158
- .rc-duo-mode button[aria-pressed='true'] {
159
- background: #202b3c;
160
- color: white;
161
- }
162
- .rc-duo-flat-stage {
163
- position: relative;
164
- flex: 1;
165
- min-height: 160px;
166
- margin-top: 48px;
167
- }
168
- .rc-duo-flat-device {
169
- position: absolute;
170
- left: 50%;
171
- top: 50%;
172
- flex: none;
173
- transform-origin: center;
174
- }
175
- .rc-duo-flat-frame {
176
- position: absolute;
177
- inset: 0;
178
- width: 100%;
179
- height: 100%;
180
- overflow: visible;
181
- pointer-events: none;
182
- filter: drop-shadow(0 5px 6px #17202e1c);
183
- }
184
- .rc-duo-flat-screen {
185
- position: absolute;
186
- overflow: hidden;
187
- background: #090b0d;
188
- touch-action: none;
189
- outline: none;
190
- }
191
- .rc-duo-flat-screen video,
192
- .rc-duo-flat-screen canvas {
193
- position: absolute;
194
- left: 50%;
195
- top: 50%;
196
- max-width: none;
197
- pointer-events: none;
198
- }
199
- .rc-duo-flat-stage[data-folding='true'] > .rc-duo-flat-device,
200
- .rc-duo-flat-stage[data-folding='true'] > .rc-duo-hardware {
201
- visibility: hidden;
202
- pointer-events: none;
203
- }
204
- .rc-duo-fold-hold {
205
- position: absolute;
206
- left: 50%;
207
- top: 50%;
208
- pointer-events: none;
209
- }
210
- .rc-duo-fold-still {
211
- position: relative;
212
- }
213
- .rc-duo-fold-canvas {
214
- position: absolute;
215
- inset: 0;
216
- width: 100%;
217
- height: 100%;
218
- pointer-events: none;
219
- }
220
- @media (prefers-reduced-motion: reduce) {
221
- .rc-duo-fold-canvas,
222
- .rc-duo-fold-hold {
223
- display: none;
224
- }
225
- .rc-duo-flat-stage[data-folding='true'] > .rc-duo-flat-device {
226
- visibility: visible;
227
- }
228
- }
229
- .rc-duo .rc-duo-physical {
230
- position: absolute;
231
- z-index: 2;
232
- padding: 0;
233
- border-radius: 0;
234
- touch-action: none;
235
- }
236
- .rc-duo-physical[data-edge='top'] {
237
- transform: translate(-50%, -100%);
238
- }
239
- .rc-duo-physical[data-edge='right'] {
240
- transform: translate(0, -50%);
241
- }
242
- .rc-duo-physical span {
243
- position: absolute;
244
- display: block;
245
- border: 1px solid #7d8387;
246
- border-radius: 2px;
247
- box-sizing: border-box;
248
- background: linear-gradient(180deg, #747d83, #fafcfb 32%, #afb5b9 64%, #636b70);
249
- box-shadow: 0 0.5px 1px #0004;
250
- transition: transform 110ms ease;
251
- pointer-events: none;
252
- }
253
- .rc-duo-physical[data-edge='top'] span {
254
- bottom: 0;
255
- left: 50%;
256
- transform: translateX(-50%);
257
- }
258
- .rc-duo-physical[data-edge='right'] span {
259
- top: 50%;
260
- left: 0;
261
- transform: translateY(-50%);
262
- background: linear-gradient(90deg, #747d83, #fafcfb 32%, #afb5b9 64%, #636b70);
263
- }
264
- .rc-duo-physical[data-edge='top'][data-highlighted='true'] span,
265
- .rc-duo-physical[data-edge='top']:focus-visible span {
266
- transform: translate(-50%, -2px);
267
- }
268
- .rc-duo-physical[data-edge='right'][data-highlighted='true'] span,
269
- .rc-duo-physical[data-edge='right']:focus-visible span {
270
- transform: translate(2px, -50%);
271
- }
272
- .rc-duo-physical[data-edge='top'][data-pressed='true'] span {
273
- transform: translate(-50%, 0.5px);
274
- }
275
- .rc-duo-physical[data-edge='right'][data-pressed='true'] span {
276
- transform: translate(-0.5px, -50%);
277
- }
278
- .rc-duo {
279
- position: absolute;
280
- inset: 0;
281
- display: flex;
282
- flex-direction: column;
283
- overflow: hidden;
284
- background: radial-gradient(ellipse at 50% 40%, #ffffff, #e8ebee);
285
- border-radius: 16px;
286
- color: #29313e;
287
- }
288
- .rc-duo-stage {
289
- position: relative;
290
- margin-top: 48px;
291
- flex: 1;
292
- min-height: 160px;
293
- width: 100%;
294
- outline: none;
295
- touch-action: none;
296
- }
297
- .rc-duo-stage canvas {
298
- display: block;
299
- width: 100%;
300
- height: 100%;
301
- touch-action: none;
302
- }
303
- .rc-duo .rc-duo-hardware {
304
- position: absolute;
305
- display: grid;
306
- place-items: center;
307
- z-index: 1;
308
- width: 44px;
309
- height: 44px;
310
- padding: 0;
311
- transform: translate(-50%, -50%);
312
- color: #73777c;
313
- opacity: 0;
314
- pointer-events: none;
315
- transition:
316
- opacity 120ms ease,
317
- color 100ms ease;
318
- }
319
- .rc-duo .rc-duo-hardware[data-visible='true'],
320
- .rc-duo .rc-duo-hardware:focus-visible {
321
- opacity: 1;
322
- pointer-events: auto;
323
- }
324
- .rc-duo .rc-duo-hardware svg {
325
- width: var(--duo-hardware-icon-size, 24px);
326
- height: var(--duo-hardware-icon-size, 24px);
327
- transform: translate(var(--duo-hardware-icon-x, 0px), var(--duo-hardware-icon-y, 0px));
328
- }
329
- .rc-duo .rc-duo-hardware:hover,
330
- .rc-duo .rc-duo-hardware:focus-visible,
331
- .rc-duo .rc-duo-hardware[data-pressed='true'] {
332
- color: #007aff;
333
- }
334
- .rc-duo-controls {
335
- flex: none;
336
- align-self: center;
337
- width: min(540px, calc(100% - 40px));
338
- box-sizing: border-box;
339
- margin: 0 20px 20px;
340
- padding: 12px;
341
- background: rgba(255, 255, 255, 0.88);
342
- border: 1px solid #d9dde4;
343
- border-radius: 16px;
344
- box-shadow: 0 6px 25px #13203610;
345
- font:
346
- 12px system-ui,
347
- sans-serif;
348
- }
349
- .rc-duo-hinge,
350
- .rc-duo-views {
351
- display: flex;
352
- align-items: center;
353
- gap: 10px;
354
- flex-wrap: wrap;
355
- }
356
- .rc-duo-hinge {
357
- flex-wrap: nowrap;
358
- gap: 8px;
359
- }
360
- .rc-duo-hinge input {
361
- flex: 1;
362
- min-width: 30px;
363
- width: 100%;
364
- accent-color: #34435b;
365
- }
366
- .rc-duo-hinge output {
367
- min-width: 32px;
368
- font-variant-numeric: tabular-nums;
369
- }
370
- .rc-duo button {
371
- border: 0;
372
- padding: 7px 10px;
373
- border-radius: 8px;
374
- background: transparent;
375
- color: inherit;
376
- cursor: pointer;
377
- font: inherit;
378
- }
379
- .rc-duo-hinge .rc-duo-fold {
380
- flex: none;
381
- background: #202b3c;
382
- color: white;
383
- min-width: 65px;
384
- }
385
- .rc-duo-views {
386
- min-height: 29px;
387
- margin-top: 8px;
388
- gap: 2px;
389
- font-size: 11px;
390
- }
391
- .rc-duo-views button {
392
- padding: 6px 8px;
393
- }
394
- .rc-duo-view-label {
395
- padding: 6px 8px;
396
- color: #77808d;
397
- }
398
- .rc-duo .rc-duo-rotate {
399
- display: flex;
400
- align-items: center;
401
- justify-content: center;
402
- padding: 7px;
403
- border: 1px solid #d9dde4;
404
- }
405
- .rc-duo button:disabled {
406
- cursor: default;
407
- opacity: 0.5;
408
- }
409
- .rc-duo-views button[aria-pressed='true'] {
410
- background: #e5eaf0;
411
- }
412
- .rc-duo button:focus-visible,
413
- .rc-duo input:focus-visible {
414
- outline: 2px solid #4275c3;
415
- outline-offset: 2px;
416
- }
417
- .rc-duo-error {
418
- position: absolute;
419
- top: 16px;
420
- left: 16px;
421
- right: 16px;
422
- padding: 10px;
423
- border-radius: 8px;
424
- background: #fff0ee;
425
- color: #9c2e26;
426
- font: 13px system-ui;
427
- }
428
-
429
- .rc-duo .rc-duo-lock {
430
- display: inline-flex;
431
- align-items: center;
432
- gap: 6px;
433
- margin-left: auto;
434
- border: 1px solid #d3dae3;
435
- }
436
- .rc-duo-stage[data-position-locked='false'] canvas {
437
- cursor: grab;
438
- }
439
- .rc-duo-stage[data-position-locked='false'] canvas:active {
440
- cursor: grabbing;
441
- }
@@ -1,34 +0,0 @@
1
- // Covers `withAuthenticationToken` only — the rest of <RemoteControl> is
2
- // integration-tested (see vitest.config.ts).
3
- //
4
- // Assertions parse the result and read decoded parameter values, so they
5
- // don't depend on whether a space serializes as `+` or `%20`.
6
-
7
- import { describe, expect, test } from 'vitest';
8
- import { withAuthenticationToken } from './remote-control';
9
-
10
- describe('withAuthenticationToken', () => {
11
- test('adds the token alongside query parameters already on the endpoint', () => {
12
- const result = new URL(
13
- withAuthenticationToken('wss://example.com/socket?transport=webrtc', 'instance-token'),
14
- );
15
-
16
- expect(result.searchParams.get('transport')).toBe('webrtc');
17
- expect(result.searchParams.get('token')).toBe('instance-token');
18
- });
19
-
20
- test('keeps a token containing URL syntax as a single decoded value', () => {
21
- const token = 'instance token&scope=preview';
22
- const result = new URL(withAuthenticationToken('wss://example.com/socket?transport=webrtc', token));
23
-
24
- expect(result.searchParams.get('token')).toBe(token);
25
- expect(result.searchParams.get('transport')).toBe('webrtc');
26
- expect(result.searchParams.get('scope')).toBeNull();
27
- });
28
-
29
- test('replaces an existing token instead of duplicating it', () => {
30
- const result = new URL(withAuthenticationToken('wss://example.com/socket?token=stale', 'fresh-token'));
31
-
32
- expect(result.searchParams.getAll('token')).toEqual(['fresh-token']);
33
- });
34
- });