@expo/ui 58.0.20 → 58.0.22

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 (117) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +86 -2
  3. package/android/build.gradle +2 -2
  4. package/android/src/main/java/expo/modules/ui/CompositionLocalProviderView.kt +26 -0
  5. package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +12 -0
  6. package/android/src/main/java/expo/modules/ui/HostView.kt +4 -1
  7. package/android/src/main/java/expo/modules/ui/MaskView.kt +3 -2
  8. package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +3 -1
  9. package/android/src/main/java/expo/modules/ui/RNHostView.kt +11 -7
  10. package/android/src/main/java/expo/modules/ui/SwitchView.kt +6 -1
  11. package/android/src/main/java/expo/modules/ui/TopAppBarView.kt +62 -0
  12. package/android/src/main/java/expo/modules/ui/colors/MaterialColors.kt +61 -0
  13. package/build/community/bottom-sheet/BottomSheet.ios.js +8 -3
  14. package/build/community/bottom-sheet/BottomSheet.ios.js.map +1 -1
  15. package/build/community/pager-view/PagerView.ios.js +25 -8
  16. package/build/community/pager-view/PagerView.ios.js.map +1 -1
  17. package/build/community/segmented-control/SegmentedControl.ios.js +11 -2
  18. package/build/community/segmented-control/SegmentedControl.ios.js.map +1 -1
  19. package/build/community/segmented-control/types.d.ts +5 -1
  20. package/build/community/segmented-control/types.js.map +1 -1
  21. package/build/community/segmented-control/vendor/SegmentedControl.js +2 -2
  22. package/build/community/segmented-control/vendor/SegmentedControl.js.map +1 -1
  23. package/build/jetpack-compose/CompositionLocalProvider/index.d.ts +28 -0
  24. package/build/jetpack-compose/CompositionLocalProvider/index.js +15 -0
  25. package/build/jetpack-compose/CompositionLocalProvider/index.js.map +1 -0
  26. package/build/jetpack-compose/Host/index.d.ts +8 -0
  27. package/build/jetpack-compose/Host/index.js +38 -5
  28. package/build/jetpack-compose/Host/index.js.map +1 -1
  29. package/build/jetpack-compose/Switch/index.d.ts +2 -0
  30. package/build/jetpack-compose/Switch/index.js +1 -0
  31. package/build/jetpack-compose/Switch/index.js.map +1 -1
  32. package/build/jetpack-compose/TopAppBar/index.d.ts +72 -0
  33. package/build/jetpack-compose/TopAppBar/index.js +45 -0
  34. package/build/jetpack-compose/TopAppBar/index.js.map +1 -0
  35. package/build/jetpack-compose/index.d.ts +2 -0
  36. package/build/jetpack-compose/index.js +2 -0
  37. package/build/jetpack-compose/index.js.map +1 -1
  38. package/build/jetpack-compose/modifiers/index.d.ts +5 -1
  39. package/build/jetpack-compose/modifiers/index.js +6 -2
  40. package/build/jetpack-compose/modifiers/index.js.map +1 -1
  41. package/build/swift-ui/BottomSheet/index.d.ts +6 -0
  42. package/build/swift-ui/BottomSheet/index.js +9 -3
  43. package/build/swift-ui/BottomSheet/index.js.map +1 -1
  44. package/build/universal/Checkbox/index.android.js +16 -4
  45. package/build/universal/Checkbox/index.android.js.map +1 -1
  46. package/build/universal/ScrollView/index.ios.js +12 -6
  47. package/build/universal/ScrollView/index.ios.js.map +1 -1
  48. package/build/universal/Switch/index.android.js +17 -4
  49. package/build/universal/Switch/index.android.js.map +1 -1
  50. package/build/universal/Switch/index.js +1 -0
  51. package/build/universal/Switch/index.js.map +1 -1
  52. package/build/universal/Text/index.js +2 -2
  53. package/build/universal/Text/index.js.map +1 -1
  54. package/build/universal/webUtils.js +4 -0
  55. package/build/universal/webUtils.js.map +1 -1
  56. package/ios/BottomSheetView.swift +11 -2
  57. package/ios/DataListForEachView.swift +24 -6
  58. package/ios/DatePickerView.swift +134 -9
  59. package/ios/Modifiers/SelectedSegmentTintColorModifier.swift +86 -0
  60. package/ios/Modifiers/ViewModifierRegistry.swift +4 -0
  61. package/ios/RNHostView.swift +34 -16
  62. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.20/expo.modules.ui-58.0.20-sources.jar → 58.0.22/expo.modules.ui-58.0.22-sources.jar} +0 -0
  63. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22-sources.jar.md5 +1 -0
  64. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22-sources.jar.sha1 +1 -0
  65. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22-sources.jar.sha256 +1 -0
  66. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22-sources.jar.sha512 +1 -0
  67. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.aar +0 -0
  68. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.aar.md5 +1 -0
  69. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.aar.sha1 +1 -0
  70. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.aar.sha256 +1 -0
  71. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.aar.sha512 +1 -0
  72. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.20/expo.modules.ui-58.0.20.module → 58.0.22/expo.modules.ui-58.0.22.module} +22 -22
  73. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.module.md5 +1 -0
  74. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.module.sha1 +1 -0
  75. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.module.sha256 +1 -0
  76. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.module.sha512 +1 -0
  77. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.20/expo.modules.ui-58.0.20.pom → 58.0.22/expo.modules.ui-58.0.22.pom} +1 -1
  78. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.pom.md5 +1 -0
  79. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.pom.sha1 +1 -0
  80. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.pom.sha256 +1 -0
  81. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.22/expo.modules.ui-58.0.22.pom.sha512 +1 -0
  82. package/package.json +2 -2
  83. package/src/community/bottom-sheet/BottomSheet.ios.tsx +7 -3
  84. package/src/community/pager-view/PagerView.ios.tsx +25 -8
  85. package/src/community/segmented-control/SegmentedControl.ios.tsx +13 -1
  86. package/src/community/segmented-control/types.tsx +5 -1
  87. package/src/community/segmented-control/vendor/SegmentedControl.tsx +10 -2
  88. package/src/jetpack-compose/CompositionLocalProvider/index.tsx +43 -0
  89. package/src/jetpack-compose/Host/index.tsx +50 -4
  90. package/src/jetpack-compose/Switch/index.tsx +4 -0
  91. package/src/jetpack-compose/TopAppBar/index.tsx +113 -0
  92. package/src/jetpack-compose/index.ts +2 -0
  93. package/src/jetpack-compose/modifiers/index.ts +11 -3
  94. package/src/swift-ui/BottomSheet/index.tsx +24 -3
  95. package/src/universal/Checkbox/index.android.tsx +24 -5
  96. package/src/universal/ScrollView/index.ios.tsx +14 -3
  97. package/src/universal/Switch/index.android.tsx +23 -4
  98. package/src/universal/Switch/index.tsx +1 -0
  99. package/src/universal/Text/index.tsx +2 -2
  100. package/src/universal/webUtils.ts +4 -0
  101. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20-sources.jar.md5 +0 -1
  102. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20-sources.jar.sha1 +0 -1
  103. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20-sources.jar.sha256 +0 -1
  104. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20-sources.jar.sha512 +0 -1
  105. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.aar +0 -0
  106. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.aar.md5 +0 -1
  107. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.aar.sha1 +0 -1
  108. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.aar.sha256 +0 -1
  109. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.aar.sha512 +0 -1
  110. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.module.md5 +0 -1
  111. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.module.sha1 +0 -1
  112. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.module.sha256 +0 -1
  113. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.module.sha512 +0 -1
  114. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.pom.md5 +0 -1
  115. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.pom.sha1 +0 -1
  116. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.pom.sha256 +0 -1
  117. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.20/expo.modules.ui-58.0.20.pom.sha512 +0 -1
@@ -0,0 +1,113 @@
1
+ import { requireNativeView } from 'expo';
2
+ import type { ColorValue } from 'react-native';
3
+
4
+ import type { ExpoModifier } from '../../types';
5
+ import type { PaddingValuesRecord } from '../Carousel';
6
+ import { createViewModifierEventListener } from '../modifiers/utils';
7
+
8
+ export type { PaddingValuesRecord };
9
+
10
+ /**
11
+ * Colors for the top app bar.
12
+ */
13
+ export type TopAppBarColors = {
14
+ /**
15
+ * Color of the container (background).
16
+ */
17
+ containerColor?: ColorValue;
18
+ /**
19
+ * Color of the navigation icon.
20
+ */
21
+ navigationIconContentColor?: ColorValue;
22
+ /**
23
+ * Color of the title.
24
+ */
25
+ titleContentColor?: ColorValue;
26
+ /**
27
+ * Color of the action icons.
28
+ */
29
+ actionIconContentColor?: ColorValue;
30
+ };
31
+
32
+ export interface TopAppBarProps {
33
+ /**
34
+ * Colors for the app bar. Unset colors use `TopAppBarDefaults.topAppBarColors()`.
35
+ */
36
+ colors?: TopAppBarColors;
37
+ /**
38
+ * Insets in dp that the app bar adds around its content. Missing sides are `0`.
39
+ * When omitted, the app bar uses `TopAppBarDefaults.windowInsets`, which assumes
40
+ * the bar is at the top edge of the window, even inside a nested `Host`.
41
+ * Pass `{}` when a parent handles the insets. This removes both the top status
42
+ * bar inset and the horizontal system bar and display cutout insets.
43
+ */
44
+ windowInsets?: PaddingValuesRecord;
45
+ /**
46
+ * Modifiers for the component.
47
+ */
48
+ modifiers?: ExpoModifier[];
49
+ /**
50
+ * `TopAppBar.Title`, `TopAppBar.NavigationIcon`, and `TopAppBar.Actions` slots.
51
+ */
52
+ children: React.ReactNode;
53
+ }
54
+
55
+ type SlotProps = {
56
+ children: React.ReactNode;
57
+ };
58
+
59
+ type NativeSlotViewProps = {
60
+ slotName: string;
61
+ children: React.ReactNode;
62
+ };
63
+
64
+ const TopAppBarNativeView: React.ComponentType<TopAppBarProps> = requireNativeView(
65
+ 'ExpoUI',
66
+ 'TopAppBarView'
67
+ );
68
+
69
+ const SlotNativeView: React.ComponentType<NativeSlotViewProps> = requireNativeView(
70
+ 'ExpoUI',
71
+ 'SlotView'
72
+ );
73
+
74
+ /**
75
+ * Title slot for `TopAppBar`.
76
+ */
77
+ function TopAppBarTitle(props: SlotProps) {
78
+ return <SlotNativeView slotName="title">{props.children}</SlotNativeView>;
79
+ }
80
+
81
+ /**
82
+ * Navigation icon slot for `TopAppBar`. It appears at the start of the app bar.
83
+ */
84
+ function TopAppBarNavigationIcon(props: SlotProps) {
85
+ return <SlotNativeView slotName="navigationIcon">{props.children}</SlotNativeView>;
86
+ }
87
+
88
+ /**
89
+ * Actions slot for `TopAppBar`. Its children appear in a row at the end of the app bar.
90
+ */
91
+ function TopAppBarActions(props: SlotProps) {
92
+ return <SlotNativeView slotName="actions">{props.children}</SlotNativeView>;
93
+ }
94
+
95
+ /**
96
+ * A Material 3 small top app bar that shows a title, a navigation icon, and actions.
97
+ */
98
+ function TopAppBar(props: TopAppBarProps) {
99
+ const { modifiers, ...restProps } = props;
100
+ return (
101
+ <TopAppBarNativeView
102
+ modifiers={modifiers}
103
+ {...(modifiers ? createViewModifierEventListener(modifiers) : undefined)}
104
+ {...restProps}
105
+ />
106
+ );
107
+ }
108
+
109
+ TopAppBar.Title = TopAppBarTitle;
110
+ TopAppBar.NavigationIcon = TopAppBarNavigationIcon;
111
+ TopAppBar.Actions = TopAppBarActions;
112
+
113
+ export { TopAppBar };
@@ -59,6 +59,7 @@ export * from './SearchBar';
59
59
  export * from './Snackbar';
60
60
  export * from './DockedSearchBar';
61
61
  export * from './HorizontalFloatingToolbar';
62
+ export * from './TopAppBar';
62
63
  export * from './FloatingActionButton';
63
64
  export * from './PullToRefreshBox';
64
65
  export * from './RadioButton';
@@ -71,6 +72,7 @@ export * from './AnimatedVisibility';
71
72
  export * from './Box';
72
73
  export * from './Row';
73
74
  export * from './Column';
75
+ export * from './CompositionLocalProvider';
74
76
  export * from './FlowRow';
75
77
  export { useNativeState, useWorkletCallback, type WorkletCallback } from '../State';
76
78
  export type { ViewEvent } from '../types';
@@ -403,13 +403,21 @@ export const selectableGroup = () => createModifier('selectableGroup');
403
403
  * @param value - The current toggle state.
404
404
  * @param handler - Function to call when toggled.
405
405
  * @param options - Optional configuration.
406
- * @param options.role - The semantic role for accessibility: `'checkbox'`, `'radioButton'`, `'switch'`, or `'tab'`.
406
+ * @param options.role - The semantic role for accessibility: `'checkbox'`, `'radioButton'`,
407
+ * `'switch'`, or `'tab'`.
408
+ * @param options.enabled - Whether the view responds to input and is reported as enabled to
409
+ * accessibility services. Defaults to `true`.
407
410
  */
408
411
  export const toggleable = (
409
412
  value: boolean,
410
413
  handler: () => void,
411
- options?: { role?: 'checkbox' | 'radioButton' | 'switch' | 'tab' }
412
- ) => createModifierWithEventListener('toggleable', handler, { value, role: options?.role });
414
+ options?: { role?: 'checkbox' | 'radioButton' | 'switch' | 'tab'; enabled?: boolean }
415
+ ) =>
416
+ createModifierWithEventListener('toggleable', handler, {
417
+ value,
418
+ role: options?.role,
419
+ enabled: options?.enabled,
420
+ });
413
421
 
414
422
  // =============================================================================
415
423
  // Lifecycle Modifiers
@@ -18,6 +18,12 @@ export interface BottomSheetProps extends CommonViewModifierProps {
18
18
  * kept mounted, so presenting the sheet doesn't shift surrounding layout. Optional.
19
19
  */
20
20
  anchor?: ReactNode;
21
+ /**
22
+ * A view that fills the whole sheet behind its content, for example a `Rectangle` filled with a
23
+ * material. Unlike the `presentationBackground` modifier, a material in a view stays translucent
24
+ * on iOS 26 and later.
25
+ */
26
+ presentationBackground?: ReactNode;
21
27
  /**
22
28
  * Whether the `BottomSheet` is presented.
23
29
  */
@@ -40,7 +46,7 @@ export interface BottomSheetProps extends CommonViewModifierProps {
40
46
 
41
47
  type NativeBottomSheetProps = Omit<
42
48
  BottomSheetProps,
43
- 'onIsPresentedChange' | 'onDismiss' | 'anchor'
49
+ 'onIsPresentedChange' | 'onDismiss' | 'anchor' | 'presentationBackground'
44
50
  > & {
45
51
  onIsPresentedChange: (event: NativeSyntheticEvent<{ isPresented: boolean }>) => void;
46
52
  onDismiss: (event: NativeSyntheticEvent<object>) => void;
@@ -55,7 +61,15 @@ const BottomSheetNativeView: ComponentType<NativeBottomSheetProps> = requireNati
55
61
  * `BottomSheet` presents content from the bottom of the screen.
56
62
  */
57
63
  function BottomSheet(props: BottomSheetProps) {
58
- const { modifiers, onIsPresentedChange, onDismiss, anchor, children, ...restProps } = props;
64
+ const {
65
+ modifiers,
66
+ onIsPresentedChange,
67
+ onDismiss,
68
+ anchor,
69
+ presentationBackground,
70
+ children,
71
+ ...restProps
72
+ } = props;
59
73
  const [isMounted, setIsMounted] = useState(props.isPresented);
60
74
 
61
75
  if (props.isPresented && !isMounted) {
@@ -79,7 +93,14 @@ function BottomSheet(props: BottomSheetProps) {
79
93
  {anchor != null ? <Slot name="anchor">{anchor}</Slot> : null}
80
94
  {/* Only the sheet's content is presented in its own view controller. The anchor renders in
81
95
  place, in the React Native surface, so it stays outside `PresentedContent`. */}
82
- {isMounted ? <PresentedContent>{children}</PresentedContent> : null}
96
+ {isMounted ? (
97
+ <PresentedContent>
98
+ {presentationBackground != null ? (
99
+ <Slot name="presentationBackground">{presentationBackground}</Slot>
100
+ ) : null}
101
+ {children}
102
+ </PresentedContent>
103
+ ) : null}
83
104
  </BottomSheetNativeView>
84
105
  );
85
106
  }
@@ -1,8 +1,15 @@
1
1
  import { Checkbox as ComposeCheckbox, Row, Text } from '@expo/ui/jetpack-compose';
2
- import { clickable, testID as testIDModifier } from '@expo/ui/jetpack-compose/modifiers';
2
+ import {
3
+ defaultMinSize,
4
+ testID as testIDModifier,
5
+ toggleable,
6
+ } from '@expo/ui/jetpack-compose/modifiers';
3
7
 
4
8
  import type { CheckboxProps } from './types';
5
9
 
10
+ // Material's minimum touch target.
11
+ const MIN_INTERACTIVE_SIZE = 48;
12
+
6
13
  export function Checkbox({
7
14
  value,
8
15
  onValueChange,
@@ -11,22 +18,34 @@ export function Checkbox({
11
18
  testID,
12
19
  modifiers,
13
20
  }: CheckboxProps) {
21
+ const isLabeled = label != null;
14
22
  const checkbox = (
15
23
  <ComposeCheckbox
16
24
  value={value}
17
- onCheckedChange={disabled ? undefined : onValueChange}
25
+ onCheckedChange={isLabeled ? undefined : onValueChange}
18
26
  enabled={!disabled}
19
- modifiers={[...(modifiers ?? []), ...(testID ? [testIDModifier(testID)] : [])]}
27
+ modifiers={[
28
+ ...(modifiers ?? []),
29
+ ...(isLabeled
30
+ ? [defaultMinSize({ minWidth: MIN_INTERACTIVE_SIZE, minHeight: MIN_INTERACTIVE_SIZE })]
31
+ : []),
32
+ ...(testID ? [testIDModifier(testID)] : []),
33
+ ]}
20
34
  />
21
35
  );
22
36
 
23
- if (label == null) return checkbox;
37
+ if (!isLabeled) return checkbox;
24
38
 
25
39
  return (
26
40
  <Row
27
41
  verticalAlignment="center"
28
42
  horizontalArrangement={{ spacedBy: 8 }}
29
- modifiers={[clickable(() => !disabled && onValueChange(!value))]}>
43
+ modifiers={[
44
+ toggleable(value, () => !disabled && onValueChange(!value), {
45
+ role: 'checkbox',
46
+ enabled: !disabled,
47
+ }),
48
+ ]}>
30
49
  {checkbox}
31
50
  <Text>{label}</Text>
32
51
  </Row>
@@ -1,4 +1,4 @@
1
- import { Group, ScrollView as SwiftUIScrollView } from '@expo/ui/swift-ui';
1
+ import { HStack, ScrollView as SwiftUIScrollView, VStack } from '@expo/ui/swift-ui';
2
2
  import { frame, padding } from '@expo/ui/swift-ui/modifiers';
3
3
  import type { ModifierConfig } from '@expo/ui/swift-ui/modifiers';
4
4
 
@@ -18,7 +18,7 @@ export function ScrollView({
18
18
  testID,
19
19
  modifiers: extraModifiers,
20
20
  }: ScrollViewProps) {
21
- // Extract padding from style — it goes on the inner Group so content is
21
+ // Extract padding from style — it goes on the inner stack so content is
22
22
  // inset after stretching to full width.
23
23
  const {
24
24
  padding: paddingAll,
@@ -64,13 +64,24 @@ export function ScrollView({
64
64
  );
65
65
  }
66
66
 
67
+ const stack =
68
+ direction === 'horizontal' ? (
69
+ <HStack alignment="top" modifiers={innerModifiers}>
70
+ {children}
71
+ </HStack>
72
+ ) : (
73
+ <VStack alignment="leading" modifiers={innerModifiers}>
74
+ {children}
75
+ </VStack>
76
+ );
77
+
67
78
  return (
68
79
  <SwiftUIScrollView
69
80
  axes={direction}
70
81
  showsIndicators={showsIndicators}
71
82
  modifiers={scrollModifiers}
72
83
  testID={testID}>
73
- <Group modifiers={innerModifiers}>{children}</Group>
84
+ {stack}
74
85
  </SwiftUIScrollView>
75
86
  );
76
87
  }
@@ -1,31 +1,50 @@
1
1
  import { Row, Switch as ComposeSwitch, Text } from '@expo/ui/jetpack-compose';
2
2
  import {
3
+ defaultMinSize,
3
4
  fillMaxWidth,
4
5
  IntrinsicSize,
5
6
  testID as testIDModifier,
7
+ toggleable,
6
8
  weight,
7
9
  width,
8
10
  } from '@expo/ui/jetpack-compose/modifiers';
9
11
 
10
12
  import type { SwitchProps } from './types';
11
13
 
14
+ // Material's minimum touch target.
15
+ const MIN_INTERACTIVE_SIZE = 48;
16
+
12
17
  export function Switch({ value, onValueChange, label, disabled, testID, modifiers }: SwitchProps) {
18
+ const isLabeled = label != null;
13
19
  const toggle = (
14
20
  <ComposeSwitch
15
21
  value={value}
16
- onCheckedChange={disabled ? undefined : onValueChange}
22
+ onCheckedChange={isLabeled ? undefined : onValueChange}
17
23
  enabled={!disabled}
18
- modifiers={[...(modifiers ?? []), ...(testID ? [testIDModifier(testID)] : [])]}
24
+ modifiers={[
25
+ ...(modifiers ?? []),
26
+ ...(isLabeled
27
+ ? [defaultMinSize({ minWidth: MIN_INTERACTIVE_SIZE, minHeight: MIN_INTERACTIVE_SIZE })]
28
+ : []),
29
+ ...(testID ? [testIDModifier(testID)] : []),
30
+ ]}
19
31
  />
20
32
  );
21
33
 
22
- if (label == null) return toggle;
34
+ if (!isLabeled) return toggle;
23
35
 
24
36
  return (
25
37
  <Row
26
38
  verticalAlignment="center"
27
39
  horizontalArrangement={{ spacedBy: 8 }}
28
- modifiers={[fillMaxWidth(), width(IntrinsicSize.Max)]}>
40
+ modifiers={[
41
+ fillMaxWidth(),
42
+ width(IntrinsicSize.Max),
43
+ toggleable(value, () => !disabled && onValueChange(!value), {
44
+ role: 'switch',
45
+ enabled: !disabled,
46
+ }),
47
+ ]}>
29
48
  <Text modifiers={[weight(1)]}>{label}</Text>
30
49
  {toggle}
31
50
  </Row>
@@ -28,6 +28,7 @@ const styles = StyleSheet.create({
28
28
  },
29
29
  text: {
30
30
  color: colors.foreground,
31
+ flexGrow: 1,
31
32
  userSelect: 'none',
32
33
  },
33
34
  track: {
@@ -4,8 +4,8 @@ import { useUniversalLifecycle } from '../hooks';
4
4
  import type { TextProps } from './types';
5
5
 
6
6
  const styles = StyleSheet.create({
7
- light: { color: '#000000' },
8
- dark: { color: '#FFFFFF' },
7
+ light: { color: 'var(--expo-ui-foreground, #000000)' },
8
+ dark: { color: 'var(--expo-ui-foreground, #FFFFFF)' },
9
9
  hidden: { display: 'none' },
10
10
  disabled: { opacity: 0.5 },
11
11
  });
@@ -132,6 +132,10 @@ export const globalCss = css`
132
132
  }
133
133
  }
134
134
 
135
+ [data-theme='light'] {
136
+ ${lightVariables}
137
+ }
138
+
135
139
  [data-theme='dark'] {
136
140
  ${darkVariables}
137
141
  }
@@ -1 +0,0 @@
1
- 5d7c4fd251da7578f23af5102d539533aefb3e64
@@ -1 +0,0 @@
1
- f9a24faad34f9f66bebcdde7d05a6cf72a8b4b9030819b80049de5084a694ef0
@@ -1 +0,0 @@
1
- 10ed672c04082cf5f06e6ca6dca0f28229f11f3d503d46e5b61dbc7d3ad50bfdc1399838dd38dc5b8c1643ec375c4bf1672c95606ce28f7ed36384f66b829b68
@@ -1 +0,0 @@
1
- 93a6d734857d79049d179014133d651be167840a
@@ -1 +0,0 @@
1
- 6cbb10f1e4cd5618c6997d87c2021e97c7bab1b8fc4ecc7be48f563e9c0e284a
@@ -1 +0,0 @@
1
- ba561fa50c9fde30184d2c36051e644fd87db59555b7b38f8e2e5b7096b03bf0d2aec3e53fff1831d2705d85b174ec1a7fc2e9cadc69c41237aac262bbea9365
@@ -1 +0,0 @@
1
- b378b5a3097dfa2a27e87822671b5b1867b14d52
@@ -1 +0,0 @@
1
- 46af13485988415a3ff14c812754b46df0b5cf7d0b7ebb28a80d7b16c3306fe4
@@ -1 +0,0 @@
1
- c9fcfdbaa4dbae59c5112fffa82e03ce4c36bb3840f98c1f149c9b0d8d0634dff5c5f63e47f32e921933b5a29bdab362830aecf5f37e3fa82cd552c28e774f71
@@ -1 +0,0 @@
1
- ff65582de003d4ba6fbfb2194fb4bb97bd523798
@@ -1 +0,0 @@
1
- fde46f8c2665d31cc8c43574f2897aed7e82a9db1e29fdf0a557e4c8d528f005
@@ -1 +0,0 @@
1
- 1f1f387588df2979f0a9f2eb9db168b05343069b1ffe2f46f30da422e31d554d9133a96afc594e69824183460ab5bfb9f2982a43613d294c31eac7a3d814b23b