@symbiote-native/navigation 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/README.md +89 -14
  2. package/build/angular/drawer/index.js +23 -9
  3. package/build/angular/index.d.ts +4 -4
  4. package/build/angular/index.js +1 -1
  5. package/build/angular/injectors/inject-navigation.js +1 -1
  6. package/build/angular/navigation-scope.directive.js +1 -1
  7. package/build/angular/search-bar-ref.directive.js +1 -1
  8. package/build/angular/stack/index.js +20 -6
  9. package/build/angular/tabs/index.js +21 -7
  10. package/build/core/drawer-options/index.js +19 -5
  11. package/build/core/drawer-router-state/index.js +8 -2
  12. package/build/core/guards.js +3 -1
  13. package/build/core/header-bar-buttons.js +14 -4
  14. package/build/core/index.d.ts +4 -4
  15. package/build/core/index.js +2 -2
  16. package/build/core/navigator-state/index.js +12 -4
  17. package/build/core/render-drawer.js +4 -1
  18. package/build/core/render-stack.js +13 -4
  19. package/build/core/screen-options.js +1 -1
  20. package/build/core/search-bar-commands.js +1 -1
  21. package/build/core/state-persistence/index.js +6 -2
  22. package/build/core/tab-router-state/index.js +8 -2
  23. package/build/react/drawer/index.js +36 -13
  24. package/build/react/index.d.ts +7 -7
  25. package/build/react/index.js +3 -3
  26. package/build/react/stack/index.js +34 -8
  27. package/build/react/tabs/index.js +14 -4
  28. package/build/solid/drawer/index.d.ts +22 -0
  29. package/build/solid/drawer/index.js +394 -0
  30. package/build/solid/drawer-screen-props.d.ts +13 -0
  31. package/build/solid/drawer-screen-props.js +2 -0
  32. package/build/solid/host.d.ts +2 -0
  33. package/build/solid/host.js +23 -0
  34. package/build/solid/index.d.ts +19 -0
  35. package/build/solid/index.js +24 -0
  36. package/build/solid/linking.d.ts +3 -0
  37. package/build/solid/linking.js +55 -0
  38. package/build/solid/navigation-context.d.ts +13 -0
  39. package/build/solid/navigation-context.js +37 -0
  40. package/build/solid/primitives/create-focus-effect.d.ts +1 -0
  41. package/build/solid/primitives/create-focus-effect.js +30 -0
  42. package/build/solid/primitives/create-is-focused.d.ts +2 -0
  43. package/build/solid/primitives/create-is-focused.js +31 -0
  44. package/build/solid/primitives/create-navigation-state.d.ts +3 -0
  45. package/build/solid/primitives/create-navigation-state.js +30 -0
  46. package/build/solid/primitives/index.d.ts +12 -0
  47. package/build/solid/primitives/index.js +8 -0
  48. package/build/solid/primitives/use-drawer-navigation.d.ts +5 -0
  49. package/build/solid/primitives/use-drawer-navigation.js +15 -0
  50. package/build/solid/primitives/use-navigation.d.ts +8 -0
  51. package/build/solid/primitives/use-navigation.js +23 -0
  52. package/build/solid/primitives/use-route.d.ts +3 -0
  53. package/build/solid/primitives/use-route.js +14 -0
  54. package/build/solid/primitives/use-stack-navigation.d.ts +5 -0
  55. package/build/solid/primitives/use-stack-navigation.js +19 -0
  56. package/build/solid/primitives/use-tab-navigation.d.ts +5 -0
  57. package/build/solid/primitives/use-tab-navigation.js +15 -0
  58. package/build/solid/screen-props.d.ts +19 -0
  59. package/build/solid/screen-props.js +9 -0
  60. package/build/solid/screen-registry.d.ts +31 -0
  61. package/build/solid/screen-registry.js +86 -0
  62. package/build/solid/screen.d.ts +6 -0
  63. package/build/solid/screen.js +69 -0
  64. package/build/solid/stack/index.d.ts +15 -0
  65. package/build/solid/stack/index.js +348 -0
  66. package/build/solid/tab-screen-props.d.ts +13 -0
  67. package/build/solid/tab-screen-props.js +3 -0
  68. package/build/solid/tabs/index.d.ts +14 -0
  69. package/build/solid/tabs/index.js +228 -0
  70. package/build/svelte/descriptor-subtree.js +3 -1
  71. package/build/svelte/drawer/index.svelte +163 -25
  72. package/build/svelte/drawer-screen.svelte +2 -1
  73. package/build/svelte/index.d.ts +3 -3
  74. package/build/svelte/index.js +1 -1
  75. package/build/svelte/navigation-scope.svelte +4 -1
  76. package/build/svelte/runes/use-navigation.svelte.js +5 -1
  77. package/build/svelte/stack/index.svelte +43 -6
  78. package/build/svelte/stack/stack-screen.svelte +66 -9
  79. package/build/svelte/tabs/index.svelte +42 -20
  80. package/build/vue/composables/use-navigation.js +5 -1
  81. package/build/vue/drawer/index.js +30 -8
  82. package/build/vue/index.d.ts +3 -3
  83. package/build/vue/index.js +1 -1
  84. package/build/vue/navigation-context.js +1 -1
  85. package/build/vue/stack/index.js +17 -6
  86. package/build/vue/tabs/index.js +18 -5
  87. package/build-ngc/angular/drawer/index.js +31 -11
  88. package/build-ngc/angular/drawer/index.js.map +1 -1
  89. package/build-ngc/angular/index.d.ts +4 -4
  90. package/build-ngc/angular/index.js.map +1 -1
  91. package/build-ngc/angular/injectors/inject-focus-effect.js.map +1 -1
  92. package/build-ngc/angular/injectors/inject-is-focused.js.map +1 -1
  93. package/build-ngc/angular/injectors/inject-navigation-state.js.map +1 -1
  94. package/build-ngc/angular/injectors/inject-navigation.js +1 -1
  95. package/build-ngc/angular/injectors/inject-navigation.js.map +1 -1
  96. package/build-ngc/angular/linking.js.map +1 -1
  97. package/build-ngc/angular/navigation-context.service.js.map +1 -1
  98. package/build-ngc/angular/navigation-scope.directive.js +1 -1
  99. package/build-ngc/angular/navigation-scope.directive.js.map +1 -1
  100. package/build-ngc/angular/screen.directive.js.map +1 -1
  101. package/build-ngc/angular/search-bar-ref.directive.js +1 -1
  102. package/build-ngc/angular/search-bar-ref.directive.js.map +1 -1
  103. package/build-ngc/angular/stack/index.js +26 -8
  104. package/build-ngc/angular/stack/index.js.map +1 -1
  105. package/build-ngc/angular/tab-screen.directive.js.map +1 -1
  106. package/build-ngc/angular/tabs/index.js +21 -7
  107. package/build-ngc/angular/tabs/index.js.map +1 -1
  108. package/build-ngc/core/constants.js.map +1 -1
  109. package/build-ngc/core/drawer-options/index.js +19 -5
  110. package/build-ngc/core/drawer-options/index.js.map +1 -1
  111. package/build-ngc/core/drawer-router-state/index.js +8 -2
  112. package/build-ngc/core/drawer-router-state/index.js.map +1 -1
  113. package/build-ngc/core/guards.js +3 -1
  114. package/build-ngc/core/guards.js.map +1 -1
  115. package/build-ngc/core/header-bar-buttons.js +14 -4
  116. package/build-ngc/core/header-bar-buttons.js.map +1 -1
  117. package/build-ngc/core/index.d.ts +4 -4
  118. package/build-ngc/core/index.js +2 -2
  119. package/build-ngc/core/index.js.map +1 -1
  120. package/build-ngc/core/linking-config/index.js.map +1 -1
  121. package/build-ngc/core/navigation-events/index.js.map +1 -1
  122. package/build-ngc/core/navigator-handles/index.js.map +1 -1
  123. package/build-ngc/core/navigator-state/index.js +12 -4
  124. package/build-ngc/core/navigator-state/index.js.map +1 -1
  125. package/build-ngc/core/render-drawer.js +4 -1
  126. package/build-ngc/core/render-drawer.js.map +1 -1
  127. package/build-ngc/core/render-stack.js +13 -4
  128. package/build-ngc/core/render-stack.js.map +1 -1
  129. package/build-ngc/core/render-tabs.js.map +1 -1
  130. package/build-ngc/core/screen-options.js +1 -1
  131. package/build-ngc/core/screen-options.js.map +1 -1
  132. package/build-ngc/core/search-bar-commands.js +1 -1
  133. package/build-ngc/core/search-bar-commands.js.map +1 -1
  134. package/build-ngc/core/stack-router-state/index.js.map +1 -1
  135. package/build-ngc/core/state-persistence/index.js +6 -2
  136. package/build-ngc/core/state-persistence/index.js.map +1 -1
  137. package/build-ngc/core/tab-router-state/index.js +8 -2
  138. package/build-ngc/core/tab-router-state/index.js.map +1 -1
  139. package/package.json +40 -15
  140. package/src/angular/drawer/index.ts +69 -25
  141. package/src/angular/index.ts +20 -4
  142. package/src/angular/injectors/inject-focus-effect.ts +8 -2
  143. package/src/angular/injectors/inject-is-focused.ts +6 -4
  144. package/src/angular/injectors/inject-navigation-state.ts +7 -4
  145. package/src/angular/injectors/inject-navigation.ts +12 -3
  146. package/src/angular/linking.ts +4 -1
  147. package/src/angular/navigation-context.service.ts +5 -2
  148. package/src/angular/navigation-scope.directive.ts +6 -2
  149. package/src/angular/screen.directive.ts +13 -3
  150. package/src/angular/search-bar-ref.directive.ts +10 -2
  151. package/src/angular/stack/index.ts +68 -22
  152. package/src/angular/tab-screen.directive.ts +3 -1
  153. package/src/angular/tabs/index.ts +36 -12
  154. package/src/core/constants.ts +6 -3
  155. package/src/core/drawer-options/index.ts +40 -13
  156. package/src/core/drawer-router-state/index.ts +11 -3
  157. package/src/core/guards.ts +3 -1
  158. package/src/core/header-bar-buttons.ts +41 -12
  159. package/src/core/index.ts +18 -4
  160. package/src/core/linking-config/index.ts +31 -10
  161. package/src/core/navigation-events/index.ts +8 -2
  162. package/src/core/navigator-handles/index.ts +8 -3
  163. package/src/core/navigator-props.ts +13 -4
  164. package/src/core/navigator-state/index.ts +24 -7
  165. package/src/core/render-drawer.ts +24 -9
  166. package/src/core/render-stack.ts +52 -13
  167. package/src/core/render-tabs.ts +24 -6
  168. package/src/core/screen-options.ts +15 -5
  169. package/src/core/search-bar-commands.ts +12 -3
  170. package/src/core/stack-router-state/index.ts +5 -2
  171. package/src/core/state-persistence/index.ts +13 -3
  172. package/src/core/tab-router-state/index.ts +10 -3
  173. package/src/react/drawer/index.ts +408 -344
  174. package/src/react/drawer-screen.ts +8 -2
  175. package/src/react/hooks/use-focus-effect.ts +8 -2
  176. package/src/react/hooks/use-is-focused.ts +6 -2
  177. package/src/react/hooks/use-navigation.ts +8 -2
  178. package/src/react/index.ts +37 -7
  179. package/src/react/linking.ts +4 -1
  180. package/src/react/navigation-context.ts +6 -2
  181. package/src/react/screen.ts +12 -3
  182. package/src/react/stack/index.ts +294 -231
  183. package/src/react/tab-screen.ts +3 -1
  184. package/src/react/tabs/index.ts +188 -158
  185. package/src/solid/drawer/index.ts +570 -0
  186. package/src/solid/drawer-screen-props.ts +24 -0
  187. package/src/solid/host.ts +29 -0
  188. package/src/solid/index.ts +87 -0
  189. package/src/solid/linking.ts +74 -0
  190. package/src/solid/navigation-context.ts +56 -0
  191. package/src/solid/primitives/create-focus-effect.ts +41 -0
  192. package/src/solid/primitives/create-is-focused.ts +41 -0
  193. package/src/solid/primitives/create-navigation-state.ts +44 -0
  194. package/src/solid/primitives/index.ts +12 -0
  195. package/src/solid/primitives/use-drawer-navigation.ts +25 -0
  196. package/src/solid/primitives/use-navigation.ts +44 -0
  197. package/src/solid/primitives/use-route.ts +18 -0
  198. package/src/solid/primitives/use-stack-navigation.ts +29 -0
  199. package/src/solid/primitives/use-tab-navigation.ts +25 -0
  200. package/src/solid/screen-props.ts +51 -0
  201. package/src/solid/screen-registry.ts +159 -0
  202. package/src/solid/screen.ts +80 -0
  203. package/src/solid/stack/index.ts +528 -0
  204. package/src/solid/tab-screen-props.ts +21 -0
  205. package/src/solid/tabs/index.ts +327 -0
  206. package/src/svelte/attachments.ts +3 -1
  207. package/src/svelte/descriptor-subtree.ts +3 -1
  208. package/src/svelte/drawer/index.svelte +163 -25
  209. package/src/svelte/drawer-screen-props.ts +8 -2
  210. package/src/svelte/drawer-screen.svelte +2 -1
  211. package/src/svelte/fabric-tree.test-helper.ts +37 -3
  212. package/src/svelte/index.ts +15 -3
  213. package/src/svelte/linking.svelte.ts +11 -5
  214. package/src/svelte/navigation-scope.svelte +4 -1
  215. package/src/svelte/runes/use-drawer-navigation.svelte.ts +3 -1
  216. package/src/svelte/runes/use-focus-effect.svelte.ts +8 -2
  217. package/src/svelte/runes/use-navigation-state.svelte.ts +3 -1
  218. package/src/svelte/runes/use-navigation.svelte.ts +13 -3
  219. package/src/svelte/runes/use-stack-navigation.svelte.ts +3 -1
  220. package/src/svelte/screen-props.ts +7 -2
  221. package/src/svelte/screen-registry.ts +9 -3
  222. package/src/svelte/stack/index.svelte +43 -6
  223. package/src/svelte/stack/stack-screen.svelte +66 -9
  224. package/src/svelte/svelte-compile.test-helper.ts +16 -12
  225. package/src/svelte/tab-screen-props.ts +3 -1
  226. package/src/svelte/tabs/index.svelte +42 -20
  227. package/src/vue/composables/use-navigation-state.ts +7 -4
  228. package/src/vue/composables/use-navigation.ts +13 -3
  229. package/src/vue/drawer/index.ts +122 -36
  230. package/src/vue/drawer-screen.ts +12 -5
  231. package/src/vue/index.ts +15 -3
  232. package/src/vue/linking.ts +7 -2
  233. package/src/vue/navigation-context.ts +17 -5
  234. package/src/vue/screen.ts +7 -2
  235. package/src/vue/stack/index.ts +82 -34
  236. package/src/vue/tab-screen.ts +3 -1
  237. package/src/vue/tabs/index.ts +51 -13
@@ -24,8 +24,17 @@
24
24
  <script lang="ts">
25
25
  import type { Component } from 'svelte';
26
26
  import { onDestroy, tick } from 'svelte';
27
- import { AnimatedValue, Dimensions, PanResponder, dlog, timing } from '@symbiote-native/engine';
28
- import type { IPanResponderGestureState, ISymbioteEvent } from '@symbiote-native/engine';
27
+ import {
28
+ AnimatedValue,
29
+ Dimensions,
30
+ PanResponder,
31
+ dlog,
32
+ timing,
33
+ } from '@symbiote-native/engine';
34
+ import type {
35
+ IPanResponderGestureState,
36
+ ISymbioteEvent,
37
+ } from '@symbiote-native/engine';
29
38
  // The ONLY import from the adapter's main barrel: `Animated.View` is a compiled `.svelte`
30
39
  // component, so unlike PanResponder/Dimensions/AnimatedValue (pure engine re-exports, taken
31
40
  // from the engine directly here) it has no `.svelte`-free home to import from.
@@ -63,7 +72,11 @@
63
72
  import type { INavigationScopeValue } from '../navigation-context';
64
73
  import NavigationScope from '../navigation-scope.svelte';
65
74
  import { SCREEN_REGISTRY_HOST_PROPS } from '../registry-host';
66
- import { setScreenCollector, toRegistry, withoutScreen } from '../screen-registry';
75
+ import {
76
+ setScreenCollector,
77
+ toRegistry,
78
+ withoutScreen,
79
+ } from '../screen-registry';
67
80
  import type { IRegisteredScreen } from '../screen-registry';
68
81
  import type { IDrawerScreenProps } from '../drawer-screen-props';
69
82
  import type { IDrawerProps } from './drawer-props';
@@ -103,7 +116,9 @@
103
116
  swipeMinVelocity,
104
117
  });
105
118
 
106
- let screens = $state.raw<IRegisteredScreen<IDrawerScreenProps['options']>[]>([]);
119
+ let screens = $state.raw<IRegisteredScreen<IDrawerScreenProps['options']>[]>(
120
+ [],
121
+ );
107
122
  setScreenCollector<IDrawerScreenProps['options']>({
108
123
  kind: 'drawer',
109
124
  register: screen => {
@@ -123,10 +138,16 @@
123
138
 
124
139
  function seedState(): IDrawerRouterState {
125
140
  if (seededState !== undefined) return seededState;
126
- const routes: IRoute<unknown>[] = [...registry.entries()].map(([name, entry]) => {
127
- routeSequence += 1;
128
- return { key: `${routeIdPrefix}-${name}-${routeSequence}`, name, params: entry.initialParams };
129
- });
141
+ const routes: IRoute<unknown>[] = [...registry.entries()].map(
142
+ ([name, entry]) => {
143
+ routeSequence += 1;
144
+ return {
145
+ key: `${routeIdPrefix}-${name}-${routeSequence}`,
146
+ name,
147
+ params: entry.initialParams,
148
+ };
149
+ },
150
+ );
130
151
  if (routes.length === 0) {
131
152
  dlog('Drawer: no <Drawer.Screen> children registered');
132
153
  // Deliberately not memoized - markers may still be registering.
@@ -164,17 +185,23 @@
164
185
  }
165
186
 
166
187
  export function openDrawer(): void {
167
- dlog(`Drawer: openDrawer() called, isOpen=${state.isOpen} at t=${Date.now()}`);
188
+ dlog(
189
+ `Drawer: openDrawer() called, isOpen=${state.isOpen} at t=${Date.now()}`,
190
+ );
168
191
  animateProgressTo(true);
169
192
  dispatch({ type: 'openDrawer' });
170
193
  }
171
194
  export function closeDrawer(): void {
172
- dlog(`Drawer: closeDrawer() called, isOpen=${state.isOpen} at t=${Date.now()}`);
195
+ dlog(
196
+ `Drawer: closeDrawer() called, isOpen=${state.isOpen} at t=${Date.now()}`,
197
+ );
173
198
  animateProgressTo(false);
174
199
  dispatch({ type: 'closeDrawer' });
175
200
  }
176
201
  export function toggleDrawer(): void {
177
- dlog(`Drawer: toggleDrawer() called, isOpen=${state.isOpen} at t=${Date.now()}`);
202
+ dlog(
203
+ `Drawer: toggleDrawer() called, isOpen=${state.isOpen} at t=${Date.now()}`,
204
+ );
178
205
  animateProgressTo(!state.isOpen);
179
206
  dispatch({ type: 'toggleDrawer' });
180
207
  }
@@ -189,7 +216,12 @@
189
216
  if (wasOpen && !state.isOpen) animateProgressTo(false);
190
217
  }
191
218
 
192
- const handle: IDrawerNavigatorHandle = { openDrawer, closeDrawer, toggleDrawer, jumpTo };
219
+ const handle: IDrawerNavigatorHandle = {
220
+ openDrawer,
221
+ closeDrawer,
222
+ toggleDrawer,
223
+ jumpTo,
224
+ };
193
225
 
194
226
  // The window width is read fresh AT GESTURE TIME rather than through a reactive
195
227
  // window-dimensions rune: it is only ever consumed inside these PanResponder callbacks (never
@@ -224,8 +256,13 @@
224
256
  dlog('Drawer: gesture grant');
225
257
  dragStartProgress = state.isOpen ? 1 : 0;
226
258
  },
227
- onPanResponderMove: (_event: ISymbioteEvent, gestureState: IPanResponderGestureState): void => {
228
- progress.setValue(resolveDragProgress(gestureState, dragStartProgress, options));
259
+ onPanResponderMove: (
260
+ _event: ISymbioteEvent,
261
+ gestureState: IPanResponderGestureState,
262
+ ): void => {
263
+ progress.setValue(
264
+ resolveDragProgress(gestureState, dragStartProgress, options),
265
+ );
229
266
  },
230
267
  onPanResponderRelease: (
231
268
  _event: ISymbioteEvent,
@@ -288,12 +325,16 @@
288
325
 
289
326
  const panelTranslateX = $derived(
290
327
  animated
291
- ? progress.interpolate(resolveDrawerSlotInterpolation(geometry, 'panel').translateX)
328
+ ? progress.interpolate(
329
+ resolveDrawerSlotInterpolation(geometry, 'panel').translateX,
330
+ )
292
331
  : undefined,
293
332
  );
294
333
  const contentTranslateX = $derived(
295
334
  animated
296
- ? progress.interpolate(resolveDrawerSlotInterpolation(geometry, 'content').translateX)
335
+ ? progress.interpolate(
336
+ resolveDrawerSlotInterpolation(geometry, 'content').translateX,
337
+ )
297
338
  : undefined,
298
339
  );
299
340
  // The overlay is a full-screen absolutely-positioned sibling BELOW content in paint order (see
@@ -310,14 +351,22 @@
310
351
  ? undefined
311
352
  : {
312
353
  opacity: progress.interpolate(overlayInterpolation.opacity),
313
- transform: [{ translateX: progress.interpolate(overlayInterpolation.translateX) }],
354
+ transform: [
355
+ {
356
+ translateX: progress.interpolate(overlayInterpolation.translateX),
357
+ },
358
+ ],
314
359
  },
315
360
  );
316
361
  const contentStyle = $derived(
317
- contentTranslateX === undefined ? undefined : { transform: [{ translateX: contentTranslateX }] },
362
+ contentTranslateX === undefined
363
+ ? undefined
364
+ : { transform: [{ translateX: contentTranslateX }] },
318
365
  );
319
366
  const panelStyle = $derived(
320
- panelTranslateX === undefined ? undefined : { transform: [{ translateX: panelTranslateX }] },
367
+ panelTranslateX === undefined
368
+ ? undefined
369
+ : { transform: [{ translateX: panelTranslateX }] },
321
370
  );
322
371
 
323
372
  const focusedRoute = $derived(state.routes[state.index]);
@@ -327,7 +376,9 @@
327
376
  if (focusedRoute === undefined) return undefined;
328
377
  const entry = registry.get(focusedRoute.name);
329
378
  if (entry === undefined) {
330
- dlog(`Drawer: no screen registered for route name "${focusedRoute.name}"`);
379
+ dlog(
380
+ `Drawer: no screen registered for route name "${focusedRoute.name}"`,
381
+ );
331
382
  return undefined;
332
383
  }
333
384
  return {
@@ -345,7 +396,8 @@
345
396
  entry: IRegisteredScreen<IDrawerScreenProps['options']>,
346
397
  route: IRoute<unknown>,
347
398
  ): IDrawerScreenOptions {
348
- if (typeof entry.options === 'function') return entry.options({ route, navigation: handle });
399
+ if (typeof entry.options === 'function')
400
+ return entry.options({ route, navigation: handle });
349
401
  return entry.options ?? {};
350
402
  }
351
403
 
@@ -354,7 +406,10 @@
354
406
  for (const route of state.routes) {
355
407
  const entry = registry.get(route.name);
356
408
  if (entry === undefined) continue;
357
- map[route.key] = { options: resolveDrawerScreenOptions(entry, route), navigation: handle };
409
+ map[route.key] = {
410
+ options: resolveDrawerScreenOptions(entry, route),
411
+ navigation: handle,
412
+ };
358
413
  }
359
414
  return map;
360
415
  });
@@ -385,11 +440,14 @@
385
440
 
386
441
  // renderDrawer emits its slots as root children IN `drawerChildOrder`'s order, so the two zip
387
442
  // together - the same index-pairing Vue's own render loop does.
388
- const slotDescriptors = $derived.by<Partial<Record<IDrawerSlot, IDescriptor>>>(() => {
443
+ const slotDescriptors = $derived.by<
444
+ Partial<Record<IDrawerSlot, IDescriptor>>
445
+ >(() => {
389
446
  const map: Partial<Record<IDrawerSlot, IDescriptor>> = {};
390
447
  order.forEach((slot, index) => {
391
448
  const descriptor = root.children[index];
392
- if (typeof descriptor !== 'string' && descriptor !== undefined) map[slot] = descriptor;
449
+ if (typeof descriptor !== 'string' && descriptor !== undefined)
450
+ map[slot] = descriptor;
393
451
  });
394
452
  return map;
395
453
  });
@@ -400,7 +458,87 @@
400
458
  });
401
459
  </script>
402
460
 
403
- {#snippet screenContent()}{#if focusedScreen !== undefined}{@const FocusedComponent = focusedScreen.component}<NavigationScope value={focusedScreen.scope}><FocusedComponent /></NavigationScope>{/if}{/snippet}{#snippet contentSlot()}{@const descriptor = slotDescriptors.content}{#if descriptor !== undefined}{#if contentStyle !== undefined}<Animated.View {...descriptor.props} style={[descriptor.props.style, contentStyle]}>{@render screenContent()}</Animated.View>{:else}<symbiote-view p={descriptor.props}>{@render screenContent()}</symbiote-view>{/if}{/if}{/snippet}{#snippet overlaySlot()}{@const descriptor = slotDescriptors.overlay}{#if descriptor !== undefined}{#if overlayStyle !== undefined}<Animated.View {...descriptor.props} style={[descriptor.props.style, overlayStyle]} />{:else}<symbiote-view p={descriptor.props} />{/if}{/if}{/snippet}{#snippet panelSlot()}{@const descriptor = slotDescriptors.panel}{#if descriptor !== undefined}{#if panelStyle !== undefined}<Animated.View {...descriptor.props} style={[descriptor.props.style, panelStyle]}>{@render drawerContent?.({ state, descriptors, navigation: handle })}</Animated.View>{:else}<symbiote-view p={descriptor.props}>{@render drawerContent?.({ state, descriptors, navigation: handle })}</symbiote-view>{/if}{/if}{/snippet}<symbiote-view p={rootProps}><symbiote-text p={SCREEN_REGISTRY_HOST_PROPS}>{@render children?.()}</symbiote-text>{#each order as slot (slot)}{#if slot === 'content'}{@render contentSlot()}{:else if slot === 'overlay'}{@render overlaySlot()}{:else}{@render panelSlot()}{/if}{/each}</symbiote-view>
461
+ {#snippet screenContent()}
462
+ {#if focusedScreen !== undefined}
463
+ {@const FocusedComponent = focusedScreen.component}
464
+ <NavigationScope value={focusedScreen.scope}>
465
+ <FocusedComponent />
466
+ </NavigationScope>
467
+ {/if}
468
+ {/snippet}
469
+
470
+ {#snippet contentSlot()}
471
+ {@const descriptor = slotDescriptors.content}
472
+ {#if descriptor !== undefined}
473
+ {#if contentStyle !== undefined}
474
+ <Animated.View
475
+ {...descriptor.props}
476
+ style={[descriptor.props.style, contentStyle]}
477
+ >
478
+ {@render screenContent()}
479
+ </Animated.View>
480
+ {:else}
481
+ <symbiote-view p={descriptor.props}>
482
+ {@render screenContent()}
483
+ </symbiote-view>
484
+ {/if}
485
+ {/if}
486
+ {/snippet}
487
+
488
+ {#snippet overlaySlot()}
489
+ {@const descriptor = slotDescriptors.overlay}
490
+ {#if descriptor !== undefined}
491
+ {#if overlayStyle !== undefined}
492
+ <Animated.View
493
+ {...descriptor.props}
494
+ style={[descriptor.props.style, overlayStyle]}
495
+ />
496
+ {:else}
497
+ <symbiote-view p={descriptor.props} />
498
+ {/if}
499
+ {/if}
500
+ {/snippet}
501
+
502
+ {#snippet panelSlot()}
503
+ {@const descriptor = slotDescriptors.panel}
504
+ {#if descriptor !== undefined}
505
+ {#if panelStyle !== undefined}
506
+ <Animated.View
507
+ {...descriptor.props}
508
+ style={[descriptor.props.style, panelStyle]}
509
+ >
510
+ {@render drawerContent?.({
511
+ state,
512
+ descriptors,
513
+ navigation: handle,
514
+ })}
515
+ </Animated.View>
516
+ {:else}
517
+ <symbiote-view p={descriptor.props}>
518
+ {@render drawerContent?.({
519
+ state,
520
+ descriptors,
521
+ navigation: handle,
522
+ })}
523
+ </symbiote-view>
524
+ {/if}
525
+ {/if}
526
+ {/snippet}
527
+
528
+ <symbiote-view p={rootProps}>
529
+ <symbiote-text p={SCREEN_REGISTRY_HOST_PROPS}>
530
+ {@render children?.()}
531
+ </symbiote-text>
532
+ {#each order as slot (slot)}
533
+ {#if slot === 'content'}
534
+ {@render contentSlot()}
535
+ {:else if slot === 'overlay'}
536
+ {@render overlaySlot()}
537
+ {:else}
538
+ {@render panelSlot()}
539
+ {/if}
540
+ {/each}
541
+ </symbiote-view>
404
542
 
405
543
  <!-- --- Explicit gap list vs the real react-native-gesture-handler + react-native-reanimated
406
544
  @react-navigation/drawer (confirmed against its current docs, mirrored verbatim from the
@@ -5,7 +5,8 @@
5
5
  import { collectScreen } from './screen-registry';
6
6
  import type { IDrawerScreenProps } from './drawer-screen-props';
7
7
 
8
- let { name, component, options, initialParams }: IDrawerScreenProps = $props();
8
+ let { name, component, options, initialParams }: IDrawerScreenProps =
9
+ $props();
9
10
 
10
11
  collectScreen('drawer', {
11
12
  get name(): IDrawerScreenProps['name'] {
@@ -3,10 +3,10 @@ export { Stack } from './stack';
3
3
  export type { INavigatorHandle, IStackProps } from './stack';
4
4
  export { default as Screen } from './screen.svelte';
5
5
  export type { IScreenOptionsArgs, IScreenOptionsResolver, IScreenProps, ISvelteScreenOptions, ISvelteSearchBarOptions, } from './screen-props';
6
- export type { IScreenOptions, IStackAnimation, IStackPresentation } from '../core';
6
+ export type { IScreenOptions, IStackAnimation, IStackPresentation, } from '../core';
7
7
  export { useNavigation, useStackNavigation, useTabNavigation, useDrawerNavigation, useRoute, useIsFocused, useFocusEffect, useNavigationState, } from './runes';
8
8
  export type { INavigationHandle, IStackNavigationHandle, ITabNavigationHandle, IDrawerNavigationHandle, } from './runes';
9
- export type { INavigationScopeValue, IAnyNavigatorHandle } from './navigation-context';
9
+ export type { INavigationScopeValue, IAnyNavigatorHandle, } from './navigation-context';
10
10
  export { useLinkingIntegration } from './linking.svelte';
11
11
  export type { ILinkingConfig, IScreenLinkingConfig } from '../core';
12
12
  export { Tab } from './tabs';
@@ -18,4 +18,4 @@ export { Drawer } from './drawer';
18
18
  export type { IDrawerContentSlotProps, IDrawerNavigatorHandle, IDrawerProps, IDrawerDescriptorMap, } from './drawer';
19
19
  export { default as DrawerScreen } from './drawer-screen.svelte';
20
20
  export type { IDrawerScreenOptionsArgs, IDrawerScreenOptionsResolver, IDrawerScreenProps, } from './drawer-screen-props';
21
- export type { IDrawerOptions, IDrawerScreenOptions, IDrawerType, IDrawerPosition } from '../core';
21
+ export type { IDrawerOptions, IDrawerScreenOptions, IDrawerType, IDrawerPosition, } from '../core';
@@ -3,7 +3,7 @@
3
3
  // views' ViewConfigs (../register, a side-effect import of the codegen specs - never
4
4
  // react-native-screens' own React components), then exposes Stack (with Stack.Screen attached)
5
5
  // and the navigator handle. Mirrors vue/index.ts's barrel shape.
6
- import '../register';
6
+ import '../register.js';
7
7
  export { Stack } from './stack/index.js';
8
8
  export { default as Screen } from './screen.svelte';
9
9
  export { useNavigation, useStackNavigation, useTabNavigation, useDrawerNavigation, useRoute, useIsFocused, useFocusEffect, useNavigationState, } from './runes/index.js';
@@ -12,7 +12,10 @@
12
12
  import { setNavigationScope } from './navigation-context';
13
13
  import type { INavigationScopeValue } from './navigation-context';
14
14
 
15
- let { value, children }: { value: INavigationScopeValue; children?: Snippet } = $props();
15
+ let {
16
+ value,
17
+ children,
18
+ }: { value: INavigationScopeValue; children?: Snippet } = $props();
16
19
 
17
20
  setNavigationScope({
18
21
  get current(): INavigationScopeValue {
@@ -12,7 +12,11 @@ export function useNavigation() {
12
12
  const scope = requireNavigationScope('useNavigation');
13
13
  const handle = $derived.by(() => {
14
14
  const { navigation, emitter, parent } = scope.current;
15
- return { ...navigation, addListener: emitter.addListener, getParent: () => parent?.navigation };
15
+ return {
16
+ ...navigation,
17
+ addListener: emitter.addListener,
18
+ getParent: () => parent?.navigation,
19
+ };
16
20
  });
17
21
  return {
18
22
  get current() {
@@ -48,7 +48,11 @@
48
48
  import { hostProps } from '../attachments';
49
49
  import { getNavigationScope } from '../navigation-context';
50
50
  import { SCREEN_REGISTRY_HOST_PROPS } from '../registry-host';
51
- import { setScreenCollector, toRegistry, withoutScreen } from '../screen-registry';
51
+ import {
52
+ setScreenCollector,
53
+ toRegistry,
54
+ withoutScreen,
55
+ } from '../screen-registry';
52
56
  import type { IRegisteredScreen } from '../screen-registry';
53
57
  import type { IScreenProps, ISvelteScreenOptions } from '../screen-props';
54
58
  import StackScreen from './stack-screen.svelte';
@@ -100,7 +104,11 @@
100
104
  dlog('Stack: no <Stack.Screen> children registered');
101
105
  // Deliberately NOT memoized: markers may still be registering, and the next derivation run
102
106
  // should get a real initial route rather than being stuck on this placeholder.
103
- return createInitialNavigatorState({ key: routeIdPrefix, name: '', params: undefined });
107
+ return createInitialNavigatorState({
108
+ key: routeIdPrefix,
109
+ name: '',
110
+ params: undefined,
111
+ });
104
112
  }
105
113
  seededState = createInitialNavigatorState(
106
114
  createRoute(startRouteName, registry.get(startRouteName)?.initialParams),
@@ -114,7 +122,9 @@
114
122
  // derivation because it is PURE - it hands back the same state reference when nothing changed, so
115
123
  // it writes no state and cannot re-trigger itself; `dispatch` below then persists the pruned
116
124
  // history, since it reduces over this value rather than over `pushedState`.
117
- const state = $derived(reconcileStackRoutes(pushedState ?? seedState(), [...registry.keys()]));
125
+ const state = $derived(
126
+ reconcileStackRoutes(pushedState ?? seedState(), [...registry.keys()]),
127
+ );
118
128
 
119
129
  function dispatch(action: INavigatorAction): void {
120
130
  pushedState = navigatorReducer(state, action);
@@ -185,7 +195,8 @@
185
195
  emitterFor(route.key).emit(NAVIGATION_EVENT_STATE, current);
186
196
  }
187
197
  for (const routeKey of [...emitters.keys()]) {
188
- if (!current.routes.some(route => route.key === routeKey)) emitters.delete(routeKey);
198
+ if (!current.routes.some(route => route.key === routeKey))
199
+ emitters.delete(routeKey);
189
200
  }
190
201
  });
191
202
 
@@ -196,7 +207,8 @@
196
207
  // never removed.
197
208
  const stackProps = resolveStackProps({
198
209
  passthrough: {
199
- [STACK_ON_FINISH_TRANSITIONING]: () => dlog(`Stack: onFinishTransitioning at t=${Date.now()}`),
210
+ [STACK_ON_FINISH_TRANSITIONING]: () =>
211
+ dlog(`Stack: onFinishTransitioning at t=${Date.now()}`),
200
212
  },
201
213
  });
202
214
 
@@ -221,4 +233,29 @@
221
233
  }
222
234
  </script>
223
235
 
224
- <symbiote-view p={STACK_ROOT_PROPS}><symbiote-text p={SCREEN_REGISTRY_HOST_PROPS}>{@render children?.()}</symbiote-text><svelte:element this={RNS_SCREEN_STACK_VIEW_NAME} {@attach hostProps(stackProps)}>{#each state.routes as route, index (route.key)}{@const screenComponent = componentFor(route)}{#if screenComponent !== undefined}<StackScreen {route} {index} routeCount={state.routes.length} options={optionsFor(route)} navigation={handle} emitter={emitterFor(route.key)} parentScope={parentScope?.current} component={screenComponent} onPopRequested={popOne} />{/if}{/each}</svelte:element></symbiote-view>
236
+ <symbiote-view p={STACK_ROOT_PROPS}>
237
+ <symbiote-text p={SCREEN_REGISTRY_HOST_PROPS}>
238
+ {@render children?.()}
239
+ </symbiote-text>
240
+ <svelte:element
241
+ this={RNS_SCREEN_STACK_VIEW_NAME}
242
+ {@attach hostProps(stackProps)}
243
+ >
244
+ {#each state.routes as route, index (route.key)}
245
+ {@const screenComponent = componentFor(route)}
246
+ {#if screenComponent !== undefined}
247
+ <StackScreen
248
+ {route}
249
+ {index}
250
+ routeCount={state.routes.length}
251
+ options={optionsFor(route)}
252
+ navigation={handle}
253
+ emitter={emitterFor(route.key)}
254
+ parentScope={parentScope?.current}
255
+ component={screenComponent}
256
+ onPopRequested={popOne}
257
+ />
258
+ {/if}
259
+ {/each}
260
+ </svelte:element>
261
+ </symbiote-view>
@@ -5,7 +5,9 @@
5
5
  // (CT.WithDefault<boolean, 'true'>) - no ios/android divergence in v1 scope, so a single
6
6
  // constant stands in for the per-platform injection point ISliderPlatform-style adapters use
7
7
  // elsewhere.
8
- const NAVIGATOR_PLATFORM: INavigatorPlatform = { defaultHeaderBackTitleVisible: true };
8
+ const NAVIGATOR_PLATFORM: INavigatorPlatform = {
9
+ defaultHeaderBackTitleVisible: true,
10
+ };
9
11
 
10
12
  // react-native-screens' RNSScreenStackHeaderConfig.mm requires every header child to be an
11
13
  // RNSScreenStackHeaderSubview; `type: 'searchBar'` is how it knows which slot this one fills.
@@ -24,9 +26,9 @@
24
26
  // compiles through Svelte's generic setAttribute path and never the custom-element property-SET
25
27
  // path the object bag depends on - see ../attachments.ts for the full reasoning.
26
28
  //
27
- // The whole per-route tree is packed edge-to-edge with zero whitespace between sibling tags:
28
- // svelte-adapter-dom-shim skill §16, where a stray space would become a real RCTRawText child
29
- // of a react-native-screens view.
29
+ // Whitespace between sibling tags in the per-route tree is inert: the shim drops a
30
+ // whitespace-only text node whose parent takes no raw text, so it never becomes an RCTRawText
31
+ // child of a react-native-screens view (dom-shim/text.ts, svelte-adapter-dom-shim skill §16b).
30
32
  import { Platform, dlog } from '@symbiote-native/engine';
31
33
  import {
32
34
  NAVIGATION_EVENT_BLUR,
@@ -86,13 +88,19 @@
86
88
  [SCREEN_ON_WILL_APPEAR]: () =>
87
89
  dlog(`Stack: route "${route.name}" will appear at t=${Date.now()}`),
88
90
  [SCREEN_ON_APPEAR]: () => {
89
- dlog(`Stack: route "${route.name}" appeared (focus) at t=${Date.now()}`);
91
+ dlog(
92
+ `Stack: route "${route.name}" appeared (focus) at t=${Date.now()}`,
93
+ );
90
94
  emitter.emit(NAVIGATION_EVENT_FOCUS);
91
95
  },
92
96
  [SCREEN_ON_WILL_DISAPPEAR]: () =>
93
- dlog(`Stack: route "${route.name}" will disappear at t=${Date.now()}`),
97
+ dlog(
98
+ `Stack: route "${route.name}" will disappear at t=${Date.now()}`,
99
+ ),
94
100
  [SCREEN_ON_DISAPPEAR]: () => {
95
- dlog(`Stack: route "${route.name}" disappeared (blur) at t=${Date.now()}`);
101
+ dlog(
102
+ `Stack: route "${route.name}" disappeared (blur) at t=${Date.now()}`,
103
+ );
96
104
  emitter.emit(NAVIGATION_EVENT_BLUR);
97
105
  },
98
106
  },
@@ -131,7 +139,9 @@
131
139
  // controller to attach to, so the header silently never renders. activityState mirrors the
132
140
  // outer screen's own value - RNSScreen.mm treats an unset/inactive nested screen as not yet
133
141
  // pushed, leaving it parked at its pre-push transition position.
134
- const innerStackProps = $derived<Record<string, unknown>>({ style: plan.innerStackStyle });
142
+ const innerStackProps = $derived<Record<string, unknown>>({
143
+ style: plan.innerStackStyle,
144
+ });
135
145
  const innerScreenProps = $derived<Record<string, unknown>>({
136
146
  style: plan.innerScreenStyle,
137
147
  activityState: plan.activityState,
@@ -145,4 +155,51 @@
145
155
  });
146
156
  </script>
147
157
 
148
- {#snippet chrome()}<svelte:element this={RNS_SCREEN_STACK_HEADER_CONFIG_VIEW_NAME} {@attach hostProps(plan.headerConfig.props)}>{#if plan.searchBarProps !== undefined}<svelte:element this={RNS_SCREEN_STACK_HEADER_SUBVIEW_VIEW_NAME} {@attach hostProps(HEADER_SUBVIEW_PROPS)}><svelte:element this={RNS_SEARCH_BAR_VIEW_NAME} {@attach hostProps(plan.searchBarProps)} {@attach searchBarRef(searchBarOptions?.ref)}></svelte:element></svelte:element>{/if}</svelte:element><svelte:element this={RNS_SCREEN_CONTENT_WRAPPER_VIEW_NAME} {@attach hostProps(plan.contentWrapperProps)}><NavigationScope value={scopeValue}><ScreenComponent /></NavigationScope></svelte:element>{/snippet}<svelte:element this={plan.screenViewName} {@attach hostProps(plan.screenProps)}>{#if plan.inModal}<svelte:element this={RNS_SCREEN_STACK_VIEW_NAME} {@attach hostProps(innerStackProps)}><svelte:element this={RNS_SCREEN_VIEW_NAME} {@attach hostProps(innerScreenProps)}>{@render chrome()}</svelte:element></svelte:element>{:else}{@render chrome()}{/if}</svelte:element>
158
+ {#snippet chrome()}
159
+ <svelte:element
160
+ this={RNS_SCREEN_STACK_HEADER_CONFIG_VIEW_NAME}
161
+ {@attach hostProps(plan.headerConfig.props)}
162
+ >
163
+ {#if plan.searchBarProps !== undefined}
164
+ <svelte:element
165
+ this={RNS_SCREEN_STACK_HEADER_SUBVIEW_VIEW_NAME}
166
+ {@attach hostProps(HEADER_SUBVIEW_PROPS)}
167
+ >
168
+ <svelte:element
169
+ this={RNS_SEARCH_BAR_VIEW_NAME}
170
+ {@attach hostProps(plan.searchBarProps)}
171
+ {@attach searchBarRef(searchBarOptions?.ref)}
172
+ />
173
+ </svelte:element>
174
+ {/if}
175
+ </svelte:element>
176
+ <svelte:element
177
+ this={RNS_SCREEN_CONTENT_WRAPPER_VIEW_NAME}
178
+ {@attach hostProps(plan.contentWrapperProps)}
179
+ >
180
+ <NavigationScope value={scopeValue}>
181
+ <ScreenComponent />
182
+ </NavigationScope>
183
+ </svelte:element>
184
+ {/snippet}
185
+
186
+ <svelte:element
187
+ this={plan.screenViewName}
188
+ {@attach hostProps(plan.screenProps)}
189
+ >
190
+ {#if plan.inModal}
191
+ <svelte:element
192
+ this={RNS_SCREEN_STACK_VIEW_NAME}
193
+ {@attach hostProps(innerStackProps)}
194
+ >
195
+ <svelte:element
196
+ this={RNS_SCREEN_VIEW_NAME}
197
+ {@attach hostProps(innerScreenProps)}
198
+ >
199
+ {@render chrome()}
200
+ </svelte:element>
201
+ </svelte:element>
202
+ {:else}
203
+ {@render chrome()}
204
+ {/if}
205
+ </svelte:element>
@@ -48,7 +48,11 @@
48
48
  import type { INavigationScopeValue } from '../navigation-context';
49
49
  import NavigationScope from '../navigation-scope.svelte';
50
50
  import { SCREEN_REGISTRY_HOST_PROPS } from '../registry-host';
51
- import { setScreenCollector, toRegistry, withoutScreen } from '../screen-registry';
51
+ import {
52
+ setScreenCollector,
53
+ toRegistry,
54
+ withoutScreen,
55
+ } from '../screen-registry';
52
56
  import type { IRegisteredScreen } from '../screen-registry';
53
57
  import type { ITabScreenProps } from '../tab-screen-props';
54
58
  import type { ITabProps } from './tab-props';
@@ -94,7 +98,8 @@
94
98
  let dispatchedState = $state.raw<ITabRouterState | null>(null);
95
99
 
96
100
  const state = $derived.by<ITabRouterState>(() => {
97
- if (registeredRoutes.length === 0) dlog('Tab: no <Tab.Screen> children registered');
101
+ if (registeredRoutes.length === 0)
102
+ dlog('Tab: no <Tab.Screen> children registered');
98
103
  const dispatched = dispatchedState;
99
104
  return dispatched === null
100
105
  ? createInitialTabState(registeredRoutes, initialRouteName)
@@ -207,29 +212,33 @@
207
212
  );
208
213
 
209
214
  const tabBar = $derived.by<IDescriptor>(() =>
210
- renderTabBar({ items, style: focusedOptions?.tabBarStyle, passthrough: {} }),
215
+ renderTabBar({
216
+ items,
217
+ style: focusedOptions?.tabBarStyle,
218
+ passthrough: {},
219
+ }),
211
220
  );
212
221
 
213
222
  // Only the focused route's screen is ever mounted (unlike Stack, which keeps every pushed route
214
223
  // alive), so a fresh NavigationScope per focus change is sufficient - the previous screen's
215
224
  // whole subtree (and any listeners it registered) is torn down by an ordinary unmount when
216
225
  // focus moves on.
217
- const focusedScreen = $derived.by<{ scope: INavigationScopeValue; component: Component } | undefined>(
218
- () => {
219
- if (focusedRoute === undefined) return undefined;
220
- const entry = registry.get(focusedRoute.name);
221
- if (entry === undefined) return undefined;
222
- return {
223
- component: entry.component,
224
- scope: {
225
- route: focusedRoute,
226
- navigation: handle,
227
- emitter: emitterFor(focusedRoute.key),
228
- parent: parentScope?.current,
229
- },
230
- };
231
- },
232
- );
226
+ const focusedScreen = $derived.by<
227
+ { scope: INavigationScopeValue; component: Component } | undefined
228
+ >(() => {
229
+ if (focusedRoute === undefined) return undefined;
230
+ const entry = registry.get(focusedRoute.name);
231
+ if (entry === undefined) return undefined;
232
+ return {
233
+ component: entry.component,
234
+ scope: {
235
+ route: focusedRoute,
236
+ navigation: handle,
237
+ emitter: emitterFor(focusedRoute.key),
238
+ parent: parentScope?.current,
239
+ },
240
+ };
241
+ });
233
242
 
234
243
  // The bar's ROOT stays a literal template tag (so `bind:this` has a statically known tag) and
235
244
  // only its children go through the Descriptor bridge - the uniform shape every Svelte component
@@ -244,4 +253,17 @@
244
253
  });
245
254
  </script>
246
255
 
247
- <symbiote-view p={TAB_ROOT_PROPS}><symbiote-text p={SCREEN_REGISTRY_HOST_PROPS}>{@render children?.()}</symbiote-text><symbiote-view p={TAB_CONTENT_PROPS}>{#if focusedScreen !== undefined}{@const FocusedComponent = focusedScreen.component}<NavigationScope value={focusedScreen.scope}><FocusedComponent /></NavigationScope>{/if}</symbiote-view><symbiote-view p={tabBar.props} bind:this={tabBarHost}></symbiote-view></symbiote-view>
256
+ <symbiote-view p={TAB_ROOT_PROPS}>
257
+ <symbiote-text p={SCREEN_REGISTRY_HOST_PROPS}>
258
+ {@render children?.()}
259
+ </symbiote-text>
260
+ <symbiote-view p={TAB_CONTENT_PROPS}>
261
+ {#if focusedScreen !== undefined}
262
+ {@const FocusedComponent = focusedScreen.component}
263
+ <NavigationScope value={focusedScreen.scope}>
264
+ <FocusedComponent />
265
+ </NavigationScope>
266
+ {/if}
267
+ </symbiote-view>
268
+ <symbiote-view p={tabBar.props} bind:this={tabBarHost} />
269
+ </symbiote-view>