@limrun/ui 0.9.0-rc.1 → 0.9.0-rc.11

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 (46) hide show
  1. package/dist/components/inspect-overlay.d.ts +33 -0
  2. package/dist/components/remote-control.d.ts +86 -0
  3. package/dist/core/ax-fetcher.d.ts +49 -0
  4. package/dist/core/ax-tree.d.ts +99 -0
  5. package/dist/core/device-install/apple/client.d.ts +1 -0
  6. package/dist/core/device-install/apple/provisioning.d.ts +42 -31
  7. package/dist/core/device-install/apple/relay.d.ts +5 -9
  8. package/dist/core/device-install/storage/browser-storage.d.ts +19 -0
  9. package/dist/core/device-install/types.d.ts +2 -2
  10. package/dist/device-install/index.cjs +1 -9
  11. package/dist/device-install/index.js +76 -210
  12. package/dist/device-install/react.cjs +1 -1
  13. package/dist/device-install/react.js +1 -1
  14. package/dist/device-install-dialog-CjH25hnN.js +2 -0
  15. package/dist/device-install-dialog-W5Xv9kWL.mjs +443 -0
  16. package/dist/device-install-dialog.css +1 -1
  17. package/dist/hooks/use-device-install.d.ts +21 -3
  18. package/dist/index.cjs +1 -1
  19. package/dist/index.css +1 -1
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.js +1485 -778
  22. package/dist/use-device-install-Y1u6vIBB.js +31 -0
  23. package/dist/use-device-install-sDVvby1V.mjs +13627 -0
  24. package/package.json +7 -3
  25. package/src/components/device-install/device-install-dialog.css +82 -1
  26. package/src/components/device-install/device-install-dialog.tsx +319 -187
  27. package/src/components/inspect-overlay.css +223 -0
  28. package/src/components/inspect-overlay.tsx +437 -0
  29. package/src/components/remote-control.tsx +547 -9
  30. package/src/core/ax-fetcher.test.ts +418 -0
  31. package/src/core/ax-fetcher.ts +377 -0
  32. package/src/core/ax-tree.test.ts +491 -0
  33. package/src/core/ax-tree.ts +416 -0
  34. package/src/core/device-install/apple/client.ts +92 -4
  35. package/src/core/device-install/apple/provisioning.ts +67 -24
  36. package/src/core/device-install/apple/relay.ts +121 -205
  37. package/src/core/device-install/storage/browser-storage.ts +26 -1
  38. package/src/core/device-install/types.ts +2 -2
  39. package/src/demo.tsx +93 -10
  40. package/src/hooks/use-device-install.ts +766 -67
  41. package/src/index.ts +19 -1
  42. package/vitest.config.ts +23 -0
  43. package/dist/device-install-dialog-CTwVViYY.js +0 -2
  44. package/dist/device-install-dialog-zzKJu7SM.mjs +0 -328
  45. package/dist/use-device-install-CgrOKKyi.mjs +0 -13042
  46. package/dist/use-device-install-DDKRf6IL.js +0 -23
package/src/demo.tsx CHANGED
@@ -1,17 +1,39 @@
1
1
  import { useState, useRef } from 'react';
2
2
  import { createRoot } from 'react-dom/client';
3
3
  import { RemoteControl, RemoteControlHandle } from './components/remote-control';
4
+ import { AxSnapshot } from './core/ax-tree';
5
+
6
+ type InspectChoice = 'off' | 'hover-only' | 'select';
7
+
8
+ // Pre-fill from query string so the developer testing the demo can deeplink
9
+ // `?url=...&token=...&inspect=select&autoconnect=1`. Nothing is persisted.
10
+ const initialParams = new URLSearchParams(window.location.search);
11
+ const initialUrl = initialParams.get('url') || 'ws://localhost:8833/signaling';
12
+ const initialToken = initialParams.get('token') || 'token';
13
+ const initialPlatformParam = initialParams.get('platform');
14
+ const initialPlatform: 'ios' | 'android' = initialPlatformParam === 'android' ? 'android' : 'ios';
15
+ const initialInspect = (initialParams.get('inspect') as InspectChoice | null) ?? 'off';
16
+ const initialAutoconnect =
17
+ initialParams.get('autoconnect') === '1' && initialParams.has('url') && initialParams.has('token');
4
18
 
5
19
  function Demo() {
6
- const [url, setUrl] = useState('ws://localhost:8833/signaling');
7
- const [token, setToken] = useState('token');
8
- const [platform, setPlatform] = useState<'ios' | 'android'>('ios');
9
- const [isConnected, setIsConnected] = useState(false);
20
+ const [url, setUrl] = useState(initialUrl);
21
+ const [token, setToken] = useState(initialToken);
22
+ const [platform, setPlatform] = useState<'ios' | 'android'>(initialPlatform);
23
+ const [isConnected, setIsConnected] = useState(initialAutoconnect);
10
24
  const [key, setKey] = useState(0);
11
25
  const [showDebugInfo, setShowDebugInfo] = useState(false);
26
+ const [inspectChoice, setInspectChoice] = useState<InspectChoice>(initialInspect);
27
+ const [latestSnapshot, setLatestSnapshot] = useState<AxSnapshot | null>(null);
28
+ const [latestSelection, setLatestSelection] = useState<string | null>(null);
12
29
 
13
30
  const remoteControlRef = useRef<RemoteControlHandle>(null);
14
31
 
32
+ const inspectModeProp: boolean | 'hover-only' | undefined =
33
+ inspectChoice === 'off' ? undefined
34
+ : inspectChoice === 'hover-only' ? 'hover-only'
35
+ : true;
36
+
15
37
  const handleConnect = () => {
16
38
  if (url) {
17
39
  setIsConnected(true);
@@ -112,6 +134,19 @@ function Demo() {
112
134
  </label>
113
135
  </div>
114
136
 
137
+ <div className="control-group">
138
+ <label htmlFor="inspect-mode">Inspect Mode</label>
139
+ <select
140
+ id="inspect-mode"
141
+ value={inspectChoice}
142
+ onChange={(e) => setInspectChoice(e.target.value as InspectChoice)}
143
+ >
144
+ <option value="off">Off</option>
145
+ <option value="hover-only">Hover-only (input still works)</option>
146
+ <option value="select">Select (click to pin, ESC to clear)</option>
147
+ </select>
148
+ </div>
149
+
115
150
  <div className="button-group">
116
151
  {!isConnected ?
117
152
  <button className="primary" onClick={handleConnect} disabled={!url}>
@@ -153,14 +188,62 @@ function Demo() {
153
188
  )}
154
189
 
155
190
  {isConnected ?
156
- <div className="device-preview">
157
- <div className="preview-item">
158
- <h3>{platform === 'ios' ? '📱 iOS with Frame' : '🤖 Android (No Frame)'}</h3>
159
- <div className="device-wrapper">
160
- <RemoteControl key={key} ref={remoteControlRef} url={url} token={token} />
191
+ <>
192
+ <div className="device-preview">
193
+ <div className="preview-item">
194
+ <h3>{platform === 'ios' ? '📱 iOS with Frame' : '🤖 Android (No Frame)'}</h3>
195
+ <div className="device-wrapper">
196
+ <RemoteControl
197
+ key={key}
198
+ ref={remoteControlRef}
199
+ url={url}
200
+ token={token}
201
+ inspectMode={inspectModeProp}
202
+ onAxSnapshotChange={setLatestSnapshot}
203
+ onInspectSelectionChange={(sel) =>
204
+ setLatestSelection(
205
+ sel ?
206
+ `${sel.element.role || sel.element.type} · ${sel.element.label || '(no label)'}`
207
+ : null,
208
+ )
209
+ }
210
+ />
211
+ </div>
161
212
  </div>
162
213
  </div>
163
- </div>
214
+
215
+ {inspectChoice !== 'off' && (
216
+ <div
217
+ style={{
218
+ marginTop: '20px',
219
+ background: '#0f172a',
220
+ color: '#e2e8f0',
221
+ border: '1px solid #1e293b',
222
+ borderRadius: '8px',
223
+ padding: '12px 14px',
224
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
225
+ fontSize: '12px',
226
+ }}
227
+ >
228
+ <div
229
+ style={{
230
+ fontWeight: 600,
231
+ marginBottom: '6px',
232
+ display: 'flex',
233
+ gap: '12px',
234
+ flexWrap: 'wrap',
235
+ }}
236
+ >
237
+ <span>Inspect debug (demo-only)</span>
238
+ <span style={{ color: '#94a3b8', fontWeight: 400 }}>
239
+ elements: {latestSnapshot?.elements.length ?? 0} · screen:{' '}
240
+ {latestSnapshot ? `${latestSnapshot.screen.width}×${latestSnapshot.screen.height}` : '—'}{' '}
241
+ · platform: {latestSnapshot?.platform ?? '—'} · selection: {latestSelection ?? '(none)'}
242
+ </span>
243
+ </div>
244
+ </div>
245
+ )}
246
+ </>
164
247
  : <div
165
248
  style={{
166
249
  textAlign: 'center',