@expo/ui 58.0.14 → 58.0.16

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 (130) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/ui/DatePickerView.kt +35 -2
  4. package/android/src/main/java/expo/modules/ui/DateRangePickerView.kt +35 -2
  5. package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +3 -0
  6. package/android/src/main/java/expo/modules/ui/HostView.kt +21 -0
  7. package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +2 -2
  8. package/android/src/main/java/expo/modules/ui/RNHostView.kt +117 -1
  9. package/android/src/main/java/expo/modules/ui/menu/DropdownMenu.kt +8 -1
  10. package/android/src/main/java/expo/modules/ui/menu/DropdownMenuRecords.kt +13 -1
  11. package/build/NativeTreeContext.d.ts +10 -0
  12. package/build/NativeTreeContext.js +25 -0
  13. package/build/NativeTreeContext.js.map +1 -0
  14. package/build/State/useWorkletCallback.d.ts +1 -1
  15. package/build/community/bottom-sheet/BottomSheet.ios.js +11 -4
  16. package/build/community/bottom-sheet/BottomSheet.ios.js.map +1 -1
  17. package/build/community/datetime-picker/DateTimePicker.android.js +4 -0
  18. package/build/community/datetime-picker/DateTimePicker.android.js.map +1 -1
  19. package/build/community/menu/MenuView.android.js +6 -0
  20. package/build/community/menu/MenuView.android.js.map +1 -1
  21. package/build/jetpack-compose/DatePicker/index.d.ts +38 -0
  22. package/build/jetpack-compose/DatePicker/index.js.map +1 -1
  23. package/build/jetpack-compose/DropdownMenu/index.d.ts +8 -1
  24. package/build/jetpack-compose/DropdownMenu/index.js.map +1 -1
  25. package/build/jetpack-compose/Host/index.js +8 -2
  26. package/build/jetpack-compose/Host/index.js.map +1 -1
  27. package/build/jetpack-compose/RNHostView/index.js +5 -1
  28. package/build/jetpack-compose/RNHostView/index.js.map +1 -1
  29. package/build/swift-ui/Chart/index.d.ts +10 -0
  30. package/build/swift-ui/Chart/index.js.map +1 -1
  31. package/build/swift-ui/Host/index.js +8 -2
  32. package/build/swift-ui/Host/index.js.map +1 -1
  33. package/build/swift-ui/RNHostView.js +5 -1
  34. package/build/swift-ui/RNHostView.js.map +1 -1
  35. package/build/swift-ui/Toolbar/index.d.ts +2 -0
  36. package/build/swift-ui/Toolbar/index.js +2 -0
  37. package/build/swift-ui/Toolbar/index.js.map +1 -1
  38. package/build/swift-ui/modifiers/hingeObservation.d.ts +1 -1
  39. package/build/swift-ui/modifiers/hingeObservation.js +1 -1
  40. package/build/swift-ui/modifiers/index.d.ts +1 -0
  41. package/build/swift-ui/modifiers/index.js +1 -0
  42. package/build/swift-ui/modifiers/index.js.map +1 -1
  43. package/build/swift-ui/modifiers/presentationModifiers.d.ts +17 -1
  44. package/build/swift-ui/modifiers/presentationModifiers.js +4 -2
  45. package/build/swift-ui/modifiers/presentationModifiers.js.map +1 -1
  46. package/build/swift-ui/modifiers/searchable.d.ts +83 -0
  47. package/build/swift-ui/modifiers/searchable.js +74 -0
  48. package/build/swift-ui/modifiers/searchable.js.map +1 -0
  49. package/build/types.d.ts +27 -0
  50. package/build/types.js +1 -1
  51. package/build/types.js.map +1 -1
  52. package/build/universal/BottomSheet/index.android.js +26 -18
  53. package/build/universal/BottomSheet/index.android.js.map +1 -1
  54. package/build/universal/BottomSheet/index.ios.js +20 -12
  55. package/build/universal/BottomSheet/index.ios.js.map +1 -1
  56. package/ios/ChartView.swift +15 -10
  57. package/ios/DataListForEachView.swift +1 -0
  58. package/ios/GridView.swift +1 -0
  59. package/ios/HostView.swift +27 -4
  60. package/ios/Modifiers/PresentationModifiers.swift +20 -4
  61. package/ios/Modifiers/SearchToolbarBehaviorModifier.swift +35 -0
  62. package/ios/Modifiers/SearchableModifier.swift +94 -0
  63. package/ios/Modifiers/ViewModifierRegistry.swift +8 -0
  64. package/ios/NamespaceView.swift +1 -0
  65. package/ios/Picker/PickerView.swift +9 -7
  66. package/ios/RNHostView.swift +19 -4
  67. package/ios/SlotView.swift +1 -0
  68. package/ios/TabView/TabView.swift +2 -0
  69. package/ios/ToolbarView.swift +2 -1
  70. package/ios/UIBaseView.swift +13 -0
  71. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.14/expo.modules.ui-58.0.14-sources.jar → 58.0.16/expo.modules.ui-58.0.16-sources.jar} +0 -0
  72. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16-sources.jar.md5 +1 -0
  73. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16-sources.jar.sha1 +1 -0
  74. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16-sources.jar.sha256 +1 -0
  75. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16-sources.jar.sha512 +1 -0
  76. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar +0 -0
  77. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.md5 +1 -0
  78. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.sha1 +1 -0
  79. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.sha256 +1 -0
  80. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.sha512 +1 -0
  81. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.14/expo.modules.ui-58.0.14.module → 58.0.16/expo.modules.ui-58.0.16.module} +22 -22
  82. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.md5 +1 -0
  83. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.sha1 +1 -0
  84. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.sha256 +1 -0
  85. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.sha512 +1 -0
  86. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.14/expo.modules.ui-58.0.14.pom → 58.0.16/expo.modules.ui-58.0.16.pom} +1 -1
  87. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.md5 +1 -0
  88. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.sha1 +1 -0
  89. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.sha256 +1 -0
  90. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.sha512 +1 -0
  91. package/package.json +2 -2
  92. package/prebuilds/output/debug/xcframeworks/ExpoUI.tar.gz +0 -0
  93. package/prebuilds/output/release/xcframeworks/ExpoUI.tar.gz +0 -0
  94. package/src/NativeTreeContext.tsx +31 -0
  95. package/src/State/useWorkletCallback.ts +1 -1
  96. package/src/community/bottom-sheet/BottomSheet.ios.tsx +7 -6
  97. package/src/community/datetime-picker/DateTimePicker.android.tsx +4 -0
  98. package/src/community/menu/MenuView.android.tsx +12 -2
  99. package/src/jetpack-compose/DatePicker/index.tsx +38 -0
  100. package/src/jetpack-compose/DropdownMenu/index.tsx +12 -1
  101. package/src/jetpack-compose/Host/index.tsx +6 -2
  102. package/src/jetpack-compose/RNHostView/index.tsx +3 -1
  103. package/src/swift-ui/Chart/index.tsx +10 -0
  104. package/src/swift-ui/Host/index.tsx +6 -2
  105. package/src/swift-ui/RNHostView.tsx +3 -1
  106. package/src/swift-ui/Toolbar/index.tsx +2 -0
  107. package/src/swift-ui/modifiers/hingeObservation.ts +1 -1
  108. package/src/swift-ui/modifiers/index.ts +1 -0
  109. package/src/swift-ui/modifiers/presentationModifiers.ts +18 -2
  110. package/src/swift-ui/modifiers/searchable.ts +107 -0
  111. package/src/types.ts +28 -0
  112. package/src/universal/BottomSheet/index.android.tsx +23 -12
  113. package/src/universal/BottomSheet/index.ios.tsx +20 -9
  114. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14-sources.jar.md5 +0 -1
  115. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14-sources.jar.sha1 +0 -1
  116. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14-sources.jar.sha256 +0 -1
  117. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14-sources.jar.sha512 +0 -1
  118. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar +0 -0
  119. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar.md5 +0 -1
  120. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar.sha1 +0 -1
  121. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar.sha256 +0 -1
  122. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar.sha512 +0 -1
  123. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.module.md5 +0 -1
  124. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.module.sha1 +0 -1
  125. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.module.sha256 +0 -1
  126. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.module.sha512 +0 -1
  127. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.pom.md5 +0 -1
  128. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.pom.sha1 +0 -1
  129. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.pom.sha256 +0 -1
  130. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.pom.sha512 +0 -1
@@ -0,0 +1,83 @@
1
+ import { type ObservableState } from '../../State';
2
+ /**
3
+ * The placement of a search field in a view hierarchy.
4
+ *
5
+ * - `automatic`: SwiftUI places the search field automatically.
6
+ * - `toolbar`: The search field appears in the toolbar. Falls back to `automatic` on tvOS.
7
+ * - `sidebar`: The search field appears in the sidebar of a navigation view. Falls back to
8
+ * `automatic` on tvOS.
9
+ * - `navigationBarDrawer`: The search field appears in the navigation bar. Falls back to
10
+ * `automatic` on macOS and tvOS.
11
+ */
12
+ export type SearchFieldPlacement = 'automatic' | 'toolbar' | 'sidebar' | 'navigationBarDrawer';
13
+ /**
14
+ * Marks this view as searchable, which configures the display of a search field.
15
+ *
16
+ * @param text - The text to display and edit in the search field. An `ObservableState<string>`
17
+ * created with `useNativeState`.
18
+ * @param options.placement - The preferred placement of the search field within the containing
19
+ * view hierarchy. Defaults to `automatic`.
20
+ * @param options.prompt - The prompt of the search field, which provides users with guidance on
21
+ * what to search for.
22
+ * @param options.onChange - Fires on the JS thread when the user edits or clears the search field.
23
+ * It does not fire for values written from JavaScript.
24
+ *
25
+ * @platform ios
26
+ * @platform tvos
27
+ * @platform macos
28
+ *
29
+ * @see Official [SwiftUI documentation](https://developer.apple.com/documentation/swiftui/view/searchable(text:placement:prompt:)-18a8f).
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * const query = useNativeState('');
34
+ *
35
+ * <Host>
36
+ * <NavigationStack>
37
+ * <List
38
+ * modifiers={[
39
+ * searchable(query, {
40
+ * prompt: 'Search agents',
41
+ * onChange: (text) => setFilter(text),
42
+ * }),
43
+ * ]}>
44
+ * {rows.map((row) => (
45
+ * <Text key={row.id}>{row.name}</Text>
46
+ * ))}
47
+ * </List>
48
+ * </NavigationStack>
49
+ * </Host>
50
+ * ```
51
+ */
52
+ export declare const searchable: (text: ObservableState<string>, options?: {
53
+ placement?: SearchFieldPlacement;
54
+ prompt?: string;
55
+ onChange?: (text: string) => void;
56
+ }) => import("./createModifier").ModifierConfig;
57
+ /**
58
+ * The behavior of a search field in a toolbar.
59
+ *
60
+ * - `automatic`: The automatic behavior.
61
+ * - `minimize`: A search toolbar behavior that prefers rendering a search field as a button-like
62
+ * control. Falls back to `automatic` on macOS and tvOS.
63
+ */
64
+ export type SearchToolbarBehavior = 'automatic' | 'minimize';
65
+ /**
66
+ * Configures the behavior for search in the toolbar.
67
+ *
68
+ * On iOS below 26.0, the modifier is a no-op.
69
+ *
70
+ * @param behavior - The search field behavior.
71
+ *
72
+ * @platform ios 26.0+
73
+ * @platform tvos 26.0+
74
+ * @platform macos 26.0+
75
+ *
76
+ * @see Official [SwiftUI documentation](https://developer.apple.com/documentation/swiftui/view/searchtoolbarbehavior(_:)).
77
+ *
78
+ * @example
79
+ * ```tsx
80
+ * <List modifiers={[searchable(query), searchToolbarBehavior('minimize')]}>
81
+ * ```
82
+ */
83
+ export declare const searchToolbarBehavior: (behavior: SearchToolbarBehavior) => import("./createModifier").ModifierConfig;
@@ -0,0 +1,74 @@
1
+ import { getStateId } from '../../State';
2
+ import { createModifier, createModifierWithEventListener } from './createModifier';
3
+ /**
4
+ * Marks this view as searchable, which configures the display of a search field.
5
+ *
6
+ * @param text - The text to display and edit in the search field. An `ObservableState<string>`
7
+ * created with `useNativeState`.
8
+ * @param options.placement - The preferred placement of the search field within the containing
9
+ * view hierarchy. Defaults to `automatic`.
10
+ * @param options.prompt - The prompt of the search field, which provides users with guidance on
11
+ * what to search for.
12
+ * @param options.onChange - Fires on the JS thread when the user edits or clears the search field.
13
+ * It does not fire for values written from JavaScript.
14
+ *
15
+ * @platform ios
16
+ * @platform tvos
17
+ * @platform macos
18
+ *
19
+ * @see Official [SwiftUI documentation](https://developer.apple.com/documentation/swiftui/view/searchable(text:placement:prompt:)-18a8f).
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * const query = useNativeState('');
24
+ *
25
+ * <Host>
26
+ * <NavigationStack>
27
+ * <List
28
+ * modifiers={[
29
+ * searchable(query, {
30
+ * prompt: 'Search agents',
31
+ * onChange: (text) => setFilter(text),
32
+ * }),
33
+ * ]}>
34
+ * {rows.map((row) => (
35
+ * <Text key={row.id}>{row.name}</Text>
36
+ * ))}
37
+ * </List>
38
+ * </NavigationStack>
39
+ * </Host>
40
+ * ```
41
+ */ export const searchable = (text, options)=>{
42
+ const params = {
43
+ text: getStateId(text),
44
+ placement: options?.placement,
45
+ prompt: options?.prompt
46
+ };
47
+ const onChange = options?.onChange;
48
+ if (onChange) {
49
+ return createModifierWithEventListener('searchable', (event)=>onChange(event?.text ?? ''), params);
50
+ }
51
+ return createModifier('searchable', params);
52
+ };
53
+ /**
54
+ * Configures the behavior for search in the toolbar.
55
+ *
56
+ * On iOS below 26.0, the modifier is a no-op.
57
+ *
58
+ * @param behavior - The search field behavior.
59
+ *
60
+ * @platform ios 26.0+
61
+ * @platform tvos 26.0+
62
+ * @platform macos 26.0+
63
+ *
64
+ * @see Official [SwiftUI documentation](https://developer.apple.com/documentation/swiftui/view/searchtoolbarbehavior(_:)).
65
+ *
66
+ * @example
67
+ * ```tsx
68
+ * <List modifiers={[searchable(query), searchToolbarBehavior('minimize')]}>
69
+ * ```
70
+ */ export const searchToolbarBehavior = (behavior)=>createModifier('searchToolbarBehavior', {
71
+ behavior
72
+ });
73
+
74
+ //# sourceMappingURL=searchable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["swift-ui/modifiers/searchable.ts"],"sourcesContent":[null],"names":["getStateId","createModifier","createModifierWithEventListener","searchable","text","options","params","placement","prompt","onChange","event","searchToolbarBehavior","behavior"],"mappings":"AAAA,SAASA,UAAU,QAA8B,cAAc;AAC/D,SAASC,cAAc,EAAEC,+BAA+B,QAAQ,mBAAmB;AAcnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCC,GACD,OAAO,MAAMC,aAAa,CACxBC,MACAC;IAMA,MAAMC,SAAS;QACbF,MAAMJ,WAAWI;QACjBG,WAAWF,SAASE;QACpBC,QAAQH,SAASG;IACnB;IACA,MAAMC,WAAWJ,SAASI;IAC1B,IAAIA,UAAU;QACZ,OAAOP,gCACL,cACA,CAACQ,QAA6BD,SAASC,OAAON,QAAQ,KACtDE;IAEJ;IACA,OAAOL,eAAe,cAAcK;AACtC,EAAE;AAWF;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,MAAMK,wBAAwB,CAACC,WACpCX,eAAe,yBAAyB;QAAEW;IAAS,GAAG"}
package/build/types.d.ts CHANGED
@@ -44,3 +44,30 @@ export type DialogProperties = {
44
44
  */
45
45
  decorFitsSystemWindows?: boolean;
46
46
  };
47
+ /**
48
+ * Properties for the popup window, matching `PopupProperties` in Compose.
49
+ */
50
+ export type PopupProperties = {
51
+ /**
52
+ * Whether the popup is focusable. When `true`, the popup receives IME events and key presses,
53
+ * such as the back button.
54
+ * @default true
55
+ */
56
+ focusable?: boolean;
57
+ /**
58
+ * Whether the popup can be dismissed by pressing the back button. Has no effect when `focusable` is `false`.
59
+ * @default true
60
+ */
61
+ dismissOnBackPress?: boolean;
62
+ /**
63
+ * Whether the popup can be dismissed by clicking outside of its bounds.
64
+ * @default true
65
+ */
66
+ dismissOnClickOutside?: boolean;
67
+ /**
68
+ * Whether the popup window is clipped to the screen boundaries. Set to `false` to let it extend
69
+ * beyond them, which positions the popup accurately.
70
+ * @default true
71
+ */
72
+ clippingEnabled?: boolean;
73
+ };
package/build/types.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @hidden
3
3
  */ /**
4
- * Properties for the dialog window, matching `DialogProperties` in Compose.
4
+ * Properties for the popup window, matching `PopupProperties` in Compose.
5
5
  */ export { };
6
6
 
7
7
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["types.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;CAEC,GAwBD;;CAEC,GACD,WAsBE"}
1
+ {"version":3,"sources":["types.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;CAEC,GAmDD;;CAEC,GACD,WAuBE"}
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Column, Host, ModalBottomSheet } from '@expo/ui/jetpack-compose';
3
3
  import { fillMaxHeight, padding, testID as testIDModifier } from '@expo/ui/jetpack-compose/modifiers';
4
4
  import { useEffect, useRef, useState } from 'react';
5
+ import { useIsInsideNativeTree } from '../../NativeTreeContext';
5
6
  import { resolveContentPadding } from './utils';
6
7
  // M3 `ModalBottomSheet` only has partial/expanded states.
7
8
  // Only allow the partial state when the consumer requested a partial-friendly snap point.
@@ -16,6 +17,7 @@ function shouldFillMaxHeight(snapPoints) {
16
17
  return snapPoints.some((sp)=>sp === 'full' || typeof sp === 'object' && 'fraction' in sp && sp.fraction >= 1);
17
18
  }
18
19
  export function BottomSheet({ children, isPresented, onDismiss, showDragIndicator = true, snapPoints, testID, modifiers, shouldDismissOnBackPress = true, shouldDismissOnClickOutside = true, scrimColor, contentPadding, containerColor, contentColor }) {
20
+ const isInsideHost = useIsInsideNativeTree();
19
21
  const sheetRef = useRef(null);
20
22
  const [mount, setMount] = useState(isPresented);
21
23
  useEffect(()=>{
@@ -49,29 +51,35 @@ export function BottomSheet({ children, isPresented, onDismiss, showDragIndicato
49
51
  ];
50
52
  if (shouldFillMaxHeight(snapPoints)) contentModifiers.push(fillMaxHeight());
51
53
  if (testID) contentModifiers.push(testIDModifier(testID));
54
+ const sheet = /*#__PURE__*/ _jsx(ModalBottomSheet, {
55
+ ref: sheetRef,
56
+ onDismissRequest: onDismiss,
57
+ showDragHandle: showDragIndicator,
58
+ skipPartiallyExpanded: shouldSkipPartiallyExpanded(snapPoints),
59
+ properties: {
60
+ shouldDismissOnBackPress,
61
+ shouldDismissOnClickOutside
62
+ },
63
+ scrimColor: scrimColor,
64
+ containerColor: containerColor,
65
+ contentColor: contentColor,
66
+ modifiers: modifiers,
67
+ children: /*#__PURE__*/ _jsx(Column, {
68
+ modifiers: contentModifiers,
69
+ children: children
70
+ })
71
+ });
72
+ // Already inside a `Host`, for example nested in another sheet's content: a `Host` of its own
73
+ // would be a `Host` directly inside Compose.
74
+ if (isInsideHost) {
75
+ return sheet;
76
+ }
52
77
  return /*#__PURE__*/ _jsx(Host, {
53
78
  style: {
54
79
  position: 'absolute'
55
80
  },
56
81
  pointerEvents: "none",
57
- children: /*#__PURE__*/ _jsx(ModalBottomSheet, {
58
- ref: sheetRef,
59
- onDismissRequest: onDismiss,
60
- showDragHandle: showDragIndicator,
61
- skipPartiallyExpanded: shouldSkipPartiallyExpanded(snapPoints),
62
- properties: {
63
- shouldDismissOnBackPress,
64
- shouldDismissOnClickOutside
65
- },
66
- scrimColor: scrimColor,
67
- containerColor: containerColor,
68
- contentColor: contentColor,
69
- modifiers: modifiers,
70
- children: /*#__PURE__*/ _jsx(Column, {
71
- modifiers: contentModifiers,
72
- children: children
73
- })
74
- })
82
+ children: sheet
75
83
  });
76
84
  }
77
85
  export * from './types';
@@ -1 +1 @@
1
- {"version":3,"sources":["universal/BottomSheet/index.android.tsx"],"sourcesContent":[null],"names":["Column","Host","ModalBottomSheet","fillMaxHeight","padding","testID","testIDModifier","useEffect","useRef","useState","resolveContentPadding","shouldSkipPartiallyExpanded","snapPoints","length","some","sp","fraction","shouldFillMaxHeight","BottomSheet","children","isPresented","onDismiss","showDragIndicator","modifiers","shouldDismissOnBackPress","shouldDismissOnClickOutside","scrimColor","contentPadding","containerColor","contentColor","sheetRef","mount","setMount","cancelled","current","hide","then","top","bottom","left","right","contentModifiers","push","style","position","pointerEvents","ref","onDismissRequest","showDragHandle","skipPartiallyExpanded","properties"],"mappings":";AAAA,SAASA,MAAM,EAAEC,IAAI,EAAEC,gBAAgB,QAAkC,2BAA2B;AACpG,SACEC,aAAa,EACbC,OAAO,EACPC,UAAUC,cAAc,QAEnB,qCAAqC;AAC5C,SAASC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AAGpD,SAASC,qBAAqB,QAAQ,UAAU;AAEhD,0DAA0D;AAC1D,0FAA0F;AAC1F,SAASC,4BAA4BC,UAAmC;IACtE,IAAI,CAACA,cAAcA,WAAWC,MAAM,KAAK,GAAG,OAAO;IACnD,OAAO,CAACD,WAAWE,IAAI,CACrB,CAACC,KACCA,OAAO,UACN,OAAOA,OAAO,YAAY,cAAcA,MAAMA,GAAGC,QAAQ,GAAG,KAC5D,OAAOD,OAAO,YAAY,YAAYA;AAE7C;AAEA,wCAAwC;AACxC,uGAAuG;AACvG,SAASE,oBAAoBL,UAAmC;IAC9D,IAAI,CAACA,cAAcA,WAAWC,MAAM,KAAK,GAAG,OAAO;IACnD,OAAOD,WAAWE,IAAI,CACpB,CAACC,KAAOA,OAAO,UAAW,OAAOA,OAAO,YAAY,cAAcA,MAAMA,GAAGC,QAAQ,IAAI;AAE3F;AAEA,OAAO,SAASE,YAAY,EAC1BC,QAAQ,EACRC,WAAW,EACXC,SAAS,EACTC,oBAAoB,IAAI,EACxBV,UAAU,EACVP,MAAM,EACNkB,SAAS,EACTC,2BAA2B,IAAI,EAC/BC,8BAA8B,IAAI,EAClCC,UAAU,EACVC,cAAc,EACdC,cAAc,EACdC,YAAY,EACK;IACjB,MAAMC,WAAWtB,OAA4B;IAC7C,MAAM,CAACuB,OAAOC,SAAS,GAAGvB,SAASW;IAEnCb,UAAU;QACR,IAAIa,aAAa;YACfY,SAAS;YACT;QACF;QACA,IAAIC,YAAY;QAChBH,SAASI,OAAO,EAAEC,OAAOC,KAAK;YAC5B,IAAI,CAACH,WAAWD,SAAS;QAC3B;QACA,OAAO;YACLC,YAAY;QACd;IACF,GAAG;QAACb;KAAY;IAEhB,IAAI,CAACW,OAAO;QACV,OAAO;IACT;IAEA,6FAA6F;IAC7F,qCAAqC;IACrC,MAAM,EAAEM,GAAG,EAAEC,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAG9B,sBAAsBiB,gBAAgB;QACzEU,KAAKf,oBAAoB,IAAI;QAC7BgB,QAAQ;QACRC,MAAM;QACNC,OAAO;IACT;IACA,MAAMC,mBAAqC;QAACrC,QAAQmC,MAAMF,KAAKG,OAAOF;KAAQ;IAC9E,IAAIrB,oBAAoBL,aAAa6B,iBAAiBC,IAAI,CAACvC;IAC3D,IAAIE,QAAQoC,iBAAiBC,IAAI,CAACpC,eAAeD;IAEjD,qBACE,KAACJ;QAAK0C,OAAO;YAAEC,UAAU;QAAW;QAAGC,eAAc;kBACnD,cAAA,KAAC3C;YACC4C,KAAKhB;YACLiB,kBAAkB1B;YAClB2B,gBAAgB1B;YAChB2B,uBAAuBtC,4BAA4BC;YACnDsC,YAAY;gBAAE1B;gBAA0BC;YAA4B;YACpEC,YAAYA;YACZE,gBAAgBA;YAChBC,cAAcA;YACdN,WAAWA;sBACX,cAAA,KAACvB;gBAAOuB,WAAWkB;0BAAmBtB;;;;AAI9C;AAEA,cAAc,UAAU"}
1
+ {"version":3,"sources":["universal/BottomSheet/index.android.tsx"],"sourcesContent":[null],"names":["Column","Host","ModalBottomSheet","fillMaxHeight","padding","testID","testIDModifier","useEffect","useRef","useState","useIsInsideNativeTree","resolveContentPadding","shouldSkipPartiallyExpanded","snapPoints","length","some","sp","fraction","shouldFillMaxHeight","BottomSheet","children","isPresented","onDismiss","showDragIndicator","modifiers","shouldDismissOnBackPress","shouldDismissOnClickOutside","scrimColor","contentPadding","containerColor","contentColor","isInsideHost","sheetRef","mount","setMount","cancelled","current","hide","then","top","bottom","left","right","contentModifiers","push","sheet","ref","onDismissRequest","showDragHandle","skipPartiallyExpanded","properties","style","position","pointerEvents"],"mappings":";AAAA,SAASA,MAAM,EAAEC,IAAI,EAAEC,gBAAgB,QAAkC,2BAA2B;AACpG,SACEC,aAAa,EACbC,OAAO,EACPC,UAAUC,cAAc,QAEnB,qCAAqC;AAC5C,SAASC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AAEpD,SAASC,qBAAqB,QAAQ,0BAA0B;AAEhE,SAASC,qBAAqB,QAAQ,UAAU;AAEhD,0DAA0D;AAC1D,0FAA0F;AAC1F,SAASC,4BAA4BC,UAAmC;IACtE,IAAI,CAACA,cAAcA,WAAWC,MAAM,KAAK,GAAG,OAAO;IACnD,OAAO,CAACD,WAAWE,IAAI,CACrB,CAACC,KACCA,OAAO,UACN,OAAOA,OAAO,YAAY,cAAcA,MAAMA,GAAGC,QAAQ,GAAG,KAC5D,OAAOD,OAAO,YAAY,YAAYA;AAE7C;AAEA,wCAAwC;AACxC,uGAAuG;AACvG,SAASE,oBAAoBL,UAAmC;IAC9D,IAAI,CAACA,cAAcA,WAAWC,MAAM,KAAK,GAAG,OAAO;IACnD,OAAOD,WAAWE,IAAI,CACpB,CAACC,KAAOA,OAAO,UAAW,OAAOA,OAAO,YAAY,cAAcA,MAAMA,GAAGC,QAAQ,IAAI;AAE3F;AAEA,OAAO,SAASE,YAAY,EAC1BC,QAAQ,EACRC,WAAW,EACXC,SAAS,EACTC,oBAAoB,IAAI,EACxBV,UAAU,EACVR,MAAM,EACNmB,SAAS,EACTC,2BAA2B,IAAI,EAC/BC,8BAA8B,IAAI,EAClCC,UAAU,EACVC,cAAc,EACdC,cAAc,EACdC,YAAY,EACK;IACjB,MAAMC,eAAerB;IACrB,MAAMsB,WAAWxB,OAA4B;IAC7C,MAAM,CAACyB,OAAOC,SAAS,GAAGzB,SAASY;IAEnCd,UAAU;QACR,IAAIc,aAAa;YACfa,SAAS;YACT;QACF;QACA,IAAIC,YAAY;QAChBH,SAASI,OAAO,EAAEC,OAAOC,KAAK;YAC5B,IAAI,CAACH,WAAWD,SAAS;QAC3B;QACA,OAAO;YACLC,YAAY;QACd;IACF,GAAG;QAACd;KAAY;IAEhB,IAAI,CAACY,OAAO;QACV,OAAO;IACT;IAEA,6FAA6F;IAC7F,qCAAqC;IACrC,MAAM,EAAEM,GAAG,EAAEC,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAG/B,sBAAsBiB,gBAAgB;QACzEW,KAAKhB,oBAAoB,IAAI;QAC7BiB,QAAQ;QACRC,MAAM;QACNC,OAAO;IACT;IACA,MAAMC,mBAAqC;QAACvC,QAAQqC,MAAMF,KAAKG,OAAOF;KAAQ;IAC9E,IAAItB,oBAAoBL,aAAa8B,iBAAiBC,IAAI,CAACzC;IAC3D,IAAIE,QAAQsC,iBAAiBC,IAAI,CAACtC,eAAeD;IAEjD,MAAMwC,sBACJ,KAAC3C;QACC4C,KAAKd;QACLe,kBAAkBzB;QAClB0B,gBAAgBzB;QAChB0B,uBAAuBrC,4BAA4BC;QACnDqC,YAAY;YAAEzB;YAA0BC;QAA4B;QACpEC,YAAYA;QACZE,gBAAgBA;QAChBC,cAAcA;QACdN,WAAWA;kBACX,cAAA,KAACxB;YAAOwB,WAAWmB;sBAAmBvB;;;IAI1C,8FAA8F;IAC9F,6CAA6C;IAC7C,IAAIW,cAAc;QAChB,OAAOc;IACT;IACA,qBACE,KAAC5C;QAAKkD,OAAO;YAAEC,UAAU;QAAW;QAAGC,eAAc;kBAClDR;;AAGP;AAEA,cAAc,UAAU"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { BottomSheet as SwiftUIBottomSheet, Group, Host } from '@expo/ui/swift-ui';
3
3
  import { frame, padding, presentationBackground, presentationDetents, presentationDragIndicator } from '@expo/ui/swift-ui/modifiers';
4
+ import { useIsInsideNativeTree } from '../../NativeTreeContext';
4
5
  import { resolveContentPadding } from './utils';
5
6
  function snapPointToDetent(snapPoint) {
6
7
  if (snapPoint === 'half') return 'medium';
@@ -8,6 +9,7 @@ function snapPointToDetent(snapPoint) {
8
9
  return snapPoint;
9
10
  }
10
11
  export function BottomSheet({ children, isPresented, onDismiss, showDragIndicator = true, snapPoints, testID, modifiers, contentPadding, containerColor }) {
12
+ const isInsideHost = useIsInsideNativeTree();
11
13
  const { top, bottom, left, right } = resolveContentPadding(contentPadding, {
12
14
  top: 16,
13
15
  bottom: 0,
@@ -36,23 +38,29 @@ export function BottomSheet({ children, isPresented, onDismiss, showDragIndicato
36
38
  if (modifiers?.length) {
37
39
  presentationModifiers.push(...modifiers);
38
40
  }
41
+ const sheet = /*#__PURE__*/ _jsx(SwiftUIBottomSheet, {
42
+ isPresented: isPresented,
43
+ onIsPresentedChange: (presented)=>{
44
+ if (!presented) onDismiss();
45
+ },
46
+ fitToContents: !snapPoints || snapPoints.length === 0,
47
+ testID: testID,
48
+ children: /*#__PURE__*/ _jsx(Group, {
49
+ modifiers: presentationModifiers,
50
+ children: children
51
+ })
52
+ });
53
+ // Already inside a `Host`, for example nested in another sheet's content: a `Host` of its own
54
+ // would be a `Host` directly inside SwiftUI.
55
+ if (isInsideHost) {
56
+ return sheet;
57
+ }
39
58
  return /*#__PURE__*/ _jsx(Host, {
40
59
  style: {
41
60
  position: 'absolute'
42
61
  },
43
62
  pointerEvents: "none",
44
- children: /*#__PURE__*/ _jsx(SwiftUIBottomSheet, {
45
- isPresented: isPresented,
46
- onIsPresentedChange: (presented)=>{
47
- if (!presented) onDismiss();
48
- },
49
- fitToContents: !snapPoints || snapPoints.length === 0,
50
- testID: testID,
51
- children: /*#__PURE__*/ _jsx(Group, {
52
- modifiers: presentationModifiers,
53
- children: children
54
- })
55
- })
63
+ children: sheet
56
64
  });
57
65
  }
58
66
  export * from './types';
@@ -1 +1 @@
1
- {"version":3,"sources":["universal/BottomSheet/index.ios.tsx"],"sourcesContent":[null],"names":["BottomSheet","SwiftUIBottomSheet","Group","Host","frame","padding","presentationBackground","presentationDetents","presentationDragIndicator","resolveContentPadding","snapPointToDetent","snapPoint","children","isPresented","onDismiss","showDragIndicator","snapPoints","testID","modifiers","contentPadding","containerColor","top","bottom","left","right","presentationModifiers","maxWidth","Infinity","alignment","leading","trailing","length","push","map","style","position","pointerEvents","onIsPresentedChange","presented","fitToContents"],"mappings":";AAAA,SAASA,eAAeC,kBAAkB,EAAEC,KAAK,EAAEC,IAAI,QAAQ,oBAAoB;AACnF,SACEC,KAAK,EACLC,OAAO,EACPC,sBAAsB,EACtBC,mBAAmB,EACnBC,yBAAyB,QAGpB,8BAA8B;AAGrC,SAASC,qBAAqB,QAAQ,UAAU;AAEhD,SAASC,kBAAkBC,SAAoB;IAC7C,IAAIA,cAAc,QAAQ,OAAO;IACjC,IAAIA,cAAc,QAAQ,OAAO;IACjC,OAAOA;AACT;AAEA,OAAO,SAASX,YAAY,EAC1BY,QAAQ,EACRC,WAAW,EACXC,SAAS,EACTC,oBAAoB,IAAI,EACxBC,UAAU,EACVC,MAAM,EACNC,SAAS,EACTC,cAAc,EACdC,cAAc,EACG;IACjB,MAAM,EAAEC,GAAG,EAAEC,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGf,sBAAsBU,gBAAgB;QACzEE,KAAK;QACLC,QAAQ;QACRC,MAAM;QACNC,OAAO;IACT;IACA,MAAMC,wBAA0C;QAC9CrB,MAAM;YAAEsB,UAAUC;YAAUC,WAAW;QAAa;QACpDvB,QAAQ;YAAEgB;YAAKC;YAAQO,SAASN;YAAMO,UAAUN;QAAM;QACtDhB,0BAA0BO,oBAAoB,YAAY;KAC3D;IACD,IAAIC,cAAcA,WAAWe,MAAM,GAAG,GAAG;QACvCN,sBAAsBO,IAAI,CAACzB,oBAAoBS,WAAWiB,GAAG,CAACvB;IAChE;IACA,IAAIU,gBAAgB;QAClBK,sBAAsBO,IAAI,CAAC1B,uBAAuBc;IACpD;IACA,IAAIF,WAAWa,QAAQ;QACrBN,sBAAsBO,IAAI,IAAId;IAChC;IAEA,qBACE,KAACf;QAAK+B,OAAO;YAAEC,UAAU;QAAW;QAAGC,eAAc;kBACnD,cAAA,KAACnC;YACCY,aAAaA;YACbwB,qBAAqB,CAACC;gBACpB,IAAI,CAACA,WAAWxB;YAClB;YACAyB,eAAe,CAACvB,cAAcA,WAAWe,MAAM,KAAK;YACpDd,QAAQA;sBACR,cAAA,KAACf;gBAAMgB,WAAWO;0BAAwBb;;;;AAIlD;AAEA,cAAc,UAAU"}
1
+ {"version":3,"sources":["universal/BottomSheet/index.ios.tsx"],"sourcesContent":[null],"names":["BottomSheet","SwiftUIBottomSheet","Group","Host","frame","padding","presentationBackground","presentationDetents","presentationDragIndicator","useIsInsideNativeTree","resolveContentPadding","snapPointToDetent","snapPoint","children","isPresented","onDismiss","showDragIndicator","snapPoints","testID","modifiers","contentPadding","containerColor","isInsideHost","top","bottom","left","right","presentationModifiers","maxWidth","Infinity","alignment","leading","trailing","length","push","map","sheet","onIsPresentedChange","presented","fitToContents","style","position","pointerEvents"],"mappings":";AAAA,SAASA,eAAeC,kBAAkB,EAAEC,KAAK,EAAEC,IAAI,QAAQ,oBAAoB;AACnF,SACEC,KAAK,EACLC,OAAO,EACPC,sBAAsB,EACtBC,mBAAmB,EACnBC,yBAAyB,QAGpB,8BAA8B;AAErC,SAASC,qBAAqB,QAAQ,0BAA0B;AAEhE,SAASC,qBAAqB,QAAQ,UAAU;AAEhD,SAASC,kBAAkBC,SAAoB;IAC7C,IAAIA,cAAc,QAAQ,OAAO;IACjC,IAAIA,cAAc,QAAQ,OAAO;IACjC,OAAOA;AACT;AAEA,OAAO,SAASZ,YAAY,EAC1Ba,QAAQ,EACRC,WAAW,EACXC,SAAS,EACTC,oBAAoB,IAAI,EACxBC,UAAU,EACVC,MAAM,EACNC,SAAS,EACTC,cAAc,EACdC,cAAc,EACG;IACjB,MAAMC,eAAeb;IACrB,MAAM,EAAEc,GAAG,EAAEC,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGhB,sBAAsBU,gBAAgB;QACzEG,KAAK;QACLC,QAAQ;QACRC,MAAM;QACNC,OAAO;IACT;IACA,MAAMC,wBAA0C;QAC9CvB,MAAM;YAAEwB,UAAUC;YAAUC,WAAW;QAAa;QACpDzB,QAAQ;YAAEkB;YAAKC;YAAQO,SAASN;YAAMO,UAAUN;QAAM;QACtDlB,0BAA0BQ,oBAAoB,YAAY;KAC3D;IACD,IAAIC,cAAcA,WAAWgB,MAAM,GAAG,GAAG;QACvCN,sBAAsBO,IAAI,CAAC3B,oBAAoBU,WAAWkB,GAAG,CAACxB;IAChE;IACA,IAAIU,gBAAgB;QAClBM,sBAAsBO,IAAI,CAAC5B,uBAAuBe;IACpD;IACA,IAAIF,WAAWc,QAAQ;QACrBN,sBAAsBO,IAAI,IAAIf;IAChC;IAEA,MAAMiB,sBACJ,KAACnC;QACCa,aAAaA;QACbuB,qBAAqB,CAACC;YACpB,IAAI,CAACA,WAAWvB;QAClB;QACAwB,eAAe,CAACtB,cAAcA,WAAWgB,MAAM,KAAK;QACpDf,QAAQA;kBACR,cAAA,KAAChB;YAAMiB,WAAWQ;sBAAwBd;;;IAI9C,8FAA8F;IAC9F,6CAA6C;IAC7C,IAAIS,cAAc;QAChB,OAAOc;IACT;IACA,qBACE,KAACjC;QAAKqC,OAAO;YAAEC,UAAU;QAAW;QAAGC,eAAc;kBAClDN;;AAGP;AAEA,cAAc,UAAU"}
@@ -59,6 +59,8 @@ struct BarChartStyle: Record {
59
59
  struct PieChartStyle: Record {
60
60
  @Field var innerRadius: Double = 0.3
61
61
  @Field var angularInset: Double = 2.0
62
+ @Field var cornerRadius: Double = 0.0
63
+ @Field var opacity: Double = 0.8
62
64
  }
63
65
 
64
66
  struct PointChartStyle: Record {
@@ -115,10 +117,11 @@ public struct ChartView: ExpoSwiftUI.View {
115
117
 
116
118
  @available(iOS 17.0, tvOS 17.0, *)
117
119
  private func createBasePieMark(for dataPoint: ChartDataPoint) -> SectorMark {
118
- let style = props.pieStyle ?? PieChartStyle()
119
- return SectorMark(angle: .value("Value", dataPoint.y), innerRadius: .ratio(style.innerRadius), angularInset: style.angularInset)
120
+ return SectorMark(angle: .value("Value", dataPoint.y), innerRadius: .ratio(pieStyle.innerRadius), angularInset: pieStyle.angularInset)
120
121
  }
121
122
 
123
+ private var pieStyle: PieChartStyle { props.pieStyle ?? PieChartStyle() }
124
+
122
125
  @available(iOS 16.0, tvOS 16.0, *)
123
126
  private func createAreaMark(for dataPoint: ChartDataPoint) -> some ChartContent {
124
127
  if let numericX = dataPoint.xNumericValue {
@@ -137,15 +140,13 @@ public struct ChartView: ExpoSwiftUI.View {
137
140
  .foregroundStyle(props.lineStyle?.color ?? .blue)
138
141
  .symbol(getSymbol(props.lineStyle?.pointStyle ?? .circle))
139
142
  .symbolSize(CGFloat(props.lineStyle?.pointSize ?? 6.0))
140
- .lineStyle(getLineStyle(props.lineStyle?.dashArray ?? []))
141
- .lineStyle(.init(lineWidth: CGFloat(props.lineStyle?.width ?? 2.0)))
143
+ .lineStyle(getLineStyle(props.lineStyle))
142
144
  } else {
143
145
  LineMark(x: .value("X", dataPoint.xValue), y: .value("Y", dataPoint.y))
144
146
  .foregroundStyle(props.lineStyle?.color ?? .blue)
145
147
  .symbol(getSymbol(props.lineStyle?.pointStyle ?? .circle))
146
148
  .symbolSize(CGFloat(props.lineStyle?.pointSize ?? 6.0))
147
- .lineStyle(getLineStyle(props.lineStyle?.dashArray ?? []))
148
- .lineStyle(.init(lineWidth: CGFloat(props.lineStyle?.width ?? 2.0)))
149
+ .lineStyle(getLineStyle(props.lineStyle))
149
150
  }
150
151
  }
151
152
 
@@ -214,9 +215,9 @@ public struct ChartView: ExpoSwiftUI.View {
214
215
  case .pie:
215
216
  if #available(iOS 17.0, tvOS 17.0, *) {
216
217
  if hasIndividualColors {
217
- createBasePieMark(for: dataPoint).foregroundStyle(dataPoint.color ?? .blue).opacity(0.8)
218
+ createBasePieMark(for: dataPoint).foregroundStyle(dataPoint.color ?? .blue).cornerRadius(CGFloat(pieStyle.cornerRadius)).opacity(pieStyle.opacity)
218
219
  } else {
219
- createBasePieMark(for: dataPoint).foregroundStyle(by: .value("Category", dataPoint.xValue)).opacity(0.8)
220
+ createBasePieMark(for: dataPoint).foregroundStyle(by: .value("Category", dataPoint.xValue)).cornerRadius(CGFloat(pieStyle.cornerRadius)).opacity(pieStyle.opacity)
220
221
  }
221
222
  }
222
223
  case .rectangle:
@@ -254,7 +255,11 @@ public struct ChartView: ExpoSwiftUI.View {
254
255
  }
255
256
  }
256
257
 
257
- private func getLineStyle(_ dashArray: [Double]) -> StrokeStyle {
258
- StrokeStyle(dash: dashArray.map { CGFloat($0) })
258
+ // A single stroke style: chained `.lineStyle` modifiers don't merge, the first one wins.
259
+ private func getLineStyle(_ style: LineChartStyle?) -> StrokeStyle {
260
+ StrokeStyle(
261
+ lineWidth: CGFloat(style?.width ?? 2.0),
262
+ dash: (style?.dashArray ?? []).map { CGFloat($0) }
263
+ )
259
264
  }
260
265
  }
@@ -48,6 +48,7 @@ struct DataListForEachItemView: ExpoSwiftUI.View {
48
48
 
49
49
  var body: some View {
50
50
  Children()
51
+ .publishZeroContentOrigin(props.shadowNodeProxy)
51
52
  }
52
53
  }
53
54
 
@@ -41,6 +41,7 @@ public struct GridRowView: ExpoSwiftUI.View {
41
41
  if #available(iOS 16.0, macOS 13.0, tvOS 16.0, *) {
42
42
  GridRow {
43
43
  Children()
44
+ .publishZeroContentOrigin(props.shadowNodeProxy)
44
45
  }
45
46
  } else {
46
47
  EmptyView()
@@ -3,11 +3,28 @@
3
3
  import SwiftUI
4
4
  import ExpoModulesCore
5
5
 
6
- /// Coordinate space anchored at the `Host`, so hosted React Native views can report where SwiftUI
7
- /// actually placed them. Name it last in the chain: Yoga measures a hosted view from the `Host`
8
- /// component view, so any `Host` inset or alignment has to be inside this space, not outside it.
6
+ /// Coordinate space anchored at the `Host`'s SwiftUI root, which macOS measures hosted React Native
7
+ /// views from. iOS uses `HostingViewReference` instead, because this space starts after the
8
+ /// safe-area inset that `UIHostingController` applies to the root.
9
9
  internal let expoHostCoordinateSpace = "expo.ui.host"
10
10
 
11
+ /// The enclosing `Host`'s UIKit view, which Yoga laid out. iOS measures hosted React Native views
12
+ /// from it.
13
+ internal final class HostingViewReference {
14
+ weak var view: UIView?
15
+ }
16
+
17
+ private struct HostingViewEnvironmentKey: EnvironmentKey {
18
+ static let defaultValue: HostingViewReference? = nil
19
+ }
20
+
21
+ extension EnvironmentValues {
22
+ var expoHostingView: HostingViewReference? {
23
+ get { self[HostingViewEnvironmentKey.self] }
24
+ set { self[HostingViewEnvironmentKey.self] = newValue }
25
+ }
26
+ }
27
+
11
28
  internal enum ExpoColorScheme: String, Enumerable {
12
29
  case light
13
30
  case dark
@@ -46,7 +63,11 @@ internal final class HostViewProps: ExpoSwiftUI.ViewProps, ExpoSwiftUI.SafeAreaC
46
63
  @Field var ignoreSafeArea: ExpoSwiftUI.IgnoreSafeArea?
47
64
  @Field var modifiers: ModifierArray?
48
65
  var onLayoutContent = EventDispatcher()
49
- weak var hostingView: UIView?
66
+ let hostingViewReference = HostingViewReference()
67
+ var hostingView: UIView? {
68
+ get { hostingViewReference.view }
69
+ set { hostingViewReference.view = newValue }
70
+ }
50
71
  }
51
72
 
52
73
  struct HostView: ExpoSwiftUI.View, ExpoSwiftUI.WithHostingView {
@@ -68,6 +89,7 @@ struct HostView: ExpoSwiftUI.View, ExpoSwiftUI.WithHostingView {
68
89
  HostLayout {
69
90
  Children()
70
91
  }
92
+ .environment(\.expoHostingView, props.hostingViewReference)
71
93
  .fixedSize(horizontal: props.matchContentsHorizontal, vertical: props.matchContentsVertical)
72
94
  .modifier(LayoutDirectionModifier(layoutDirection: layoutDirection))
73
95
  .modifier(ColorSchemeModifier(colorScheme: props.colorScheme?.toColorScheme()))
@@ -90,6 +112,7 @@ struct HostView: ExpoSwiftUI.View, ExpoSwiftUI.WithHostingView {
90
112
  ZStack(alignment: alignment) {
91
113
  Children()
92
114
  }
115
+ .environment(\.expoHostingView, props.hostingViewReference)
93
116
  .fixedSize(horizontal: props.matchContentsHorizontal, vertical: props.matchContentsVertical)
94
117
  .modifier(LayoutDirectionModifier(layoutDirection: layoutDirection))
95
118
  .modifier(ColorSchemeModifier(colorScheme: props.colorScheme?.toColorScheme()))
@@ -238,23 +238,39 @@ internal enum PresentationSizingOption: String, Enumerable {
238
238
  case page
239
239
  }
240
240
 
241
+ internal struct PresentationSizingFittedAxes: Record {
242
+ @Field var horizontal: Bool = false
243
+ @Field var vertical: Bool = false
244
+ }
245
+
241
246
  internal struct PresentationSizingModifier: ViewModifier, Record {
242
247
  @Field var sizing: PresentationSizingOption = .automatic
248
+ @Field var fitted: PresentationSizingFittedAxes?
243
249
 
244
250
  func body(content: Content) -> some View {
245
251
  if #available(iOS 18.0, tvOS 18.0, macOS 15.0, *) {
246
252
  switch sizing {
247
253
  case .automatic:
248
- content.presentationSizing(.automatic)
254
+ applySizing(content, .automatic)
249
255
  case .fitted:
250
- content.presentationSizing(.fitted)
256
+ applySizing(content, .fitted)
251
257
  case .form:
252
- content.presentationSizing(.form)
258
+ applySizing(content, .form)
253
259
  case .page:
254
- content.presentationSizing(.page)
260
+ applySizing(content, .page)
255
261
  }
256
262
  } else {
257
263
  content
258
264
  }
259
265
  }
266
+
267
+ @available(iOS 18.0, tvOS 18.0, macOS 15.0, *)
268
+ @ViewBuilder
269
+ private func applySizing(_ content: Content, _ sizing: some PresentationSizing) -> some View {
270
+ if let fitted {
271
+ content.presentationSizing(sizing.fitted(horizontal: fitted.horizontal, vertical: fitted.vertical))
272
+ } else {
273
+ content.presentationSizing(sizing)
274
+ }
275
+ }
260
276
  }
@@ -0,0 +1,35 @@
1
+ // Copyright 2026-present 650 Industries. All rights reserved.
2
+
3
+ import ExpoModulesCore
4
+ import SwiftUI
5
+
6
+ internal enum SearchToolbarBehaviorType: String, Enumerable {
7
+ case automatic
8
+ case minimize
9
+ }
10
+
11
+ internal struct SearchToolbarBehaviorModifier: ViewModifier, Record {
12
+ @Field var behavior: SearchToolbarBehaviorType = .automatic
13
+
14
+ @ViewBuilder
15
+ func body(content: Content) -> some View {
16
+ if #available(iOS 26.0, macOS 26.0, tvOS 26.0, *) {
17
+ #if compiler(>=6.2) // Xcode 26
18
+ switch behavior {
19
+ case .automatic:
20
+ content.searchToolbarBehavior(.automatic)
21
+ case .minimize:
22
+ #if os(macOS) || os(tvOS)
23
+ content.searchToolbarBehavior(.automatic)
24
+ #else
25
+ content.searchToolbarBehavior(.minimize)
26
+ #endif
27
+ }
28
+ #else
29
+ content
30
+ #endif
31
+ } else {
32
+ content
33
+ }
34
+ }
35
+ }