@qontinui/ui-bridge-native 0.3.2 → 0.5.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.
- package/dist/control/{index.d.mts → action-executor.d.ts} +6 -10
- package/dist/control/action-executor.d.ts.map +1 -0
- package/dist/control/index.d.ts +5 -95
- package/dist/control/index.d.ts.map +1 -0
- package/dist/{types-CjEKTDYT.d.ts → control/types.d.ts} +17 -20
- package/dist/control/types.d.ts.map +1 -0
- package/dist/core/element-identifier.d.ts +41 -0
- package/dist/core/element-identifier.d.ts.map +1 -0
- package/dist/core/index.d.ts +6 -43
- package/dist/core/index.d.ts.map +1 -0
- package/dist/{registry-pAUpQq2O.d.ts → core/registry.d.ts} +10 -13
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/{types-CGVut7mc.d.mts → core/types.d.ts} +41 -41
- package/dist/core/types.d.ts.map +1 -0
- package/dist/debug/index.d.ts +4 -44
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/index.js +1 -1
- package/dist/debug/index.js.map +1 -1
- package/dist/debug/index.mjs +2 -2
- package/dist/debug/index.mjs.map +1 -1
- package/dist/debug/{index.d.mts → inspector.d.ts} +3 -6
- package/dist/debug/inspector.d.ts.map +1 -0
- package/dist/design/{index.d.mts → design-inspector-native.d.ts} +7 -11
- package/dist/design/design-inspector-native.d.ts.map +1 -0
- package/dist/{design-types-BHr6Q1FX.d.mts → design/design-types.d.ts} +10 -11
- package/dist/design/design-types.d.ts.map +1 -0
- package/dist/design/index.d.ts +5 -60
- package/dist/design/index.d.ts.map +1 -0
- package/dist/index.d.ts +37 -86
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +61 -5
- package/dist/index.mjs.map +1 -1
- package/dist/modal/index.d.ts +2 -0
- package/dist/modal/index.d.ts.map +1 -0
- package/dist/modal/modal-detector.d.ts +29 -0
- package/dist/modal/modal-detector.d.ts.map +1 -0
- package/dist/react/StateAnnotation.d.ts +30 -0
- package/dist/react/StateAnnotation.d.ts.map +1 -0
- package/dist/react/UIBridgeNativeProvider.d.ts +163 -0
- package/dist/react/UIBridgeNativeProvider.d.ts.map +1 -0
- package/dist/react/index.d.ts +14 -69
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +60 -4
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +61 -5
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/{index.d.mts → useAutoRegister.d.ts} +7 -15
- package/dist/react/useAutoRegister.d.ts.map +1 -0
- package/dist/react/useUIBridge.d.ts +103 -0
- package/dist/react/useUIBridge.d.ts.map +1 -0
- package/dist/react/useUIBridgeModal.d.ts +14 -0
- package/dist/react/useUIBridgeModal.d.ts.map +1 -0
- package/dist/react/useUIBridgeToast.d.ts +25 -0
- package/dist/react/useUIBridgeToast.d.ts.map +1 -0
- package/dist/react/useUIComponent.d.ts +112 -0
- package/dist/react/useUIComponent.d.ts.map +1 -0
- package/dist/react/useUIElement.d.ts +162 -0
- package/dist/react/useUIElement.d.ts.map +1 -0
- package/dist/server/design-handlers.d.ts +47 -0
- package/dist/server/design-handlers.d.ts.map +1 -0
- package/dist/server/handlers.d.ts +25 -0
- package/dist/server/handlers.d.ts.map +1 -0
- package/dist/server/http-server.d.ts +269 -0
- package/dist/server/http-server.d.ts.map +1 -0
- package/dist/server/index.d.ts +14 -176
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +51 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +51 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/observability.d.ts +55 -0
- package/dist/server/observability.d.ts.map +1 -0
- package/dist/server/types.d.ts +377 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/ws-connection.d.ts +48 -0
- package/dist/server/ws-connection.d.ts.map +1 -0
- package/dist/server/ws-event-bridge.d.ts +113 -0
- package/dist/server/ws-event-bridge.d.ts.map +1 -0
- package/dist/server/ws-protocol.d.ts +48 -0
- package/dist/server/ws-protocol.d.ts.map +1 -0
- package/dist/server/ws-types.d.ts +65 -0
- package/dist/server/ws-types.d.ts.map +1 -0
- package/dist/toast/index.d.ts +2 -0
- package/dist/toast/index.d.ts.map +1 -0
- package/dist/toast/toast-capture.d.ts +27 -0
- package/dist/toast/toast-capture.d.ts.map +1 -0
- package/dist/transport/CloudRelayClient.d.ts +51 -0
- package/dist/transport/CloudRelayClient.d.ts.map +1 -0
- package/dist/transport/DeviceAnnouncer.d.ts +75 -0
- package/dist/transport/DeviceAnnouncer.d.ts.map +1 -0
- package/dist/transport/index.d.ts +3 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/logger.d.ts +23 -0
- package/dist/transport/logger.d.ts.map +1 -0
- package/dist/undo/index.d.ts +3 -0
- package/dist/undo/index.d.ts.map +1 -0
- package/dist/undo/undo-tracker.d.ts +59 -0
- package/dist/undo/undo-tracker.d.ts.map +1 -0
- package/package.json +3 -3
- package/dist/StateAnnotation--zm0Jfqj.d.ts +0 -755
- package/dist/StateAnnotation-BgFoVWFy.d.mts +0 -755
- package/dist/core/index.d.mts +0 -46
- package/dist/design-types-BHr6Q1FX.d.ts +0 -205
- package/dist/http-server--550eD1F.d.mts +0 -805
- package/dist/http-server-C9NaNBEP.d.ts +0 -805
- package/dist/index.d.mts +0 -89
- package/dist/registry-B5JadBN9.d.mts +0 -300
- package/dist/server/index.d.mts +0 -178
- package/dist/types-B0XA4vOF.d.mts +0 -197
- package/dist/types-CGVut7mc.d.ts +0 -567
package/dist/debug/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/design-handlers.ts","../../src/react/UIBridgeNativeProvider.tsx","../../src/debug/inspector.tsx"],"names":["jsx","useState","useMemo","useCallback"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * UI Bridge Native Design Review Handlers\n *\n * HTTP handlers for the 8 design review endpoints.\n * Maps registered element styles to the web SDK's design data format.\n */\n\nimport type { NativeUIBridgeRegistry } from '../core/registry';\nimport type { APIResponse, HandlerContext } from './types';\nimport type { ElementDesignData, StateStyles, ResponsiveSnapshot } from '../design/design-types';\nimport {\n mapNativeStyleToExtended,\n getNativeElementDesignData,\n captureNativeStateVariations,\n captureNativeResponsiveSnapshot,\n} from '../design/design-inspector-native';\n\n// Style guide and baseline stored in closure (same pattern as web SDK)\nlet loadedStyleGuide: unknown = null;\nlet savedBaseline: unknown = null;\n\n// Try to load the style validator from the web SDK (optional peer dep)\nlet styleValidator: {\n runStyleAudit: (\n elements: Array<{ elementId: string; styles: Record<string, string> }>,\n guide: unknown\n ) => unknown;\n} | null = null;\n\n// Try to load quality evaluator from the web SDK (optional peer dep)\nlet qualityEvaluator: {\n evaluateQuality: (\n elements: ElementDesignData[],\n viewport: { width: number; height: number },\n context?: unknown\n ) => unknown;\n listContexts: () => Array<{ name: string; description: string }>;\n createBaseline: (\n elements: ElementDesignData[],\n viewport: { width: number; height: number },\n label?: string\n ) => unknown;\n diffSnapshots: (baseline: unknown, current: ElementDesignData[]) => unknown;\n} | null = null;\n\ntry {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const specs = require('@qontinui/ui-bridge/specs');\n styleValidator = specs;\n qualityEvaluator = specs;\n} catch {\n // Optional dependency not installed — audit/evaluate endpoints will return an error\n}\n\nfunction success<T>(data: T): APIResponse<T> {\n return { success: true, data, timestamp: Date.now() };\n}\n\nfunction error<T = unknown>(message: string, code?: string): APIResponse<T> {\n return { success: false, error: message, code, timestamp: Date.now() };\n}\n\n/**\n * Design handler interface (subset of NativeServerHandlers)\n */\nexport interface NativeDesignHandlers {\n getElementStyles: (ctx: HandlerContext) => Promise<APIResponse<ElementDesignData>>;\n getElementStateStyles: (\n ctx: HandlerContext\n ) => Promise<APIResponse<{ elementId: string; stateStyles: StateStyles[] }>>;\n getDesignSnapshot: (\n ctx: HandlerContext\n ) => Promise<APIResponse<{ elements: ElementDesignData[]; timestamp: number }>>;\n getResponsiveSnapshots: (ctx: HandlerContext) => Promise<APIResponse<ResponsiveSnapshot[]>>;\n runDesignAudit: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;\n loadStyleGuide: (ctx: HandlerContext) => Promise<APIResponse<{ loaded: boolean }>>;\n getStyleGuide: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;\n clearStyleGuide: (ctx: HandlerContext) => Promise<APIResponse<{ cleared: boolean }>>;\n evaluateQuality: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;\n getQualityContexts: (\n ctx: HandlerContext\n ) => Promise<APIResponse<Array<{ name: string; description: string }>>>;\n saveBaseline: (\n ctx: HandlerContext\n ) => Promise<APIResponse<{ saved: boolean; elementCount: number }>>;\n diffBaseline: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;\n}\n\n/**\n * Create design review handlers.\n */\nexport function createDesignHandlers(registry: NativeUIBridgeRegistry): NativeDesignHandlers {\n // Helper to get screen dimensions (React Native's Dimensions API must be\n // called at handler time, not import time, so we use a lazy getter).\n function getScreenDimensions(): { width: number; height: number } {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { Dimensions } = require('react-native');\n const screen = Dimensions.get('screen');\n return { width: screen.width, height: screen.height };\n } catch {\n return { width: 0, height: 0 };\n }\n }\n\n return {\n // 1. GET /design/element/:id/styles\n getElementStyles: async (ctx) => {\n const { id } = ctx.params;\n const element = registry.getElement(id);\n\n if (!element) {\n return error('Element not found: ' + id, 'ELEMENT_NOT_FOUND');\n }\n\n const state = element.getState();\n const data = getNativeElementDesignData(\n id,\n element.label,\n element.type,\n element.flatStyle,\n state.layout\n );\n\n return success(data);\n },\n\n // 2. POST /design/element/:id/state-styles\n getElementStateStyles: async (ctx) => {\n const { id } = ctx.params;\n const element = registry.getElement(id);\n\n if (!element) {\n return error('Element not found: ' + id, 'ELEMENT_NOT_FOUND');\n }\n\n const stateStyles = captureNativeStateVariations(element.flatStyle, element.stateStyles);\n\n return success({ elementId: id, stateStyles });\n },\n\n // 3. POST /design/snapshot\n getDesignSnapshot: async (ctx) => {\n const body = ctx.body as\n | {\n elementIds?: string[];\n includePseudoElements?: boolean;\n }\n | undefined;\n\n let elements = registry.getAllElements();\n\n // Filter to requested IDs if specified\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n const designData: ElementDesignData[] = elements.map((el) => {\n const state = el.getState();\n return getNativeElementDesignData(el.id, el.label, el.type, el.flatStyle, state.layout);\n });\n\n return success({ elements: designData, timestamp: Date.now() });\n },\n\n // 4. POST /design/responsive\n getResponsiveSnapshots: async () => {\n // Platform limitation: RN cannot constrain screen width at runtime.\n // Returns a single snapshot at current device dimensions.\n const elements = registry.getAllElements();\n const elementData = elements.map((el) => {\n const state = el.getState();\n return {\n id: el.id,\n label: el.label,\n type: el.type,\n flatStyle: el.flatStyle,\n layout: state.layout,\n };\n });\n\n const snapshots = captureNativeResponsiveSnapshot(elementData, getScreenDimensions());\n return success(snapshots);\n },\n\n // 5. POST /design/audit\n runDesignAudit: async (ctx) => {\n const body = ctx.body as\n | {\n guide?: unknown;\n elementIds?: string[];\n }\n | undefined;\n\n const guide = body?.guide ?? loadedStyleGuide;\n\n if (!guide) {\n return error('No style guide loaded or provided', 'NO_STYLE_GUIDE');\n }\n\n if (!styleValidator) {\n return error(\n 'Install @qontinui/ui-bridge for style audit support. ' +\n 'Add it as a dependency: npm install @qontinui/ui-bridge',\n 'VALIDATOR_NOT_AVAILABLE'\n );\n }\n\n let elements = registry.getAllElements();\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n // Map elements to the format expected by the validator\n const auditElements = elements.map((el) => ({\n elementId: el.id,\n styles: mapNativeStyleToExtended(el.flatStyle) as unknown as Record<string, string>,\n }));\n\n try {\n const report = styleValidator.runStyleAudit(auditElements, guide);\n return success(report);\n } catch (err) {\n return error(\n 'Audit failed: ' + (err instanceof Error ? err.message : String(err)),\n 'DESIGN_AUDIT_ERROR'\n );\n }\n },\n\n // 6. POST /design/style-guide/load\n loadStyleGuide: async (ctx) => {\n const body = ctx.body as { guide?: unknown } | undefined;\n\n if (!body?.guide) {\n return error('Style guide is required in request body', 'INVALID_REQUEST');\n }\n\n loadedStyleGuide = body.guide;\n return success({ loaded: true });\n },\n\n // 7. GET /design/style-guide\n getStyleGuide: async () => {\n return success(loadedStyleGuide);\n },\n\n // 8. DELETE /design/style-guide\n clearStyleGuide: async () => {\n loadedStyleGuide = null;\n return success({ cleared: true });\n },\n\n // 9. POST /design/evaluate\n evaluateQuality: async (ctx) => {\n if (!qualityEvaluator) {\n return error(\n 'Install @qontinui/ui-bridge for quality evaluation support. ' +\n 'Add it as a dependency: npm install @qontinui/ui-bridge',\n 'EVALUATOR_NOT_AVAILABLE'\n );\n }\n\n const body = ctx.body as\n | {\n context?: string;\n customContext?: unknown;\n elementIds?: string[];\n viewport?: { width: number; height: number };\n }\n | undefined;\n\n let elements = registry.getAllElements();\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n const designData: ElementDesignData[] = elements.map((el) => {\n const state = el.getState();\n return getNativeElementDesignData(el.id, el.label, el.type, el.flatStyle, state.layout);\n });\n\n const viewport = body?.viewport ?? getScreenDimensions();\n\n // Resolve context: custom object > style guide context > built-in name\n let context: unknown = body?.customContext ?? body?.context ?? 'general';\n if (typeof context === 'string' && loadedStyleGuide) {\n const guide = loadedStyleGuide as { qualityContexts?: Record<string, unknown> };\n if (guide.qualityContexts?.[context]) {\n context = guide.qualityContexts[context];\n }\n }\n\n try {\n const report = qualityEvaluator.evaluateQuality(designData, viewport, context);\n return success(report);\n } catch (err) {\n return error(\n 'Evaluation failed: ' + (err instanceof Error ? err.message : String(err)),\n 'QUALITY_EVALUATION_ERROR'\n );\n }\n },\n\n // 10. GET /design/evaluate/contexts\n getQualityContexts: async () => {\n if (!qualityEvaluator) {\n return error(\n 'Install @qontinui/ui-bridge for quality evaluation support.',\n 'EVALUATOR_NOT_AVAILABLE'\n );\n }\n return success(qualityEvaluator.listContexts());\n },\n\n // 11. POST /design/evaluate/baseline\n saveBaseline: async (ctx) => {\n if (!qualityEvaluator) {\n return error(\n 'Install @qontinui/ui-bridge for quality evaluation support.',\n 'EVALUATOR_NOT_AVAILABLE'\n );\n }\n\n const body = ctx.body as\n | {\n label?: string;\n elementIds?: string[];\n }\n | undefined;\n\n let elements = registry.getAllElements();\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n const designData: ElementDesignData[] = elements.map((el) => {\n const state = el.getState();\n return getNativeElementDesignData(el.id, el.label, el.type, el.flatStyle, state.layout);\n });\n\n const viewport = getScreenDimensions();\n savedBaseline = qualityEvaluator.createBaseline(designData, viewport, body?.label);\n return success({ saved: true, elementCount: designData.length });\n },\n\n // 12. POST /design/evaluate/diff\n diffBaseline: async (ctx) => {\n if (!qualityEvaluator) {\n return error(\n 'Install @qontinui/ui-bridge for quality evaluation support.',\n 'EVALUATOR_NOT_AVAILABLE'\n );\n }\n\n if (!savedBaseline) {\n return error('No baseline saved. Call saveBaseline first.', 'NO_BASELINE');\n }\n\n const body = ctx.body as { elementIds?: string[] } | undefined;\n\n let elements = registry.getAllElements();\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n const designData: ElementDesignData[] = elements.map((el) => {\n const state = el.getState();\n return getNativeElementDesignData(el.id, el.label, el.type, el.flatStyle, state.layout);\n });\n\n try {\n const report = qualityEvaluator.diffSnapshots(savedBaseline, designData);\n return success(report);\n } catch (err) {\n return error(\n 'Diff failed: ' + (err instanceof Error ? err.message : String(err)),\n 'DIFF_BASELINE_ERROR'\n );\n }\n },\n };\n}\n","/**\n * UI Bridge Native Provider\n *\n * React context provider for UI Bridge Native functionality.\n */\n\nimport React, {\n createContext,\n useContext,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n useState,\n} from 'react';\nimport type {\n NativeUIBridgeFeatures,\n NativeUIBridgeConfig,\n RegisteredNativeElement,\n RegisteredNativeComponent,\n NativeBridgeSnapshot,\n BridgeEventType,\n BridgeEventListener,\n} from '../core/types';\nimport { NativeUIBridgeRegistry, setGlobalRegistry, resetGlobalRegistry } from '../core/registry';\nimport { createNativeActionExecutor } from '../control/action-executor';\nimport type { NativeActionExecutor } from '../control/types';\nimport {\n createNativeServer,\n type NativeUIBridgeServer,\n type ServerAdapter,\n type WebSocketServerAdapter,\n} from '../server/http-server';\nimport type { RouteProvider } from '../server/types';\nimport { WebSocketEventBridge } from '../server/ws-event-bridge';\nimport { DeviceAnnouncer } from '../transport/DeviceAnnouncer';\nimport { CloudRelayClient, type CloudRelayConfig } from '../transport/CloudRelayClient';\nimport { ModalDetector } from '../modal/modal-detector';\nimport { ToastCapture } from '../toast/toast-capture';\nimport { UndoTracker } from '../undo/undo-tracker';\n\n/**\n * UI Bridge Native context value\n */\nexport interface UIBridgeNativeContextValue {\n /** Feature flags */\n features: NativeUIBridgeFeatures;\n /** Configuration */\n config: NativeUIBridgeConfig;\n /** Element registry */\n registry: NativeUIBridgeRegistry;\n /** Action executor */\n executor: NativeActionExecutor;\n /** Modal stack tracker (declarative pushModal/dismissModal) */\n modalDetector: ModalDetector;\n /** Toast/snackbar tracker (declarative recordToast/dismissToast) */\n toastCapture: ToastCapture;\n /** Undo/redo action-correlation tracker */\n undoTracker: UndoTracker;\n /** Get all registered elements */\n getElements: () => RegisteredNativeElement[];\n /** Get all registered components */\n getComponents: () => RegisteredNativeComponent[];\n /** Create a snapshot */\n createSnapshot: () => NativeBridgeSnapshot;\n /** Subscribe to events */\n on: <T = unknown>(type: BridgeEventType, listener: BridgeEventListener<T>) => () => void;\n /** Unsubscribe from events */\n off: <T = unknown>(type: BridgeEventType, listener: BridgeEventListener<T>) => void;\n /** Whether the provider is initialized */\n initialized: boolean;\n /** Server running status */\n serverRunning: boolean;\n /** Start the HTTP server */\n startServer: () => Promise<void>;\n /** Stop the HTTP server */\n stopServer: () => void;\n /** Get the current navigation route (if a RouteProvider is configured) */\n getCurrentRoute: () => string | null;\n}\n\n/**\n * UI Bridge Native context\n */\nconst UIBridgeNativeContext = createContext<UIBridgeNativeContextValue | null>(null);\n\n/**\n * UI Bridge Native provider props\n */\nexport interface UIBridgeNativeProviderProps {\n /** Child components */\n children: React.ReactNode;\n /** Feature flags */\n features?: NativeUIBridgeFeatures;\n /** Configuration */\n config?: NativeUIBridgeConfig;\n /** Event handler */\n onEvent?: BridgeEventListener;\n /**\n * A ServerAdapter instance for the HTTP server.\n * The app is responsible for creating this using its preferred native TCP/HTTP library.\n * @see ServerAdapter interface in server/http-server.ts\n */\n serverAdapter?: ServerAdapter;\n /**\n * Navigation provider for programmatic route navigation via UI Bridge.\n * Pass Expo Router's push/back functions to enable `control/page/navigate`.\n */\n navigationProvider?: { navigate: (url: string) => void; back?: () => void };\n /**\n * Screenshot provider for native screen capture via UI Bridge.\n * Pass a function that captures the current screen as base64 PNG.\n */\n screenshotProvider?: {\n capture: () => Promise<{ base64: string; width: number; height: number }>;\n };\n /**\n * Route provider for exposing the current navigation route in snapshots.\n * Wire this to Expo Router's `usePathname()` / `useSegments()` via a module-level ref.\n */\n routeProvider?: RouteProvider;\n /**\n * Configuration for the cloud relay tunnel (enables remote device verification\n * when USB/LAN are not available). Omit `uiBridgeServer` — the provider wires\n * that automatically after the server starts.\n */\n cloudRelayConfig?: Omit<CloudRelayConfig, 'uiBridgeServer'>;\n /**\n * Enable mDNS advertisement so that runners on the same LAN can discover this\n * device automatically (requires react-native-zeroconf).\n */\n enableMdnsAnnounce?: boolean;\n /**\n * Stable device identifier used for mDNS TXT records and cloud relay\n * registration. Typically sourced from expo-device or a UUID stored in\n * AsyncStorage.\n */\n deviceId?: string;\n}\n\n/**\n * UI Bridge Native Provider\n *\n * Provides UI Bridge Native context to child components.\n *\n * @example\n * ```tsx\n * // app/_layout.tsx\n * import { UIBridgeNativeProvider } from 'ui-bridge-native';\n *\n * export default function RootLayout() {\n * return (\n * <UIBridgeNativeProvider\n * features={{ server: __DEV__, debug: __DEV__ }}\n * config={{ serverPort: 8087 }}\n * >\n * <Stack>{children}</Stack>\n * </UIBridgeNativeProvider>\n * );\n * }\n * ```\n */\nexport function UIBridgeNativeProvider({\n children,\n features = {},\n config = {},\n onEvent,\n serverAdapter,\n navigationProvider,\n screenshotProvider,\n routeProvider,\n cloudRelayConfig,\n enableMdnsAnnounce,\n deviceId,\n}: UIBridgeNativeProviderProps) {\n const registryRef = useRef<NativeUIBridgeRegistry | null>(null);\n const executorRef = useRef<NativeActionExecutor | null>(null);\n const modalDetectorRef = useRef<ModalDetector | null>(null);\n const toastCaptureRef = useRef<ToastCapture | null>(null);\n const undoTrackerRef = useRef<UndoTracker | null>(null);\n const [serverRunning, setServerRunning] = useState(false);\n\n // Initialize on first render\n if (!registryRef.current) {\n registryRef.current = new NativeUIBridgeRegistry({\n verbose: config.verbose,\n onEvent,\n });\n setGlobalRegistry(registryRef.current);\n }\n\n const registry = registryRef.current;\n\n // Create executor (memoized)\n if (!executorRef.current) {\n executorRef.current = createNativeActionExecutor(registry);\n }\n\n const executor = executorRef.current;\n\n // Trackers — lazy-init the same way as registry/executor so each provider\n // lifecycle has exactly one stable instance.\n if (!modalDetectorRef.current) modalDetectorRef.current = new ModalDetector();\n if (!toastCaptureRef.current) toastCaptureRef.current = new ToastCapture();\n if (!undoTrackerRef.current) undoTrackerRef.current = new UndoTracker();\n\n const modalDetector = modalDetectorRef.current;\n const toastCapture = toastCaptureRef.current;\n const undoTracker = undoTrackerRef.current;\n\n // Server instance (persisted across renders)\n const serverRef = useRef<NativeUIBridgeServer | null>(null);\n const eventBridgeRef = useRef<WebSocketEventBridge | null>(null);\n\n // Cloud / mDNS transport references\n const announcerRef = useRef<DeviceAnnouncer | null>(null);\n const cloudRelayRef = useRef<CloudRelayClient | null>(null);\n\n // Server management — uses injected serverAdapter if provided\n const startServer = useCallback(async () => {\n if (!features.server) return;\n\n if (!serverAdapter) {\n console.warn(\n `[ui-bridge-native] HTTP server not available: no serverAdapter prop provided. ` +\n `Pass a serverAdapter to UIBridgeNativeProvider to enable the HTTP server.`\n );\n return;\n }\n\n const server = createNativeServer(registry, executor, {\n serverPort: config.serverPort || 8087,\n cors: true,\n appInfo: config.appInfo,\n testHooks: features.testHooks === true,\n });\n\n server.setAdapter(serverAdapter);\n\n // Wire navigation provider if supplied\n if (navigationProvider) {\n server.setNavigationProvider(navigationProvider);\n }\n\n // Wire screenshot provider if supplied\n if (screenshotProvider) {\n server.setScreenshotProvider(screenshotProvider);\n }\n\n // Wire route provider if supplied (must be set AFTER navigationProvider\n // since both may override getSnapshot / pageNavigate handlers)\n if (routeProvider) {\n server.setRouteProvider(routeProvider);\n }\n\n // Wire up WebSocket event bridge if adapter supports it\n const wsAdapter = serverAdapter as WebSocketServerAdapter;\n if (typeof wsAdapter.broadcast === 'function') {\n const eventBridge = new WebSocketEventBridge(registry);\n server.setEventBridge(eventBridge);\n\n wsAdapter.onWebSocketConnect = (connId: string) => {\n // Create a lightweight connection proxy for the event bridge\n // The actual WebSocketConnection lives in the adapter\n eventBridge.addConnection({\n id: connId,\n subscriptions: new Set(),\n alive: true,\n isOpen: true,\n send: (msg: string) => wsAdapter.sendToConnection?.(connId, msg),\n sendEvent: (event: { event: string }) => {\n if (!eventBridge.isSubscribed(connId, event.event)) return;\n wsAdapter.sendToConnection?.(connId, JSON.stringify(event));\n },\n ping: () => {\n /* adapter handles heartbeat */\n },\n close: () => {\n /* adapter handles close */\n },\n destroy: () => {\n /* adapter handles destroy */\n },\n } as any); // eslint-disable-line @typescript-eslint/no-explicit-any\n };\n\n wsAdapter.onWebSocketDisconnect = (connId: string) => {\n // Abort any pending waiters (waitForElement / waitForCondition)\n // for this connection BEFORE removing it — stops leaked timers\n // and registry listeners.\n server.abortWaitersForConnection(connId);\n eventBridge.removeConnection(connId);\n };\n\n wsAdapter.onWebSocketMessage = async (connId: string, message: string) => {\n return server.handleWebSocketMessage(connId, message);\n };\n\n eventBridge.start();\n eventBridgeRef.current = eventBridge;\n }\n\n try {\n await server.start();\n serverRef.current = server;\n setServerRunning(true);\n } catch (err) {\n console.warn('[ui-bridge-native] Failed to start HTTP server:', err);\n }\n }, [\n features.server,\n features.testHooks,\n config.serverPort,\n config.appInfo,\n registry,\n executor,\n serverAdapter,\n navigationProvider,\n screenshotProvider,\n routeProvider,\n ]);\n\n const stopServer = useCallback(() => {\n if (eventBridgeRef.current) {\n eventBridgeRef.current.stop();\n eventBridgeRef.current = null;\n }\n if (serverRef.current) {\n serverRef.current.stop().catch(() => {});\n serverRef.current = null;\n }\n setServerRunning(false);\n }, []);\n\n // Auto-start server if enabled\n useEffect(() => {\n if (features.server) {\n startServer();\n return () => stopServer();\n }\n }, [features.server, startServer, stopServer]);\n\n // Start mDNS announcement and cloud relay.\n //\n // The cloud relay path does NOT require the HTTP server to be running —\n // it calls `server.handleRequest()` directly, bypassing HTTP. This matters\n // for preview/production builds where `features.server` is typically\n // false (no native TCP server adapter available). We still need a\n // NativeUIBridgeServer instance to handle tunneled requests, so we create\n // a bare instance here if startServer() didn't already make one.\n //\n // mDNS also doesn't need the HTTP server — it just advertises on the\n // network so remote devices can discover this phone's address.\n useEffect(() => {\n // Everything here is best-effort — any exception must not crash the app.\n try {\n const needsBareServer = !serverRef.current && !!cloudRelayConfig;\n if (needsBareServer) {\n try {\n // Create a server instance for handleRequest() use only; no adapter,\n // no HTTP listener. This is safe without features.server.\n const bareServer = createNativeServer(registry, executor, {\n serverPort: config.serverPort || 8087,\n cors: true,\n appInfo: config.appInfo,\n testHooks: features.testHooks === true,\n });\n if (navigationProvider) bareServer.setNavigationProvider(navigationProvider);\n if (screenshotProvider) bareServer.setScreenshotProvider(screenshotProvider);\n if (routeProvider) bareServer.setRouteProvider(routeProvider);\n serverRef.current = bareServer;\n } catch (err) {\n console.warn('[ui-bridge-native] Failed to create bare server:', err);\n }\n }\n\n // mDNS advertisement\n if (enableMdnsAnnounce && deviceId) {\n try {\n const announcer = new DeviceAnnouncer({\n deviceId,\n appId: config.appInfo?.appId ?? 'unknown',\n port: config.serverPort ?? 8087,\n cloudRelayUrl: cloudRelayConfig?.relayUrl,\n cloudToken: cloudRelayConfig?.authToken,\n });\n announcerRef.current = announcer;\n void announcer.startMdnsAdvertise().catch((err) => {\n console.warn('[ui-bridge-native] mDNS advertise failed:', err);\n });\n } catch (err) {\n console.warn('[ui-bridge-native] Failed to start DeviceAnnouncer:', err);\n }\n }\n\n // Cloud relay tunnel (works without HTTP server)\n if (cloudRelayConfig && serverRef.current) {\n try {\n const relayClient = new CloudRelayClient({\n ...cloudRelayConfig,\n uiBridgeServer: serverRef.current,\n });\n cloudRelayRef.current = relayClient;\n relayClient.start();\n } catch (err) {\n console.warn('[ui-bridge-native] Failed to start CloudRelayClient:', err);\n }\n }\n } catch (err) {\n console.warn('[ui-bridge-native] Transport effect failed:', err);\n }\n\n return () => {\n try {\n if (announcerRef.current) {\n void announcerRef.current.stop().catch(() => {});\n announcerRef.current = null;\n }\n if (cloudRelayRef.current) {\n cloudRelayRef.current.stop();\n cloudRelayRef.current = null;\n }\n } catch {\n // cleanup must never throw\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n serverRunning,\n cloudRelayConfig?.relayUrl,\n cloudRelayConfig?.authToken,\n enableMdnsAnnounce,\n deviceId,\n ]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n stopServer();\n resetGlobalRegistry();\n };\n }, [stopServer]);\n\n // Context methods\n const getElements = useCallback(() => registry.getAllElements(), [registry]);\n\n const getComponents = useCallback(() => registry.getAllComponents(), [registry]);\n\n const createSnapshot = useCallback(() => registry.createSnapshot(), [registry]);\n\n const getCurrentRoute = useCallback(() => {\n return routeProvider?.getCurrentRoute() ?? null;\n }, [routeProvider]);\n\n // Mark the previous route's elements offscreen when the active route changes.\n // Without this, React Navigation's persistent-mount behavior leaves stale\n // layouts in the registry for tabs the user has left. Elements on the new\n // route re-fire `onLayout` and repopulate their layout.\n useEffect(() => {\n if (!routeProvider) return;\n\n let lastRoute: string | null = routeProvider.getCurrentRoute();\n\n return routeProvider.subscribe((current: string | null) => {\n if (current !== lastRoute && lastRoute != null) {\n registry.markRouteOffscreen(lastRoute);\n }\n lastRoute = current;\n });\n }, [routeProvider, registry]);\n\n // Wire trackers into the registry's snapshot enricher slots. Trackers are\n // stable refs, so this effect runs exactly once per provider lifecycle.\n useEffect(() => {\n registry.setEnrichers({ modalDetector, toastCapture, undoTracker });\n }, [registry, modalDetector, toastCapture, undoTracker]);\n\n // Mirror successful bridge actions into UndoTracker's rolling history so\n // snapshots can surface action-correlation undo context without each\n // action site needing to call recordAction manually.\n useEffect(() => {\n const unsubscribe = executor.onActionExecuted((event) => {\n if (!event.success) return;\n undoTracker.recordAction({\n id: event.requestId ?? `action-${event.timestamp}`,\n type: event.action,\n targetId: event.elementId,\n timestamp: event.timestamp,\n reversible: true,\n });\n });\n return unsubscribe;\n }, [executor, undoTracker]);\n\n const on = useCallback(\n <T = unknown,>(type: BridgeEventType, listener: BridgeEventListener<T>) =>\n registry.on(type, listener),\n [registry]\n );\n\n const off = useCallback(\n <T = unknown,>(type: BridgeEventType, listener: BridgeEventListener<T>) =>\n registry.off(type, listener),\n [registry]\n );\n\n const contextValue = useMemo<UIBridgeNativeContextValue>(\n () => ({\n features,\n config,\n registry,\n executor,\n modalDetector,\n toastCapture,\n undoTracker,\n getElements,\n getComponents,\n createSnapshot,\n on,\n off,\n initialized: true,\n serverRunning,\n startServer,\n stopServer,\n getCurrentRoute,\n }),\n [\n features,\n config,\n registry,\n executor,\n modalDetector,\n toastCapture,\n undoTracker,\n getElements,\n getComponents,\n createSnapshot,\n on,\n off,\n serverRunning,\n startServer,\n stopServer,\n getCurrentRoute,\n ]\n );\n\n return (\n <UIBridgeNativeContext.Provider value={contextValue}>{children}</UIBridgeNativeContext.Provider>\n );\n}\n\n/**\n * useUIBridgeNative hook\n *\n * Access the UI Bridge Native context. Throws if used outside provider.\n */\nexport function useUIBridgeNative(): UIBridgeNativeContextValue {\n const context = useContext(UIBridgeNativeContext);\n if (!context) {\n throw new Error('useUIBridgeNative must be used within a UIBridgeNativeProvider');\n }\n return context;\n}\n\n/**\n * useUIBridgeNativeOptional hook\n *\n * Access the UI Bridge Native context, returning null if outside provider.\n */\nexport function useUIBridgeNativeOptional(): UIBridgeNativeContextValue | null {\n return useContext(UIBridgeNativeContext);\n}\n\n/**\n * useUIBridgeNativeRequired hook\n *\n * Alias for useUIBridgeNative (throws if outside provider).\n */\nexport const useUIBridgeNativeRequired = useUIBridgeNative;\n","/**\n * UI Bridge Native Debug Inspector\n *\n * An overlay component that shows registered elements and allows\n * inspection of the UI Bridge state.\n */\n\nimport { useState, useCallback, useMemo } from 'react';\nimport {\n View,\n Text,\n StyleSheet,\n TouchableOpacity,\n ScrollView,\n Modal,\n Dimensions,\n} from 'react-native';\nimport { useUIBridgeNativeOptional } from '../react/UIBridgeNativeProvider';\nimport type { RegisteredNativeElement } from '../core/types';\n\n/**\n * Inspector props\n */\nexport interface UIBridgeInspectorProps {\n /** Whether to show the inspector */\n visible?: boolean;\n /** Callback when inspector is closed */\n onClose?: () => void;\n /** Position of the inspector toggle button */\n togglePosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n}\n\n/**\n * Element info card\n */\nfunction ElementCard({\n element,\n onPress,\n}: {\n element: RegisteredNativeElement;\n onPress: (element: RegisteredNativeElement) => void;\n}) {\n const state = element.getState();\n const identifier = element.getIdentifier();\n\n return (\n <TouchableOpacity style={styles.elementCard} onPress={() => onPress(element)}>\n <View style={styles.elementHeader}>\n <Text style={styles.elementId}>{element.id}</Text>\n <Text style={styles.elementType}>{element.type}</Text>\n </View>\n {element.label && <Text style={styles.elementLabel}>{element.label}</Text>}\n <View style={styles.stateRow}>\n <StateIndicator label=\"Mounted\" value={state.mounted} />\n <StateIndicator label=\"Visible\" value={state.visible} />\n <StateIndicator label=\"Enabled\" value={state.enabled} />\n </View>\n {identifier.testId && <Text style={styles.testId}>testID: {identifier.testId}</Text>}\n </TouchableOpacity>\n );\n}\n\n/**\n * State indicator\n */\nfunction StateIndicator({ label, value }: { label: string; value: boolean }) {\n return (\n <View style={styles.stateIndicator}>\n <View style={[styles.stateDot, { backgroundColor: value ? '#4CAF50' : '#F44336' }]} />\n <Text style={styles.stateLabel}>{label}</Text>\n </View>\n );\n}\n\n/**\n * Element detail view\n */\nfunction ElementDetail({\n element,\n onClose,\n}: {\n element: RegisteredNativeElement;\n onClose: () => void;\n}) {\n const state = element.getState();\n const identifier = element.getIdentifier();\n\n return (\n <View style={styles.detailContainer}>\n <View style={styles.detailHeader}>\n <Text style={styles.detailTitle}>{element.id}</Text>\n <TouchableOpacity onPress={onClose}>\n <Text style={styles.closeButton}>Close</Text>\n </TouchableOpacity>\n </View>\n\n <ScrollView style={styles.detailContent}>\n <Text style={styles.sectionTitle}>Type</Text>\n <Text style={styles.sectionValue}>{element.type}</Text>\n\n {element.label && (\n <>\n <Text style={styles.sectionTitle}>Label</Text>\n <Text style={styles.sectionValue}>{element.label}</Text>\n </>\n )}\n\n <Text style={styles.sectionTitle}>State</Text>\n <View style={styles.stateSection}>\n <Text style={styles.stateText}>Mounted: {String(state.mounted)}</Text>\n <Text style={styles.stateText}>Visible: {String(state.visible)}</Text>\n <Text style={styles.stateText}>Enabled: {String(state.enabled)}</Text>\n <Text style={styles.stateText}>Focused: {String(state.focused)}</Text>\n {state.value !== undefined && <Text style={styles.stateText}>Value: {state.value}</Text>}\n </View>\n\n {state.layout && (\n <>\n <Text style={styles.sectionTitle}>Layout</Text>\n <View style={styles.stateSection}>\n <Text style={styles.stateText}>\n Position: ({state.layout.x}, {state.layout.y})\n </Text>\n <Text style={styles.stateText}>\n Size: {state.layout.width} x {state.layout.height}\n </Text>\n <Text style={styles.stateText}>\n Page: ({state.layout.pageX}, {state.layout.pageY})\n </Text>\n </View>\n </>\n )}\n\n <Text style={styles.sectionTitle}>Identifier</Text>\n <View style={styles.stateSection}>\n {identifier.uiId && <Text style={styles.stateText}>uiId: {identifier.uiId}</Text>}\n {identifier.testId && <Text style={styles.stateText}>testId: {identifier.testId}</Text>}\n {identifier.accessibilityLabel && (\n <Text style={styles.stateText}>a11yLabel: {identifier.accessibilityLabel}</Text>\n )}\n <Text style={styles.stateText}>treePath: {identifier.treePath}</Text>\n </View>\n\n <Text style={styles.sectionTitle}>Actions</Text>\n <View style={styles.actionsSection}>\n {element.actions.map((action) => (\n <View key={action} style={styles.actionBadge}>\n <Text style={styles.actionText}>{action}</Text>\n </View>\n ))}\n </View>\n\n {element.customActions && Object.keys(element.customActions).length > 0 && (\n <>\n <Text style={styles.sectionTitle}>Custom Actions</Text>\n <View style={styles.actionsSection}>\n {Object.keys(element.customActions).map((action) => (\n <View key={action} style={[styles.actionBadge, styles.customActionBadge]}>\n <Text style={styles.actionText}>{action}</Text>\n </View>\n ))}\n </View>\n </>\n )}\n </ScrollView>\n </View>\n );\n}\n\n/**\n * UI Bridge Inspector component\n *\n * Shows an overlay with information about registered elements.\n * Useful for debugging and development.\n *\n * @example\n * ```tsx\n * function App() {\n * const [showInspector, setShowInspector] = useState(false);\n *\n * return (\n * <UIBridgeNativeProvider features={{ debug: __DEV__ }}>\n * <MainContent />\n * {__DEV__ && (\n * <UIBridgeInspector\n * visible={showInspector}\n * onClose={() => setShowInspector(false)}\n * />\n * )}\n * </UIBridgeNativeProvider>\n * );\n * }\n * ```\n */\nexport function UIBridgeInspector({\n visible = false,\n onClose,\n togglePosition = 'bottom-right',\n}: UIBridgeInspectorProps) {\n const bridge = useUIBridgeNativeOptional();\n const [showInspector, setShowInspector] = useState(visible);\n const [selectedElement, setSelectedElement] = useState<RegisteredNativeElement | null>(null);\n\n const elements = useMemo(() => (bridge ? bridge.getElements() : []), [bridge]);\n\n const components = useMemo(() => (bridge ? bridge.getComponents() : []), [bridge]);\n\n const handleToggle = useCallback(() => {\n setShowInspector((prev) => !prev);\n }, []);\n\n const handleClose = useCallback(() => {\n setShowInspector(false);\n onClose?.();\n }, [onClose]);\n\n const handleSelectElement = useCallback((element: RegisteredNativeElement) => {\n setSelectedElement(element);\n }, []);\n\n const handleCloseDetail = useCallback(() => {\n setSelectedElement(null);\n }, []);\n\n // Position style for toggle button\n const toggleStyle = useMemo(() => {\n switch (togglePosition) {\n case 'top-left':\n return { top: 50, left: 10 };\n case 'top-right':\n return { top: 50, right: 10 };\n case 'bottom-left':\n return { bottom: 50, left: 10 };\n case 'bottom-right':\n default:\n return { bottom: 50, right: 10 };\n }\n }, [togglePosition]);\n\n if (!bridge) {\n return null;\n }\n\n return (\n <>\n {/* Toggle button */}\n <TouchableOpacity style={[styles.toggleButton, toggleStyle]} onPress={handleToggle}>\n <Text style={styles.toggleText}>UI</Text>\n </TouchableOpacity>\n\n {/* Inspector modal */}\n <Modal\n visible={showInspector}\n animationType=\"slide\"\n transparent={true}\n onRequestClose={handleClose}\n >\n <View style={styles.modalContainer}>\n <View style={styles.inspectorContainer}>\n {/* Header */}\n <View style={styles.header}>\n <Text style={styles.headerTitle}>UI Bridge Inspector</Text>\n <TouchableOpacity onPress={handleClose}>\n <Text style={styles.closeButton}>X</Text>\n </TouchableOpacity>\n </View>\n\n {/* Stats */}\n <View style={styles.statsRow}>\n <View style={styles.stat}>\n <Text style={styles.statValue}>{elements.length}</Text>\n <Text style={styles.statLabel}>Elements</Text>\n </View>\n <View style={styles.stat}>\n <Text style={styles.statValue}>{components.length}</Text>\n <Text style={styles.statLabel}>Components</Text>\n </View>\n <View style={styles.stat}>\n <Text style={styles.statValue}>{bridge.serverRunning ? 'ON' : 'OFF'}</Text>\n <Text style={styles.statLabel}>Server</Text>\n </View>\n </View>\n\n {/* Element list or detail */}\n {selectedElement ? (\n <ElementDetail element={selectedElement} onClose={handleCloseDetail} />\n ) : (\n <ScrollView style={styles.elementList}>\n {elements.map((element) => (\n <ElementCard key={element.id} element={element} onPress={handleSelectElement} />\n ))}\n {elements.length === 0 && (\n <Text style={styles.emptyText}>No elements registered yet</Text>\n )}\n </ScrollView>\n )}\n </View>\n </View>\n </Modal>\n </>\n );\n}\n\nconst { height: screenHeight } = Dimensions.get('window');\n\nconst styles = StyleSheet.create({\n toggleButton: {\n position: 'absolute',\n width: 44,\n height: 44,\n borderRadius: 22,\n backgroundColor: '#2196F3',\n justifyContent: 'center',\n alignItems: 'center',\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n shadowOpacity: 0.25,\n shadowRadius: 4,\n elevation: 5,\n zIndex: 1000,\n },\n toggleText: {\n color: '#fff',\n fontWeight: 'bold',\n fontSize: 14,\n },\n modalContainer: {\n flex: 1,\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\n justifyContent: 'flex-end',\n },\n inspectorContainer: {\n backgroundColor: '#1e1e1e',\n borderTopLeftRadius: 16,\n borderTopRightRadius: 16,\n maxHeight: screenHeight * 0.8,\n },\n header: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: 16,\n borderBottomWidth: 1,\n borderBottomColor: '#333',\n },\n headerTitle: {\n color: '#fff',\n fontSize: 18,\n fontWeight: 'bold',\n },\n closeButton: {\n color: '#2196F3',\n fontSize: 16,\n fontWeight: 'bold',\n },\n statsRow: {\n flexDirection: 'row',\n padding: 12,\n borderBottomWidth: 1,\n borderBottomColor: '#333',\n },\n stat: {\n flex: 1,\n alignItems: 'center',\n },\n statValue: {\n color: '#fff',\n fontSize: 20,\n fontWeight: 'bold',\n },\n statLabel: {\n color: '#888',\n fontSize: 12,\n marginTop: 2,\n },\n elementList: {\n padding: 12,\n },\n elementCard: {\n backgroundColor: '#2d2d2d',\n borderRadius: 8,\n padding: 12,\n marginBottom: 8,\n },\n elementHeader: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n elementId: {\n color: '#fff',\n fontSize: 14,\n fontWeight: 'bold',\n },\n elementType: {\n color: '#888',\n fontSize: 12,\n backgroundColor: '#444',\n paddingHorizontal: 8,\n paddingVertical: 2,\n borderRadius: 4,\n },\n elementLabel: {\n color: '#aaa',\n fontSize: 12,\n marginTop: 4,\n },\n stateRow: {\n flexDirection: 'row',\n marginTop: 8,\n },\n stateIndicator: {\n flexDirection: 'row',\n alignItems: 'center',\n marginRight: 12,\n },\n stateDot: {\n width: 8,\n height: 8,\n borderRadius: 4,\n marginRight: 4,\n },\n stateLabel: {\n color: '#888',\n fontSize: 10,\n },\n testId: {\n color: '#666',\n fontSize: 10,\n marginTop: 4,\n fontFamily: 'monospace',\n },\n emptyText: {\n color: '#888',\n textAlign: 'center',\n marginTop: 20,\n },\n detailContainer: {\n flex: 1,\n },\n detailHeader: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: 12,\n borderBottomWidth: 1,\n borderBottomColor: '#333',\n },\n detailTitle: {\n color: '#fff',\n fontSize: 16,\n fontWeight: 'bold',\n },\n detailContent: {\n padding: 12,\n },\n sectionTitle: {\n color: '#888',\n fontSize: 12,\n marginTop: 12,\n marginBottom: 4,\n textTransform: 'uppercase',\n },\n sectionValue: {\n color: '#fff',\n fontSize: 14,\n },\n stateSection: {\n backgroundColor: '#2d2d2d',\n borderRadius: 8,\n padding: 8,\n },\n stateText: {\n color: '#ddd',\n fontSize: 12,\n fontFamily: 'monospace',\n marginBottom: 2,\n },\n actionsSection: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n },\n actionBadge: {\n backgroundColor: '#2196F3',\n paddingHorizontal: 8,\n paddingVertical: 4,\n borderRadius: 4,\n marginRight: 6,\n marginBottom: 6,\n },\n customActionBadge: {\n backgroundColor: '#9C27B0',\n },\n actionText: {\n color: '#fff',\n fontSize: 12,\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/design-handlers.ts","../../src/react/UIBridgeNativeProvider.tsx","../../src/debug/inspector.tsx"],"names":["jsx","useState","useMemo","useCallback"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * UI Bridge Native Design Review Handlers\n *\n * HTTP handlers for the 8 design review endpoints.\n * Maps registered element styles to the web SDK's design data format.\n */\n\nimport type { NativeUIBridgeRegistry } from '../core/registry';\nimport type { APIResponse, HandlerContext } from './types';\nimport type { ElementDesignData, StateStyles, ResponsiveSnapshot } from '../design/design-types';\nimport {\n mapNativeStyleToExtended,\n getNativeElementDesignData,\n captureNativeStateVariations,\n captureNativeResponsiveSnapshot,\n} from '../design/design-inspector-native';\n\n// Style guide and baseline stored in closure (same pattern as web SDK)\nlet loadedStyleGuide: unknown = null;\nlet savedBaseline: unknown = null;\n\n// Try to load the style validator from the web SDK (optional peer dep)\nlet styleValidator: {\n runStyleAudit: (\n elements: Array<{ elementId: string; styles: Record<string, string> }>,\n guide: unknown\n ) => unknown;\n} | null = null;\n\n// Try to load quality evaluator from the web SDK (optional peer dep)\nlet qualityEvaluator: {\n evaluateQuality: (\n elements: ElementDesignData[],\n viewport: { width: number; height: number },\n context?: unknown\n ) => unknown;\n listContexts: () => Array<{ name: string; description: string }>;\n createBaseline: (\n elements: ElementDesignData[],\n viewport: { width: number; height: number },\n label?: string\n ) => unknown;\n diffSnapshots: (baseline: unknown, current: ElementDesignData[]) => unknown;\n} | null = null;\n\ntry {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const specs = require('@qontinui/ui-bridge/specs');\n styleValidator = specs;\n qualityEvaluator = specs;\n} catch {\n // Optional dependency not installed — audit/evaluate endpoints will return an error\n}\n\nfunction success<T>(data: T): APIResponse<T> {\n return { success: true, data, timestamp: Date.now() };\n}\n\nfunction error<T = unknown>(message: string, code?: string): APIResponse<T> {\n return { success: false, error: message, code, timestamp: Date.now() };\n}\n\n/**\n * Design handler interface (subset of NativeServerHandlers)\n */\nexport interface NativeDesignHandlers {\n getElementStyles: (ctx: HandlerContext) => Promise<APIResponse<ElementDesignData>>;\n getElementStateStyles: (\n ctx: HandlerContext\n ) => Promise<APIResponse<{ elementId: string; stateStyles: StateStyles[] }>>;\n getDesignSnapshot: (\n ctx: HandlerContext\n ) => Promise<APIResponse<{ elements: ElementDesignData[]; timestamp: number }>>;\n getResponsiveSnapshots: (ctx: HandlerContext) => Promise<APIResponse<ResponsiveSnapshot[]>>;\n runDesignAudit: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;\n loadStyleGuide: (ctx: HandlerContext) => Promise<APIResponse<{ loaded: boolean }>>;\n getStyleGuide: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;\n clearStyleGuide: (ctx: HandlerContext) => Promise<APIResponse<{ cleared: boolean }>>;\n evaluateQuality: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;\n getQualityContexts: (\n ctx: HandlerContext\n ) => Promise<APIResponse<Array<{ name: string; description: string }>>>;\n saveBaseline: (\n ctx: HandlerContext\n ) => Promise<APIResponse<{ saved: boolean; elementCount: number }>>;\n diffBaseline: (ctx: HandlerContext) => Promise<APIResponse<unknown>>;\n}\n\n/**\n * Create design review handlers.\n */\nexport function createDesignHandlers(registry: NativeUIBridgeRegistry): NativeDesignHandlers {\n // Helper to get screen dimensions (React Native's Dimensions API must be\n // called at handler time, not import time, so we use a lazy getter).\n function getScreenDimensions(): { width: number; height: number } {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { Dimensions } = require('react-native');\n const screen = Dimensions.get('screen');\n return { width: screen.width, height: screen.height };\n } catch {\n return { width: 0, height: 0 };\n }\n }\n\n return {\n // 1. GET /design/element/:id/styles\n getElementStyles: async (ctx) => {\n const { id } = ctx.params;\n const element = registry.getElement(id);\n\n if (!element) {\n return error('Element not found: ' + id, 'ELEMENT_NOT_FOUND');\n }\n\n const state = element.getState();\n const data = getNativeElementDesignData(\n id,\n element.label,\n element.type,\n element.flatStyle,\n state.layout\n );\n\n return success(data);\n },\n\n // 2. POST /design/element/:id/state-styles\n getElementStateStyles: async (ctx) => {\n const { id } = ctx.params;\n const element = registry.getElement(id);\n\n if (!element) {\n return error('Element not found: ' + id, 'ELEMENT_NOT_FOUND');\n }\n\n const stateStyles = captureNativeStateVariations(element.flatStyle, element.stateStyles);\n\n return success({ elementId: id, stateStyles });\n },\n\n // 3. POST /design/snapshot\n getDesignSnapshot: async (ctx) => {\n const body = ctx.body as\n | {\n elementIds?: string[];\n includePseudoElements?: boolean;\n }\n | undefined;\n\n let elements = registry.getAllElements();\n\n // Filter to requested IDs if specified\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n const designData: ElementDesignData[] = elements.map((el) => {\n const state = el.getState();\n return getNativeElementDesignData(el.id, el.label, el.type, el.flatStyle, state.layout);\n });\n\n return success({ elements: designData, timestamp: Date.now() });\n },\n\n // 4. POST /design/responsive\n getResponsiveSnapshots: async () => {\n // Platform limitation: RN cannot constrain screen width at runtime.\n // Returns a single snapshot at current device dimensions.\n const elements = registry.getAllElements();\n const elementData = elements.map((el) => {\n const state = el.getState();\n return {\n id: el.id,\n label: el.label,\n type: el.type,\n flatStyle: el.flatStyle,\n layout: state.layout,\n };\n });\n\n const snapshots = captureNativeResponsiveSnapshot(elementData, getScreenDimensions());\n return success(snapshots);\n },\n\n // 5. POST /design/audit\n runDesignAudit: async (ctx) => {\n const body = ctx.body as\n | {\n guide?: unknown;\n elementIds?: string[];\n }\n | undefined;\n\n const guide = body?.guide ?? loadedStyleGuide;\n\n if (!guide) {\n return error('No style guide loaded or provided', 'NO_STYLE_GUIDE');\n }\n\n if (!styleValidator) {\n return error(\n 'Install @qontinui/ui-bridge for style audit support. ' +\n 'Add it as a dependency: npm install @qontinui/ui-bridge',\n 'VALIDATOR_NOT_AVAILABLE'\n );\n }\n\n let elements = registry.getAllElements();\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n // Map elements to the format expected by the validator\n const auditElements = elements.map((el) => ({\n elementId: el.id,\n styles: mapNativeStyleToExtended(el.flatStyle) as unknown as Record<string, string>,\n }));\n\n try {\n const report = styleValidator.runStyleAudit(auditElements, guide);\n return success(report);\n } catch (err) {\n return error(\n 'Audit failed: ' + (err instanceof Error ? err.message : String(err)),\n 'DESIGN_AUDIT_ERROR'\n );\n }\n },\n\n // 6. POST /design/style-guide/load\n loadStyleGuide: async (ctx) => {\n const body = ctx.body as { guide?: unknown } | undefined;\n\n if (!body?.guide) {\n return error('Style guide is required in request body', 'INVALID_REQUEST');\n }\n\n loadedStyleGuide = body.guide;\n return success({ loaded: true });\n },\n\n // 7. GET /design/style-guide\n getStyleGuide: async () => {\n return success(loadedStyleGuide);\n },\n\n // 8. DELETE /design/style-guide\n clearStyleGuide: async () => {\n loadedStyleGuide = null;\n return success({ cleared: true });\n },\n\n // 9. POST /design/evaluate\n evaluateQuality: async (ctx) => {\n if (!qualityEvaluator) {\n return error(\n 'Install @qontinui/ui-bridge for quality evaluation support. ' +\n 'Add it as a dependency: npm install @qontinui/ui-bridge',\n 'EVALUATOR_NOT_AVAILABLE'\n );\n }\n\n const body = ctx.body as\n | {\n context?: string;\n customContext?: unknown;\n elementIds?: string[];\n viewport?: { width: number; height: number };\n }\n | undefined;\n\n let elements = registry.getAllElements();\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n const designData: ElementDesignData[] = elements.map((el) => {\n const state = el.getState();\n return getNativeElementDesignData(el.id, el.label, el.type, el.flatStyle, state.layout);\n });\n\n const viewport = body?.viewport ?? getScreenDimensions();\n\n // Resolve context: custom object > style guide context > built-in name\n let context: unknown = body?.customContext ?? body?.context ?? 'general';\n if (typeof context === 'string' && loadedStyleGuide) {\n const guide = loadedStyleGuide as { qualityContexts?: Record<string, unknown> };\n if (guide.qualityContexts?.[context]) {\n context = guide.qualityContexts[context];\n }\n }\n\n try {\n const report = qualityEvaluator.evaluateQuality(designData, viewport, context);\n return success(report);\n } catch (err) {\n return error(\n 'Evaluation failed: ' + (err instanceof Error ? err.message : String(err)),\n 'QUALITY_EVALUATION_ERROR'\n );\n }\n },\n\n // 10. GET /design/evaluate/contexts\n getQualityContexts: async () => {\n if (!qualityEvaluator) {\n return error(\n 'Install @qontinui/ui-bridge for quality evaluation support.',\n 'EVALUATOR_NOT_AVAILABLE'\n );\n }\n return success(qualityEvaluator.listContexts());\n },\n\n // 11. POST /design/evaluate/baseline\n saveBaseline: async (ctx) => {\n if (!qualityEvaluator) {\n return error(\n 'Install @qontinui/ui-bridge for quality evaluation support.',\n 'EVALUATOR_NOT_AVAILABLE'\n );\n }\n\n const body = ctx.body as\n | {\n label?: string;\n elementIds?: string[];\n }\n | undefined;\n\n let elements = registry.getAllElements();\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n const designData: ElementDesignData[] = elements.map((el) => {\n const state = el.getState();\n return getNativeElementDesignData(el.id, el.label, el.type, el.flatStyle, state.layout);\n });\n\n const viewport = getScreenDimensions();\n savedBaseline = qualityEvaluator.createBaseline(designData, viewport, body?.label);\n return success({ saved: true, elementCount: designData.length });\n },\n\n // 12. POST /design/evaluate/diff\n diffBaseline: async (ctx) => {\n if (!qualityEvaluator) {\n return error(\n 'Install @qontinui/ui-bridge for quality evaluation support.',\n 'EVALUATOR_NOT_AVAILABLE'\n );\n }\n\n if (!savedBaseline) {\n return error('No baseline saved. Call saveBaseline first.', 'NO_BASELINE');\n }\n\n const body = ctx.body as { elementIds?: string[] } | undefined;\n\n let elements = registry.getAllElements();\n if (body?.elementIds && body.elementIds.length > 0) {\n const idSet = new Set(body.elementIds);\n elements = elements.filter((e) => idSet.has(e.id));\n }\n\n const designData: ElementDesignData[] = elements.map((el) => {\n const state = el.getState();\n return getNativeElementDesignData(el.id, el.label, el.type, el.flatStyle, state.layout);\n });\n\n try {\n const report = qualityEvaluator.diffSnapshots(savedBaseline, designData);\n return success(report);\n } catch (err) {\n return error(\n 'Diff failed: ' + (err instanceof Error ? err.message : String(err)),\n 'DIFF_BASELINE_ERROR'\n );\n }\n },\n };\n}\n","/**\n * UI Bridge Native Provider\n *\n * React context provider for UI Bridge Native functionality.\n */\n\nimport React, {\n createContext,\n use,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n useState,\n} from 'react';\nimport type {\n NativeUIBridgeFeatures,\n NativeUIBridgeConfig,\n RegisteredNativeElement,\n RegisteredNativeComponent,\n NativeBridgeSnapshot,\n BridgeEventType,\n BridgeEventListener,\n} from '../core/types';\nimport { NativeUIBridgeRegistry, setGlobalRegistry, resetGlobalRegistry } from '../core/registry';\nimport { createNativeActionExecutor } from '../control/action-executor';\nimport type { NativeActionExecutor } from '../control/types';\nimport {\n createNativeServer,\n type NativeUIBridgeServer,\n type ServerAdapter,\n type WebSocketServerAdapter,\n} from '../server/http-server';\nimport type { RouteProvider, KeepAwakeProvider } from '../server/types';\nimport { WebSocketEventBridge } from '../server/ws-event-bridge';\nimport { DeviceAnnouncer } from '../transport/DeviceAnnouncer';\nimport { CloudRelayClient, type CloudRelayConfig } from '../transport/CloudRelayClient';\nimport { ModalDetector } from '../modal/modal-detector';\nimport { ToastCapture } from '../toast/toast-capture';\nimport { UndoTracker } from '../undo/undo-tracker';\n\n/**\n * UI Bridge Native context value\n */\nexport interface UIBridgeNativeContextValue {\n /** Feature flags */\n features: NativeUIBridgeFeatures;\n /** Configuration */\n config: NativeUIBridgeConfig;\n /** Element registry */\n registry: NativeUIBridgeRegistry;\n /** Action executor */\n executor: NativeActionExecutor;\n /** Modal stack tracker (declarative pushModal/dismissModal) */\n modalDetector: ModalDetector;\n /** Toast/snackbar tracker (declarative recordToast/dismissToast) */\n toastCapture: ToastCapture;\n /** Undo/redo action-correlation tracker */\n undoTracker: UndoTracker;\n /** Get all registered elements */\n getElements: () => RegisteredNativeElement[];\n /** Get all registered components */\n getComponents: () => RegisteredNativeComponent[];\n /** Create a snapshot */\n createSnapshot: () => NativeBridgeSnapshot;\n /** Subscribe to events */\n on: <T = unknown>(type: BridgeEventType, listener: BridgeEventListener<T>) => () => void;\n /** Unsubscribe from events */\n off: <T = unknown>(type: BridgeEventType, listener: BridgeEventListener<T>) => void;\n /** Whether the provider is initialized */\n initialized: boolean;\n /** Server running status */\n serverRunning: boolean;\n /** Start the HTTP server */\n startServer: () => Promise<void>;\n /** Stop the HTTP server */\n stopServer: () => void;\n /** Get the current navigation route (if a RouteProvider is configured) */\n getCurrentRoute: () => string | null;\n}\n\n/**\n * UI Bridge Native context\n */\nconst UIBridgeNativeContext = createContext<UIBridgeNativeContextValue | null>(null);\n\n/**\n * UI Bridge Native provider props\n */\nexport interface UIBridgeNativeProviderProps {\n /** Child components */\n children: React.ReactNode;\n /** Feature flags */\n features?: NativeUIBridgeFeatures;\n /** Configuration */\n config?: NativeUIBridgeConfig;\n /** Event handler */\n onEvent?: BridgeEventListener;\n /**\n * A ServerAdapter instance for the HTTP server.\n * The app is responsible for creating this using its preferred native TCP/HTTP library.\n * @see ServerAdapter interface in server/http-server.ts\n */\n serverAdapter?: ServerAdapter;\n /**\n * Navigation provider for programmatic route navigation via UI Bridge.\n * Pass Expo Router's push/back functions to enable `control/page/navigate`.\n */\n navigationProvider?: { navigate: (url: string) => void; back?: () => void };\n /**\n * Screenshot provider for native screen capture via UI Bridge.\n * Pass a function that captures the current screen as base64 PNG.\n */\n screenshotProvider?: {\n capture: () => Promise<{ base64: string; width: number; height: number }>;\n };\n /**\n * Keep-awake provider for native screen-wake control via UI Bridge.\n * Pass expo-keep-awake's activateKeepAwakeAsync/deactivateKeepAwake (wrapped\n * to the request/release shape) so an external runner never loses the device\n * to a screen lock. The SDK never imports expo-keep-awake directly.\n */\n keepAwakeProvider?: KeepAwakeProvider;\n /**\n * Route provider for exposing the current navigation route in snapshots.\n * Wire this to Expo Router's `usePathname()` / `useSegments()` via a module-level ref.\n */\n routeProvider?: RouteProvider;\n /**\n * Configuration for the cloud relay tunnel (enables remote device verification\n * when USB/LAN are not available). Omit `uiBridgeServer` — the provider wires\n * that automatically after the server starts.\n */\n cloudRelayConfig?: Omit<CloudRelayConfig, 'uiBridgeServer'>;\n /**\n * Enable mDNS advertisement so that runners on the same LAN can discover this\n * device automatically (requires react-native-zeroconf).\n */\n enableMdnsAnnounce?: boolean;\n /**\n * Stable device identifier used for mDNS TXT records and cloud relay\n * registration. Typically sourced from expo-device or a UUID stored in\n * AsyncStorage.\n */\n deviceId?: string;\n}\n\n/**\n * UI Bridge Native Provider\n *\n * Provides UI Bridge Native context to child components.\n *\n * @example\n * ```tsx\n * // app/_layout.tsx\n * import { UIBridgeNativeProvider } from 'ui-bridge-native';\n *\n * export default function RootLayout() {\n * return (\n * <UIBridgeNativeProvider\n * features={{ server: __DEV__, debug: __DEV__ }}\n * config={{ serverPort: 8087 }}\n * >\n * <Stack>{children}</Stack>\n * </UIBridgeNativeProvider>\n * );\n * }\n * ```\n */\nexport function UIBridgeNativeProvider({\n children,\n features = {},\n config = {},\n onEvent,\n serverAdapter,\n navigationProvider,\n screenshotProvider,\n keepAwakeProvider,\n routeProvider,\n cloudRelayConfig,\n enableMdnsAnnounce,\n deviceId,\n}: UIBridgeNativeProviderProps) {\n const registryRef = useRef<NativeUIBridgeRegistry | null>(null);\n const executorRef = useRef<NativeActionExecutor | null>(null);\n const modalDetectorRef = useRef<ModalDetector | null>(null);\n const toastCaptureRef = useRef<ToastCapture | null>(null);\n const undoTrackerRef = useRef<UndoTracker | null>(null);\n const [serverRunning, setServerRunning] = useState(false);\n\n // Initialize on first render\n if (!registryRef.current) {\n registryRef.current = new NativeUIBridgeRegistry({\n verbose: config.verbose,\n onEvent,\n });\n setGlobalRegistry(registryRef.current);\n }\n\n const registry = registryRef.current;\n\n // Create executor (memoized)\n if (!executorRef.current) {\n executorRef.current = createNativeActionExecutor(registry);\n }\n\n const executor = executorRef.current;\n\n // Trackers — lazy-init the same way as registry/executor so each provider\n // lifecycle has exactly one stable instance.\n if (!modalDetectorRef.current) modalDetectorRef.current = new ModalDetector();\n if (!toastCaptureRef.current) toastCaptureRef.current = new ToastCapture();\n if (!undoTrackerRef.current) undoTrackerRef.current = new UndoTracker();\n\n const modalDetector = modalDetectorRef.current;\n const toastCapture = toastCaptureRef.current;\n const undoTracker = undoTrackerRef.current;\n\n // Server instance (persisted across renders)\n const serverRef = useRef<NativeUIBridgeServer | null>(null);\n const eventBridgeRef = useRef<WebSocketEventBridge | null>(null);\n\n // Cloud / mDNS transport references\n const announcerRef = useRef<DeviceAnnouncer | null>(null);\n const cloudRelayRef = useRef<CloudRelayClient | null>(null);\n\n // Server management — uses injected serverAdapter if provided\n const startServer = useCallback(async () => {\n if (!features.server) return;\n\n if (!serverAdapter) {\n console.warn(\n `[ui-bridge-native] HTTP server not available: no serverAdapter prop provided. ` +\n `Pass a serverAdapter to UIBridgeNativeProvider to enable the HTTP server.`\n );\n return;\n }\n\n const server = createNativeServer(registry, executor, {\n serverPort: config.serverPort || 8087,\n cors: true,\n appInfo: config.appInfo,\n testHooks: features.testHooks === true,\n });\n\n server.setAdapter(serverAdapter);\n\n // Wire navigation provider if supplied\n if (navigationProvider) {\n server.setNavigationProvider(navigationProvider);\n }\n\n // Wire screenshot provider if supplied\n if (screenshotProvider) {\n server.setScreenshotProvider(screenshotProvider);\n }\n\n // Wire keep-awake provider if supplied\n if (keepAwakeProvider) {\n server.setKeepAwakeProvider(keepAwakeProvider);\n }\n\n // Wire route provider if supplied (must be set AFTER navigationProvider\n // since both may override getSnapshot / pageNavigate handlers)\n if (routeProvider) {\n server.setRouteProvider(routeProvider);\n }\n\n // Wire up WebSocket event bridge if adapter supports it\n const wsAdapter = serverAdapter as WebSocketServerAdapter;\n if (typeof wsAdapter.broadcast === 'function') {\n const eventBridge = new WebSocketEventBridge(registry);\n server.setEventBridge(eventBridge);\n\n wsAdapter.onWebSocketConnect = (connId: string) => {\n // Create a lightweight connection proxy for the event bridge\n // The actual WebSocketConnection lives in the adapter\n eventBridge.addConnection({\n id: connId,\n subscriptions: new Set(),\n alive: true,\n isOpen: true,\n send: (msg: string) => wsAdapter.sendToConnection?.(connId, msg),\n sendEvent: (event: { event: string }) => {\n if (!eventBridge.isSubscribed(connId, event.event)) return;\n wsAdapter.sendToConnection?.(connId, JSON.stringify(event));\n },\n ping: () => {\n /* adapter handles heartbeat */\n },\n close: () => {\n /* adapter handles close */\n },\n destroy: () => {\n /* adapter handles destroy */\n },\n } as any); // eslint-disable-line @typescript-eslint/no-explicit-any\n };\n\n wsAdapter.onWebSocketDisconnect = (connId: string) => {\n // Abort any pending waiters (waitForElement / waitForCondition)\n // for this connection BEFORE removing it — stops leaked timers\n // and registry listeners.\n server.abortWaitersForConnection(connId);\n eventBridge.removeConnection(connId);\n };\n\n wsAdapter.onWebSocketMessage = async (connId: string, message: string) => {\n return server.handleWebSocketMessage(connId, message);\n };\n\n eventBridge.start();\n eventBridgeRef.current = eventBridge;\n }\n\n try {\n await server.start();\n serverRef.current = server;\n setServerRunning(true);\n } catch (err) {\n console.warn('[ui-bridge-native] Failed to start HTTP server:', err);\n }\n }, [\n features.server,\n features.testHooks,\n config.serverPort,\n config.appInfo,\n registry,\n executor,\n serverAdapter,\n navigationProvider,\n screenshotProvider,\n keepAwakeProvider,\n routeProvider,\n ]);\n\n const stopServer = useCallback(() => {\n if (eventBridgeRef.current) {\n eventBridgeRef.current.stop();\n eventBridgeRef.current = null;\n }\n if (serverRef.current) {\n serverRef.current.stop().catch(() => {});\n serverRef.current = null;\n }\n setServerRunning(false);\n }, []);\n\n // Auto-start server if enabled\n useEffect(() => {\n if (features.server) {\n startServer();\n return () => stopServer();\n }\n }, [features.server, startServer, stopServer]);\n\n // Start mDNS announcement and cloud relay.\n //\n // The cloud relay path does NOT require the HTTP server to be running —\n // it calls `server.handleRequest()` directly, bypassing HTTP. This matters\n // for preview/production builds where `features.server` is typically\n // false (no native TCP server adapter available). We still need a\n // NativeUIBridgeServer instance to handle tunneled requests, so we create\n // a bare instance here if startServer() didn't already make one.\n //\n // mDNS also doesn't need the HTTP server — it just advertises on the\n // network so remote devices can discover this phone's address.\n useEffect(() => {\n // Everything here is best-effort — any exception must not crash the app.\n try {\n const needsBareServer = !serverRef.current && !!cloudRelayConfig;\n if (needsBareServer) {\n try {\n // Create a server instance for handleRequest() use only; no adapter,\n // no HTTP listener. This is safe without features.server.\n const bareServer = createNativeServer(registry, executor, {\n serverPort: config.serverPort || 8087,\n cors: true,\n appInfo: config.appInfo,\n testHooks: features.testHooks === true,\n });\n if (navigationProvider) bareServer.setNavigationProvider(navigationProvider);\n if (screenshotProvider) bareServer.setScreenshotProvider(screenshotProvider);\n if (keepAwakeProvider) bareServer.setKeepAwakeProvider(keepAwakeProvider);\n if (routeProvider) bareServer.setRouteProvider(routeProvider);\n serverRef.current = bareServer;\n } catch (err) {\n console.warn('[ui-bridge-native] Failed to create bare server:', err);\n }\n }\n\n // mDNS advertisement\n if (enableMdnsAnnounce && deviceId) {\n try {\n const announcer = new DeviceAnnouncer({\n deviceId,\n appId: config.appInfo?.appId ?? 'unknown',\n port: config.serverPort ?? 8087,\n cloudRelayUrl: cloudRelayConfig?.relayUrl,\n cloudToken: cloudRelayConfig?.authToken,\n });\n announcerRef.current = announcer;\n void announcer.startMdnsAdvertise().catch((err) => {\n console.warn('[ui-bridge-native] mDNS advertise failed:', err);\n });\n } catch (err) {\n console.warn('[ui-bridge-native] Failed to start DeviceAnnouncer:', err);\n }\n }\n\n // Cloud relay tunnel (works without HTTP server)\n if (cloudRelayConfig && serverRef.current) {\n try {\n const relayClient = new CloudRelayClient({\n ...cloudRelayConfig,\n uiBridgeServer: serverRef.current,\n });\n cloudRelayRef.current = relayClient;\n relayClient.start();\n } catch (err) {\n console.warn('[ui-bridge-native] Failed to start CloudRelayClient:', err);\n }\n }\n } catch (err) {\n console.warn('[ui-bridge-native] Transport effect failed:', err);\n }\n\n return () => {\n try {\n if (announcerRef.current) {\n void announcerRef.current.stop().catch(() => {});\n announcerRef.current = null;\n }\n if (cloudRelayRef.current) {\n cloudRelayRef.current.stop();\n cloudRelayRef.current = null;\n }\n } catch {\n // cleanup must never throw\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n serverRunning,\n cloudRelayConfig?.relayUrl,\n cloudRelayConfig?.authToken,\n enableMdnsAnnounce,\n deviceId,\n ]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n stopServer();\n resetGlobalRegistry();\n };\n }, [stopServer]);\n\n // Context methods\n const getElements = useCallback(() => registry.getAllElements(), [registry]);\n\n const getComponents = useCallback(() => registry.getAllComponents(), [registry]);\n\n const createSnapshot = useCallback(() => registry.createSnapshot(), [registry]);\n\n const getCurrentRoute = useCallback(() => {\n return routeProvider?.getCurrentRoute() ?? null;\n }, [routeProvider]);\n\n // Mark the previous route's elements offscreen when the active route changes.\n // Without this, React Navigation's persistent-mount behavior leaves stale\n // layouts in the registry for tabs the user has left. Elements on the new\n // route re-fire `onLayout` and repopulate their layout.\n useEffect(() => {\n if (!routeProvider) return;\n\n let lastRoute: string | null = routeProvider.getCurrentRoute();\n\n return routeProvider.subscribe((current: string | null) => {\n if (current !== lastRoute && lastRoute != null) {\n registry.markRouteOffscreen(lastRoute);\n }\n lastRoute = current;\n });\n }, [routeProvider, registry]);\n\n // Wire trackers into the registry's snapshot enricher slots. Trackers are\n // stable refs, so this effect runs exactly once per provider lifecycle.\n useEffect(() => {\n registry.setEnrichers({ modalDetector, toastCapture, undoTracker });\n }, [registry, modalDetector, toastCapture, undoTracker]);\n\n // Mirror successful bridge actions into UndoTracker's rolling history so\n // snapshots can surface action-correlation undo context without each\n // action site needing to call recordAction manually.\n useEffect(() => {\n const unsubscribe = executor.onActionExecuted((event) => {\n if (!event.success) return;\n undoTracker.recordAction({\n id: event.requestId ?? `action-${event.timestamp}`,\n type: event.action,\n targetId: event.elementId,\n timestamp: event.timestamp,\n reversible: true,\n });\n });\n return unsubscribe;\n }, [executor, undoTracker]);\n\n const on = useCallback(\n <T = unknown,>(type: BridgeEventType, listener: BridgeEventListener<T>) =>\n registry.on(type, listener),\n [registry]\n );\n\n const off = useCallback(\n <T = unknown,>(type: BridgeEventType, listener: BridgeEventListener<T>) =>\n registry.off(type, listener),\n [registry]\n );\n\n const contextValue = useMemo<UIBridgeNativeContextValue>(\n () => ({\n features,\n config,\n registry,\n executor,\n modalDetector,\n toastCapture,\n undoTracker,\n getElements,\n getComponents,\n createSnapshot,\n on,\n off,\n initialized: true,\n serverRunning,\n startServer,\n stopServer,\n getCurrentRoute,\n }),\n [\n features,\n config,\n registry,\n executor,\n modalDetector,\n toastCapture,\n undoTracker,\n getElements,\n getComponents,\n createSnapshot,\n on,\n off,\n serverRunning,\n startServer,\n stopServer,\n getCurrentRoute,\n ]\n );\n\n return <UIBridgeNativeContext value={contextValue}>{children}</UIBridgeNativeContext>;\n}\n\n/**\n * useUIBridgeNative hook\n *\n * Access the UI Bridge Native context. Throws if used outside provider.\n */\nexport function useUIBridgeNative(): UIBridgeNativeContextValue {\n const context = use(UIBridgeNativeContext);\n if (!context) {\n throw new Error('useUIBridgeNative must be used within a UIBridgeNativeProvider');\n }\n return context;\n}\n\n/**\n * useUIBridgeNativeOptional hook\n *\n * Access the UI Bridge Native context, returning null if outside provider.\n */\nexport function useUIBridgeNativeOptional(): UIBridgeNativeContextValue | null {\n return use(UIBridgeNativeContext);\n}\n\n/**\n * useUIBridgeNativeRequired hook\n *\n * Alias for useUIBridgeNative (throws if outside provider).\n */\nexport const useUIBridgeNativeRequired = useUIBridgeNative;\n","/**\n * UI Bridge Native Debug Inspector\n *\n * An overlay component that shows registered elements and allows\n * inspection of the UI Bridge state.\n */\n\nimport { useState, useCallback, useMemo } from 'react';\nimport {\n View,\n Text,\n StyleSheet,\n TouchableOpacity,\n ScrollView,\n Modal,\n Dimensions,\n} from 'react-native';\nimport { useUIBridgeNativeOptional } from '../react/UIBridgeNativeProvider';\nimport type { RegisteredNativeElement } from '../core/types';\n\n/**\n * Inspector props\n */\nexport interface UIBridgeInspectorProps {\n /** Whether to show the inspector */\n visible?: boolean;\n /** Callback when inspector is closed */\n onClose?: () => void;\n /** Position of the inspector toggle button */\n togglePosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n}\n\n/**\n * Element info card\n */\nfunction ElementCard({\n element,\n onPress,\n}: {\n element: RegisteredNativeElement;\n onPress: (element: RegisteredNativeElement) => void;\n}) {\n const state = element.getState();\n const identifier = element.getIdentifier();\n\n return (\n <TouchableOpacity style={styles.elementCard} onPress={() => onPress(element)}>\n <View style={styles.elementHeader}>\n <Text style={styles.elementId}>{element.id}</Text>\n <Text style={styles.elementType}>{element.type}</Text>\n </View>\n {element.label && <Text style={styles.elementLabel}>{element.label}</Text>}\n <View style={styles.stateRow}>\n <StateIndicator label=\"Mounted\" value={state.mounted} />\n <StateIndicator label=\"Visible\" value={state.visible} />\n <StateIndicator label=\"Enabled\" value={state.enabled} />\n </View>\n {identifier.testId && <Text style={styles.testId}>testID: {identifier.testId}</Text>}\n </TouchableOpacity>\n );\n}\n\n/**\n * State indicator\n */\nfunction StateIndicator({ label, value }: { label: string; value: boolean }) {\n return (\n <View style={styles.stateIndicator}>\n <View style={[styles.stateDot, { backgroundColor: value ? '#4CAF50' : '#F44336' }]} />\n <Text style={styles.stateLabel}>{label}</Text>\n </View>\n );\n}\n\n/**\n * Element detail view\n */\nfunction ElementDetail({\n element,\n onClose,\n}: {\n element: RegisteredNativeElement;\n onClose: () => void;\n}) {\n const state = element.getState();\n const identifier = element.getIdentifier();\n\n return (\n <View style={styles.detailContainer}>\n <View style={styles.detailHeader}>\n <Text style={styles.detailTitle}>{element.id}</Text>\n <TouchableOpacity onPress={onClose}>\n <Text style={styles.closeButton}>Close</Text>\n </TouchableOpacity>\n </View>\n\n <ScrollView style={styles.detailContent}>\n <Text style={styles.sectionTitle}>Type</Text>\n <Text style={styles.sectionValue}>{element.type}</Text>\n\n {element.label && (\n <>\n <Text style={styles.sectionTitle}>Label</Text>\n <Text style={styles.sectionValue}>{element.label}</Text>\n </>\n )}\n\n <Text style={styles.sectionTitle}>State</Text>\n <View style={styles.stateSection}>\n <Text style={styles.stateText}>Mounted: {String(state.mounted)}</Text>\n <Text style={styles.stateText}>Visible: {String(state.visible)}</Text>\n <Text style={styles.stateText}>Enabled: {String(state.enabled)}</Text>\n <Text style={styles.stateText}>Focused: {String(state.focused)}</Text>\n {state.value !== undefined && <Text style={styles.stateText}>Value: {state.value}</Text>}\n </View>\n\n {state.layout && (\n <>\n <Text style={styles.sectionTitle}>Layout</Text>\n <View style={styles.stateSection}>\n <Text style={styles.stateText}>\n Position: ({state.layout.x}, {state.layout.y})\n </Text>\n <Text style={styles.stateText}>\n Size: {state.layout.width} x {state.layout.height}\n </Text>\n <Text style={styles.stateText}>\n Page: ({state.layout.pageX}, {state.layout.pageY})\n </Text>\n </View>\n </>\n )}\n\n <Text style={styles.sectionTitle}>Identifier</Text>\n <View style={styles.stateSection}>\n {identifier.uiId && <Text style={styles.stateText}>uiId: {identifier.uiId}</Text>}\n {identifier.testId && <Text style={styles.stateText}>testId: {identifier.testId}</Text>}\n {identifier.accessibilityLabel && (\n <Text style={styles.stateText}>a11yLabel: {identifier.accessibilityLabel}</Text>\n )}\n <Text style={styles.stateText}>treePath: {identifier.treePath}</Text>\n </View>\n\n <Text style={styles.sectionTitle}>Actions</Text>\n <View style={styles.actionsSection}>\n {element.actions.map((action) => (\n <View key={action} style={styles.actionBadge}>\n <Text style={styles.actionText}>{action}</Text>\n </View>\n ))}\n </View>\n\n {element.customActions && Object.keys(element.customActions).length > 0 && (\n <>\n <Text style={styles.sectionTitle}>Custom Actions</Text>\n <View style={styles.actionsSection}>\n {Object.keys(element.customActions).map((action) => (\n <View key={action} style={[styles.actionBadge, styles.customActionBadge]}>\n <Text style={styles.actionText}>{action}</Text>\n </View>\n ))}\n </View>\n </>\n )}\n </ScrollView>\n </View>\n );\n}\n\n/**\n * UI Bridge Inspector component\n *\n * Shows an overlay with information about registered elements.\n * Useful for debugging and development.\n *\n * @example\n * ```tsx\n * function App() {\n * const [showInspector, setShowInspector] = useState(false);\n *\n * return (\n * <UIBridgeNativeProvider features={{ debug: __DEV__ }}>\n * <MainContent />\n * {__DEV__ && (\n * <UIBridgeInspector\n * visible={showInspector}\n * onClose={() => setShowInspector(false)}\n * />\n * )}\n * </UIBridgeNativeProvider>\n * );\n * }\n * ```\n */\nexport function UIBridgeInspector({\n visible = false,\n onClose,\n togglePosition = 'bottom-right',\n}: UIBridgeInspectorProps) {\n const bridge = useUIBridgeNativeOptional();\n const [showInspector, setShowInspector] = useState(visible);\n const [selectedElement, setSelectedElement] = useState<RegisteredNativeElement | null>(null);\n\n const elements = useMemo(() => (bridge ? bridge.getElements() : []), [bridge]);\n\n const components = useMemo(() => (bridge ? bridge.getComponents() : []), [bridge]);\n\n const handleToggle = useCallback(() => {\n setShowInspector((prev) => !prev);\n }, []);\n\n const handleClose = useCallback(() => {\n setShowInspector(false);\n onClose?.();\n }, [onClose]);\n\n const handleSelectElement = useCallback((element: RegisteredNativeElement) => {\n setSelectedElement(element);\n }, []);\n\n const handleCloseDetail = useCallback(() => {\n setSelectedElement(null);\n }, []);\n\n // Position style for toggle button\n const toggleStyle = useMemo(() => {\n switch (togglePosition) {\n case 'top-left':\n return { top: 50, left: 10 };\n case 'top-right':\n return { top: 50, right: 10 };\n case 'bottom-left':\n return { bottom: 50, left: 10 };\n case 'bottom-right':\n default:\n return { bottom: 50, right: 10 };\n }\n }, [togglePosition]);\n\n if (!bridge) {\n return null;\n }\n\n return (\n <>\n {/* Toggle button */}\n <TouchableOpacity style={[styles.toggleButton, toggleStyle]} onPress={handleToggle}>\n <Text style={styles.toggleText}>UI</Text>\n </TouchableOpacity>\n\n {/* Inspector modal */}\n <Modal\n visible={showInspector}\n animationType=\"slide\"\n transparent={true}\n onRequestClose={handleClose}\n >\n <View style={styles.modalContainer}>\n <View style={styles.inspectorContainer}>\n {/* Header */}\n <View style={styles.header}>\n <Text style={styles.headerTitle}>UI Bridge Inspector</Text>\n <TouchableOpacity onPress={handleClose}>\n <Text style={styles.closeButton}>X</Text>\n </TouchableOpacity>\n </View>\n\n {/* Stats */}\n <View style={styles.statsRow}>\n <View style={styles.stat}>\n <Text style={styles.statValue}>{elements.length}</Text>\n <Text style={styles.statLabel}>Elements</Text>\n </View>\n <View style={styles.stat}>\n <Text style={styles.statValue}>{components.length}</Text>\n <Text style={styles.statLabel}>Components</Text>\n </View>\n <View style={styles.stat}>\n <Text style={styles.statValue}>{bridge.serverRunning ? 'ON' : 'OFF'}</Text>\n <Text style={styles.statLabel}>Server</Text>\n </View>\n </View>\n\n {/* Element list or detail */}\n {selectedElement ? (\n <ElementDetail element={selectedElement} onClose={handleCloseDetail} />\n ) : (\n <ScrollView style={styles.elementList}>\n {elements.map((element) => (\n <ElementCard key={element.id} element={element} onPress={handleSelectElement} />\n ))}\n {elements.length === 0 && (\n <Text style={styles.emptyText}>No elements registered yet</Text>\n )}\n </ScrollView>\n )}\n </View>\n </View>\n </Modal>\n </>\n );\n}\n\nconst { height: screenHeight } = Dimensions.get('window');\n\nconst styles = StyleSheet.create({\n toggleButton: {\n position: 'absolute',\n width: 44,\n height: 44,\n borderRadius: 22,\n backgroundColor: '#2196F3',\n justifyContent: 'center',\n alignItems: 'center',\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n shadowOpacity: 0.25,\n shadowRadius: 4,\n elevation: 5,\n zIndex: 1000,\n },\n toggleText: {\n color: '#fff',\n fontWeight: 'bold',\n fontSize: 14,\n },\n modalContainer: {\n flex: 1,\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\n justifyContent: 'flex-end',\n },\n inspectorContainer: {\n backgroundColor: '#1e1e1e',\n borderTopLeftRadius: 16,\n borderTopRightRadius: 16,\n maxHeight: screenHeight * 0.8,\n },\n header: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: 16,\n borderBottomWidth: 1,\n borderBottomColor: '#333',\n },\n headerTitle: {\n color: '#fff',\n fontSize: 18,\n fontWeight: 'bold',\n },\n closeButton: {\n color: '#2196F3',\n fontSize: 16,\n fontWeight: 'bold',\n },\n statsRow: {\n flexDirection: 'row',\n padding: 12,\n borderBottomWidth: 1,\n borderBottomColor: '#333',\n },\n stat: {\n flex: 1,\n alignItems: 'center',\n },\n statValue: {\n color: '#fff',\n fontSize: 20,\n fontWeight: 'bold',\n },\n statLabel: {\n color: '#888',\n fontSize: 12,\n marginTop: 2,\n },\n elementList: {\n padding: 12,\n },\n elementCard: {\n backgroundColor: '#2d2d2d',\n borderRadius: 8,\n padding: 12,\n marginBottom: 8,\n },\n elementHeader: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n elementId: {\n color: '#fff',\n fontSize: 14,\n fontWeight: 'bold',\n },\n elementType: {\n color: '#888',\n fontSize: 12,\n backgroundColor: '#444',\n paddingHorizontal: 8,\n paddingVertical: 2,\n borderRadius: 4,\n },\n elementLabel: {\n color: '#aaa',\n fontSize: 12,\n marginTop: 4,\n },\n stateRow: {\n flexDirection: 'row',\n marginTop: 8,\n },\n stateIndicator: {\n flexDirection: 'row',\n alignItems: 'center',\n marginRight: 12,\n },\n stateDot: {\n width: 8,\n height: 8,\n borderRadius: 4,\n marginRight: 4,\n },\n stateLabel: {\n color: '#888',\n fontSize: 10,\n },\n testId: {\n color: '#666',\n fontSize: 10,\n marginTop: 4,\n fontFamily: 'monospace',\n },\n emptyText: {\n color: '#888',\n textAlign: 'center',\n marginTop: 20,\n },\n detailContainer: {\n flex: 1,\n },\n detailHeader: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: 12,\n borderBottomWidth: 1,\n borderBottomColor: '#333',\n },\n detailTitle: {\n color: '#fff',\n fontSize: 16,\n fontWeight: 'bold',\n },\n detailContent: {\n padding: 12,\n },\n sectionTitle: {\n color: '#888',\n fontSize: 12,\n marginTop: 12,\n marginBottom: 4,\n textTransform: 'uppercase',\n },\n sectionValue: {\n color: '#fff',\n fontSize: 14,\n },\n stateSection: {\n backgroundColor: '#2d2d2d',\n borderRadius: 8,\n padding: 8,\n },\n stateText: {\n color: '#ddd',\n fontSize: 12,\n fontFamily: 'monospace',\n marginBottom: 2,\n },\n actionsSection: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n },\n actionBadge: {\n backgroundColor: '#2196F3',\n paddingHorizontal: 8,\n paddingVertical: 4,\n borderRadius: 4,\n marginRight: 6,\n marginBottom: 6,\n },\n customActionBadge: {\n backgroundColor: '#9C27B0',\n },\n actionText: {\n color: '#fff',\n fontSize: 12,\n },\n});\n"]}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* UI Bridge Native Debug Inspector
|
|
5
3
|
*
|
|
@@ -9,7 +7,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
9
7
|
/**
|
|
10
8
|
* Inspector props
|
|
11
9
|
*/
|
|
12
|
-
interface UIBridgeInspectorProps {
|
|
10
|
+
export interface UIBridgeInspectorProps {
|
|
13
11
|
/** Whether to show the inspector */
|
|
14
12
|
visible?: boolean;
|
|
15
13
|
/** Callback when inspector is closed */
|
|
@@ -42,6 +40,5 @@ interface UIBridgeInspectorProps {
|
|
|
42
40
|
* }
|
|
43
41
|
* ```
|
|
44
42
|
*/
|
|
45
|
-
declare function UIBridgeInspector({ visible, onClose, togglePosition, }: UIBridgeInspectorProps):
|
|
46
|
-
|
|
47
|
-
export { UIBridgeInspector, type UIBridgeInspectorProps };
|
|
43
|
+
export declare function UIBridgeInspector({ visible, onClose, togglePosition, }: UIBridgeInspectorProps): import("react/jsx-runtime").JSX.Element | null;
|
|
44
|
+
//# sourceMappingURL=inspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/debug/inspector.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,GAAG,cAAc,CAAC;CAC5E;AA2ID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAe,EACf,OAAO,EACP,cAA+B,GAChC,EAAE,sBAAsB,kDAuGxB"}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import { R as ResponsiveSnapshot, S as StateStyles, E as ElementDesignData, a as ExtendedComputedStyles } from '../design-types-BHr6Q1FX.mjs';
|
|
2
|
-
export { F as FlattenedNativeStyle, N as NativeInteractionStateName, b as NativeStateStyles, P as PseudoElementStyles, c as StyleDiff } from '../design-types-BHr6Q1FX.mjs';
|
|
3
|
-
import { o as NativeLayout } from '../types-CGVut7mc.mjs';
|
|
4
|
-
|
|
5
1
|
/**
|
|
6
2
|
* Native Design Inspector
|
|
7
3
|
*
|
|
@@ -18,7 +14,8 @@ import { o as NativeLayout } from '../types-CGVut7mc.mjs';
|
|
|
18
14
|
* - Shadows differ: iOS uses shadow* props, Android uses elevation
|
|
19
15
|
* - Numeric values → "Npx" strings
|
|
20
16
|
*/
|
|
21
|
-
|
|
17
|
+
import type { ExtendedComputedStyles, ElementDesignData, StateStyles, ResponsiveSnapshot } from './design-types';
|
|
18
|
+
import type { NativeLayout } from '../core/types';
|
|
22
19
|
/**
|
|
23
20
|
* Map a flattened React Native style object to ExtendedComputedStyles.
|
|
24
21
|
*
|
|
@@ -29,16 +26,16 @@ import { o as NativeLayout } from '../types-CGVut7mc.mjs';
|
|
|
29
26
|
* - RN shadow props → boxShadow string
|
|
30
27
|
* - CSS-only properties (cursor, visibility, grid*, etc.) → empty string
|
|
31
28
|
*/
|
|
32
|
-
declare function mapNativeStyleToExtended(rnStyle: Record<string, unknown> | undefined | null): ExtendedComputedStyles;
|
|
29
|
+
export declare function mapNativeStyleToExtended(rnStyle: Record<string, unknown> | undefined | null): ExtendedComputedStyles;
|
|
33
30
|
/**
|
|
34
31
|
* Produce ElementDesignData for a single native element.
|
|
35
32
|
*/
|
|
36
|
-
declare function getNativeElementDesignData(id: string, label: string | undefined, type: string, rnStyle: Record<string, unknown> | undefined | null, layout: NativeLayout | null): ElementDesignData;
|
|
33
|
+
export declare function getNativeElementDesignData(id: string, label: string | undefined, type: string, rnStyle: Record<string, unknown> | undefined | null, layout: NativeLayout | null): ElementDesignData;
|
|
37
34
|
/**
|
|
38
35
|
* Produce StateStyles[] for default/pressed/focused/disabled.
|
|
39
36
|
* Only includes states that have actual overrides or the default state.
|
|
40
37
|
*/
|
|
41
|
-
declare function captureNativeStateVariations(baseStyle: Record<string, unknown> | undefined | null, stateStyles?: {
|
|
38
|
+
export declare function captureNativeStateVariations(baseStyle: Record<string, unknown> | undefined | null, stateStyles?: {
|
|
42
39
|
pressed?: Record<string, unknown>;
|
|
43
40
|
focused?: Record<string, unknown>;
|
|
44
41
|
disabled?: Record<string, unknown>;
|
|
@@ -49,7 +46,7 @@ declare function captureNativeStateVariations(baseStyle: Record<string, unknown>
|
|
|
49
46
|
* Platform limitation: RN cannot constrain screen width at runtime.
|
|
50
47
|
* This returns a single snapshot at the current device dimensions.
|
|
51
48
|
*/
|
|
52
|
-
declare function captureNativeResponsiveSnapshot(elements: Array<{
|
|
49
|
+
export declare function captureNativeResponsiveSnapshot(elements: Array<{
|
|
53
50
|
id: string;
|
|
54
51
|
label?: string;
|
|
55
52
|
type: string;
|
|
@@ -59,5 +56,4 @@ declare function captureNativeResponsiveSnapshot(elements: Array<{
|
|
|
59
56
|
width: number;
|
|
60
57
|
height: number;
|
|
61
58
|
}): ResponsiveSnapshot[];
|
|
62
|
-
|
|
63
|
-
export { ElementDesignData, ExtendedComputedStyles, ResponsiveSnapshot, StateStyles, captureNativeResponsiveSnapshot, captureNativeStateVariations, getNativeElementDesignData, mapNativeStyleToExtended };
|
|
59
|
+
//# sourceMappingURL=design-inspector-native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-inspector-native.d.ts","sourceRoot":"","sources":["../../src/design/design-inspector-native.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,sBAAsB,EACtB,iBAAiB,EACjB,WAAW,EAEX,kBAAkB,EAEnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA6JlD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GAClD,sBAAsB,CAqExB;AAMD;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EACnD,MAAM,EAAE,YAAY,GAAG,IAAI,GAC1B,iBAAiB,CAgBnB;AAiCD;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EACrD,WAAW,CAAC,EAAE;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,GACA,WAAW,EAAE,CA+Bf;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,KAAK,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;CAC7B,CAAC,EACF,gBAAgB,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClD,kBAAkB,EAAE,CAatB"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Extended computed styles (~40 design-relevant CSS properties).
|
|
9
9
|
* This is the canonical format shared with the web SDK.
|
|
10
10
|
*/
|
|
11
|
-
interface ExtendedComputedStyles {
|
|
11
|
+
export interface ExtendedComputedStyles {
|
|
12
12
|
display: string;
|
|
13
13
|
position: string;
|
|
14
14
|
boxSizing: string;
|
|
@@ -65,7 +65,7 @@ interface ExtendedComputedStyles {
|
|
|
65
65
|
/**
|
|
66
66
|
* Style diff entry: a property that changed from default state
|
|
67
67
|
*/
|
|
68
|
-
interface StyleDiff {
|
|
68
|
+
export interface StyleDiff {
|
|
69
69
|
property: string;
|
|
70
70
|
defaultValue: string;
|
|
71
71
|
stateValue: string;
|
|
@@ -73,7 +73,7 @@ interface StyleDiff {
|
|
|
73
73
|
/**
|
|
74
74
|
* Styles captured in a specific interaction state
|
|
75
75
|
*/
|
|
76
|
-
interface StateStyles {
|
|
76
|
+
export interface StateStyles {
|
|
77
77
|
state: NativeInteractionStateName;
|
|
78
78
|
styles: ExtendedComputedStyles;
|
|
79
79
|
diffFromDefault: StyleDiff[];
|
|
@@ -81,7 +81,7 @@ interface StateStyles {
|
|
|
81
81
|
/**
|
|
82
82
|
* Full design data for a single element
|
|
83
83
|
*/
|
|
84
|
-
interface ElementDesignData {
|
|
84
|
+
export interface ElementDesignData {
|
|
85
85
|
elementId: string;
|
|
86
86
|
label?: string;
|
|
87
87
|
type: string;
|
|
@@ -98,7 +98,7 @@ interface ElementDesignData {
|
|
|
98
98
|
/**
|
|
99
99
|
* Pseudo-element styles (always empty on RN — no ::before/::after)
|
|
100
100
|
*/
|
|
101
|
-
interface PseudoElementStyles {
|
|
101
|
+
export interface PseudoElementStyles {
|
|
102
102
|
selector: '::before' | '::after';
|
|
103
103
|
content: string;
|
|
104
104
|
styles: Partial<ExtendedComputedStyles>;
|
|
@@ -106,7 +106,7 @@ interface PseudoElementStyles {
|
|
|
106
106
|
/**
|
|
107
107
|
* Design snapshot at a specific viewport/screen size
|
|
108
108
|
*/
|
|
109
|
-
interface ResponsiveSnapshot {
|
|
109
|
+
export interface ResponsiveSnapshot {
|
|
110
110
|
viewportWidth: number;
|
|
111
111
|
viewportLabel?: string;
|
|
112
112
|
elements: ElementDesignData[];
|
|
@@ -116,7 +116,7 @@ interface ResponsiveSnapshot {
|
|
|
116
116
|
* Flattened React Native style — explicit RN style properties.
|
|
117
117
|
* Not tied to any specific RN version. All properties optional.
|
|
118
118
|
*/
|
|
119
|
-
interface FlattenedNativeStyle {
|
|
119
|
+
export interface FlattenedNativeStyle {
|
|
120
120
|
display?: 'flex' | 'none';
|
|
121
121
|
position?: 'absolute' | 'relative';
|
|
122
122
|
width?: number | string;
|
|
@@ -191,7 +191,7 @@ interface FlattenedNativeStyle {
|
|
|
191
191
|
/**
|
|
192
192
|
* State-specific style overrides for RN (maps to Pressable states)
|
|
193
193
|
*/
|
|
194
|
-
interface NativeStateStyles {
|
|
194
|
+
export interface NativeStateStyles {
|
|
195
195
|
pressed?: FlattenedNativeStyle;
|
|
196
196
|
focused?: FlattenedNativeStyle;
|
|
197
197
|
disabled?: FlattenedNativeStyle;
|
|
@@ -200,6 +200,5 @@ interface NativeStateStyles {
|
|
|
200
200
|
* Native interaction state names.
|
|
201
201
|
* RN doesn't have hover/active — uses pressed, focused, disabled instead.
|
|
202
202
|
*/
|
|
203
|
-
type NativeInteractionStateName = 'default' | 'pressed' | 'focused' | 'disabled';
|
|
204
|
-
|
|
205
|
-
export type { ElementDesignData as E, FlattenedNativeStyle as F, NativeInteractionStateName as N, PseudoElementStyles as P, ResponsiveSnapshot as R, StateStyles as S, ExtendedComputedStyles as a, NativeStateStyles as b, StyleDiff as c };
|
|
203
|
+
export type NativeInteractionStateName = 'default' | 'pressed' | 'focused' | 'disabled';
|
|
204
|
+
//# sourceMappingURL=design-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-types.d.ts","sourceRoot":"","sources":["../../src/design/design-types.ts"],"names":[],"mappings":"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"}
|
package/dist/design/index.d.ts
CHANGED
|
@@ -1,63 +1,8 @@
|
|
|
1
|
-
import { R as ResponsiveSnapshot, S as StateStyles, E as ElementDesignData, a as ExtendedComputedStyles } from '../design-types-BHr6Q1FX.js';
|
|
2
|
-
export { F as FlattenedNativeStyle, N as NativeInteractionStateName, b as NativeStateStyles, P as PseudoElementStyles, c as StyleDiff } from '../design-types-BHr6Q1FX.js';
|
|
3
|
-
import { o as NativeLayout } from '../types-CGVut7mc.js';
|
|
4
|
-
|
|
5
1
|
/**
|
|
6
|
-
* Native Design
|
|
2
|
+
* UI Bridge Native - Design Review
|
|
7
3
|
*
|
|
8
|
-
*
|
|
9
|
-
* web SDK's ExtendedComputedStyles format. No react-native imports — works
|
|
10
|
-
* with already-flattened style objects from the registry.
|
|
11
|
-
*
|
|
12
|
-
* Key differences from web:
|
|
13
|
-
* - No `window.getComputedStyle()` — styles are declarative objects
|
|
14
|
-
* - No hover/active states — uses pressed/focused/disabled
|
|
15
|
-
* - No pseudo-elements (::before/::after)
|
|
16
|
-
* - No CSS grid, cursor, visibility, transitions, background-image
|
|
17
|
-
* - RN default flexDirection is 'column' (not 'row')
|
|
18
|
-
* - Shadows differ: iOS uses shadow* props, Android uses elevation
|
|
19
|
-
* - Numeric values → "Npx" strings
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Map a flattened React Native style object to ExtendedComputedStyles.
|
|
24
|
-
*
|
|
25
|
-
* Rules:
|
|
26
|
-
* - Numeric values → "Npx"
|
|
27
|
-
* - String values → pass through
|
|
28
|
-
* - textDecorationLine → textDecoration
|
|
29
|
-
* - RN shadow props → boxShadow string
|
|
30
|
-
* - CSS-only properties (cursor, visibility, grid*, etc.) → empty string
|
|
31
|
-
*/
|
|
32
|
-
declare function mapNativeStyleToExtended(rnStyle: Record<string, unknown> | undefined | null): ExtendedComputedStyles;
|
|
33
|
-
/**
|
|
34
|
-
* Produce ElementDesignData for a single native element.
|
|
35
|
-
*/
|
|
36
|
-
declare function getNativeElementDesignData(id: string, label: string | undefined, type: string, rnStyle: Record<string, unknown> | undefined | null, layout: NativeLayout | null): ElementDesignData;
|
|
37
|
-
/**
|
|
38
|
-
* Produce StateStyles[] for default/pressed/focused/disabled.
|
|
39
|
-
* Only includes states that have actual overrides or the default state.
|
|
40
|
-
*/
|
|
41
|
-
declare function captureNativeStateVariations(baseStyle: Record<string, unknown> | undefined | null, stateStyles?: {
|
|
42
|
-
pressed?: Record<string, unknown>;
|
|
43
|
-
focused?: Record<string, unknown>;
|
|
44
|
-
disabled?: Record<string, unknown>;
|
|
45
|
-
}): StateStyles[];
|
|
46
|
-
/**
|
|
47
|
-
* Capture a responsive snapshot.
|
|
48
|
-
*
|
|
49
|
-
* Platform limitation: RN cannot constrain screen width at runtime.
|
|
50
|
-
* This returns a single snapshot at the current device dimensions.
|
|
4
|
+
* Style capture, mapping, and design review for React Native elements.
|
|
51
5
|
*/
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
type: string;
|
|
56
|
-
flatStyle?: Record<string, unknown>;
|
|
57
|
-
layout: NativeLayout | null;
|
|
58
|
-
}>, screenDimensions: {
|
|
59
|
-
width: number;
|
|
60
|
-
height: number;
|
|
61
|
-
}): ResponsiveSnapshot[];
|
|
62
|
-
|
|
63
|
-
export { ElementDesignData, ExtendedComputedStyles, ResponsiveSnapshot, StateStyles, captureNativeResponsiveSnapshot, captureNativeStateVariations, getNativeElementDesignData, mapNativeStyleToExtended };
|
|
6
|
+
export type { ExtendedComputedStyles, StyleDiff, StateStyles, ElementDesignData, PseudoElementStyles, ResponsiveSnapshot, FlattenedNativeStyle, NativeStateStyles, NativeInteractionStateName, } from './design-types';
|
|
7
|
+
export { mapNativeStyleToExtended, getNativeElementDesignData, captureNativeStateVariations, captureNativeResponsiveSnapshot, } from './design-inspector-native';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/design/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,sBAAsB,EACtB,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,4BAA4B,EAC5B,+BAA+B,GAChC,MAAM,2BAA2B,CAAC"}
|