@xaui/native 0.0.19 → 0.0.21
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/dist/input/index.cjs +1321 -0
- package/dist/input/index.d.cts +492 -0
- package/dist/input/index.d.ts +492 -0
- package/dist/input/index.js +1254 -0
- package/dist/list/index.cjs +470 -0
- package/dist/list/index.d.cts +188 -0
- package/dist/list/index.d.ts +188 -0
- package/dist/list/index.js +395 -0
- package/package.json +11 -1
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import * as react_native from 'react-native';
|
|
3
|
+
import { ViewStyle, TextStyle, GestureResponderEvent } from 'react-native';
|
|
4
|
+
import { T as ThemeColor, S as Size } from '../index-BOw6tbkc.js';
|
|
5
|
+
|
|
6
|
+
type ListSelectionMode = 'single' | 'multiple' | 'none';
|
|
7
|
+
type ListItemCustomAppearance = {
|
|
8
|
+
/**
|
|
9
|
+
* Custom styles for the item container
|
|
10
|
+
*/
|
|
11
|
+
container?: ViewStyle;
|
|
12
|
+
/**
|
|
13
|
+
* Custom styles for the content container
|
|
14
|
+
*/
|
|
15
|
+
content?: ViewStyle;
|
|
16
|
+
/**
|
|
17
|
+
* Custom styles for the title text
|
|
18
|
+
*/
|
|
19
|
+
title?: TextStyle;
|
|
20
|
+
/**
|
|
21
|
+
* Custom styles for the description text
|
|
22
|
+
*/
|
|
23
|
+
description?: TextStyle;
|
|
24
|
+
};
|
|
25
|
+
type ListItemProps = {
|
|
26
|
+
/**
|
|
27
|
+
* Unique key for the item (used for selection)
|
|
28
|
+
*/
|
|
29
|
+
itemKey: string;
|
|
30
|
+
/**
|
|
31
|
+
* Title text for the ListItem
|
|
32
|
+
*/
|
|
33
|
+
title: ReactNode;
|
|
34
|
+
/**
|
|
35
|
+
* Optional description text
|
|
36
|
+
*/
|
|
37
|
+
description?: ReactNode;
|
|
38
|
+
/**
|
|
39
|
+
* Content to display at the start of the item
|
|
40
|
+
*/
|
|
41
|
+
startContent?: ReactNode;
|
|
42
|
+
/**
|
|
43
|
+
* Content to display at the end of the item
|
|
44
|
+
*/
|
|
45
|
+
endContent?: ReactNode;
|
|
46
|
+
/**
|
|
47
|
+
* Whether the item is disabled
|
|
48
|
+
* @default false
|
|
49
|
+
*/
|
|
50
|
+
isDisabled?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Whether the item is selected
|
|
53
|
+
* @default false
|
|
54
|
+
*/
|
|
55
|
+
isSelected?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Custom appearance styles for item parts
|
|
58
|
+
*/
|
|
59
|
+
customAppearance?: ListItemCustomAppearance;
|
|
60
|
+
/**
|
|
61
|
+
* Callback fired when the item is pressed
|
|
62
|
+
*/
|
|
63
|
+
onPress?: (event: GestureResponderEvent) => void;
|
|
64
|
+
};
|
|
65
|
+
type ListProps = {
|
|
66
|
+
/**
|
|
67
|
+
* List items
|
|
68
|
+
*/
|
|
69
|
+
children: ReactNode;
|
|
70
|
+
/**
|
|
71
|
+
* Selection mode for the list
|
|
72
|
+
* @default 'none'
|
|
73
|
+
*/
|
|
74
|
+
selectionMode?: ListSelectionMode;
|
|
75
|
+
/**
|
|
76
|
+
* Controlled selected keys
|
|
77
|
+
*/
|
|
78
|
+
selectedKeys?: string[];
|
|
79
|
+
/**
|
|
80
|
+
* Default selected keys (uncontrolled)
|
|
81
|
+
*/
|
|
82
|
+
defaultSelectedKeys?: string[];
|
|
83
|
+
/**
|
|
84
|
+
* Whether to show dividers between items
|
|
85
|
+
* @default false
|
|
86
|
+
*/
|
|
87
|
+
showDivider?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Whether items are pressable
|
|
90
|
+
* @default true
|
|
91
|
+
*/
|
|
92
|
+
isPressable?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Whether items are selectable
|
|
95
|
+
* @default false
|
|
96
|
+
*/
|
|
97
|
+
isSelectable?: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Theme color for selected items
|
|
100
|
+
* @default 'primary'
|
|
101
|
+
*/
|
|
102
|
+
themeColor?: ThemeColor;
|
|
103
|
+
/**
|
|
104
|
+
* Size of the list items
|
|
105
|
+
* @default 'md'
|
|
106
|
+
*/
|
|
107
|
+
size?: Size;
|
|
108
|
+
/**
|
|
109
|
+
* Callback fired when selection changes
|
|
110
|
+
*/
|
|
111
|
+
onSelectionChange?: (keys: string[]) => void;
|
|
112
|
+
/**
|
|
113
|
+
* Custom styles for the list container
|
|
114
|
+
*/
|
|
115
|
+
style?: ViewStyle;
|
|
116
|
+
};
|
|
117
|
+
type ListBuilderProps<T> = {
|
|
118
|
+
/**
|
|
119
|
+
* Data array to render
|
|
120
|
+
*/
|
|
121
|
+
data: T[];
|
|
122
|
+
/**
|
|
123
|
+
* Function to extract unique key from item
|
|
124
|
+
*/
|
|
125
|
+
keyExtractor: (item: T, index: number) => string;
|
|
126
|
+
/**
|
|
127
|
+
* Function to render each item
|
|
128
|
+
*/
|
|
129
|
+
renderItem: (item: T, index: number) => ReactNode;
|
|
130
|
+
/**
|
|
131
|
+
* Selection mode for the list
|
|
132
|
+
* @default 'none'
|
|
133
|
+
*/
|
|
134
|
+
selectionMode?: ListSelectionMode;
|
|
135
|
+
/**
|
|
136
|
+
* Controlled selected keys
|
|
137
|
+
*/
|
|
138
|
+
selectedKeys?: string[];
|
|
139
|
+
/**
|
|
140
|
+
* Default selected keys (uncontrolled)
|
|
141
|
+
*/
|
|
142
|
+
defaultSelectedKeys?: string[];
|
|
143
|
+
/**
|
|
144
|
+
* Whether to show dividers between items
|
|
145
|
+
* @default false
|
|
146
|
+
*/
|
|
147
|
+
showDivider?: boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Whether items are pressable
|
|
150
|
+
* @default true
|
|
151
|
+
*/
|
|
152
|
+
isPressable?: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Whether items are selectable
|
|
155
|
+
* @default false
|
|
156
|
+
*/
|
|
157
|
+
isSelectable?: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Theme color for selected items
|
|
160
|
+
* @default 'primary'
|
|
161
|
+
*/
|
|
162
|
+
themeColor?: ThemeColor;
|
|
163
|
+
/**
|
|
164
|
+
* Size of the list items
|
|
165
|
+
* @default 'md'
|
|
166
|
+
*/
|
|
167
|
+
size?: Size;
|
|
168
|
+
/**
|
|
169
|
+
* Callback fired when selection changes
|
|
170
|
+
*/
|
|
171
|
+
onSelectionChange?: (keys: string[]) => void;
|
|
172
|
+
/**
|
|
173
|
+
* Custom styles for the list container
|
|
174
|
+
*/
|
|
175
|
+
style?: ViewStyle;
|
|
176
|
+
/**
|
|
177
|
+
* FlatList props to pass through
|
|
178
|
+
*/
|
|
179
|
+
flatListProps?: Omit<React.ComponentProps<typeof react_native.FlatList<T>>, 'data' | 'renderItem' | 'keyExtractor'>;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
declare const List: React.FC<ListProps>;
|
|
183
|
+
|
|
184
|
+
declare const ListItem: React.FC<ListItemProps>;
|
|
185
|
+
|
|
186
|
+
declare function ListBuilder<T>({ data, keyExtractor, renderItem, selectionMode, selectedKeys: controlledSelectedKeys, defaultSelectedKeys, showDivider, isPressable, isSelectable, themeColor, size, onSelectionChange, style, flatListProps, }: ListBuilderProps<T>): React.JSX.Element;
|
|
187
|
+
|
|
188
|
+
export { List, ListBuilder, type ListBuilderProps, ListItem, type ListItemCustomAppearance, type ListItemProps, type ListProps, type ListSelectionMode };
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import "../chunk-DXXNBF5P.js";
|
|
2
|
+
import {
|
|
3
|
+
useXUITheme
|
|
4
|
+
} from "../chunk-LTKYHG5V.js";
|
|
5
|
+
|
|
6
|
+
// src/components/list/list.tsx
|
|
7
|
+
import React2, { useCallback, useMemo, useState } from "react";
|
|
8
|
+
import { View as View2 } from "react-native";
|
|
9
|
+
|
|
10
|
+
// src/components/list/list-context.ts
|
|
11
|
+
import { createContext, useContext } from "react";
|
|
12
|
+
var ListContext = createContext(null);
|
|
13
|
+
|
|
14
|
+
// src/components/list/list.style.ts
|
|
15
|
+
import { StyleSheet } from "react-native";
|
|
16
|
+
var styles = StyleSheet.create({
|
|
17
|
+
list: {
|
|
18
|
+
flex: 1
|
|
19
|
+
},
|
|
20
|
+
item: {
|
|
21
|
+
flexDirection: "row",
|
|
22
|
+
alignItems: "center",
|
|
23
|
+
gap: 12
|
|
24
|
+
},
|
|
25
|
+
content: {
|
|
26
|
+
flex: 1,
|
|
27
|
+
gap: 2
|
|
28
|
+
},
|
|
29
|
+
title: {
|
|
30
|
+
fontWeight: "500"
|
|
31
|
+
},
|
|
32
|
+
description: {
|
|
33
|
+
opacity: 0.7
|
|
34
|
+
},
|
|
35
|
+
disabled: {
|
|
36
|
+
opacity: 0.5
|
|
37
|
+
},
|
|
38
|
+
divider: {
|
|
39
|
+
height: 1,
|
|
40
|
+
marginLeft: 10
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// src/components/list/list-divider.tsx
|
|
45
|
+
import React, { Children } from "react";
|
|
46
|
+
import { View } from "react-native";
|
|
47
|
+
var ListDivider = () => {
|
|
48
|
+
const theme = useXUITheme();
|
|
49
|
+
return /* @__PURE__ */ React.createElement(
|
|
50
|
+
View,
|
|
51
|
+
{
|
|
52
|
+
style: [styles.divider, { backgroundColor: theme.colors.foreground + "30" }]
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
var ListChildren = ({ children, showDivider }) => {
|
|
57
|
+
if (!showDivider) {
|
|
58
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
|
|
59
|
+
}
|
|
60
|
+
const childArray = Children.toArray(children);
|
|
61
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, childArray.map((child, index) => /* @__PURE__ */ React.createElement(React.Fragment, { key: index }, child, index < childArray.length - 1 && /* @__PURE__ */ React.createElement(ListDivider, null))));
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// src/components/list/list.tsx
|
|
65
|
+
var List = ({
|
|
66
|
+
children,
|
|
67
|
+
selectionMode = "none",
|
|
68
|
+
selectedKeys: controlledSelectedKeys,
|
|
69
|
+
defaultSelectedKeys = [],
|
|
70
|
+
showDivider = false,
|
|
71
|
+
isPressable = true,
|
|
72
|
+
isSelectable = false,
|
|
73
|
+
themeColor = "primary",
|
|
74
|
+
size = "md",
|
|
75
|
+
onSelectionChange,
|
|
76
|
+
style
|
|
77
|
+
}) => {
|
|
78
|
+
const isControlled = controlledSelectedKeys !== void 0;
|
|
79
|
+
const [internalSelectedKeys, setInternalSelectedKeys] = useState(defaultSelectedKeys);
|
|
80
|
+
const selectedKeys = isControlled ? controlledSelectedKeys : internalSelectedKeys;
|
|
81
|
+
const isSelected = useCallback(
|
|
82
|
+
(key) => {
|
|
83
|
+
return selectedKeys.includes(key);
|
|
84
|
+
},
|
|
85
|
+
[selectedKeys]
|
|
86
|
+
);
|
|
87
|
+
const toggleSelection = useCallback(
|
|
88
|
+
(key) => {
|
|
89
|
+
if (selectionMode === "none" || !isSelectable) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
let newSelectedKeys;
|
|
93
|
+
if (selectionMode === "single") {
|
|
94
|
+
newSelectedKeys = isSelected(key) ? [] : [key];
|
|
95
|
+
} else {
|
|
96
|
+
newSelectedKeys = isSelected(key) ? selectedKeys.filter((k) => k !== key) : [...selectedKeys, key];
|
|
97
|
+
}
|
|
98
|
+
if (!isControlled) {
|
|
99
|
+
setInternalSelectedKeys(newSelectedKeys);
|
|
100
|
+
}
|
|
101
|
+
onSelectionChange?.(newSelectedKeys);
|
|
102
|
+
},
|
|
103
|
+
[
|
|
104
|
+
selectionMode,
|
|
105
|
+
isSelectable,
|
|
106
|
+
isSelected,
|
|
107
|
+
selectedKeys,
|
|
108
|
+
isControlled,
|
|
109
|
+
onSelectionChange
|
|
110
|
+
]
|
|
111
|
+
);
|
|
112
|
+
const contextValue = useMemo(
|
|
113
|
+
() => ({
|
|
114
|
+
selectionMode,
|
|
115
|
+
selectedKeys,
|
|
116
|
+
isPressable,
|
|
117
|
+
isSelectable,
|
|
118
|
+
themeColor,
|
|
119
|
+
size,
|
|
120
|
+
showDivider,
|
|
121
|
+
toggleSelection,
|
|
122
|
+
isSelected
|
|
123
|
+
}),
|
|
124
|
+
[
|
|
125
|
+
selectionMode,
|
|
126
|
+
selectedKeys,
|
|
127
|
+
isPressable,
|
|
128
|
+
isSelectable,
|
|
129
|
+
themeColor,
|
|
130
|
+
size,
|
|
131
|
+
showDivider,
|
|
132
|
+
toggleSelection,
|
|
133
|
+
isSelected
|
|
134
|
+
]
|
|
135
|
+
);
|
|
136
|
+
return /* @__PURE__ */ React2.createElement(ListContext.Provider, { value: contextValue }, /* @__PURE__ */ React2.createElement(View2, { style: [styles.list, style] }, /* @__PURE__ */ React2.createElement(ListChildren, { showDivider }, children)));
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// src/components/list/list-item.tsx
|
|
140
|
+
import React3, { useContext as useContext2 } from "react";
|
|
141
|
+
import { Pressable, Text, View as View3 } from "react-native";
|
|
142
|
+
|
|
143
|
+
// src/components/list/list.hook.ts
|
|
144
|
+
import { useMemo as useMemo2 } from "react";
|
|
145
|
+
var useListItemSizeStyles = (size) => {
|
|
146
|
+
const theme = useXUITheme();
|
|
147
|
+
return useMemo2(() => {
|
|
148
|
+
const sizes = {
|
|
149
|
+
xs: {
|
|
150
|
+
paddingVertical: theme.spacing.sm,
|
|
151
|
+
paddingHorizontal: theme.spacing.sm,
|
|
152
|
+
titleSize: theme.fontSizes.xs,
|
|
153
|
+
descriptionSize: theme.fontSizes.xs
|
|
154
|
+
},
|
|
155
|
+
sm: {
|
|
156
|
+
paddingVertical: theme.spacing.sm,
|
|
157
|
+
paddingHorizontal: theme.spacing.md,
|
|
158
|
+
titleSize: theme.fontSizes.sm,
|
|
159
|
+
descriptionSize: theme.fontSizes.xs
|
|
160
|
+
},
|
|
161
|
+
md: {
|
|
162
|
+
paddingVertical: theme.spacing.md,
|
|
163
|
+
paddingHorizontal: theme.spacing.md,
|
|
164
|
+
titleSize: theme.fontSizes.md,
|
|
165
|
+
descriptionSize: theme.fontSizes.sm
|
|
166
|
+
},
|
|
167
|
+
lg: {
|
|
168
|
+
paddingVertical: theme.spacing.lg,
|
|
169
|
+
paddingHorizontal: theme.spacing.lg,
|
|
170
|
+
titleSize: theme.fontSizes.lg,
|
|
171
|
+
descriptionSize: theme.fontSizes.md
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
return sizes[size];
|
|
175
|
+
}, [size, theme]);
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/components/list/list-item.tsx
|
|
179
|
+
import { getSafeThemeColor } from "@xaui/core";
|
|
180
|
+
var ListItem = ({
|
|
181
|
+
itemKey,
|
|
182
|
+
title,
|
|
183
|
+
description,
|
|
184
|
+
startContent,
|
|
185
|
+
endContent,
|
|
186
|
+
isDisabled = false,
|
|
187
|
+
isSelected: propIsSelected,
|
|
188
|
+
customAppearance,
|
|
189
|
+
onPress
|
|
190
|
+
}) => {
|
|
191
|
+
const context = useContext2(ListContext);
|
|
192
|
+
const theme = useXUITheme();
|
|
193
|
+
const selectionMode = context?.selectionMode ?? "none";
|
|
194
|
+
const isPressable = context?.isPressable ?? true;
|
|
195
|
+
const isSelectable = context?.isSelectable ?? false;
|
|
196
|
+
const themeColor = context?.themeColor ?? "primary";
|
|
197
|
+
const size = context?.size ?? "md";
|
|
198
|
+
const isSelected = propIsSelected ?? (context ? context.isSelected(itemKey) : false);
|
|
199
|
+
const sizeStyles = useListItemSizeStyles(size);
|
|
200
|
+
const safeThemeColor = getSafeThemeColor(themeColor);
|
|
201
|
+
const colorScheme = theme.colors[safeThemeColor];
|
|
202
|
+
const backgroundColor = isSelected ? colorScheme.background : "transparent";
|
|
203
|
+
const titleColor = isDisabled ? theme.colors.foreground + "50" : theme.colors.foreground;
|
|
204
|
+
const descriptionColor = isDisabled ? theme.colors.foreground + "50" : theme.colors.foreground + "99";
|
|
205
|
+
const handlePress = () => {
|
|
206
|
+
if (isDisabled) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (isSelectable && selectionMode !== "none") {
|
|
210
|
+
context?.toggleSelection(itemKey);
|
|
211
|
+
}
|
|
212
|
+
onPress?.({});
|
|
213
|
+
};
|
|
214
|
+
const renderTitle = () => {
|
|
215
|
+
if (typeof title === "string" || typeof title === "number") {
|
|
216
|
+
return /* @__PURE__ */ React3.createElement(
|
|
217
|
+
Text,
|
|
218
|
+
{
|
|
219
|
+
style: [
|
|
220
|
+
styles.title,
|
|
221
|
+
{ fontSize: sizeStyles.titleSize, color: titleColor },
|
|
222
|
+
customAppearance?.title
|
|
223
|
+
],
|
|
224
|
+
numberOfLines: 1
|
|
225
|
+
},
|
|
226
|
+
title
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
return title;
|
|
230
|
+
};
|
|
231
|
+
const renderDescription = () => {
|
|
232
|
+
if (!description) return null;
|
|
233
|
+
if (typeof description === "string" || typeof description === "number") {
|
|
234
|
+
return /* @__PURE__ */ React3.createElement(
|
|
235
|
+
Text,
|
|
236
|
+
{
|
|
237
|
+
style: [
|
|
238
|
+
styles.description,
|
|
239
|
+
{ fontSize: sizeStyles.descriptionSize, color: descriptionColor },
|
|
240
|
+
customAppearance?.description
|
|
241
|
+
],
|
|
242
|
+
numberOfLines: 2
|
|
243
|
+
},
|
|
244
|
+
description
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
return description;
|
|
248
|
+
};
|
|
249
|
+
const content = /* @__PURE__ */ React3.createElement(
|
|
250
|
+
View3,
|
|
251
|
+
{
|
|
252
|
+
style: [
|
|
253
|
+
styles.item,
|
|
254
|
+
{
|
|
255
|
+
paddingVertical: sizeStyles.paddingVertical,
|
|
256
|
+
paddingHorizontal: sizeStyles.paddingHorizontal,
|
|
257
|
+
backgroundColor
|
|
258
|
+
},
|
|
259
|
+
isDisabled && styles.disabled,
|
|
260
|
+
customAppearance?.container
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
startContent && /* @__PURE__ */ React3.createElement(View3, { style: customAppearance?.content }, startContent),
|
|
264
|
+
/* @__PURE__ */ React3.createElement(View3, { style: [styles.content, customAppearance?.content] }, renderTitle(), renderDescription()),
|
|
265
|
+
endContent && /* @__PURE__ */ React3.createElement(View3, { style: customAppearance?.content }, endContent)
|
|
266
|
+
);
|
|
267
|
+
if (!isPressable) {
|
|
268
|
+
return content;
|
|
269
|
+
}
|
|
270
|
+
return /* @__PURE__ */ React3.createElement(
|
|
271
|
+
Pressable,
|
|
272
|
+
{
|
|
273
|
+
onPress: handlePress,
|
|
274
|
+
disabled: isDisabled,
|
|
275
|
+
style: ({ pressed }) => [
|
|
276
|
+
pressed && !isDisabled && {
|
|
277
|
+
backgroundColor: theme.colors.foreground + "10"
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
},
|
|
281
|
+
content
|
|
282
|
+
);
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// src/components/list/list-builder.tsx
|
|
286
|
+
import React4, { useCallback as useCallback2, useMemo as useMemo3, useState as useState2 } from "react";
|
|
287
|
+
import { FlatList, View as View4 } from "react-native";
|
|
288
|
+
function ListBuilder({
|
|
289
|
+
data,
|
|
290
|
+
keyExtractor,
|
|
291
|
+
renderItem,
|
|
292
|
+
selectionMode = "none",
|
|
293
|
+
selectedKeys: controlledSelectedKeys,
|
|
294
|
+
defaultSelectedKeys = [],
|
|
295
|
+
showDivider = false,
|
|
296
|
+
isPressable = true,
|
|
297
|
+
isSelectable = false,
|
|
298
|
+
themeColor = "primary",
|
|
299
|
+
size = "md",
|
|
300
|
+
onSelectionChange,
|
|
301
|
+
style,
|
|
302
|
+
flatListProps
|
|
303
|
+
}) {
|
|
304
|
+
const theme = useXUITheme();
|
|
305
|
+
const isControlled = controlledSelectedKeys !== void 0;
|
|
306
|
+
const [internalSelectedKeys, setInternalSelectedKeys] = useState2(defaultSelectedKeys);
|
|
307
|
+
const selectedKeys = isControlled ? controlledSelectedKeys : internalSelectedKeys;
|
|
308
|
+
const isSelected = useCallback2(
|
|
309
|
+
(key) => {
|
|
310
|
+
return selectedKeys.includes(key);
|
|
311
|
+
},
|
|
312
|
+
[selectedKeys]
|
|
313
|
+
);
|
|
314
|
+
const toggleSelection = useCallback2(
|
|
315
|
+
(key) => {
|
|
316
|
+
if (selectionMode === "none" || !isSelectable) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
let newSelectedKeys;
|
|
320
|
+
if (selectionMode === "single") {
|
|
321
|
+
newSelectedKeys = isSelected(key) ? [] : [key];
|
|
322
|
+
} else {
|
|
323
|
+
newSelectedKeys = isSelected(key) ? selectedKeys.filter((k) => k !== key) : [...selectedKeys, key];
|
|
324
|
+
}
|
|
325
|
+
if (!isControlled) {
|
|
326
|
+
setInternalSelectedKeys(newSelectedKeys);
|
|
327
|
+
}
|
|
328
|
+
onSelectionChange?.(newSelectedKeys);
|
|
329
|
+
},
|
|
330
|
+
[
|
|
331
|
+
selectionMode,
|
|
332
|
+
isSelectable,
|
|
333
|
+
isSelected,
|
|
334
|
+
selectedKeys,
|
|
335
|
+
isControlled,
|
|
336
|
+
onSelectionChange
|
|
337
|
+
]
|
|
338
|
+
);
|
|
339
|
+
const contextValue = useMemo3(
|
|
340
|
+
() => ({
|
|
341
|
+
selectionMode,
|
|
342
|
+
selectedKeys,
|
|
343
|
+
isPressable,
|
|
344
|
+
isSelectable,
|
|
345
|
+
themeColor,
|
|
346
|
+
size,
|
|
347
|
+
showDivider,
|
|
348
|
+
toggleSelection,
|
|
349
|
+
isSelected
|
|
350
|
+
}),
|
|
351
|
+
[
|
|
352
|
+
selectionMode,
|
|
353
|
+
selectedKeys,
|
|
354
|
+
isPressable,
|
|
355
|
+
isSelectable,
|
|
356
|
+
themeColor,
|
|
357
|
+
size,
|
|
358
|
+
showDivider,
|
|
359
|
+
toggleSelection,
|
|
360
|
+
isSelected
|
|
361
|
+
]
|
|
362
|
+
);
|
|
363
|
+
const renderListItem = useCallback2(
|
|
364
|
+
(item, index) => {
|
|
365
|
+
const element = renderItem(item, index);
|
|
366
|
+
if (!showDivider || index === data.length - 1) {
|
|
367
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: keyExtractor(item, index) }, element);
|
|
368
|
+
}
|
|
369
|
+
return /* @__PURE__ */ React4.createElement(View4, { key: keyExtractor(item, index) }, element, /* @__PURE__ */ React4.createElement(
|
|
370
|
+
View4,
|
|
371
|
+
{
|
|
372
|
+
style: [
|
|
373
|
+
styles.divider,
|
|
374
|
+
{ backgroundColor: theme.colors.foreground + "15" }
|
|
375
|
+
]
|
|
376
|
+
}
|
|
377
|
+
));
|
|
378
|
+
},
|
|
379
|
+
[data.length, keyExtractor, renderItem, showDivider, theme.colors.foreground]
|
|
380
|
+
);
|
|
381
|
+
return /* @__PURE__ */ React4.createElement(ListContext.Provider, { value: contextValue }, /* @__PURE__ */ React4.createElement(View4, { style: [styles.list, style] }, /* @__PURE__ */ React4.createElement(
|
|
382
|
+
FlatList,
|
|
383
|
+
{
|
|
384
|
+
data,
|
|
385
|
+
keyExtractor,
|
|
386
|
+
renderItem: ({ item, index }) => renderListItem(item, index),
|
|
387
|
+
...flatListProps
|
|
388
|
+
}
|
|
389
|
+
)));
|
|
390
|
+
}
|
|
391
|
+
export {
|
|
392
|
+
List,
|
|
393
|
+
ListBuilder,
|
|
394
|
+
ListItem
|
|
395
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xaui/native",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"description": "Flutter-inspired React Native UI components with native animations powered by React Native Reanimated",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -146,6 +146,16 @@
|
|
|
146
146
|
"types": "./dist/card/index.d.ts",
|
|
147
147
|
"import": "./dist/card/index.js",
|
|
148
148
|
"require": "./dist/card/index.js"
|
|
149
|
+
},
|
|
150
|
+
"./input": {
|
|
151
|
+
"types": "./dist/input/index.d.ts",
|
|
152
|
+
"import": "./dist/input/index.js",
|
|
153
|
+
"require": "./dist/input/index.js"
|
|
154
|
+
},
|
|
155
|
+
"./list": {
|
|
156
|
+
"types": "./dist/list/index.d.ts",
|
|
157
|
+
"import": "./dist/list/index.js",
|
|
158
|
+
"require": "./dist/list/index.js"
|
|
149
159
|
}
|
|
150
160
|
},
|
|
151
161
|
"files": [
|