@qontinui/ui-bridge 0.2.0 → 0.3.1

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 (140) hide show
  1. package/dist/ai/index.d.mts +312 -155
  2. package/dist/ai/index.d.ts +312 -155
  3. package/dist/ai/index.js +2363 -67
  4. package/dist/ai/index.js.map +1 -1
  5. package/dist/ai/index.mjs +2328 -68
  6. package/dist/ai/index.mjs.map +1 -1
  7. package/dist/annotations/index.d.mts +218 -0
  8. package/dist/annotations/index.d.ts +218 -0
  9. package/dist/annotations/index.js +246 -0
  10. package/dist/annotations/index.js.map +1 -0
  11. package/dist/annotations/index.mjs +241 -0
  12. package/dist/annotations/index.mjs.map +1 -0
  13. package/dist/assertions-BSR3afVr.d.ts +161 -0
  14. package/dist/assertions-CTw1hfOx.d.mts +161 -0
  15. package/dist/babel-plugin/index.js +504 -0
  16. package/dist/babel-plugin/index.js.map +1 -0
  17. package/dist/babel-plugin/index.mjs +488 -0
  18. package/dist/babel-plugin/index.mjs.map +1 -0
  19. package/dist/browser-capture-Bms60T6f.d.mts +47 -0
  20. package/dist/browser-capture-CsTU29mb.d.ts +47 -0
  21. package/dist/control/index.d.mts +26 -7
  22. package/dist/control/index.d.ts +26 -7
  23. package/dist/control/index.js +276 -48
  24. package/dist/control/index.js.map +1 -1
  25. package/dist/control/index.mjs +276 -48
  26. package/dist/control/index.mjs.map +1 -1
  27. package/dist/core/index.d.mts +115 -44
  28. package/dist/core/index.d.ts +115 -44
  29. package/dist/core/index.js +0 -1560
  30. package/dist/core/index.js.map +1 -1
  31. package/dist/core/index.mjs +1 -1549
  32. package/dist/core/index.mjs.map +1 -1
  33. package/dist/debug/index.d.mts +5 -3
  34. package/dist/debug/index.d.ts +5 -3
  35. package/dist/debug/index.js +925 -1
  36. package/dist/debug/index.js.map +1 -1
  37. package/dist/debug/index.mjs +924 -2
  38. package/dist/debug/index.mjs.map +1 -1
  39. package/dist/index.d.mts +13 -9
  40. package/dist/index.d.ts +13 -9
  41. package/dist/index.js +8310 -3777
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.mjs +8246 -3766
  44. package/dist/index.mjs.map +1 -1
  45. package/dist/{metrics-NC3csD0R.d.mts → metrics-DuA2qIIz.d.mts} +2 -2
  46. package/dist/{metrics-C9XRi_mL.d.ts → metrics-KFAAKNEB.d.ts} +2 -2
  47. package/dist/native/control/index.js +448 -0
  48. package/dist/native/control/index.js.map +1 -0
  49. package/dist/native/control/index.mjs +445 -0
  50. package/dist/native/control/index.mjs.map +1 -0
  51. package/dist/native/core/index.js +486 -0
  52. package/dist/native/core/index.js.map +1 -0
  53. package/dist/native/core/index.mjs +475 -0
  54. package/dist/native/core/index.mjs.map +1 -0
  55. package/dist/native/debug/index.js +408 -0
  56. package/dist/native/debug/index.js.map +1 -0
  57. package/dist/native/debug/index.mjs +406 -0
  58. package/dist/native/debug/index.mjs.map +1 -0
  59. package/dist/native/index.js +2232 -0
  60. package/dist/native/index.js.map +1 -0
  61. package/dist/native/index.mjs +2204 -0
  62. package/dist/native/index.mjs.map +1 -0
  63. package/dist/native/react/index.js +1377 -0
  64. package/dist/native/react/index.js.map +1 -0
  65. package/dist/native/react/index.mjs +1365 -0
  66. package/dist/native/react/index.mjs.map +1 -0
  67. package/dist/native/server/index.js +440 -0
  68. package/dist/native/server/index.js.map +1 -0
  69. package/dist/native/server/index.mjs +435 -0
  70. package/dist/native/server/index.mjs.map +1 -0
  71. package/dist/react/index.d.mts +121 -9
  72. package/dist/react/index.d.ts +121 -9
  73. package/dist/react/index.js +2239 -91
  74. package/dist/react/index.js.map +1 -1
  75. package/dist/react/index.mjs +2239 -92
  76. package/dist/react/index.mjs.map +1 -1
  77. package/dist/{registry-CIEDjbQ9.d.ts → registry-C6dDtn1v.d.ts} +34 -15
  78. package/dist/{registry-SsSDq46X.d.mts → registry-POtcxnal.d.mts} +34 -15
  79. package/dist/render-log/index.d.mts +1 -1
  80. package/dist/render-log/index.d.ts +1 -1
  81. package/dist/server/express.d.mts +37 -0
  82. package/dist/server/express.d.ts +37 -0
  83. package/dist/server/express.js +298 -0
  84. package/dist/server/express.js.map +1 -0
  85. package/dist/server/express.mjs +294 -0
  86. package/dist/server/express.mjs.map +1 -0
  87. package/dist/server/handlers.d.mts +124 -0
  88. package/dist/server/handlers.d.ts +124 -0
  89. package/dist/server/handlers.js +7183 -0
  90. package/dist/server/handlers.js.map +1 -0
  91. package/dist/server/handlers.mjs +7180 -0
  92. package/dist/server/handlers.mjs.map +1 -0
  93. package/dist/server/index.d.mts +12 -0
  94. package/dist/server/index.d.ts +12 -0
  95. package/dist/server/index.js +8384 -0
  96. package/dist/server/index.js.map +1 -0
  97. package/dist/server/index.mjs +8369 -0
  98. package/dist/server/index.mjs.map +1 -0
  99. package/dist/server/nextjs.d.mts +128 -0
  100. package/dist/server/nextjs.d.ts +128 -0
  101. package/dist/server/nextjs.js +390 -0
  102. package/dist/server/nextjs.js.map +1 -0
  103. package/dist/server/nextjs.mjs +385 -0
  104. package/dist/server/nextjs.mjs.map +1 -0
  105. package/dist/server/standalone.d.mts +7 -0
  106. package/dist/server/standalone.d.ts +7 -0
  107. package/dist/server/standalone.js +845 -0
  108. package/dist/server/standalone.js.map +1 -0
  109. package/dist/server/standalone.mjs +841 -0
  110. package/dist/server/standalone.mjs.map +1 -0
  111. package/dist/specs/index.d.mts +365 -0
  112. package/dist/specs/index.d.ts +365 -0
  113. package/dist/specs/index.js +2809 -0
  114. package/dist/specs/index.js.map +1 -0
  115. package/dist/specs/index.mjs +2786 -0
  116. package/dist/specs/index.mjs.map +1 -0
  117. package/dist/standalone-B6GLIEmR.d.ts +216 -0
  118. package/dist/standalone-CjdYqj3P.d.mts +216 -0
  119. package/dist/swc-plugin/index.d.mts +79 -0
  120. package/dist/swc-plugin/index.d.ts +79 -0
  121. package/dist/swc-plugin/index.js +15 -0
  122. package/dist/swc-plugin/index.js.map +1 -0
  123. package/dist/swc-plugin/index.mjs +9 -0
  124. package/dist/swc-plugin/index.mjs.map +1 -0
  125. package/dist/types-B2EfvEaq.d.ts +236 -0
  126. package/dist/{types-Dr6tH-bm.d.mts → types-C7gVYRnF.d.ts} +72 -2
  127. package/dist/{types-oCTrRxSw.d.ts → types-CJGrBEhC.d.mts} +72 -2
  128. package/dist/types-CebMQj76.d.ts +1275 -0
  129. package/dist/types-D_ypYl3T.d.mts +1275 -0
  130. package/dist/types-UBtp7R0u.d.mts +132 -0
  131. package/dist/types-UBtp7R0u.d.ts +132 -0
  132. package/dist/types-gO696T_t.d.mts +236 -0
  133. package/dist/{types-CPMbN_Iw.d.mts → types-suaYwWWg.d.mts} +519 -152
  134. package/dist/{types-CPMbN_Iw.d.ts → types-suaYwWWg.d.ts} +519 -152
  135. package/package.json +123 -4
  136. package/swc-plugin-wasm/ui_bridge_swc_plugin.wasm +0 -0
  137. package/dist/types-BvCfFuEV.d.ts +0 -534
  138. package/dist/types-CFT3Dnx4.d.mts +0 -534
  139. package/dist/websocket-client-CX4QJesI.d.ts +0 -124
  140. package/dist/websocket-client-C_Na0OSp.d.mts +0 -124
@@ -0,0 +1,2232 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var reactNative = require('react-native');
6
+
7
+ // src/native/core/registry.ts
8
+ function inferActions(type) {
9
+ const baseActions = ["focus", "blur"];
10
+ switch (type) {
11
+ case "button":
12
+ case "touchable":
13
+ case "pressable":
14
+ return [...baseActions, "press", "longPress", "doubleTap"];
15
+ case "input":
16
+ return [...baseActions, "press", "type", "clear"];
17
+ case "text":
18
+ return [...baseActions, "press", "longPress"];
19
+ case "view":
20
+ return [...baseActions, "press"];
21
+ case "scroll":
22
+ return [...baseActions, "scroll", "swipe"];
23
+ case "list":
24
+ return [...baseActions, "scroll", "swipe"];
25
+ case "listItem":
26
+ return [...baseActions, "press", "longPress", "swipe"];
27
+ case "switch":
28
+ case "checkbox":
29
+ return [...baseActions, "press", "toggle"];
30
+ case "radio":
31
+ return [...baseActions, "press"];
32
+ case "image":
33
+ return [...baseActions, "press", "longPress"];
34
+ case "modal":
35
+ return ["focus", "blur"];
36
+ case "custom":
37
+ default:
38
+ return [...baseActions, "press"];
39
+ }
40
+ }
41
+ var NativeUIBridgeRegistry = class {
42
+ constructor(config = {}) {
43
+ this.elements = /* @__PURE__ */ new Map();
44
+ this.components = /* @__PURE__ */ new Map();
45
+ this.workflows = /* @__PURE__ */ new Map();
46
+ this.eventListeners = /* @__PURE__ */ new Map();
47
+ this.config = config;
48
+ }
49
+ // ============================================================================
50
+ // Element Management
51
+ // ============================================================================
52
+ /**
53
+ * Register a native element
54
+ */
55
+ registerElement(id, ref, options = {}) {
56
+ const {
57
+ type = "custom",
58
+ label,
59
+ actions = inferActions(type),
60
+ customActions,
61
+ props,
62
+ treePath = id,
63
+ testId,
64
+ accessibilityLabel
65
+ } = options;
66
+ const getState = () => {
67
+ const element = ref.current;
68
+ if (!element) {
69
+ return {
70
+ mounted: false,
71
+ visible: false,
72
+ enabled: false,
73
+ focused: false,
74
+ layout: null
75
+ };
76
+ }
77
+ const stored = this.elements.get(id);
78
+ if (stored && stored.getState !== getState) {
79
+ return stored.getState();
80
+ }
81
+ return {
82
+ mounted: true,
83
+ visible: true,
84
+ enabled: true,
85
+ focused: false,
86
+ layout: null
87
+ };
88
+ };
89
+ const getIdentifier = () => ({
90
+ uiId: id,
91
+ testId: testId || id,
92
+ accessibilityLabel,
93
+ treePath
94
+ });
95
+ const registered = {
96
+ id,
97
+ ref,
98
+ type,
99
+ label,
100
+ actions,
101
+ customActions,
102
+ props,
103
+ getState,
104
+ getIdentifier,
105
+ registeredAt: Date.now(),
106
+ mounted: true
107
+ };
108
+ this.elements.set(id, registered);
109
+ this.emit("element:registered", { id, type, label });
110
+ if (this.config.verbose) {
111
+ console.log(`[ui-bridge-native] Registered element: ${id} (${type})`);
112
+ }
113
+ return registered;
114
+ }
115
+ /**
116
+ * Unregister an element
117
+ */
118
+ unregisterElement(id) {
119
+ const element = this.elements.get(id);
120
+ if (element) {
121
+ this.elements.delete(id);
122
+ this.emit("element:unregistered", { id });
123
+ if (this.config.verbose) {
124
+ console.log(`[ui-bridge-native] Unregistered element: ${id}`);
125
+ }
126
+ }
127
+ }
128
+ /**
129
+ * Get a registered element
130
+ */
131
+ getElement(id) {
132
+ return this.elements.get(id);
133
+ }
134
+ /**
135
+ * Get all registered elements
136
+ */
137
+ getAllElements() {
138
+ return Array.from(this.elements.values());
139
+ }
140
+ /**
141
+ * Update element state
142
+ */
143
+ updateElementState(id, state) {
144
+ const element = this.elements.get(id);
145
+ if (element) {
146
+ const currentState = element.getState();
147
+ const newState = { ...currentState, ...state };
148
+ const updated = {
149
+ ...element,
150
+ getState: () => newState
151
+ };
152
+ this.elements.set(id, updated);
153
+ this.emit("element:stateChanged", { id, state: newState });
154
+ }
155
+ }
156
+ /**
157
+ * Update element props (for action execution)
158
+ */
159
+ updateElementProps(id, props) {
160
+ const element = this.elements.get(id);
161
+ if (element) {
162
+ const updated = {
163
+ ...element,
164
+ props: { ...element.props, ...props }
165
+ };
166
+ this.elements.set(id, updated);
167
+ }
168
+ }
169
+ /**
170
+ * Find element by testID
171
+ */
172
+ findByTestId(testId) {
173
+ for (const element of this.elements.values()) {
174
+ const identifier = element.getIdentifier();
175
+ if (identifier.testId === testId) {
176
+ return element;
177
+ }
178
+ }
179
+ return void 0;
180
+ }
181
+ /**
182
+ * Find elements by type
183
+ */
184
+ findByType(type) {
185
+ return Array.from(this.elements.values()).filter((e) => e.type === type);
186
+ }
187
+ // ============================================================================
188
+ // Component Management
189
+ // ============================================================================
190
+ /**
191
+ * Register a component
192
+ */
193
+ registerComponent(id, options) {
194
+ const { name, description, actions = [], elementIds } = options;
195
+ const registered = {
196
+ id,
197
+ name,
198
+ description,
199
+ actions: actions.map((a) => ({
200
+ id: a.id,
201
+ label: a.label,
202
+ description: a.description,
203
+ handler: a.handler
204
+ })),
205
+ elementIds,
206
+ registeredAt: Date.now(),
207
+ mounted: true
208
+ };
209
+ this.components.set(id, registered);
210
+ this.emit("component:registered", { id, name });
211
+ if (this.config.verbose) {
212
+ console.log(`[ui-bridge-native] Registered component: ${id} (${name})`);
213
+ }
214
+ return registered;
215
+ }
216
+ /**
217
+ * Unregister a component
218
+ */
219
+ unregisterComponent(id) {
220
+ const component = this.components.get(id);
221
+ if (component) {
222
+ this.components.delete(id);
223
+ this.emit("component:unregistered", { id });
224
+ if (this.config.verbose) {
225
+ console.log(`[ui-bridge-native] Unregistered component: ${id}`);
226
+ }
227
+ }
228
+ }
229
+ /**
230
+ * Get a registered component
231
+ */
232
+ getComponent(id) {
233
+ return this.components.get(id);
234
+ }
235
+ /**
236
+ * Get all registered components
237
+ */
238
+ getAllComponents() {
239
+ return Array.from(this.components.values());
240
+ }
241
+ // ============================================================================
242
+ // Workflow Management
243
+ // ============================================================================
244
+ /**
245
+ * Register a workflow
246
+ */
247
+ registerWorkflow(workflow) {
248
+ this.workflows.set(workflow.id, workflow);
249
+ if (this.config.verbose) {
250
+ console.log(`[ui-bridge-native] Registered workflow: ${workflow.id}`);
251
+ }
252
+ }
253
+ /**
254
+ * Unregister a workflow
255
+ */
256
+ unregisterWorkflow(id) {
257
+ this.workflows.delete(id);
258
+ }
259
+ /**
260
+ * Get a workflow
261
+ */
262
+ getWorkflow(id) {
263
+ return this.workflows.get(id);
264
+ }
265
+ /**
266
+ * Get all workflows
267
+ */
268
+ getAllWorkflows() {
269
+ return Array.from(this.workflows.values());
270
+ }
271
+ // ============================================================================
272
+ // Event System
273
+ // ============================================================================
274
+ /**
275
+ * Subscribe to events
276
+ */
277
+ on(type, listener) {
278
+ if (!this.eventListeners.has(type)) {
279
+ this.eventListeners.set(type, /* @__PURE__ */ new Set());
280
+ }
281
+ this.eventListeners.get(type).add(listener);
282
+ return () => this.off(type, listener);
283
+ }
284
+ /**
285
+ * Unsubscribe from events
286
+ */
287
+ off(type, listener) {
288
+ this.eventListeners.get(type)?.delete(listener);
289
+ }
290
+ /**
291
+ * Emit an event
292
+ */
293
+ emit(type, data) {
294
+ const event = {
295
+ type,
296
+ timestamp: Date.now(),
297
+ data
298
+ };
299
+ const listeners = this.eventListeners.get(type);
300
+ if (listeners) {
301
+ for (const listener of listeners) {
302
+ try {
303
+ listener(event);
304
+ } catch (error2) {
305
+ console.error(`[ui-bridge-native] Event listener error:`, error2);
306
+ }
307
+ }
308
+ }
309
+ if (this.config.onEvent) {
310
+ try {
311
+ this.config.onEvent(event);
312
+ } catch (error2) {
313
+ console.error(`[ui-bridge-native] Global event handler error:`, error2);
314
+ }
315
+ }
316
+ }
317
+ // ============================================================================
318
+ // Snapshots
319
+ // ============================================================================
320
+ /**
321
+ * Create a snapshot of the current state
322
+ */
323
+ createSnapshot() {
324
+ return {
325
+ timestamp: Date.now(),
326
+ elements: this.getAllElements().map((e) => ({
327
+ id: e.id,
328
+ type: e.type,
329
+ label: e.label,
330
+ identifier: e.getIdentifier(),
331
+ state: e.getState(),
332
+ actions: e.actions,
333
+ customActions: e.customActions ? Object.keys(e.customActions) : void 0
334
+ })),
335
+ components: this.getAllComponents().map((c) => ({
336
+ id: c.id,
337
+ name: c.name,
338
+ description: c.description,
339
+ actions: c.actions.map((a) => a.id),
340
+ elementIds: c.elementIds
341
+ })),
342
+ workflows: this.getAllWorkflows().map((w) => ({
343
+ id: w.id,
344
+ name: w.name,
345
+ description: w.description,
346
+ stepCount: w.steps.length
347
+ }))
348
+ };
349
+ }
350
+ /**
351
+ * Get registry statistics
352
+ */
353
+ getStats() {
354
+ return {
355
+ elements: this.elements.size,
356
+ components: this.components.size,
357
+ workflows: this.workflows.size
358
+ };
359
+ }
360
+ /**
361
+ * Clear all registrations
362
+ */
363
+ clear() {
364
+ this.elements.clear();
365
+ this.components.clear();
366
+ this.workflows.clear();
367
+ if (this.config.verbose) {
368
+ console.log(`[ui-bridge-native] Registry cleared`);
369
+ }
370
+ }
371
+ };
372
+ var globalRegistry = null;
373
+ function setGlobalRegistry(registry) {
374
+ globalRegistry = registry;
375
+ }
376
+ function getGlobalRegistry() {
377
+ return globalRegistry;
378
+ }
379
+ function resetGlobalRegistry() {
380
+ globalRegistry?.clear();
381
+ globalRegistry = null;
382
+ }
383
+
384
+ // src/native/core/element-identifier.ts
385
+ function createNativeElementIdentifier(id, options = {}) {
386
+ return {
387
+ uiId: id,
388
+ testId: options.testId || id,
389
+ accessibilityLabel: options.accessibilityLabel,
390
+ accessibilityHint: options.accessibilityHint,
391
+ treePath: options.treePath || id
392
+ };
393
+ }
394
+ function findElementByIdentifier(identifier) {
395
+ const registry = getGlobalRegistry();
396
+ if (!registry) return null;
397
+ if (typeof identifier === "string") {
398
+ const byId = registry.getElement(identifier);
399
+ if (byId) return byId;
400
+ const byTestId = registry.findByTestId(identifier);
401
+ if (byTestId) return byTestId;
402
+ return findByPattern(registry, identifier);
403
+ }
404
+ if (identifier.uiId) {
405
+ const byId = registry.getElement(identifier.uiId);
406
+ if (byId) return byId;
407
+ }
408
+ if (identifier.testId) {
409
+ const byTestId = registry.findByTestId(identifier.testId);
410
+ if (byTestId) return byTestId;
411
+ }
412
+ return null;
413
+ }
414
+ function findByPattern(registry, pattern) {
415
+ if (!registry) return null;
416
+ const regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
417
+ const regex = new RegExp(`^${regexPattern}$`, "i");
418
+ for (const element of registry.getAllElements()) {
419
+ const identifier = element.getIdentifier();
420
+ if (identifier.testId && regex.test(identifier.testId)) {
421
+ return element;
422
+ }
423
+ if (identifier.uiId && regex.test(identifier.uiId)) {
424
+ return element;
425
+ }
426
+ if (identifier.treePath && regex.test(identifier.treePath)) {
427
+ return element;
428
+ }
429
+ if (identifier.accessibilityLabel && regex.test(identifier.accessibilityLabel)) {
430
+ return element;
431
+ }
432
+ }
433
+ return null;
434
+ }
435
+ function findAllByPattern(pattern) {
436
+ const registry = getGlobalRegistry();
437
+ if (!registry) return [];
438
+ const regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
439
+ const regex = new RegExp(`^${regexPattern}$`, "i");
440
+ const results = [];
441
+ for (const element of registry.getAllElements()) {
442
+ const identifier = element.getIdentifier();
443
+ if (identifier.testId && regex.test(identifier.testId) || identifier.uiId && regex.test(identifier.uiId) || identifier.treePath && regex.test(identifier.treePath) || identifier.accessibilityLabel && regex.test(identifier.accessibilityLabel)) {
444
+ results.push(element);
445
+ }
446
+ }
447
+ return results;
448
+ }
449
+ function buildTreePath(componentPath, elementIndex) {
450
+ let path = componentPath.join("/");
451
+ if (elementIndex !== void 0) {
452
+ path += `[${elementIndex}]`;
453
+ }
454
+ return path;
455
+ }
456
+ function parseTreePath(treePath) {
457
+ const indexMatch = treePath.match(/\[(\d+)\]$/);
458
+ const index = indexMatch ? parseInt(indexMatch[1], 10) : void 0;
459
+ const pathWithoutIndex = treePath.replace(/\[\d+\]$/, "");
460
+ const components = pathWithoutIndex.split("/").filter(Boolean);
461
+ return { components, index };
462
+ }
463
+ function matchesIdentifier(identifier, criteria) {
464
+ if (criteria.uiId && identifier.uiId !== criteria.uiId) {
465
+ return false;
466
+ }
467
+ if (criteria.testId && identifier.testId !== criteria.testId) {
468
+ return false;
469
+ }
470
+ if (criteria.accessibilityLabel && identifier.accessibilityLabel !== criteria.accessibilityLabel) {
471
+ return false;
472
+ }
473
+ if (criteria.treePath && identifier.treePath !== criteria.treePath) {
474
+ return false;
475
+ }
476
+ return true;
477
+ }
478
+
479
+ // src/native/control/action-executor.ts
480
+ var DEFAULT_WAIT_OPTIONS = {
481
+ visible: true,
482
+ enabled: true,
483
+ focused: false,
484
+ state: {},
485
+ timeout: 1e4,
486
+ interval: 100
487
+ };
488
+ function sleep(ms) {
489
+ return new Promise((resolve) => setTimeout(resolve, ms));
490
+ }
491
+ var DefaultNativeActionExecutor = class {
492
+ constructor(registry) {
493
+ this.registry = registry;
494
+ }
495
+ /**
496
+ * Execute an action on an element
497
+ */
498
+ async executeAction(elementId, request) {
499
+ const startTime = Date.now();
500
+ let waitDurationMs = 0;
501
+ try {
502
+ let registered = this.registry.getElement(elementId);
503
+ if (!registered) {
504
+ registered = findElementByIdentifier(elementId) ?? void 0;
505
+ }
506
+ if (!registered) {
507
+ return {
508
+ success: false,
509
+ error: `Element not found: ${elementId}`,
510
+ durationMs: Date.now() - startTime,
511
+ timestamp: Date.now(),
512
+ requestId: request.requestId
513
+ };
514
+ }
515
+ if (request.waitOptions) {
516
+ const waitResult = await this.waitForElementInternal(registered.id, request.waitOptions);
517
+ waitDurationMs = waitResult.waitedMs;
518
+ if (!waitResult.met) {
519
+ return {
520
+ success: false,
521
+ error: waitResult.error || "Wait condition not met",
522
+ durationMs: Date.now() - startTime,
523
+ timestamp: Date.now(),
524
+ requestId: request.requestId,
525
+ waitDurationMs
526
+ };
527
+ }
528
+ }
529
+ const result = await this.performAction(registered, request.action, request.params);
530
+ return {
531
+ success: true,
532
+ elementState: registered.getState(),
533
+ result,
534
+ durationMs: Date.now() - startTime,
535
+ timestamp: Date.now(),
536
+ requestId: request.requestId,
537
+ waitDurationMs
538
+ };
539
+ } catch (error2) {
540
+ return {
541
+ success: false,
542
+ error: error2 instanceof Error ? error2.message : String(error2),
543
+ stack: error2 instanceof Error ? error2.stack : void 0,
544
+ durationMs: Date.now() - startTime,
545
+ timestamp: Date.now(),
546
+ requestId: request.requestId,
547
+ waitDurationMs
548
+ };
549
+ }
550
+ }
551
+ /**
552
+ * Perform an action on an element
553
+ */
554
+ async performAction(element, action, params) {
555
+ if (!element) {
556
+ throw new Error("Element not found");
557
+ }
558
+ const props = element.props || {};
559
+ if (element.customActions && action in element.customActions) {
560
+ return element.customActions[action].handler(params);
561
+ }
562
+ switch (action) {
563
+ case "press":
564
+ return this.performPress(props, params);
565
+ case "longPress":
566
+ return this.performLongPress(props, params);
567
+ case "doubleTap":
568
+ return this.performDoubleTap(props);
569
+ case "type":
570
+ return this.performType(element, props, params);
571
+ case "clear":
572
+ return this.performClear(element, props);
573
+ case "focus":
574
+ return this.performFocus(element);
575
+ case "blur":
576
+ return this.performBlur(element);
577
+ case "scroll":
578
+ return this.performScroll(props, params);
579
+ case "swipe":
580
+ return this.performSwipe(props, params);
581
+ case "toggle":
582
+ return this.performToggle(props);
583
+ default:
584
+ throw new Error(`Unknown action: ${action}`);
585
+ }
586
+ }
587
+ /**
588
+ * Perform press action
589
+ */
590
+ async performPress(props, params) {
591
+ const handlers = ["onPress", "onPressIn", "onResponderRelease"];
592
+ for (const handler of handlers) {
593
+ if (typeof props[handler] === "function") {
594
+ const event = this.createPressEvent(params);
595
+ props[handler](event);
596
+ return;
597
+ }
598
+ }
599
+ throw new Error("No press handler found on element");
600
+ }
601
+ /**
602
+ * Perform long press action
603
+ */
604
+ async performLongPress(props, params) {
605
+ if (typeof props.onLongPress === "function") {
606
+ const event = this.createPressEvent(params);
607
+ props.onLongPress(event);
608
+ return;
609
+ }
610
+ throw new Error("No long press handler found on element");
611
+ }
612
+ /**
613
+ * Perform double tap action
614
+ */
615
+ async performDoubleTap(props) {
616
+ if (typeof props.onDoubleTap === "function") {
617
+ props.onDoubleTap();
618
+ return;
619
+ }
620
+ if (typeof props.onPress === "function") {
621
+ const event = this.createPressEvent();
622
+ props.onPress(event);
623
+ await sleep(50);
624
+ props.onPress(event);
625
+ return;
626
+ }
627
+ throw new Error("No press handler found for double tap");
628
+ }
629
+ /**
630
+ * Perform type action
631
+ */
632
+ async performType(element, props, params) {
633
+ if (!params?.text) {
634
+ throw new Error("Type action requires text parameter");
635
+ }
636
+ if (params.clearFirst) {
637
+ await this.performClear(element, props);
638
+ }
639
+ if (params.delay && params.delay > 0) {
640
+ const currentValue = element?.getState().value || "";
641
+ for (const char of params.text) {
642
+ const newValue = currentValue + char;
643
+ if (typeof props.onChangeText === "function") {
644
+ props.onChangeText(newValue);
645
+ }
646
+ await sleep(params.delay);
647
+ }
648
+ } else {
649
+ if (typeof props.onChangeText === "function") {
650
+ props.onChangeText(params.text);
651
+ } else if (typeof props.onChange === "function") {
652
+ props.onChange({
653
+ nativeEvent: { text: params.text }
654
+ });
655
+ } else {
656
+ throw new Error("No text change handler found on element");
657
+ }
658
+ }
659
+ if (element) {
660
+ this.registry.updateElementState(element.id, { value: params.text });
661
+ }
662
+ }
663
+ /**
664
+ * Perform clear action
665
+ */
666
+ async performClear(element, props) {
667
+ if (typeof props.onChangeText === "function") {
668
+ props.onChangeText("");
669
+ } else if (typeof props.onChange === "function") {
670
+ props.onChange({
671
+ nativeEvent: { text: "" }
672
+ });
673
+ }
674
+ if (element) {
675
+ this.registry.updateElementState(element.id, { value: "" });
676
+ }
677
+ }
678
+ /**
679
+ * Perform focus action
680
+ */
681
+ async performFocus(element) {
682
+ if (element?.ref.current && "focus" in element.ref.current) {
683
+ element.ref.current.focus();
684
+ }
685
+ if (element) {
686
+ this.registry.updateElementState(element.id, { focused: true });
687
+ }
688
+ }
689
+ /**
690
+ * Perform blur action
691
+ */
692
+ async performBlur(element) {
693
+ if (element?.ref.current && "blur" in element.ref.current) {
694
+ element.ref.current.blur();
695
+ }
696
+ if (element) {
697
+ this.registry.updateElementState(element.id, { focused: false });
698
+ }
699
+ }
700
+ /**
701
+ * Perform scroll action
702
+ */
703
+ async performScroll(props, params) {
704
+ if (typeof props.onScroll === "function") {
705
+ const event = {
706
+ nativeEvent: {
707
+ contentOffset: params?.offset || { x: 0, y: 0 }
708
+ }
709
+ };
710
+ props.onScroll(event);
711
+ }
712
+ }
713
+ /**
714
+ * Perform swipe action
715
+ */
716
+ async performSwipe(props, params) {
717
+ if (!params?.direction) {
718
+ throw new Error("Swipe action requires direction parameter");
719
+ }
720
+ const handlerMap = {
721
+ left: "onSwipeLeft",
722
+ right: "onSwipeRight",
723
+ up: "onSwipeUp",
724
+ down: "onSwipeDown"
725
+ };
726
+ const handler = handlerMap[params.direction];
727
+ if (handler && typeof props[handler] === "function") {
728
+ props[handler]();
729
+ return;
730
+ }
731
+ if (typeof props.onSwipe === "function") {
732
+ props.onSwipe(params.direction);
733
+ }
734
+ }
735
+ /**
736
+ * Perform toggle action
737
+ */
738
+ async performToggle(props) {
739
+ if (typeof props.onValueChange === "function") {
740
+ const currentValue = props.value;
741
+ props.onValueChange(!currentValue);
742
+ return;
743
+ }
744
+ if (typeof props.onPress === "function") {
745
+ props.onPress();
746
+ return;
747
+ }
748
+ throw new Error("No toggle handler found on element");
749
+ }
750
+ /**
751
+ * Create a synthetic press event
752
+ */
753
+ createPressEvent(params) {
754
+ return {
755
+ nativeEvent: {
756
+ locationX: params?.position?.x ?? 0,
757
+ locationY: params?.position?.y ?? 0,
758
+ timestamp: Date.now()
759
+ },
760
+ persist: () => {
761
+ }
762
+ };
763
+ }
764
+ /**
765
+ * Execute a component action
766
+ */
767
+ async executeComponentAction(componentId, request) {
768
+ const startTime = Date.now();
769
+ try {
770
+ const component = this.registry.getComponent(componentId);
771
+ if (!component) {
772
+ return {
773
+ success: false,
774
+ error: `Component not found: ${componentId}`,
775
+ durationMs: Date.now() - startTime,
776
+ timestamp: Date.now(),
777
+ requestId: request.requestId
778
+ };
779
+ }
780
+ const action = component.actions.find((a) => a.id === request.action);
781
+ if (!action) {
782
+ return {
783
+ success: false,
784
+ error: `Action not found: ${request.action}`,
785
+ durationMs: Date.now() - startTime,
786
+ timestamp: Date.now(),
787
+ requestId: request.requestId
788
+ };
789
+ }
790
+ const result = await action.handler(request.params);
791
+ return {
792
+ success: true,
793
+ result,
794
+ durationMs: Date.now() - startTime,
795
+ timestamp: Date.now(),
796
+ requestId: request.requestId
797
+ };
798
+ } catch (error2) {
799
+ return {
800
+ success: false,
801
+ error: error2 instanceof Error ? error2.message : String(error2),
802
+ stack: error2 instanceof Error ? error2.stack : void 0,
803
+ durationMs: Date.now() - startTime,
804
+ timestamp: Date.now(),
805
+ requestId: request.requestId
806
+ };
807
+ }
808
+ }
809
+ /**
810
+ * Find elements
811
+ */
812
+ async find(request) {
813
+ const startTime = Date.now();
814
+ const allElements = this.registry.getAllElements();
815
+ let filtered = allElements;
816
+ if (request.types && request.types.length > 0) {
817
+ filtered = filtered.filter((e) => request.types.includes(e.type));
818
+ }
819
+ if (request.testIdPattern) {
820
+ const regex = new RegExp(request.testIdPattern.replace(/\*/g, ".*").replace(/\?/g, "."));
821
+ filtered = filtered.filter((e) => {
822
+ const identifier = e.getIdentifier();
823
+ return identifier.testId && regex.test(identifier.testId);
824
+ });
825
+ }
826
+ if (request.accessibilityLabelPattern) {
827
+ const regex = new RegExp(
828
+ request.accessibilityLabelPattern.replace(/\*/g, ".*").replace(/\?/g, ".")
829
+ );
830
+ filtered = filtered.filter((e) => {
831
+ const identifier = e.getIdentifier();
832
+ return identifier.accessibilityLabel && regex.test(identifier.accessibilityLabel);
833
+ });
834
+ }
835
+ if (request.visibleOnly) {
836
+ filtered = filtered.filter((e) => e.getState().visible);
837
+ }
838
+ if (request.limit && request.limit > 0) {
839
+ filtered = filtered.slice(0, request.limit);
840
+ }
841
+ const elements = filtered.map((e) => ({
842
+ id: e.id,
843
+ type: e.type,
844
+ identifier: e.getIdentifier(),
845
+ state: e.getState(),
846
+ actions: e.actions,
847
+ label: e.label
848
+ }));
849
+ return {
850
+ elements,
851
+ total: elements.length,
852
+ durationMs: Date.now() - startTime,
853
+ timestamp: Date.now()
854
+ };
855
+ }
856
+ /**
857
+ * Wait for element conditions
858
+ */
859
+ async waitForElement(elementId, options) {
860
+ return this.waitForElementInternal(elementId, options);
861
+ }
862
+ /**
863
+ * Internal wait implementation
864
+ */
865
+ async waitForElementInternal(elementId, options) {
866
+ const opts = { ...DEFAULT_WAIT_OPTIONS, ...options };
867
+ const startTime = Date.now();
868
+ while (Date.now() - startTime < opts.timeout) {
869
+ const element = this.registry.getElement(elementId);
870
+ if (!element) {
871
+ await sleep(opts.interval);
872
+ continue;
873
+ }
874
+ const state = element.getState();
875
+ let conditionsMet = true;
876
+ if (opts.visible && !state.visible) {
877
+ conditionsMet = false;
878
+ }
879
+ if (opts.enabled && !state.enabled) {
880
+ conditionsMet = false;
881
+ }
882
+ if (opts.focused && !state.focused) {
883
+ conditionsMet = false;
884
+ }
885
+ if (opts.state && Object.keys(opts.state).length > 0) {
886
+ const stateRecord = state;
887
+ for (const [key, value] of Object.entries(opts.state)) {
888
+ if (stateRecord[key] !== value) {
889
+ conditionsMet = false;
890
+ break;
891
+ }
892
+ }
893
+ }
894
+ if (conditionsMet) {
895
+ return {
896
+ met: true,
897
+ waitedMs: Date.now() - startTime,
898
+ state
899
+ };
900
+ }
901
+ await sleep(opts.interval);
902
+ }
903
+ return {
904
+ met: false,
905
+ waitedMs: Date.now() - startTime,
906
+ error: `Timeout waiting for conditions on element: ${elementId}`
907
+ };
908
+ }
909
+ };
910
+ function createNativeActionExecutor(registry) {
911
+ return new DefaultNativeActionExecutor(registry);
912
+ }
913
+ var UIBridgeNativeContext = react.createContext(null);
914
+ function UIBridgeNativeProvider({
915
+ children,
916
+ features = {},
917
+ config = {},
918
+ onEvent
919
+ }) {
920
+ const registryRef = react.useRef(null);
921
+ const executorRef = react.useRef(null);
922
+ const [serverRunning, setServerRunning] = react.useState(false);
923
+ if (!registryRef.current) {
924
+ registryRef.current = new NativeUIBridgeRegistry({
925
+ verbose: config.verbose,
926
+ onEvent
927
+ });
928
+ setGlobalRegistry(registryRef.current);
929
+ }
930
+ const registry = registryRef.current;
931
+ if (!executorRef.current) {
932
+ executorRef.current = createNativeActionExecutor(registry);
933
+ }
934
+ const executor = executorRef.current;
935
+ const startServer = react.useCallback(async () => {
936
+ if (!features.server) {
937
+ console.warn("[ui-bridge-native] Server feature not enabled");
938
+ return;
939
+ }
940
+ console.log(`[ui-bridge-native] Would start HTTP server on port ${config.serverPort || 9876}`);
941
+ setServerRunning(true);
942
+ }, [features.server, config.serverPort]);
943
+ const stopServer = react.useCallback(() => {
944
+ console.log("[ui-bridge-native] Would stop HTTP server");
945
+ setServerRunning(false);
946
+ }, []);
947
+ react.useEffect(() => {
948
+ if (features.server) {
949
+ startServer();
950
+ return () => stopServer();
951
+ }
952
+ }, [features.server, startServer, stopServer]);
953
+ react.useEffect(() => {
954
+ return () => {
955
+ stopServer();
956
+ resetGlobalRegistry();
957
+ };
958
+ }, [stopServer]);
959
+ const getElements = react.useCallback(() => registry.getAllElements(), [registry]);
960
+ const getComponents = react.useCallback(() => registry.getAllComponents(), [registry]);
961
+ const createSnapshot = react.useCallback(() => registry.createSnapshot(), [registry]);
962
+ const on = react.useCallback(
963
+ (type, listener) => registry.on(type, listener),
964
+ [registry]
965
+ );
966
+ const off = react.useCallback(
967
+ (type, listener) => registry.off(type, listener),
968
+ [registry]
969
+ );
970
+ const contextValue = react.useMemo(
971
+ () => ({
972
+ features,
973
+ config,
974
+ registry,
975
+ executor,
976
+ getElements,
977
+ getComponents,
978
+ createSnapshot,
979
+ on,
980
+ off,
981
+ initialized: true,
982
+ serverRunning,
983
+ startServer,
984
+ stopServer
985
+ }),
986
+ [
987
+ features,
988
+ config,
989
+ registry,
990
+ executor,
991
+ getElements,
992
+ getComponents,
993
+ createSnapshot,
994
+ on,
995
+ off,
996
+ serverRunning,
997
+ startServer,
998
+ stopServer
999
+ ]
1000
+ );
1001
+ return /* @__PURE__ */ jsxRuntime.jsx(UIBridgeNativeContext.Provider, { value: contextValue, children });
1002
+ }
1003
+ function useUIBridgeNative() {
1004
+ const context = react.useContext(UIBridgeNativeContext);
1005
+ if (!context) {
1006
+ throw new Error("useUIBridgeNative must be used within a UIBridgeNativeProvider");
1007
+ }
1008
+ return context;
1009
+ }
1010
+ function useUIBridgeNativeOptional() {
1011
+ return react.useContext(UIBridgeNativeContext);
1012
+ }
1013
+ var useUIBridgeNativeRequired = useUIBridgeNative;
1014
+ function useUIElement(options) {
1015
+ const bridge = useUIBridgeNativeOptional();
1016
+ const ref = react.useRef(null);
1017
+ const [registered, setRegistered] = react.useState(false);
1018
+ const [_layout, setLayout] = react.useState(null);
1019
+ const propsRef = react.useRef({});
1020
+ const {
1021
+ id,
1022
+ type = "custom",
1023
+ label,
1024
+ actions,
1025
+ customActions,
1026
+ autoRegister = true,
1027
+ onStateChange,
1028
+ parentPath
1029
+ } = options;
1030
+ const treePath = parentPath ? `${parentPath}/${id}` : id;
1031
+ const bridgeProps = react.useMemo(
1032
+ () => ({
1033
+ testID: id,
1034
+ accessibilityLabel: label
1035
+ }),
1036
+ [id, label]
1037
+ );
1038
+ const register = react.useCallback(() => {
1039
+ if (!bridge || registered) return;
1040
+ bridge.registry.registerElement(id, ref, {
1041
+ type,
1042
+ label,
1043
+ actions,
1044
+ customActions,
1045
+ treePath,
1046
+ testId: id,
1047
+ accessibilityLabel: label
1048
+ });
1049
+ setRegistered(true);
1050
+ }, [bridge, registered, id, type, label, actions, customActions, treePath]);
1051
+ const unregister = react.useCallback(() => {
1052
+ if (!bridge || !registered) return;
1053
+ bridge.registry.unregisterElement(id);
1054
+ setRegistered(false);
1055
+ }, [bridge, registered, id]);
1056
+ const onLayout = react.useCallback(
1057
+ (event) => {
1058
+ const { x, y, width, height } = event.nativeEvent.layout;
1059
+ if (ref.current && "measureInWindow" in ref.current) {
1060
+ ref.current.measureInWindow((pageX, pageY) => {
1061
+ const newLayout = {
1062
+ x,
1063
+ y,
1064
+ width,
1065
+ height,
1066
+ pageX,
1067
+ pageY
1068
+ };
1069
+ setLayout(newLayout);
1070
+ if (bridge && registered) {
1071
+ const newState = {
1072
+ mounted: true,
1073
+ visible: width > 0 && height > 0,
1074
+ enabled: true,
1075
+ focused: false,
1076
+ layout: newLayout
1077
+ };
1078
+ bridge.registry.updateElementState(id, newState);
1079
+ onStateChange?.(newState);
1080
+ }
1081
+ });
1082
+ } else {
1083
+ const newLayout = {
1084
+ x,
1085
+ y,
1086
+ width,
1087
+ height,
1088
+ pageX: x,
1089
+ pageY: y
1090
+ };
1091
+ setLayout(newLayout);
1092
+ if (bridge && registered) {
1093
+ const newState = {
1094
+ mounted: true,
1095
+ visible: width > 0 && height > 0,
1096
+ enabled: true,
1097
+ focused: false,
1098
+ layout: newLayout
1099
+ };
1100
+ bridge.registry.updateElementState(id, newState);
1101
+ onStateChange?.(newState);
1102
+ }
1103
+ }
1104
+ },
1105
+ [bridge, registered, id, onStateChange]
1106
+ );
1107
+ react.useEffect(() => {
1108
+ if (autoRegister) {
1109
+ register();
1110
+ }
1111
+ return () => {
1112
+ unregister();
1113
+ };
1114
+ }, [autoRegister, register, unregister]);
1115
+ react.useCallback(
1116
+ (props) => {
1117
+ propsRef.current = { ...propsRef.current, ...props };
1118
+ if (bridge && registered) {
1119
+ bridge.registry.updateElementProps(id, props);
1120
+ }
1121
+ },
1122
+ [bridge, registered, id]
1123
+ );
1124
+ const getState = react.useCallback(() => {
1125
+ if (!bridge) return null;
1126
+ const element = bridge.registry.getElement(id);
1127
+ return element?.getState() || null;
1128
+ }, [bridge, id]);
1129
+ const getIdentifier = react.useCallback(() => {
1130
+ if (!bridge) return null;
1131
+ const element = bridge.registry.getElement(id);
1132
+ return element?.getIdentifier() || null;
1133
+ }, [bridge, id]);
1134
+ const trigger = react.useCallback(
1135
+ async (action, params) => {
1136
+ if (!bridge) {
1137
+ throw new Error("UI Bridge Native not available");
1138
+ }
1139
+ const response = await bridge.executor.executeAction(id, {
1140
+ action,
1141
+ params
1142
+ });
1143
+ if (!response.success) {
1144
+ throw new Error(response.error || "Action failed");
1145
+ }
1146
+ },
1147
+ [bridge, id]
1148
+ );
1149
+ const registeredElement = react.useMemo(() => {
1150
+ if (!bridge) return null;
1151
+ return bridge.registry.getElement(id) || null;
1152
+ }, [bridge, id, registered]);
1153
+ return {
1154
+ ref,
1155
+ onLayout,
1156
+ bridgeProps,
1157
+ registered,
1158
+ getState,
1159
+ getIdentifier,
1160
+ trigger,
1161
+ register,
1162
+ unregister,
1163
+ registeredElement
1164
+ };
1165
+ }
1166
+ function useUIElementWithProps(options) {
1167
+ const elementReturn = useUIElement(options);
1168
+ const bridge = useUIBridgeNativeOptional();
1169
+ const captureProps = react.useCallback(
1170
+ (props) => {
1171
+ if (bridge && elementReturn.registered) {
1172
+ bridge.registry.updateElementProps(options.id, props);
1173
+ }
1174
+ },
1175
+ [bridge, elementReturn.registered, options.id]
1176
+ );
1177
+ return {
1178
+ ...elementReturn,
1179
+ captureProps
1180
+ };
1181
+ }
1182
+ function useUIComponent(options) {
1183
+ const bridge = useUIBridgeNativeOptional();
1184
+ const registeredRef = react.useRef(false);
1185
+ const actionsRef = react.useRef(options.actions || []);
1186
+ const elementIdsRef = react.useRef(options.elementIds || []);
1187
+ const { id, name, description, autoRegister = true } = options;
1188
+ react.useEffect(() => {
1189
+ actionsRef.current = options.actions || [];
1190
+ elementIdsRef.current = options.elementIds || [];
1191
+ }, [options.actions, options.elementIds]);
1192
+ const register = react.useCallback(() => {
1193
+ if (!bridge || registeredRef.current) return;
1194
+ bridge.registry.registerComponent(id, {
1195
+ name,
1196
+ description,
1197
+ actions: actionsRef.current.map((a) => ({
1198
+ id: a.id,
1199
+ label: a.label,
1200
+ description: a.description,
1201
+ handler: a.handler
1202
+ })),
1203
+ elementIds: elementIdsRef.current
1204
+ });
1205
+ registeredRef.current = true;
1206
+ }, [bridge, id, name, description]);
1207
+ const unregister = react.useCallback(() => {
1208
+ if (!bridge || !registeredRef.current) return;
1209
+ bridge.registry.unregisterComponent(id);
1210
+ registeredRef.current = false;
1211
+ }, [bridge, id]);
1212
+ const executeAction = react.useCallback(
1213
+ async (actionId, params) => {
1214
+ if (!bridge) {
1215
+ throw new Error("UI Bridge Native not available");
1216
+ }
1217
+ const response = await bridge.executor.executeComponentAction(id, {
1218
+ action: actionId,
1219
+ params
1220
+ });
1221
+ if (!response.success) {
1222
+ throw new Error(response.error || "Action failed");
1223
+ }
1224
+ return response.result;
1225
+ },
1226
+ [bridge, id]
1227
+ );
1228
+ const updateActions = react.useCallback(
1229
+ (actions) => {
1230
+ actionsRef.current = actions;
1231
+ if (registeredRef.current && bridge) {
1232
+ bridge.registry.unregisterComponent(id);
1233
+ registeredRef.current = false;
1234
+ register();
1235
+ }
1236
+ },
1237
+ [bridge, id, register]
1238
+ );
1239
+ const addElement = react.useCallback((elementId) => {
1240
+ if (!elementIdsRef.current.includes(elementId)) {
1241
+ elementIdsRef.current = [...elementIdsRef.current, elementId];
1242
+ }
1243
+ }, []);
1244
+ const removeElement = react.useCallback((elementId) => {
1245
+ elementIdsRef.current = elementIdsRef.current.filter((eid) => eid !== elementId);
1246
+ }, []);
1247
+ react.useEffect(() => {
1248
+ if (autoRegister) {
1249
+ register();
1250
+ }
1251
+ return () => {
1252
+ unregister();
1253
+ };
1254
+ }, [autoRegister, register, unregister]);
1255
+ const registeredComponent = react.useMemo(() => {
1256
+ if (!bridge) return null;
1257
+ return bridge.registry.getComponent(id) || null;
1258
+ }, [bridge, id, registeredRef.current]);
1259
+ return {
1260
+ registered: registeredRef.current,
1261
+ executeAction,
1262
+ register,
1263
+ unregister,
1264
+ updateActions,
1265
+ addElement,
1266
+ removeElement,
1267
+ registeredComponent
1268
+ };
1269
+ }
1270
+ function useUIComponentAction(handler, deps) {
1271
+ return react.useCallback(handler, deps);
1272
+ }
1273
+ function useUIBridge() {
1274
+ const bridge = useUIBridgeNativeOptional();
1275
+ const available = bridge !== null;
1276
+ const initialized = bridge?.initialized ?? false;
1277
+ const elements = react.useMemo(() => bridge ? bridge.getElements() : [], [bridge]);
1278
+ const components = react.useMemo(() => bridge ? bridge.getComponents() : [], [bridge]);
1279
+ const workflows = react.useMemo(() => bridge ? bridge.registry.getAllWorkflows() : [], [bridge]);
1280
+ const createSnapshot = react.useCallback(() => {
1281
+ if (!bridge) {
1282
+ return {
1283
+ timestamp: Date.now(),
1284
+ elements: [],
1285
+ components: [],
1286
+ workflows: []
1287
+ };
1288
+ }
1289
+ return bridge.createSnapshot();
1290
+ }, [bridge]);
1291
+ const executeAction = react.useCallback(
1292
+ async (elementId, request) => {
1293
+ if (!bridge) {
1294
+ return {
1295
+ success: false,
1296
+ error: "UI Bridge not available",
1297
+ durationMs: 0,
1298
+ timestamp: Date.now()
1299
+ };
1300
+ }
1301
+ return bridge.executor.executeAction(elementId, request);
1302
+ },
1303
+ [bridge]
1304
+ );
1305
+ const executeComponentAction = react.useCallback(
1306
+ async (componentId, request) => {
1307
+ if (!bridge) {
1308
+ return {
1309
+ success: false,
1310
+ error: "UI Bridge not available",
1311
+ durationMs: 0,
1312
+ timestamp: Date.now()
1313
+ };
1314
+ }
1315
+ return bridge.executor.executeComponentAction(componentId, request);
1316
+ },
1317
+ [bridge]
1318
+ );
1319
+ const find = react.useCallback(
1320
+ async (request) => {
1321
+ if (!bridge) {
1322
+ return {
1323
+ elements: [],
1324
+ total: 0,
1325
+ durationMs: 0,
1326
+ timestamp: Date.now()
1327
+ };
1328
+ }
1329
+ return bridge.executor.find(request || {});
1330
+ },
1331
+ [bridge]
1332
+ );
1333
+ const getElement = react.useCallback((id) => bridge?.registry.getElement(id), [bridge]);
1334
+ const getComponent = react.useCallback((id) => bridge?.registry.getComponent(id), [bridge]);
1335
+ const getElementState = react.useCallback(
1336
+ (id) => {
1337
+ const element = bridge?.registry.getElement(id);
1338
+ return element?.getState() ?? null;
1339
+ },
1340
+ [bridge]
1341
+ );
1342
+ const registerWorkflow = react.useCallback(
1343
+ (workflow) => {
1344
+ bridge?.registry.registerWorkflow(workflow);
1345
+ },
1346
+ [bridge]
1347
+ );
1348
+ const unregisterWorkflow = react.useCallback(
1349
+ (id) => {
1350
+ bridge?.registry.unregisterWorkflow(id);
1351
+ },
1352
+ [bridge]
1353
+ );
1354
+ return {
1355
+ available,
1356
+ initialized,
1357
+ elements,
1358
+ components,
1359
+ workflows,
1360
+ createSnapshot,
1361
+ executeAction,
1362
+ executeComponentAction,
1363
+ find,
1364
+ getElement,
1365
+ getComponent,
1366
+ getElementState,
1367
+ registerWorkflow,
1368
+ unregisterWorkflow
1369
+ };
1370
+ }
1371
+ function useUIBridgeRequired() {
1372
+ const result = useUIBridge();
1373
+ if (!result.available) {
1374
+ throw new Error("useUIBridgeRequired must be used within a UIBridgeNativeProvider");
1375
+ }
1376
+ return result;
1377
+ }
1378
+
1379
+ // src/native/server/types.ts
1380
+ var UI_BRIDGE_NATIVE_ROUTES = {
1381
+ // Control - Elements
1382
+ GET_ELEMENTS: {
1383
+ method: "GET",
1384
+ path: "/ui-bridge/control/elements",
1385
+ description: "List all registered elements"
1386
+ },
1387
+ GET_ELEMENT: {
1388
+ method: "GET",
1389
+ path: "/ui-bridge/control/element/:id",
1390
+ description: "Get element details"
1391
+ },
1392
+ GET_ELEMENT_STATE: {
1393
+ method: "GET",
1394
+ path: "/ui-bridge/control/element/:id/state",
1395
+ description: "Get element state"
1396
+ },
1397
+ EXECUTE_ACTION: {
1398
+ method: "POST",
1399
+ path: "/ui-bridge/control/element/:id/action",
1400
+ description: "Execute action on element"
1401
+ },
1402
+ // Control - Components
1403
+ GET_COMPONENTS: {
1404
+ method: "GET",
1405
+ path: "/ui-bridge/control/components",
1406
+ description: "List all registered components"
1407
+ },
1408
+ GET_COMPONENT: {
1409
+ method: "GET",
1410
+ path: "/ui-bridge/control/component/:id",
1411
+ description: "Get component details"
1412
+ },
1413
+ EXECUTE_COMPONENT_ACTION: {
1414
+ method: "POST",
1415
+ path: "/ui-bridge/control/component/:id/action/:actionId",
1416
+ description: "Execute component action"
1417
+ },
1418
+ // Discovery
1419
+ FIND: {
1420
+ method: "POST",
1421
+ path: "/ui-bridge/control/find",
1422
+ description: "Find elements matching criteria"
1423
+ },
1424
+ GET_SNAPSHOT: {
1425
+ method: "GET",
1426
+ path: "/ui-bridge/control/snapshot",
1427
+ description: "Get full bridge snapshot"
1428
+ },
1429
+ // Workflows
1430
+ GET_WORKFLOWS: {
1431
+ method: "GET",
1432
+ path: "/ui-bridge/control/workflows",
1433
+ description: "List all workflows"
1434
+ },
1435
+ RUN_WORKFLOW: {
1436
+ method: "POST",
1437
+ path: "/ui-bridge/control/workflow/:id/run",
1438
+ description: "Run a workflow"
1439
+ },
1440
+ // Page Navigation
1441
+ PAGE_REFRESH: {
1442
+ method: "POST",
1443
+ path: "/ui-bridge/control/page/refresh",
1444
+ description: "Refresh the current page"
1445
+ },
1446
+ PAGE_NAVIGATE: {
1447
+ method: "POST",
1448
+ path: "/ui-bridge/control/page/navigate",
1449
+ description: "Navigate to a URL"
1450
+ },
1451
+ PAGE_GO_BACK: {
1452
+ method: "POST",
1453
+ path: "/ui-bridge/control/page/back",
1454
+ description: "Go back in navigation history"
1455
+ },
1456
+ PAGE_GO_FORWARD: {
1457
+ method: "POST",
1458
+ path: "/ui-bridge/control/page/forward",
1459
+ description: "Go forward in navigation history"
1460
+ },
1461
+ // Health
1462
+ HEALTH: {
1463
+ method: "GET",
1464
+ path: "/ui-bridge/health",
1465
+ description: "Health check"
1466
+ }
1467
+ };
1468
+
1469
+ // src/native/server/handlers.ts
1470
+ function success(data) {
1471
+ return {
1472
+ success: true,
1473
+ data,
1474
+ timestamp: Date.now()
1475
+ };
1476
+ }
1477
+ function error(message, code) {
1478
+ return {
1479
+ success: false,
1480
+ error: message,
1481
+ code,
1482
+ timestamp: Date.now()
1483
+ };
1484
+ }
1485
+ function createServerHandlers(registry, executor) {
1486
+ return {
1487
+ // Elements
1488
+ getElements: async () => {
1489
+ const elements = registry.getAllElements().map((e) => ({
1490
+ id: e.id,
1491
+ type: e.type,
1492
+ label: e.label,
1493
+ identifier: e.getIdentifier(),
1494
+ state: e.getState(),
1495
+ actions: e.actions,
1496
+ customActions: e.customActions ? Object.keys(e.customActions) : void 0
1497
+ }));
1498
+ return success({ elements });
1499
+ },
1500
+ getElement: async (ctx) => {
1501
+ const { id } = ctx.params;
1502
+ const element = registry.getElement(id);
1503
+ if (!element) {
1504
+ return error(`Element not found: ${id}`, "ELEMENT_NOT_FOUND");
1505
+ }
1506
+ return success({
1507
+ element: {
1508
+ id: element.id,
1509
+ type: element.type,
1510
+ label: element.label,
1511
+ identifier: element.getIdentifier(),
1512
+ state: element.getState(),
1513
+ actions: element.actions,
1514
+ customActions: element.customActions ? Object.keys(element.customActions) : void 0
1515
+ }
1516
+ });
1517
+ },
1518
+ getElementState: async (ctx) => {
1519
+ const { id } = ctx.params;
1520
+ const element = registry.getElement(id);
1521
+ if (!element) {
1522
+ return error(`Element not found: ${id}`, "ELEMENT_NOT_FOUND");
1523
+ }
1524
+ return success({ state: element.getState() });
1525
+ },
1526
+ executeAction: async (ctx) => {
1527
+ const { id } = ctx.params;
1528
+ const body = ctx.body;
1529
+ if (!body?.action) {
1530
+ return error("Action is required", "INVALID_REQUEST");
1531
+ }
1532
+ const response = await executor.executeAction(id, {
1533
+ action: body.action,
1534
+ params: body.params,
1535
+ waitOptions: body.waitOptions
1536
+ });
1537
+ if (!response.success) {
1538
+ return error(response.error || "Action failed", "ACTION_FAILED");
1539
+ }
1540
+ return success(response);
1541
+ },
1542
+ // Components
1543
+ getComponents: async () => {
1544
+ const components = registry.getAllComponents().map((c) => ({
1545
+ id: c.id,
1546
+ name: c.name,
1547
+ description: c.description,
1548
+ actions: c.actions.map((a) => ({ id: a.id, label: a.label })),
1549
+ elementIds: c.elementIds
1550
+ }));
1551
+ return success({ components });
1552
+ },
1553
+ getComponent: async (ctx) => {
1554
+ const { id } = ctx.params;
1555
+ const component = registry.getComponent(id);
1556
+ if (!component) {
1557
+ return error(`Component not found: ${id}`, "COMPONENT_NOT_FOUND");
1558
+ }
1559
+ return success({
1560
+ component: {
1561
+ id: component.id,
1562
+ name: component.name,
1563
+ description: component.description,
1564
+ actions: component.actions.map((a) => ({
1565
+ id: a.id,
1566
+ label: a.label,
1567
+ description: a.description
1568
+ })),
1569
+ elementIds: component.elementIds
1570
+ }
1571
+ });
1572
+ },
1573
+ executeComponentAction: async (ctx) => {
1574
+ const { id, actionId } = ctx.params;
1575
+ const body = ctx.body;
1576
+ const response = await executor.executeComponentAction(id, {
1577
+ action: actionId,
1578
+ params: body?.params
1579
+ });
1580
+ if (!response.success) {
1581
+ return error(response.error || "Action failed", "ACTION_FAILED");
1582
+ }
1583
+ return success(response);
1584
+ },
1585
+ // Discovery
1586
+ find: async (ctx) => {
1587
+ const body = ctx.body;
1588
+ const response = await executor.find({
1589
+ types: body?.types,
1590
+ testIdPattern: body?.testIdPattern,
1591
+ accessibilityLabelPattern: body?.accessibilityLabelPattern,
1592
+ visibleOnly: body?.visibleOnly,
1593
+ limit: body?.limit
1594
+ });
1595
+ return success(response);
1596
+ },
1597
+ getSnapshot: async () => {
1598
+ const snapshot = registry.createSnapshot();
1599
+ return success(snapshot);
1600
+ },
1601
+ // Workflows
1602
+ getWorkflows: async () => {
1603
+ const workflows = registry.getAllWorkflows().map((w) => ({
1604
+ id: w.id,
1605
+ name: w.name,
1606
+ description: w.description,
1607
+ stepCount: w.steps.length
1608
+ }));
1609
+ return success({ workflows });
1610
+ },
1611
+ runWorkflow: async (ctx) => {
1612
+ const { id } = ctx.params;
1613
+ const workflow = registry.getWorkflow(id);
1614
+ if (!workflow) {
1615
+ return error(`Workflow not found: ${id}`, "WORKFLOW_NOT_FOUND");
1616
+ }
1617
+ return success({
1618
+ runId: `run-${Date.now()}`,
1619
+ status: "pending"
1620
+ });
1621
+ },
1622
+ // Page Navigation (stubs — React Native apps should override with their navigation provider)
1623
+ pageRefresh: async () => {
1624
+ return error("Page refresh not supported on native platform", "NOT_SUPPORTED");
1625
+ },
1626
+ pageNavigate: async () => {
1627
+ return error("Page navigation not supported on native platform", "NOT_SUPPORTED");
1628
+ },
1629
+ pageGoBack: async () => {
1630
+ return error("Page go back not supported on native platform", "NOT_SUPPORTED");
1631
+ },
1632
+ pageGoForward: async () => {
1633
+ return error("Page go forward not supported on native platform", "NOT_SUPPORTED");
1634
+ },
1635
+ // Health
1636
+ health: async () => {
1637
+ const stats = registry.getStats();
1638
+ return success({
1639
+ status: "healthy",
1640
+ timestamp: Date.now(),
1641
+ ...stats
1642
+ });
1643
+ }
1644
+ };
1645
+ }
1646
+
1647
+ // src/native/server/http-server.ts
1648
+ var NativeUIBridgeServer = class {
1649
+ constructor(registry, executor, config = {}) {
1650
+ this.registry = registry;
1651
+ this.executor = executor;
1652
+ this.running = false;
1653
+ this.config = {
1654
+ serverPort: 9876,
1655
+ cors: true,
1656
+ ...config
1657
+ };
1658
+ this.handlers = createServerHandlers(registry, executor);
1659
+ }
1660
+ /**
1661
+ * Set the server adapter
1662
+ */
1663
+ setAdapter(adapter) {
1664
+ this.adapter = adapter;
1665
+ }
1666
+ /**
1667
+ * Start the HTTP server
1668
+ */
1669
+ async start() {
1670
+ if (this.running) {
1671
+ console.warn("[ui-bridge-native] Server already running");
1672
+ return;
1673
+ }
1674
+ if (!this.adapter) {
1675
+ console.warn("[ui-bridge-native] No server adapter configured. Call setAdapter() first.");
1676
+ console.warn("[ui-bridge-native] See documentation for supported adapters.");
1677
+ return;
1678
+ }
1679
+ await this.adapter.start(this.config.serverPort, this.handleRequest.bind(this));
1680
+ this.running = true;
1681
+ console.log(`[ui-bridge-native] HTTP server started on port ${this.config.serverPort}`);
1682
+ }
1683
+ /**
1684
+ * Stop the HTTP server
1685
+ */
1686
+ async stop() {
1687
+ if (!this.running || !this.adapter) {
1688
+ return;
1689
+ }
1690
+ await this.adapter.stop();
1691
+ this.running = false;
1692
+ console.log("[ui-bridge-native] HTTP server stopped");
1693
+ }
1694
+ /**
1695
+ * Check if server is running
1696
+ */
1697
+ isRunning() {
1698
+ return this.running;
1699
+ }
1700
+ /**
1701
+ * Handle incoming HTTP request
1702
+ */
1703
+ async handleRequest(request) {
1704
+ const headers = {
1705
+ "Content-Type": "application/json"
1706
+ };
1707
+ if (this.config.cors) {
1708
+ headers["Access-Control-Allow-Origin"] = this.config.allowedOrigins ? this.config.allowedOrigins.join(",") : "*";
1709
+ headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS";
1710
+ headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization";
1711
+ }
1712
+ if (request.method === "OPTIONS") {
1713
+ return { status: 204, headers, body: "" };
1714
+ }
1715
+ try {
1716
+ const response = await this.routeRequest(request);
1717
+ return {
1718
+ status: response.success ? 200 : 400,
1719
+ headers,
1720
+ body: JSON.stringify(response)
1721
+ };
1722
+ } catch (error2) {
1723
+ const errorResponse = {
1724
+ success: false,
1725
+ error: error2 instanceof Error ? error2.message : "Internal server error",
1726
+ code: "INTERNAL_ERROR",
1727
+ timestamp: Date.now()
1728
+ };
1729
+ return {
1730
+ status: 500,
1731
+ headers,
1732
+ body: JSON.stringify(errorResponse)
1733
+ };
1734
+ }
1735
+ }
1736
+ /**
1737
+ * Route request to appropriate handler
1738
+ */
1739
+ async routeRequest(request) {
1740
+ const { method, path, query, body } = request;
1741
+ const parsePath = (pattern, actual) => {
1742
+ const patternParts = pattern.split("/");
1743
+ const actualParts = actual.split("/");
1744
+ if (patternParts.length !== actualParts.length) {
1745
+ return null;
1746
+ }
1747
+ const params2 = {};
1748
+ for (let i = 0; i < patternParts.length; i++) {
1749
+ if (patternParts[i].startsWith(":")) {
1750
+ params2[patternParts[i].slice(1)] = actualParts[i];
1751
+ } else if (patternParts[i] !== actualParts[i]) {
1752
+ return null;
1753
+ }
1754
+ }
1755
+ return params2;
1756
+ };
1757
+ if (method === "GET" && path === "/ui-bridge/health") {
1758
+ return this.handlers.health({ params: {}, query, body });
1759
+ }
1760
+ if (method === "GET" && path === "/ui-bridge/control/elements") {
1761
+ return this.handlers.getElements({ params: {}, query, body });
1762
+ }
1763
+ let params = parsePath("/ui-bridge/control/element/:id", path);
1764
+ if (method === "GET" && params) {
1765
+ return this.handlers.getElement({ params, query, body });
1766
+ }
1767
+ params = parsePath("/ui-bridge/control/element/:id/state", path);
1768
+ if (method === "GET" && params) {
1769
+ return this.handlers.getElementState({ params, query, body });
1770
+ }
1771
+ params = parsePath("/ui-bridge/control/element/:id/action", path);
1772
+ if (method === "POST" && params) {
1773
+ return this.handlers.executeAction({ params, query, body });
1774
+ }
1775
+ if (method === "GET" && path === "/ui-bridge/control/components") {
1776
+ return this.handlers.getComponents({ params: {}, query, body });
1777
+ }
1778
+ params = parsePath("/ui-bridge/control/component/:id", path);
1779
+ if (method === "GET" && params) {
1780
+ return this.handlers.getComponent({ params, query, body });
1781
+ }
1782
+ params = parsePath("/ui-bridge/control/component/:id/action/:actionId", path);
1783
+ if (method === "POST" && params) {
1784
+ return this.handlers.executeComponentAction({ params, query, body });
1785
+ }
1786
+ if (method === "POST" && path === "/ui-bridge/control/find") {
1787
+ return this.handlers.find({ params: {}, query, body });
1788
+ }
1789
+ if (method === "GET" && path === "/ui-bridge/control/snapshot") {
1790
+ return this.handlers.getSnapshot({ params: {}, query, body });
1791
+ }
1792
+ if (method === "GET" && path === "/ui-bridge/control/workflows") {
1793
+ return this.handlers.getWorkflows({ params: {}, query, body });
1794
+ }
1795
+ params = parsePath("/ui-bridge/control/workflow/:id/run", path);
1796
+ if (method === "POST" && params) {
1797
+ return this.handlers.runWorkflow({ params, query, body });
1798
+ }
1799
+ return {
1800
+ success: false,
1801
+ error: `Route not found: ${method} ${path}`,
1802
+ code: "NOT_FOUND",
1803
+ timestamp: Date.now()
1804
+ };
1805
+ }
1806
+ };
1807
+ function createNativeServer(registry, executor, config) {
1808
+ return new NativeUIBridgeServer(registry, executor, config);
1809
+ }
1810
+ function ElementCard({
1811
+ element,
1812
+ onPress
1813
+ }) {
1814
+ const state = element.getState();
1815
+ const identifier = element.getIdentifier();
1816
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.TouchableOpacity, { style: styles.elementCard, onPress: () => onPress(element), children: [
1817
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.elementHeader, children: [
1818
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.elementId, children: element.id }),
1819
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.elementType, children: element.type })
1820
+ ] }),
1821
+ element.label && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.elementLabel, children: element.label }),
1822
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.stateRow, children: [
1823
+ /* @__PURE__ */ jsxRuntime.jsx(StateIndicator, { label: "Mounted", value: state.mounted }),
1824
+ /* @__PURE__ */ jsxRuntime.jsx(StateIndicator, { label: "Visible", value: state.visible }),
1825
+ /* @__PURE__ */ jsxRuntime.jsx(StateIndicator, { label: "Enabled", value: state.enabled })
1826
+ ] }),
1827
+ identifier.testId && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.testId, children: [
1828
+ "testID: ",
1829
+ identifier.testId
1830
+ ] })
1831
+ ] });
1832
+ }
1833
+ function StateIndicator({ label, value }) {
1834
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.stateIndicator, children: [
1835
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.stateDot, { backgroundColor: value ? "#4CAF50" : "#F44336" }] }),
1836
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.stateLabel, children: label })
1837
+ ] });
1838
+ }
1839
+ function ElementDetail({
1840
+ element,
1841
+ onClose
1842
+ }) {
1843
+ const state = element.getState();
1844
+ const identifier = element.getIdentifier();
1845
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.detailContainer, children: [
1846
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.detailHeader, children: [
1847
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.detailTitle, children: element.id }),
1848
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.closeButton, children: "Close" }) })
1849
+ ] }),
1850
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.ScrollView, { style: styles.detailContent, children: [
1851
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionTitle, children: "Type" }),
1852
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionValue, children: element.type }),
1853
+ element.label && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1854
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionTitle, children: "Label" }),
1855
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionValue, children: element.label })
1856
+ ] }),
1857
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionTitle, children: "State" }),
1858
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.stateSection, children: [
1859
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1860
+ "Mounted: ",
1861
+ String(state.mounted)
1862
+ ] }),
1863
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1864
+ "Visible: ",
1865
+ String(state.visible)
1866
+ ] }),
1867
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1868
+ "Enabled: ",
1869
+ String(state.enabled)
1870
+ ] }),
1871
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1872
+ "Focused: ",
1873
+ String(state.focused)
1874
+ ] }),
1875
+ state.value !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1876
+ "Value: ",
1877
+ state.value
1878
+ ] })
1879
+ ] }),
1880
+ state.layout && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1881
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionTitle, children: "Layout" }),
1882
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.stateSection, children: [
1883
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1884
+ "Position: (",
1885
+ state.layout.x,
1886
+ ", ",
1887
+ state.layout.y,
1888
+ ")"
1889
+ ] }),
1890
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1891
+ "Size: ",
1892
+ state.layout.width,
1893
+ " x ",
1894
+ state.layout.height
1895
+ ] }),
1896
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1897
+ "Page: (",
1898
+ state.layout.pageX,
1899
+ ", ",
1900
+ state.layout.pageY,
1901
+ ")"
1902
+ ] })
1903
+ ] })
1904
+ ] }),
1905
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionTitle, children: "Identifier" }),
1906
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.stateSection, children: [
1907
+ identifier.uiId && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1908
+ "uiId: ",
1909
+ identifier.uiId
1910
+ ] }),
1911
+ identifier.testId && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1912
+ "testId: ",
1913
+ identifier.testId
1914
+ ] }),
1915
+ identifier.accessibilityLabel && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1916
+ "a11yLabel: ",
1917
+ identifier.accessibilityLabel
1918
+ ] }),
1919
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: styles.stateText, children: [
1920
+ "treePath: ",
1921
+ identifier.treePath
1922
+ ] })
1923
+ ] }),
1924
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionTitle, children: "Actions" }),
1925
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.actionsSection, children: element.actions.map((action) => /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.actionBadge, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.actionText, children: action }) }, action)) }),
1926
+ element.customActions && Object.keys(element.customActions).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1927
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionTitle, children: "Custom Actions" }),
1928
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.actionsSection, children: Object.keys(element.customActions).map((action) => /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.actionBadge, styles.customActionBadge], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.actionText, children: action }) }, action)) })
1929
+ ] })
1930
+ ] })
1931
+ ] });
1932
+ }
1933
+ function UIBridgeInspector({
1934
+ visible = false,
1935
+ onClose,
1936
+ togglePosition = "bottom-right"
1937
+ }) {
1938
+ const bridge = useUIBridgeNativeOptional();
1939
+ const [showInspector, setShowInspector] = react.useState(visible);
1940
+ const [selectedElement, setSelectedElement] = react.useState(null);
1941
+ const elements = react.useMemo(() => bridge ? bridge.getElements() : [], [bridge, showInspector]);
1942
+ const components = react.useMemo(() => bridge ? bridge.getComponents() : [], [bridge, showInspector]);
1943
+ const handleToggle = react.useCallback(() => {
1944
+ setShowInspector((prev) => !prev);
1945
+ }, []);
1946
+ const handleClose = react.useCallback(() => {
1947
+ setShowInspector(false);
1948
+ onClose?.();
1949
+ }, [onClose]);
1950
+ const handleSelectElement = react.useCallback((element) => {
1951
+ setSelectedElement(element);
1952
+ }, []);
1953
+ const handleCloseDetail = react.useCallback(() => {
1954
+ setSelectedElement(null);
1955
+ }, []);
1956
+ const toggleStyle = react.useMemo(() => {
1957
+ switch (togglePosition) {
1958
+ case "top-left":
1959
+ return { top: 50, left: 10 };
1960
+ case "top-right":
1961
+ return { top: 50, right: 10 };
1962
+ case "bottom-left":
1963
+ return { bottom: 50, left: 10 };
1964
+ case "bottom-right":
1965
+ default:
1966
+ return { bottom: 50, right: 10 };
1967
+ }
1968
+ }, [togglePosition]);
1969
+ if (!bridge) {
1970
+ return null;
1971
+ }
1972
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1973
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { style: [styles.toggleButton, toggleStyle], onPress: handleToggle, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.toggleText, children: "UI" }) }),
1974
+ /* @__PURE__ */ jsxRuntime.jsx(
1975
+ reactNative.Modal,
1976
+ {
1977
+ visible: showInspector,
1978
+ animationType: "slide",
1979
+ transparent: true,
1980
+ onRequestClose: handleClose,
1981
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.modalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.inspectorContainer, children: [
1982
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.header, children: [
1983
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.headerTitle, children: "UI Bridge Inspector" }),
1984
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: handleClose, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.closeButton, children: "X" }) })
1985
+ ] }),
1986
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.statsRow, children: [
1987
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.stat, children: [
1988
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.statValue, children: elements.length }),
1989
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.statLabel, children: "Elements" })
1990
+ ] }),
1991
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.stat, children: [
1992
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.statValue, children: components.length }),
1993
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.statLabel, children: "Components" })
1994
+ ] }),
1995
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.stat, children: [
1996
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.statValue, children: bridge.serverRunning ? "ON" : "OFF" }),
1997
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.statLabel, children: "Server" })
1998
+ ] })
1999
+ ] }),
2000
+ selectedElement ? /* @__PURE__ */ jsxRuntime.jsx(ElementDetail, { element: selectedElement, onClose: handleCloseDetail }) : /* @__PURE__ */ jsxRuntime.jsxs(reactNative.ScrollView, { style: styles.elementList, children: [
2001
+ elements.map((element) => /* @__PURE__ */ jsxRuntime.jsx(ElementCard, { element, onPress: handleSelectElement }, element.id)),
2002
+ elements.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.emptyText, children: "No elements registered yet" })
2003
+ ] })
2004
+ ] }) })
2005
+ }
2006
+ )
2007
+ ] });
2008
+ }
2009
+ var { height: screenHeight } = reactNative.Dimensions.get("window");
2010
+ var styles = reactNative.StyleSheet.create({
2011
+ toggleButton: {
2012
+ position: "absolute",
2013
+ width: 44,
2014
+ height: 44,
2015
+ borderRadius: 22,
2016
+ backgroundColor: "#2196F3",
2017
+ justifyContent: "center",
2018
+ alignItems: "center",
2019
+ shadowColor: "#000",
2020
+ shadowOffset: { width: 0, height: 2 },
2021
+ shadowOpacity: 0.25,
2022
+ shadowRadius: 4,
2023
+ elevation: 5,
2024
+ zIndex: 1e3
2025
+ },
2026
+ toggleText: {
2027
+ color: "#fff",
2028
+ fontWeight: "bold",
2029
+ fontSize: 14
2030
+ },
2031
+ modalContainer: {
2032
+ flex: 1,
2033
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
2034
+ justifyContent: "flex-end"
2035
+ },
2036
+ inspectorContainer: {
2037
+ backgroundColor: "#1e1e1e",
2038
+ borderTopLeftRadius: 16,
2039
+ borderTopRightRadius: 16,
2040
+ maxHeight: screenHeight * 0.8
2041
+ },
2042
+ header: {
2043
+ flexDirection: "row",
2044
+ justifyContent: "space-between",
2045
+ alignItems: "center",
2046
+ padding: 16,
2047
+ borderBottomWidth: 1,
2048
+ borderBottomColor: "#333"
2049
+ },
2050
+ headerTitle: {
2051
+ color: "#fff",
2052
+ fontSize: 18,
2053
+ fontWeight: "bold"
2054
+ },
2055
+ closeButton: {
2056
+ color: "#2196F3",
2057
+ fontSize: 16,
2058
+ fontWeight: "bold"
2059
+ },
2060
+ statsRow: {
2061
+ flexDirection: "row",
2062
+ padding: 12,
2063
+ borderBottomWidth: 1,
2064
+ borderBottomColor: "#333"
2065
+ },
2066
+ stat: {
2067
+ flex: 1,
2068
+ alignItems: "center"
2069
+ },
2070
+ statValue: {
2071
+ color: "#fff",
2072
+ fontSize: 20,
2073
+ fontWeight: "bold"
2074
+ },
2075
+ statLabel: {
2076
+ color: "#888",
2077
+ fontSize: 12,
2078
+ marginTop: 2
2079
+ },
2080
+ elementList: {
2081
+ padding: 12
2082
+ },
2083
+ elementCard: {
2084
+ backgroundColor: "#2d2d2d",
2085
+ borderRadius: 8,
2086
+ padding: 12,
2087
+ marginBottom: 8
2088
+ },
2089
+ elementHeader: {
2090
+ flexDirection: "row",
2091
+ justifyContent: "space-between",
2092
+ alignItems: "center"
2093
+ },
2094
+ elementId: {
2095
+ color: "#fff",
2096
+ fontSize: 14,
2097
+ fontWeight: "bold"
2098
+ },
2099
+ elementType: {
2100
+ color: "#888",
2101
+ fontSize: 12,
2102
+ backgroundColor: "#444",
2103
+ paddingHorizontal: 8,
2104
+ paddingVertical: 2,
2105
+ borderRadius: 4
2106
+ },
2107
+ elementLabel: {
2108
+ color: "#aaa",
2109
+ fontSize: 12,
2110
+ marginTop: 4
2111
+ },
2112
+ stateRow: {
2113
+ flexDirection: "row",
2114
+ marginTop: 8
2115
+ },
2116
+ stateIndicator: {
2117
+ flexDirection: "row",
2118
+ alignItems: "center",
2119
+ marginRight: 12
2120
+ },
2121
+ stateDot: {
2122
+ width: 8,
2123
+ height: 8,
2124
+ borderRadius: 4,
2125
+ marginRight: 4
2126
+ },
2127
+ stateLabel: {
2128
+ color: "#888",
2129
+ fontSize: 10
2130
+ },
2131
+ testId: {
2132
+ color: "#666",
2133
+ fontSize: 10,
2134
+ marginTop: 4,
2135
+ fontFamily: "monospace"
2136
+ },
2137
+ emptyText: {
2138
+ color: "#888",
2139
+ textAlign: "center",
2140
+ marginTop: 20
2141
+ },
2142
+ detailContainer: {
2143
+ flex: 1
2144
+ },
2145
+ detailHeader: {
2146
+ flexDirection: "row",
2147
+ justifyContent: "space-between",
2148
+ alignItems: "center",
2149
+ padding: 12,
2150
+ borderBottomWidth: 1,
2151
+ borderBottomColor: "#333"
2152
+ },
2153
+ detailTitle: {
2154
+ color: "#fff",
2155
+ fontSize: 16,
2156
+ fontWeight: "bold"
2157
+ },
2158
+ detailContent: {
2159
+ padding: 12
2160
+ },
2161
+ sectionTitle: {
2162
+ color: "#888",
2163
+ fontSize: 12,
2164
+ marginTop: 12,
2165
+ marginBottom: 4,
2166
+ textTransform: "uppercase"
2167
+ },
2168
+ sectionValue: {
2169
+ color: "#fff",
2170
+ fontSize: 14
2171
+ },
2172
+ stateSection: {
2173
+ backgroundColor: "#2d2d2d",
2174
+ borderRadius: 8,
2175
+ padding: 8
2176
+ },
2177
+ stateText: {
2178
+ color: "#ddd",
2179
+ fontSize: 12,
2180
+ fontFamily: "monospace",
2181
+ marginBottom: 2
2182
+ },
2183
+ actionsSection: {
2184
+ flexDirection: "row",
2185
+ flexWrap: "wrap"
2186
+ },
2187
+ actionBadge: {
2188
+ backgroundColor: "#2196F3",
2189
+ paddingHorizontal: 8,
2190
+ paddingVertical: 4,
2191
+ borderRadius: 4,
2192
+ marginRight: 6,
2193
+ marginBottom: 6
2194
+ },
2195
+ customActionBadge: {
2196
+ backgroundColor: "#9C27B0"
2197
+ },
2198
+ actionText: {
2199
+ color: "#fff",
2200
+ fontSize: 12
2201
+ }
2202
+ });
2203
+
2204
+ exports.DefaultNativeActionExecutor = DefaultNativeActionExecutor;
2205
+ exports.NativeUIBridgeRegistry = NativeUIBridgeRegistry;
2206
+ exports.NativeUIBridgeServer = NativeUIBridgeServer;
2207
+ exports.UIBridgeInspector = UIBridgeInspector;
2208
+ exports.UIBridgeNativeProvider = UIBridgeNativeProvider;
2209
+ exports.UI_BRIDGE_NATIVE_ROUTES = UI_BRIDGE_NATIVE_ROUTES;
2210
+ exports.buildTreePath = buildTreePath;
2211
+ exports.createNativeActionExecutor = createNativeActionExecutor;
2212
+ exports.createNativeElementIdentifier = createNativeElementIdentifier;
2213
+ exports.createNativeServer = createNativeServer;
2214
+ exports.createServerHandlers = createServerHandlers;
2215
+ exports.findAllByPattern = findAllByPattern;
2216
+ exports.findElementByIdentifier = findElementByIdentifier;
2217
+ exports.getGlobalRegistry = getGlobalRegistry;
2218
+ exports.matchesIdentifier = matchesIdentifier;
2219
+ exports.parseTreePath = parseTreePath;
2220
+ exports.resetGlobalRegistry = resetGlobalRegistry;
2221
+ exports.setGlobalRegistry = setGlobalRegistry;
2222
+ exports.useUIBridge = useUIBridge;
2223
+ exports.useUIBridgeNative = useUIBridgeNative;
2224
+ exports.useUIBridgeNativeOptional = useUIBridgeNativeOptional;
2225
+ exports.useUIBridgeNativeRequired = useUIBridgeNativeRequired;
2226
+ exports.useUIBridgeRequired = useUIBridgeRequired;
2227
+ exports.useUIComponent = useUIComponent;
2228
+ exports.useUIComponentAction = useUIComponentAction;
2229
+ exports.useUIElement = useUIElement;
2230
+ exports.useUIElementWithProps = useUIElementWithProps;
2231
+ //# sourceMappingURL=index.js.map
2232
+ //# sourceMappingURL=index.js.map