@qontinui/ui-bridge-native 0.6.10 → 0.6.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createContext, useRef, useState, useCallback, useEffect, useMemo, use } from 'react';
2
- import { Dimensions, StyleSheet, Platform, TouchableOpacity, Text, Modal, View, ScrollView } from 'react-native';
2
+ import { Dimensions, StyleSheet, Platform, PixelRatio, TouchableOpacity, Text, Modal, View, ScrollView } from 'react-native';
3
3
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
4
4
 
5
5
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -9,6 +9,179 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
9
9
  throw Error('Dynamic require of "' + x + '" is not supported');
10
10
  });
11
11
 
12
+ // src/core/vision-fields.ts
13
+ var INTERACTIVE_HANDLER_NAMES = /* @__PURE__ */ new Set([
14
+ "onPress",
15
+ "onPressIn",
16
+ "onPressOut",
17
+ "onLongPress",
18
+ "onChangeText",
19
+ "onValueChange",
20
+ "onChange",
21
+ "onSubmitEditing",
22
+ "onClick",
23
+ "onTouchStart",
24
+ "onTouchEnd"
25
+ ]);
26
+ var INTERACTIVE_TYPES = /* @__PURE__ */ new Set([
27
+ "button",
28
+ "input",
29
+ "switch",
30
+ "checkbox",
31
+ "radio",
32
+ "touchable",
33
+ "pressable",
34
+ "listItem"
35
+ ]);
36
+ function roleForType(type) {
37
+ switch (type) {
38
+ case "button":
39
+ case "touchable":
40
+ case "pressable":
41
+ return "button";
42
+ case "input":
43
+ return "textbox";
44
+ case "text":
45
+ return "text";
46
+ case "switch":
47
+ return "switch";
48
+ case "checkbox":
49
+ return "checkbox";
50
+ case "radio":
51
+ return "radio";
52
+ case "image":
53
+ return "img";
54
+ case "list":
55
+ return "list";
56
+ case "listItem":
57
+ return "listitem";
58
+ case "modal":
59
+ return "dialog";
60
+ case "scroll":
61
+ case "view":
62
+ case "custom":
63
+ default:
64
+ return void 0;
65
+ }
66
+ }
67
+ function deriveInteractable(type, handlerNames) {
68
+ if (INTERACTIVE_TYPES.has(type)) return true;
69
+ if (handlerNames) {
70
+ for (const name of handlerNames) {
71
+ if (INTERACTIVE_HANDLER_NAMES.has(name)) return true;
72
+ }
73
+ }
74
+ return false;
75
+ }
76
+ function deriveText(state, label) {
77
+ const candidates = [state.value, state.textContent, label];
78
+ for (const c of candidates) {
79
+ if (typeof c === "string") {
80
+ const trimmed = c.trim();
81
+ if (trimmed.length > 0) return trimmed;
82
+ }
83
+ }
84
+ return void 0;
85
+ }
86
+ var NAMED_COLORS = {
87
+ black: { r: 0, g: 0, b: 0 },
88
+ white: { r: 255, g: 255, b: 255 },
89
+ red: { r: 255, g: 0, b: 0 },
90
+ green: { r: 0, g: 128, b: 0 },
91
+ blue: { r: 0, g: 0, b: 255 },
92
+ gray: { r: 128, g: 128, b: 128 },
93
+ grey: { r: 128, g: 128, b: 128 },
94
+ silver: { r: 192, g: 192, b: 192 },
95
+ transparent: { r: 0, g: 0, b: 0 },
96
+ orange: { r: 255, g: 165, b: 0 },
97
+ yellow: { r: 255, g: 255, b: 0 },
98
+ purple: { r: 128, g: 0, b: 128 },
99
+ navy: { r: 0, g: 0, b: 128 }
100
+ };
101
+ var clamp255 = (n) => Math.max(0, Math.min(255, Math.round(n)));
102
+ function parseColorToRgb(input) {
103
+ if (typeof input !== "string") return void 0;
104
+ const raw = input.trim().toLowerCase();
105
+ if (raw.length === 0) return void 0;
106
+ if (Object.prototype.hasOwnProperty.call(NAMED_COLORS, raw)) {
107
+ return NAMED_COLORS[raw];
108
+ }
109
+ if (raw.startsWith("#")) {
110
+ const hex = raw.slice(1);
111
+ if (hex.length === 3 || hex.length === 4) {
112
+ const r = parseInt(hex[0] + hex[0], 16);
113
+ const g = parseInt(hex[1] + hex[1], 16);
114
+ const b = parseInt(hex[2] + hex[2], 16);
115
+ if ([r, g, b].every((v) => Number.isFinite(v))) return { r, g, b };
116
+ return void 0;
117
+ }
118
+ if (hex.length === 6 || hex.length === 8) {
119
+ const r = parseInt(hex.slice(0, 2), 16);
120
+ const g = parseInt(hex.slice(2, 4), 16);
121
+ const b = parseInt(hex.slice(4, 6), 16);
122
+ if ([r, g, b].every((v) => Number.isFinite(v))) return { r, g, b };
123
+ return void 0;
124
+ }
125
+ return void 0;
126
+ }
127
+ const rgbMatch = raw.match(/^rgba?\(([^)]+)\)$/);
128
+ if (rgbMatch) {
129
+ const parts = rgbMatch[1].split(",").map((p) => p.trim());
130
+ if (parts.length < 3) return void 0;
131
+ const channel = (p) => {
132
+ if (p.endsWith("%")) {
133
+ const pct = parseFloat(p.slice(0, -1));
134
+ if (!Number.isFinite(pct)) return void 0;
135
+ return clamp255(pct / 100 * 255);
136
+ }
137
+ const n = parseFloat(p);
138
+ if (!Number.isFinite(n)) return void 0;
139
+ return clamp255(n);
140
+ };
141
+ const r = channel(parts[0]);
142
+ const g = channel(parts[1]);
143
+ const b = channel(parts[2]);
144
+ if (r === void 0 || g === void 0 || b === void 0) return void 0;
145
+ return { r, g, b };
146
+ }
147
+ return void 0;
148
+ }
149
+ function parseFontSizePx(input) {
150
+ if (typeof input === "number") {
151
+ return Number.isFinite(input) && input > 0 ? input : void 0;
152
+ }
153
+ if (typeof input === "string") {
154
+ const m = input.trim().match(/^(-?\d*\.?\d+)/);
155
+ if (m) {
156
+ const n = parseFloat(m[1]);
157
+ return Number.isFinite(n) && n > 0 ? n : void 0;
158
+ }
159
+ }
160
+ return void 0;
161
+ }
162
+ function projectVisionFields(args) {
163
+ const { type, label, handlerNames, state, flatStyle } = args;
164
+ const fields = {
165
+ interactable: deriveInteractable(type, handlerNames)
166
+ };
167
+ const text = deriveText(state, label);
168
+ if (text !== void 0) fields.text = text;
169
+ const role = roleForType(type);
170
+ if (role !== void 0) fields.role = role;
171
+ if (flatStyle) {
172
+ const fg = parseColorToRgb(flatStyle.color);
173
+ if (fg !== void 0) fields.fg_color = fg;
174
+ const bg = parseColorToRgb(flatStyle.backgroundColor);
175
+ if (bg !== void 0) fields.bg_color = bg;
176
+ const size = parseFontSizePx(flatStyle.fontSize);
177
+ if (size !== void 0) fields.font_size_px = size;
178
+ if (typeof flatStyle.fontFamily === "string" && flatStyle.fontFamily.trim().length > 0) {
179
+ fields.font_family = flatStyle.fontFamily;
180
+ }
181
+ }
182
+ return fields;
183
+ }
184
+
12
185
  // src/core/registry.ts
13
186
  function extractHandlerNames(props) {
14
187
  if (!props) return [];
@@ -18,6 +191,25 @@ function matchesCurrentRoute(registrationRoute, currentRoute) {
18
191
  if (registrationRoute == null || registrationRoute === "") return true;
19
192
  return registrationRoute === currentRoute;
20
193
  }
194
+ function projectBbox(state, visibility, pixelRatio = 1) {
195
+ if (visibility !== "visible") return void 0;
196
+ const layout = state.layout;
197
+ if (!layout) return void 0;
198
+ const ratio = pixelRatio > 0 && Number.isFinite(pixelRatio) ? pixelRatio : 1;
199
+ const toPx = (v) => Math.max(0, Math.round(v * ratio));
200
+ const hasPage = typeof layout.pageX === "number" && typeof layout.pageY === "number" && Number.isFinite(layout.pageX) && Number.isFinite(layout.pageY);
201
+ const originX = hasPage ? layout.pageX : layout.x;
202
+ const originY = hasPage ? layout.pageY : layout.y;
203
+ if (typeof originX !== "number" || typeof originY !== "number" || typeof layout.width !== "number" || typeof layout.height !== "number" || !Number.isFinite(originX) || !Number.isFinite(originY) || !Number.isFinite(layout.width) || !Number.isFinite(layout.height)) {
204
+ return void 0;
205
+ }
206
+ return {
207
+ x: toPx(originX),
208
+ y: toPx(originY),
209
+ w: toPx(layout.width),
210
+ h: toPx(layout.height)
211
+ };
212
+ }
21
213
  function inferActions(type) {
22
214
  const baseActions = ["focus", "blur"];
23
215
  switch (type) {
@@ -82,6 +274,15 @@ var NativeUIBridgeRegistry = class {
82
274
  * already installs.
83
275
  */
84
276
  this.routeProvider = null;
277
+ /**
278
+ * Device pixel ratio used to project `state.layout` (logical dp) into the
279
+ * physical-pixel `bbox` emitted on each snapshot element. Defaults to `1`
280
+ * (dp ≈ px) so callers/tests that never inject a ratio still get a usable
281
+ * box; the React provider wires the real `PixelRatio.get()` via
282
+ * {@link setPixelRatio}. Read from a non-React core module on purpose — see
283
+ * the `projectBbox` doc comment for why we don't import `react-native` here.
284
+ */
285
+ this.pixelRatio = 1;
85
286
  /**
86
287
  * Sticky flag: flips `true` the first time any element is registered and
87
288
  * stays `true` even after elements are unregistered. Lets agents distinguish
@@ -119,6 +320,21 @@ var NativeUIBridgeRegistry = class {
119
320
  getRouteProvider() {
120
321
  return this.routeProvider;
121
322
  }
323
+ /**
324
+ * Set the device pixel ratio used to project per-element `bbox` geometry
325
+ * into physical pixels. The React provider passes `PixelRatio.get()` here
326
+ * once at startup. Ignores non-finite / non-positive values (keeps the
327
+ * previous ratio) so a bad call can't zero out every bbox.
328
+ */
329
+ setPixelRatio(ratio) {
330
+ if (typeof ratio === "number" && Number.isFinite(ratio) && ratio > 0) {
331
+ this.pixelRatio = ratio;
332
+ }
333
+ }
334
+ /** Read-only accessor for the device pixel ratio used for bbox projection. */
335
+ getPixelRatio() {
336
+ return this.pixelRatio;
337
+ }
122
338
  // ============================================================================
123
339
  // Snapshot Enricher Slots
124
340
  // ============================================================================
@@ -658,6 +874,18 @@ var NativeUIBridgeRegistry = class {
658
874
  const handlers = extractHandlerNames(e.props);
659
875
  const state = e.getState();
660
876
  const visibility = !state.visible ? "hidden" : state.layout !== null ? "visible" : "likely-visible";
877
+ const bbox = projectBbox(state, visibility, this.pixelRatio);
878
+ const vision = projectVisionFields({
879
+ type: e.type,
880
+ label: e.label,
881
+ // Real interactivity signal: the names of props that are actually
882
+ // functions (onPress/onChangeText/...). NOT `e.actions`, which
883
+ // `inferActions` synthesizes press/click onto for every element —
884
+ // using it would mark plain text/view nodes interactable.
885
+ handlerNames: handlers,
886
+ state,
887
+ flatStyle: e.flatStyle
888
+ });
661
889
  return {
662
890
  id: e.id,
663
891
  type: e.type,
@@ -668,7 +896,9 @@ var NativeUIBridgeRegistry = class {
668
896
  customActions: e.customActions ? Object.keys(e.customActions) : void 0,
669
897
  registeredHandlers: handlers.length > 0 ? handlers : void 0,
670
898
  registrationRoute: e.registrationRoute,
671
- visibility
899
+ visibility,
900
+ ...bbox ? { bbox } : {},
901
+ ...vision
672
902
  };
673
903
  }),
674
904
  components: this.getAllComponents().map((c) => ({
@@ -1894,7 +2124,7 @@ function createDesignHandlers(registry, viewportProvider) {
1894
2124
  var GRID_SIZE = 20;
1895
2125
  var NAV_TYPES = /* @__PURE__ */ new Set(["button", "heading", "badge", "status-message"]);
1896
2126
  var SKIP_TEXT_TYPES = /* @__PURE__ */ new Set(["button", "link", "tab", "menuitem"]);
1897
- var INTERACTIVE_TYPES = /* @__PURE__ */ new Set([
2127
+ var INTERACTIVE_TYPES2 = /* @__PURE__ */ new Set([
1898
2128
  "button",
1899
2129
  "input",
1900
2130
  "switch",
@@ -2091,7 +2321,7 @@ function diagnosePageHealth(elements, viewport) {
2091
2321
  let interactiveTotal = 0;
2092
2322
  let interactiveDisabled = 0;
2093
2323
  for (const el of elements) {
2094
- if (!INTERACTIVE_TYPES.has(el.type)) continue;
2324
+ if (!INTERACTIVE_TYPES2.has(el.type)) continue;
2095
2325
  interactiveTotal++;
2096
2326
  if (el.state.enabled === false) interactiveDisabled++;
2097
2327
  }
@@ -2374,6 +2604,16 @@ function createServerHandlers(registry, executor, config) {
2374
2604
  const handlers = extractHandlerNames(e.props);
2375
2605
  const state = e.getState();
2376
2606
  const visibility = !state.visible ? "hidden" : state.layout !== null ? "visible" : "likely-visible";
2607
+ const bbox = projectBbox(state, visibility, registry.getPixelRatio());
2608
+ const vision = projectVisionFields({
2609
+ type: e.type,
2610
+ label: e.label,
2611
+ // Real handler names (onPress/...), NOT inferred actions which
2612
+ // synthesize press/click onto every element. See projectVisionFields.
2613
+ handlerNames: handlers,
2614
+ state,
2615
+ flatStyle: e.flatStyle
2616
+ });
2377
2617
  return {
2378
2618
  id: e.id,
2379
2619
  type: e.type,
@@ -2384,7 +2624,9 @@ function createServerHandlers(registry, executor, config) {
2384
2624
  customActions: e.customActions ? Object.keys(e.customActions) : void 0,
2385
2625
  registeredHandlers: handlers.length > 0 ? handlers : void 0,
2386
2626
  registrationRoute: e.registrationRoute,
2387
- visibility
2627
+ visibility,
2628
+ ...bbox ? { bbox } : {},
2629
+ ...vision
2388
2630
  };
2389
2631
  });
2390
2632
  return success2({ elements });
@@ -3067,7 +3309,7 @@ function createServerHandlers(registry, executor, config) {
3067
3309
  };
3068
3310
  if (config?.appInfo) {
3069
3311
  response.uiBridge = {
3070
- version: "0.6.10",
3312
+ version: "0.6.11",
3071
3313
  ...config.appInfo,
3072
3314
  capabilities: ["elements", "components", "actions", "design"],
3073
3315
  elementCount: stats.elements,
@@ -3659,6 +3901,14 @@ var NativeUIBridgeServer = class {
3659
3901
  };
3660
3902
  };
3661
3903
  }
3904
+ /**
3905
+ * Whether the console/network capture should be installed. The dedicated
3906
+ * `observability` flag wins when set; otherwise falls back to `testHooks`
3907
+ * so consumers predating the flag keep their exact behavior.
3908
+ */
3909
+ observabilityEnabled() {
3910
+ return this.config.observability ?? this.config.testHooks === true;
3911
+ }
3662
3912
  /**
3663
3913
  * Set the server adapter
3664
3914
  */
@@ -3872,7 +4122,7 @@ var NativeUIBridgeServer = class {
3872
4122
  console.warn("[ui-bridge-native] See documentation for supported adapters.");
3873
4123
  return;
3874
4124
  }
3875
- if (this.config.testHooks === true) {
4125
+ if (this.observabilityEnabled()) {
3876
4126
  this.consoleErrorBuffer.install();
3877
4127
  this.networkRequestBuffer.install();
3878
4128
  }
@@ -5374,6 +5624,7 @@ function UIBridgeNativeProvider({
5374
5624
  verbose: config.verbose,
5375
5625
  onEvent
5376
5626
  });
5627
+ registryRef.current.setPixelRatio(PixelRatio.get());
5377
5628
  setGlobalRegistry(registryRef.current);
5378
5629
  }
5379
5630
  const registry = registryRef.current;
@@ -5404,6 +5655,10 @@ function UIBridgeNativeProvider({
5404
5655
  cors: true,
5405
5656
  appInfo: config.appInfo,
5406
5657
  testHooks: features.testHooks === true,
5658
+ // Dedicated console/network-capture flag; the server defaults it to
5659
+ // the `testHooks` value when undefined, so passing it through verbatim
5660
+ // keeps existing consumers unchanged.
5661
+ observability: features.observability,
5407
5662
  // Injected device-viewport getter for POST /control/page-health. The
5408
5663
  // server doesn't import `react-native` itself — the require/import
5409
5664
  // pattern there crashed the host RN app in 0.6.3/0.6.4 (Metro/Hermes
@@ -5471,6 +5726,7 @@ function UIBridgeNativeProvider({
5471
5726
  }, [
5472
5727
  features.server,
5473
5728
  features.testHooks,
5729
+ features.observability,
5474
5730
  config.serverPort,
5475
5731
  config.appInfo,
5476
5732
  registry,
@@ -5509,6 +5765,7 @@ function UIBridgeNativeProvider({
5509
5765
  cors: true,
5510
5766
  appInfo: config.appInfo,
5511
5767
  testHooks: features.testHooks === true,
5768
+ observability: features.observability,
5512
5769
  viewportProvider: () => {
5513
5770
  const win = Dimensions.get("window");
5514
5771
  return { width: win.width, height: win.height };
@@ -5712,12 +5969,41 @@ function scheduleDeadButtonWarning(bridge, id, type) {
5712
5969
  }
5713
5970
  function useUIElement(options) {
5714
5971
  const bridge = useUIBridgeNativeOptional();
5715
- const ref = useRef(null);
5716
5972
  const [registered, setRegistered] = useState(false);
5717
5973
  const [_layout, setLayout] = useState(null);
5718
5974
  const propsRef = useRef({});
5719
5975
  const registeredRef = useRef(false);
5720
5976
  const registeredIdRef = useRef(null);
5977
+ const bridgeRef = useRef(bridge);
5978
+ bridgeRef.current = bridge;
5979
+ const nodeRef = useRef(null);
5980
+ const refInterceptorRef = useRef(null);
5981
+ if (refInterceptorRef.current === null) {
5982
+ refInterceptorRef.current = {
5983
+ get current() {
5984
+ return nodeRef.current;
5985
+ },
5986
+ set current(node) {
5987
+ const prev = nodeRef.current;
5988
+ nodeRef.current = node;
5989
+ const liveBridge = bridgeRef.current;
5990
+ const registeredId = registeredIdRef.current;
5991
+ if (!liveBridge || !registeredRef.current || registeredId === null) return;
5992
+ if (node == null && prev != null) {
5993
+ const state = liveBridge.registry.getElement(registeredId)?.getState();
5994
+ if (state && state.visible !== false) {
5995
+ liveBridge.registry.updateElementState(registeredId, { visible: false });
5996
+ }
5997
+ } else if (node != null && prev == null) {
5998
+ const state = liveBridge.registry.getElement(registeredId)?.getState();
5999
+ if (state && state.visible !== true) {
6000
+ liveBridge.registry.updateElementState(registeredId, { visible: true });
6001
+ }
6002
+ }
6003
+ }
6004
+ };
6005
+ }
6006
+ const ref = refInterceptorRef.current;
5721
6007
  const {
5722
6008
  id,
5723
6009
  type = "custom",
@@ -5761,7 +6047,7 @@ function useUIElement(options) {
5761
6047
  }
5762
6048
  setRegistered(true);
5763
6049
  scheduleDeadButtonWarning(bridge, id, type);
5764
- }, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp]);
6050
+ }, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp, ref]);
5765
6051
  const unregister = useCallback(() => {
5766
6052
  if (!bridge || !registeredRef.current) return;
5767
6053
  bridge.registry.unregisterElement(registeredIdRef.current ?? id);
@@ -5797,7 +6083,8 @@ function useUIElement(options) {
5797
6083
  writeLayout({ x, y, width, height, pageX: x, pageY: y });
5798
6084
  }
5799
6085
  },
5800
- [bridge, id]
6086
+ // `ref` is the once-per-hook interceptor object — identity-stable.
6087
+ [bridge, id, ref]
5801
6088
  );
5802
6089
  const registerRef = useRef(register);
5803
6090
  const unregisterRef = useRef(unregister);
@@ -5818,7 +6105,14 @@ function useUIElement(options) {
5818
6105
  useEffect(() => {
5819
6106
  if (!bridge || !registered) return;
5820
6107
  const node = ref.current;
5821
- if (!node || typeof node.measureInWindow !== "function") return;
6108
+ if (!node) {
6109
+ const seeded = bridge.registry.getElement(id)?.getState();
6110
+ if (seeded && seeded.visible !== false) {
6111
+ bridge.registry.updateElementState(id, { visible: false });
6112
+ }
6113
+ return;
6114
+ }
6115
+ if (typeof node.measureInWindow !== "function") return;
5822
6116
  let cancelled = false;
5823
6117
  let pendingTimer = null;
5824
6118
  const backoffMs = [50, 200, 500, 1e3, 2500];
@@ -5857,7 +6151,7 @@ function useUIElement(options) {
5857
6151
  cancelled = true;
5858
6152
  if (pendingTimer != null) clearTimeout(pendingTimer);
5859
6153
  };
5860
- }, [bridge, registered, id]);
6154
+ }, [bridge, registered, id, ref]);
5861
6155
  const registeredHandlerKeysRef = useRef([]);
5862
6156
  useEffect(() => {
5863
6157
  if (!bridge || !registered || !handlersProp) return;
@@ -7245,6 +7539,6 @@ var styles = StyleSheet.create({
7245
7539
  }
7246
7540
  });
7247
7541
 
7248
- export { CloudRelayClient, DefaultNativeActionExecutor, DeviceAnnouncer, ModalDetector, NativeUIBridgeRegistry, NativeUIBridgeServer, State, ToastCapture, TransitionTo, UIBridgeInspector, UIBridgeNativeProvider, UI_BRIDGE_NATIVE_ROUTES, UndoTracker, WebSocketConnection, WebSocketEventBridge, bindWithRetry, buildTreePath, buildUpgradeResponse, captureNativeResponsiveSnapshot, captureNativeStateVariations, computeAcceptKey, createDesignHandlers, createNativeActionExecutor, createNativeElementIdentifier, createNativeServer, createServerHandlers, extractHandlerNames, findAllByPattern, findElementByIdentifier, getGlobalRegistry, getNativeElementDesignData, isAddrInUseError, mapNativeStyleToExtended, matchesIdentifier, parseTreePath, resetGlobalRegistry, setGlobalRegistry, useToastRecorder, useUIBridge, useUIBridgeModal, useUIBridgeNative, useUIBridgeNativeOptional, useUIBridgeNativeRequired, useUIBridgeRequired, useUIBridgeToast, useUIComponent, useUIComponentAction, useUIElement, useUIElementWithProps };
7542
+ export { CloudRelayClient, DefaultNativeActionExecutor, DeviceAnnouncer, ModalDetector, NativeUIBridgeRegistry, NativeUIBridgeServer, State, ToastCapture, TransitionTo, UIBridgeInspector, UIBridgeNativeProvider, UI_BRIDGE_NATIVE_ROUTES, UndoTracker, WebSocketConnection, WebSocketEventBridge, bindWithRetry, buildTreePath, buildUpgradeResponse, captureNativeResponsiveSnapshot, captureNativeStateVariations, computeAcceptKey, createDesignHandlers, createNativeActionExecutor, createNativeElementIdentifier, createNativeServer, createServerHandlers, deriveInteractable, deriveText, extractHandlerNames, findAllByPattern, findElementByIdentifier, getGlobalRegistry, getNativeElementDesignData, isAddrInUseError, mapNativeStyleToExtended, matchesIdentifier, parseColorToRgb, parseFontSizePx, parseTreePath, projectVisionFields, resetGlobalRegistry, roleForType, setGlobalRegistry, useToastRecorder, useUIBridge, useUIBridgeModal, useUIBridgeNative, useUIBridgeNativeOptional, useUIBridgeNativeRequired, useUIBridgeRequired, useUIBridgeToast, useUIComponent, useUIComponentAction, useUIElement, useUIElementWithProps };
7249
7543
  //# sourceMappingURL=index.mjs.map
7250
7544
  //# sourceMappingURL=index.mjs.map