expo-router 5.2.0-canary-20250613-b29d676-2 → 5.2.0-canary-20250630-547cd82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/ExpoRoot.d.ts.map +1 -1
- package/build/ExpoRoot.js +13 -7
- package/build/ExpoRoot.js.map +1 -1
- package/build/exports.d.ts +2 -0
- package/build/exports.d.ts.map +1 -1
- package/build/exports.js +5 -1
- package/build/exports.js.map +1 -1
- package/build/fork/getStateFromPath-forks.d.ts.map +1 -1
- package/build/fork/getStateFromPath-forks.js +4 -1
- package/build/fork/getStateFromPath-forks.js.map +1 -1
- package/build/getRoutes.d.ts +1 -1
- package/build/getRoutes.d.ts.map +1 -1
- package/build/getRoutes.js +14 -6
- package/build/getRoutes.js.map +1 -1
- package/build/getRoutesCore.d.ts +7 -2
- package/build/getRoutesCore.d.ts.map +1 -1
- package/build/getRoutesCore.js +86 -58
- package/build/getRoutesCore.js.map +1 -1
- package/build/getRoutesRedirects.d.ts +2 -2
- package/build/getRoutesRedirects.d.ts.map +1 -1
- package/build/getRoutesRedirects.js +18 -24
- package/build/getRoutesRedirects.js.map +1 -1
- package/build/getRoutesSSR.d.ts +1 -1
- package/build/getRoutesSSR.d.ts.map +1 -1
- package/build/getRoutesSSR.js +2 -3
- package/build/getRoutesSSR.js.map +1 -1
- package/build/global-state/router-store.d.ts +52 -1
- package/build/global-state/router-store.d.ts.map +1 -1
- package/build/global-state/router-store.js +22 -1
- package/build/global-state/router-store.js.map +1 -1
- package/build/global-state/routing.d.ts +1 -0
- package/build/global-state/routing.d.ts.map +1 -1
- package/build/global-state/routing.js +3 -2
- package/build/global-state/routing.js.map +1 -1
- package/build/global-state/storeContext.d.ts +50 -0
- package/build/global-state/storeContext.d.ts.map +1 -1
- package/build/hooks.d.ts.map +1 -1
- package/build/hooks.js +33 -1
- package/build/hooks.js.map +1 -1
- package/build/layouts/StackClient.d.ts.map +1 -1
- package/build/layouts/StackClient.js +39 -2
- package/build/layouts/StackClient.js.map +1 -1
- package/build/link/BaseExpoRouterLink.d.ts +3 -0
- package/build/link/BaseExpoRouterLink.d.ts.map +1 -0
- package/build/link/BaseExpoRouterLink.js +63 -0
- package/build/link/BaseExpoRouterLink.js.map +1 -0
- package/build/link/ExpoLink.d.ts +3 -0
- package/build/link/ExpoLink.d.ts.map +1 -0
- package/build/link/ExpoLink.js +23 -0
- package/build/link/ExpoLink.js.map +1 -0
- package/build/link/Link.d.ts +63 -78
- package/build/link/Link.d.ts.map +1 -1
- package/build/link/Link.js +81 -99
- package/build/link/Link.js.map +1 -1
- package/build/link/LinkWithPreview.d.ts +36 -0
- package/build/link/LinkWithPreview.d.ts.map +1 -0
- package/build/link/LinkWithPreview.js +187 -0
- package/build/link/LinkWithPreview.js.map +1 -0
- package/build/link/Redirect.d.ts +58 -0
- package/build/link/Redirect.d.ts.map +1 -0
- package/build/link/Redirect.js +46 -0
- package/build/link/Redirect.js.map +1 -0
- package/build/link/preview/HrefPreview.d.ts +5 -0
- package/build/link/preview/HrefPreview.d.ts.map +1 -0
- package/build/link/preview/HrefPreview.js +99 -0
- package/build/link/preview/HrefPreview.js.map +1 -0
- package/build/link/preview/LinkPreviewContext.d.ts +7 -0
- package/build/link/preview/LinkPreviewContext.d.ts.map +1 -0
- package/build/link/preview/LinkPreviewContext.js +21 -0
- package/build/link/preview/LinkPreviewContext.js.map +1 -0
- package/build/link/preview/PreviewRouteContext.d.ts +22 -0
- package/build/link/preview/PreviewRouteContext.d.ts.map +1 -0
- package/build/link/preview/PreviewRouteContext.js +28 -0
- package/build/link/preview/PreviewRouteContext.js.map +1 -0
- package/build/link/preview/native.d.ts +31 -0
- package/build/link/preview/native.d.ts.map +1 -0
- package/build/link/preview/native.js +53 -0
- package/build/link/preview/native.js.map +1 -0
- package/build/link/preview/useNextScreenId.d.ts +3 -0
- package/build/link/preview/useNextScreenId.d.ts.map +1 -0
- package/build/link/preview/useNextScreenId.js +42 -0
- package/build/link/preview/useNextScreenId.js.map +1 -0
- package/build/link/useLinkHooks.d.ts +3 -2
- package/build/link/useLinkHooks.d.ts.map +1 -1
- package/build/link/useLinkHooks.js +1 -0
- package/build/link/useLinkHooks.js.map +1 -1
- package/build/modal/Modal.d.ts +82 -0
- package/build/modal/Modal.d.ts.map +1 -0
- package/build/modal/Modal.js +82 -0
- package/build/modal/Modal.js.map +1 -0
- package/build/modal/ModalComponent.d.ts +7 -0
- package/build/modal/ModalComponent.d.ts.map +1 -0
- package/build/modal/ModalComponent.js +10 -0
- package/build/modal/ModalComponent.js.map +1 -0
- package/build/modal/ModalContext.d.ts +22 -0
- package/build/modal/ModalContext.d.ts.map +1 -0
- package/build/modal/ModalContext.js +150 -0
- package/build/modal/ModalContext.js.map +1 -0
- package/build/typed-routes/generate.js +1 -1
- package/build/typed-routes/generate.js.map +1 -1
- package/build/useFocusEffect.d.ts.map +1 -1
- package/build/useFocusEffect.js +5 -3
- package/build/useFocusEffect.js.map +1 -1
- package/build/useScreens.js +1 -1
- package/build/useScreens.js.map +1 -1
- package/build/utils/stack.d.ts +5 -0
- package/build/utils/stack.d.ts.map +1 -0
- package/build/utils/stack.js +10 -0
- package/build/utils/stack.js.map +1 -0
- package/build/views/Screen.d.ts.map +1 -1
- package/build/views/Screen.js +13 -40
- package/build/views/Screen.js.map +1 -1
- package/build/views/Unmatched.d.ts.map +1 -1
- package/build/views/Unmatched.js +9 -3
- package/build/views/Unmatched.js.map +1 -1
- package/build/views/useSafeLayoutEffect.d.ts +3 -0
- package/build/views/useSafeLayoutEffect.d.ts.map +1 -0
- package/build/views/useSafeLayoutEffect.js +6 -0
- package/build/views/useSafeLayoutEffect.js.map +1 -0
- package/expo-module.config.json +1 -1
- package/ios/ExpoHead.podspec +1 -1
- package/ios/LinkPreview/LinkPreviewNativeActionView.swift +12 -0
- package/ios/LinkPreview/LinkPreviewNativeModule.swift +50 -0
- package/ios/LinkPreview/LinkPreviewNativeNavigation.h +18 -0
- package/ios/LinkPreview/LinkPreviewNativeNavigation.mm +108 -0
- package/ios/LinkPreview/LinkPreviewNativePreviewView.swift +15 -0
- package/ios/LinkPreview/LinkPreviewNativeTriggerView.swift +9 -0
- package/ios/LinkPreview/LinkPreviewNativeView.swift +193 -0
- package/package.json +6 -6
- package/plugin/options.json +29 -1
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
|
|
3
|
+
class NativeLinkPreviewView: ExpoView, UIContextMenuInteractionDelegate {
|
|
4
|
+
private var trigger: NativeLinkPreviewTrigger?
|
|
5
|
+
private var preview: NativeLinkPreviewContentView?
|
|
6
|
+
private var interaction: UIContextMenuInteraction?
|
|
7
|
+
private var nextScreenId: String?
|
|
8
|
+
private var actions: [LinkPreviewNativeActionView] = []
|
|
9
|
+
|
|
10
|
+
private let linkPreviewNativeNavigation = LinkPreviewNativeNavigation()
|
|
11
|
+
|
|
12
|
+
let onPreviewTapped = EventDispatcher()
|
|
13
|
+
let onWillPreviewOpen = EventDispatcher()
|
|
14
|
+
let onDidPreviewOpen = EventDispatcher()
|
|
15
|
+
let onPreviewWillClose = EventDispatcher()
|
|
16
|
+
let onPreviewDidClose = EventDispatcher()
|
|
17
|
+
let onActionSelected = EventDispatcher()
|
|
18
|
+
|
|
19
|
+
required init(appContext: AppContext? = nil) {
|
|
20
|
+
super.init(appContext: appContext)
|
|
21
|
+
self.interaction = UIContextMenuInteraction(delegate: self)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// MARK: - Props
|
|
25
|
+
|
|
26
|
+
func setNextScreenId(_ screenId: String) {
|
|
27
|
+
self.nextScreenId = screenId
|
|
28
|
+
linkPreviewNativeNavigation.updatePreloadedView(screenId, with: self)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// MARK: - Children
|
|
32
|
+
|
|
33
|
+
override func mountChildComponentView(_ childComponentView: UIView, index: Int) {
|
|
34
|
+
if let triggerView = childComponentView as? NativeLinkPreviewTrigger {
|
|
35
|
+
trigger = triggerView
|
|
36
|
+
if let interaction = self.interaction, self.preview != nil {
|
|
37
|
+
trigger?.addInteraction(interaction)
|
|
38
|
+
}
|
|
39
|
+
super.mountChildComponentView(childComponentView, index: index)
|
|
40
|
+
} else if let previewView = childComponentView as? NativeLinkPreviewContentView {
|
|
41
|
+
preview = previewView
|
|
42
|
+
if let interaction = self.interaction, let trigger = self.trigger {
|
|
43
|
+
trigger.addInteraction(interaction)
|
|
44
|
+
}
|
|
45
|
+
} else if let actionView = childComponentView as? LinkPreviewNativeActionView {
|
|
46
|
+
actions.append(actionView)
|
|
47
|
+
} else {
|
|
48
|
+
print(
|
|
49
|
+
"ExpoRouter: Unknown child component view (\(childComponentView)) mounted to NativeLinkPreviewView"
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
override func unmountChildComponentView(_ child: UIView, index: Int) {
|
|
55
|
+
if child is NativeLinkPreviewTrigger {
|
|
56
|
+
if let interaction = self.interaction {
|
|
57
|
+
trigger?.removeInteraction(interaction)
|
|
58
|
+
}
|
|
59
|
+
trigger = nil
|
|
60
|
+
super.unmountChildComponentView(child, index: index)
|
|
61
|
+
} else if child is NativeLinkPreviewContentView {
|
|
62
|
+
preview = nil
|
|
63
|
+
if let interaction = self.interaction {
|
|
64
|
+
trigger?.removeInteraction(interaction)
|
|
65
|
+
}
|
|
66
|
+
} else if let actionView = child as? LinkPreviewNativeActionView {
|
|
67
|
+
actions.removeAll(where: {
|
|
68
|
+
$0 == actionView
|
|
69
|
+
})
|
|
70
|
+
} else {
|
|
71
|
+
print(
|
|
72
|
+
"ExpoRouter: Unknown child component view (\(child)) unmounted from NativeLinkPreviewView")
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// MARK: - UIContextMenuInteractionDelegate
|
|
77
|
+
|
|
78
|
+
func contextMenuInteraction(
|
|
79
|
+
_ interaction: UIContextMenuInteraction,
|
|
80
|
+
configurationForMenuAtLocation location: CGPoint
|
|
81
|
+
) -> UIContextMenuConfiguration? {
|
|
82
|
+
onWillPreviewOpen()
|
|
83
|
+
return UIContextMenuConfiguration(
|
|
84
|
+
identifier: nil,
|
|
85
|
+
previewProvider: { [weak self] in
|
|
86
|
+
self?.createPreviewViewController()
|
|
87
|
+
},
|
|
88
|
+
actionProvider: { [weak self] _ in
|
|
89
|
+
self?.createContextMenu()
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
func contextMenuInteraction(
|
|
94
|
+
_ interaction: UIContextMenuInteraction,
|
|
95
|
+
configuration: UIContextMenuConfiguration,
|
|
96
|
+
highlightPreviewForItemWithIdentifier identifier: any NSCopying
|
|
97
|
+
) -> UITargetedPreview? {
|
|
98
|
+
if let trigger = self.trigger {
|
|
99
|
+
let target = UIPreviewTarget(container: self, center: trigger.center)
|
|
100
|
+
|
|
101
|
+
let parameters = UIPreviewParameters()
|
|
102
|
+
parameters.backgroundColor = .clear
|
|
103
|
+
parameters.shadowPath = UIBezierPath(roundedRect: trigger.bounds, cornerRadius: 10)
|
|
104
|
+
|
|
105
|
+
return UITargetedPreview(view: trigger, parameters: parameters, target: target)
|
|
106
|
+
}
|
|
107
|
+
return nil
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
func contextMenuInteraction(
|
|
111
|
+
_ interaction: UIContextMenuInteraction,
|
|
112
|
+
willDisplayMenuFor configuration: UIContextMenuConfiguration,
|
|
113
|
+
animator: UIContextMenuInteractionAnimating?
|
|
114
|
+
) {
|
|
115
|
+
// This happens when preview starts to become visible.
|
|
116
|
+
// It is not yet fully extended at this moment though
|
|
117
|
+
self.onDidPreviewOpen()
|
|
118
|
+
animator?.addCompletion {
|
|
119
|
+
// This happens around a second after the preview is opened and thus gives us no real value
|
|
120
|
+
// User could have already interacted with preview beforehand
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
func contextMenuInteraction(
|
|
125
|
+
_ interaction: UIContextMenuInteraction,
|
|
126
|
+
willEndFor configuration: UIContextMenuConfiguration,
|
|
127
|
+
animator: UIContextMenuInteractionAnimating?
|
|
128
|
+
) {
|
|
129
|
+
onPreviewWillClose()
|
|
130
|
+
animator?.addCompletion {
|
|
131
|
+
self.onPreviewDidClose()
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func contextMenuInteraction(
|
|
136
|
+
_ interaction: UIContextMenuInteraction,
|
|
137
|
+
willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration,
|
|
138
|
+
animator: UIContextMenuInteractionCommitAnimating
|
|
139
|
+
) {
|
|
140
|
+
linkPreviewNativeNavigation.pushPreloadedView()
|
|
141
|
+
animator.addCompletion { [weak self] in
|
|
142
|
+
self?.onPreviewTapped()
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// MARK: - Context Menu Helpers
|
|
147
|
+
|
|
148
|
+
private func createPreviewViewController() -> UIViewController {
|
|
149
|
+
guard let preview = preview else {
|
|
150
|
+
return UIViewController()
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let vc = PreviewViewController(linkPreviewNativePreview: preview)
|
|
154
|
+
vc.view.addSubview(preview)
|
|
155
|
+
let preferredSize = preview.preferredContentSize
|
|
156
|
+
vc.preferredContentSize.width = preferredSize.width
|
|
157
|
+
vc.preferredContentSize.height = preferredSize.height
|
|
158
|
+
return vc
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private func createContextMenu() -> UIMenu {
|
|
162
|
+
let uiActions = actions.map { action in
|
|
163
|
+
return UIAction(
|
|
164
|
+
title: action.title
|
|
165
|
+
) { _ in
|
|
166
|
+
self.onActionSelected([
|
|
167
|
+
"id": action.id
|
|
168
|
+
])
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return UIMenu(title: "", children: uiActions)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
class PreviewViewController: UIViewController {
|
|
177
|
+
private let linkPreviewNativePreview: NativeLinkPreviewContentView
|
|
178
|
+
init(linkPreviewNativePreview: NativeLinkPreviewContentView) {
|
|
179
|
+
self.linkPreviewNativePreview = linkPreviewNativePreview
|
|
180
|
+
super.init(nibName: nil, bundle: nil)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@available(*, unavailable)
|
|
184
|
+
required init?(coder: NSCoder) {
|
|
185
|
+
fatalError("init(coder:) has not been implemented")
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// TODO: Consider using setViewSize from ExpoFabricView
|
|
189
|
+
override func viewDidAppear(_ animated: Bool) {
|
|
190
|
+
super.viewDidAppear(animated)
|
|
191
|
+
linkPreviewNativePreview.setInitialSize(bounds: self.view.bounds)
|
|
192
|
+
}
|
|
193
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-router",
|
|
3
|
-
"version": "5.2.0-canary-
|
|
3
|
+
"version": "5.2.0-canary-20250630-547cd82",
|
|
4
4
|
"description": "Expo Router is a file-based router for React Native and web applications.",
|
|
5
5
|
"author": "650 Industries, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
],
|
|
77
77
|
"peerDependencies": {
|
|
78
78
|
"@react-navigation/drawer": "^7.3.9",
|
|
79
|
-
"expo": "54.0.0-canary-
|
|
80
|
-
"expo-constants": "17.1.7-canary-
|
|
81
|
-
"expo-linking": "7.1.6-canary-
|
|
79
|
+
"expo": "54.0.0-canary-20250630-547cd82",
|
|
80
|
+
"expo-constants": "17.1.7-canary-20250630-547cd82",
|
|
81
|
+
"expo-linking": "7.1.6-canary-20250630-547cd82",
|
|
82
82
|
"react-native-reanimated": "*",
|
|
83
83
|
"react-native-safe-area-context": "*",
|
|
84
84
|
"react-native-screens": "*"
|
|
@@ -105,8 +105,8 @@
|
|
|
105
105
|
"tsd": "^0.28.1"
|
|
106
106
|
},
|
|
107
107
|
"dependencies": {
|
|
108
|
-
"@expo/metro-runtime": "
|
|
109
|
-
"@expo/server": "0.6.
|
|
108
|
+
"@expo/metro-runtime": "6.0.0-canary-20250630-547cd82",
|
|
109
|
+
"@expo/server": "0.6.4-canary-20250630-547cd82",
|
|
110
110
|
"@radix-ui/react-slot": "1.2.0",
|
|
111
111
|
"@react-navigation/bottom-tabs": "^7.3.10",
|
|
112
112
|
"@react-navigation/native": "^7.1.6",
|
package/plugin/options.json
CHANGED
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"description": "The target file path that this route should redirect to",
|
|
92
92
|
"type": "string"
|
|
93
93
|
},
|
|
94
|
-
"
|
|
94
|
+
"permanent": {
|
|
95
95
|
"description": "Whether the redirect is temporary or permanent. Defaults to `false`.",
|
|
96
96
|
"type": "boolean",
|
|
97
97
|
"default": false
|
|
@@ -107,6 +107,34 @@
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
|
+
},
|
|
111
|
+
"rewrites": {
|
|
112
|
+
"description": "Enable static rewrites",
|
|
113
|
+
"type": "array",
|
|
114
|
+
"uniqueItems": true,
|
|
115
|
+
"items": {
|
|
116
|
+
"type": "object",
|
|
117
|
+
"required": ["source", "destination"],
|
|
118
|
+
"properties": {
|
|
119
|
+
"source": {
|
|
120
|
+
"description": "The previous file path that should be rewritten",
|
|
121
|
+
"type": "string"
|
|
122
|
+
},
|
|
123
|
+
"destination": {
|
|
124
|
+
"description": "The target file path that this route should rewrite",
|
|
125
|
+
"type": "string"
|
|
126
|
+
},
|
|
127
|
+
"methods": {
|
|
128
|
+
"description": "HTTP methods that should be rewritten. Omit to rewrite all methods.",
|
|
129
|
+
"type": "array",
|
|
130
|
+
"uniqueItems": true,
|
|
131
|
+
"items": {
|
|
132
|
+
"type": "string",
|
|
133
|
+
"enum": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"]
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
110
138
|
}
|
|
111
139
|
},
|
|
112
140
|
"additionalProperties": false
|