@react-navigation/native 8.0.0-alpha.27 → 8.0.0-alpha.29

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 (99) hide show
  1. package/ios/ReactNavigationSFSymbolView.mm +22 -9
  2. package/ios/ReactNavigationSFSymbolView.swift +351 -65
  3. package/lib/module/__stubs__/createStackNavigator.js +9 -1
  4. package/lib/module/__stubs__/createStackNavigator.js.map +1 -1
  5. package/lib/module/__stubs__/window.js +3 -0
  6. package/lib/module/__stubs__/window.js.map +1 -1
  7. package/lib/module/createMemoryHistory.js +7 -3
  8. package/lib/module/createMemoryHistory.js.map +1 -1
  9. package/lib/module/createStandardNavigationFactories.js +99 -0
  10. package/lib/module/createStandardNavigationFactories.js.map +1 -0
  11. package/lib/module/extractPathFromURL.js +1 -1
  12. package/lib/module/extractPathFromURL.js.map +1 -1
  13. package/lib/module/getStateFromHref.js +2 -2
  14. package/lib/module/getStateFromHref.js.map +1 -1
  15. package/lib/module/index.js +1 -0
  16. package/lib/module/index.js.map +1 -1
  17. package/lib/module/native/SFSymbol.ios.js +35 -14
  18. package/lib/module/native/SFSymbol.ios.js.map +1 -1
  19. package/lib/module/native/SFSymbolViewNativeComponent.ts +22 -9
  20. package/lib/module/useLinkBuilder.js +4 -3
  21. package/lib/module/useLinkBuilder.js.map +1 -1
  22. package/lib/module/useLinking.js +11 -2
  23. package/lib/module/useLinking.js.map +1 -1
  24. package/lib/module/useLinking.native.js +5 -5
  25. package/lib/module/useLinking.native.js.map +1 -1
  26. package/lib/module/useMemoArray.js +25 -0
  27. package/lib/module/useMemoArray.js.map +1 -0
  28. package/lib/module/useScrollToTop.js +2 -1
  29. package/lib/module/useScrollToTop.js.map +1 -1
  30. package/lib/typescript/src/Link.d.ts +1 -1
  31. package/lib/typescript/src/Link.d.ts.map +1 -1
  32. package/lib/typescript/src/LinkingContext.d.ts +1 -1
  33. package/lib/typescript/src/LinkingContext.d.ts.map +1 -1
  34. package/lib/typescript/src/LocaleDirContext.d.ts +1 -1
  35. package/lib/typescript/src/LocaleDirContext.d.ts.map +1 -1
  36. package/lib/typescript/src/NavigationContainer.d.ts +2 -2
  37. package/lib/typescript/src/NavigationContainer.d.ts.map +1 -1
  38. package/lib/typescript/src/__stubs__/createStackNavigator.d.ts +1 -1
  39. package/lib/typescript/src/__stubs__/createStackNavigator.d.ts.map +1 -1
  40. package/lib/typescript/src/__stubs__/window.d.ts.map +1 -1
  41. package/lib/typescript/src/createMemoryHistory.d.ts +1 -1
  42. package/lib/typescript/src/createMemoryHistory.d.ts.map +1 -1
  43. package/lib/typescript/src/createStandardNavigationFactories.d.ts +31 -0
  44. package/lib/typescript/src/createStandardNavigationFactories.d.ts.map +1 -0
  45. package/lib/typescript/src/createStaticNavigation.d.ts +3 -3
  46. package/lib/typescript/src/createStaticNavigation.d.ts.map +1 -1
  47. package/lib/typescript/src/extractPathFromURL.d.ts +1 -1
  48. package/lib/typescript/src/extractPathFromURL.d.ts.map +1 -1
  49. package/lib/typescript/src/getStateFromHref.d.ts +3 -3
  50. package/lib/typescript/src/getStateFromHref.d.ts.map +1 -1
  51. package/lib/typescript/src/index.d.ts +15 -14
  52. package/lib/typescript/src/index.d.ts.map +1 -1
  53. package/lib/typescript/src/native/CornerInset.d.ts +1 -1
  54. package/lib/typescript/src/native/CornerInset.d.ts.map +1 -1
  55. package/lib/typescript/src/native/CornerInset.ios.d.ts +2 -2
  56. package/lib/typescript/src/native/CornerInset.ios.d.ts.map +1 -1
  57. package/lib/typescript/src/native/MaterialSymbol.android.d.ts +1 -1
  58. package/lib/typescript/src/native/MaterialSymbol.android.d.ts.map +1 -1
  59. package/lib/typescript/src/native/MaterialSymbol.d.ts +1 -1
  60. package/lib/typescript/src/native/MaterialSymbol.d.ts.map +1 -1
  61. package/lib/typescript/src/native/SFSymbol.d.ts +1 -1
  62. package/lib/typescript/src/native/SFSymbol.d.ts.map +1 -1
  63. package/lib/typescript/src/native/SFSymbol.ios.d.ts +2 -2
  64. package/lib/typescript/src/native/SFSymbol.ios.d.ts.map +1 -1
  65. package/lib/typescript/src/native/SFSymbolViewNativeComponent.d.ts +22 -9
  66. package/lib/typescript/src/native/SFSymbolViewNativeComponent.d.ts.map +1 -1
  67. package/lib/typescript/src/native/types.d.ts +227 -31
  68. package/lib/typescript/src/native/types.d.ts.map +1 -1
  69. package/lib/typescript/src/server/index.d.ts +1 -1
  70. package/lib/typescript/src/server/index.d.ts.map +1 -1
  71. package/lib/typescript/src/theming/MaterialTheme.d.ts +1 -1
  72. package/lib/typescript/src/theming/MaterialTheme.d.ts.map +1 -1
  73. package/lib/typescript/src/useDocumentTitle.d.ts +1 -1
  74. package/lib/typescript/src/useDocumentTitle.d.ts.map +1 -1
  75. package/lib/typescript/src/useLinkBuilder.d.ts.map +1 -1
  76. package/lib/typescript/src/useLinking.d.ts +6 -6
  77. package/lib/typescript/src/useLinking.d.ts.map +1 -1
  78. package/lib/typescript/src/useLinking.native.d.ts +10 -10
  79. package/lib/typescript/src/useLinking.native.d.ts.map +1 -1
  80. package/lib/typescript/src/useLocale.d.ts +1 -1
  81. package/lib/typescript/src/useMemoArray.d.ts +2 -0
  82. package/lib/typescript/src/useMemoArray.d.ts.map +1 -0
  83. package/lib/typescript/src/useScrollToTop.d.ts.map +1 -1
  84. package/package.json +13 -12
  85. package/src/__stubs__/createStackNavigator.tsx +13 -5
  86. package/src/__stubs__/window.tsx +5 -0
  87. package/src/createMemoryHistory.tsx +10 -3
  88. package/src/createStandardNavigationFactories.tsx +218 -0
  89. package/src/extractPathFromURL.tsx +1 -1
  90. package/src/getStateFromHref.tsx +8 -3
  91. package/src/index.tsx +4 -0
  92. package/src/native/SFSymbol.ios.tsx +73 -14
  93. package/src/native/SFSymbolViewNativeComponent.ts +22 -9
  94. package/src/native/types.tsx +278 -32
  95. package/src/useLinkBuilder.tsx +4 -2
  96. package/src/useLinking.native.tsx +17 -10
  97. package/src/useLinking.tsx +19 -2
  98. package/src/useMemoArray.tsx +41 -0
  99. package/src/useScrollToTop.tsx +2 -1
@@ -47,15 +47,28 @@ static ReactNavigationSFSymbolViewImplProps *convertProps(const Props::Shared &p
47
47
  swiftProps.color = RCTUIColorFromSharedColor(viewProps.color);
48
48
  swiftProps.weight = viewProps.weight;
49
49
  swiftProps.scale = RCTNSStringFromString(viewProps.scale);
50
- swiftProps.mode = RCTNSStringFromString(viewProps.mode);
51
- swiftProps.animation = RCTNSStringFromString(viewProps.animation);
52
- swiftProps.animationRepeating = viewProps.animationRepeating;
53
- swiftProps.animationRepeatCount = viewProps.animationRepeatCount;
54
- swiftProps.animationSpeed = viewProps.animationSpeed;
55
- swiftProps.animationWholeSymbol = viewProps.animationWholeSymbol;
56
- swiftProps.animationDirection = RCTNSStringFromString(viewProps.animationDirection);
57
- swiftProps.animationReversing = viewProps.animationReversing;
58
- swiftProps.animationCumulative = viewProps.animationCumulative;
50
+ swiftProps.variableValue = viewProps.variableValue;
51
+ swiftProps.variableValueMode = RCTNSStringFromString(viewProps.variableValueMode);
52
+ swiftProps.colorRenderingMode = RCTNSStringFromString(viewProps.colorRenderingMode);
53
+ swiftProps.renderingMode = RCTNSStringFromString(viewProps.renderingMode);
54
+ swiftProps.effect = RCTNSStringFromString(viewProps.effect);
55
+ swiftProps.effectRepeat = RCTNSStringFromString(viewProps.effectRepeat);
56
+ swiftProps.effectRepeatCount = viewProps.effectRepeatCount;
57
+ swiftProps.effectRepeatDelay = viewProps.effectRepeatDelay;
58
+ swiftProps.effectSpeed = viewProps.effectSpeed;
59
+ swiftProps.effectScope = RCTNSStringFromString(viewProps.effectScope);
60
+ swiftProps.effectDirection = RCTNSStringFromString(viewProps.effectDirection);
61
+ swiftProps.effectVariant = RCTNSStringFromString(viewProps.effectVariant);
62
+ swiftProps.effectAngle = viewProps.effectAngle;
63
+ swiftProps.effectReversing = viewProps.effectReversing;
64
+ swiftProps.effectCumulative = viewProps.effectCumulative;
65
+ swiftProps.effectInactiveLayers = RCTNSStringFromString(viewProps.effectInactiveLayers);
66
+ swiftProps.effectDrawDirection = RCTNSStringFromString(viewProps.effectDrawDirection);
67
+ swiftProps.contentTransition = RCTNSStringFromString(viewProps.contentTransition);
68
+ swiftProps.contentTransitionSpeed = viewProps.contentTransitionSpeed;
69
+ swiftProps.contentTransitionVariant = RCTNSStringFromString(viewProps.contentTransitionVariant);
70
+ swiftProps.contentTransitionScope = RCTNSStringFromString(viewProps.contentTransitionScope);
71
+ swiftProps.contentTransitionMagic = viewProps.contentTransitionMagic;
59
72
 
60
73
  if (viewProps.colorPrimary) {
61
74
  swiftProps.colorPrimary = RCTUIColorFromSharedColor(viewProps.colorPrimary);
@@ -6,23 +6,35 @@ import UIKit
6
6
  public var color: UIColor = .black
7
7
  public var weight: Int = 0
8
8
  public var scale: String = "medium"
9
- public var mode: String = "monochrome"
9
+ public var renderingMode: String = "monochrome"
10
10
  public var colorPrimary: UIColor?
11
11
  public var colorSecondary: UIColor?
12
12
  public var colorTertiary: UIColor?
13
- public var animation: String = ""
14
- public var animationRepeating: Bool = false
15
- public var animationRepeatCount: Int = 0
16
- public var animationSpeed: CGFloat = 1
17
- public var animationWholeSymbol: Bool = false
18
- public var animationDirection: String = ""
19
- public var animationReversing: Bool = false
20
- public var animationCumulative: Bool = false
13
+ public var effect: String = ""
14
+ public var variableValue: CGFloat = -1
15
+ public var variableValueMode: String = "automatic"
16
+ public var colorRenderingMode: String = "automatic"
17
+ public var effectRepeat: String = ""
18
+ public var effectRepeatCount: Int = 0
19
+ public var effectRepeatDelay: CGFloat = 0
20
+ public var effectSpeed: CGFloat = 1
21
+ public var effectScope: String = ""
22
+ public var effectDirection: String = ""
23
+ public var effectVariant: String = ""
24
+ public var effectAngle: CGFloat = -1
25
+ public var effectReversing: Bool = false
26
+ public var effectCumulative: Bool = false
27
+ public var effectInactiveLayers: String = ""
28
+ public var effectDrawDirection: String = ""
29
+ public var contentTransition: String = ""
30
+ public var contentTransitionSpeed: CGFloat = 1
31
+ public var contentTransitionVariant: String = ""
32
+ public var contentTransitionScope: String = ""
33
+ public var contentTransitionMagic: Bool = false
21
34
  }
22
35
 
23
36
  @objc public class ReactNavigationSFSymbolViewImpl: UIView {
24
37
  private var imageView: UIImageView
25
- private var currentAnimation: String = ""
26
38
 
27
39
  override init(frame: CGRect) {
28
40
  imageView = UIImageView()
@@ -53,30 +65,55 @@ import UIKit
53
65
  props.size != oldProps.size ||
54
66
  props.weight != oldProps.weight ||
55
67
  props.scale != oldProps.scale ||
56
- props.mode != oldProps.mode ||
68
+ props.variableValue != oldProps.variableValue ||
69
+ props.variableValueMode != oldProps.variableValueMode ||
70
+ props.colorRenderingMode != oldProps.colorRenderingMode ||
71
+ props.renderingMode != oldProps.renderingMode ||
57
72
  props.colorPrimary != oldProps.colorPrimary ||
58
73
  props.colorSecondary != oldProps.colorSecondary ||
59
74
  props.colorTertiary != oldProps.colorTertiary
60
75
 
61
76
  if needsImageUpdate {
62
77
  if let name = props.name {
78
+ // Content transitions animate between symbol contents, so only run them
79
+ // when the symbol or its variable value changes and a previous image
80
+ // exists. Configuration changes and the first appearance set the image
81
+ // directly to match native behavior.
82
+ let shouldAnimate =
83
+ imageView.image != nil &&
84
+ (props.name != oldProps.name || props.variableValue != oldProps.variableValue)
85
+
63
86
  let symbolWeight = Self.symbolWeight(from: props.weight)
64
87
  let symbolScale = Self.symbolScale(from: props.scale)
65
88
 
66
89
  var configuration = UIImage.SymbolConfiguration(pointSize: props.size, weight: symbolWeight, scale: symbolScale)
67
90
 
91
+ if #available(iOS 26.0, *) {
92
+ configuration = configuration.applying(
93
+ UIImage.SymbolConfiguration(
94
+ variableValueMode: Self.symbolVariableValueMode(from: props.variableValueMode)
95
+ )
96
+ )
97
+
98
+ configuration = configuration.applying(
99
+ UIImage.SymbolConfiguration(
100
+ colorRenderingMode: Self.symbolColorRenderingMode(from: props.colorRenderingMode)
101
+ )
102
+ )
103
+ }
104
+
68
105
  let primaryColor = props.colorPrimary ?? props.color
69
106
 
70
- switch props.mode {
107
+ switch props.renderingMode {
71
108
  case "hierarchical":
72
109
  configuration = configuration.applying(
73
110
  UIImage.SymbolConfiguration(hierarchicalColor: primaryColor)
74
111
  )
75
112
 
76
- let image = UIImage(systemName: name, withConfiguration: configuration)
113
+ let image = Self.symbolImage(name: name, configuration: configuration, props: props)
77
114
 
78
- imageView.image = image
79
115
  imageView.tintColor = nil
116
+ setImage(image, props: props, animated: shouldAnimate)
80
117
 
81
118
  case "palette":
82
119
  var paletteColors: [UIColor] = []
@@ -95,82 +132,148 @@ import UIKit
95
132
  UIImage.SymbolConfiguration(paletteColors: paletteColors)
96
133
  )
97
134
 
98
- let image = UIImage(systemName: name, withConfiguration: configuration)
135
+ let image = Self.symbolImage(name: name, configuration: configuration, props: props)
99
136
 
100
- imageView.image = image
101
137
  imageView.tintColor = nil
138
+ setImage(image, props: props, animated: shouldAnimate)
102
139
 
103
140
  case "multicolor":
104
141
  configuration = configuration.applying(
105
142
  UIImage.SymbolConfiguration.preferringMulticolor()
106
143
  )
107
144
 
108
- let image = UIImage(systemName: name, withConfiguration: configuration)
145
+ let image = Self.symbolImage(name: name, configuration: configuration, props: props)
109
146
 
110
- imageView.image = image
111
147
  imageView.tintColor = nil
148
+ setImage(image, props: props, animated: shouldAnimate)
112
149
 
113
150
  default:
114
151
  // monochrome
115
- let image = UIImage(systemName: name, withConfiguration: configuration)
152
+ let image = Self.symbolImage(name: name, configuration: configuration, props: props)
116
153
 
117
- imageView.image = image?.withRenderingMode(.alwaysTemplate)
118
154
  imageView.tintColor = primaryColor
155
+ setImage(image?.withRenderingMode(.alwaysTemplate), props: props, animated: shouldAnimate)
119
156
  }
120
157
  }
121
158
  }
122
159
 
123
- if !needsImageUpdate && props.color != oldProps.color && props.mode == "monochrome" {
160
+ if !needsImageUpdate && props.color != oldProps.color && props.renderingMode == "monochrome" {
124
161
  imageView.tintColor = props.colorPrimary ?? props.color
125
162
  }
126
163
 
127
- let animationChanged =
128
- props.animation != oldProps.animation ||
129
- props.animationRepeating != oldProps.animationRepeating ||
130
- props.animationRepeatCount != oldProps.animationRepeatCount ||
131
- props.animationSpeed != oldProps.animationSpeed ||
132
- props.animationWholeSymbol != oldProps.animationWholeSymbol ||
133
- props.animationDirection != oldProps.animationDirection ||
134
- props.animationReversing != oldProps.animationReversing ||
135
- props.animationCumulative != oldProps.animationCumulative
136
-
137
- if animationChanged {
138
- updateAnimation(props)
164
+ let effectChanged =
165
+ props.effect != oldProps.effect ||
166
+ props.effectRepeat != oldProps.effectRepeat ||
167
+ props.effectRepeatCount != oldProps.effectRepeatCount ||
168
+ props.effectRepeatDelay != oldProps.effectRepeatDelay ||
169
+ props.effectSpeed != oldProps.effectSpeed ||
170
+ props.effectScope != oldProps.effectScope ||
171
+ props.effectDirection != oldProps.effectDirection ||
172
+ props.effectVariant != oldProps.effectVariant ||
173
+ props.effectAngle != oldProps.effectAngle ||
174
+ props.effectReversing != oldProps.effectReversing ||
175
+ props.effectCumulative != oldProps.effectCumulative ||
176
+ props.effectInactiveLayers != oldProps.effectInactiveLayers ||
177
+ props.effectDrawDirection != oldProps.effectDrawDirection
178
+
179
+ if effectChanged {
180
+ updateEffect(props)
139
181
  }
140
182
  }
141
183
 
142
- private func updateAnimation(_ props: ReactNavigationSFSymbolViewImplProps) {
143
- guard #available(iOS 17.0, *) else { return }
184
+ private func setImage(_ image: UIImage?, props: ReactNavigationSFSymbolViewImplProps, animated: Bool) {
185
+ guard let image else {
186
+ imageView.image = nil
187
+ return
188
+ }
144
189
 
145
- imageView.removeAllSymbolEffects()
190
+ guard animated, #available(iOS 17.0, *) else {
191
+ imageView.image = image
192
+ return
193
+ }
194
+
195
+ let options = Self.contentTransitionOptions(from: props)
196
+
197
+ switch props.contentTransition {
198
+ case "automatic":
199
+ imageView.setSymbolImage(
200
+ image,
201
+ contentTransition: .automatic,
202
+ options: options
203
+ )
204
+
205
+ case "replace":
206
+ var effect = ReplaceSymbolEffect.replace
207
+
208
+ switch props.contentTransitionVariant {
209
+ case "upUp":
210
+ effect = effect.upUp
211
+ case "offUp":
212
+ effect = effect.offUp
213
+ default:
214
+ effect = effect.downUp
215
+ }
146
216
 
147
- guard !props.animation.isEmpty else { return }
217
+ if props.contentTransitionScope == "wholeSymbol" {
218
+ effect = effect.wholeSymbol
219
+ } else if props.contentTransitionScope == "byLayer" {
220
+ effect = effect.byLayer
221
+ }
148
222
 
149
- var options: SymbolEffectOptions = .default
223
+ if props.contentTransitionMagic, #available(iOS 18.0, *) {
224
+ imageView.setSymbolImage(
225
+ image,
226
+ contentTransition: effect.magic(fallback: effect),
227
+ options: options
228
+ )
229
+ } else {
230
+ imageView.setSymbolImage(
231
+ image,
232
+ contentTransition: effect,
233
+ options: options
234
+ )
235
+ }
150
236
 
151
- if props.animationRepeating {
152
- options = options.repeating
153
- } else if props.animationRepeatCount > 0 {
154
- options = options.repeat(props.animationRepeatCount)
237
+ default:
238
+ imageView.image = image
155
239
  }
240
+ }
156
241
 
157
- if props.animationSpeed != 1 {
158
- options = options.speed(props.animationSpeed)
242
+ @available(iOS 17.0, *)
243
+ private static func contentTransitionOptions(from props: ReactNavigationSFSymbolViewImplProps) -> SymbolEffectOptions {
244
+ var options: SymbolEffectOptions = .default
245
+
246
+ if props.contentTransitionSpeed != 1 {
247
+ options = options.speed(props.contentTransitionSpeed)
159
248
  }
160
249
 
161
- switch props.animation {
250
+ return options
251
+ }
252
+
253
+ private func updateEffect(_ props: ReactNavigationSFSymbolViewImplProps) {
254
+ guard #available(iOS 17.0, *) else { return }
255
+
256
+ imageView.removeAllSymbolEffects()
257
+
258
+ guard !props.effect.isEmpty else { return }
259
+
260
+ let options = Self.symbolEffectOptions(from: props)
261
+
262
+ switch props.effect {
162
263
  case "bounce":
163
264
  var effect = BounceSymbolEffect.bounce
164
265
 
165
- if props.animationWholeSymbol {
266
+ if props.effectScope == "wholeSymbol" {
166
267
  effect = effect.wholeSymbol
268
+ } else if props.effectScope == "byLayer" {
269
+ effect = effect.byLayer
167
270
  }
168
271
 
169
- if props.animationDirection == "up" {
272
+ if props.effectDirection == "up" {
170
273
  effect = effect.up
171
274
  }
172
275
 
173
- if props.animationDirection == "down" {
276
+ if props.effectDirection == "down" {
174
277
  effect = effect.down
175
278
  }
176
279
 
@@ -179,8 +282,10 @@ import UIKit
179
282
  case "pulse":
180
283
  var effect = PulseSymbolEffect.pulse
181
284
 
182
- if props.animationWholeSymbol {
285
+ if props.effectScope == "wholeSymbol" {
183
286
  effect = effect.wholeSymbol
287
+ } else if props.effectScope == "byLayer" {
288
+ effect = effect.byLayer
184
289
  }
185
290
 
186
291
  imageView.addSymbolEffect(effect, options: options)
@@ -188,15 +293,17 @@ import UIKit
188
293
  case "appear":
189
294
  var effect = AppearSymbolEffect.appear
190
295
 
191
- if props.animationWholeSymbol {
296
+ if props.effectScope == "wholeSymbol" {
192
297
  effect = effect.wholeSymbol
298
+ } else if props.effectScope == "byLayer" {
299
+ effect = effect.byLayer
193
300
  }
194
301
 
195
- if props.animationDirection == "up" {
302
+ if props.effectDirection == "up" {
196
303
  effect = effect.up
197
304
  }
198
305
 
199
- if props.animationDirection == "down" {
306
+ if props.effectDirection == "down" {
200
307
  effect = effect.down
201
308
  }
202
309
 
@@ -205,15 +312,17 @@ import UIKit
205
312
  case "disappear":
206
313
  var effect = DisappearSymbolEffect.disappear
207
314
 
208
- if props.animationWholeSymbol {
315
+ if props.effectScope == "wholeSymbol" {
209
316
  effect = effect.wholeSymbol
317
+ } else if props.effectScope == "byLayer" {
318
+ effect = effect.byLayer
210
319
  }
211
320
 
212
- if props.animationDirection == "up" {
321
+ if props.effectDirection == "up" {
213
322
  effect = effect.up
214
323
  }
215
324
 
216
- if props.animationDirection == "down" {
325
+ if props.effectDirection == "down" {
217
326
  effect = effect.down
218
327
  }
219
328
 
@@ -222,10 +331,37 @@ import UIKit
222
331
  case "variableColor":
223
332
  var effect = VariableColorSymbolEffect.variableColor
224
333
 
225
- if props.animationReversing {
226
- effect = props.animationCumulative ? effect.reversing.cumulative : effect.reversing.iterative
334
+ if props.effectReversing {
335
+ effect = props.effectCumulative ? effect.reversing.cumulative : effect.reversing.iterative
227
336
  } else {
228
- effect = props.animationCumulative ? effect.nonReversing.cumulative : effect.nonReversing.iterative
337
+ effect = props.effectCumulative ? effect.nonReversing.cumulative : effect.nonReversing.iterative
338
+ }
339
+
340
+ if props.effectInactiveLayers == "hide" {
341
+ effect = effect.hideInactiveLayers
342
+ }
343
+
344
+ if props.effectInactiveLayers == "dim" {
345
+ effect = effect.dimInactiveLayers
346
+ }
347
+
348
+ imageView.addSymbolEffect(effect, options: options)
349
+
350
+ case "scale":
351
+ var effect = ScaleSymbolEffect.scale
352
+
353
+ if props.effectScope == "wholeSymbol" {
354
+ effect = effect.wholeSymbol
355
+ } else if props.effectScope == "byLayer" {
356
+ effect = effect.byLayer
357
+ }
358
+
359
+ if props.effectDirection == "up" {
360
+ effect = effect.up
361
+ }
362
+
363
+ if props.effectDirection == "down" {
364
+ effect = effect.down
229
365
  }
230
366
 
231
367
  imageView.addSymbolEffect(effect, options: options)
@@ -234,8 +370,18 @@ import UIKit
234
370
  if #available(iOS 18.0, *) {
235
371
  var effect = BreatheSymbolEffect.breathe
236
372
 
237
- if props.animationWholeSymbol {
373
+ if props.effectVariant == "plain" {
374
+ effect = effect.plain
375
+ }
376
+
377
+ if props.effectVariant == "pulse" {
378
+ effect = effect.pulse
379
+ }
380
+
381
+ if props.effectScope == "wholeSymbol" {
238
382
  effect = effect.wholeSymbol
383
+ } else if props.effectScope == "byLayer" {
384
+ effect = effect.byLayer
239
385
  }
240
386
 
241
387
  imageView.addSymbolEffect(effect, options: options)
@@ -245,16 +391,30 @@ import UIKit
245
391
  if #available(iOS 18.0, *) {
246
392
  var effect = WiggleSymbolEffect.wiggle
247
393
 
248
- if props.animationWholeSymbol {
394
+ if props.effectScope == "wholeSymbol" {
249
395
  effect = effect.wholeSymbol
396
+ } else if props.effectScope == "byLayer" {
397
+ effect = effect.byLayer
250
398
  }
251
399
 
252
- if props.animationDirection == "up" {
400
+ if props.effectAngle >= 0 {
401
+ effect = effect.custom(angle: Double(props.effectAngle))
402
+ } else if props.effectDirection == "up" {
253
403
  effect = effect.up
254
- }
255
-
256
- if props.animationDirection == "down" {
404
+ } else if props.effectDirection == "down" {
257
405
  effect = effect.down
406
+ } else if props.effectDirection == "left" {
407
+ effect = effect.left
408
+ } else if props.effectDirection == "right" {
409
+ effect = effect.right
410
+ } else if props.effectDirection == "forward" {
411
+ effect = effect.forward
412
+ } else if props.effectDirection == "backward" {
413
+ effect = effect.backward
414
+ } else if props.effectDirection == "clockwise" {
415
+ effect = effect.clockwise
416
+ } else if props.effectDirection == "counterClockwise" {
417
+ effect = effect.counterClockwise
258
418
  }
259
419
 
260
420
  imageView.addSymbolEffect(effect, options: options)
@@ -264,8 +424,56 @@ import UIKit
264
424
  if #available(iOS 18.0, *) {
265
425
  var effect = RotateSymbolEffect.rotate
266
426
 
267
- if props.animationWholeSymbol {
427
+ if props.effectScope == "wholeSymbol" {
268
428
  effect = effect.wholeSymbol
429
+ } else if props.effectScope == "byLayer" {
430
+ effect = effect.byLayer
431
+ }
432
+
433
+ if props.effectDirection == "clockwise" {
434
+ effect = effect.clockwise
435
+ }
436
+
437
+ if props.effectDirection == "counterClockwise" {
438
+ effect = effect.counterClockwise
439
+ }
440
+
441
+ imageView.addSymbolEffect(effect, options: options)
442
+ }
443
+
444
+ case "drawOn":
445
+ if #available(iOS 26.0, *) {
446
+ var effect = DrawOnSymbolEffect.drawOn
447
+
448
+ if props.effectScope == "wholeSymbol" {
449
+ effect = effect.wholeSymbol
450
+ } else if props.effectScope == "individually" {
451
+ effect = effect.individually
452
+ } else if props.effectScope == "byLayer" {
453
+ effect = effect.byLayer
454
+ }
455
+
456
+ imageView.addSymbolEffect(effect, options: options)
457
+ }
458
+
459
+ case "drawOff":
460
+ if #available(iOS 26.0, *) {
461
+ var effect = DrawOffSymbolEffect.drawOff
462
+
463
+ if props.effectDrawDirection == "reversed" {
464
+ effect = effect.reversed
465
+ }
466
+
467
+ if props.effectDrawDirection == "nonReversed" {
468
+ effect = effect.nonReversed
469
+ }
470
+
471
+ if props.effectScope == "wholeSymbol" {
472
+ effect = effect.wholeSymbol
473
+ } else if props.effectScope == "individually" {
474
+ effect = effect.individually
475
+ } else if props.effectScope == "byLayer" {
476
+ effect = effect.byLayer
269
477
  }
270
478
 
271
479
  imageView.addSymbolEffect(effect, options: options)
@@ -275,6 +483,84 @@ import UIKit
275
483
  }
276
484
  }
277
485
 
486
+ @available(iOS 17.0, *)
487
+ private static func symbolEffectOptions(from props: ReactNavigationSFSymbolViewImplProps) -> SymbolEffectOptions {
488
+ var options: SymbolEffectOptions = .default
489
+
490
+ switch props.effectRepeat {
491
+ case "continuous":
492
+ if #available(iOS 18.0, *) {
493
+ options = options.repeat(.continuous)
494
+ } else {
495
+ options = options.repeating
496
+ }
497
+
498
+ case "nonRepeating":
499
+ options = options.nonRepeating
500
+
501
+ case "periodic":
502
+ if #available(iOS 18.0, *) {
503
+ let count: Int? = props.effectRepeatCount > 0 ? props.effectRepeatCount : nil
504
+ let delay: Double? = props.effectRepeatDelay > 0 ? Double(props.effectRepeatDelay) : nil
505
+
506
+ options = options.repeat(
507
+ .periodic(count, delay: delay)
508
+ )
509
+ } else if props.effectRepeatCount > 0 {
510
+ options = options.repeat(props.effectRepeatCount)
511
+ } else {
512
+ options = options.repeating
513
+ }
514
+
515
+ default:
516
+ break
517
+ }
518
+
519
+ if props.effectSpeed != 1 {
520
+ options = options.speed(props.effectSpeed)
521
+ }
522
+
523
+ return options
524
+ }
525
+
526
+ private static func symbolImage(
527
+ name: String,
528
+ configuration: UIImage.SymbolConfiguration,
529
+ props: ReactNavigationSFSymbolViewImplProps
530
+ ) -> UIImage? {
531
+ if props.variableValue >= 0 {
532
+ let variableValue = min(max(props.variableValue, 0), 1)
533
+
534
+ if #available(iOS 16.0, *) {
535
+ return UIImage(
536
+ systemName: name,
537
+ variableValue: Double(variableValue),
538
+ configuration: configuration
539
+ )
540
+ }
541
+ }
542
+
543
+ return UIImage(systemName: name, withConfiguration: configuration)
544
+ }
545
+
546
+ @available(iOS 26.0, *)
547
+ private static func symbolVariableValueMode(from value: String) -> UIImage.SymbolVariableValueMode {
548
+ switch value {
549
+ case "color": return .color
550
+ case "draw": return .draw
551
+ default: return .automatic
552
+ }
553
+ }
554
+
555
+ @available(iOS 26.0, *)
556
+ private static func symbolColorRenderingMode(from value: String) -> UIImage.SymbolColorRenderingMode {
557
+ switch value {
558
+ case "flat": return .flat
559
+ case "gradient": return .gradient
560
+ default: return .automatic
561
+ }
562
+ }
563
+
278
564
  private static func symbolWeight(from value: Int) -> UIImage.SymbolWeight {
279
565
  switch value {
280
566
  case 100: return .thin
@@ -8,8 +8,16 @@ const StackNavigator = props => {
8
8
  descriptors,
9
9
  NavigationContent
10
10
  } = useNavigationBuilder(StackRouter, props);
11
+ const route = state.routes[state.index];
12
+ if (route == null) {
13
+ throw new Error(`Couldn't find a route at index ${state.index}.`);
14
+ }
15
+ const descriptor = descriptors[route.key];
16
+ if (descriptor == null) {
17
+ throw new Error(`Couldn't find a descriptor for route '${route.key}'.`);
18
+ }
11
19
  return /*#__PURE__*/_jsx(NavigationContent, {
12
- children: descriptors[state.routes[state.index].key].render()
20
+ children: descriptor.render()
13
21
  });
14
22
  };
15
23
  export const createStackNavigator = createNavigatorFactory(StackNavigator);
@@ -1 +1 @@
1
- {"version":3,"names":["createNavigatorFactory","StackRouter","useNavigationBuilder","jsx","_jsx","StackNavigator","props","state","descriptors","NavigationContent","children","routes","index","key","render","createStackNavigator"],"sourceRoot":"../../../src","sources":["__stubs__/createStackNavigator.tsx"],"mappings":";;AAAA,SACEA,sBAAsB,EAKtBC,WAAW,EACXC,oBAAoB,QACf,wBAAwB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAEhC,MAAMC,cAAc,GAClBC,KAMC,IACE;EACH,MAAM;IAAEC,KAAK;IAAEC,WAAW;IAAEC;EAAkB,CAAC,GAAGP,oBAAoB,CACpED,WAAW,EACXK,KACF,CAAC;EAED,oBACEF,IAAA,CAACK,iBAAiB;IAAAC,QAAA,EACfF,WAAW,CAACD,KAAK,CAACI,MAAM,CAACJ,KAAK,CAACK,KAAK,CAAC,CAACC,GAAG,CAAC,CAACC,MAAM,CAAC;EAAC,CACnC,CAAC;AAExB,CAAC;AAOD,OAAO,MAAMC,oBAAoB,GAC/Bf,sBAAsB,CAAmBK,cAAc,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["createNavigatorFactory","StackRouter","useNavigationBuilder","jsx","_jsx","StackNavigator","props","state","descriptors","NavigationContent","route","routes","index","Error","descriptor","key","children","render","createStackNavigator"],"sourceRoot":"../../../src","sources":["__stubs__/createStackNavigator.tsx"],"mappings":";;AAAA,SACEA,sBAAsB,EAKtBC,WAAW,EACXC,oBAAoB,QACf,wBAAwB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAEhC,MAAMC,cAAc,GAClBC,KAMC,IACE;EACH,MAAM;IAAEC,KAAK;IAAEC,WAAW;IAAEC;EAAkB,CAAC,GAAGP,oBAAoB,CACpED,WAAW,EACXK,KACF,CAAC;EAED,MAAMI,KAAK,GAAGH,KAAK,CAACI,MAAM,CAACJ,KAAK,CAACK,KAAK,CAAC;EAEvC,IAAIF,KAAK,IAAI,IAAI,EAAE;IACjB,MAAM,IAAIG,KAAK,CAAC,kCAAkCN,KAAK,CAACK,KAAK,GAAG,CAAC;EACnE;EAEA,MAAME,UAAU,GAAGN,WAAW,CAACE,KAAK,CAACK,GAAG,CAAC;EAEzC,IAAID,UAAU,IAAI,IAAI,EAAE;IACtB,MAAM,IAAID,KAAK,CAAC,yCAAyCH,KAAK,CAACK,GAAG,IAAI,CAAC;EACzE;EAEA,oBAAOX,IAAA,CAACK,iBAAiB;IAAAO,QAAA,EAAEF,UAAU,CAACG,MAAM,CAAC;EAAC,CAAoB,CAAC;AACrE,CAAC;AAOD,OAAO,MAAMC,oBAAoB,GAC/BlB,sBAAsB,CAAmBK,cAAc,CAAC","ignoreList":[]}
@@ -35,6 +35,9 @@ const history = {
35
35
  if (n > 0 && n < entries.length - index || n < 0 && Math.abs(n) <= index) {
36
36
  index += n;
37
37
  const entry = entries[index];
38
+ if (entry == null) {
39
+ throw new Error(`Couldn't find a history entry at index ${index}.`);
40
+ }
38
41
  location = new URL(entry.href);
39
42
  currentState = entry.state;
40
43
  listeners.forEach(cb => cb());
@@ -1 +1 @@
1
- {"version":3,"names":["location","URL","listeners","entries","state","href","index","currentState","history","pushState","_","path","origin","slice","push","length","replaceState","go","n","setTimeout","Math","abs","entry","forEach","cb","back","forward","addEventListener","type","listener","removeEventListener","filter","window","document","title"],"sourceRoot":"../../../src","sources":["__stubs__/window.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["location","URL","listeners","entries","state","href","index","currentState","history","pushState","_","path","origin","slice","push","length","replaceState","go","n","setTimeout","Math","abs","entry","Error","forEach","cb","back","forward","addEventListener","type","listener","removeEventListener","filter","window","document","title"],"sourceRoot":"../../../src","sources":["__stubs__/window.tsx"],"mappings":"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","ignoreList":[]}