@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,1365 @@
1
+ import { createContext, useRef, useState, useCallback, useEffect, useMemo, useContext } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ // src/native/react/UIBridgeNativeProvider.tsx
5
+
6
+ // src/native/core/registry.ts
7
+ function inferActions(type) {
8
+ const baseActions = ["focus", "blur"];
9
+ switch (type) {
10
+ case "button":
11
+ case "touchable":
12
+ case "pressable":
13
+ return [...baseActions, "press", "longPress", "doubleTap"];
14
+ case "input":
15
+ return [...baseActions, "press", "type", "clear"];
16
+ case "text":
17
+ return [...baseActions, "press", "longPress"];
18
+ case "view":
19
+ return [...baseActions, "press"];
20
+ case "scroll":
21
+ return [...baseActions, "scroll", "swipe"];
22
+ case "list":
23
+ return [...baseActions, "scroll", "swipe"];
24
+ case "listItem":
25
+ return [...baseActions, "press", "longPress", "swipe"];
26
+ case "switch":
27
+ case "checkbox":
28
+ return [...baseActions, "press", "toggle"];
29
+ case "radio":
30
+ return [...baseActions, "press"];
31
+ case "image":
32
+ return [...baseActions, "press", "longPress"];
33
+ case "modal":
34
+ return ["focus", "blur"];
35
+ case "custom":
36
+ default:
37
+ return [...baseActions, "press"];
38
+ }
39
+ }
40
+ var NativeUIBridgeRegistry = class {
41
+ constructor(config = {}) {
42
+ this.elements = /* @__PURE__ */ new Map();
43
+ this.components = /* @__PURE__ */ new Map();
44
+ this.workflows = /* @__PURE__ */ new Map();
45
+ this.eventListeners = /* @__PURE__ */ new Map();
46
+ this.config = config;
47
+ }
48
+ // ============================================================================
49
+ // Element Management
50
+ // ============================================================================
51
+ /**
52
+ * Register a native element
53
+ */
54
+ registerElement(id, ref, options = {}) {
55
+ const {
56
+ type = "custom",
57
+ label,
58
+ actions = inferActions(type),
59
+ customActions,
60
+ props,
61
+ treePath = id,
62
+ testId,
63
+ accessibilityLabel
64
+ } = options;
65
+ const getState = () => {
66
+ const element = ref.current;
67
+ if (!element) {
68
+ return {
69
+ mounted: false,
70
+ visible: false,
71
+ enabled: false,
72
+ focused: false,
73
+ layout: null
74
+ };
75
+ }
76
+ const stored = this.elements.get(id);
77
+ if (stored && stored.getState !== getState) {
78
+ return stored.getState();
79
+ }
80
+ return {
81
+ mounted: true,
82
+ visible: true,
83
+ enabled: true,
84
+ focused: false,
85
+ layout: null
86
+ };
87
+ };
88
+ const getIdentifier = () => ({
89
+ uiId: id,
90
+ testId: testId || id,
91
+ accessibilityLabel,
92
+ treePath
93
+ });
94
+ const registered = {
95
+ id,
96
+ ref,
97
+ type,
98
+ label,
99
+ actions,
100
+ customActions,
101
+ props,
102
+ getState,
103
+ getIdentifier,
104
+ registeredAt: Date.now(),
105
+ mounted: true
106
+ };
107
+ this.elements.set(id, registered);
108
+ this.emit("element:registered", { id, type, label });
109
+ if (this.config.verbose) {
110
+ console.log(`[ui-bridge-native] Registered element: ${id} (${type})`);
111
+ }
112
+ return registered;
113
+ }
114
+ /**
115
+ * Unregister an element
116
+ */
117
+ unregisterElement(id) {
118
+ const element = this.elements.get(id);
119
+ if (element) {
120
+ this.elements.delete(id);
121
+ this.emit("element:unregistered", { id });
122
+ if (this.config.verbose) {
123
+ console.log(`[ui-bridge-native] Unregistered element: ${id}`);
124
+ }
125
+ }
126
+ }
127
+ /**
128
+ * Get a registered element
129
+ */
130
+ getElement(id) {
131
+ return this.elements.get(id);
132
+ }
133
+ /**
134
+ * Get all registered elements
135
+ */
136
+ getAllElements() {
137
+ return Array.from(this.elements.values());
138
+ }
139
+ /**
140
+ * Update element state
141
+ */
142
+ updateElementState(id, state) {
143
+ const element = this.elements.get(id);
144
+ if (element) {
145
+ const currentState = element.getState();
146
+ const newState = { ...currentState, ...state };
147
+ const updated = {
148
+ ...element,
149
+ getState: () => newState
150
+ };
151
+ this.elements.set(id, updated);
152
+ this.emit("element:stateChanged", { id, state: newState });
153
+ }
154
+ }
155
+ /**
156
+ * Update element props (for action execution)
157
+ */
158
+ updateElementProps(id, props) {
159
+ const element = this.elements.get(id);
160
+ if (element) {
161
+ const updated = {
162
+ ...element,
163
+ props: { ...element.props, ...props }
164
+ };
165
+ this.elements.set(id, updated);
166
+ }
167
+ }
168
+ /**
169
+ * Find element by testID
170
+ */
171
+ findByTestId(testId) {
172
+ for (const element of this.elements.values()) {
173
+ const identifier = element.getIdentifier();
174
+ if (identifier.testId === testId) {
175
+ return element;
176
+ }
177
+ }
178
+ return void 0;
179
+ }
180
+ /**
181
+ * Find elements by type
182
+ */
183
+ findByType(type) {
184
+ return Array.from(this.elements.values()).filter((e) => e.type === type);
185
+ }
186
+ // ============================================================================
187
+ // Component Management
188
+ // ============================================================================
189
+ /**
190
+ * Register a component
191
+ */
192
+ registerComponent(id, options) {
193
+ const { name, description, actions = [], elementIds } = options;
194
+ const registered = {
195
+ id,
196
+ name,
197
+ description,
198
+ actions: actions.map((a) => ({
199
+ id: a.id,
200
+ label: a.label,
201
+ description: a.description,
202
+ handler: a.handler
203
+ })),
204
+ elementIds,
205
+ registeredAt: Date.now(),
206
+ mounted: true
207
+ };
208
+ this.components.set(id, registered);
209
+ this.emit("component:registered", { id, name });
210
+ if (this.config.verbose) {
211
+ console.log(`[ui-bridge-native] Registered component: ${id} (${name})`);
212
+ }
213
+ return registered;
214
+ }
215
+ /**
216
+ * Unregister a component
217
+ */
218
+ unregisterComponent(id) {
219
+ const component = this.components.get(id);
220
+ if (component) {
221
+ this.components.delete(id);
222
+ this.emit("component:unregistered", { id });
223
+ if (this.config.verbose) {
224
+ console.log(`[ui-bridge-native] Unregistered component: ${id}`);
225
+ }
226
+ }
227
+ }
228
+ /**
229
+ * Get a registered component
230
+ */
231
+ getComponent(id) {
232
+ return this.components.get(id);
233
+ }
234
+ /**
235
+ * Get all registered components
236
+ */
237
+ getAllComponents() {
238
+ return Array.from(this.components.values());
239
+ }
240
+ // ============================================================================
241
+ // Workflow Management
242
+ // ============================================================================
243
+ /**
244
+ * Register a workflow
245
+ */
246
+ registerWorkflow(workflow) {
247
+ this.workflows.set(workflow.id, workflow);
248
+ if (this.config.verbose) {
249
+ console.log(`[ui-bridge-native] Registered workflow: ${workflow.id}`);
250
+ }
251
+ }
252
+ /**
253
+ * Unregister a workflow
254
+ */
255
+ unregisterWorkflow(id) {
256
+ this.workflows.delete(id);
257
+ }
258
+ /**
259
+ * Get a workflow
260
+ */
261
+ getWorkflow(id) {
262
+ return this.workflows.get(id);
263
+ }
264
+ /**
265
+ * Get all workflows
266
+ */
267
+ getAllWorkflows() {
268
+ return Array.from(this.workflows.values());
269
+ }
270
+ // ============================================================================
271
+ // Event System
272
+ // ============================================================================
273
+ /**
274
+ * Subscribe to events
275
+ */
276
+ on(type, listener) {
277
+ if (!this.eventListeners.has(type)) {
278
+ this.eventListeners.set(type, /* @__PURE__ */ new Set());
279
+ }
280
+ this.eventListeners.get(type).add(listener);
281
+ return () => this.off(type, listener);
282
+ }
283
+ /**
284
+ * Unsubscribe from events
285
+ */
286
+ off(type, listener) {
287
+ this.eventListeners.get(type)?.delete(listener);
288
+ }
289
+ /**
290
+ * Emit an event
291
+ */
292
+ emit(type, data) {
293
+ const event = {
294
+ type,
295
+ timestamp: Date.now(),
296
+ data
297
+ };
298
+ const listeners = this.eventListeners.get(type);
299
+ if (listeners) {
300
+ for (const listener of listeners) {
301
+ try {
302
+ listener(event);
303
+ } catch (error) {
304
+ console.error(`[ui-bridge-native] Event listener error:`, error);
305
+ }
306
+ }
307
+ }
308
+ if (this.config.onEvent) {
309
+ try {
310
+ this.config.onEvent(event);
311
+ } catch (error) {
312
+ console.error(`[ui-bridge-native] Global event handler error:`, error);
313
+ }
314
+ }
315
+ }
316
+ // ============================================================================
317
+ // Snapshots
318
+ // ============================================================================
319
+ /**
320
+ * Create a snapshot of the current state
321
+ */
322
+ createSnapshot() {
323
+ return {
324
+ timestamp: Date.now(),
325
+ elements: this.getAllElements().map((e) => ({
326
+ id: e.id,
327
+ type: e.type,
328
+ label: e.label,
329
+ identifier: e.getIdentifier(),
330
+ state: e.getState(),
331
+ actions: e.actions,
332
+ customActions: e.customActions ? Object.keys(e.customActions) : void 0
333
+ })),
334
+ components: this.getAllComponents().map((c) => ({
335
+ id: c.id,
336
+ name: c.name,
337
+ description: c.description,
338
+ actions: c.actions.map((a) => a.id),
339
+ elementIds: c.elementIds
340
+ })),
341
+ workflows: this.getAllWorkflows().map((w) => ({
342
+ id: w.id,
343
+ name: w.name,
344
+ description: w.description,
345
+ stepCount: w.steps.length
346
+ }))
347
+ };
348
+ }
349
+ /**
350
+ * Get registry statistics
351
+ */
352
+ getStats() {
353
+ return {
354
+ elements: this.elements.size,
355
+ components: this.components.size,
356
+ workflows: this.workflows.size
357
+ };
358
+ }
359
+ /**
360
+ * Clear all registrations
361
+ */
362
+ clear() {
363
+ this.elements.clear();
364
+ this.components.clear();
365
+ this.workflows.clear();
366
+ if (this.config.verbose) {
367
+ console.log(`[ui-bridge-native] Registry cleared`);
368
+ }
369
+ }
370
+ };
371
+ var globalRegistry = null;
372
+ function setGlobalRegistry(registry) {
373
+ globalRegistry = registry;
374
+ }
375
+ function getGlobalRegistry() {
376
+ return globalRegistry;
377
+ }
378
+ function resetGlobalRegistry() {
379
+ globalRegistry?.clear();
380
+ globalRegistry = null;
381
+ }
382
+
383
+ // src/native/core/element-identifier.ts
384
+ function findElementByIdentifier(identifier) {
385
+ const registry = getGlobalRegistry();
386
+ if (!registry) return null;
387
+ if (typeof identifier === "string") {
388
+ const byId = registry.getElement(identifier);
389
+ if (byId) return byId;
390
+ const byTestId = registry.findByTestId(identifier);
391
+ if (byTestId) return byTestId;
392
+ return findByPattern(registry, identifier);
393
+ }
394
+ if (identifier.uiId) {
395
+ const byId = registry.getElement(identifier.uiId);
396
+ if (byId) return byId;
397
+ }
398
+ if (identifier.testId) {
399
+ const byTestId = registry.findByTestId(identifier.testId);
400
+ if (byTestId) return byTestId;
401
+ }
402
+ return null;
403
+ }
404
+ function findByPattern(registry, pattern) {
405
+ if (!registry) return null;
406
+ const regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
407
+ const regex = new RegExp(`^${regexPattern}$`, "i");
408
+ for (const element of registry.getAllElements()) {
409
+ const identifier = element.getIdentifier();
410
+ if (identifier.testId && regex.test(identifier.testId)) {
411
+ return element;
412
+ }
413
+ if (identifier.uiId && regex.test(identifier.uiId)) {
414
+ return element;
415
+ }
416
+ if (identifier.treePath && regex.test(identifier.treePath)) {
417
+ return element;
418
+ }
419
+ if (identifier.accessibilityLabel && regex.test(identifier.accessibilityLabel)) {
420
+ return element;
421
+ }
422
+ }
423
+ return null;
424
+ }
425
+
426
+ // src/native/control/action-executor.ts
427
+ var DEFAULT_WAIT_OPTIONS = {
428
+ visible: true,
429
+ enabled: true,
430
+ focused: false,
431
+ state: {},
432
+ timeout: 1e4,
433
+ interval: 100
434
+ };
435
+ function sleep(ms) {
436
+ return new Promise((resolve) => setTimeout(resolve, ms));
437
+ }
438
+ var DefaultNativeActionExecutor = class {
439
+ constructor(registry) {
440
+ this.registry = registry;
441
+ }
442
+ /**
443
+ * Execute an action on an element
444
+ */
445
+ async executeAction(elementId, request) {
446
+ const startTime = Date.now();
447
+ let waitDurationMs = 0;
448
+ try {
449
+ let registered = this.registry.getElement(elementId);
450
+ if (!registered) {
451
+ registered = findElementByIdentifier(elementId) ?? void 0;
452
+ }
453
+ if (!registered) {
454
+ return {
455
+ success: false,
456
+ error: `Element not found: ${elementId}`,
457
+ durationMs: Date.now() - startTime,
458
+ timestamp: Date.now(),
459
+ requestId: request.requestId
460
+ };
461
+ }
462
+ if (request.waitOptions) {
463
+ const waitResult = await this.waitForElementInternal(registered.id, request.waitOptions);
464
+ waitDurationMs = waitResult.waitedMs;
465
+ if (!waitResult.met) {
466
+ return {
467
+ success: false,
468
+ error: waitResult.error || "Wait condition not met",
469
+ durationMs: Date.now() - startTime,
470
+ timestamp: Date.now(),
471
+ requestId: request.requestId,
472
+ waitDurationMs
473
+ };
474
+ }
475
+ }
476
+ const result = await this.performAction(registered, request.action, request.params);
477
+ return {
478
+ success: true,
479
+ elementState: registered.getState(),
480
+ result,
481
+ durationMs: Date.now() - startTime,
482
+ timestamp: Date.now(),
483
+ requestId: request.requestId,
484
+ waitDurationMs
485
+ };
486
+ } catch (error) {
487
+ return {
488
+ success: false,
489
+ error: error instanceof Error ? error.message : String(error),
490
+ stack: error instanceof Error ? error.stack : void 0,
491
+ durationMs: Date.now() - startTime,
492
+ timestamp: Date.now(),
493
+ requestId: request.requestId,
494
+ waitDurationMs
495
+ };
496
+ }
497
+ }
498
+ /**
499
+ * Perform an action on an element
500
+ */
501
+ async performAction(element, action, params) {
502
+ if (!element) {
503
+ throw new Error("Element not found");
504
+ }
505
+ const props = element.props || {};
506
+ if (element.customActions && action in element.customActions) {
507
+ return element.customActions[action].handler(params);
508
+ }
509
+ switch (action) {
510
+ case "press":
511
+ return this.performPress(props, params);
512
+ case "longPress":
513
+ return this.performLongPress(props, params);
514
+ case "doubleTap":
515
+ return this.performDoubleTap(props);
516
+ case "type":
517
+ return this.performType(element, props, params);
518
+ case "clear":
519
+ return this.performClear(element, props);
520
+ case "focus":
521
+ return this.performFocus(element);
522
+ case "blur":
523
+ return this.performBlur(element);
524
+ case "scroll":
525
+ return this.performScroll(props, params);
526
+ case "swipe":
527
+ return this.performSwipe(props, params);
528
+ case "toggle":
529
+ return this.performToggle(props);
530
+ default:
531
+ throw new Error(`Unknown action: ${action}`);
532
+ }
533
+ }
534
+ /**
535
+ * Perform press action
536
+ */
537
+ async performPress(props, params) {
538
+ const handlers = ["onPress", "onPressIn", "onResponderRelease"];
539
+ for (const handler of handlers) {
540
+ if (typeof props[handler] === "function") {
541
+ const event = this.createPressEvent(params);
542
+ props[handler](event);
543
+ return;
544
+ }
545
+ }
546
+ throw new Error("No press handler found on element");
547
+ }
548
+ /**
549
+ * Perform long press action
550
+ */
551
+ async performLongPress(props, params) {
552
+ if (typeof props.onLongPress === "function") {
553
+ const event = this.createPressEvent(params);
554
+ props.onLongPress(event);
555
+ return;
556
+ }
557
+ throw new Error("No long press handler found on element");
558
+ }
559
+ /**
560
+ * Perform double tap action
561
+ */
562
+ async performDoubleTap(props) {
563
+ if (typeof props.onDoubleTap === "function") {
564
+ props.onDoubleTap();
565
+ return;
566
+ }
567
+ if (typeof props.onPress === "function") {
568
+ const event = this.createPressEvent();
569
+ props.onPress(event);
570
+ await sleep(50);
571
+ props.onPress(event);
572
+ return;
573
+ }
574
+ throw new Error("No press handler found for double tap");
575
+ }
576
+ /**
577
+ * Perform type action
578
+ */
579
+ async performType(element, props, params) {
580
+ if (!params?.text) {
581
+ throw new Error("Type action requires text parameter");
582
+ }
583
+ if (params.clearFirst) {
584
+ await this.performClear(element, props);
585
+ }
586
+ if (params.delay && params.delay > 0) {
587
+ const currentValue = element?.getState().value || "";
588
+ for (const char of params.text) {
589
+ const newValue = currentValue + char;
590
+ if (typeof props.onChangeText === "function") {
591
+ props.onChangeText(newValue);
592
+ }
593
+ await sleep(params.delay);
594
+ }
595
+ } else {
596
+ if (typeof props.onChangeText === "function") {
597
+ props.onChangeText(params.text);
598
+ } else if (typeof props.onChange === "function") {
599
+ props.onChange({
600
+ nativeEvent: { text: params.text }
601
+ });
602
+ } else {
603
+ throw new Error("No text change handler found on element");
604
+ }
605
+ }
606
+ if (element) {
607
+ this.registry.updateElementState(element.id, { value: params.text });
608
+ }
609
+ }
610
+ /**
611
+ * Perform clear action
612
+ */
613
+ async performClear(element, props) {
614
+ if (typeof props.onChangeText === "function") {
615
+ props.onChangeText("");
616
+ } else if (typeof props.onChange === "function") {
617
+ props.onChange({
618
+ nativeEvent: { text: "" }
619
+ });
620
+ }
621
+ if (element) {
622
+ this.registry.updateElementState(element.id, { value: "" });
623
+ }
624
+ }
625
+ /**
626
+ * Perform focus action
627
+ */
628
+ async performFocus(element) {
629
+ if (element?.ref.current && "focus" in element.ref.current) {
630
+ element.ref.current.focus();
631
+ }
632
+ if (element) {
633
+ this.registry.updateElementState(element.id, { focused: true });
634
+ }
635
+ }
636
+ /**
637
+ * Perform blur action
638
+ */
639
+ async performBlur(element) {
640
+ if (element?.ref.current && "blur" in element.ref.current) {
641
+ element.ref.current.blur();
642
+ }
643
+ if (element) {
644
+ this.registry.updateElementState(element.id, { focused: false });
645
+ }
646
+ }
647
+ /**
648
+ * Perform scroll action
649
+ */
650
+ async performScroll(props, params) {
651
+ if (typeof props.onScroll === "function") {
652
+ const event = {
653
+ nativeEvent: {
654
+ contentOffset: params?.offset || { x: 0, y: 0 }
655
+ }
656
+ };
657
+ props.onScroll(event);
658
+ }
659
+ }
660
+ /**
661
+ * Perform swipe action
662
+ */
663
+ async performSwipe(props, params) {
664
+ if (!params?.direction) {
665
+ throw new Error("Swipe action requires direction parameter");
666
+ }
667
+ const handlerMap = {
668
+ left: "onSwipeLeft",
669
+ right: "onSwipeRight",
670
+ up: "onSwipeUp",
671
+ down: "onSwipeDown"
672
+ };
673
+ const handler = handlerMap[params.direction];
674
+ if (handler && typeof props[handler] === "function") {
675
+ props[handler]();
676
+ return;
677
+ }
678
+ if (typeof props.onSwipe === "function") {
679
+ props.onSwipe(params.direction);
680
+ }
681
+ }
682
+ /**
683
+ * Perform toggle action
684
+ */
685
+ async performToggle(props) {
686
+ if (typeof props.onValueChange === "function") {
687
+ const currentValue = props.value;
688
+ props.onValueChange(!currentValue);
689
+ return;
690
+ }
691
+ if (typeof props.onPress === "function") {
692
+ props.onPress();
693
+ return;
694
+ }
695
+ throw new Error("No toggle handler found on element");
696
+ }
697
+ /**
698
+ * Create a synthetic press event
699
+ */
700
+ createPressEvent(params) {
701
+ return {
702
+ nativeEvent: {
703
+ locationX: params?.position?.x ?? 0,
704
+ locationY: params?.position?.y ?? 0,
705
+ timestamp: Date.now()
706
+ },
707
+ persist: () => {
708
+ }
709
+ };
710
+ }
711
+ /**
712
+ * Execute a component action
713
+ */
714
+ async executeComponentAction(componentId, request) {
715
+ const startTime = Date.now();
716
+ try {
717
+ const component = this.registry.getComponent(componentId);
718
+ if (!component) {
719
+ return {
720
+ success: false,
721
+ error: `Component not found: ${componentId}`,
722
+ durationMs: Date.now() - startTime,
723
+ timestamp: Date.now(),
724
+ requestId: request.requestId
725
+ };
726
+ }
727
+ const action = component.actions.find((a) => a.id === request.action);
728
+ if (!action) {
729
+ return {
730
+ success: false,
731
+ error: `Action not found: ${request.action}`,
732
+ durationMs: Date.now() - startTime,
733
+ timestamp: Date.now(),
734
+ requestId: request.requestId
735
+ };
736
+ }
737
+ const result = await action.handler(request.params);
738
+ return {
739
+ success: true,
740
+ result,
741
+ durationMs: Date.now() - startTime,
742
+ timestamp: Date.now(),
743
+ requestId: request.requestId
744
+ };
745
+ } catch (error) {
746
+ return {
747
+ success: false,
748
+ error: error instanceof Error ? error.message : String(error),
749
+ stack: error instanceof Error ? error.stack : void 0,
750
+ durationMs: Date.now() - startTime,
751
+ timestamp: Date.now(),
752
+ requestId: request.requestId
753
+ };
754
+ }
755
+ }
756
+ /**
757
+ * Find elements
758
+ */
759
+ async find(request) {
760
+ const startTime = Date.now();
761
+ const allElements = this.registry.getAllElements();
762
+ let filtered = allElements;
763
+ if (request.types && request.types.length > 0) {
764
+ filtered = filtered.filter((e) => request.types.includes(e.type));
765
+ }
766
+ if (request.testIdPattern) {
767
+ const regex = new RegExp(request.testIdPattern.replace(/\*/g, ".*").replace(/\?/g, "."));
768
+ filtered = filtered.filter((e) => {
769
+ const identifier = e.getIdentifier();
770
+ return identifier.testId && regex.test(identifier.testId);
771
+ });
772
+ }
773
+ if (request.accessibilityLabelPattern) {
774
+ const regex = new RegExp(
775
+ request.accessibilityLabelPattern.replace(/\*/g, ".*").replace(/\?/g, ".")
776
+ );
777
+ filtered = filtered.filter((e) => {
778
+ const identifier = e.getIdentifier();
779
+ return identifier.accessibilityLabel && regex.test(identifier.accessibilityLabel);
780
+ });
781
+ }
782
+ if (request.visibleOnly) {
783
+ filtered = filtered.filter((e) => e.getState().visible);
784
+ }
785
+ if (request.limit && request.limit > 0) {
786
+ filtered = filtered.slice(0, request.limit);
787
+ }
788
+ const elements = filtered.map((e) => ({
789
+ id: e.id,
790
+ type: e.type,
791
+ identifier: e.getIdentifier(),
792
+ state: e.getState(),
793
+ actions: e.actions,
794
+ label: e.label
795
+ }));
796
+ return {
797
+ elements,
798
+ total: elements.length,
799
+ durationMs: Date.now() - startTime,
800
+ timestamp: Date.now()
801
+ };
802
+ }
803
+ /**
804
+ * Wait for element conditions
805
+ */
806
+ async waitForElement(elementId, options) {
807
+ return this.waitForElementInternal(elementId, options);
808
+ }
809
+ /**
810
+ * Internal wait implementation
811
+ */
812
+ async waitForElementInternal(elementId, options) {
813
+ const opts = { ...DEFAULT_WAIT_OPTIONS, ...options };
814
+ const startTime = Date.now();
815
+ while (Date.now() - startTime < opts.timeout) {
816
+ const element = this.registry.getElement(elementId);
817
+ if (!element) {
818
+ await sleep(opts.interval);
819
+ continue;
820
+ }
821
+ const state = element.getState();
822
+ let conditionsMet = true;
823
+ if (opts.visible && !state.visible) {
824
+ conditionsMet = false;
825
+ }
826
+ if (opts.enabled && !state.enabled) {
827
+ conditionsMet = false;
828
+ }
829
+ if (opts.focused && !state.focused) {
830
+ conditionsMet = false;
831
+ }
832
+ if (opts.state && Object.keys(opts.state).length > 0) {
833
+ const stateRecord = state;
834
+ for (const [key, value] of Object.entries(opts.state)) {
835
+ if (stateRecord[key] !== value) {
836
+ conditionsMet = false;
837
+ break;
838
+ }
839
+ }
840
+ }
841
+ if (conditionsMet) {
842
+ return {
843
+ met: true,
844
+ waitedMs: Date.now() - startTime,
845
+ state
846
+ };
847
+ }
848
+ await sleep(opts.interval);
849
+ }
850
+ return {
851
+ met: false,
852
+ waitedMs: Date.now() - startTime,
853
+ error: `Timeout waiting for conditions on element: ${elementId}`
854
+ };
855
+ }
856
+ };
857
+ function createNativeActionExecutor(registry) {
858
+ return new DefaultNativeActionExecutor(registry);
859
+ }
860
+ var UIBridgeNativeContext = createContext(null);
861
+ function UIBridgeNativeProvider({
862
+ children,
863
+ features = {},
864
+ config = {},
865
+ onEvent
866
+ }) {
867
+ const registryRef = useRef(null);
868
+ const executorRef = useRef(null);
869
+ const [serverRunning, setServerRunning] = useState(false);
870
+ if (!registryRef.current) {
871
+ registryRef.current = new NativeUIBridgeRegistry({
872
+ verbose: config.verbose,
873
+ onEvent
874
+ });
875
+ setGlobalRegistry(registryRef.current);
876
+ }
877
+ const registry = registryRef.current;
878
+ if (!executorRef.current) {
879
+ executorRef.current = createNativeActionExecutor(registry);
880
+ }
881
+ const executor = executorRef.current;
882
+ const startServer = useCallback(async () => {
883
+ if (!features.server) {
884
+ console.warn("[ui-bridge-native] Server feature not enabled");
885
+ return;
886
+ }
887
+ console.log(`[ui-bridge-native] Would start HTTP server on port ${config.serverPort || 9876}`);
888
+ setServerRunning(true);
889
+ }, [features.server, config.serverPort]);
890
+ const stopServer = useCallback(() => {
891
+ console.log("[ui-bridge-native] Would stop HTTP server");
892
+ setServerRunning(false);
893
+ }, []);
894
+ useEffect(() => {
895
+ if (features.server) {
896
+ startServer();
897
+ return () => stopServer();
898
+ }
899
+ }, [features.server, startServer, stopServer]);
900
+ useEffect(() => {
901
+ return () => {
902
+ stopServer();
903
+ resetGlobalRegistry();
904
+ };
905
+ }, [stopServer]);
906
+ const getElements = useCallback(() => registry.getAllElements(), [registry]);
907
+ const getComponents = useCallback(() => registry.getAllComponents(), [registry]);
908
+ const createSnapshot = useCallback(() => registry.createSnapshot(), [registry]);
909
+ const on = useCallback(
910
+ (type, listener) => registry.on(type, listener),
911
+ [registry]
912
+ );
913
+ const off = useCallback(
914
+ (type, listener) => registry.off(type, listener),
915
+ [registry]
916
+ );
917
+ const contextValue = useMemo(
918
+ () => ({
919
+ features,
920
+ config,
921
+ registry,
922
+ executor,
923
+ getElements,
924
+ getComponents,
925
+ createSnapshot,
926
+ on,
927
+ off,
928
+ initialized: true,
929
+ serverRunning,
930
+ startServer,
931
+ stopServer
932
+ }),
933
+ [
934
+ features,
935
+ config,
936
+ registry,
937
+ executor,
938
+ getElements,
939
+ getComponents,
940
+ createSnapshot,
941
+ on,
942
+ off,
943
+ serverRunning,
944
+ startServer,
945
+ stopServer
946
+ ]
947
+ );
948
+ return /* @__PURE__ */ jsx(UIBridgeNativeContext.Provider, { value: contextValue, children });
949
+ }
950
+ function useUIBridgeNative() {
951
+ const context = useContext(UIBridgeNativeContext);
952
+ if (!context) {
953
+ throw new Error("useUIBridgeNative must be used within a UIBridgeNativeProvider");
954
+ }
955
+ return context;
956
+ }
957
+ function useUIBridgeNativeOptional() {
958
+ return useContext(UIBridgeNativeContext);
959
+ }
960
+ var useUIBridgeNativeRequired = useUIBridgeNative;
961
+ function useUIElement(options) {
962
+ const bridge = useUIBridgeNativeOptional();
963
+ const ref = useRef(null);
964
+ const [registered, setRegistered] = useState(false);
965
+ const [_layout, setLayout] = useState(null);
966
+ const propsRef = useRef({});
967
+ const {
968
+ id,
969
+ type = "custom",
970
+ label,
971
+ actions,
972
+ customActions,
973
+ autoRegister = true,
974
+ onStateChange,
975
+ parentPath
976
+ } = options;
977
+ const treePath = parentPath ? `${parentPath}/${id}` : id;
978
+ const bridgeProps = useMemo(
979
+ () => ({
980
+ testID: id,
981
+ accessibilityLabel: label
982
+ }),
983
+ [id, label]
984
+ );
985
+ const register = useCallback(() => {
986
+ if (!bridge || registered) return;
987
+ bridge.registry.registerElement(id, ref, {
988
+ type,
989
+ label,
990
+ actions,
991
+ customActions,
992
+ treePath,
993
+ testId: id,
994
+ accessibilityLabel: label
995
+ });
996
+ setRegistered(true);
997
+ }, [bridge, registered, id, type, label, actions, customActions, treePath]);
998
+ const unregister = useCallback(() => {
999
+ if (!bridge || !registered) return;
1000
+ bridge.registry.unregisterElement(id);
1001
+ setRegistered(false);
1002
+ }, [bridge, registered, id]);
1003
+ const onLayout = useCallback(
1004
+ (event) => {
1005
+ const { x, y, width, height } = event.nativeEvent.layout;
1006
+ if (ref.current && "measureInWindow" in ref.current) {
1007
+ ref.current.measureInWindow((pageX, pageY) => {
1008
+ const newLayout = {
1009
+ x,
1010
+ y,
1011
+ width,
1012
+ height,
1013
+ pageX,
1014
+ pageY
1015
+ };
1016
+ setLayout(newLayout);
1017
+ if (bridge && registered) {
1018
+ const newState = {
1019
+ mounted: true,
1020
+ visible: width > 0 && height > 0,
1021
+ enabled: true,
1022
+ focused: false,
1023
+ layout: newLayout
1024
+ };
1025
+ bridge.registry.updateElementState(id, newState);
1026
+ onStateChange?.(newState);
1027
+ }
1028
+ });
1029
+ } else {
1030
+ const newLayout = {
1031
+ x,
1032
+ y,
1033
+ width,
1034
+ height,
1035
+ pageX: x,
1036
+ pageY: y
1037
+ };
1038
+ setLayout(newLayout);
1039
+ if (bridge && registered) {
1040
+ const newState = {
1041
+ mounted: true,
1042
+ visible: width > 0 && height > 0,
1043
+ enabled: true,
1044
+ focused: false,
1045
+ layout: newLayout
1046
+ };
1047
+ bridge.registry.updateElementState(id, newState);
1048
+ onStateChange?.(newState);
1049
+ }
1050
+ }
1051
+ },
1052
+ [bridge, registered, id, onStateChange]
1053
+ );
1054
+ useEffect(() => {
1055
+ if (autoRegister) {
1056
+ register();
1057
+ }
1058
+ return () => {
1059
+ unregister();
1060
+ };
1061
+ }, [autoRegister, register, unregister]);
1062
+ useCallback(
1063
+ (props) => {
1064
+ propsRef.current = { ...propsRef.current, ...props };
1065
+ if (bridge && registered) {
1066
+ bridge.registry.updateElementProps(id, props);
1067
+ }
1068
+ },
1069
+ [bridge, registered, id]
1070
+ );
1071
+ const getState = useCallback(() => {
1072
+ if (!bridge) return null;
1073
+ const element = bridge.registry.getElement(id);
1074
+ return element?.getState() || null;
1075
+ }, [bridge, id]);
1076
+ const getIdentifier = useCallback(() => {
1077
+ if (!bridge) return null;
1078
+ const element = bridge.registry.getElement(id);
1079
+ return element?.getIdentifier() || null;
1080
+ }, [bridge, id]);
1081
+ const trigger = useCallback(
1082
+ async (action, params) => {
1083
+ if (!bridge) {
1084
+ throw new Error("UI Bridge Native not available");
1085
+ }
1086
+ const response = await bridge.executor.executeAction(id, {
1087
+ action,
1088
+ params
1089
+ });
1090
+ if (!response.success) {
1091
+ throw new Error(response.error || "Action failed");
1092
+ }
1093
+ },
1094
+ [bridge, id]
1095
+ );
1096
+ const registeredElement = useMemo(() => {
1097
+ if (!bridge) return null;
1098
+ return bridge.registry.getElement(id) || null;
1099
+ }, [bridge, id, registered]);
1100
+ return {
1101
+ ref,
1102
+ onLayout,
1103
+ bridgeProps,
1104
+ registered,
1105
+ getState,
1106
+ getIdentifier,
1107
+ trigger,
1108
+ register,
1109
+ unregister,
1110
+ registeredElement
1111
+ };
1112
+ }
1113
+ function useUIElementWithProps(options) {
1114
+ const elementReturn = useUIElement(options);
1115
+ const bridge = useUIBridgeNativeOptional();
1116
+ const captureProps = useCallback(
1117
+ (props) => {
1118
+ if (bridge && elementReturn.registered) {
1119
+ bridge.registry.updateElementProps(options.id, props);
1120
+ }
1121
+ },
1122
+ [bridge, elementReturn.registered, options.id]
1123
+ );
1124
+ return {
1125
+ ...elementReturn,
1126
+ captureProps
1127
+ };
1128
+ }
1129
+ function useUIComponent(options) {
1130
+ const bridge = useUIBridgeNativeOptional();
1131
+ const registeredRef = useRef(false);
1132
+ const actionsRef = useRef(options.actions || []);
1133
+ const elementIdsRef = useRef(options.elementIds || []);
1134
+ const { id, name, description, autoRegister = true } = options;
1135
+ useEffect(() => {
1136
+ actionsRef.current = options.actions || [];
1137
+ elementIdsRef.current = options.elementIds || [];
1138
+ }, [options.actions, options.elementIds]);
1139
+ const register = useCallback(() => {
1140
+ if (!bridge || registeredRef.current) return;
1141
+ bridge.registry.registerComponent(id, {
1142
+ name,
1143
+ description,
1144
+ actions: actionsRef.current.map((a) => ({
1145
+ id: a.id,
1146
+ label: a.label,
1147
+ description: a.description,
1148
+ handler: a.handler
1149
+ })),
1150
+ elementIds: elementIdsRef.current
1151
+ });
1152
+ registeredRef.current = true;
1153
+ }, [bridge, id, name, description]);
1154
+ const unregister = useCallback(() => {
1155
+ if (!bridge || !registeredRef.current) return;
1156
+ bridge.registry.unregisterComponent(id);
1157
+ registeredRef.current = false;
1158
+ }, [bridge, id]);
1159
+ const executeAction = useCallback(
1160
+ async (actionId, params) => {
1161
+ if (!bridge) {
1162
+ throw new Error("UI Bridge Native not available");
1163
+ }
1164
+ const response = await bridge.executor.executeComponentAction(id, {
1165
+ action: actionId,
1166
+ params
1167
+ });
1168
+ if (!response.success) {
1169
+ throw new Error(response.error || "Action failed");
1170
+ }
1171
+ return response.result;
1172
+ },
1173
+ [bridge, id]
1174
+ );
1175
+ const updateActions = useCallback(
1176
+ (actions) => {
1177
+ actionsRef.current = actions;
1178
+ if (registeredRef.current && bridge) {
1179
+ bridge.registry.unregisterComponent(id);
1180
+ registeredRef.current = false;
1181
+ register();
1182
+ }
1183
+ },
1184
+ [bridge, id, register]
1185
+ );
1186
+ const addElement = useCallback((elementId) => {
1187
+ if (!elementIdsRef.current.includes(elementId)) {
1188
+ elementIdsRef.current = [...elementIdsRef.current, elementId];
1189
+ }
1190
+ }, []);
1191
+ const removeElement = useCallback((elementId) => {
1192
+ elementIdsRef.current = elementIdsRef.current.filter((eid) => eid !== elementId);
1193
+ }, []);
1194
+ useEffect(() => {
1195
+ if (autoRegister) {
1196
+ register();
1197
+ }
1198
+ return () => {
1199
+ unregister();
1200
+ };
1201
+ }, [autoRegister, register, unregister]);
1202
+ const registeredComponent = useMemo(() => {
1203
+ if (!bridge) return null;
1204
+ return bridge.registry.getComponent(id) || null;
1205
+ }, [bridge, id, registeredRef.current]);
1206
+ return {
1207
+ registered: registeredRef.current,
1208
+ executeAction,
1209
+ register,
1210
+ unregister,
1211
+ updateActions,
1212
+ addElement,
1213
+ removeElement,
1214
+ registeredComponent
1215
+ };
1216
+ }
1217
+ function useUIComponentAction(handler, deps) {
1218
+ return useCallback(handler, deps);
1219
+ }
1220
+ function useUIBridge() {
1221
+ const bridge = useUIBridgeNativeOptional();
1222
+ const available = bridge !== null;
1223
+ const initialized = bridge?.initialized ?? false;
1224
+ const elements = useMemo(() => bridge ? bridge.getElements() : [], [bridge]);
1225
+ const components = useMemo(() => bridge ? bridge.getComponents() : [], [bridge]);
1226
+ const workflows = useMemo(() => bridge ? bridge.registry.getAllWorkflows() : [], [bridge]);
1227
+ const createSnapshot = useCallback(() => {
1228
+ if (!bridge) {
1229
+ return {
1230
+ timestamp: Date.now(),
1231
+ elements: [],
1232
+ components: [],
1233
+ workflows: []
1234
+ };
1235
+ }
1236
+ return bridge.createSnapshot();
1237
+ }, [bridge]);
1238
+ const executeAction = useCallback(
1239
+ async (elementId, request) => {
1240
+ if (!bridge) {
1241
+ return {
1242
+ success: false,
1243
+ error: "UI Bridge not available",
1244
+ durationMs: 0,
1245
+ timestamp: Date.now()
1246
+ };
1247
+ }
1248
+ return bridge.executor.executeAction(elementId, request);
1249
+ },
1250
+ [bridge]
1251
+ );
1252
+ const executeComponentAction = useCallback(
1253
+ async (componentId, request) => {
1254
+ if (!bridge) {
1255
+ return {
1256
+ success: false,
1257
+ error: "UI Bridge not available",
1258
+ durationMs: 0,
1259
+ timestamp: Date.now()
1260
+ };
1261
+ }
1262
+ return bridge.executor.executeComponentAction(componentId, request);
1263
+ },
1264
+ [bridge]
1265
+ );
1266
+ const find = useCallback(
1267
+ async (request) => {
1268
+ if (!bridge) {
1269
+ return {
1270
+ elements: [],
1271
+ total: 0,
1272
+ durationMs: 0,
1273
+ timestamp: Date.now()
1274
+ };
1275
+ }
1276
+ return bridge.executor.find(request || {});
1277
+ },
1278
+ [bridge]
1279
+ );
1280
+ const getElement = useCallback((id) => bridge?.registry.getElement(id), [bridge]);
1281
+ const getComponent = useCallback((id) => bridge?.registry.getComponent(id), [bridge]);
1282
+ const getElementState = useCallback(
1283
+ (id) => {
1284
+ const element = bridge?.registry.getElement(id);
1285
+ return element?.getState() ?? null;
1286
+ },
1287
+ [bridge]
1288
+ );
1289
+ const registerWorkflow = useCallback(
1290
+ (workflow) => {
1291
+ bridge?.registry.registerWorkflow(workflow);
1292
+ },
1293
+ [bridge]
1294
+ );
1295
+ const unregisterWorkflow = useCallback(
1296
+ (id) => {
1297
+ bridge?.registry.unregisterWorkflow(id);
1298
+ },
1299
+ [bridge]
1300
+ );
1301
+ return {
1302
+ available,
1303
+ initialized,
1304
+ elements,
1305
+ components,
1306
+ workflows,
1307
+ createSnapshot,
1308
+ executeAction,
1309
+ executeComponentAction,
1310
+ find,
1311
+ getElement,
1312
+ getComponent,
1313
+ getElementState,
1314
+ registerWorkflow,
1315
+ unregisterWorkflow
1316
+ };
1317
+ }
1318
+ function useUIBridgeRequired() {
1319
+ const result = useUIBridge();
1320
+ if (!result.available) {
1321
+ throw new Error("useUIBridgeRequired must be used within a UIBridgeNativeProvider");
1322
+ }
1323
+ return result;
1324
+ }
1325
+ function useAutoRegister(options = {}) {
1326
+ const { enabled = false, onRegister, onUnregister } = options;
1327
+ const bridge = useUIBridgeNativeOptional();
1328
+ const registeredIdsRef = useRef(/* @__PURE__ */ new Set());
1329
+ const register = useCallback(
1330
+ (id, ref, elementOptions) => {
1331
+ if (!enabled || !bridge?.registry) return;
1332
+ if (registeredIdsRef.current.has(id)) return;
1333
+ bridge.registry.registerElement(id, ref, elementOptions);
1334
+ registeredIdsRef.current.add(id);
1335
+ onRegister?.(id);
1336
+ },
1337
+ [enabled, bridge, onRegister]
1338
+ );
1339
+ const unregister = useCallback(
1340
+ (id) => {
1341
+ if (!bridge?.registry) return;
1342
+ bridge.registry.unregisterElement(id);
1343
+ registeredIdsRef.current.delete(id);
1344
+ onUnregister?.(id);
1345
+ },
1346
+ [bridge, onUnregister]
1347
+ );
1348
+ useEffect(() => {
1349
+ return () => {
1350
+ registeredIdsRef.current.forEach((id) => {
1351
+ bridge?.registry.unregisterElement(id);
1352
+ });
1353
+ registeredIdsRef.current.clear();
1354
+ };
1355
+ }, [bridge]);
1356
+ return {
1357
+ register,
1358
+ unregister,
1359
+ isEnabled: enabled && !!bridge?.registry
1360
+ };
1361
+ }
1362
+
1363
+ export { UIBridgeNativeProvider, useAutoRegister, useUIBridge, useUIBridgeNative, useUIBridgeNativeOptional, useUIBridgeNativeRequired, useUIBridgeRequired, useUIComponent, useUIComponentAction, useUIElement, useUIElementWithProps };
1364
+ //# sourceMappingURL=index.mjs.map
1365
+ //# sourceMappingURL=index.mjs.map