@expo/ui 1.0.0-canary-20250320-7a205d3 → 1.0.0-canary-20250331-817737a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/build/components/Label/index.d.ts +28 -0
- package/build/components/Label/index.d.ts.map +1 -0
- package/build/components/Label/index.ios.d.ts +10 -0
- package/build/components/Label/index.ios.d.ts.map +1 -0
- package/build/components/List/index.d.ts +87 -0
- package/build/components/List/index.d.ts.map +1 -0
- package/build/components/List/index.ios.d.ts +9 -0
- package/build/components/List/index.ios.d.ts.map +1 -0
- package/build/components/Section/index.d.ts +4 -1
- package/build/components/Section/index.d.ts.map +1 -1
- package/build/src/types.d.ts +2 -0
- package/build/src/types.d.ts.map +1 -1
- package/components/Label/index.ios.tsx +16 -0
- package/components/Label/index.tsx +34 -0
- package/components/List/index.ios.tsx +35 -0
- package/components/List/index.tsx +99 -0
- package/components/Section/index.tsx +4 -1
- package/ios/ExpoUIModule.swift +2 -0
- package/ios/Label.swift +24 -0
- package/ios/List.swift +122 -0
- package/ios/SectionView.swift +1 -1
- package/package.json +2 -2
- package/src/types.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
- Adds `DateTimePicker` component. ([#34883](https://github.com/expo/expo/pull/34883) by [@alanjhughes](https://github.com/alanjhughes))
|
|
20
20
|
- Add CircularProgress and LinearProgress component. ([#34907](https://github.com/expo/expo/pull/34907) by [@janicduplessis](https://github.com/janicduplessis))
|
|
21
21
|
- Add Gauge component ([#35032](https://github.com/expo/expo/pull/35032) by [@jakex7](https://github.com/jakex7))
|
|
22
|
+
- Add List and Label component ([#35222](https://github.com/expo/expo/pull/35222) by [@Pflaumenbaum](https://github.com/Pflaumenbaum))
|
|
22
23
|
|
|
23
24
|
### 🐛 Bug fixes
|
|
24
25
|
|
|
@@ -53,6 +54,7 @@
|
|
|
53
54
|
- Add docs ([#34808](https://github.com/expo/expo/pull/34808) by [@aleqsio](https://github.com/aleqsio))
|
|
54
55
|
- [apple] Migrate remaining `expo-module.config.json` to unified platform syntax. ([#34445](https://github.com/expo/expo/pull/34445) by [@reichhartd](https://github.com/reichhartd))
|
|
55
56
|
- Rename the events for the `Switch` component. ([#34577](https://github.com/expo/expo/pull/34577) by [@behenate](https://github.com/behenate))
|
|
57
|
+
- Allow lower case section titles ([#35113](https://github.com/expo/expo/pull/35113) by [@Pflaumenbaum](https://github.com/Pflaumenbaum))
|
|
56
58
|
|
|
57
59
|
## 0.0.1 — 2025-01-21
|
|
58
60
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
export type LabelProps = {
|
|
3
|
+
/**
|
|
4
|
+
* The title text to be displayed in the label.
|
|
5
|
+
*/
|
|
6
|
+
title?: string;
|
|
7
|
+
/**
|
|
8
|
+
* The name of the SFSymbol to be displayed in the label.
|
|
9
|
+
*/
|
|
10
|
+
systemImage?: string;
|
|
11
|
+
/**
|
|
12
|
+
* The color of the label icon.
|
|
13
|
+
*/
|
|
14
|
+
color?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Additional styles to apply to the label.
|
|
17
|
+
*/
|
|
18
|
+
style?: StyleProp<ViewStyle>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Renders a native label view, which could be used in a list or section.
|
|
22
|
+
*
|
|
23
|
+
* @param {LabelProps} props - The properties passed to the Label component.
|
|
24
|
+
* @returns {JSX.Element} The rendered native Label component.
|
|
25
|
+
* @platform ios
|
|
26
|
+
*/
|
|
27
|
+
export declare function Label(props: LabelProps): import("react").JSX.Element;
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../components/Label/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAQ,SAAS,EAAE,MAAM,cAAc,CAAC;AAE1D,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,+BAEtC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LabelProps } from '.';
|
|
2
|
+
/**
|
|
3
|
+
* Renders a native label view, which could be used in a list or section.
|
|
4
|
+
*
|
|
5
|
+
* @param {LabelProps} props - The properties passed to the Label component.
|
|
6
|
+
* @returns {JSX.Element} The rendered native Label component.
|
|
7
|
+
* @platform ios
|
|
8
|
+
*/
|
|
9
|
+
export declare function Label(props: LabelProps): import("react").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=index.ios.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.ios.d.ts","sourceRoot":"","sources":["../../../components/Label/index.ios.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC;AAI/B;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,+BAEtC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
import { ViewEvent } from '../../src/types';
|
|
3
|
+
export type ListStyle = 'automatic' | 'plain' | 'inset' | 'insetGrouped' | 'grouped' | 'sidebar';
|
|
4
|
+
export interface ListProps {
|
|
5
|
+
/**
|
|
6
|
+
* Custom style for the container wrapping the list.
|
|
7
|
+
*/
|
|
8
|
+
style?: StyleProp<ViewStyle>;
|
|
9
|
+
/**
|
|
10
|
+
* One of the predefined ListStyle types in SwiftUI.
|
|
11
|
+
* @default 'automatic'
|
|
12
|
+
*/
|
|
13
|
+
listStyle?: ListStyle;
|
|
14
|
+
/**
|
|
15
|
+
* Allows the selection of list items.
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
selectEnabled?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Enables reordering of list items.
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
moveEnabled?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Allows the deletion of list items.
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
deleteEnabled?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Makes the list scrollable.
|
|
31
|
+
* @default true
|
|
32
|
+
* @platform ios 16.0+
|
|
33
|
+
*/
|
|
34
|
+
scrollEnabled?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Enables SwiftUI edit mode.
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
editModeEnabled?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* The children elements to be rendered inside the list.
|
|
42
|
+
*/
|
|
43
|
+
children: React.ReactNode;
|
|
44
|
+
/**
|
|
45
|
+
* Callback triggered when an item is deleted from the list.
|
|
46
|
+
*/
|
|
47
|
+
onDeleteItem?: (index: number) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Callback triggered when an item is moved in the list.
|
|
50
|
+
*/
|
|
51
|
+
onMoveItem?: (from: number, to: number) => void;
|
|
52
|
+
/**
|
|
53
|
+
* Callback triggered when the selection changes in a list.
|
|
54
|
+
*/
|
|
55
|
+
onSelectionChange?: (selection: number[]) => void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* DeleteItemEvent represents an event triggered when an item is deleted from the list.
|
|
59
|
+
*/
|
|
60
|
+
type DeleteItemEvent = ViewEvent<'onDeleteItem', {
|
|
61
|
+
index: number;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* MoveItemEvent represents an event triggered when an item is moved in the list.
|
|
65
|
+
*/
|
|
66
|
+
type MoveItemEvent = ViewEvent<'onMoveItem', {
|
|
67
|
+
from: number;
|
|
68
|
+
to: number;
|
|
69
|
+
}>;
|
|
70
|
+
/**
|
|
71
|
+
* SelectItemEvent represents an event triggered when the selection changes in a list.
|
|
72
|
+
*/
|
|
73
|
+
type SelectItemEvent = ViewEvent<'onSelectionChange', {
|
|
74
|
+
selection: number[];
|
|
75
|
+
}>;
|
|
76
|
+
export type NativeListProps = Omit<ListProps, 'onDeleteItem' | 'onMoveItem' | 'onSelectionChange'> & DeleteItemEvent & MoveItemEvent & SelectItemEvent & {
|
|
77
|
+
children: React.ReactNode;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* A list component that renders its children using a native SwiftUI list.
|
|
81
|
+
* @param {ListProps} props - The properties for the list component.
|
|
82
|
+
* @returns {JSX.Element | null} The rendered list with its children or null if the platform is unsupported.
|
|
83
|
+
* @platform ios
|
|
84
|
+
*/
|
|
85
|
+
export declare function List({ children }: ListProps): import("react").ReactNode;
|
|
86
|
+
export {};
|
|
87
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../components/List/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,cAAc,GAAG,SAAS,GAAG,SAAS,CAAC;AAEjG,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE7B;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAE1B;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEvC;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhD;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACnD;AAED;;GAEG;AACH,KAAK,eAAe,GAAG,SAAS,CAAC,cAAc,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACpE;;GAEG;AACH,KAAK,aAAa,GAAG,SAAS,CAAC,YAAY,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC3E;;GAEG;AACH,KAAK,eAAe,GAAG,SAAS,CAAC,mBAAmB,EAAE;IAAE,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAAC;AAE/E,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,GAAG,YAAY,GAAG,mBAAmB,CAAC,GAChG,eAAe,GACf,aAAa,GACb,eAAe,GAAG;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEJ;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,SAAS,6BAE3C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ListProps } from '.';
|
|
2
|
+
/**
|
|
3
|
+
* A list component that renders its children using a native SwiftUI list.
|
|
4
|
+
* @param {ListProps} props - The properties for the list component.
|
|
5
|
+
* @returns {JSX.Element | null} The rendered list with its children or null if the platform is unsupported.
|
|
6
|
+
* @platform ios
|
|
7
|
+
*/
|
|
8
|
+
export declare function List(props: ListProps): import("react").JSX.Element | null;
|
|
9
|
+
//# sourceMappingURL=index.ios.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.ios.d.ts","sourceRoot":"","sources":["../../../components/List/index.ios.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAmB,MAAM,GAAG,CAAC;AAc/C;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,sCAYpC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
2
|
export type SectionProps = {
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @note On iOS, section titles are usually capitalized for consistency with platform conventions.
|
|
5
|
+
*/
|
|
4
6
|
title?: string;
|
|
5
7
|
children: any;
|
|
8
|
+
style?: StyleProp<ViewStyle>;
|
|
6
9
|
};
|
|
7
10
|
/**
|
|
8
11
|
* Section component uses the native [Section](https://developer.apple.com/documentation/swiftui/section) component.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../components/Section/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../components/Section/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG;IACzB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,EAAE,YAAY,OAEjD"}
|
package/build/src/types.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export type * from '../components/Picker';
|
|
|
4
4
|
export type * from '../components/Section';
|
|
5
5
|
export type * from '../components/Slider';
|
|
6
6
|
export type * from '../components/Switch';
|
|
7
|
+
export type * from '../components/Label';
|
|
8
|
+
export type * from '../components/List';
|
|
7
9
|
/**
|
|
8
10
|
* @hidden
|
|
9
11
|
*/
|
package/build/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,mBAAmB,sBAAsB,CAAC;AAC1C,mBAAmB,2BAA2B,CAAC;AAC/C,mBAAmB,sBAAsB,CAAC;AAC1C,mBAAmB,uBAAuB,CAAC;AAC3C,mBAAmB,sBAAsB,CAAC;AAC1C,mBAAmB,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,mBAAmB,sBAAsB,CAAC;AAC1C,mBAAmB,2BAA2B,CAAC;AAC/C,mBAAmB,sBAAsB,CAAC;AAC1C,mBAAmB,uBAAuB,CAAC;AAC3C,mBAAmB,sBAAsB,CAAC;AAC1C,mBAAmB,sBAAsB,CAAC;AAC1C,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,oBAAoB,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,IAAI,SAAS,MAAM,EAAE,IAAI,IAAI,MAAM,CACvD,IAAI,EACJ,IAAI,SAAS,MAAM,GACf,CAAC,CAAC,KAAK,EAAE;IAAE,WAAW,EAAE,IAAI,CAAA;CAAE,KAAK,IAAI,CAAC,GAAG,SAAS,GACpD,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAC7B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { requireNativeView } from 'expo';
|
|
2
|
+
|
|
3
|
+
import { LabelProps } from '.';
|
|
4
|
+
|
|
5
|
+
const LabelNativeView: React.ComponentType<LabelProps> = requireNativeView('ExpoUI', 'LabelView');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Renders a native label view, which could be used in a list or section.
|
|
9
|
+
*
|
|
10
|
+
* @param {LabelProps} props - The properties passed to the Label component.
|
|
11
|
+
* @returns {JSX.Element} The rendered native Label component.
|
|
12
|
+
* @platform ios
|
|
13
|
+
*/
|
|
14
|
+
export function Label(props: LabelProps) {
|
|
15
|
+
return <LabelNativeView {...props} />;
|
|
16
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { StyleProp, Text, ViewStyle } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export type LabelProps = {
|
|
4
|
+
/**
|
|
5
|
+
* The title text to be displayed in the label.
|
|
6
|
+
*/
|
|
7
|
+
title?: string;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The name of the SFSymbol to be displayed in the label.
|
|
11
|
+
*/
|
|
12
|
+
systemImage?: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The color of the label icon.
|
|
16
|
+
*/
|
|
17
|
+
color?: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Additional styles to apply to the label.
|
|
21
|
+
*/
|
|
22
|
+
style?: StyleProp<ViewStyle>;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Renders a native label view, which could be used in a list or section.
|
|
27
|
+
*
|
|
28
|
+
* @param {LabelProps} props - The properties passed to the Label component.
|
|
29
|
+
* @returns {JSX.Element} The rendered native Label component.
|
|
30
|
+
* @platform ios
|
|
31
|
+
*/
|
|
32
|
+
export function Label(props: LabelProps) {
|
|
33
|
+
return <Text>{props.title}</Text>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { requireNativeView } from 'expo';
|
|
2
|
+
|
|
3
|
+
import { ListProps, NativeListProps } from '.';
|
|
4
|
+
|
|
5
|
+
const ListNativeView: React.ComponentType<NativeListProps> | null =
|
|
6
|
+
requireNativeView<NativeListProps>('ExpoUI', 'ListView');
|
|
7
|
+
|
|
8
|
+
function transformListProps(props: Omit<ListProps, 'children'>): Omit<NativeListProps, 'children'> {
|
|
9
|
+
return {
|
|
10
|
+
...props,
|
|
11
|
+
onDeleteItem: ({ nativeEvent: { index } }) => props?.onDeleteItem?.(index),
|
|
12
|
+
onMoveItem: ({ nativeEvent: { from, to } }) => props?.onMoveItem?.(from, to),
|
|
13
|
+
onSelectionChange: ({ nativeEvent: { selection } }) => props?.onSelectionChange?.(selection),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A list component that renders its children using a native SwiftUI list.
|
|
19
|
+
* @param {ListProps} props - The properties for the list component.
|
|
20
|
+
* @returns {JSX.Element | null} The rendered list with its children or null if the platform is unsupported.
|
|
21
|
+
* @platform ios
|
|
22
|
+
*/
|
|
23
|
+
export function List(props: ListProps) {
|
|
24
|
+
const { children, ...nativeProps } = props;
|
|
25
|
+
|
|
26
|
+
if (!ListNativeView) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<ListNativeView {...transformListProps(nativeProps)} style={[props.style, { flex: 1 }]}>
|
|
32
|
+
{children}
|
|
33
|
+
</ListNativeView>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
|
|
3
|
+
import { ViewEvent } from '../../src/types';
|
|
4
|
+
|
|
5
|
+
export type ListStyle = 'automatic' | 'plain' | 'inset' | 'insetGrouped' | 'grouped' | 'sidebar';
|
|
6
|
+
|
|
7
|
+
export interface ListProps {
|
|
8
|
+
/**
|
|
9
|
+
* Custom style for the container wrapping the list.
|
|
10
|
+
*/
|
|
11
|
+
style?: StyleProp<ViewStyle>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* One of the predefined ListStyle types in SwiftUI.
|
|
15
|
+
* @default 'automatic'
|
|
16
|
+
*/
|
|
17
|
+
listStyle?: ListStyle;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Allows the selection of list items.
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
selectEnabled?: boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Enables reordering of list items.
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
moveEnabled?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Allows the deletion of list items.
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
deleteEnabled?: boolean;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Makes the list scrollable.
|
|
39
|
+
* @default true
|
|
40
|
+
* @platform ios 16.0+
|
|
41
|
+
*/
|
|
42
|
+
scrollEnabled?: boolean;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Enables SwiftUI edit mode.
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
editModeEnabled?: boolean;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The children elements to be rendered inside the list.
|
|
52
|
+
*/
|
|
53
|
+
children: React.ReactNode;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Callback triggered when an item is deleted from the list.
|
|
57
|
+
*/
|
|
58
|
+
onDeleteItem?: (index: number) => void;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Callback triggered when an item is moved in the list.
|
|
62
|
+
*/
|
|
63
|
+
onMoveItem?: (from: number, to: number) => void;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Callback triggered when the selection changes in a list.
|
|
67
|
+
*/
|
|
68
|
+
onSelectionChange?: (selection: number[]) => void;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* DeleteItemEvent represents an event triggered when an item is deleted from the list.
|
|
73
|
+
*/
|
|
74
|
+
type DeleteItemEvent = ViewEvent<'onDeleteItem', { index: number }>;
|
|
75
|
+
/**
|
|
76
|
+
* MoveItemEvent represents an event triggered when an item is moved in the list.
|
|
77
|
+
*/
|
|
78
|
+
type MoveItemEvent = ViewEvent<'onMoveItem', { from: number; to: number }>;
|
|
79
|
+
/**
|
|
80
|
+
* SelectItemEvent represents an event triggered when the selection changes in a list.
|
|
81
|
+
*/
|
|
82
|
+
type SelectItemEvent = ViewEvent<'onSelectionChange', { selection: number[] }>;
|
|
83
|
+
|
|
84
|
+
export type NativeListProps = Omit<ListProps, 'onDeleteItem' | 'onMoveItem' | 'onSelectionChange'> &
|
|
85
|
+
DeleteItemEvent &
|
|
86
|
+
MoveItemEvent &
|
|
87
|
+
SelectItemEvent & {
|
|
88
|
+
children: React.ReactNode;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* A list component that renders its children using a native SwiftUI list.
|
|
93
|
+
* @param {ListProps} props - The properties for the list component.
|
|
94
|
+
* @returns {JSX.Element | null} The rendered list with its children or null if the platform is unsupported.
|
|
95
|
+
* @platform ios
|
|
96
|
+
*/
|
|
97
|
+
export function List({ children }: ListProps) {
|
|
98
|
+
return children;
|
|
99
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
2
|
|
|
3
3
|
export type SectionProps = {
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @note On iOS, section titles are usually capitalized for consistency with platform conventions.
|
|
6
|
+
*/
|
|
5
7
|
title?: string;
|
|
6
8
|
children: any;
|
|
9
|
+
style?: StyleProp<ViewStyle>;
|
|
7
10
|
};
|
|
8
11
|
|
|
9
12
|
/**
|
package/ios/ExpoUIModule.swift
CHANGED
package/ios/Label.swift
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Copyright 2025-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesCore
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
class LabelViewProps: ExpoSwiftUI.ViewProps {
|
|
7
|
+
@Field var title: String?
|
|
8
|
+
@Field var systemImage: String?
|
|
9
|
+
@Field var color: Color?
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
struct LabelView: ExpoSwiftUI.View {
|
|
13
|
+
@EnvironmentObject var props: LabelViewProps
|
|
14
|
+
@EnvironmentObject var shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy
|
|
15
|
+
var body: some View {
|
|
16
|
+
ExpoSwiftUI.AutoSizingStack(shadowNodeProxy: shadowNodeProxy, axis: .both) {
|
|
17
|
+
Label(
|
|
18
|
+
title: { Text(props.title ?? "") },
|
|
19
|
+
icon: { Image(systemName: props.systemImage ?? "").foregroundStyle(props.color ?? Color.accentColor) }
|
|
20
|
+
)
|
|
21
|
+
.fixedSize()
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
package/ios/List.swift
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Copyright 2025-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesCore
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
class ListProps: ExpoSwiftUI.ViewProps {
|
|
7
|
+
@Field var listStyle: String = "automatic"
|
|
8
|
+
@Field var moveEnabled: Bool = false
|
|
9
|
+
@Field var deleteEnabled: Bool = false
|
|
10
|
+
@Field var selectEnabled: Bool = true
|
|
11
|
+
@Field var scrollEnabled: Bool = false
|
|
12
|
+
@Field var editModeEnabled: Bool = false
|
|
13
|
+
var onDeleteItem = EventDispatcher()
|
|
14
|
+
var onMoveItem = EventDispatcher()
|
|
15
|
+
var onSelectionChange = EventDispatcher()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
struct ListView: ExpoSwiftUI.View {
|
|
19
|
+
@EnvironmentObject var props: ListProps
|
|
20
|
+
@State private var selection: Set<Int> = []
|
|
21
|
+
@State var editModeEnabled: EditMode = .inactive
|
|
22
|
+
@State var search: String = ""
|
|
23
|
+
var body: some View {
|
|
24
|
+
let list = List(selection: props.selectEnabled ? $selection : nil) {
|
|
25
|
+
UnwrappedChildren { child, isHostingView in
|
|
26
|
+
child
|
|
27
|
+
.if(!isHostingView) {
|
|
28
|
+
$0.offset(
|
|
29
|
+
x: UIDevice.current.userInterfaceIdiom == .pad
|
|
30
|
+
? IPAD_OFFSET : IPHONE_OFFSET)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
.onDelete(perform: handleDelete)
|
|
34
|
+
.onMove(perform: handleMove)
|
|
35
|
+
.deleteDisabled(!props.deleteEnabled)
|
|
36
|
+
.moveDisabled(!props.moveEnabled)
|
|
37
|
+
}
|
|
38
|
+
.modifier(ListStyleModifer(style: props.listStyle))
|
|
39
|
+
.onAppear {
|
|
40
|
+
editModeEnabled = props.editModeEnabled ? .active : .inactive
|
|
41
|
+
}
|
|
42
|
+
.onChange(of: props.editModeEnabled) { newValue in
|
|
43
|
+
withAnimation {
|
|
44
|
+
editModeEnabled = newValue ? .active : .inactive
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
.onChange(of: selection) { selection in
|
|
48
|
+
print(selection)
|
|
49
|
+
handleSelectionChange(selection: selection)
|
|
50
|
+
}
|
|
51
|
+
.modifier(ScrollDisabledModifier(scrollEnabled: props.selectEnabled))
|
|
52
|
+
.environment(\.editMode, $editModeEnabled)
|
|
53
|
+
if #available(iOS 16.0, tvOS 16.0, *) {
|
|
54
|
+
list.scrollDisabled(!props.scrollEnabled)
|
|
55
|
+
} else {
|
|
56
|
+
list
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
func handleDelete(at offsets: IndexSet) {
|
|
60
|
+
for offset in offsets {
|
|
61
|
+
props.onDeleteItem([
|
|
62
|
+
"index": offset
|
|
63
|
+
])
|
|
64
|
+
selection.remove(offset)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
func handleMove(from sources: IndexSet, to destination: Int) {
|
|
68
|
+
for source in sources {
|
|
69
|
+
props.onMoveItem([
|
|
70
|
+
"from": source,
|
|
71
|
+
"to": destination
|
|
72
|
+
])
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
func handleSelectionChange(selection: Set<Int>) {
|
|
76
|
+
let selectionArray = Array(selection)
|
|
77
|
+
let jsonDict: [String: Any] = [
|
|
78
|
+
"selection": selectionArray
|
|
79
|
+
]
|
|
80
|
+
props.onSelectionChange(jsonDict)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
struct ListStyleModifer: ViewModifier {
|
|
85
|
+
var style: String
|
|
86
|
+
@ViewBuilder func body(content: Content) -> some View {
|
|
87
|
+
switch style {
|
|
88
|
+
case "grouped":
|
|
89
|
+
content.listStyle(.grouped)
|
|
90
|
+
case "insetGrouped":
|
|
91
|
+
#if !os(tvOS)
|
|
92
|
+
content.listStyle(.insetGrouped)
|
|
93
|
+
#endif
|
|
94
|
+
case "inset":
|
|
95
|
+
#if !os(tvOS)
|
|
96
|
+
content.listStyle(.inset)
|
|
97
|
+
#endif
|
|
98
|
+
case "plain":
|
|
99
|
+
content.listStyle(.plain)
|
|
100
|
+
case "sidebar":
|
|
101
|
+
#if !os(tvOS)
|
|
102
|
+
content.listStyle(.sidebar)
|
|
103
|
+
#endif
|
|
104
|
+
case "automatic":
|
|
105
|
+
content.listStyle(.automatic)
|
|
106
|
+
default:
|
|
107
|
+
content
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
struct ScrollDisabledModifier: ViewModifier {
|
|
113
|
+
let scrollEnabled: Bool
|
|
114
|
+
|
|
115
|
+
func body(content: Content) -> some View {
|
|
116
|
+
if #available(iOS 16.0, tvOS 16.0, *) {
|
|
117
|
+
content.scrollDisabled(!scrollEnabled)
|
|
118
|
+
} else {
|
|
119
|
+
content
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/ios/SectionView.swift
CHANGED
|
@@ -15,7 +15,7 @@ struct SectionView: ExpoSwiftUI.View {
|
|
|
15
15
|
|
|
16
16
|
var body: some View {
|
|
17
17
|
let form = Form {
|
|
18
|
-
Section(header: Text(props.title ?? "")) {
|
|
18
|
+
Section(header: Text(props.title ?? "").textCase(nil)) {
|
|
19
19
|
UnwrappedChildren { child, isHostingView in
|
|
20
20
|
child
|
|
21
21
|
.if(!isHostingView) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/ui",
|
|
3
|
-
"version": "1.0.0-canary-
|
|
3
|
+
"version": "1.0.0-canary-20250331-817737a",
|
|
4
4
|
"description": "A collection of UI components",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "expo-module build",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"dependencies": {},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/react": "~19.0.10",
|
|
30
|
-
"expo-module-scripts": "4.0.5-canary-
|
|
30
|
+
"expo-module-scripts": "4.0.5-canary-20250331-817737a"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"expo": "*",
|
package/src/types.ts
CHANGED
|
@@ -4,6 +4,8 @@ export type * from '../components/Picker';
|
|
|
4
4
|
export type * from '../components/Section';
|
|
5
5
|
export type * from '../components/Slider';
|
|
6
6
|
export type * from '../components/Switch';
|
|
7
|
+
export type * from '../components/Label';
|
|
8
|
+
export type * from '../components/List';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* @hidden
|