@expo/ui 58.0.4 → 58.0.6
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 +21 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/ui/HostView.kt +6 -4
- package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +11 -0
- package/build/jetpack-compose/colors.js +20 -1
- package/build/jetpack-compose/colors.js.map +1 -1
- package/build/jetpack-compose/modifiers/index.d.ts +10 -0
- package/build/jetpack-compose/modifiers/index.js +11 -0
- package/build/jetpack-compose/modifiers/index.js.map +1 -1
- package/build/swift-ui/List/DataListForEach.d.ts +59 -0
- package/build/swift-ui/List/DataListForEach.js +137 -0
- package/build/swift-ui/List/DataListForEach.js.map +1 -0
- package/build/swift-ui/List/ListForEach.d.ts +15 -4
- package/build/swift-ui/List/ListForEach.js +40 -3
- package/build/swift-ui/List/ListForEach.js.map +1 -1
- package/build/swift-ui/List/index.d.ts +1 -1
- package/build/swift-ui/List/index.js.map +1 -1
- package/build/swift-ui/List/window.d.ts +5 -0
- package/build/swift-ui/List/window.js +28 -0
- package/build/swift-ui/List/window.js.map +1 -0
- package/build/swift-ui/modifiers/index.d.ts +16 -7
- package/build/swift-ui/modifiers/index.js +10 -5
- package/build/swift-ui/modifiers/index.js.map +1 -1
- package/expo-module.config.json +1 -1
- package/ios/DataListForEachView.swift +255 -0
- package/ios/ExpoUIModule.swift +3 -0
- package/ios/HostView.swift +29 -7
- package/ios/ListForEachView.swift +12 -3
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.4/expo.modules.ui-58.0.4-sources.jar → 58.0.6/expo.modules.ui-58.0.6-sources.jar} +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6-sources.jar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6-sources.jar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6-sources.jar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6-sources.jar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.aar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.aar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.aar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.aar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.4/expo.modules.ui-58.0.4.module → 58.0.6/expo.modules.ui-58.0.6.module} +22 -22
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.module.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.module.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.module.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.module.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.4/expo.modules.ui-58.0.4.pom → 58.0.6/expo.modules.ui-58.0.6.pom} +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.pom.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.pom.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.pom.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.6/expo.modules.ui-58.0.6.pom.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml +4 -4
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.md5 +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha1 +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha256 +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha512 +1 -1
- package/package.json +2 -2
- package/prebuilds/output/debug/xcframeworks/ExpoUI.tar.gz +0 -0
- package/prebuilds/output/release/xcframeworks/ExpoUI.tar.gz +0 -0
- package/src/jetpack-compose/colors.ts +23 -1
- package/src/jetpack-compose/modifiers/index.ts +11 -0
- package/src/swift-ui/List/DataListForEach.tsx +249 -0
- package/src/swift-ui/List/ListForEach.tsx +56 -6
- package/src/swift-ui/List/index.tsx +1 -1
- package/src/swift-ui/List/window.ts +28 -0
- package/src/swift-ui/modifiers/index.ts +50 -14
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4-sources.jar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4-sources.jar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4-sources.jar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4-sources.jar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.aar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.aar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.aar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.aar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.module.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.module.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.module.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.module.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.pom.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.pom.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.pom.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.pom.sha512 +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
89c63e4e2a7fce899cd9101093d5c1105c62feffaea5ec288e6a39e5b8739446
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
50a66b6bfe1bbcedd9157651a817cac9309fb48c2a649c274b5a34e625370c8cd487af0235f5801320779f19049a619e06bcb71e69df646a129d06bfb0041c27
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/ui",
|
|
3
|
-
"version": "58.0.
|
|
3
|
+
"version": "58.0.6",
|
|
4
4
|
"description": "A collection of UI components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Jetpack Compose",
|
|
@@ -171,7 +171,7 @@
|
|
|
171
171
|
"optional": true
|
|
172
172
|
}
|
|
173
173
|
},
|
|
174
|
-
"gitHead": "
|
|
174
|
+
"gitHead": "8aeb4368d396d2d71a2fc8c652c4d1d4d53ed858",
|
|
175
175
|
"scripts": {
|
|
176
176
|
"precompile-ios": "et prebuild-package-for-publish",
|
|
177
177
|
"build": "pnpm run build:lib && pnpm run build:plugin",
|
|
Binary file
|
|
Binary file
|
|
@@ -183,11 +183,33 @@ export const isDynamicColorAvailable: boolean = ExpoUIModule.isDynamicColorAvail
|
|
|
183
183
|
*/
|
|
184
184
|
export const HostPaletteContext = createContext<MaterialColors | null>(null);
|
|
185
185
|
|
|
186
|
+
// Cache the `scheme` + `seedColor` keyed palette to prevent sync calls to `getMaterialColors`.
|
|
187
|
+
// https://github.com/expo/expo/issues/50477
|
|
188
|
+
const seededPalettes = new Map<string, MaterialColors>();
|
|
189
|
+
const MAX_SEEDED_PALETTES = 32;
|
|
190
|
+
|
|
186
191
|
/**
|
|
187
192
|
* Get the Material 3 color palette.
|
|
188
193
|
*/
|
|
189
194
|
export function getMaterialColors(options?: MaterialColorsOptions): MaterialColors {
|
|
190
|
-
|
|
195
|
+
const scheme = options?.scheme;
|
|
196
|
+
const seedColor = options?.seedColor;
|
|
197
|
+
const isCacheable =
|
|
198
|
+
(scheme === 'light' || scheme === 'dark') &&
|
|
199
|
+
(typeof seedColor === 'string' || typeof seedColor === 'number');
|
|
200
|
+
if (!isCacheable) {
|
|
201
|
+
return ExpoUIModule.getMaterialColors(options ?? null);
|
|
202
|
+
}
|
|
203
|
+
const key = `${scheme}:${seedColor}`;
|
|
204
|
+
let palette = seededPalettes.get(key);
|
|
205
|
+
if (!palette) {
|
|
206
|
+
palette = ExpoUIModule.getMaterialColors(options) as MaterialColors;
|
|
207
|
+
if (seededPalettes.size >= MAX_SEEDED_PALETTES) {
|
|
208
|
+
seededPalettes.delete(seededPalettes.keys().next().value!);
|
|
209
|
+
}
|
|
210
|
+
seededPalettes.set(key, palette);
|
|
211
|
+
}
|
|
212
|
+
return palette;
|
|
191
213
|
}
|
|
192
214
|
|
|
193
215
|
/**
|
|
@@ -211,6 +211,17 @@ export const alpha = (alpha: number) => createModifier('alpha', { alpha });
|
|
|
211
211
|
*/
|
|
212
212
|
export const blur = (radius: number) => createModifier('blur', { radius });
|
|
213
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Adds rounded corners to the component.
|
|
216
|
+
*
|
|
217
|
+
* > **Note:** Works only inside Android widgets built with `expo-widgets`, on Android 12 (API level 31) and later.
|
|
218
|
+
*
|
|
219
|
+
* Jetpack Compose has no exact equivalent of Glance's `cornerRadius`, so Expo UI ignores this
|
|
220
|
+
* modifier. Use `clip(Shapes.RoundedCorner(radius))` to round corners in an app.
|
|
221
|
+
* @param radius - Corner radius in dp.
|
|
222
|
+
*/
|
|
223
|
+
export const cornerRadius = (radius: number) => createModifier('cornerRadius', { radius });
|
|
224
|
+
|
|
214
225
|
// =============================================================================
|
|
215
226
|
// Transform Modifiers
|
|
216
227
|
// =============================================================================
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { requireNativeView } from 'expo';
|
|
2
|
+
import { memo, useLayoutEffect, useMemo, useRef, useState, type ReactElement } from 'react';
|
|
3
|
+
|
|
4
|
+
import { type ViewEvent } from '../../types';
|
|
5
|
+
import { createViewModifierEventListener } from '../modifiers/utils';
|
|
6
|
+
import { type CommonViewModifierProps } from '../types';
|
|
7
|
+
import { getSlotIndices, getWindow } from './window';
|
|
8
|
+
|
|
9
|
+
export interface ListForEachProps<ItemT> extends CommonViewModifierProps {
|
|
10
|
+
/** Called with deleted indices from this group's `data` array. */
|
|
11
|
+
onDelete?: (indices: number[]) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Called with the source indices and the destination index. The destination index counts
|
|
14
|
+
* positions before the moved items are removed, so it can equal `data.length`.
|
|
15
|
+
*/
|
|
16
|
+
onMove?: (sourceIndices: number[], destination: number) => void;
|
|
17
|
+
/** Items to display. Replace the array when updating data. */
|
|
18
|
+
data: readonly ItemT[];
|
|
19
|
+
/** Returns a stable, unique string key, also used for `List` selection. */
|
|
20
|
+
keyExtractor: (item: ItemT, index: number) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Renders a row. When `recycling` is `true`, wrap it in `useCallback`, or every row
|
|
23
|
+
* re-renders on each parent render.
|
|
24
|
+
* Recycled rows are reused for other items, so their local state (`useState`) carries over.
|
|
25
|
+
* Reset it when the item changes, or keep the state outside the row.
|
|
26
|
+
*/
|
|
27
|
+
children: (info: { item: ItemT; index: number }) => ReactElement;
|
|
28
|
+
/**
|
|
29
|
+
* Renders only the rows near the visible range and reuses them while scrolling. Set to `false` to
|
|
30
|
+
* render every row at once. Set it once; changing it remounts the rows.
|
|
31
|
+
* @default true
|
|
32
|
+
*/
|
|
33
|
+
recycling?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Extra rows to prepare on each side of the visible rows. Must be a non-negative integer.
|
|
36
|
+
* Ignored when `recycling` is `false`.
|
|
37
|
+
* @default 10
|
|
38
|
+
*/
|
|
39
|
+
overscanCount?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Placeholder height in points, excluding `List` insets, until a row is measured.
|
|
42
|
+
* Must be positive. Measurements reset when `data` or width changes.
|
|
43
|
+
* Ignored when `recycling` is `false`.
|
|
44
|
+
* @default 64
|
|
45
|
+
*/
|
|
46
|
+
estimatedItemSize?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type WindowEvent = { first: number; last: number; revision: number };
|
|
50
|
+
type NativeProps = CommonViewModifierProps &
|
|
51
|
+
ViewEvent<'onWindowChange', WindowEvent> &
|
|
52
|
+
ViewEvent<'onDelete', { indices: number[]; revision: number }> &
|
|
53
|
+
ViewEvent<'onMove', { sourceIndices: number[]; destination: number; revision: number }> & {
|
|
54
|
+
deleteEnabled: boolean;
|
|
55
|
+
moveEnabled: boolean;
|
|
56
|
+
itemKeys: string[];
|
|
57
|
+
revision: number;
|
|
58
|
+
estimatedItemSize: number;
|
|
59
|
+
children: ReactElement;
|
|
60
|
+
};
|
|
61
|
+
type SlotProps = {
|
|
62
|
+
itemKey: string;
|
|
63
|
+
index: number;
|
|
64
|
+
revision: number;
|
|
65
|
+
children: ReactElement;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const NativeList = requireNativeView<NativeProps>('ExpoUI', 'DataListForEachView');
|
|
69
|
+
export const NativeSlot = requireNativeView<SlotProps>('ExpoUI', 'DataListForEachItemView');
|
|
70
|
+
const NativePool = requireNativeView<{ children: ReactElement[] }>(
|
|
71
|
+
'ExpoUI',
|
|
72
|
+
'DataListForEachPoolView'
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// Skip unchanged rows when the window moves.
|
|
76
|
+
const RecycledRow = memo(function RecycledRow<ItemT>({
|
|
77
|
+
item,
|
|
78
|
+
index,
|
|
79
|
+
itemKey,
|
|
80
|
+
revision,
|
|
81
|
+
renderItem,
|
|
82
|
+
}: SlotPropsWithoutChildren & {
|
|
83
|
+
item: ItemT;
|
|
84
|
+
renderItem: ListForEachProps<ItemT>['children'];
|
|
85
|
+
}) {
|
|
86
|
+
return (
|
|
87
|
+
<NativeSlot itemKey={itemKey} index={index} revision={revision}>
|
|
88
|
+
{renderItem({ item, index })}
|
|
89
|
+
</NativeSlot>
|
|
90
|
+
);
|
|
91
|
+
}) as <ItemT>(
|
|
92
|
+
props: SlotPropsWithoutChildren & {
|
|
93
|
+
item: ItemT;
|
|
94
|
+
renderItem: ListForEachProps<ItemT>['children'];
|
|
95
|
+
}
|
|
96
|
+
) => ReactElement;
|
|
97
|
+
type SlotPropsWithoutChildren = Omit<SlotProps, 'children'>;
|
|
98
|
+
|
|
99
|
+
export function useItemKeys<ItemT>(
|
|
100
|
+
data: readonly ItemT[],
|
|
101
|
+
keyExtractor: ListForEachProps<ItemT>['keyExtractor']
|
|
102
|
+
): string[] {
|
|
103
|
+
const keyExtractorRef = useRef(keyExtractor);
|
|
104
|
+
keyExtractorRef.current = keyExtractor;
|
|
105
|
+
return useMemo(() => {
|
|
106
|
+
const keys = data.map((item, index) => keyExtractorRef.current(item, index));
|
|
107
|
+
if (keys.some((key) => typeof key !== 'string') || new Set(keys).size !== keys.length) {
|
|
108
|
+
throw new Error('List.ForEach keyExtractor must return a unique string for every item.');
|
|
109
|
+
}
|
|
110
|
+
return keys;
|
|
111
|
+
}, [data]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Renders a window of recycled rows inside List or Section.
|
|
116
|
+
* Rows show placeholders while JS prepares content. Native keys still cover the full data set.
|
|
117
|
+
* @platform ios
|
|
118
|
+
*/
|
|
119
|
+
export function DataListForEach<ItemT>({
|
|
120
|
+
data,
|
|
121
|
+
keyExtractor,
|
|
122
|
+
children: renderItem,
|
|
123
|
+
overscanCount = 10,
|
|
124
|
+
estimatedItemSize = 64,
|
|
125
|
+
modifiers,
|
|
126
|
+
onDelete,
|
|
127
|
+
onMove,
|
|
128
|
+
...props
|
|
129
|
+
}: ListForEachProps<ItemT>) {
|
|
130
|
+
if (!Number.isSafeInteger(overscanCount) || overscanCount < 0) {
|
|
131
|
+
throw new Error('List.ForEach overscanCount must be a non-negative integer.');
|
|
132
|
+
}
|
|
133
|
+
if (!Number.isFinite(estimatedItemSize) || estimatedItemSize <= 0) {
|
|
134
|
+
throw new Error('List.ForEach estimatedItemSize must be a positive finite number.');
|
|
135
|
+
}
|
|
136
|
+
const itemKeys = useItemKeys(data, keyExtractor);
|
|
137
|
+
const [state, setState] = useState({
|
|
138
|
+
keys: itemKeys,
|
|
139
|
+
first: 0,
|
|
140
|
+
last: 0,
|
|
141
|
+
revision: 0,
|
|
142
|
+
capacity: 0,
|
|
143
|
+
overscanCount,
|
|
144
|
+
});
|
|
145
|
+
let current = state;
|
|
146
|
+
if (state.keys !== itemKeys) {
|
|
147
|
+
const previousKey = state.keys[state.first];
|
|
148
|
+
const anchor = previousKey === undefined ? 0 : Math.max(0, itemKeys.indexOf(previousKey));
|
|
149
|
+
current = {
|
|
150
|
+
...state,
|
|
151
|
+
keys: itemKeys,
|
|
152
|
+
first: Math.min(anchor, Math.max(0, data.length - 1)),
|
|
153
|
+
last: Math.min(anchor + state.last - state.first, Math.max(0, data.length - 1)),
|
|
154
|
+
revision: state.revision + 1,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (current.overscanCount !== overscanCount) {
|
|
158
|
+
current = { ...current, overscanCount, capacity: 0 };
|
|
159
|
+
}
|
|
160
|
+
if (current !== state) setState(current);
|
|
161
|
+
const { start, capacity } = getWindow(
|
|
162
|
+
data.length,
|
|
163
|
+
current.first,
|
|
164
|
+
current.last,
|
|
165
|
+
overscanCount,
|
|
166
|
+
current.capacity
|
|
167
|
+
);
|
|
168
|
+
const committedRevision = useRef(current.revision);
|
|
169
|
+
useLayoutEffect(() => {
|
|
170
|
+
committedRevision.current = current.revision;
|
|
171
|
+
}, [current.revision]);
|
|
172
|
+
const indices = getSlotIndices(start, capacity);
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<NativeList
|
|
176
|
+
{...props}
|
|
177
|
+
modifiers={modifiers}
|
|
178
|
+
{...(modifiers ? createViewModifierEventListener(modifiers) : undefined)}
|
|
179
|
+
deleteEnabled={!!onDelete}
|
|
180
|
+
moveEnabled={!!onMove}
|
|
181
|
+
onDelete={
|
|
182
|
+
onDelete
|
|
183
|
+
? ({ nativeEvent }) => {
|
|
184
|
+
if (nativeEvent.revision === committedRevision.current) onDelete(nativeEvent.indices);
|
|
185
|
+
}
|
|
186
|
+
: undefined
|
|
187
|
+
}
|
|
188
|
+
onMove={
|
|
189
|
+
onMove
|
|
190
|
+
? ({ nativeEvent }) => {
|
|
191
|
+
if (nativeEvent.revision === committedRevision.current) {
|
|
192
|
+
onMove(nativeEvent.sourceIndices, nativeEvent.destination);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
: undefined
|
|
196
|
+
}
|
|
197
|
+
itemKeys={itemKeys}
|
|
198
|
+
revision={current.revision}
|
|
199
|
+
estimatedItemSize={estimatedItemSize}
|
|
200
|
+
onWindowChange={({ nativeEvent: event }) => {
|
|
201
|
+
if (
|
|
202
|
+
!Number.isSafeInteger(event.first) ||
|
|
203
|
+
!Number.isSafeInteger(event.last) ||
|
|
204
|
+
event.last < event.first
|
|
205
|
+
) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
setState((previous) => {
|
|
209
|
+
// Ignore requests from before a data change.
|
|
210
|
+
if (event.revision !== previous.revision) return previous;
|
|
211
|
+
const maximum = Math.max(0, previous.keys.length - 1);
|
|
212
|
+
const first = Math.max(0, Math.min(event.first, maximum));
|
|
213
|
+
const last = Math.max(first, Math.min(event.last, maximum));
|
|
214
|
+
const { capacity } = getWindow(
|
|
215
|
+
previous.keys.length,
|
|
216
|
+
first,
|
|
217
|
+
last,
|
|
218
|
+
previous.overscanCount,
|
|
219
|
+
previous.capacity
|
|
220
|
+
);
|
|
221
|
+
return first === previous.first &&
|
|
222
|
+
last === previous.last &&
|
|
223
|
+
capacity === previous.capacity
|
|
224
|
+
? previous
|
|
225
|
+
: { ...previous, first, last, capacity };
|
|
226
|
+
});
|
|
227
|
+
}}>
|
|
228
|
+
<NativePool>
|
|
229
|
+
{indices.map((index, slot) => {
|
|
230
|
+
const item = data[index];
|
|
231
|
+
const itemKey = itemKeys[index];
|
|
232
|
+
if (item === undefined || itemKey === undefined) {
|
|
233
|
+
throw new Error(`List.ForEach could not resolve the item at index ${index}.`);
|
|
234
|
+
}
|
|
235
|
+
return (
|
|
236
|
+
<RecycledRow
|
|
237
|
+
key={slot}
|
|
238
|
+
item={item}
|
|
239
|
+
index={index}
|
|
240
|
+
itemKey={itemKey}
|
|
241
|
+
revision={current.revision}
|
|
242
|
+
renderItem={renderItem}
|
|
243
|
+
/>
|
|
244
|
+
);
|
|
245
|
+
})}
|
|
246
|
+
</NativePool>
|
|
247
|
+
</NativeList>
|
|
248
|
+
);
|
|
249
|
+
}
|
|
@@ -2,6 +2,9 @@ import { requireNativeView } from 'expo';
|
|
|
2
2
|
|
|
3
3
|
import { type ViewEvent } from '../../types';
|
|
4
4
|
import { type CommonViewModifierProps } from '../types';
|
|
5
|
+
import { DataListForEach, NativeSlot, useItemKeys, type ListForEachProps } from './DataListForEach';
|
|
6
|
+
|
|
7
|
+
export { type ListForEachProps };
|
|
5
8
|
|
|
6
9
|
const ListForEachNativeView: React.ComponentType<NativeListForEachProps> =
|
|
7
10
|
requireNativeView<NativeListForEachProps>('ExpoUI', 'ListForEachView');
|
|
@@ -14,21 +17,29 @@ type NativeListForEachProps = CommonViewModifierProps &
|
|
|
14
17
|
DeleteEvent &
|
|
15
18
|
MoveEvent & {
|
|
16
19
|
children: React.ReactNode;
|
|
20
|
+
deleteEnabled: boolean;
|
|
21
|
+
moveEnabled: boolean;
|
|
17
22
|
};
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated Pass `data` and `keyExtractor`, and render each row from a `children` function.
|
|
26
|
+
*/
|
|
27
|
+
export interface ListForEachElementsProps extends CommonViewModifierProps {
|
|
28
|
+
data?: never;
|
|
29
|
+
keyExtractor?: never;
|
|
30
|
+
recycling?: never;
|
|
31
|
+
overscanCount?: never;
|
|
32
|
+
estimatedItemSize?: never;
|
|
20
33
|
/**
|
|
21
34
|
* The children elements to be rendered inside the `List.ForEach`.
|
|
22
35
|
*/
|
|
23
36
|
children: React.ReactNode;
|
|
24
|
-
|
|
25
37
|
/**
|
|
26
38
|
* Callback triggered when items are deleted.
|
|
27
39
|
* Receives an array of indices that were deleted.
|
|
28
40
|
* @see Official [SwiftUI documentation](https://developer.apple.com/documentation/swiftui/dynamicviewcontent/ondelete(perform:)).
|
|
29
41
|
*/
|
|
30
42
|
onDelete?: (indices: number[]) => void;
|
|
31
|
-
|
|
32
43
|
/**
|
|
33
44
|
* Callback triggered when items are moved.
|
|
34
45
|
* Receives the source indices and destination index.
|
|
@@ -37,14 +48,33 @@ export interface ListForEachProps extends CommonViewModifierProps {
|
|
|
37
48
|
onMove?: (sourceIndices: number[], destination: number) => void;
|
|
38
49
|
}
|
|
39
50
|
|
|
51
|
+
let warnedElements = false;
|
|
52
|
+
|
|
40
53
|
/**
|
|
41
|
-
* A
|
|
42
|
-
*
|
|
54
|
+
* A group of rows inside `List`, with optional deletion and reordering.
|
|
55
|
+
* Pass `data` with `keyExtractor`, and render each row from a `children` function.
|
|
56
|
+
* Recycles rows unless `recycling` is `false`.
|
|
43
57
|
*/
|
|
44
|
-
export function ListForEach(
|
|
58
|
+
export function ListForEach<ItemT>(props: ListForEachProps<ItemT> | ListForEachElementsProps) {
|
|
59
|
+
if (props.data === undefined) {
|
|
60
|
+
if (__DEV__ && !warnedElements) {
|
|
61
|
+
warnedElements = true;
|
|
62
|
+
console.warn(
|
|
63
|
+
'[@expo/ui] Passing elements as List.ForEach children is deprecated. Pass `data` and `keyExtractor`, and render each row from a `children` function: `{({ item }) => <Row item={item} />}`.'
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
return <ChildrenListForEach {...props} />;
|
|
67
|
+
}
|
|
68
|
+
const { recycling = true, ...rest } = props;
|
|
69
|
+
return recycling ? <DataListForEach {...rest} /> : <StaticListForEach {...rest} />;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function ChildrenListForEach({ children, onDelete, onMove, ...props }: ListForEachElementsProps) {
|
|
45
73
|
return (
|
|
46
74
|
<ListForEachNativeView
|
|
47
75
|
{...props}
|
|
76
|
+
deleteEnabled={!!onDelete}
|
|
77
|
+
moveEnabled={!!onMove}
|
|
48
78
|
onDelete={onDelete ? ({ nativeEvent }) => onDelete(nativeEvent.indices) : undefined}
|
|
49
79
|
onMove={
|
|
50
80
|
onMove
|
|
@@ -55,3 +85,23 @@ export function ListForEach({ children, onDelete, onMove, ...props }: ListForEac
|
|
|
55
85
|
</ListForEachNativeView>
|
|
56
86
|
);
|
|
57
87
|
}
|
|
88
|
+
|
|
89
|
+
function StaticListForEach<ItemT>({
|
|
90
|
+
data,
|
|
91
|
+
keyExtractor,
|
|
92
|
+
children: renderItem,
|
|
93
|
+
overscanCount: _overscanCount,
|
|
94
|
+
estimatedItemSize: _estimatedItemSize,
|
|
95
|
+
...props
|
|
96
|
+
}: Omit<ListForEachProps<ItemT>, 'recycling'>) {
|
|
97
|
+
const itemKeys = useItemKeys(data, keyExtractor);
|
|
98
|
+
return (
|
|
99
|
+
<ChildrenListForEach {...props}>
|
|
100
|
+
{data.map((item, index) => (
|
|
101
|
+
<NativeSlot key={itemKeys[index]} itemKey={itemKeys[index]!} index={index} revision={0}>
|
|
102
|
+
{renderItem({ item, index })}
|
|
103
|
+
</NativeSlot>
|
|
104
|
+
))}
|
|
105
|
+
</ChildrenListForEach>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
@@ -5,7 +5,7 @@ import { createViewModifierEventListener } from '../modifiers/utils';
|
|
|
5
5
|
import { type CommonViewModifierProps } from '../types';
|
|
6
6
|
import { ListForEach } from './ListForEach';
|
|
7
7
|
|
|
8
|
-
export { ListForEach, type ListForEachProps } from './ListForEach';
|
|
8
|
+
export { ListForEach, type ListForEachProps, type ListForEachElementsProps } from './ListForEach';
|
|
9
9
|
|
|
10
10
|
const ListNativeView: React.ComponentType<NativeListProps> = requireNativeView<NativeListProps>(
|
|
11
11
|
'ExpoUI',
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function getWindow(
|
|
2
|
+
count: number,
|
|
3
|
+
first: number,
|
|
4
|
+
last: number,
|
|
5
|
+
overscanCount: number,
|
|
6
|
+
minCapacity = 0
|
|
7
|
+
) {
|
|
8
|
+
if (count === 0) return { start: 0, capacity: 0 };
|
|
9
|
+
first = Math.max(0, Math.min(first, count - 1));
|
|
10
|
+
last = Math.max(first, Math.min(last, count - 1));
|
|
11
|
+
const start = Math.max(0, first - overscanCount);
|
|
12
|
+
const end = Math.min(count, last + 1 + overscanCount);
|
|
13
|
+
// Never shrink the pool: a stable capacity keeps `index % capacity` slot assignments stable.
|
|
14
|
+
// Grow it with headroom, because every growth re-renders the whole pool.
|
|
15
|
+
const needed = end - start;
|
|
16
|
+
let capacity = minCapacity;
|
|
17
|
+
if (needed > capacity) capacity = capacity === 0 ? needed : needed + overscanCount;
|
|
18
|
+
capacity = Math.min(count, capacity);
|
|
19
|
+
return { start: Math.min(start, count - capacity), capacity };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getSlotIndices(start: number, capacity: number): number[] {
|
|
23
|
+
if (capacity === 0) return [];
|
|
24
|
+
return Array.from(
|
|
25
|
+
{ length: capacity },
|
|
26
|
+
(_, slot) => start + ((slot - (start % capacity) + capacity) % capacity)
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -106,31 +106,67 @@ export const matchedGeometryEffect = (
|
|
|
106
106
|
*/
|
|
107
107
|
export const geometryGroup = () => createModifier('geometryGroup', {});
|
|
108
108
|
|
|
109
|
+
type FrameAlignment =
|
|
110
|
+
| 'center'
|
|
111
|
+
| 'leading'
|
|
112
|
+
| 'trailing'
|
|
113
|
+
| 'top'
|
|
114
|
+
| 'bottom'
|
|
115
|
+
| 'topLeading'
|
|
116
|
+
| 'topTrailing'
|
|
117
|
+
| 'bottomLeading'
|
|
118
|
+
| 'bottomTrailing';
|
|
119
|
+
|
|
109
120
|
/**
|
|
110
|
-
*
|
|
111
|
-
* @param params - The frame parameters
|
|
121
|
+
* Positions this view within an invisible frame with the specified size.
|
|
122
|
+
* @param params - The fixed frame parameters: `width`, `height` and `alignment`.
|
|
112
123
|
* @see Official [SwiftUI documentation](https://developer.apple.com/documentation/SwiftUI/View/frame(width:height:alignment:)).
|
|
113
124
|
*/
|
|
114
|
-
export
|
|
125
|
+
export function frame(params: {
|
|
115
126
|
width?: number;
|
|
116
127
|
height?: number;
|
|
128
|
+
alignment?: FrameAlignment;
|
|
129
|
+
}): ModifierConfig;
|
|
130
|
+
/**
|
|
131
|
+
* Positions this view within an invisible frame having the specified size constraints.
|
|
132
|
+
* @param params - The flexible frame parameters: `minWidth`, `idealWidth`, `maxWidth`, `minHeight`, `idealHeight`, `maxHeight` and `alignment`.
|
|
133
|
+
* @see Official [SwiftUI documentation](https://developer.apple.com/documentation/swiftui/view/frame(minwidth:idealwidth:maxwidth:minheight:idealheight:maxheight:alignment:)).
|
|
134
|
+
*/
|
|
135
|
+
export function frame(params: {
|
|
117
136
|
minWidth?: number;
|
|
137
|
+
idealWidth?: number;
|
|
118
138
|
maxWidth?: number;
|
|
119
139
|
minHeight?: number;
|
|
140
|
+
idealHeight?: number;
|
|
120
141
|
maxHeight?: number;
|
|
142
|
+
alignment?: FrameAlignment;
|
|
143
|
+
}): ModifierConfig;
|
|
144
|
+
export function frame(params: {
|
|
145
|
+
width?: number;
|
|
146
|
+
height?: number;
|
|
147
|
+
minWidth?: number;
|
|
121
148
|
idealWidth?: number;
|
|
149
|
+
maxWidth?: number;
|
|
150
|
+
minHeight?: number;
|
|
122
151
|
idealHeight?: number;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
152
|
+
maxHeight?: number;
|
|
153
|
+
alignment?: FrameAlignment;
|
|
154
|
+
}): ModifierConfig {
|
|
155
|
+
if (__DEV__) {
|
|
156
|
+
const { width, height, alignment: _alignment, ...flexible } = params;
|
|
157
|
+
const ignored = Object.keys(flexible).filter(
|
|
158
|
+
(key) => flexible[key as keyof typeof flexible] !== undefined
|
|
159
|
+
);
|
|
160
|
+
if ((width !== undefined || height !== undefined) && ignored.length > 0) {
|
|
161
|
+
console.warn(
|
|
162
|
+
`frame() ignores ${ignored.join(', ')} because width or height is also set. ` +
|
|
163
|
+
'SwiftUI applies fixed and flexible frames as separate modifiers. ' +
|
|
164
|
+
'Split the values into two calls, for example [frame({ height: 50 }), frame({ maxWidth: Infinity })].'
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return createModifier('frame', params);
|
|
169
|
+
}
|
|
134
170
|
|
|
135
171
|
/**
|
|
136
172
|
* Positions this view within an invisible frame with a size relative to the nearest container.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
feafc8819618513e9a38001814fc14e2
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
749807825339b7f72362b37e830ea704ec60f72d
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
c42bba76435f8b36b4fc0ed86a8290f9e1ccaa3a0ebe4cb6e77d029a4be92be6
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
d105c1535934d743de599730ba9b0501a424eece52f1a4190b3764b4e7e280be42e3c9b880e4f80bef8ab6299938a0da275c00d342c593fd54375574d0ecd3ae
|
|
Binary file
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.aar.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
317b952ccecb056bea4a1e5b20b7b5bf
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.aar.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
77a2cb3cfd3195ad299b84c7d844dcb10d52fbe9
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.aar.sha256
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
7576f0fb76c81d2a1925ffa93e4175b8ab41c4c47a7c4c375b73707812438133
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.aar.sha512
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
408cceb3d6f97d29c6e734ab578c86c5c2c3f65fba19170bf1edc1f30648e6906b3a0e2284f1721543450bb579ddf37e54b00a51d21f9e5d77ad82e0857fef02
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.module.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
6f395b4604efe8cb782c2d07ed0a034f
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.module.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
a5735cfc927a4a919d056a8d002778b3b03a9571
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.module.sha256
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
6ac59cdec02bfaab3cc9a0201b3f3efc2472ebdae06731eb1754f50be6adeb56
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.module.sha512
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
dd59787b0055dc18c4dae85147258bdbce099df415a74de7bd47a403b17d9138fdffbf7351e383761e9bea7c3c7aa72ed062784da242edfa312a4d8a4703e4dd
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.pom.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
7d3bc2e18bfdc6ff7dde3b9952e57b0d
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.pom.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
686f495f389f5d58061c48dd2be09c59dff6d282
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.pom.sha256
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ed17ef29d2de582e5dd219506d2f5c6a83ae6b9499877a208b82c4642389afab
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.4/expo.modules.ui-58.0.4.pom.sha512
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ec8c0d91c6f8c40ced69d655e02868faa9945e2417cd82852b5455e3ddec9a1a23b14093fbb0e07093570af8823812af20ad0a61d84c035ae88fb093d0aee7fd
|