@expo/ui 58.0.0 → 58.0.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/android/build/intermediates/incremental/release/packageReleaseResources/compile-file-map.properties +1 -1
  3. package/android/build/kotlin/compileReleaseKotlin/cacheable/last-build.bin +0 -0
  4. package/android/build/publications/release/module.json +7 -7
  5. package/android/build/publications/release/pom-default.xml +1 -1
  6. package/android/build/tmp/publishReleasePublicationToNPMPackageRepository/module-maven-metadata.xml +4 -4
  7. package/android/build.gradle +2 -2
  8. package/build/swift-ui/NavigationDestination/index.d.ts +29 -0
  9. package/build/swift-ui/NavigationDestination/index.js +29 -0
  10. package/build/swift-ui/NavigationDestination/index.js.map +1 -0
  11. package/build/swift-ui/NavigationLink/index.d.ts +31 -0
  12. package/build/swift-ui/NavigationLink/index.js +31 -0
  13. package/build/swift-ui/NavigationLink/index.js.map +1 -0
  14. package/build/swift-ui/NavigationStack/index.d.ts +33 -2
  15. package/build/swift-ui/NavigationStack/index.js +21 -2
  16. package/build/swift-ui/NavigationStack/index.js.map +1 -1
  17. package/build/swift-ui/TabView/index.d.ts +1 -1
  18. package/build/swift-ui/TabView/index.js +1 -1
  19. package/build/swift-ui/index.d.ts +2 -0
  20. package/build/swift-ui/index.js +2 -0
  21. package/build/swift-ui/index.js.map +1 -1
  22. package/expo-module.config.json +1 -1
  23. package/ios/BackgroundView.swift +10 -6
  24. package/ios/ExpoUIModule.swift +1 -0
  25. package/ios/MaskView.swift +9 -5
  26. package/ios/NavigationLinkView.swift +22 -0
  27. package/ios/NavigationStackView.swift +46 -3
  28. package/ios/OverlayView.swift +9 -5
  29. package/ios/SlotView.swift +10 -5
  30. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0.module → 58.0.1/expo.modules.ui-58.0.1.module} +7 -7
  31. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.1/expo.modules.ui-58.0.1.module.md5 +1 -0
  32. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.1/expo.modules.ui-58.0.1.module.sha1 +1 -0
  33. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.1/expo.modules.ui-58.0.1.module.sha256 +1 -0
  34. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.1/expo.modules.ui-58.0.1.module.sha512 +1 -0
  35. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0.pom → 58.0.1/expo.modules.ui-58.0.1.pom} +1 -1
  36. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.1/expo.modules.ui-58.0.1.pom.md5 +1 -0
  37. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.1/expo.modules.ui-58.0.1.pom.sha1 +1 -0
  38. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.1/expo.modules.ui-58.0.1.pom.sha256 +1 -0
  39. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.1/expo.modules.ui-58.0.1.pom.sha512 +1 -0
  40. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml +4 -4
  41. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.md5 +1 -1
  42. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha1 +1 -1
  43. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha256 +1 -1
  44. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha512 +1 -1
  45. package/package.json +2 -2
  46. package/prebuilds/output/debug/xcframeworks/ExpoUI.tar.gz +0 -0
  47. package/prebuilds/output/release/xcframeworks/ExpoUI.tar.gz +0 -0
  48. package/src/swift-ui/NavigationDestination/index.tsx +39 -0
  49. package/src/swift-ui/NavigationLink/index.tsx +51 -0
  50. package/src/swift-ui/NavigationStack/index.tsx +47 -4
  51. package/src/swift-ui/TabView/index.tsx +1 -1
  52. package/src/swift-ui/index.tsx +2 -0
  53. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.0/expo.modules.ui-58.0.0.module.md5 +0 -1
  54. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.0/expo.modules.ui-58.0.0.module.sha1 +0 -1
  55. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.0/expo.modules.ui-58.0.0.module.sha256 +0 -1
  56. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.0/expo.modules.ui-58.0.0.module.sha512 +0 -1
  57. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.0/expo.modules.ui-58.0.0.pom.md5 +0 -1
  58. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.0/expo.modules.ui-58.0.0.pom.sha1 +0 -1
  59. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.0/expo.modules.ui-58.0.0.pom.sha256 +0 -1
  60. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.0/expo.modules.ui-58.0.0.pom.sha512 +0 -1
  61. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0-sources.jar → 58.0.1/expo.modules.ui-58.0.1-sources.jar} +0 -0
  62. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0-sources.jar.md5 → 58.0.1/expo.modules.ui-58.0.1-sources.jar.md5} +0 -0
  63. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0-sources.jar.sha1 → 58.0.1/expo.modules.ui-58.0.1-sources.jar.sha1} +0 -0
  64. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0-sources.jar.sha256 → 58.0.1/expo.modules.ui-58.0.1-sources.jar.sha256} +0 -0
  65. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0-sources.jar.sha512 → 58.0.1/expo.modules.ui-58.0.1-sources.jar.sha512} +0 -0
  66. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0.aar → 58.0.1/expo.modules.ui-58.0.1.aar} +0 -0
  67. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0.aar.md5 → 58.0.1/expo.modules.ui-58.0.1.aar.md5} +0 -0
  68. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0.aar.sha1 → 58.0.1/expo.modules.ui-58.0.1.aar.sha1} +0 -0
  69. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0.aar.sha256 → 58.0.1/expo.modules.ui-58.0.1.aar.sha256} +0 -0
  70. /package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.0/expo.modules.ui-58.0.0.aar.sha512 → 58.0.1/expo.modules.ui-58.0.1.aar.sha512} +0 -0
package/CHANGELOG.md CHANGED
@@ -10,6 +10,12 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 58.0.1 — 2026-09-14
14
+
15
+ ### 💡 Others
16
+
17
+ - Update the native tabs import path in the `TabView` API reference. ([#50119](https://github.com/expo/expo/pull/50119) by [@Ubax](https://github.com/Ubax))
18
+
13
19
  ## 58.0.0 — 2026-09-10
14
20
 
15
21
  ### 🛠 Breaking changes
@@ -47,6 +53,7 @@
47
53
  - [iOS] Added the `scrollClipDisabled` modifier, which lets content that draws outside a scrollable view's bounds, such as a shadow or a scaled-up card, stay visible instead of being clipped. ([#49780](https://github.com/expo/expo/pull/49780) by [@Den1Marshall](https://github.com/Den1Marshall))
48
54
  - [iOS] Taught the `tint`, `border`, `strokeBorder` and `containerBackground` modifiers to paint with any `ShapeStyle`, matching SwiftUI, where all four take a `ShapeStyle` rather than a color. The `color` parameter of `border` and `strokeBorder` is deprecated in favor of `content`, the name SwiftUI gives it. ([#49838](https://github.com/expo/expo/pull/49838) by [@Den1Marshall](https://github.com/Den1Marshall))
49
55
  - [iOS] Added the `NavigationStack` and `Toolbar` components, the `navigationTitle` modifier, and the `close` button role. ([#49940](https://github.com/expo/expo/pull/49940) by [@nishan](https://github.com/intergalacticspacehighway))
56
+ - [iOS] Added the `NavigationLink` component, and the `path` and `onPathChange` props and the `NavigationDestination` component, so a stack can push a destination that is built only when the link is followed. ([#49991](https://github.com/expo/expo/pull/49991) by [@nishan](https://github.com/intergalacticspacehighway))
50
57
 
51
58
  ### 🐛 Bug fixes
52
59
 
@@ -78,6 +85,7 @@
78
85
  - [Android] Explicitly enable `buildFeatures.buildConfig`, required by AGP 9. ([#47729](https://github.com/expo/expo/pull/47729) by [@gabrieldonadel](https://github.com/gabrieldonadel))
79
86
  - Fix `Host` color scheme type errors on React Native 0.87. ([#47729](https://github.com/expo/expo/pull/47729) by [@gabrieldonadel](https://github.com/gabrieldonadel))
80
87
  - [iOS] Fixed `PlatformColor` and `DynamicColorIOS` values dropping the `backgroundColor` and `borderColor` of a universal component. Both were stringified to `"[object Object]"`, which the native color converter rejects, so the modifier was discarded without a trace. ([#49746](https://github.com/expo/expo/pull/49746) by [@Den1Marshall](https://github.com/Den1Marshall))
88
+ - [iOS] Preserve string-based child identities in `Overlay`, `Background`, and `Mask`. ([#49734](https://github.com/expo/expo/pull/49734) by [@jakex7](https://github.com/jakex7))
81
89
 
82
90
  ### 💡 Others
83
91
 
@@ -1 +1 @@
1
- #Thu Sep 10 20:19:44 IST 2026
1
+ #Mon Sep 14 16:00:38 IST 2026
@@ -3,7 +3,7 @@
3
3
  "component": {
4
4
  "group": "expo.modules.ui",
5
5
  "module": "expo.modules.ui",
6
- "version": "58.0.0",
6
+ "version": "58.0.1",
7
7
  "attributes": {
8
8
  "org.gradle.status": "release"
9
9
  }
@@ -24,8 +24,8 @@
24
24
  },
25
25
  "files": [
26
26
  {
27
- "name": "expo.modules.ui-58.0.0.aar",
28
- "url": "expo.modules.ui-58.0.0.aar",
27
+ "name": "expo.modules.ui-58.0.1.aar",
28
+ "url": "expo.modules.ui-58.0.1.aar",
29
29
  "size": 1789469,
30
30
  "sha512": "dfe706437f10aa521a458896b97fa14d945cf66c80dab9cc43fddd444cddd016073b783076f38ba90e07c5076b8752bf66e136ce9c40d85195cf27a231ce7f9d",
31
31
  "sha256": "8faeae3cb56c1d29d1a120a9a8c1964e6015ba993519f244283855a066a1704c",
@@ -141,8 +141,8 @@
141
141
  ],
142
142
  "files": [
143
143
  {
144
- "name": "expo.modules.ui-58.0.0.aar",
145
- "url": "expo.modules.ui-58.0.0.aar",
144
+ "name": "expo.modules.ui-58.0.1.aar",
145
+ "url": "expo.modules.ui-58.0.1.aar",
146
146
  "size": 1789469,
147
147
  "sha512": "dfe706437f10aa521a458896b97fa14d945cf66c80dab9cc43fddd444cddd016073b783076f38ba90e07c5076b8752bf66e136ce9c40d85195cf27a231ce7f9d",
148
148
  "sha256": "8faeae3cb56c1d29d1a120a9a8c1964e6015ba993519f244283855a066a1704c",
@@ -161,8 +161,8 @@
161
161
  },
162
162
  "files": [
163
163
  {
164
- "name": "expo.modules.ui-58.0.0-sources.jar",
165
- "url": "expo.modules.ui-58.0.0-sources.jar",
164
+ "name": "expo.modules.ui-58.0.1-sources.jar",
165
+ "url": "expo.modules.ui-58.0.1-sources.jar",
166
166
  "size": 106165,
167
167
  "sha512": "59ec9e524c62a8b77c41e894e4833d24d2c9bb1912ef1be23d81ab6eb04bcf1f8743cdc11528bf2630b0f1f29db20b017e8015ebde418530196d7dcea06a90bc",
168
168
  "sha256": "297ecd2b76dbb6908b0b2897c6adba6be5dd10cb16c8ca169525a40e207d52c2",
@@ -9,7 +9,7 @@
9
9
  <modelVersion>4.0.0</modelVersion>
10
10
  <groupId>expo.modules.ui</groupId>
11
11
  <artifactId>expo.modules.ui</artifactId>
12
- <version>58.0.0</version>
12
+ <version>58.0.1</version>
13
13
  <packaging>aar</packaging>
14
14
  <name>expo.modules.ui</name>
15
15
  <url>https://github.com/expo/expo</url>
@@ -3,11 +3,11 @@
3
3
  <groupId>expo.modules.ui</groupId>
4
4
  <artifactId>expo.modules.ui</artifactId>
5
5
  <versioning>
6
- <latest>58.0.0</latest>
7
- <release>58.0.0</release>
6
+ <latest>58.0.1</latest>
7
+ <release>58.0.1</release>
8
8
  <versions>
9
- <version>58.0.0</version>
9
+ <version>58.0.1</version>
10
10
  </versions>
11
- <lastUpdated>20260910192012</lastUpdated>
11
+ <lastUpdated>20260914150056</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -12,13 +12,13 @@ apply plugin: 'expo-module-gradle-plugin'
12
12
  apply plugin: 'org.jetbrains.kotlin.plugin.compose'
13
13
 
14
14
  group = 'expo.modules.ui'
15
- version = '58.0.0'
15
+ version = '58.0.1'
16
16
 
17
17
  android {
18
18
  namespace "expo.modules.ui"
19
19
  defaultConfig {
20
20
  versionCode 1
21
- versionName "58.0.0"
21
+ versionName "58.0.1"
22
22
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
23
23
  }
24
24
  buildFeatures {
@@ -0,0 +1,29 @@
1
+ import { type ReactNode } from 'react';
2
+ export interface NavigationDestinationProps {
3
+ /**
4
+ * The `NavigationLink` value this destination is presented for.
5
+ */
6
+ value: string;
7
+ /**
8
+ * The view pushed onto the stack for `value`.
9
+ */
10
+ children: ReactNode;
11
+ }
12
+ /**
13
+ * Associates a destination view with a `NavigationLink` value, matching SwiftUI's
14
+ * `navigationDestination(for:destination:)`. It must be a direct child of the `NavigationStack`,
15
+ * however deeply the link that pushes it is nested inside that stack.
16
+ *
17
+ * Keep it mounted so the pushed screen already carries its `navigationTitle` when the slide
18
+ * starts, or render one for each value on the stack's `path` to build screens on demand.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * <NavigationDestination value="settings">
23
+ * <SettingsScreen />
24
+ * </NavigationDestination>
25
+ * ```
26
+ *
27
+ * @platform ios
28
+ */
29
+ export declare function NavigationDestination(props: NavigationDestinationProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Slot } from '../SlotView';
3
+ /**
4
+ * Associates a destination view with a `NavigationLink` value, matching SwiftUI's
5
+ * `navigationDestination(for:destination:)`. It must be a direct child of the `NavigationStack`,
6
+ * however deeply the link that pushes it is nested inside that stack.
7
+ *
8
+ * Keep it mounted so the pushed screen already carries its `navigationTitle` when the slide
9
+ * starts, or render one for each value on the stack's `path` to build screens on demand.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * <NavigationDestination value="settings">
14
+ * <SettingsScreen />
15
+ * </NavigationDestination>
16
+ * ```
17
+ *
18
+ * @platform ios
19
+ */ export function NavigationDestination(props) {
20
+ return /*#__PURE__*/ _jsx(Slot, {
21
+ name: "destination",
22
+ extraProps: {
23
+ value: props.value
24
+ },
25
+ children: props.children
26
+ });
27
+ }
28
+
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["swift-ui/NavigationDestination/index.tsx"],"sourcesContent":[null],"names":["Slot","NavigationDestination","props","name","extraProps","value","children"],"mappings":";AAEA,SAASA,IAAI,QAAQ,cAAc;AAanC;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,SAASC,sBAAsBC,KAAiC;IACrE,qBACE,KAACF;QAAKG,MAAK;QAAcC,YAAY;YAAEC,OAAOH,MAAMG,KAAK;QAAC;kBACvDH,MAAMI,QAAQ;;AAGrB"}
@@ -0,0 +1,31 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type CommonViewModifierProps } from '../types';
3
+ export interface NavigationLinkProps extends CommonViewModifierProps {
4
+ /**
5
+ * The value to append to the enclosing `NavigationStack`'s path when the link is tapped. The
6
+ * stack presents the `NavigationDestination` whose `value` matches.
7
+ */
8
+ value: string;
9
+ /**
10
+ * A view that describes the link.
11
+ */
12
+ children: ReactNode;
13
+ }
14
+ /**
15
+ * A view that controls a navigation presentation. In a `List` it renders as a row with a
16
+ * disclosure chevron, and tapping it pushes the matching `NavigationDestination`.
17
+ *
18
+ * The link has to be inside the `NavigationStack` itself. Content presented from the stack, such
19
+ * as a `BottomSheet` or a `Popover`, is its own presentation context and does not reach the
20
+ * stack's destinations, so give that content its own `NavigationStack`.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * <NavigationLink value="settings">
25
+ * <Text>Settings</Text>
26
+ * </NavigationLink>
27
+ * ```
28
+ *
29
+ * @platform ios
30
+ */
31
+ export declare function NavigationLink(props: NavigationLinkProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { requireNativeView } from 'expo';
3
+ import { createViewModifierEventListener } from '../modifiers/utils';
4
+ const NavigationLinkNativeView = requireNativeView('ExpoUI', 'NavigationLinkView');
5
+ /**
6
+ * A view that controls a navigation presentation. In a `List` it renders as a row with a
7
+ * disclosure chevron, and tapping it pushes the matching `NavigationDestination`.
8
+ *
9
+ * The link has to be inside the `NavigationStack` itself. Content presented from the stack, such
10
+ * as a `BottomSheet` or a `Popover`, is its own presentation context and does not reach the
11
+ * stack's destinations, so give that content its own `NavigationStack`.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * <NavigationLink value="settings">
16
+ * <Text>Settings</Text>
17
+ * </NavigationLink>
18
+ * ```
19
+ *
20
+ * @platform ios
21
+ */ export function NavigationLink(props) {
22
+ const { modifiers, children, ...restProps } = props;
23
+ return /*#__PURE__*/ _jsx(NavigationLinkNativeView, {
24
+ modifiers: modifiers,
25
+ ...modifiers ? createViewModifierEventListener(modifiers) : undefined,
26
+ ...restProps,
27
+ children: children
28
+ });
29
+ }
30
+
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["swift-ui/NavigationLink/index.tsx"],"sourcesContent":[null],"names":["requireNativeView","createViewModifierEventListener","NavigationLinkNativeView","NavigationLink","props","modifiers","children","restProps","undefined"],"mappings":";AAAA,SAASA,iBAAiB,QAAQ,OAAO;AAGzC,SAASC,+BAA+B,QAAQ,qBAAqB;AAerE,MAAMC,2BAA+DF,kBACnE,UACA;AAGF;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,SAASG,eAAeC,KAA0B;IACvD,MAAM,EAAEC,SAAS,EAAEC,QAAQ,EAAE,GAAGC,WAAW,GAAGH;IAC9C,qBACE,KAACF;QACCG,WAAWA;QACV,GAAIA,YAAYJ,gCAAgCI,aAAaG,SAAS;QACtE,GAAGD,SAAS;kBACZD;;AAGP"}
@@ -1,13 +1,44 @@
1
+ import { type ReactNode } from 'react';
1
2
  import { type CommonViewModifierProps } from '../types';
2
3
  export interface NavigationStackProps extends CommonViewModifierProps {
3
4
  /**
4
- * The root view of the stack. It is displayed inside a navigation bar.
5
+ * The root view of the stack, and the `NavigationDestination` views the stack can push. It is
6
+ * displayed inside a navigation bar.
5
7
  */
6
- children: React.ReactNode;
8
+ children: ReactNode;
9
+ /**
10
+ * The values of the views pushed on top of the root view, in the order they were pushed.
11
+ * Leave it undefined to let the stack manage its own path.
12
+ */
13
+ path?: string[];
14
+ /**
15
+ * Callback function that is called when the stack pushes or pops a view, for example when a
16
+ * `NavigationLink` is tapped or the user swipes back. Gets called with the new path.
17
+ *
18
+ * When `path` is set, the stack is controlled: a push takes effect once the new path comes back
19
+ * through this prop.
20
+ */
21
+ onPathChange?: (path: string[]) => void;
7
22
  }
8
23
  /**
9
24
  * A view that displays a root view and enables you to present additional views over the root view.
10
25
  *
26
+ * @example
27
+ * ```tsx
28
+ * const [path, setPath] = useState<string[]>([]);
29
+ *
30
+ * <NavigationStack path={path} onPathChange={setPath}>
31
+ * <List>
32
+ * <NavigationLink value="settings">
33
+ * <Text>Settings</Text>
34
+ * </NavigationLink>
35
+ * </List>
36
+ * <NavigationDestination value="settings">
37
+ * <SettingsScreen />
38
+ * </NavigationDestination>
39
+ * </NavigationStack>
40
+ * ```
41
+ *
11
42
  * @platform ios
12
43
  */
13
44
  export declare function NavigationStack(props: NavigationStackProps): import("react/jsx-runtime").JSX.Element;
@@ -5,13 +5,32 @@ const NavigationStackNativeView = requireNativeView('ExpoUI', 'NavigationStackVi
5
5
  /**
6
6
  * A view that displays a root view and enables you to present additional views over the root view.
7
7
  *
8
+ * @example
9
+ * ```tsx
10
+ * const [path, setPath] = useState<string[]>([]);
11
+ *
12
+ * <NavigationStack path={path} onPathChange={setPath}>
13
+ * <List>
14
+ * <NavigationLink value="settings">
15
+ * <Text>Settings</Text>
16
+ * </NavigationLink>
17
+ * </List>
18
+ * <NavigationDestination value="settings">
19
+ * <SettingsScreen />
20
+ * </NavigationDestination>
21
+ * </NavigationStack>
22
+ * ```
23
+ *
8
24
  * @platform ios
9
25
  */ export function NavigationStack(props) {
10
- const { modifiers, ...restProps } = props;
26
+ const { modifiers, onPathChange, ...restProps } = props;
11
27
  return /*#__PURE__*/ _jsx(NavigationStackNativeView, {
12
28
  modifiers: modifiers,
13
29
  ...modifiers ? createViewModifierEventListener(modifiers) : undefined,
14
- ...restProps
30
+ ...restProps,
31
+ onPathChange: onPathChange ? ({ nativeEvent: { path } })=>{
32
+ onPathChange(path);
33
+ } : undefined
15
34
  });
16
35
  }
17
36
 
@@ -1 +1 @@
1
- {"version":3,"sources":["swift-ui/NavigationStack/index.tsx"],"sourcesContent":[null],"names":["requireNativeView","createViewModifierEventListener","NavigationStackNativeView","NavigationStack","props","modifiers","restProps","undefined"],"mappings":";AAAA,SAASA,iBAAiB,QAAQ,OAAO;AAEzC,SAASC,+BAA+B,QAAQ,qBAAqB;AAUrE,MAAMC,4BAAuEF,kBAC3E,UACA;AAGF;;;;CAIC,GACD,OAAO,SAASG,gBAAgBC,KAA2B;IACzD,MAAM,EAAEC,SAAS,EAAE,GAAGC,WAAW,GAAGF;IACpC,qBACE,KAACF;QACCG,WAAWA;QACV,GAAIA,YAAYJ,gCAAgCI,aAAaE,SAAS;QACtE,GAAGD,SAAS;;AAGnB"}
1
+ {"version":3,"sources":["swift-ui/NavigationStack/index.tsx"],"sourcesContent":[null],"names":["requireNativeView","createViewModifierEventListener","NavigationStackNativeView","NavigationStack","props","modifiers","onPathChange","restProps","undefined","nativeEvent","path"],"mappings":";AAAA,SAASA,iBAAiB,QAAQ,OAAO;AAIzC,SAASC,+BAA+B,QAAQ,qBAAqB;AA4BrE,MAAMC,4BAAuEF,kBAC3E,UACA;AAGF;;;;;;;;;;;;;;;;;;;;CAoBC,GACD,OAAO,SAASG,gBAAgBC,KAA2B;IACzD,MAAM,EAAEC,SAAS,EAAEC,YAAY,EAAE,GAAGC,WAAW,GAAGH;IAClD,qBACE,KAACF;QACCG,WAAWA;QACV,GAAIA,YAAYJ,gCAAgCI,aAAaG,SAAS;QACtE,GAAGD,SAAS;QACbD,cACEA,eACI,CAAC,EAAEG,aAAa,EAAEC,IAAI,EAAE,EAAE;YACxBJ,aAAaI;QACf,IACAF;;AAIZ"}
@@ -33,7 +33,7 @@ export type { TabProps } from './Tab';
33
33
  * `value` prop, which is used for selection.
34
34
  *
35
35
  * For routed bottom-tab navigation across full-screen routes, prefer
36
- * `expo-router/unstable-native-tabs`.
36
+ * `expo-router/native-tabs`.
37
37
  *
38
38
  * @platform ios
39
39
  */
@@ -23,7 +23,7 @@ function TabView(props) {
23
23
  * `value` prop, which is used for selection.
24
24
  *
25
25
  * For routed bottom-tab navigation across full-screen routes, prefer
26
- * `expo-router/unstable-native-tabs`.
26
+ * `expo-router/native-tabs`.
27
27
  *
28
28
  * @platform ios
29
29
  */ const _TabView = Object.assign(TabView, {
@@ -25,6 +25,8 @@ export * from './ZStack';
25
25
  export * from './Group';
26
26
  export * from './List';
27
27
  export * from './Menu';
28
+ export * from './NavigationDestination';
29
+ export * from './NavigationLink';
28
30
  export * from './NavigationStack';
29
31
  export * from './Picker';
30
32
  export * from './ProgressView';
@@ -25,6 +25,8 @@ export * from './ZStack';
25
25
  export * from './Group';
26
26
  export * from './List';
27
27
  export * from './Menu';
28
+ export * from './NavigationDestination';
29
+ export * from './NavigationLink';
28
30
  export * from './NavigationStack';
29
31
  export * from './Picker';
30
32
  export * from './ProgressView';
@@ -1 +1 @@
1
- {"version":3,"sources":["swift-ui/index.tsx"],"sourcesContent":[null],"names":["useNativeState","withAnimation","TextField"],"mappings":"AAAA,cAAc,8BAA8B;AAC5C,cAAc,UAAU;AACxB,cAAc,gBAAgB;AAC9B,cAAc,WAAW;AACzB,cAAc,UAAU;AACxB,cAAc,gBAAgB;AAC9B,cAAc,2BAA2B;AACzC,cAAc,uBAAuB;AACrC,cAAc,iBAAiB;AAC/B,cAAc,gBAAgB;AAC9B,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,oBAAoB;AAClC,cAAc,SAAS;AACvB,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,UAAU;AACxB,cAAc,UAAU;AACxB,cAAc,mBAAmB;AACjC,cAAc,WAAW;AACzB,cAAc,eAAe;AAC7B,cAAc,eAAe;AAC7B,cAAc,WAAW;AACzB,cAAc,WAAW;AACzB,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,SAAS;AACvB,cAAc,oBAAoB;AAClC,cAAc,WAAW;AACzB,cAAc,iBAAiB;AAC/B,cAAc,YAAY;AAC1B,cAAc,cAAc;AAC5B,cAAc,WAAW;AACzB,cAAc,WAAW;AACzB,cAAc,YAAY;AAC1B,cAAc,iBAAiB;AAC/B,cAAc,SAAS;AACvB,SAASA,cAAc,QAAQ,WAAW;AAC1C,SAASC,aAAa,QAA8C,kBAAkB;AACtF,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,YAAY;AAC1B,cAAc,WAAW;AACzB,SACEC,SAAS,QAIJ,cAAc;AACrB,cAAc,gBAAgB;AAC9B,cAAc,cAAc;AAC5B,cAAc,yBAAyB;AACvC,cAAc,eAAe;AAC7B,cAAc,WAAW;AACzB,cAAc,SAAS;AACvB,cAAc,YAAY;AAC1B,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,SAAS;AACvB,cAAc,eAAe;AAC7B,cAAc,SAAS"}
1
+ {"version":3,"sources":["swift-ui/index.tsx"],"sourcesContent":[null],"names":["useNativeState","withAnimation","TextField"],"mappings":"AAAA,cAAc,8BAA8B;AAC5C,cAAc,UAAU;AACxB,cAAc,gBAAgB;AAC9B,cAAc,WAAW;AACzB,cAAc,UAAU;AACxB,cAAc,gBAAgB;AAC9B,cAAc,2BAA2B;AACzC,cAAc,uBAAuB;AACrC,cAAc,iBAAiB;AAC/B,cAAc,gBAAgB;AAC9B,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,oBAAoB;AAClC,cAAc,SAAS;AACvB,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,UAAU;AACxB,cAAc,UAAU;AACxB,cAAc,mBAAmB;AACjC,cAAc,WAAW;AACzB,cAAc,eAAe;AAC7B,cAAc,eAAe;AAC7B,cAAc,WAAW;AACzB,cAAc,WAAW;AACzB,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,SAAS;AACvB,cAAc,0BAA0B;AACxC,cAAc,mBAAmB;AACjC,cAAc,oBAAoB;AAClC,cAAc,WAAW;AACzB,cAAc,iBAAiB;AAC/B,cAAc,YAAY;AAC1B,cAAc,cAAc;AAC5B,cAAc,WAAW;AACzB,cAAc,WAAW;AACzB,cAAc,YAAY;AAC1B,cAAc,iBAAiB;AAC/B,cAAc,SAAS;AACvB,SAASA,cAAc,QAAQ,WAAW;AAC1C,SAASC,aAAa,QAA8C,kBAAkB;AACtF,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,YAAY;AAC1B,cAAc,WAAW;AACzB,SACEC,SAAS,QAIJ,cAAc;AACrB,cAAc,gBAAgB;AAC9B,cAAc,cAAc;AAC5B,cAAc,yBAAyB;AACvC,cAAc,eAAe;AAC7B,cAAc,WAAW;AACzB,cAAc,SAAS;AACvB,cAAc,YAAY;AAC1B,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,SAAS;AACvB,cAAc,eAAe;AAC7B,cAAc,SAAS"}
@@ -10,7 +10,7 @@
10
10
  "publication": {
11
11
  "groupId": "expo.modules.ui",
12
12
  "artifactId": "expo.modules.ui",
13
- "version": "58.0.0",
13
+ "version": "58.0.1",
14
14
  "repository": "local-maven-repo"
15
15
  }
16
16
  }
@@ -3,14 +3,18 @@
3
3
  import ExpoModulesCore
4
4
  import SwiftUI
5
5
 
6
- internal class BackgroundViewProps: UIBaseViewProps {
6
+ public final class BackgroundViewProps: UIBaseViewProps {
7
7
  @Field var alignment: AlignmentOptions?
8
8
  }
9
9
 
10
- internal struct BackgroundView: ExpoSwiftUI.View {
11
- @ObservedObject var props: BackgroundViewProps
10
+ public struct BackgroundView: ExpoSwiftUI.View {
11
+ @ObservedObject public var props: BackgroundViewProps
12
12
 
13
- var body: some View {
13
+ public init(props: BackgroundViewProps) {
14
+ self.props = props
15
+ }
16
+
17
+ public var body: some View {
14
18
  baseContent
15
19
  .background(alignment: props.alignment?.toAlignment() ?? .center) {
16
20
  backgroundContent
@@ -19,7 +23,7 @@ internal struct BackgroundView: ExpoSwiftUI.View {
19
23
 
20
24
  @ViewBuilder
21
25
  private var baseContent: some View {
22
- ForEach(props.children?.withoutSlots() ?? [], id: \.id) { child in
26
+ ForEach(props.children?.withoutSlots() ?? [], id: \.childIdentity) { child in
23
27
  let view: any View = child.childView
24
28
  AnyView(view)
25
29
  }
@@ -31,4 +35,4 @@ internal struct BackgroundView: ExpoSwiftUI.View {
31
35
  content
32
36
  }
33
37
  }
34
- }
38
+ }
@@ -157,6 +157,7 @@ public final class ExpoUIModule: Module {
157
157
  ExpoUIView(MenuView.self)
158
158
 
159
159
  ExpoUIView(NavigationStackView.self)
160
+ ExpoUIView(NavigationLinkView.self)
160
161
  ExpoUIView(ToolbarView.self)
161
162
 
162
163
  ExpoUIView(FormView.self)
@@ -3,14 +3,18 @@
3
3
  import ExpoModulesCore
4
4
  import SwiftUI
5
5
 
6
- internal class MaskViewProps: UIBaseViewProps {
6
+ public final class MaskViewProps: UIBaseViewProps {
7
7
  @Field var alignment: AlignmentOptions?
8
8
  }
9
9
 
10
- internal struct MaskView: ExpoSwiftUI.View {
11
- @ObservedObject var props: MaskViewProps
10
+ public struct MaskView: ExpoSwiftUI.View {
11
+ @ObservedObject public var props: MaskViewProps
12
12
 
13
- var body: some View {
13
+ public init(props: MaskViewProps) {
14
+ self.props = props
15
+ }
16
+
17
+ public var body: some View {
14
18
  if let mask = props.children?.slot("content") {
15
19
  baseContent.mask(alignment: props.alignment?.toAlignment() ?? .center) {
16
20
  mask
@@ -22,7 +26,7 @@ internal struct MaskView: ExpoSwiftUI.View {
22
26
 
23
27
  @ViewBuilder
24
28
  private var baseContent: some View {
25
- ForEach(props.children?.withoutSlots() ?? [], id: \.id) { child in
29
+ ForEach(props.children?.withoutSlots() ?? [], id: \.childIdentity) { child in
26
30
  let view: any View = child.childView
27
31
  AnyView(view)
28
32
  }
@@ -0,0 +1,22 @@
1
+ // Copyright 2025-present 650 Industries. All rights reserved.
2
+
3
+ import SwiftUI
4
+ import ExpoModulesCore
5
+
6
+ internal final class NavigationLinkViewProps: UIBaseViewProps {
7
+ @Field var value: String = ""
8
+ }
9
+
10
+ internal struct NavigationLinkView: ExpoSwiftUI.View {
11
+ @ObservedObject var props: NavigationLinkViewProps
12
+
13
+ init(props: NavigationLinkViewProps) {
14
+ self.props = props
15
+ }
16
+
17
+ var body: some View {
18
+ NavigationLink(value: props.value) {
19
+ Children()
20
+ }
21
+ }
22
+ }
@@ -3,18 +3,61 @@
3
3
  import SwiftUI
4
4
  import ExpoModulesCore
5
5
 
6
- internal final class NavigationStackViewProps: UIBaseViewProps {}
6
+ internal final class NavigationStackViewProps: UIBaseViewProps {
7
+ @Field var path: [String]?
8
+ var onPathChange = EventDispatcher()
9
+ }
10
+
11
+ private struct NavigationDestinationContent: View {
12
+ @ObservedObject var props: NavigationStackViewProps
13
+ let value: String
14
+
15
+ var body: some View {
16
+ props.children?
17
+ .slots("destination")
18
+ .first { $0.extra("value", as: String.self) == value }
19
+ }
20
+ }
7
21
 
8
22
  internal struct NavigationStackView: ExpoSwiftUI.View {
9
23
  @ObservedObject var props: NavigationStackViewProps
24
+ @State private var uncontrolledPath: [String] = []
10
25
 
11
26
  init(props: NavigationStackViewProps) {
12
27
  self.props = props
13
28
  }
14
29
 
30
+ private var pathBinding: Binding<[String]> {
31
+ let props = props
32
+ let uncontrolled = $uncontrolledPath
33
+ return Binding(
34
+ get: { props.path ?? uncontrolled.wrappedValue },
35
+ set: { newPath in
36
+ guard (props.path ?? uncontrolled.wrappedValue) != newPath else {
37
+ return
38
+ }
39
+ if props.path == nil {
40
+ uncontrolled.wrappedValue = newPath
41
+ }
42
+ props.onPathChange(["path": newPath])
43
+ }
44
+ )
45
+ }
46
+
15
47
  var body: some View {
16
- NavigationStack {
17
- Children()
48
+ NavigationStack(path: pathBinding) {
49
+ rootContent
50
+ .navigationDestination(for: String.self) { value in
51
+ NavigationDestinationContent(props: props, value: value)
52
+ }
53
+ }
54
+ }
55
+
56
+ @ViewBuilder
57
+ private var rootContent: some View {
58
+ ForEach(props.children?.withoutSlot("destination") ?? [], id: \.id) { child in
59
+ let view: any View = child.childView
60
+ AnyView(view)
18
61
  }
19
62
  }
20
63
  }
@@ -3,14 +3,18 @@
3
3
  import ExpoModulesCore
4
4
  import SwiftUI
5
5
 
6
- internal class OverlayViewProps: UIBaseViewProps {
6
+ public final class OverlayViewProps: UIBaseViewProps {
7
7
  @Field var alignment: AlignmentOptions?
8
8
  }
9
9
 
10
- internal struct OverlayView: ExpoSwiftUI.View {
11
- @ObservedObject var props: OverlayViewProps
10
+ public struct OverlayView: ExpoSwiftUI.View {
11
+ @ObservedObject public var props: OverlayViewProps
12
12
 
13
- var body: some View {
13
+ public init(props: OverlayViewProps) {
14
+ self.props = props
15
+ }
16
+
17
+ public var body: some View {
14
18
  baseContent
15
19
  .overlay(alignment: props.alignment?.toAlignment() ?? .center) {
16
20
  overlayContent
@@ -19,7 +23,7 @@ internal struct OverlayView: ExpoSwiftUI.View {
19
23
 
20
24
  @ViewBuilder
21
25
  private var baseContent: some View {
22
- ForEach(props.children?.withoutSlots() ?? [], id: \.id) { child in
26
+ ForEach(props.children?.withoutSlots() ?? [], id: \.childIdentity) { child in
23
27
  let view: any View = child.childView
24
28
  AnyView(view)
25
29
  }
@@ -3,19 +3,19 @@
3
3
  import SwiftUI
4
4
  import ExpoModulesCore
5
5
 
6
- internal final class SlotViewProps: ExpoSwiftUI.ViewProps {
6
+ public final class SlotViewProps: ExpoSwiftUI.ViewProps {
7
7
  @Field var name: String = ""
8
8
  @Field var extraProps: [String: Any]?
9
9
  }
10
10
 
11
- internal struct SlotView: ExpoSwiftUI.View {
12
- @ObservedObject var props: SlotViewProps
11
+ public struct SlotView: ExpoSwiftUI.View {
12
+ @ObservedObject public var props: SlotViewProps
13
13
 
14
- init(props: SlotViewProps) {
14
+ public init(props: SlotViewProps) {
15
15
  self.props = props
16
16
  }
17
17
 
18
- var body: some View {
18
+ public var body: some View {
19
19
  Children()
20
20
  }
21
21
 
@@ -30,6 +30,11 @@ extension [any ExpoSwiftUI.AnyChild] {
30
30
  .first { $0.props.name == name }
31
31
  }
32
32
 
33
+ func slots(_ name: String) -> [SlotView] {
34
+ compactMap { $0.childView as? SlotView }
35
+ .filter { $0.props.name == name }
36
+ }
37
+
33
38
  func withoutSlot(_ name: String) -> [any ExpoSwiftUI.AnyChild] {
34
39
  filter {
35
40
  guard let slot = $0.childView as? SlotView else { return true }
@@ -3,7 +3,7 @@
3
3
  "component": {
4
4
  "group": "expo.modules.ui",
5
5
  "module": "expo.modules.ui",
6
- "version": "58.0.0",
6
+ "version": "58.0.1",
7
7
  "attributes": {
8
8
  "org.gradle.status": "release"
9
9
  }
@@ -24,8 +24,8 @@
24
24
  },
25
25
  "files": [
26
26
  {
27
- "name": "expo.modules.ui-58.0.0.aar",
28
- "url": "expo.modules.ui-58.0.0.aar",
27
+ "name": "expo.modules.ui-58.0.1.aar",
28
+ "url": "expo.modules.ui-58.0.1.aar",
29
29
  "size": 1789469,
30
30
  "sha512": "dfe706437f10aa521a458896b97fa14d945cf66c80dab9cc43fddd444cddd016073b783076f38ba90e07c5076b8752bf66e136ce9c40d85195cf27a231ce7f9d",
31
31
  "sha256": "8faeae3cb56c1d29d1a120a9a8c1964e6015ba993519f244283855a066a1704c",
@@ -141,8 +141,8 @@
141
141
  ],
142
142
  "files": [
143
143
  {
144
- "name": "expo.modules.ui-58.0.0.aar",
145
- "url": "expo.modules.ui-58.0.0.aar",
144
+ "name": "expo.modules.ui-58.0.1.aar",
145
+ "url": "expo.modules.ui-58.0.1.aar",
146
146
  "size": 1789469,
147
147
  "sha512": "dfe706437f10aa521a458896b97fa14d945cf66c80dab9cc43fddd444cddd016073b783076f38ba90e07c5076b8752bf66e136ce9c40d85195cf27a231ce7f9d",
148
148
  "sha256": "8faeae3cb56c1d29d1a120a9a8c1964e6015ba993519f244283855a066a1704c",
@@ -161,8 +161,8 @@
161
161
  },
162
162
  "files": [
163
163
  {
164
- "name": "expo.modules.ui-58.0.0-sources.jar",
165
- "url": "expo.modules.ui-58.0.0-sources.jar",
164
+ "name": "expo.modules.ui-58.0.1-sources.jar",
165
+ "url": "expo.modules.ui-58.0.1-sources.jar",
166
166
  "size": 106165,
167
167
  "sha512": "59ec9e524c62a8b77c41e894e4833d24d2c9bb1912ef1be23d81ab6eb04bcf1f8743cdc11528bf2630b0f1f29db20b017e8015ebde418530196d7dcea06a90bc",
168
168
  "sha256": "297ecd2b76dbb6908b0b2897c6adba6be5dd10cb16c8ca169525a40e207d52c2",
@@ -0,0 +1 @@
1
+ bb33b2a423bd39ff4c9b62f929b7b19653779f0a
@@ -0,0 +1 @@
1
+ e2e5ddebc4739e29b6a0a2490b66f62c035b4c90513828665f499129a403e5ce
@@ -0,0 +1 @@
1
+ 5c40773634772fa4a4c2351fb536c084383caf1eedec9b538b6bc93586964d9f64a0b4830b829fd99483eba76ad2c67757adbbce39dff40ef277ec883eb8b1d3
@@ -9,7 +9,7 @@
9
9
  <modelVersion>4.0.0</modelVersion>
10
10
  <groupId>expo.modules.ui</groupId>
11
11
  <artifactId>expo.modules.ui</artifactId>
12
- <version>58.0.0</version>
12
+ <version>58.0.1</version>
13
13
  <packaging>aar</packaging>
14
14
  <name>expo.modules.ui</name>
15
15
  <url>https://github.com/expo/expo</url>
@@ -0,0 +1 @@
1
+ 4c38eb3e34223e6d9091aea17e5e351b0b478a99
@@ -0,0 +1 @@
1
+ 306e2675bfd0ba09e8156499f87079ae52a242e297b094d1d29ca058a8bb254b
@@ -0,0 +1 @@
1
+ f6e3b59b8caf48640be922818917d28d85e20da868e4dbf377389e62483073b93b013720c1a2267400abbf38288f2912d409a135d4dc1d7dc4bd0009947cce05
@@ -3,11 +3,11 @@
3
3
  <groupId>expo.modules.ui</groupId>
4
4
  <artifactId>expo.modules.ui</artifactId>
5
5
  <versioning>
6
- <latest>58.0.0</latest>
7
- <release>58.0.0</release>
6
+ <latest>58.0.1</latest>
7
+ <release>58.0.1</release>
8
8
  <versions>
9
- <version>58.0.0</version>
9
+ <version>58.0.1</version>
10
10
  </versions>
11
- <lastUpdated>20260910192012</lastUpdated>
11
+ <lastUpdated>20260914150056</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- aa1c6e7ec7c7463dee9f9fba9aabe6a8
1
+ eb722f5ae70ad3ee64f29cb240354616
@@ -1 +1 @@
1
- 823aeec60be8e25e8cff8f331d66984d3a2ea517
1
+ 56142e23a77a9066fd7c989581633406a68e0cc8
@@ -1 +1 @@
1
- fe9c8a01f45f367ea994344f942f70d9747c9e61fba2652200d6b2f61a6e5fe1
1
+ fcb1592cf547a24c5204afdbfbd9269826916881acb69e0882a865c18ecad91e
@@ -1 +1 @@
1
- 9e00e26460cfb5e9a9ba44adfc4a5c538b4110597f1045ad788e9801d1394c071578239e3b9e819fb189f8fd900dfb805b2d643b4a8946c838e343dcba063aab
1
+ f804a0d6f6328c9f2f60e640becd1362a0be3b2445d0be14c73b7414c6f52d2a8db6dca71b8b37c9549d53e37ae0a00b6815162f94e21294e890a0c7594e9762
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/ui",
3
- "version": "58.0.0",
3
+ "version": "58.0.1",
4
4
  "description": "A collection of UI components",
5
5
  "keywords": [
6
6
  "Jetpack Compose",
@@ -171,7 +171,7 @@
171
171
  "optional": true
172
172
  }
173
173
  },
174
- "gitHead": "c543a7181fc32e14f42d89550087b80ac5c490f2",
174
+ "gitHead": "e4b50c311af4e076b49a532ba2dca72546783e46",
175
175
  "scripts": {
176
176
  "precompile-ios": "et prebuild-package-for-publish",
177
177
  "build": "pnpm run build:lib && pnpm run build:plugin",
@@ -0,0 +1,39 @@
1
+ import { type ReactNode } from 'react';
2
+
3
+ import { Slot } from '../SlotView';
4
+
5
+ export interface NavigationDestinationProps {
6
+ /**
7
+ * The `NavigationLink` value this destination is presented for.
8
+ */
9
+ value: string;
10
+ /**
11
+ * The view pushed onto the stack for `value`.
12
+ */
13
+ children: ReactNode;
14
+ }
15
+
16
+ /**
17
+ * Associates a destination view with a `NavigationLink` value, matching SwiftUI's
18
+ * `navigationDestination(for:destination:)`. It must be a direct child of the `NavigationStack`,
19
+ * however deeply the link that pushes it is nested inside that stack.
20
+ *
21
+ * Keep it mounted so the pushed screen already carries its `navigationTitle` when the slide
22
+ * starts, or render one for each value on the stack's `path` to build screens on demand.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * <NavigationDestination value="settings">
27
+ * <SettingsScreen />
28
+ * </NavigationDestination>
29
+ * ```
30
+ *
31
+ * @platform ios
32
+ */
33
+ export function NavigationDestination(props: NavigationDestinationProps) {
34
+ return (
35
+ <Slot name="destination" extraProps={{ value: props.value }}>
36
+ {props.children}
37
+ </Slot>
38
+ );
39
+ }
@@ -0,0 +1,51 @@
1
+ import { requireNativeView } from 'expo';
2
+ import { type ComponentType, type ReactNode } from 'react';
3
+
4
+ import { createViewModifierEventListener } from '../modifiers/utils';
5
+ import { type CommonViewModifierProps } from '../types';
6
+
7
+ export interface NavigationLinkProps extends CommonViewModifierProps {
8
+ /**
9
+ * The value to append to the enclosing `NavigationStack`'s path when the link is tapped. The
10
+ * stack presents the `NavigationDestination` whose `value` matches.
11
+ */
12
+ value: string;
13
+ /**
14
+ * A view that describes the link.
15
+ */
16
+ children: ReactNode;
17
+ }
18
+
19
+ const NavigationLinkNativeView: ComponentType<NavigationLinkProps> = requireNativeView(
20
+ 'ExpoUI',
21
+ 'NavigationLinkView'
22
+ );
23
+
24
+ /**
25
+ * A view that controls a navigation presentation. In a `List` it renders as a row with a
26
+ * disclosure chevron, and tapping it pushes the matching `NavigationDestination`.
27
+ *
28
+ * The link has to be inside the `NavigationStack` itself. Content presented from the stack, such
29
+ * as a `BottomSheet` or a `Popover`, is its own presentation context and does not reach the
30
+ * stack's destinations, so give that content its own `NavigationStack`.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * <NavigationLink value="settings">
35
+ * <Text>Settings</Text>
36
+ * </NavigationLink>
37
+ * ```
38
+ *
39
+ * @platform ios
40
+ */
41
+ export function NavigationLink(props: NavigationLinkProps) {
42
+ const { modifiers, children, ...restProps } = props;
43
+ return (
44
+ <NavigationLinkNativeView
45
+ modifiers={modifiers}
46
+ {...(modifiers ? createViewModifierEventListener(modifiers) : undefined)}
47
+ {...restProps}>
48
+ {children}
49
+ </NavigationLinkNativeView>
50
+ );
51
+ }
@@ -1,16 +1,36 @@
1
1
  import { requireNativeView } from 'expo';
2
+ import { type ComponentType, type ReactNode } from 'react';
3
+ import { type NativeSyntheticEvent } from 'react-native';
2
4
 
3
5
  import { createViewModifierEventListener } from '../modifiers/utils';
4
6
  import { type CommonViewModifierProps } from '../types';
5
7
 
6
8
  export interface NavigationStackProps extends CommonViewModifierProps {
7
9
  /**
8
- * The root view of the stack. It is displayed inside a navigation bar.
10
+ * The root view of the stack, and the `NavigationDestination` views the stack can push. It is
11
+ * displayed inside a navigation bar.
9
12
  */
10
- children: React.ReactNode;
13
+ children: ReactNode;
14
+ /**
15
+ * The values of the views pushed on top of the root view, in the order they were pushed.
16
+ * Leave it undefined to let the stack manage its own path.
17
+ */
18
+ path?: string[];
19
+ /**
20
+ * Callback function that is called when the stack pushes or pops a view, for example when a
21
+ * `NavigationLink` is tapped or the user swipes back. Gets called with the new path.
22
+ *
23
+ * When `path` is set, the stack is controlled: a push takes effect once the new path comes back
24
+ * through this prop.
25
+ */
26
+ onPathChange?: (path: string[]) => void;
11
27
  }
12
28
 
13
- const NavigationStackNativeView: React.ComponentType<NavigationStackProps> = requireNativeView(
29
+ type NativeNavigationStackProps = Omit<NavigationStackProps, 'onPathChange'> & {
30
+ onPathChange?: (event: NativeSyntheticEvent<{ path: string[] }>) => void;
31
+ };
32
+
33
+ const NavigationStackNativeView: ComponentType<NativeNavigationStackProps> = requireNativeView(
14
34
  'ExpoUI',
15
35
  'NavigationStackView'
16
36
  );
@@ -18,15 +38,38 @@ const NavigationStackNativeView: React.ComponentType<NavigationStackProps> = req
18
38
  /**
19
39
  * A view that displays a root view and enables you to present additional views over the root view.
20
40
  *
41
+ * @example
42
+ * ```tsx
43
+ * const [path, setPath] = useState<string[]>([]);
44
+ *
45
+ * <NavigationStack path={path} onPathChange={setPath}>
46
+ * <List>
47
+ * <NavigationLink value="settings">
48
+ * <Text>Settings</Text>
49
+ * </NavigationLink>
50
+ * </List>
51
+ * <NavigationDestination value="settings">
52
+ * <SettingsScreen />
53
+ * </NavigationDestination>
54
+ * </NavigationStack>
55
+ * ```
56
+ *
21
57
  * @platform ios
22
58
  */
23
59
  export function NavigationStack(props: NavigationStackProps) {
24
- const { modifiers, ...restProps } = props;
60
+ const { modifiers, onPathChange, ...restProps } = props;
25
61
  return (
26
62
  <NavigationStackNativeView
27
63
  modifiers={modifiers}
28
64
  {...(modifiers ? createViewModifierEventListener(modifiers) : undefined)}
29
65
  {...restProps}
66
+ onPathChange={
67
+ onPathChange
68
+ ? ({ nativeEvent: { path } }) => {
69
+ onPathChange(path);
70
+ }
71
+ : undefined
72
+ }
30
73
  />
31
74
  );
32
75
  }
@@ -63,7 +63,7 @@ export type { TabProps } from './Tab';
63
63
  * `value` prop, which is used for selection.
64
64
  *
65
65
  * For routed bottom-tab navigation across full-screen routes, prefer
66
- * `expo-router/unstable-native-tabs`.
66
+ * `expo-router/native-tabs`.
67
67
  *
68
68
  * @platform ios
69
69
  */
@@ -25,6 +25,8 @@ export * from './ZStack';
25
25
  export * from './Group';
26
26
  export * from './List';
27
27
  export * from './Menu';
28
+ export * from './NavigationDestination';
29
+ export * from './NavigationLink';
28
30
  export * from './NavigationStack';
29
31
  export * from './Picker';
30
32
  export * from './ProgressView';
@@ -1 +0,0 @@
1
- ed65109583c15437f79af7ec544af70394d5c279
@@ -1 +0,0 @@
1
- 1b3593c9dc1b7597f685374585d404d94b6d7119969c24868365b4329070d8c6
@@ -1 +0,0 @@
1
- 5f309c672c127bc19ca3ed55b8ef97b8fefc3acd6c9eced30b762cf70ddd94f2f3e8f5a1e363d56873ad01ae1b4206295358bdcde4c061fedf50490fd937f520
@@ -1 +0,0 @@
1
- 288729551bfb3ef08d3f22eb6eecdc58
@@ -1 +0,0 @@
1
- 2182f9ea357a66c6e04f5eef6d1423b2ce1f1db6
@@ -1 +0,0 @@
1
- 4d0f823e8a2a57e85d8d6ae9e03f585fe20bd63cb53eee6a5bd07e252c93b1dc
@@ -1 +0,0 @@
1
- 4ced04902194b6af012bc167a257864a5b8aa859a7fd6207a5ec1f3c22d7f7d79d0212778c93e7b10c93f8c4b632ab4d731b7bcfcc1cb9f09b752bb218eb2f6b