@iternio/react-native-auto-play 0.5.14-beta.1 → 0.6.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 (201) hide show
  1. package/README.md +270 -36
  2. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidAutoSession.kt +5 -0
  3. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridMapTemplate.kt +9 -2
  4. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/NativeBackdrop.kt +40 -0
  5. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VirtualRenderer.kt +52 -0
  6. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/GridTemplate.kt +47 -13
  7. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/Parser.kt +69 -15
  8. package/ios/Types.swift +3 -0
  9. package/ios/extensions/UIImage+Toggle.swift +5 -2
  10. package/ios/hybrid/HybridAutoPlay.swift +28 -16
  11. package/ios/hybrid/HybridMapTemplate.swift +22 -5
  12. package/ios/scenes/AutoPlayInterfaceController.swift +261 -72
  13. package/ios/templates/AutoPlayMapPanelDelegate.swift +190 -0
  14. package/ios/templates/AutoPlayTemplate.swift +24 -2
  15. package/ios/templates/GridTemplate.swift +57 -57
  16. package/ios/templates/InformationTemplate.swift +84 -9
  17. package/ios/templates/ListTemplate.swift +66 -11
  18. package/ios/templates/MapTemplate.swift +83 -68
  19. package/ios/templates/MessageTemplate.swift +72 -6
  20. package/ios/templates/Parser.swift +564 -69
  21. package/ios/templates/SearchTemplate.swift +1 -1
  22. package/ios/templates/TemplateStore.swift +5 -15
  23. package/ios/utils/SymbolFont.swift +13 -28
  24. package/jest.js +2 -0
  25. package/lib/Constants.d.ts +4 -0
  26. package/lib/Constants.js +6 -0
  27. package/lib/index.d.ts +1 -0
  28. package/lib/index.js +1 -0
  29. package/lib/index.web.d.ts +73 -0
  30. package/lib/index.web.js +72 -1
  31. package/lib/specs/MapTemplate.nitro.d.ts +3 -1
  32. package/lib/templates/GridTemplate.d.ts +23 -3
  33. package/lib/templates/GridTemplate.js +8 -0
  34. package/lib/templates/InformationTemplate.d.ts +38 -12
  35. package/lib/templates/ListTemplate.d.ts +16 -47
  36. package/lib/templates/MapTemplate.d.ts +26 -2
  37. package/lib/templates/MapTemplate.js +16 -2
  38. package/lib/templates/MessageTemplate.d.ts +52 -11
  39. package/lib/templates/MessageTemplate.js +1 -1
  40. package/lib/types/Image.d.ts +6 -1
  41. package/lib/utils/NitroColor.d.ts +1 -0
  42. package/lib/utils/NitroColor.js +8 -0
  43. package/lib/utils/NitroImage.js +1 -1
  44. package/lib/utils/NitroManeuver.js +1 -3
  45. package/lib/utils/NitroOptionsPanel.d.ts +103 -0
  46. package/lib/utils/NitroOptionsPanel.js +63 -0
  47. package/lib/utils/NitroSection.d.ts +89 -2
  48. package/lib/utils/NitroSection.js +49 -2
  49. package/lib-cjs/AutoPlayHeadlessJsTask.js +16 -0
  50. package/lib-cjs/Constants.js +9 -0
  51. package/lib-cjs/components/MapTemplateContext.js +10 -0
  52. package/lib-cjs/components/SafeAreaInsetsContext.js +21 -0
  53. package/lib-cjs/components/SafeAreaView.js +22 -0
  54. package/lib-cjs/components/WindowInformationWrapper.js +20 -0
  55. package/lib-cjs/hooks/useAndroidAutoTelemetry.js +115 -0
  56. package/lib-cjs/hooks/useFocusedEffect.js +35 -0
  57. package/lib-cjs/hooks/useMapTemplate.js +13 -0
  58. package/lib-cjs/hooks/useSafeAreaInsets.js +9 -0
  59. package/lib-cjs/hooks/useVoiceInput.js +42 -0
  60. package/lib-cjs/hybrid/HybridAndroidAutoTelemetry.js +4 -0
  61. package/lib-cjs/hybrid/HybridAndroidWindowInformation.js +4 -0
  62. package/lib-cjs/hybrid/HybridAutoPlay.js +5 -0
  63. package/lib-cjs/hybrid/HybridVoice.js +61 -0
  64. package/lib-cjs/index.js +76 -0
  65. package/lib-cjs/index.web.js +98 -0
  66. package/lib-cjs/scenes/AutoPlayCluster.js +140 -0
  67. package/lib-cjs/scenes/CarPlayDashboardScene.js +100 -0
  68. package/lib-cjs/specs/AndroidAutoTelemetry.nitro.js +2 -0
  69. package/lib-cjs/specs/AndroidAutomotive.nitro.js +16 -0
  70. package/lib-cjs/specs/AndroidWindowInformation.nitro.js +2 -0
  71. package/lib-cjs/specs/AutoPlay.nitro.js +2 -0
  72. package/lib-cjs/specs/CarPlayDashboard.nitro.js +2 -0
  73. package/lib-cjs/specs/Cluster.nitro.js +2 -0
  74. package/lib-cjs/specs/GridTemplate.nitro.js +2 -0
  75. package/lib-cjs/specs/InformationTemplate.nitro.js +2 -0
  76. package/lib-cjs/specs/ListTemplate.nitro.js +2 -0
  77. package/lib-cjs/specs/MapTemplate.nitro.js +2 -0
  78. package/lib-cjs/specs/MessageTemplate.nitro.js +2 -0
  79. package/lib-cjs/specs/SearchTemplate.nitro.js +2 -0
  80. package/lib-cjs/specs/SignInTemplate.nitro.js +2 -0
  81. package/lib-cjs/specs/Voice.nitro.js +2 -0
  82. package/lib-cjs/templates/GridTemplate.js +41 -0
  83. package/lib-cjs/templates/InformationTemplate.js +49 -0
  84. package/lib-cjs/templates/ListTemplate.js +33 -0
  85. package/lib-cjs/templates/MapTemplate.js +168 -0
  86. package/lib-cjs/templates/MessageTemplate.js +50 -0
  87. package/lib-cjs/templates/SearchTemplate.js +32 -0
  88. package/lib-cjs/templates/SignInTemplate.js +55 -0
  89. package/lib-cjs/templates/Template.js +40 -0
  90. package/lib-cjs/types/Button.js +12 -0
  91. package/lib-cjs/types/Event.js +2 -0
  92. package/lib-cjs/types/Image.js +2 -0
  93. package/lib-cjs/types/Maneuver.js +77 -0
  94. package/lib-cjs/types/RootComponent.js +2 -0
  95. package/lib-cjs/types/SignInMethod.js +22 -0
  96. package/lib-cjs/types/Telemetry.js +24 -0
  97. package/lib-cjs/types/Text.js +8 -0
  98. package/lib-cjs/types/Trip.js +2 -0
  99. package/lib-cjs/types/Voice.js +2 -0
  100. package/lib-cjs/utils/ErrorUtil.js +34 -0
  101. package/lib-cjs/utils/NitroAction.js +129 -0
  102. package/lib-cjs/utils/NitroAlert.js +19 -0
  103. package/lib-cjs/utils/NitroAttributedString.js +14 -0
  104. package/lib-cjs/utils/NitroColor.js +32 -0
  105. package/lib-cjs/utils/NitroGrid.js +12 -0
  106. package/lib-cjs/utils/NitroImage.js +97 -0
  107. package/lib-cjs/utils/NitroManeuver.js +79 -0
  108. package/lib-cjs/utils/NitroMapButton.js +33 -0
  109. package/lib-cjs/utils/NitroOptionsPanel.js +66 -0
  110. package/lib-cjs/utils/NitroSection.js +112 -0
  111. package/nitrogen/generated/android/ReactNativeAutoPlay+autolinking.cmake +1 -0
  112. package/nitrogen/generated/android/c++/JChargingConnector.hpp +79 -0
  113. package/nitrogen/generated/android/c++/JGridImageSize.hpp +64 -0
  114. package/nitrogen/generated/android/c++/JGridTemplateConfig.hpp +7 -1
  115. package/nitrogen/generated/android/c++/JHybridGridTemplateSpec.cpp +4 -0
  116. package/nitrogen/generated/android/c++/JHybridInformationTemplateSpec.cpp +12 -0
  117. package/nitrogen/generated/android/c++/JHybridListTemplateSpec.cpp +12 -0
  118. package/nitrogen/generated/android/c++/JHybridMapTemplateSpec.cpp +78 -3
  119. package/nitrogen/generated/android/c++/JHybridMapTemplateSpec.hpp +2 -1
  120. package/nitrogen/generated/android/c++/JHybridSearchTemplateSpec.cpp +12 -0
  121. package/nitrogen/generated/android/c++/JInformationTemplateConfig.hpp +6 -0
  122. package/nitrogen/generated/android/c++/JListImageType.hpp +67 -0
  123. package/nitrogen/generated/android/c++/JListTemplateConfig.hpp +6 -0
  124. package/nitrogen/generated/android/c++/JNitroChargerLocation.hpp +115 -0
  125. package/nitrogen/generated/android/c++/JNitroChargerOutlet.hpp +82 -0
  126. package/nitrogen/generated/android/c++/JNitroColor.hpp +8 -4
  127. package/nitrogen/generated/android/c++/JNitroOptionsPanelChargerSection.hpp +112 -0
  128. package/nitrogen/generated/android/c++/JNitroOptionsPanelConfig.hpp +157 -0
  129. package/nitrogen/generated/android/c++/JNitroOptionsPanelGridSection.hpp +102 -0
  130. package/nitrogen/generated/android/c++/JNitroOptionsPanelSection.cpp +30 -0
  131. package/nitrogen/generated/android/c++/JNitroOptionsPanelSection.hpp +129 -0
  132. package/nitrogen/generated/android/c++/JNitroRow.hpp +33 -3
  133. package/nitrogen/generated/android/c++/JNitroSection.hpp +6 -0
  134. package/nitrogen/generated/android/c++/JSearchTemplateConfig.hpp +6 -0
  135. package/nitrogen/generated/android/c++/JWaypointCoordinate.hpp +65 -0
  136. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/ChargingConnector.kt +30 -0
  137. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/GridImageSize.kt +25 -0
  138. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/GridTemplateConfig.kt +9 -4
  139. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridMapTemplateSpec.kt +5 -1
  140. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/ListImageType.kt +26 -0
  141. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroChargerLocation.kt +90 -0
  142. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroChargerOutlet.kt +70 -0
  143. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroColor.kt +9 -4
  144. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroOptionsPanelChargerSection.kt +61 -0
  145. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroOptionsPanelConfig.kt +61 -0
  146. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroOptionsPanelGridSection.kt +56 -0
  147. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroOptionsPanelSection.kt +75 -0
  148. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroRow.kt +36 -6
  149. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/WaypointCoordinate.kt +61 -0
  150. package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Bridge.hpp +174 -0
  151. package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Umbrella.hpp +27 -0
  152. package/nitrogen/generated/ios/c++/HybridGridTemplateSpecSwift.hpp +3 -0
  153. package/nitrogen/generated/ios/c++/HybridInformationTemplateSpecSwift.hpp +9 -0
  154. package/nitrogen/generated/ios/c++/HybridListTemplateSpecSwift.hpp +9 -0
  155. package/nitrogen/generated/ios/c++/HybridMapTemplateSpecSwift.hpp +47 -1
  156. package/nitrogen/generated/ios/c++/HybridSearchTemplateSpecSwift.hpp +9 -0
  157. package/nitrogen/generated/ios/swift/ChargingConnector.swift +68 -0
  158. package/nitrogen/generated/ios/swift/GridImageSize.swift +48 -0
  159. package/nitrogen/generated/ios/swift/GridTemplateConfig.swift +12 -1
  160. package/nitrogen/generated/ios/swift/HybridMapTemplateSpec.swift +2 -1
  161. package/nitrogen/generated/ios/swift/HybridMapTemplateSpec_cxx.swift +31 -4
  162. package/nitrogen/generated/ios/swift/ListImageType.swift +52 -0
  163. package/nitrogen/generated/ios/swift/NitroChargerLocation.swift +161 -0
  164. package/nitrogen/generated/ios/swift/NitroChargerOutlet.swift +65 -0
  165. package/nitrogen/generated/ios/swift/NitroColor.swift +20 -2
  166. package/nitrogen/generated/ios/swift/NitroOptionsPanelChargerSection.swift +64 -0
  167. package/nitrogen/generated/ios/swift/NitroOptionsPanelConfig.swift +94 -0
  168. package/nitrogen/generated/ios/swift/NitroOptionsPanelGridSection.swift +53 -0
  169. package/nitrogen/generated/ios/swift/NitroOptionsPanelSection.swift +32 -0
  170. package/nitrogen/generated/ios/swift/NitroRow.swift +81 -1
  171. package/nitrogen/generated/ios/swift/WaypointCoordinate.swift +52 -0
  172. package/nitrogen/generated/shared/c++/ChargingConnector.hpp +104 -0
  173. package/nitrogen/generated/shared/c++/GridImageSize.hpp +84 -0
  174. package/nitrogen/generated/shared/c++/GridTemplateConfig.hpp +8 -1
  175. package/nitrogen/generated/shared/c++/HybridMapTemplateSpec.cpp +1 -0
  176. package/nitrogen/generated/shared/c++/HybridMapTemplateSpec.hpp +5 -1
  177. package/nitrogen/generated/shared/c++/ListImageType.hpp +88 -0
  178. package/nitrogen/generated/shared/c++/NitroChargerLocation.hpp +131 -0
  179. package/nitrogen/generated/shared/c++/NitroChargerOutlet.hpp +98 -0
  180. package/nitrogen/generated/shared/c++/NitroColor.hpp +7 -3
  181. package/nitrogen/generated/shared/c++/NitroOptionsPanelChargerSection.hpp +98 -0
  182. package/nitrogen/generated/shared/c++/NitroOptionsPanelConfig.hpp +107 -0
  183. package/nitrogen/generated/shared/c++/NitroOptionsPanelGridSection.hpp +91 -0
  184. package/nitrogen/generated/shared/c++/NitroRow.hpp +39 -2
  185. package/nitrogen/generated/shared/c++/WaypointCoordinate.hpp +91 -0
  186. package/package.json +7 -3
  187. package/src/Constants.ts +9 -0
  188. package/src/index.ts +1 -0
  189. package/src/index.web.ts +166 -0
  190. package/src/specs/MapTemplate.nitro.ts +3 -1
  191. package/src/templates/GridTemplate.ts +38 -3
  192. package/src/templates/InformationTemplate.ts +60 -29
  193. package/src/templates/ListTemplate.ts +27 -55
  194. package/src/templates/MapTemplate.ts +60 -2
  195. package/src/templates/MessageTemplate.ts +71 -24
  196. package/src/types/Image.ts +6 -1
  197. package/src/utils/NitroColor.ts +10 -1
  198. package/src/utils/NitroImage.ts +1 -5
  199. package/src/utils/NitroManeuver.ts +1 -4
  200. package/src/utils/NitroOptionsPanel.ts +218 -0
  201. package/src/utils/NitroSection.ts +160 -5
@@ -1,11 +1,10 @@
1
1
  import { NitroModules } from 'react-native-nitro-modules';
2
2
  import type { ListTemplate as NitroListTemplate } from '../specs/ListTemplate.nitro';
3
- import type { AutoImage } from '../types/Image';
4
3
  import type { AutoText } from '../types/Text';
5
4
  import { type NitroAction, NitroActionUtil } from '../utils/NitroAction';
6
5
  import { NitroMapButton } from '../utils/NitroMapButton';
7
- import { type NitroSection, NitroSectionUtil } from '../utils/NitroSection';
8
- import type { BaseMapTemplateConfig } from './MapTemplate';
6
+ import { type NitroSection, NitroSectionUtil, type Section } from '../utils/NitroSection';
7
+ import type { BaseMapTemplateConfig, PanelHeaderActions } from './MapTemplate';
9
8
  import {
10
9
  type HeaderActions,
11
10
  type NitroBaseMapTemplateConfig,
@@ -16,56 +15,23 @@ import {
16
15
 
17
16
  const HybridListTemplate = NitroModules.createHybridObject<NitroListTemplate>('ListTemplate');
18
17
 
19
- type BaseRow = {
20
- title: AutoText;
21
- enabled?: boolean;
22
- image?: AutoImage;
23
- };
24
-
25
- export type DefaultRow<T> = BaseRow & {
26
- type: 'default';
27
- /**
28
- * adds a chevron at the end of the row
29
- */
30
- browsable?: boolean;
31
- onPress: (template: T) => void;
32
- detailedText?: AutoText;
33
- };
34
-
35
- export type ToggleRow<T> = BaseRow & {
36
- type: 'toggle';
37
- checked: boolean;
38
- onPress: (template: T, checked: boolean) => void;
39
- };
40
-
41
- export type RadioRow<T> = BaseRow & {
42
- type: 'radio';
43
- onPress: (template: T) => void;
44
- selected?: boolean;
45
- };
46
-
47
- export type TextRow = BaseRow & {
48
- type: 'text';
49
- detailedText?: AutoText;
50
- };
51
-
52
- export type MultiSection<T> =
53
- | {
54
- type: 'default';
55
- title: string;
56
- items: Array<DefaultRow<T> | ToggleRow<T> | TextRow>;
57
- }
58
- | {
59
- type: 'radio';
60
- title: string;
61
- items: Array<RadioRow<T>>;
62
- };
63
-
64
- export type SingleSection<T> = {
65
- [K in MultiSection<T> as K['type']]: Omit<K, 'title' | 'detailedText'>;
66
- }[MultiSection<T>['type']];
67
-
68
- export type Section<T> = Array<MultiSection<T>> | SingleSection<T>;
18
+ /**
19
+ * Controls the Android image size for a list item.
20
+ * @namespace Android
21
+ */
22
+ export type ListImageType = 'large' | 'medium' | 'small' | 'extra_small' | 'icon';
23
+
24
+ export type {
25
+ DefaultRow,
26
+ MultiSection,
27
+ RadioRow,
28
+ Section,
29
+ SingleSection,
30
+ TextRow,
31
+ ToggleRow,
32
+ WaypointCoordinate,
33
+ WaypointRow,
34
+ } from '../utils/NitroSection';
69
35
 
70
36
  export interface NitroListTemplateConfig extends TemplateConfig {
71
37
  headerActions?: Array<NitroAction>;
@@ -92,9 +58,15 @@ export type ListTemplateConfig = Omit<
92
58
  sections?: Section<ListTemplate>;
93
59
  /**
94
60
  * If mapConfig is defined, it will use a MapWithContentTemplate with the current template. This results in a ListTemplate with a map in background. No actions need to be specified, can be empty object.
95
- * @namespace Android
61
+ * @namespace Android - uses MapWithContentTemplate
62
+ * @namespace iOS - renders as a CPMapPanel on the current root map template (iOS 27+);
63
+ * `headerActions` here is Android-only — on iOS this template's own `headerActions` are
64
+ * applied to the root map template's nav bar instead, since CarPlay has no separate header
65
+ * for the map behind a panel.
96
66
  */
97
- mapConfig?: BaseMapTemplateConfig<ListTemplate>;
67
+ mapConfig?: Omit<BaseMapTemplateConfig<ListTemplate>, 'headerActions'> & {
68
+ headerActions?: PanelHeaderActions<ListTemplate>;
69
+ };
98
70
  };
99
71
 
100
72
  export class ListTemplate extends Template<ListTemplateConfig, HeaderActions<ListTemplate>> {
@@ -7,7 +7,13 @@ import { SafeAreaInsetsProvider } from '../components/SafeAreaInsetsContext';
7
7
  import { WindowInformationWrapper } from '../components/WindowInformationWrapper';
8
8
  import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
9
9
  import type { MapTemplate as NitroMapTemplate } from '../specs/MapTemplate.nitro';
10
- import type { ActionButtonAndroid, MapButton, MapPanButton } from '../types/Button';
10
+ import type {
11
+ ActionButtonAndroid,
12
+ ImageButton,
13
+ MapButton,
14
+ MapPanButton,
15
+ TextButton,
16
+ } from '../types/Button';
11
17
  import type { AutoManeuver, ManeuverState } from '../types/Maneuver';
12
18
  import type { ColorScheme, RootComponentInitialProps } from '../types/RootComponent';
13
19
  import type {
@@ -21,6 +27,7 @@ import { type NavigationAlert, NitroAlertUtil } from '../utils/NitroAlert';
21
27
  import { type NitroColor, NitroColorUtil, type ThemedColor } from '../utils/NitroColor';
22
28
  import { NitroManeuverUtil, type NitroRoutingManeuver } from '../utils/NitroManeuver';
23
29
  import { NitroMapButton } from '../utils/NitroMapButton';
30
+ import { NitroOptionsPanelUtil, type OptionsPanelConfig } from '../utils/NitroOptionsPanel';
24
31
  import {
25
32
  type HeaderActionsIos,
26
33
  type NitroBaseMapTemplateConfig,
@@ -31,6 +38,17 @@ import {
31
38
 
32
39
  const HybridMapTemplate = NitroModules.createHybridObject<NitroMapTemplate>('MapTemplate');
33
40
 
41
+ export type {
42
+ ChargerLocation,
43
+ ChargerOutlet,
44
+ ChargingConnector,
45
+ OptionsPanelChargerSection,
46
+ OptionsPanelConfig,
47
+ OptionsPanelGridSection,
48
+ OptionsPanelListSection,
49
+ OptionsPanelSection,
50
+ } from '../utils/NitroOptionsPanel';
51
+
34
52
  export type Point = { x: number; y: number };
35
53
  export type VisibleTravelEstimate = 'first' | 'last';
36
54
 
@@ -118,6 +136,19 @@ export type MapHeaderActions<T> = {
118
136
  ios?: HeaderActionsIos<T>;
119
137
  };
120
138
 
139
+ /**
140
+ * @namespace iOS - not supported; CarPlay has no separate header for the map behind a panel, so
141
+ * the panel template's own `headerActions` are applied to the root map template's nav bar instead.
142
+ */
143
+ export type PanelHeaderActions<T> = Omit<MapHeaderActions<T>, 'ios'>;
144
+
145
+ /**
146
+ * @namespace iOS - a CPMapPanel can only show one CPTextButton (with a title) and one
147
+ * optional icon-only button (any title is dropped natively), so a second action must be an
148
+ * ImageButton rather than a TextButton, and a third action isn't supported at all.
149
+ */
150
+ export type PanelActionsIos<T> = [TextButton<T>] | [TextButton<T>, ImageButton<T>];
151
+
121
152
  export type BaseMapTemplateConfig<T> = {
122
153
  /**
123
154
  * buttons that represent actions on the map template, usually on the bottom right corner
@@ -146,6 +177,13 @@ export type MapTemplateConfig = Omit<
146
177
  */
147
178
  component: React.ComponentType<RootComponentInitialProps>;
148
179
 
180
+ /**
181
+ * the panel shown when tapping the ellipsis button next to the travel estimates during active navigation (iOS 27+).
182
+ * No-op on Android
183
+ * @namespace iOS
184
+ */
185
+ optionsPanel?: OptionsPanelConfig<MapTemplate>;
186
+
149
187
  /**
150
188
  * Notification that navigation was stopped. May occur when another source such as the car head unit starts navigating.
151
189
  * The navigation session on Android Auto/CarPlay is stopped already when this callback is triggered, make sure to stop other things like TTS too.
@@ -185,6 +223,7 @@ export class MapTemplate extends Template<MapTemplateConfig, MapTemplateConfig['
185
223
  onStopNavigation,
186
224
  onAutoDriveEnabled,
187
225
  defaultGuidanceBackgroundColor,
226
+ optionsPanel,
188
227
  ...baseConfig
189
228
  } = config;
190
229
 
@@ -220,6 +259,25 @@ export class MapTemplate extends Template<MapTemplateConfig, MapTemplateConfig['
220
259
  };
221
260
 
222
261
  HybridMapTemplate.createMapTemplate(nitroConfig);
262
+
263
+ // routed through updateOptionsPanel, not embedded in nitroConfig above — nitrogen can't generate
264
+ // a spec for a variant type nested that deep inside NitroMapTemplateConfig.
265
+ this.updateOptionsPanel(optionsPanel);
266
+ }
267
+
268
+ /**
269
+ * @namespace iOS updates the panel shown when tapping the ellipsis button
270
+ * next to the travel estimates during navigation (iOS 27+).
271
+ */
272
+ public updateOptionsPanel(optionsPanel?: OptionsPanelConfig<MapTemplate>) {
273
+ if (Platform.OS !== 'ios') {
274
+ return;
275
+ }
276
+
277
+ return HybridMapTemplate.updateOptionsPanel(
278
+ this.id,
279
+ NitroOptionsPanelUtil.convert(this.template, optionsPanel)
280
+ );
223
281
  }
224
282
 
225
283
  public setMapButtons(mapButtons: MapTemplateConfig['mapButtons']) {
@@ -364,7 +422,7 @@ export class MapTemplate extends Template<MapTemplateConfig, MapTemplateConfig['
364
422
  * or use this to start a navigation session without asking the user
365
423
  */
366
424
  public startNavigation(trip: TripConfig) {
367
- HybridMapTemplate.startNavigation(this.id, trip);
425
+ return HybridMapTemplate.startNavigation(this.id, trip);
368
426
  }
369
427
 
370
428
  public stopNavigation() {
@@ -5,7 +5,7 @@ import type {
5
5
  AutoImage,
6
6
  BaseMapTemplateConfig,
7
7
  CustomActionButtonAndroid,
8
- HeaderActionsAndroid,
8
+ HeaderActions,
9
9
  TextButton,
10
10
  } from '..';
11
11
  import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
@@ -14,6 +14,7 @@ import type { AutoText } from '../types/Text';
14
14
  import { type NitroAction, NitroActionUtil } from '../utils/NitroAction';
15
15
  import { type NitroImage, NitroImageUtil } from '../utils/NitroImage';
16
16
  import { NitroMapButton } from '../utils/NitroMapButton';
17
+ import type { PanelActionsIos, PanelHeaderActions } from './MapTemplate';
17
18
  import type { NitroBaseMapTemplateConfig, NitroTemplateConfig, TemplateConfig } from './Template';
18
19
 
19
20
  const HybridMessageTemplate =
@@ -23,6 +24,7 @@ export interface NitroMessageTemplateConfig extends TemplateConfig {
23
24
  headerActions?: Array<NitroAction>;
24
25
  /**
25
26
  * @namespace Android title shown on header
27
+ * @namespace iOS title shown when mapConfig is set, otherwise it isn't supported
26
28
  */
27
29
  title?: AutoText;
28
30
  message: AutoText;
@@ -31,41 +33,86 @@ export interface NitroMessageTemplateConfig extends TemplateConfig {
31
33
  mapConfig?: NitroBaseMapTemplateConfig;
32
34
  }
33
35
 
34
- export type MessageTemplateConfig = Omit<
36
+ type MessageActionsAndroid<T> =
37
+ | [CustomActionButtonAndroid<T>]
38
+ | [CustomActionButtonAndroid<T>, CustomActionButtonAndroid<T>];
39
+
40
+ type MessageTemplateBaseConfig = Omit<
35
41
  NitroMessageTemplateConfig,
36
42
  'headerActions' | 'image' | 'mapConfig' | 'actions'
37
43
  > & {
38
44
  /**
39
45
  * action buttons, usually at the top right on Android
40
- * @namespace Android
46
+ * @namespace iOS `ios` only takes effect once this renders as a CPMapPanel (`mapConfig` set,
47
+ * iOS 27+) and is applied to the root map template's nav bar — without `mapConfig` (or below
48
+ * iOS 27, where `mapConfig` is a no-op) this template is a full-screen `CPAlertTemplate`, which
49
+ * has no nav bar at all, so `ios` is silently unused there.
41
50
  */
42
- headerActions?: HeaderActionsAndroid<MessageTemplate>;
51
+ headerActions?: HeaderActions<MessageTemplate>;
43
52
  /**
44
53
  * image shown at the top of the message on Android
45
54
  * @namespace Android
46
55
  */
47
56
  image?: AutoImage;
48
- /**
49
- * If mapConfig is defined, it will use a MapWithContentTemplate with the current template. This results in a MessageTemplate with a map in background. No actions need to be specified, can be empty object.
50
- * @namespace Android
51
- */
52
- mapConfig?: BaseMapTemplateConfig<MessageTemplate>;
53
-
54
- /**
55
- * @namespace Android up to 2 buttons of type TextButton, TextAndImageButton or ImageButton
56
- * @namespace iOS - up to 3 buttons of type TextButton
57
- */
58
- actions?: {
59
- android?:
60
- | [CustomActionButtonAndroid<MessageTemplate>]
61
- | [CustomActionButtonAndroid<MessageTemplate>, CustomActionButtonAndroid<MessageTemplate>];
62
- ios?:
63
- | [TextButton<MessageTemplate>, TextButton<MessageTemplate>, TextButton<MessageTemplate>]
64
- | [TextButton<MessageTemplate>, TextButton<MessageTemplate>]
65
- | [TextButton<MessageTemplate>];
66
- };
67
57
  };
68
58
 
59
+ /**
60
+ * `actions`/`mapConfig` are a discriminated union — `mapConfig` restricts `actions.ios` to at
61
+ * most one `TextButton` plus one icon-only `ImageButton` (a `CPMapPanel` can't show more), vs. up
62
+ * to three `TextButton`s otherwise. If your `mapConfig` value comes from a variable/prop rather
63
+ * than an inline literal, TS can't narrow which branch applies — assign it to a local `const` and
64
+ * branch with `if (mapConfig) { ... } else { ... }` into two separate constructor calls instead
65
+ * of passing it straight through to one.
66
+ */
67
+ export type MessageTemplateConfig = MessageTemplateBaseConfig &
68
+ (
69
+ | {
70
+ mapConfig?: undefined;
71
+
72
+ /**
73
+ * @namespace Android up to 2 buttons of type TextButton, TextAndImageButton or ImageButton
74
+ * @namespace iOS - up to 3 buttons of type TextButton
75
+ */
76
+ actions?: {
77
+ android?: MessageActionsAndroid<MessageTemplate>;
78
+ ios?:
79
+ | [
80
+ TextButton<MessageTemplate>,
81
+ TextButton<MessageTemplate>,
82
+ TextButton<MessageTemplate>,
83
+ ]
84
+ | [TextButton<MessageTemplate>, TextButton<MessageTemplate>]
85
+ | [TextButton<MessageTemplate>];
86
+ };
87
+ }
88
+ | {
89
+ /**
90
+ * If mapConfig is defined, it will use a MapWithContentTemplate with the current
91
+ * template. This results in a MessageTemplate with a map in background. No actions
92
+ * need to be specified, can be empty object.
93
+ * @namespace Android - uses MapWithContentTemplate
94
+ * @namespace iOS - renders as a CPMapPanel on the current root map template (iOS 27+),
95
+ * trading the usual full-screen modal alert presentation for panel content;
96
+ * `headerActions` here is Android-only — on iOS this template's own `headerActions` are
97
+ * applied to the root map template's nav bar instead, since CarPlay has no separate
98
+ * header for the map behind a panel.
99
+ */
100
+ mapConfig: Omit<BaseMapTemplateConfig<MessageTemplate>, 'headerActions'> & {
101
+ headerActions?: PanelHeaderActions<MessageTemplate>;
102
+ };
103
+
104
+ /**
105
+ * @namespace Android up to 2 buttons of type TextButton, TextAndImageButton or ImageButton
106
+ * @namespace iOS - the panel can only show one TextButton plus one optional icon-only
107
+ * ImageButton, see PanelActionsIos
108
+ */
109
+ actions?: {
110
+ android?: MessageActionsAndroid<MessageTemplate>;
111
+ ios?: PanelActionsIos<MessageTemplate>;
112
+ };
113
+ }
114
+ );
115
+
69
116
  /**
70
117
  * This template is always pushed on top and will stay on top until it is popped.
71
118
  * Other templates being pushed will end up below this one on the stack.
@@ -86,7 +133,7 @@ export class MessageTemplate {
86
133
  const nitroConfig: NitroMessageTemplateConfig & NitroTemplateConfig = {
87
134
  ...rest,
88
135
  id: this.id,
89
- headerActions: NitroActionUtil.convert(this.template, { android: headerActions }),
136
+ headerActions: NitroActionUtil.convert(this.template, headerActions),
90
137
  image: NitroImageUtil.convert(image),
91
138
  actions: platformActions,
92
139
  mapConfig: mapConfig
@@ -24,7 +24,8 @@ export type GlyphMapKey = keyof AutoPlayGlyphMap extends never
24
24
  type GlyphStyleFields = {
25
25
  /**
26
26
  * Sets the icon dark and light mode color or a single color for both.
27
- * Defaults to white for dark mode and black for light mode if not specified.
27
+ * Defaults to `'default'` if not specified, which is white for dark mode and black for light mode.
28
+ * On Android Auto the host tint that follows the template is not applied when `backgroundColor` is not transparent.
28
29
  * Might not get applied everywhere like MapTemplate buttons on Android.
29
30
  */
30
31
  color?: ThemedColor | string;
@@ -61,6 +62,8 @@ export type AutoImage =
61
62
  /**
62
63
  * if specified the image gets tinted, if not it will just use the original image
63
64
  * Might not get applied everywhere like MapTemplate buttons on Android.
65
+ * Use `'default'` for monochrome icons that must stay readable on both dark and light
66
+ * Android Auto templates (17.8+), see README.
64
67
  */
65
68
  color?: ThemedColor | string;
66
69
  type: 'asset';
@@ -70,6 +73,8 @@ export type AutoImage =
70
73
  uri: string;
71
74
  /**
72
75
  * if specified the image gets tinted, if not it will just use the original image
76
+ * Use `'default'` for monochrome icons that must stay readable on both dark and light
77
+ * Android Auto templates (17.8+), see README.
73
78
  */
74
79
  color?: ThemedColor | string;
75
80
  /**
@@ -1,8 +1,14 @@
1
1
  import { processColor } from 'react-native';
2
2
 
3
- export type NitroColor = { lightColor: number; darkColor: number };
3
+ export type NitroColor = { lightColor: number; darkColor: number; isDefault?: boolean };
4
4
  export type ThemedColor = { lightColor: string; darkColor: string };
5
5
 
6
+ const DefaultNitroColor = {
7
+ darkColor: convertColor('white'),
8
+ lightColor: convertColor('black'),
9
+ isDefault: true,
10
+ };
11
+
6
12
  function convertColor(color: string): number;
7
13
  function convertColor(color?: string): number | undefined;
8
14
  function convertColor(color?: string): number | undefined {
@@ -18,6 +24,9 @@ function convert(color?: ThemedColor | string): NitroColor | undefined {
18
24
  }
19
25
 
20
26
  if (typeof color === 'string') {
27
+ if (color === 'default') {
28
+ return DefaultNitroColor;
29
+ }
21
30
  const convertedColor = convertColor(color);
22
31
  return { darkColor: convertedColor, lightColor: convertedColor };
23
32
  }
@@ -96,11 +96,7 @@ function convert(image?: AutoImage): NitroImage | undefined {
96
96
  }
97
97
 
98
98
  if (image.type === 'glyph') {
99
- const {
100
- color = { darkColor: 'white', lightColor: 'black' },
101
- fontScale,
102
- backgroundColor = 'transparent',
103
- } = image;
99
+ const { color = 'default', fontScale, backgroundColor = 'transparent' } = image;
104
100
 
105
101
  return {
106
102
  glyph: resolveGlyph(image),
@@ -71,10 +71,7 @@ function convertManeuverImage(image?: ManeuverImage): NitroImage | undefined {
71
71
  }
72
72
 
73
73
  if (image.type === 'glyph') {
74
- const color =
75
- typeof image.color === 'string'
76
- ? image.color
77
- : (image.color ?? { darkColor: 'white', lightColor: 'black' });
74
+ const color = typeof image.color === 'string' ? image.color : (image.color ?? 'default');
78
75
  return NitroImageUtil.convert({
79
76
  ...image,
80
77
  color: color,
@@ -0,0 +1,218 @@
1
+ import type { ImageButton, TextButton } from '../types/Button';
2
+ import type { AutoImage } from '../types/Image';
3
+ import type { AutoText, Distance } from '../types/Text';
4
+ import type { DurationWithTimeZone } from '../types/Trip';
5
+ import { type NitroAction, NitroActionUtil } from './NitroAction';
6
+ import { type GridButton, type NitroGridButton, NitroGridUtil } from './NitroGrid';
7
+ import { type NitroImage, NitroImageUtil } from './NitroImage';
8
+ import {
9
+ type DefaultRow,
10
+ type MultiSection,
11
+ type NitroSection,
12
+ NitroSectionUtil,
13
+ type RadioRow,
14
+ type TextRow,
15
+ type ToggleRow,
16
+ type WaypointCoordinate,
17
+ type WaypointRow,
18
+ } from './NitroSection';
19
+
20
+ export type OptionsPanelGridSection<T> = {
21
+ type: 'grid';
22
+ title?: string;
23
+ buttons: Array<GridButton<T>>;
24
+ };
25
+
26
+ export type ChargingConnector =
27
+ | 'ccs1'
28
+ | 'ccs2'
29
+ | 'j1772'
30
+ | 'chaDeMo'
31
+ | 'mennekes'
32
+ | 'gbtDC'
33
+ | 'gbtAC'
34
+ | 'nacsDC'
35
+ | 'nacsAC';
36
+
37
+ /**
38
+ * one outlet (`CPChargingStationConnection`) on a charging station.
39
+ */
40
+ export type ChargerOutlet<T> = {
41
+ connector: ChargingConnector;
42
+ voltage: number;
43
+ /** converted to megawatts on the native side above 1000 kW */
44
+ powerKw: number;
45
+ onPress?: (template: T) => void;
46
+ };
47
+
48
+ /**
49
+ * the charging station's own location, shown as an additional `CPMapTemplateWaypoint` item in
50
+ * the charger section, alongside its outlets.
51
+ */
52
+ export type ChargerLocation<T> = {
53
+ /**
54
+ * the item's own label — distinct from the section's `title`, which is already shown as the
55
+ * section header, so this defaults to blank rather than repeating it.
56
+ */
57
+ name?: string;
58
+ /** newline-separated address lines, most-preferred first */
59
+ address?: string;
60
+ coordinate: WaypointCoordinate;
61
+ travelEstimates: {
62
+ distance: Distance;
63
+ duration: DurationWithTimeZone;
64
+ /**
65
+ * by default travel estimates are not shown
66
+ * setting this to true add another row showing CPTravelEstimates
67
+ */
68
+ visible?: boolean;
69
+ };
70
+ image?: AutoImage;
71
+ onPress?: (template: T) => void;
72
+ };
73
+
74
+ /**
75
+ * charger section having n-ChargerOutlet
76
+ */
77
+ export type OptionsPanelChargerSection<T> = {
78
+ type: 'charger';
79
+ title?: string;
80
+ outlets: Array<ChargerOutlet<T>>;
81
+ location?: ChargerLocation<T>;
82
+ };
83
+
84
+ export type OptionsPanelListSection<T> = {
85
+ type: 'list';
86
+ title?: string;
87
+ items: Array<DefaultRow<T> | ToggleRow<T> | TextRow | WaypointRow<T>> | Array<RadioRow<T>>;
88
+ };
89
+
90
+ export type OptionsPanelSection<T> =
91
+ | OptionsPanelListSection<T>
92
+ | OptionsPanelGridSection<T>
93
+ | OptionsPanelChargerSection<T>;
94
+
95
+ export type OptionsPanelConfig<T> = {
96
+ title?: AutoText;
97
+ sections: Array<OptionsPanelSection<T>>;
98
+ actions?: [TextButton<T>] | [TextButton<T>, ImageButton<T>];
99
+ };
100
+
101
+ export type NitroOptionsPanelGridSection = {
102
+ title?: string;
103
+ buttons: Array<NitroGridButton>;
104
+ };
105
+
106
+ export type NitroChargerOutlet = {
107
+ connector: ChargingConnector;
108
+ voltage: number;
109
+ powerKw: number;
110
+ onPress?: () => void;
111
+ };
112
+
113
+ export type NitroChargerLocation = {
114
+ name?: string;
115
+ address?: string;
116
+ coordinate: WaypointCoordinate;
117
+ distance: Distance;
118
+ duration: DurationWithTimeZone;
119
+ visible?: boolean;
120
+ image?: NitroImage;
121
+ onPress?: () => void;
122
+ };
123
+
124
+ export type NitroOptionsPanelChargerSection = {
125
+ title?: string;
126
+ outlets: Array<NitroChargerOutlet>;
127
+ location?: NitroChargerLocation;
128
+ };
129
+
130
+ export type NitroOptionsPanelSection =
131
+ | NitroSection
132
+ | NitroOptionsPanelGridSection
133
+ | NitroOptionsPanelChargerSection;
134
+
135
+ export type NitroOptionsPanelConfig = {
136
+ title?: AutoText;
137
+ sections: Array<NitroOptionsPanelSection>;
138
+ actions?: Array<NitroAction>;
139
+ };
140
+
141
+ const isRadioSection = <T>(
142
+ items: OptionsPanelListSection<T>['items']
143
+ ): items is Array<RadioRow<T>> => {
144
+ return items.length > 0 && items.every((item) => item.type === 'radio');
145
+ };
146
+
147
+ const convertSection = <T>(
148
+ template: T,
149
+ section: OptionsPanelSection<T>
150
+ ): NitroOptionsPanelSection => {
151
+ if (section.type === 'grid') {
152
+ return {
153
+ title: section.title,
154
+ buttons: NitroGridUtil.convert(template, section.buttons),
155
+ };
156
+ }
157
+
158
+ if (section.type === 'charger') {
159
+ const { location } = section;
160
+
161
+ return {
162
+ title: section.title,
163
+ outlets: section.outlets.map((outlet) => ({
164
+ connector: outlet.connector,
165
+ voltage: outlet.voltage,
166
+ powerKw: outlet.powerKw,
167
+ onPress: outlet.onPress ? () => outlet.onPress?.(template) : undefined,
168
+ })),
169
+ location: location
170
+ ? {
171
+ name: location.name,
172
+ address: location.address,
173
+ coordinate: location.coordinate,
174
+ distance: location.travelEstimates.distance,
175
+ duration: location.travelEstimates.duration,
176
+ visible: location.travelEstimates.visible,
177
+ image: NitroImageUtil.convert(location.image),
178
+ onPress: location.onPress ? () => location.onPress?.(template) : undefined,
179
+ }
180
+ : undefined,
181
+ };
182
+ }
183
+
184
+ const { items, title = '' } = section;
185
+
186
+ const multiSection: MultiSection<T> = isRadioSection(items)
187
+ ? { type: 'radio', title, items }
188
+ : {
189
+ type: 'default',
190
+ title,
191
+ items,
192
+ };
193
+
194
+ const [nitroSection] = NitroSectionUtil.convert(template, [multiSection]) ?? [];
195
+
196
+ if (nitroSection == null) {
197
+ throw new Error('converting sections failed');
198
+ }
199
+
200
+ return nitroSection;
201
+ };
202
+
203
+ const convert = <T>(
204
+ template: T,
205
+ config?: OptionsPanelConfig<T>
206
+ ): NitroOptionsPanelConfig | undefined => {
207
+ if (config == null) {
208
+ return undefined;
209
+ }
210
+
211
+ return {
212
+ title: config.title,
213
+ sections: config.sections.map((section) => convertSection(template, section)),
214
+ actions: NitroActionUtil.convert(template, config.actions),
215
+ };
216
+ };
217
+
218
+ export const NitroOptionsPanelUtil = { convert };