@qontinui/ui-bridge-native 0.6.5 → 0.6.6

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
@@ -14,6 +14,10 @@ function extractHandlerNames(props) {
14
14
  if (!props) return [];
15
15
  return Object.keys(props).filter((k) => typeof props[k] === "function");
16
16
  }
17
+ function matchesCurrentRoute(registrationRoute, currentRoute) {
18
+ if (registrationRoute == null || registrationRoute === "") return true;
19
+ return registrationRoute === currentRoute;
20
+ }
17
21
  function inferActions(type) {
18
22
  const baseActions = ["focus", "blur"];
19
23
  switch (type) {
@@ -219,13 +223,20 @@ var NativeUIBridgeRegistry = class {
219
223
  if (this.config.verbose) {
220
224
  console.log(`[ui-bridge-native] Registered element: ${id} (${type})`);
221
225
  }
222
- this.updateElementState(id, {
226
+ const seededState = {
223
227
  mounted: true,
224
228
  visible: true,
225
229
  enabled: true,
226
230
  focused: false,
227
231
  layout: null
228
- });
232
+ };
233
+ if (type === "input" && typeof props?.value === "string") {
234
+ seededState.value = props.value;
235
+ }
236
+ if (type === "text" && typeof label === "string") {
237
+ seededState.value = label;
238
+ }
239
+ this.updateElementState(id, seededState);
229
240
  return registered;
230
241
  }
231
242
  /**
@@ -387,6 +398,9 @@ var NativeUIBridgeRegistry = class {
387
398
  })
388
399
  };
389
400
  this.elements.set(id, updated);
401
+ if (element.type === "text" && labelChanged && typeof nextLabel === "string") {
402
+ this.updateElementState(id, { value: nextLabel });
403
+ }
390
404
  this.emit("element:registered", {
391
405
  id,
392
406
  type: element.type,
@@ -395,7 +409,22 @@ var NativeUIBridgeRegistry = class {
395
409
  return true;
396
410
  }
397
411
  /**
398
- * Update element props (for action execution)
412
+ * Update element props (for action execution).
413
+ *
414
+ * Side effect for `type: 'input'` elements: when `props.value` is a string,
415
+ * mirror it into `state.value` so AI drivers reading the registry don't see
416
+ * `state.value === undefined` until the user types. Before this mirror,
417
+ * controlled-input consumers (`<TextInput value={x} onChangeText={setX} />`
418
+ * with `captureProps({ value: x, onChangeText: setX })`) registered an
419
+ * input whose `state.value` only became defined after the FIRST
420
+ * `onChangeText` call — bridge consumers couldn't read the default value
421
+ * (e.g. a pre-populated API-URL input) until someone typed into it.
422
+ *
423
+ * Re-runs on every `updateElementProps` so a parent passing a fresh
424
+ * `value` prop (controlled re-render) keeps the registry in sync. The
425
+ * mirror is gated on `type === 'input'` to avoid touching non-input
426
+ * elements that may carry an unrelated `value` prop (e.g. a Switch's
427
+ * boolean value, which lives on `state.checked`).
399
428
  */
400
429
  updateElementProps(id, props) {
401
430
  const element = this.elements.get(id);
@@ -405,6 +434,12 @@ var NativeUIBridgeRegistry = class {
405
434
  props: { ...element.props, ...props }
406
435
  };
407
436
  this.elements.set(id, updated);
437
+ if (element.type === "input" && Object.prototype.hasOwnProperty.call(props, "value") && typeof props.value === "string") {
438
+ const currentState = updated.getState();
439
+ if (currentState.value !== props.value) {
440
+ this.updateElementState(id, { value: props.value });
441
+ }
442
+ }
408
443
  }
409
444
  }
410
445
  /**
@@ -615,7 +650,7 @@ var NativeUIBridgeRegistry = class {
615
650
  let elements = options?.visibleOnly ? this.getMountedVisibleElements() : this.getAllElements();
616
651
  if (options?.currentRouteOnly && resolvedRoute.currentRoute) {
617
652
  const currentRoute = resolvedRoute.currentRoute;
618
- elements = elements.filter((e) => e.registrationRoute === currentRoute);
653
+ elements = elements.filter((e) => matchesCurrentRoute(e.registrationRoute, currentRoute));
619
654
  }
620
655
  const snapshot = {
621
656
  timestamp: Date.now(),
@@ -1606,15 +1641,9 @@ function success(data) {
1606
1641
  function error(message, code) {
1607
1642
  return { success: false, error: message, code, timestamp: Date.now() };
1608
1643
  }
1609
- function createDesignHandlers(registry) {
1644
+ function createDesignHandlers(registry, viewportProvider) {
1610
1645
  function getScreenDimensions() {
1611
- try {
1612
- const { Dimensions: Dimensions3 } = __require("react-native");
1613
- const screen = Dimensions3.get("screen");
1614
- return { width: screen.width, height: screen.height };
1615
- } catch {
1616
- return { width: 0, height: 0 };
1617
- }
1646
+ return viewportProvider?.() ?? { width: 0, height: 0 };
1618
1647
  }
1619
1648
  return {
1620
1649
  // 1. GET /design/element/:id/styles
@@ -2260,7 +2289,7 @@ function error2(message, code) {
2260
2289
  };
2261
2290
  }
2262
2291
  function createServerHandlers(registry, executor, config) {
2263
- const designHandlers = createDesignHandlers(registry);
2292
+ const designHandlers = createDesignHandlers(registry, config?.viewportProvider);
2264
2293
  return {
2265
2294
  // Elements
2266
2295
  getElements: async (ctx) => {
@@ -2268,7 +2297,7 @@ function createServerHandlers(registry, executor, config) {
2268
2297
  const forRoute = ctx.query?.route || ctx.body?.route;
2269
2298
  let allElements = visibleOnly ? registry.getMountedVisibleElements() : registry.getAllElements();
2270
2299
  if (forRoute) {
2271
- allElements = allElements.filter((e) => e.registrationRoute === forRoute);
2300
+ allElements = allElements.filter((e) => matchesCurrentRoute(e.registrationRoute, forRoute));
2272
2301
  }
2273
2302
  const elements = allElements.map((e) => {
2274
2303
  const handlers = extractHandlerNames(e.props);