@symbiote-native/navigation 2.0.3 → 2.2.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 (320) hide show
  1. package/README.md +42 -12
  2. package/build/angular/drawer/index.js +29 -13
  3. package/build/angular/index.d.ts +4 -4
  4. package/build/angular/injectors/inject-navigation.js +1 -1
  5. package/build/angular/navigation-scope.directive.js +1 -1
  6. package/build/angular/search-bar-ref.directive.js +1 -1
  7. package/build/angular/stack/index.d.ts +2 -0
  8. package/build/angular/stack/index.js +43 -9
  9. package/build/angular/tabs/index.d.ts +1 -1
  10. package/build/angular/tabs/index.js +40 -13
  11. package/build/core/drawer-options/index.js +19 -5
  12. package/build/core/drawer-router-state/index.js +8 -2
  13. package/build/core/guards.js +3 -1
  14. package/build/core/header-bar-buttons.js +14 -4
  15. package/build/core/index.d.ts +6 -5
  16. package/build/core/index.js +7 -3
  17. package/build/core/navigator-state/index.js +12 -4
  18. package/build/core/render-drawer.js +4 -1
  19. package/build/core/render-stack.js +13 -4
  20. package/build/core/screen-options.js +1 -1
  21. package/build/core/search-bar-commands.js +1 -1
  22. package/build/core/stack-router-state/index.d.ts +2 -0
  23. package/build/core/stack-router-state/index.js +44 -0
  24. package/build/core/state-persistence/index.js +6 -2
  25. package/build/core/tab-router-state/index.d.ts +1 -0
  26. package/build/core/tab-router-state/index.js +27 -2
  27. package/build/react/drawer/index.js +59 -26
  28. package/build/react/index.d.ts +7 -7
  29. package/build/react/index.js +2 -2
  30. package/build/react/stack/index.js +47 -10
  31. package/build/react/tabs/index.js +36 -12
  32. package/build/solid/drawer/index.d.ts +22 -0
  33. package/build/solid/drawer/index.js +394 -0
  34. package/build/solid/drawer-screen-props.d.ts +13 -0
  35. package/build/solid/drawer-screen-props.js +2 -0
  36. package/build/solid/host.d.ts +2 -0
  37. package/build/solid/host.js +23 -0
  38. package/build/solid/index.d.ts +19 -0
  39. package/build/solid/index.js +24 -0
  40. package/build/solid/linking.d.ts +3 -0
  41. package/build/solid/linking.js +55 -0
  42. package/build/solid/navigation-context.d.ts +13 -0
  43. package/build/solid/navigation-context.js +37 -0
  44. package/build/solid/primitives/create-focus-effect.d.ts +1 -0
  45. package/build/solid/primitives/create-focus-effect.js +30 -0
  46. package/build/solid/primitives/create-is-focused.d.ts +2 -0
  47. package/build/solid/primitives/create-is-focused.js +31 -0
  48. package/build/solid/primitives/create-navigation-state.d.ts +3 -0
  49. package/build/solid/primitives/create-navigation-state.js +30 -0
  50. package/build/solid/primitives/index.d.ts +12 -0
  51. package/build/solid/primitives/index.js +8 -0
  52. package/build/solid/primitives/use-drawer-navigation.d.ts +5 -0
  53. package/build/solid/primitives/use-drawer-navigation.js +15 -0
  54. package/build/solid/primitives/use-navigation.d.ts +8 -0
  55. package/build/solid/primitives/use-navigation.js +23 -0
  56. package/build/solid/primitives/use-route.d.ts +3 -0
  57. package/build/solid/primitives/use-route.js +14 -0
  58. package/build/solid/primitives/use-stack-navigation.d.ts +5 -0
  59. package/build/solid/primitives/use-stack-navigation.js +19 -0
  60. package/build/solid/primitives/use-tab-navigation.d.ts +5 -0
  61. package/build/solid/primitives/use-tab-navigation.js +15 -0
  62. package/build/solid/screen-props.d.ts +19 -0
  63. package/build/solid/screen-props.js +9 -0
  64. package/build/solid/screen-registry.d.ts +31 -0
  65. package/build/solid/screen-registry.js +86 -0
  66. package/build/solid/screen.d.ts +6 -0
  67. package/build/solid/screen.js +69 -0
  68. package/build/solid/stack/index.d.ts +15 -0
  69. package/build/solid/stack/index.js +348 -0
  70. package/build/solid/tab-screen-props.d.ts +13 -0
  71. package/build/solid/tab-screen-props.js +3 -0
  72. package/build/solid/tabs/index.d.ts +14 -0
  73. package/build/solid/tabs/index.js +228 -0
  74. package/build/svelte/attachments.d.ts +5 -0
  75. package/build/svelte/attachments.js +61 -0
  76. package/build/svelte/descriptor-subtree.d.ts +3 -0
  77. package/build/svelte/descriptor-subtree.js +39 -0
  78. package/build/svelte/drawer/drawer-props.d.ts +14 -0
  79. package/build/svelte/drawer/drawer-props.js +3 -0
  80. package/build/svelte/drawer/index.d.ts +10 -0
  81. package/build/svelte/drawer/index.js +6 -0
  82. package/build/svelte/drawer/index.svelte +559 -0
  83. package/build/svelte/drawer/index.svelte.d.ts +10 -0
  84. package/build/svelte/drawer-screen-props.d.ts +13 -0
  85. package/build/svelte/drawer-screen-props.js +4 -0
  86. package/build/svelte/drawer-screen.svelte +25 -0
  87. package/build/svelte/drawer-screen.svelte.d.ts +4 -0
  88. package/build/svelte/index.d.ts +21 -0
  89. package/build/svelte/index.js +20 -0
  90. package/build/svelte/linking.svelte.d.ts +2 -0
  91. package/build/svelte/linking.svelte.js +55 -0
  92. package/build/svelte/navigation-context.d.ts +14 -0
  93. package/build/svelte/navigation-context.js +44 -0
  94. package/build/svelte/navigation-scope.svelte +27 -0
  95. package/build/svelte/navigation-scope.svelte.d.ts +9 -0
  96. package/build/svelte/registry-host.d.ts +1 -0
  97. package/build/svelte/registry-host.js +26 -0
  98. package/build/svelte/runes/index.d.ts +12 -0
  99. package/build/svelte/runes/index.js +12 -0
  100. package/build/svelte/runes/use-drawer-navigation.svelte.d.ts +6 -0
  101. package/build/svelte/runes/use-drawer-navigation.svelte.js +19 -0
  102. package/build/svelte/runes/use-focus-effect.svelte.d.ts +1 -0
  103. package/build/svelte/runes/use-focus-effect.svelte.js +31 -0
  104. package/build/svelte/runes/use-is-focused.svelte.d.ts +3 -0
  105. package/build/svelte/runes/use-is-focused.svelte.js +34 -0
  106. package/build/svelte/runes/use-navigation-state.svelte.d.ts +4 -0
  107. package/build/svelte/runes/use-navigation-state.svelte.js +39 -0
  108. package/build/svelte/runes/use-navigation.svelte.d.ts +9 -0
  109. package/build/svelte/runes/use-navigation.svelte.js +26 -0
  110. package/build/svelte/runes/use-route.svelte.d.ts +4 -0
  111. package/build/svelte/runes/use-route.svelte.js +12 -0
  112. package/build/svelte/runes/use-stack-navigation.svelte.d.ts +6 -0
  113. package/build/svelte/runes/use-stack-navigation.svelte.js +22 -0
  114. package/build/svelte/runes/use-tab-navigation.svelte.d.ts +6 -0
  115. package/build/svelte/runes/use-tab-navigation.svelte.js +19 -0
  116. package/build/svelte/screen-props.d.ts +21 -0
  117. package/build/svelte/screen-props.js +6 -0
  118. package/build/svelte/screen-registry.d.ts +17 -0
  119. package/build/svelte/screen-registry.js +57 -0
  120. package/build/svelte/screen.svelte +28 -0
  121. package/build/svelte/screen.svelte.d.ts +4 -0
  122. package/build/svelte/stack/index.d.ts +14 -0
  123. package/build/svelte/stack/index.js +7 -0
  124. package/build/svelte/stack/index.svelte +261 -0
  125. package/build/svelte/stack/index.svelte.d.ts +15 -0
  126. package/build/svelte/stack/stack-props.d.ts +20 -0
  127. package/build/svelte/stack/stack-props.js +4 -0
  128. package/build/svelte/stack/stack-screen.svelte +205 -0
  129. package/build/svelte/stack/stack-screen.svelte.d.ts +4 -0
  130. package/build/svelte/tab-screen-props.d.ts +13 -0
  131. package/build/svelte/tab-screen-props.js +4 -0
  132. package/build/svelte/tab-screen.svelte +26 -0
  133. package/build/svelte/tab-screen.svelte.d.ts +4 -0
  134. package/build/svelte/tabs/index.d.ts +8 -0
  135. package/build/svelte/tabs/index.js +6 -0
  136. package/build/svelte/tabs/index.svelte +269 -0
  137. package/build/svelte/tabs/index.svelte.d.ts +8 -0
  138. package/build/svelte/tabs/tab-props.d.ts +7 -0
  139. package/build/svelte/tabs/tab-props.js +3 -0
  140. package/build/vue/composables/use-navigation.js +5 -1
  141. package/build/vue/drawer/index.js +36 -13
  142. package/build/vue/index.d.ts +3 -3
  143. package/build/vue/navigation-context.js +1 -1
  144. package/build/vue/stack/index.js +43 -18
  145. package/build/vue/tabs/index.js +65 -39
  146. package/build-ngc/angular/drawer/index.js +40 -18
  147. package/build-ngc/angular/drawer/index.js.map +1 -1
  148. package/build-ngc/angular/drawer-screen.directive.js +3 -3
  149. package/build-ngc/angular/index.d.ts +4 -4
  150. package/build-ngc/angular/index.js.map +1 -1
  151. package/build-ngc/angular/injectors/inject-focus-effect.js.map +1 -1
  152. package/build-ngc/angular/injectors/inject-is-focused.js.map +1 -1
  153. package/build-ngc/angular/injectors/inject-navigation-state.js.map +1 -1
  154. package/build-ngc/angular/injectors/inject-navigation.js +1 -1
  155. package/build-ngc/angular/injectors/inject-navigation.js.map +1 -1
  156. package/build-ngc/angular/linking.js.map +1 -1
  157. package/build-ngc/angular/navigation-context.service.js +3 -3
  158. package/build-ngc/angular/navigation-context.service.js.map +1 -1
  159. package/build-ngc/angular/navigation-scope.directive.js +4 -4
  160. package/build-ngc/angular/navigation-scope.directive.js.map +1 -1
  161. package/build-ngc/angular/screen.directive.js +3 -3
  162. package/build-ngc/angular/screen.directive.js.map +1 -1
  163. package/build-ngc/angular/search-bar-ref.directive.js +4 -4
  164. package/build-ngc/angular/search-bar-ref.directive.js.map +1 -1
  165. package/build-ngc/angular/stack/index.d.ts +2 -0
  166. package/build-ngc/angular/stack/index.js +52 -14
  167. package/build-ngc/angular/stack/index.js.map +1 -1
  168. package/build-ngc/angular/tab-screen.directive.js +3 -3
  169. package/build-ngc/angular/tab-screen.directive.js.map +1 -1
  170. package/build-ngc/angular/tabs/index.d.ts +1 -1
  171. package/build-ngc/angular/tabs/index.js +43 -16
  172. package/build-ngc/angular/tabs/index.js.map +1 -1
  173. package/build-ngc/core/constants.js.map +1 -1
  174. package/build-ngc/core/drawer-options/index.js +19 -5
  175. package/build-ngc/core/drawer-options/index.js.map +1 -1
  176. package/build-ngc/core/drawer-router-state/index.js +8 -2
  177. package/build-ngc/core/drawer-router-state/index.js.map +1 -1
  178. package/build-ngc/core/guards.js +3 -1
  179. package/build-ngc/core/guards.js.map +1 -1
  180. package/build-ngc/core/header-bar-buttons.js +14 -4
  181. package/build-ngc/core/header-bar-buttons.js.map +1 -1
  182. package/build-ngc/core/index.d.ts +6 -5
  183. package/build-ngc/core/index.js +7 -3
  184. package/build-ngc/core/index.js.map +1 -1
  185. package/build-ngc/core/linking-config/index.js.map +1 -1
  186. package/build-ngc/core/navigation-events/index.js.map +1 -1
  187. package/build-ngc/core/navigator-handles/index.js.map +1 -1
  188. package/build-ngc/core/navigator-state/index.js +12 -4
  189. package/build-ngc/core/navigator-state/index.js.map +1 -1
  190. package/build-ngc/core/render-drawer.js +4 -1
  191. package/build-ngc/core/render-drawer.js.map +1 -1
  192. package/build-ngc/core/render-stack.js +13 -4
  193. package/build-ngc/core/render-stack.js.map +1 -1
  194. package/build-ngc/core/render-tabs.js.map +1 -1
  195. package/build-ngc/core/screen-options.js +1 -1
  196. package/build-ngc/core/screen-options.js.map +1 -1
  197. package/build-ngc/core/search-bar-commands.js +1 -1
  198. package/build-ngc/core/search-bar-commands.js.map +1 -1
  199. package/build-ngc/core/stack-router-state/index.d.ts +2 -0
  200. package/build-ngc/core/stack-router-state/index.js +45 -0
  201. package/build-ngc/core/stack-router-state/index.js.map +1 -0
  202. package/build-ngc/core/state-persistence/index.js +6 -2
  203. package/build-ngc/core/state-persistence/index.js.map +1 -1
  204. package/build-ngc/core/tab-router-state/index.d.ts +1 -0
  205. package/build-ngc/core/tab-router-state/index.js +27 -2
  206. package/build-ngc/core/tab-router-state/index.js.map +1 -1
  207. package/package.json +44 -16
  208. package/src/angular/drawer/index.ts +75 -29
  209. package/src/angular/index.ts +20 -4
  210. package/src/angular/injectors/inject-focus-effect.ts +8 -2
  211. package/src/angular/injectors/inject-is-focused.ts +6 -4
  212. package/src/angular/injectors/inject-navigation-state.ts +7 -4
  213. package/src/angular/injectors/inject-navigation.ts +12 -3
  214. package/src/angular/linking.ts +4 -1
  215. package/src/angular/navigation-context.service.ts +5 -2
  216. package/src/angular/navigation-scope.directive.ts +6 -2
  217. package/src/angular/screen.directive.ts +13 -3
  218. package/src/angular/search-bar-ref.directive.ts +10 -2
  219. package/src/angular/stack/index.ts +91 -24
  220. package/src/angular/tab-screen.directive.ts +3 -1
  221. package/src/angular/tabs/index.ts +54 -16
  222. package/src/core/constants.ts +6 -3
  223. package/src/core/drawer-options/index.ts +40 -13
  224. package/src/core/drawer-router-state/index.ts +11 -3
  225. package/src/core/guards.ts +3 -1
  226. package/src/core/header-bar-buttons.ts +41 -12
  227. package/src/core/index.ts +29 -5
  228. package/src/core/linking-config/index.ts +31 -10
  229. package/src/core/navigation-events/index.ts +8 -2
  230. package/src/core/navigator-handles/index.ts +8 -3
  231. package/src/core/navigator-props.ts +13 -4
  232. package/src/core/navigator-state/index.ts +24 -7
  233. package/src/core/render-drawer.ts +24 -9
  234. package/src/core/render-stack.ts +52 -13
  235. package/src/core/render-tabs.ts +24 -6
  236. package/src/core/screen-options.ts +15 -5
  237. package/src/core/search-bar-commands.ts +12 -3
  238. package/src/core/stack-router-state/index.ts +52 -0
  239. package/src/core/state-persistence/index.ts +13 -3
  240. package/src/core/tab-router-state/index.ts +35 -3
  241. package/src/react/drawer/index.ts +409 -330
  242. package/src/react/drawer-screen.ts +8 -2
  243. package/src/react/hooks/use-focus-effect.ts +8 -2
  244. package/src/react/hooks/use-is-focused.ts +6 -2
  245. package/src/react/hooks/use-navigation.ts +8 -2
  246. package/src/react/index.ts +37 -7
  247. package/src/react/linking.ts +4 -1
  248. package/src/react/navigation-context.ts +6 -2
  249. package/src/react/screen.ts +12 -3
  250. package/src/react/stack/index.ts +297 -220
  251. package/src/react/tab-screen.ts +3 -1
  252. package/src/react/tabs/index.ts +202 -139
  253. package/src/solid/drawer/index.ts +570 -0
  254. package/src/solid/drawer-screen-props.ts +24 -0
  255. package/src/solid/host.ts +29 -0
  256. package/src/solid/index.ts +87 -0
  257. package/src/solid/linking.ts +74 -0
  258. package/src/solid/navigation-context.ts +56 -0
  259. package/src/solid/primitives/create-focus-effect.ts +41 -0
  260. package/src/solid/primitives/create-is-focused.ts +41 -0
  261. package/src/solid/primitives/create-navigation-state.ts +44 -0
  262. package/src/solid/primitives/index.ts +12 -0
  263. package/src/solid/primitives/use-drawer-navigation.ts +25 -0
  264. package/src/solid/primitives/use-navigation.ts +44 -0
  265. package/src/solid/primitives/use-route.ts +18 -0
  266. package/src/solid/primitives/use-stack-navigation.ts +29 -0
  267. package/src/solid/primitives/use-tab-navigation.ts +25 -0
  268. package/src/solid/screen-props.ts +51 -0
  269. package/src/solid/screen-registry.ts +159 -0
  270. package/src/solid/screen.ts +80 -0
  271. package/src/solid/stack/index.ts +528 -0
  272. package/src/solid/tab-screen-props.ts +21 -0
  273. package/src/solid/tabs/index.ts +327 -0
  274. package/src/svelte/attachments.ts +70 -0
  275. package/src/svelte/descriptor-subtree.ts +51 -0
  276. package/src/svelte/drawer/drawer-props.ts +28 -0
  277. package/src/svelte/drawer/index.svelte +559 -0
  278. package/src/svelte/drawer/index.ts +10 -0
  279. package/src/svelte/drawer-screen-props.ts +26 -0
  280. package/src/svelte/drawer-screen.svelte +25 -0
  281. package/src/svelte/fabric-tree.test-helper.ts +95 -0
  282. package/src/svelte/index.ts +83 -0
  283. package/src/svelte/linking.svelte.ts +72 -0
  284. package/src/svelte/navigation-context.ts +62 -0
  285. package/src/svelte/navigation-scope.svelte +27 -0
  286. package/src/svelte/registry-host.ts +26 -0
  287. package/src/svelte/runes/index.ts +17 -0
  288. package/src/svelte/runes/use-drawer-navigation.svelte.ts +31 -0
  289. package/src/svelte/runes/use-focus-effect.svelte.ts +41 -0
  290. package/src/svelte/runes/use-is-focused.svelte.ts +38 -0
  291. package/src/svelte/runes/use-navigation-state.svelte.ts +48 -0
  292. package/src/svelte/runes/use-navigation.svelte.ts +49 -0
  293. package/src/svelte/runes/use-route.svelte.ts +16 -0
  294. package/src/svelte/runes/use-stack-navigation.svelte.ts +34 -0
  295. package/src/svelte/runes/use-tab-navigation.svelte.ts +29 -0
  296. package/src/svelte/screen-props.ts +50 -0
  297. package/src/svelte/screen-registry.ts +98 -0
  298. package/src/svelte/screen.svelte +28 -0
  299. package/src/svelte/stack/index.svelte +261 -0
  300. package/src/svelte/stack/index.ts +11 -0
  301. package/src/svelte/stack/stack-props.ts +31 -0
  302. package/src/svelte/stack/stack-screen.svelte +205 -0
  303. package/src/svelte/svelte-ambient.d.ts +6 -0
  304. package/src/svelte/svelte-compile.test-helper.ts +147 -0
  305. package/src/svelte/tab-screen-props.ts +22 -0
  306. package/src/svelte/tab-screen.svelte +26 -0
  307. package/src/svelte/tabs/index.svelte +269 -0
  308. package/src/svelte/tabs/index.ts +10 -0
  309. package/src/svelte/tabs/tab-props.ts +13 -0
  310. package/src/vue/composables/use-navigation-state.ts +7 -4
  311. package/src/vue/composables/use-navigation.ts +13 -3
  312. package/src/vue/drawer/index.ts +128 -41
  313. package/src/vue/drawer-screen.ts +12 -5
  314. package/src/vue/index.ts +15 -3
  315. package/src/vue/linking.ts +7 -2
  316. package/src/vue/navigation-context.ts +17 -5
  317. package/src/vue/screen.ts +7 -2
  318. package/src/vue/stack/index.ts +108 -43
  319. package/src/vue/tab-screen.ts +3 -1
  320. package/src/vue/tabs/index.ts +109 -68
@@ -9,7 +9,12 @@
9
9
 
10
10
  import { el, txt } from '@symbiote-native/components';
11
11
  import type { IDescriptor } from '@symbiote-native/components';
12
- import type { IColorValue, IViewStyle, ITextStyle, IStyleProp } from '@symbiote-native/engine';
12
+ import type {
13
+ IColorValue,
14
+ IViewStyle,
15
+ ITextStyle,
16
+ IStyleProp,
17
+ } from '@symbiote-native/engine';
13
18
  import type { ITabBarIcon } from './tab-options';
14
19
 
15
20
  // react-navigation's own bottom-tabs default to the surrounding theme's primary/text colors;
@@ -96,14 +101,19 @@ function resolveTintColor(item: ITabBarItemView): IColorValue {
96
101
  // for a vector-icon-font label); an IDescriptor icon (an <Image>/vector-icon element the adapter
97
102
  // already resolved) is spliced in verbatim, exactly like renderHeaderConfig treats a pre-built
98
103
  // Descriptor child.
99
- function renderIcon(icon: ITabBarIcon | undefined, color: IColorValue): IDescriptor | undefined {
104
+ function renderIcon(
105
+ icon: ITabBarIcon | undefined,
106
+ color: IColorValue,
107
+ ): IDescriptor | undefined {
100
108
  if (icon === undefined) return undefined;
101
109
  if (typeof icon === 'string')
102
110
  return txt({ style: { color, fontSize: TAB_ICON_FONT_SIZE } }, [icon]);
103
111
  return icon;
104
112
  }
105
113
 
106
- function renderBadge(badge: string | number | undefined): IDescriptor | undefined {
114
+ function renderBadge(
115
+ badge: string | number | undefined,
116
+ ): IDescriptor | undefined {
107
117
  if (badge === undefined) return undefined;
108
118
  return el('symbiote-view', { style: BADGE_STYLE }, [
109
119
  txt({ style: BADGE_TEXT_STYLE }, [String(badge)]),
@@ -121,8 +131,12 @@ export function renderTabBarItem(item: ITabBarItemView): IDescriptor {
121
131
 
122
132
  const children: IDescriptor[] = [];
123
133
  if (iconChildren.length > 0)
124
- children.push(el('symbiote-view', { style: ICON_WRAPPER_STYLE }, iconChildren));
125
- children.push(txt({ style: { color, fontSize: TAB_LABEL_FONT_SIZE } }, [item.label]));
134
+ children.push(
135
+ el('symbiote-view', { style: ICON_WRAPPER_STYLE }, iconChildren),
136
+ );
137
+ children.push(
138
+ txt({ style: { color, fontSize: TAB_LABEL_FONT_SIZE } }, [item.label]),
139
+ );
126
140
 
127
141
  return el(
128
142
  'symbiote-view',
@@ -134,5 +148,9 @@ export function renderTabBarItem(item: ITabBarItemView): IDescriptor {
134
148
 
135
149
  export function renderTabBar(view: ITabBarViewProps): IDescriptor {
136
150
  const items = view.items.map(renderTabBarItem);
137
- return el('symbiote-view', { ...view.passthrough, style: [TAB_BAR_STYLE, view.style] }, items);
151
+ return el(
152
+ 'symbiote-view',
153
+ { ...view.passthrough, style: [TAB_BAR_STYLE, view.style] },
154
+ items,
155
+ );
138
156
  }
@@ -20,7 +20,10 @@ import type {
20
20
  ISheetInitialDetent,
21
21
  ISheetLargestUndimmedDetent,
22
22
  } from './navigator-props';
23
- import { buildHeaderBarButtonDispatch, prepareHeaderBarButtonItems } from './header-bar-buttons';
23
+ import {
24
+ buildHeaderBarButtonDispatch,
25
+ prepareHeaderBarButtonItems,
26
+ } from './header-bar-buttons';
24
27
 
25
28
  // These sentinels must be kept in sync with react-native-screens' native side - they are RNS's
26
29
  // own compat values for the 'fitToContents'/'large'/'medium'/'all' legacy presets, replicated
@@ -31,7 +34,9 @@ const SHEET_COMPAT_MEDIUM: number[] = [0.5];
31
34
  const SHEET_COMPAT_ALL: number[] = [0.5, 1.0];
32
35
  const SHEET_DIMMED_ALWAYS = -1;
33
36
 
34
- function resolveSheetAllowedDetents(compat: ISheetAllowedDetents | undefined): number[] {
37
+ function resolveSheetAllowedDetents(
38
+ compat: ISheetAllowedDetents | undefined,
39
+ ): number[] {
35
40
  if (compat === undefined) return SHEET_COMPAT_LARGE;
36
41
  if (Array.isArray(compat)) return compat;
37
42
  switch (compat) {
@@ -74,7 +79,9 @@ function resolveSheetInitialDetent(
74
79
  return compat;
75
80
  }
76
81
 
77
- function toOptionalBooleanNativeProp(value: boolean | undefined): IOptionalBooleanNativeProp {
82
+ function toOptionalBooleanNativeProp(
83
+ value: boolean | undefined,
84
+ ): IOptionalBooleanNativeProp {
78
85
  if (value === undefined) return 'undefined';
79
86
  return value ? 'true' : 'false';
80
87
  }
@@ -119,7 +126,9 @@ export function resolveScreenView(
119
126
  options: IScreenOptions | undefined,
120
127
  passthrough: Record<string, unknown> = {},
121
128
  ): IScreenViewProps {
122
- const sheetAllowedDetents = resolveSheetAllowedDetents(options?.sheetAllowedDetents);
129
+ const sheetAllowedDetents = resolveSheetAllowedDetents(
130
+ options?.sheetAllowedDetents,
131
+ );
123
132
  const lastDetentIndex = sheetAllowedDetents.length - 1;
124
133
  return {
125
134
  screenId,
@@ -142,7 +151,8 @@ export function resolveScreenView(
142
151
  sheetExpandsWhenScrolledToEdge: options?.sheetExpandsWhenScrolledToEdge,
143
152
  sheetElevation: options?.sheetElevation,
144
153
  sheetShouldOverflowTopInset: options?.sheetShouldOverflowTopInset,
145
- sheetDefaultResizeAnimationEnabled: options?.sheetDefaultResizeAnimationEnabled,
154
+ sheetDefaultResizeAnimationEnabled:
155
+ options?.sheetDefaultResizeAnimationEnabled,
146
156
  statusBarStyle: options?.statusBarStyle,
147
157
  statusBarHidden: options?.statusBarHidden,
148
158
  statusBarAnimation: options?.statusBarAnimation,
@@ -5,7 +5,11 @@
5
5
  // buildScrollViewHandle exactly (same lazy-getter shape); the adapter supplies the node getter
6
6
  // and its own framework-specific ref field (see react/screen.ts's IReactSearchBarOptions - the
7
7
  // ref itself is per-adapter, same split as IPressableProps).
8
- import { dispatchViewCommand, dlog, type ISymbioteNode } from '@symbiote-native/engine';
8
+ import {
9
+ dispatchViewCommand,
10
+ dlog,
11
+ type ISymbioteNode,
12
+ } from '@symbiote-native/engine';
9
13
 
10
14
  export interface ISearchBarCommands {
11
15
  focus(): void;
@@ -21,7 +25,10 @@ export interface ISearchBarCommands {
21
25
  // stale handle outlived its screen) was the one unlogged gap, silently indistinguishable from
22
26
  // "the command fired but did nothing". Investigation instrumentation (HeaderOptionsScreen
23
27
  // unresponsive-buttons bug); kept behind DEBUG per <keep_logs_gate_behind_DEBUG>, never removed.
24
- function warnIfDetached(command: string, node: ISymbioteNode | null): node is ISymbioteNode {
28
+ function warnIfDetached(
29
+ command: string,
30
+ node: ISymbioteNode | null,
31
+ ): node is ISymbioteNode {
25
32
  if (node !== null) return true;
26
33
  dlog(
27
34
  `SearchBarCommands.${command}: skipped, node is null (ref never attached) at t=${Date.now()}`,
@@ -45,7 +52,9 @@ function makeCommand(
45
52
 
46
53
  // `getNode` is a LAZY getter, read on every call - see buildScrollViewHandle's comment for why
47
54
  // an eager capture would freeze `null`.
48
- export function buildSearchBarHandle(getNode: () => ISymbioteNode | null): ISearchBarCommands {
55
+ export function buildSearchBarHandle(
56
+ getNode: () => ISymbioteNode | null,
57
+ ): ISearchBarCommands {
49
58
  return {
50
59
  focus: makeCommand(getNode, 'focus'),
51
60
  blur: makeCommand(getNode, 'blur'),
@@ -0,0 +1,52 @@
1
+ // StackRouter: the registry-reconciliation half (framework-agnostic, zero render). A Stack's route
2
+ // list is navigation HISTORY, not a projection of the registered `<Stack.Screen>` markers the way a
3
+ // Tab's is (tab-router-state) - it seeds exactly one route and grows only through push/replace. So
4
+ // a marker that unregisters while its route still sits in the history (a marker behind an `{#if}`,
5
+ // a data-driven screen list) leaves behind an entry nothing can render: the route stays, the
6
+ // adapter's componentFor() finds no screen, and the user is parked on a blank RNSScreen with no
7
+ // way to tell what happened. Mirrors @react-navigation/routers' StackRouter.getStateForRouteNames-
8
+ // Change, which filters those routes out of the history and pulls the focused index back into
9
+ // range.
10
+ //
11
+ // Deliberately NOT a navigatorReducer action: this is not something a caller dispatches, it is a
12
+ // reaction to the registry changing underneath an unchanged history, and each adapter observes
13
+ // that change through its own lifecycle. Keeping it a separate pure function lets every adapter
14
+ // wire it its own way without teaching the reducer about a registry it has never seen.
15
+
16
+ import type { INavigatorState } from '../navigator-state';
17
+
18
+ // The contract, and the two places it deliberately parts from upstream:
19
+ //
20
+ // - SURVIVORS KEEP THEIR IDENTITY. A stack route's key is COUNTER-derived (every adapter's
21
+ // createRoute increments a per-navigator sequence), not name-derived like a tab route's, so
22
+ // re-deriving the list from the registry would hand every survivor a brand-new key and remount
23
+ // live screens. Only the phantom entries go; every other route object passes through by
24
+ // reference, params included.
25
+ //
26
+ // - THE FOCUSED ROUTE IS THE TOP ONE. This state carries no `index` field: the focused route is
27
+ // always the last one (see computeActivityState's comment for why no route can outrank it), so
28
+ // upstream's `index: Math.min(state.index, routes.length - 1)` degenerates here to "the last
29
+ // survivor". Dropping the FOCUSED route therefore lands the user on the nearest still-registered
30
+ // route beneath it - where a pop() would have left them - rather than on nothing.
31
+ //
32
+ // - THE ROUTE LIST IS NEVER EMPTIED. `routes.length - 1` IS the focused index, so an empty list
33
+ // means no focused route at all - the blank screen this function exists to prevent. When nothing
34
+ // in the history survives (every marker gone, or the whole screen set swapped for new names) the
35
+ // state is returned UNCHANGED. Upstream instead pushes a freshly nanoid()-keyed route for
36
+ // initialRouteName; we cannot, because minting a route key belongs to the caller here
37
+ // (navigator-state.ts's header) and a derivation that mints one would allocate a new key on every
38
+ // re-run. Unchanged is also the right answer for the usual cause of a momentarily empty registry
39
+ // - markers unregistering and re-registering across a re-render - since the next run reconciles
40
+ // for real.
41
+ export function reconcileStackRoutes(
42
+ state: INavigatorState,
43
+ registeredNames: readonly string[],
44
+ ): INavigatorState {
45
+ const routes = state.routes.filter(route =>
46
+ registeredNames.includes(route.name),
47
+ );
48
+ // filter preserves order, so an unchanged length means nothing was dropped.
49
+ if (routes.length === state.routes.length || routes.length === 0)
50
+ return state;
51
+ return { routes };
52
+ }
@@ -11,11 +11,19 @@ import { isRecord } from '../guards';
11
11
  // params: undefined}`, and JSON.stringify drops undefined-valued keys - a JSON round trip of a
12
12
  // perfectly valid route legitimately arrives here without a `params` key at all.
13
13
  function isRoute(value: unknown): value is IRoute<unknown> {
14
- return isRecord(value) && typeof value.key === 'string' && typeof value.name === 'string';
14
+ return (
15
+ isRecord(value) &&
16
+ typeof value.key === 'string' &&
17
+ typeof value.name === 'string'
18
+ );
15
19
  }
16
20
 
17
21
  function isNavigatorState(value: unknown): value is INavigatorState {
18
- return isRecord(value) && Array.isArray(value.routes) && value.routes.every(isRoute);
22
+ return (
23
+ isRecord(value) &&
24
+ Array.isArray(value.routes) &&
25
+ value.routes.every(isRoute)
26
+ );
19
27
  }
20
28
 
21
29
  export function serializeNavigatorState(state: INavigatorState): unknown {
@@ -24,7 +32,9 @@ export function serializeNavigatorState(state: INavigatorState): unknown {
24
32
 
25
33
  export function deserializeNavigatorState(raw: unknown): INavigatorState {
26
34
  if (!isNavigatorState(raw)) {
27
- throw new Error('deserializeNavigatorState: persisted value is not a valid navigator state');
35
+ throw new Error(
36
+ 'deserializeNavigatorState: persisted value is not a valid navigator state',
37
+ );
28
38
  }
29
39
  return raw;
30
40
  }
@@ -29,11 +29,37 @@ export function createInitialTabState(
29
29
  routes: readonly IRouteEntry[],
30
30
  initialRouteName?: string,
31
31
  ): ITabRouterState {
32
- if (initialRouteName === undefined) return { routes, index: INITIAL_FOCUSED_INDEX };
32
+ if (initialRouteName === undefined)
33
+ return { routes, index: INITIAL_FOCUSED_INDEX };
33
34
  const index = routes.findIndex(route => route.name === initialRouteName);
34
35
  return { routes, index: index === -1 ? INITIAL_FOCUSED_INDEX : index };
35
36
  }
36
37
 
38
+ // A screen marker can appear or disappear after mount (a marker behind an `{#if}`, a data-driven
39
+ // screen list), so a navigator's route list has to follow its registry instead of staying frozen
40
+ // at whatever createInitialTabState saw first. Mirrors TabRouter.getStateForRouteNamesChange:
41
+ // membership and order come from `nextRoutes`, but a route that survives keeps its IDENTITY (its
42
+ // key) and everything jumpTo/setParams accumulated onto its params - only genuinely new names
43
+ // take their entry from `nextRoutes`. Focus follows the previously focused route's NAME, so an
44
+ // unrelated screen disappearing never moves the user; when the focused route is the one that
45
+ // disappeared, focus falls back to the first route, the same landing spot every unresolvable
46
+ // focus gets here (createInitialTabState's own fallback).
47
+ export function reconcileTabRoutes(
48
+ state: ITabRouterState,
49
+ nextRoutes: readonly IRouteEntry[],
50
+ ): ITabRouterState {
51
+ const routes = nextRoutes.map(
52
+ next => state.routes.find(route => route.name === next.name) ?? next,
53
+ );
54
+ const isUnchanged =
55
+ routes.length === state.routes.length &&
56
+ routes.every((route, at) => route === state.routes[at]);
57
+ if (isUnchanged) return state;
58
+ const focusedName = state.routes[state.index]?.name;
59
+ const index = routes.findIndex(route => route.name === focusedName);
60
+ return { routes, index: index === -1 ? INITIAL_FOCUSED_INDEX : index };
61
+ }
62
+
37
63
  // jumpTo moves the focused index to an existing route by name and optionally merges params
38
64
  // (navigation.jumpTo(name, params) - the tab-actions doc's own signature); it never adds,
39
65
  // removes, or reorders routes (mirrors TabRouter: JUMP_TO is a no-op when the target name isn't
@@ -52,7 +78,10 @@ export function tabRouterReducer(
52
78
  }
53
79
  const target = state.routes[index];
54
80
  const routes = state.routes.slice();
55
- routes[index] = { ...target, params: mergeParams(target.params, action.params) };
81
+ routes[index] = {
82
+ ...target,
83
+ params: mergeParams(target.params, action.params),
84
+ };
56
85
  return { ...state, index, routes };
57
86
  }
58
87
 
@@ -61,7 +90,10 @@ export function tabRouterReducer(
61
90
  if (index === -1) return state;
62
91
  const target = state.routes[index];
63
92
  const routes = state.routes.slice();
64
- routes[index] = { ...target, params: mergeParams(target.params, action.params) };
93
+ routes[index] = {
94
+ ...target,
95
+ params: mergeParams(target.params, action.params),
96
+ };
65
97
  return { ...state, routes };
66
98
  }
67
99