@vellira-ui/react-native 2.58.0 → 2.59.0
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/index.d.ts +1 -1
- package/dist/index.js +703 -451
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Children, cloneElement, createContext, forwardRef, isValidElement, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
1
|
+
import { Children, cloneElement, createContext, forwardRef, isValidElement, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
2
2
|
import { Check, ChevronDown, Close, Search } from "@vellira-ui/icons";
|
|
3
3
|
import { AccessibilityInfo, ActivityIndicator, Animated, BackHandler, Dimensions, Easing, FlatList, Modal as Modal$1, Platform, Pressable, ScrollView, StyleSheet, Text, TextInput, View, findNodeHandle, useWindowDimensions } from "react-native";
|
|
4
|
-
import { createConsoleOverlayDiagnostics, createOverlayZIndexPolicy,
|
|
4
|
+
import { createConsoleOverlayDiagnostics, createOverlayManagerStore, createOverlayZIndexPolicy, createRetainedResourceRegistry, deferOverlayFocusRestore, getCompoundSlot, markCompoundSlot, resolveOverlayPresentation } from "@vellira-ui/core";
|
|
5
5
|
import { darkTheme, highContrastTheme, lightTheme } from "@vellira-ui/tokens";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
//#region src/theme/fontWeight.ts
|
|
@@ -31,38 +31,54 @@ const nativeOverlayZIndexPolicy = createOverlayZIndexPolicy({
|
|
|
31
31
|
});
|
|
32
32
|
const nativeOverlayDiagnostics = createConsoleOverlayDiagnostics("NativeOverlayManager");
|
|
33
33
|
const createNativeOverlayManager = () => {
|
|
34
|
-
|
|
34
|
+
const store = createOverlayManagerStore({
|
|
35
|
+
diagnostics: nativeOverlayDiagnostics,
|
|
36
|
+
policy: nativeOverlayZIndexPolicy
|
|
37
|
+
});
|
|
35
38
|
const dismissHandlers = /* @__PURE__ */ new Map();
|
|
36
39
|
const outsidePressHandlers = /* @__PURE__ */ new Map();
|
|
40
|
+
const toNativeEntry = (id) => ({
|
|
41
|
+
id,
|
|
42
|
+
zIndex: store.getZIndex(id) ?? nativeOverlayZIndexPolicy.levels.modal
|
|
43
|
+
});
|
|
44
|
+
let cachedStoreSnapshot;
|
|
45
|
+
let cachedNativeSnapshot;
|
|
46
|
+
const getNativeSnapshot = () => {
|
|
47
|
+
const snapshot = store.getSnapshot();
|
|
48
|
+
if (cachedStoreSnapshot === snapshot && cachedNativeSnapshot) return cachedNativeSnapshot;
|
|
49
|
+
const stack = snapshot.stack.map((entry) => toNativeEntry(entry.id));
|
|
50
|
+
cachedStoreSnapshot = snapshot;
|
|
51
|
+
cachedNativeSnapshot = {
|
|
52
|
+
registry: new Map(stack.map((entry) => [entry.id, entry])),
|
|
53
|
+
stack,
|
|
54
|
+
topmost: snapshot.topmost ? toNativeEntry(snapshot.topmost.id) : void 0
|
|
55
|
+
};
|
|
56
|
+
return cachedNativeSnapshot;
|
|
57
|
+
};
|
|
37
58
|
return {
|
|
38
59
|
register(id) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const entry = {
|
|
42
|
-
id,
|
|
43
|
-
zIndex: resolveOverlayZIndex({
|
|
44
|
-
level: nativeOverlayZIndexPolicy.defaultLevel,
|
|
45
|
-
order: stack.length,
|
|
46
|
-
policy: nativeOverlayZIndexPolicy
|
|
47
|
-
})
|
|
48
|
-
};
|
|
49
|
-
stack.push(entry);
|
|
50
|
-
return entry;
|
|
60
|
+
const entry = store.register({ id });
|
|
61
|
+
return toNativeEntry(entry.id);
|
|
51
62
|
},
|
|
52
63
|
unregister(id) {
|
|
53
|
-
if (!stack.some((item) => item.id === id)) nativeOverlayDiagnostics.unknownUnregister?.(id);
|
|
54
64
|
dismissHandlers.delete(id);
|
|
55
65
|
outsidePressHandlers.delete(id);
|
|
56
|
-
|
|
66
|
+
store.unregister(id);
|
|
67
|
+
},
|
|
68
|
+
getSnapshot() {
|
|
69
|
+
return getNativeSnapshot();
|
|
57
70
|
},
|
|
58
71
|
isTop(id) {
|
|
59
|
-
return
|
|
72
|
+
return store.isTopmost(id);
|
|
60
73
|
},
|
|
61
74
|
getTop() {
|
|
62
|
-
return
|
|
75
|
+
return getNativeSnapshot().topmost;
|
|
63
76
|
},
|
|
64
77
|
getZIndex(id) {
|
|
65
|
-
return
|
|
78
|
+
return store.getZIndex(id) ?? nativeOverlayZIndexPolicy.levels[nativeOverlayZIndexPolicy.defaultLevel];
|
|
79
|
+
},
|
|
80
|
+
subscribe(listener) {
|
|
81
|
+
return store.subscribe(listener);
|
|
66
82
|
},
|
|
67
83
|
registerDismissHandler(id, handler) {
|
|
68
84
|
dismissHandlers.set(id, handler);
|
|
@@ -93,9 +109,9 @@ const createNativeOverlayManager = () => {
|
|
|
93
109
|
return handler();
|
|
94
110
|
},
|
|
95
111
|
clear() {
|
|
96
|
-
stack = [];
|
|
97
112
|
dismissHandlers.clear();
|
|
98
113
|
outsidePressHandlers.clear();
|
|
114
|
+
store.clear();
|
|
99
115
|
}
|
|
100
116
|
};
|
|
101
117
|
};
|
|
@@ -108,11 +124,10 @@ const useNativeOverlayManager = () => useContext(NativeOverlayManagerContext) ??
|
|
|
108
124
|
//#region src/hooks/behavior/overlay/useOverlayRegistration.ts
|
|
109
125
|
const useOverlayRegistration = ({ active, id }) => {
|
|
110
126
|
const nativeOverlayManager = useNativeOverlayManager();
|
|
111
|
-
const
|
|
127
|
+
const snapshot = useSyncExternalStore(nativeOverlayManager.subscribe, nativeOverlayManager.getSnapshot, nativeOverlayManager.getSnapshot);
|
|
112
128
|
useEffect(() => {
|
|
113
129
|
if (!active) return;
|
|
114
|
-
|
|
115
|
-
setZIndex(entry.zIndex);
|
|
130
|
+
nativeOverlayManager.register(id);
|
|
116
131
|
return () => {
|
|
117
132
|
nativeOverlayManager.unregister(id);
|
|
118
133
|
};
|
|
@@ -121,52 +136,33 @@ const useOverlayRegistration = ({ active, id }) => {
|
|
|
121
136
|
id,
|
|
122
137
|
nativeOverlayManager
|
|
123
138
|
]);
|
|
139
|
+
const isTopOverlay = useCallback(() => nativeOverlayManager.isTop(id), [id, nativeOverlayManager]);
|
|
124
140
|
return {
|
|
125
|
-
zIndex,
|
|
126
|
-
|
|
141
|
+
zIndex: snapshot.registry.get(id)?.zIndex ?? nativeOverlayManager.getZIndex(id),
|
|
142
|
+
isTopmost: snapshot.topmost?.id === id,
|
|
143
|
+
isTopOverlay
|
|
127
144
|
};
|
|
128
145
|
};
|
|
129
146
|
//#endregion
|
|
130
147
|
//#region src/hooks/behavior/overlay/useOverlayDismiss.ts
|
|
131
|
-
const dismissListeners =
|
|
132
|
-
function attachDismissListener(manager) {
|
|
133
|
-
if (dismissListeners.has(manager)) return;
|
|
148
|
+
const dismissListeners = createRetainedResourceRegistry((manager) => {
|
|
134
149
|
if (Platform.OS === "web") {
|
|
135
150
|
const handleKeyDown = (event) => {
|
|
136
151
|
if (event.key !== "Escape") return;
|
|
137
152
|
manager.dispatchTopDismiss();
|
|
138
153
|
};
|
|
139
154
|
document.addEventListener("keydown", handleKeyDown);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
144
|
-
dismissListeners.delete(manager);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
return;
|
|
155
|
+
return () => {
|
|
156
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
157
|
+
};
|
|
148
158
|
}
|
|
149
159
|
const subscription = BackHandler.addEventListener("hardwareBackPress", () => manager.dispatchTopDismiss());
|
|
150
|
-
dismissListeners.set(manager, {
|
|
151
|
-
count: 0,
|
|
152
|
-
detach: () => {
|
|
153
|
-
subscription.remove();
|
|
154
|
-
dismissListeners.delete(manager);
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
function retainDismissListener(manager) {
|
|
159
|
-
attachDismissListener(manager);
|
|
160
|
-
const retained = dismissListeners.get(manager);
|
|
161
|
-
if (!retained) return () => void 0;
|
|
162
|
-
retained.count += 1;
|
|
163
160
|
return () => {
|
|
164
|
-
|
|
165
|
-
if (!current) return;
|
|
166
|
-
current.count = Math.max(0, current.count - 1);
|
|
167
|
-
if (current.count > 0) return;
|
|
168
|
-
current.detach();
|
|
161
|
+
subscription.remove();
|
|
169
162
|
};
|
|
163
|
+
});
|
|
164
|
+
function retainDismissListener(manager) {
|
|
165
|
+
return dismissListeners.retain(manager);
|
|
170
166
|
}
|
|
171
167
|
const useOverlayDismiss = ({ active, closeOnEscape = true, closeOnOutsidePress = true, id, requestClose, requestOutsideClose }) => {
|
|
172
168
|
const nativeOverlayManager = useNativeOverlayManager();
|
|
@@ -182,6 +178,22 @@ const useOverlayDismiss = ({ active, closeOnEscape = true, closeOnOutsidePress =
|
|
|
182
178
|
const requestOutsideTopClose = useCallback(() => {
|
|
183
179
|
nativeOverlayManager.dispatchTopOutsidePress();
|
|
184
180
|
}, [nativeOverlayManager]);
|
|
181
|
+
const getOutsidePressProps = useCallback(({ accessibilityLabel = "Dismiss overlay" } = {}) => {
|
|
182
|
+
if (!active || !closeOnOutsidePress) return {
|
|
183
|
+
accessibilityLabel: void 0,
|
|
184
|
+
accessibilityRole: void 0,
|
|
185
|
+
onPress: void 0
|
|
186
|
+
};
|
|
187
|
+
return {
|
|
188
|
+
accessibilityLabel,
|
|
189
|
+
accessibilityRole: "button",
|
|
190
|
+
onPress: requestOutsideTopClose
|
|
191
|
+
};
|
|
192
|
+
}, [
|
|
193
|
+
active,
|
|
194
|
+
closeOnOutsidePress,
|
|
195
|
+
requestOutsideTopClose
|
|
196
|
+
]);
|
|
185
197
|
useEffect(() => {
|
|
186
198
|
if (!active) return;
|
|
187
199
|
return nativeOverlayManager.registerOutsidePressHandler(id, () => {
|
|
@@ -225,6 +237,7 @@ const useOverlayDismiss = ({ active, closeOnEscape = true, closeOnOutsidePress =
|
|
|
225
237
|
return {
|
|
226
238
|
zIndex: registration.zIndex,
|
|
227
239
|
isTopOverlay,
|
|
240
|
+
getOutsidePressProps,
|
|
228
241
|
requestClose: requestTopClose,
|
|
229
242
|
requestOutsideClose: requestOutsideTopClose
|
|
230
243
|
};
|
|
@@ -262,7 +275,7 @@ const useOverlayFocusRestore = ({ active = false, enabled = true, finalFocus, tr
|
|
|
262
275
|
]);
|
|
263
276
|
const restoreFocusAfterClose = useCallback(() => {
|
|
264
277
|
if (!enabled) return;
|
|
265
|
-
|
|
278
|
+
deferOverlayFocusRestore(restoreFocus, requestAnimationFrame);
|
|
266
279
|
}, [enabled, restoreFocus]);
|
|
267
280
|
useEffect(() => {
|
|
268
281
|
if (!active) return;
|
|
@@ -278,8 +291,11 @@ const useOverlayFocusRestore = ({ active = false, enabled = true, finalFocus, tr
|
|
|
278
291
|
//#region src/hooks/behavior/overlay/useOverlayPresentation.ts
|
|
279
292
|
function useOverlayPresentation(presentation = "auto", breakpoint = 768) {
|
|
280
293
|
const { width } = useWindowDimensions();
|
|
281
|
-
|
|
282
|
-
|
|
294
|
+
return resolveOverlayPresentation({
|
|
295
|
+
presentation,
|
|
296
|
+
defaultPresentation: "sheet",
|
|
297
|
+
autoPresentation: width >= breakpoint ? "popover" : "sheet"
|
|
298
|
+
});
|
|
283
299
|
}
|
|
284
300
|
//#endregion
|
|
285
301
|
//#region src/hooks/useControllableState.ts
|
|
@@ -531,11 +547,23 @@ const useModal = ({ open, defaultOpen = false, onOpenChange, closeOnEscape, clos
|
|
|
531
547
|
};
|
|
532
548
|
//#endregion
|
|
533
549
|
//#region src/hooks/useSelect.ts
|
|
534
|
-
const useSelect = ({ value, defaultValue, onValueChange,
|
|
550
|
+
const useSelect = ({ value, defaultValue, onValueChange, options, multiple = false, maxSelected, closeOnSelect = !multiple, disabled = false, open, defaultOpen = false, onOpenChange }) => {
|
|
551
|
+
const handleValueChange = useCallback((nextValue) => {
|
|
552
|
+
if (!onValueChange) return;
|
|
553
|
+
if (multiple) {
|
|
554
|
+
if (Array.isArray(nextValue)) {
|
|
555
|
+
onValueChange(nextValue);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
onValueChange(nextValue ? [nextValue] : []);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
onValueChange(Array.isArray(nextValue) ? nextValue[0] ?? "" : nextValue);
|
|
562
|
+
}, [multiple, onValueChange]);
|
|
535
563
|
const [selectedValue, setSelectedValue] = useControllableState({
|
|
536
564
|
value,
|
|
537
565
|
defaultValue: defaultValue ?? (multiple ? [] : ""),
|
|
538
|
-
onChange:
|
|
566
|
+
onChange: handleValueChange
|
|
539
567
|
});
|
|
540
568
|
const [isOpen, setIsOpen] = useControllableState({
|
|
541
569
|
value: open,
|
|
@@ -808,7 +836,7 @@ const createStyles$21 = (theme) => StyleSheet.create({
|
|
|
808
836
|
const nativePointerEventsBoxNone$1 = Platform.OS === "web" ? void 0 : { pointerEvents: "box-none" };
|
|
809
837
|
const webPointerEventsBoxNone$1 = Platform.OS === "web" ? { pointerEvents: "box-none" } : void 0;
|
|
810
838
|
function DropdownContent({ children, contentStyle, accessibilityLabel }) {
|
|
811
|
-
const { open, color, presentation, zIndex, position, searchable, searchValue, searchPlaceholder, searchAccessibilityLabel, requestClose,
|
|
839
|
+
const { open, color, presentation, zIndex, position, searchable, searchValue, searchPlaceholder, searchAccessibilityLabel, requestClose, getOutsidePressProps, onSearchChange, onFloatingLayout } = useDropdownContext();
|
|
812
840
|
const { theme } = useTheme();
|
|
813
841
|
const styles = useThemeStyles(createStyles$21);
|
|
814
842
|
const colorPalette = theme.components.dropdown[color];
|
|
@@ -881,10 +909,8 @@ function DropdownContent({ children, contentStyle, accessibilityLabel }) {
|
|
|
881
909
|
webPointerEventsBoxNone$1
|
|
882
910
|
],
|
|
883
911
|
children: /* @__PURE__ */ jsx(Pressable, {
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
style: StyleSheet.absoluteFill,
|
|
887
|
-
onPress: requestOutsideClose
|
|
912
|
+
...getOutsidePressProps({ accessibilityLabel: "Close menu" }),
|
|
913
|
+
style: StyleSheet.absoluteFill
|
|
888
914
|
})
|
|
889
915
|
}), /* @__PURE__ */ jsxs(Animated.View, {
|
|
890
916
|
accessibilityRole: "menu",
|
|
@@ -932,7 +958,7 @@ DropdownContent.displayName = "DropdownContent";
|
|
|
932
958
|
//#region src/components/Dropdown/internal/DropdownCollection.ts
|
|
933
959
|
function createDropdownSlot(name, displayName) {
|
|
934
960
|
const Slot = () => null;
|
|
935
|
-
Slot
|
|
961
|
+
markCompoundSlot(Slot, name);
|
|
936
962
|
Slot.displayName = displayName;
|
|
937
963
|
return Slot;
|
|
938
964
|
}
|
|
@@ -960,11 +986,12 @@ function parseDropdownChildren(children) {
|
|
|
960
986
|
Children.forEach(node, (child) => {
|
|
961
987
|
if (!isValidElement(child)) return;
|
|
962
988
|
const type = child.type;
|
|
989
|
+
const slot = getCompoundSlot(type);
|
|
963
990
|
if (type.__velliraPortal) {
|
|
964
991
|
visit(child.props.children);
|
|
965
992
|
return;
|
|
966
993
|
}
|
|
967
|
-
switch (
|
|
994
|
+
switch (slot) {
|
|
968
995
|
case "trigger":
|
|
969
996
|
triggerProps = child.props;
|
|
970
997
|
trigger = triggerProps.children;
|
|
@@ -1340,6 +1367,11 @@ function DropdownGroup({ label }) {
|
|
|
1340
1367
|
}
|
|
1341
1368
|
DropdownGroup.displayName = "DropdownGroup";
|
|
1342
1369
|
//#endregion
|
|
1370
|
+
//#region src/utils/devWarning.ts
|
|
1371
|
+
const devWarning = (condition, message) => {
|
|
1372
|
+
if ((typeof __DEV__ === "undefined" || __DEV__) && !condition) console.warn(message);
|
|
1373
|
+
};
|
|
1374
|
+
//#endregion
|
|
1343
1375
|
//#region src/components/Dropdown/Item/DropdownItem.styles.ts
|
|
1344
1376
|
const createStyles$18 = (theme) => StyleSheet.create({
|
|
1345
1377
|
item: {
|
|
@@ -1364,7 +1396,7 @@ const createStyles$18 = (theme) => StyleSheet.create({
|
|
|
1364
1396
|
});
|
|
1365
1397
|
//#endregion
|
|
1366
1398
|
//#region src/components/Dropdown/Item/DropdownItem.tsx
|
|
1367
|
-
function DropdownItem({ label, value, color = "default", icon, disabled = false, textWrap = "truncate", onSelect }) {
|
|
1399
|
+
function DropdownItem({ label, value, asChild = false, children, color = "default", icon, disabled = false, textWrap = "truncate", onSelect }) {
|
|
1368
1400
|
const { color: rootColor, itemStyle, textStyle } = useDropdownContext();
|
|
1369
1401
|
const { theme } = useTheme();
|
|
1370
1402
|
const styles = useThemeStyles(createStyles$18);
|
|
@@ -1389,6 +1421,24 @@ function DropdownItem({ label, value, color = "default", icon, disabled = false,
|
|
|
1389
1421
|
const accessibilityLabel = typeof label === "string" ? label : value;
|
|
1390
1422
|
const numberOfLines = textWrap === "wrap" ? void 0 : 1;
|
|
1391
1423
|
const ellipsizeMode = textWrap === "truncate" ? "tail" : "clip";
|
|
1424
|
+
const child = asChild && isValidElement(children) ? children : void 0;
|
|
1425
|
+
const getItemStyle = (pressed) => [
|
|
1426
|
+
styles.item,
|
|
1427
|
+
{ backgroundColor: getBackgroundColor(pressed) },
|
|
1428
|
+
itemStyle
|
|
1429
|
+
];
|
|
1430
|
+
devWarning(!asChild || Boolean(child), "Dropdown.Item: asChild requires a single valid React element child.");
|
|
1431
|
+
if (child) return cloneElement(child, {
|
|
1432
|
+
accessibilityRole: "menuitem",
|
|
1433
|
+
accessibilityLabel,
|
|
1434
|
+
accessibilityState: { disabled },
|
|
1435
|
+
disabled,
|
|
1436
|
+
onPress: (event) => {
|
|
1437
|
+
child.props.onPress?.(event);
|
|
1438
|
+
if (!event.defaultPrevented && !disabled) onSelect(value);
|
|
1439
|
+
},
|
|
1440
|
+
style: [getItemStyle(false), child.props.style]
|
|
1441
|
+
});
|
|
1392
1442
|
return /* @__PURE__ */ jsx(Pressable, {
|
|
1393
1443
|
disabled,
|
|
1394
1444
|
accessibilityRole: "menuitem",
|
|
@@ -1398,11 +1448,7 @@ function DropdownItem({ label, value, color = "default", icon, disabled = false,
|
|
|
1398
1448
|
if (disabled) return;
|
|
1399
1449
|
onSelect(value);
|
|
1400
1450
|
},
|
|
1401
|
-
style: ({ pressed }) =>
|
|
1402
|
-
styles.item,
|
|
1403
|
-
{ backgroundColor: getBackgroundColor(pressed) },
|
|
1404
|
-
itemStyle
|
|
1405
|
-
],
|
|
1451
|
+
style: ({ pressed }) => getItemStyle(pressed),
|
|
1406
1452
|
children: ({ pressed }) => {
|
|
1407
1453
|
const contentColor = getContentColor(pressed);
|
|
1408
1454
|
return /* @__PURE__ */ jsxs(Fragment, { children: [icon ? renderColoredNode(icon, contentColor) : null, /* @__PURE__ */ jsx(Text, {
|
|
@@ -1736,13 +1782,15 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
|
|
|
1736
1782
|
children: item.props.children
|
|
1737
1783
|
});
|
|
1738
1784
|
return /* @__PURE__ */ jsx(DropdownItem, {
|
|
1785
|
+
asChild: item.props.asChild,
|
|
1739
1786
|
label: item.props.children,
|
|
1740
1787
|
value: item.props.value ?? item.id,
|
|
1741
1788
|
color: item.props.color,
|
|
1742
1789
|
icon: item.props.icon,
|
|
1743
1790
|
disabled: item.props.disabled,
|
|
1744
1791
|
textWrap: item.props.textWrap,
|
|
1745
|
-
onSelect: () => handleSelect(item)
|
|
1792
|
+
onSelect: () => handleSelect(item),
|
|
1793
|
+
children: item.props.children
|
|
1746
1794
|
});
|
|
1747
1795
|
}, [handleSelect, styles.emptyText]);
|
|
1748
1796
|
const resolvedSearchPlaceholder = parsed.searchProps?.placeholder ?? searchPlaceholder ?? (command || contentCommand ? "Type a command..." : "Search actions...");
|
|
@@ -1764,7 +1812,7 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
|
|
|
1764
1812
|
itemStyle,
|
|
1765
1813
|
textStyle,
|
|
1766
1814
|
requestClose: dismiss.requestClose,
|
|
1767
|
-
|
|
1815
|
+
getOutsidePressProps: dismiss.getOutsidePressProps,
|
|
1768
1816
|
toggle: handleTriggerPress,
|
|
1769
1817
|
onSearchChange: handleSearchChange,
|
|
1770
1818
|
onFloatingLayout
|
|
@@ -1773,8 +1821,8 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
|
|
|
1773
1821
|
contentPresentation,
|
|
1774
1822
|
disabled,
|
|
1775
1823
|
dismiss.zIndex,
|
|
1824
|
+
dismiss.getOutsidePressProps,
|
|
1776
1825
|
dismiss.requestClose,
|
|
1777
|
-
dismiss.requestOutsideClose,
|
|
1778
1826
|
handleSearchChange,
|
|
1779
1827
|
handleTriggerPress,
|
|
1780
1828
|
isOpen,
|
|
@@ -1885,13 +1933,23 @@ const createStyles$14 = (theme) => StyleSheet.create({
|
|
|
1885
1933
|
justifyContent: "space-between",
|
|
1886
1934
|
paddingBottom: theme.components.modal.header.paddingBottom
|
|
1887
1935
|
},
|
|
1888
|
-
|
|
1936
|
+
headerContent: {
|
|
1889
1937
|
flex: 1,
|
|
1938
|
+
gap: theme.tokens.spacing["1"]
|
|
1939
|
+
},
|
|
1940
|
+
title: {
|
|
1890
1941
|
color: theme.components.modal.title.fg,
|
|
1891
1942
|
fontFamily: theme.tokens.typography.family.semibold,
|
|
1892
1943
|
fontSize: theme.tokens.typography.size.lg,
|
|
1893
1944
|
lineHeight: theme.tokens.typography.lineHeight.md
|
|
1894
1945
|
},
|
|
1946
|
+
plainTitle: { flex: 1 },
|
|
1947
|
+
description: {
|
|
1948
|
+
color: theme.components.modal.description.fg,
|
|
1949
|
+
fontFamily: theme.tokens.typography.family.regular,
|
|
1950
|
+
fontSize: theme.tokens.typography.size.sm,
|
|
1951
|
+
lineHeight: theme.tokens.typography.lineHeight.sm
|
|
1952
|
+
},
|
|
1895
1953
|
closeButton: {
|
|
1896
1954
|
width: theme.components.modal.closeButton.size,
|
|
1897
1955
|
height: theme.components.modal.closeButton.size,
|
|
@@ -1915,11 +1973,11 @@ const useModalContext = () => {
|
|
|
1915
1973
|
ModalContext.displayName = "ModalContext";
|
|
1916
1974
|
//#endregion
|
|
1917
1975
|
//#region src/components/Modal/Close/ModalClose.tsx
|
|
1918
|
-
const ModalClose = ({ children, accessibilityLabel, style }) => {
|
|
1976
|
+
const ModalClose = ({ asChild = false, children, accessibilityLabel, style }) => {
|
|
1919
1977
|
const { theme } = useTheme();
|
|
1920
1978
|
const styles = useThemeStyles(createStyles$14);
|
|
1921
1979
|
const { onClose } = useModalContext();
|
|
1922
|
-
if (isValidElement(children)) return cloneElement(children, {
|
|
1980
|
+
if ((asChild || children !== void 0) && isValidElement(children)) return cloneElement(children, {
|
|
1923
1981
|
accessibilityLabel: children.props.accessibilityLabel ?? accessibilityLabel,
|
|
1924
1982
|
onPress: (event) => {
|
|
1925
1983
|
children.props.onPress?.(event);
|
|
@@ -2012,19 +2070,46 @@ const ModalFooter = ({ children, style }) => {
|
|
|
2012
2070
|
};
|
|
2013
2071
|
ModalFooter.displayName = "ModalFooter";
|
|
2014
2072
|
//#endregion
|
|
2073
|
+
//#region src/components/Modal/Header/ModalDescription.tsx
|
|
2074
|
+
const ModalDescription = ({ children, style }) => {
|
|
2075
|
+
return /* @__PURE__ */ jsx(Text, {
|
|
2076
|
+
style: [useThemeStyles(createStyles$14).description, style],
|
|
2077
|
+
children
|
|
2078
|
+
});
|
|
2079
|
+
};
|
|
2080
|
+
ModalDescription.displayName = "Modal.Description";
|
|
2081
|
+
//#endregion
|
|
2015
2082
|
//#region src/components/Modal/Header/ModalHeader.tsx
|
|
2016
2083
|
const ModalHeader = ({ children, style, textStyle }) => {
|
|
2017
2084
|
const styles = useThemeStyles(createStyles$14);
|
|
2085
|
+
const isPlainTitle = typeof children === "string" || typeof children === "number";
|
|
2018
2086
|
return /* @__PURE__ */ jsxs(View, {
|
|
2019
2087
|
style: [styles.header, style],
|
|
2020
|
-
children: [/* @__PURE__ */ jsx(Text, {
|
|
2021
|
-
style: [
|
|
2088
|
+
children: [isPlainTitle ? /* @__PURE__ */ jsx(Text, {
|
|
2089
|
+
style: [
|
|
2090
|
+
styles.title,
|
|
2091
|
+
styles.plainTitle,
|
|
2092
|
+
textStyle
|
|
2093
|
+
],
|
|
2094
|
+
children
|
|
2095
|
+
}) : /* @__PURE__ */ jsx(View, {
|
|
2096
|
+
style: styles.headerContent,
|
|
2022
2097
|
children
|
|
2023
2098
|
}), /* @__PURE__ */ jsx(ModalClose, {})]
|
|
2024
2099
|
});
|
|
2025
2100
|
};
|
|
2026
2101
|
ModalHeader.displayName = "ModalHeader";
|
|
2027
2102
|
//#endregion
|
|
2103
|
+
//#region src/components/Modal/Header/ModalTitle.tsx
|
|
2104
|
+
const ModalTitle = ({ children, style }) => {
|
|
2105
|
+
return /* @__PURE__ */ jsx(Text, {
|
|
2106
|
+
accessibilityRole: "header",
|
|
2107
|
+
style: [useThemeStyles(createStyles$14).title, style],
|
|
2108
|
+
children
|
|
2109
|
+
});
|
|
2110
|
+
};
|
|
2111
|
+
ModalTitle.displayName = "Modal.Title";
|
|
2112
|
+
//#endregion
|
|
2028
2113
|
//#region src/components/Modal/Modal.styles.ts
|
|
2029
2114
|
const createStyles$11 = (theme) => StyleSheet.create({
|
|
2030
2115
|
overlay: {
|
|
@@ -2042,7 +2127,7 @@ const createStyles$11 = (theme) => StyleSheet.create({
|
|
|
2042
2127
|
//#region src/components/Modal/Overlay/ModalOverlay.tsx
|
|
2043
2128
|
const ModalOverlay = ({ children, overlayStyle }) => {
|
|
2044
2129
|
const styles = useThemeStyles(createStyles$11);
|
|
2045
|
-
const { animation, animationProgress,
|
|
2130
|
+
const { animation, animationProgress, zIndex, onClose, getOutsidePressProps, shouldRender } = useModalContext();
|
|
2046
2131
|
const backdropStyle = animation === "none" ? void 0 : { opacity: animationProgress };
|
|
2047
2132
|
return /* @__PURE__ */ jsx(Modal$1, {
|
|
2048
2133
|
visible: shouldRender,
|
|
@@ -2059,17 +2144,15 @@ const ModalOverlay = ({ children, overlayStyle }) => {
|
|
|
2059
2144
|
style: [styles.backdrop, backdropStyle],
|
|
2060
2145
|
children: /* @__PURE__ */ jsx(Pressable, {
|
|
2061
2146
|
testID: "modal-backdrop",
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
style: StyleSheet.absoluteFill,
|
|
2065
|
-
onPress: closeOnOutsidePress ? onOutsideClose : void 0
|
|
2147
|
+
...getOutsidePressProps({ accessibilityLabel: "Close modal" }),
|
|
2148
|
+
style: StyleSheet.absoluteFill
|
|
2066
2149
|
})
|
|
2067
2150
|
}), children]
|
|
2068
2151
|
})
|
|
2069
2152
|
});
|
|
2070
2153
|
};
|
|
2071
2154
|
//#endregion
|
|
2072
|
-
//#region src/components/Modal/Root/
|
|
2155
|
+
//#region src/components/Modal/Root/useModalRootAnimation.ts
|
|
2073
2156
|
const linearEasing = (value) => value;
|
|
2074
2157
|
const easingMap = {
|
|
2075
2158
|
standard: Easing?.bezier?.(.22, 1, .36, 1) ?? linearEasing,
|
|
@@ -2090,33 +2173,10 @@ const resolveDuration = (duration) => {
|
|
|
2090
2173
|
open: duration?.open ?? parseDuration(nativeThemes.light.components.modal.motion.openDuration)
|
|
2091
2174
|
};
|
|
2092
2175
|
};
|
|
2093
|
-
|
|
2094
|
-
const
|
|
2095
|
-
const
|
|
2096
|
-
const triggerRef = useRef(null);
|
|
2097
|
-
const [shouldRender, setShouldRender] = useState(initialOpen);
|
|
2176
|
+
function useModalRootAnimation({ animation, defaultOpen, duration, easing, open }) {
|
|
2177
|
+
const animationProgress = useRef(new Animated.Value(defaultOpen ? 1 : 0));
|
|
2178
|
+
const [shouldRender, setShouldRender] = useState(defaultOpen);
|
|
2098
2179
|
const [reduceMotion, setReduceMotion] = useState(false);
|
|
2099
|
-
const modal = useModal({
|
|
2100
|
-
open,
|
|
2101
|
-
defaultOpen,
|
|
2102
|
-
onOpenChange,
|
|
2103
|
-
closeOnOutsidePress
|
|
2104
|
-
});
|
|
2105
|
-
const { restoreFocusAfterClose } = useOverlayFocusRestore({
|
|
2106
|
-
active: modal.open,
|
|
2107
|
-
triggerRef
|
|
2108
|
-
});
|
|
2109
|
-
const previousOpenRef = useRef(modal.open);
|
|
2110
|
-
useEffect(() => {
|
|
2111
|
-
if (previousOpenRef.current && !modal.open) restoreFocusAfterClose();
|
|
2112
|
-
previousOpenRef.current = modal.open;
|
|
2113
|
-
}, [modal.open, restoreFocusAfterClose]);
|
|
2114
|
-
const dismiss = useOverlayDismiss({
|
|
2115
|
-
id: modal.contentId,
|
|
2116
|
-
active: modal.open,
|
|
2117
|
-
closeOnOutsidePress: modal.closeOnOutsidePress,
|
|
2118
|
-
requestClose: modal.requestClose
|
|
2119
|
-
});
|
|
2120
2180
|
const animationDuration = resolveDuration(duration);
|
|
2121
2181
|
const shouldAnimate = animation !== "none" && !reduceMotion;
|
|
2122
2182
|
useEffect(() => {
|
|
@@ -2128,7 +2188,7 @@ const ModalRoot = ({ open, defaultOpen = false, onOpenChange, animation = "scale
|
|
|
2128
2188
|
}, []);
|
|
2129
2189
|
useEffect(() => {
|
|
2130
2190
|
const progress = animationProgress.current;
|
|
2131
|
-
if (
|
|
2191
|
+
if (open) {
|
|
2132
2192
|
setShouldRender(true);
|
|
2133
2193
|
if (!shouldAnimate) {
|
|
2134
2194
|
progress.setValue(1);
|
|
@@ -2160,17 +2220,57 @@ const ModalRoot = ({ open, defaultOpen = false, onOpenChange, animation = "scale
|
|
|
2160
2220
|
animationDuration.close,
|
|
2161
2221
|
animationDuration.open,
|
|
2162
2222
|
easing,
|
|
2163
|
-
|
|
2223
|
+
open,
|
|
2164
2224
|
shouldAnimate
|
|
2165
2225
|
]);
|
|
2226
|
+
return {
|
|
2227
|
+
animationProgress: animationProgress.current,
|
|
2228
|
+
shouldRender
|
|
2229
|
+
};
|
|
2230
|
+
}
|
|
2231
|
+
//#endregion
|
|
2232
|
+
//#region src/components/Modal/Root/ModalRoot.tsx
|
|
2233
|
+
const ModalRoot = ({ open, defaultOpen = false, onOpenChange, animation = "scale", duration, easing = "standard", closeOnEscape = true, closeOnOutsidePress = true, restoreFocus = true, children }) => {
|
|
2234
|
+
const initialOpen = open ?? defaultOpen;
|
|
2235
|
+
const triggerRef = useRef(null);
|
|
2236
|
+
const modal = useModal({
|
|
2237
|
+
open,
|
|
2238
|
+
defaultOpen,
|
|
2239
|
+
onOpenChange,
|
|
2240
|
+
closeOnEscape,
|
|
2241
|
+
closeOnOutsidePress
|
|
2242
|
+
});
|
|
2243
|
+
const { animationProgress, shouldRender } = useModalRootAnimation({
|
|
2244
|
+
animation,
|
|
2245
|
+
defaultOpen: initialOpen,
|
|
2246
|
+
duration,
|
|
2247
|
+
easing,
|
|
2248
|
+
open: modal.open
|
|
2249
|
+
});
|
|
2250
|
+
const { restoreFocusAfterClose } = useOverlayFocusRestore({
|
|
2251
|
+
active: modal.open,
|
|
2252
|
+
enabled: restoreFocus,
|
|
2253
|
+
triggerRef
|
|
2254
|
+
});
|
|
2255
|
+
const previousOpenRef = useRef(modal.open);
|
|
2256
|
+
useEffect(() => {
|
|
2257
|
+
if (previousOpenRef.current && !modal.open) restoreFocusAfterClose();
|
|
2258
|
+
previousOpenRef.current = modal.open;
|
|
2259
|
+
}, [modal.open, restoreFocusAfterClose]);
|
|
2260
|
+
const dismiss = useOverlayDismiss({
|
|
2261
|
+
id: modal.contentId,
|
|
2262
|
+
active: modal.open,
|
|
2263
|
+
closeOnEscape: modal.closeOnEscape,
|
|
2264
|
+
closeOnOutsidePress: modal.closeOnOutsidePress,
|
|
2265
|
+
requestClose: modal.requestClose
|
|
2266
|
+
});
|
|
2166
2267
|
return /* @__PURE__ */ jsx(ModalProvider, {
|
|
2167
2268
|
value: {
|
|
2168
2269
|
animation,
|
|
2169
|
-
animationProgress
|
|
2170
|
-
closeOnOutsidePress: modal.closeOnOutsidePress,
|
|
2270
|
+
animationProgress,
|
|
2171
2271
|
zIndex: dismiss.zIndex,
|
|
2172
2272
|
onClose: dismiss.requestClose,
|
|
2173
|
-
|
|
2273
|
+
getOutsidePressProps: dismiss.getOutsidePressProps,
|
|
2174
2274
|
open: modal.open,
|
|
2175
2275
|
setOpen: modal.setOpen,
|
|
2176
2276
|
shouldRender,
|
|
@@ -2236,6 +2336,8 @@ const Modal = Object.assign(ModalRoot, {
|
|
|
2236
2336
|
Overlay: ModalOverlay,
|
|
2237
2337
|
Content: ModalContent,
|
|
2238
2338
|
Header: ModalHeader,
|
|
2339
|
+
Title: ModalTitle,
|
|
2340
|
+
Description: ModalDescription,
|
|
2239
2341
|
Body: ModalBody,
|
|
2240
2342
|
Footer: ModalFooter,
|
|
2241
2343
|
Close: ModalClose
|
|
@@ -2416,7 +2518,7 @@ function PopoverContent({ children, style, ...contentProps }) {
|
|
|
2416
2518
|
const { theme } = useTheme();
|
|
2417
2519
|
const layerRef = useRef(null);
|
|
2418
2520
|
const themedStyles = useMemo(() => createPopoverContentStyles(theme), [theme]);
|
|
2419
|
-
const { open, zIndex, position, onFloatingLayout, updatePosition, requestClose,
|
|
2521
|
+
const { open, zIndex, position, onFloatingLayout, updatePosition, requestClose, getOutsidePressProps } = usePopoverContext("Popover.Content");
|
|
2420
2522
|
useEffect(() => {
|
|
2421
2523
|
if (!open) return;
|
|
2422
2524
|
requestAnimationFrame(() => {
|
|
@@ -2432,9 +2534,7 @@ function PopoverContent({ children, style, ...contentProps }) {
|
|
|
2432
2534
|
style: [styles.root, { zIndex }],
|
|
2433
2535
|
children: [/* @__PURE__ */ jsx(Pressable, {
|
|
2434
2536
|
testID: "popover-backdrop",
|
|
2435
|
-
accessibilityLabel:
|
|
2436
|
-
accessibilityRole: closeOnOutsidePress ? "button" : void 0,
|
|
2437
|
-
onPress: closeOnOutsidePress ? requestOutsideClose : void 0,
|
|
2537
|
+
...getOutsidePressProps({ accessibilityLabel: "Close popover" }),
|
|
2438
2538
|
style: styles.backdrop
|
|
2439
2539
|
}), /* @__PURE__ */ jsx(View, {
|
|
2440
2540
|
...contentProps,
|
|
@@ -2517,7 +2617,6 @@ function PopoverRoot({ children, open: openProp, defaultOpen = false, onOpenChan
|
|
|
2517
2617
|
return /* @__PURE__ */ jsx(PopoverProvider, {
|
|
2518
2618
|
value: {
|
|
2519
2619
|
open,
|
|
2520
|
-
closeOnOutsidePress,
|
|
2521
2620
|
triggerRef,
|
|
2522
2621
|
anchorRef,
|
|
2523
2622
|
side,
|
|
@@ -2527,7 +2626,7 @@ function PopoverRoot({ children, open: openProp, defaultOpen = false, onOpenChan
|
|
|
2527
2626
|
position,
|
|
2528
2627
|
arrowPosition,
|
|
2529
2628
|
requestClose: dismiss.requestClose,
|
|
2530
|
-
|
|
2629
|
+
getOutsidePressProps: dismiss.getOutsidePressProps,
|
|
2531
2630
|
onFloatingLayout,
|
|
2532
2631
|
updatePosition,
|
|
2533
2632
|
setOpen
|
|
@@ -3231,17 +3330,14 @@ const createContentStyles = (theme) => StyleSheet.create({
|
|
|
3231
3330
|
}
|
|
3232
3331
|
});
|
|
3233
3332
|
//#endregion
|
|
3234
|
-
//#region src/components/Select/internal/types.ts
|
|
3235
|
-
const selectSlotName = Symbol("VelliraNativeSelectSlot");
|
|
3236
|
-
//#endregion
|
|
3237
3333
|
//#region src/components/Select/internal/SelectCollection.ts
|
|
3238
3334
|
const createSelectSlot = (name, displayName) => {
|
|
3239
3335
|
const Slot = (_props) => null;
|
|
3240
|
-
Slot
|
|
3336
|
+
markCompoundSlot(Slot, name);
|
|
3241
3337
|
Slot.displayName = displayName;
|
|
3242
3338
|
return Slot;
|
|
3243
3339
|
};
|
|
3244
|
-
const getSelectSlot = (type) => type
|
|
3340
|
+
const getSelectSlot = (type) => getCompoundSlot(type);
|
|
3245
3341
|
const defaultSelectFilter = (option, query) => option.label.toLowerCase().includes(query.trim().toLowerCase());
|
|
3246
3342
|
const getTextFromNode = (node) => {
|
|
3247
3343
|
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
@@ -3330,6 +3426,8 @@ const parseSelectChildren = (children) => {
|
|
|
3330
3426
|
const option = {
|
|
3331
3427
|
value: props.value,
|
|
3332
3428
|
label: props.label,
|
|
3429
|
+
asChild: props.asChild,
|
|
3430
|
+
children: props.children,
|
|
3333
3431
|
disabled: props.disabled,
|
|
3334
3432
|
description: props.description,
|
|
3335
3433
|
icon: props.icon,
|
|
@@ -3537,17 +3635,54 @@ const renderNodeOrText = (node, textStyle, fallback) => {
|
|
|
3537
3635
|
}) : null);
|
|
3538
3636
|
};
|
|
3539
3637
|
const SelectItem = createSelectSlot("item", "Select.Item");
|
|
3540
|
-
const SelectItemRow = ({ option, isSelected, isDisabled, optionStyle, onSelect }) => {
|
|
3638
|
+
const SelectItemRow = ({ option, isSelected, isDisabled, itemIndex, selectedValues, multiple, optionStyle, onSelect }) => {
|
|
3541
3639
|
const { theme } = useTheme();
|
|
3542
3640
|
const styles = useThemeStyles(createItemStyles);
|
|
3543
3641
|
const { color, variant, renderOption } = useSelectContext();
|
|
3544
3642
|
const [isHovered, setIsHovered] = useState(false);
|
|
3643
|
+
const child = option.asChild && isValidElement(option.children) ? option.children : void 0;
|
|
3545
3644
|
const optionPalette = theme.components.select[option.color ?? color][variant].option;
|
|
3546
3645
|
const getOptionState = (pressed) => {
|
|
3547
3646
|
if (isDisabled) return theme.components.select.option.disabled;
|
|
3548
3647
|
if (isSelected) return pressed ? optionPalette.selectedPressed : isHovered ? optionPalette.selectedHover : optionPalette.selected;
|
|
3549
3648
|
return pressed ? optionPalette.pressed : isHovered ? optionPalette.hover : theme.components.select.option.default;
|
|
3550
3649
|
};
|
|
3650
|
+
const getOptionStyle = (pressed) => {
|
|
3651
|
+
const optionState = getOptionState(pressed);
|
|
3652
|
+
return [
|
|
3653
|
+
styles.option,
|
|
3654
|
+
{
|
|
3655
|
+
backgroundColor: optionState.bg,
|
|
3656
|
+
borderColor: optionState.border
|
|
3657
|
+
},
|
|
3658
|
+
isDisabled && styles.optionDisabled,
|
|
3659
|
+
optionStyle
|
|
3660
|
+
];
|
|
3661
|
+
};
|
|
3662
|
+
devWarning(!option.asChild || Boolean(child), "Select.Item: asChild requires a single valid React element child.");
|
|
3663
|
+
if (child) return cloneElement(child, {
|
|
3664
|
+
accessibilityRole: "button",
|
|
3665
|
+
accessibilityLabel: option.accessibilityLabel ?? option.label,
|
|
3666
|
+
accessibilityHint: option.accessibilityHint,
|
|
3667
|
+
accessibilityState: {
|
|
3668
|
+
selected: isSelected,
|
|
3669
|
+
disabled: isDisabled
|
|
3670
|
+
},
|
|
3671
|
+
disabled: isDisabled,
|
|
3672
|
+
onPress: (event) => {
|
|
3673
|
+
child.props.onPress?.(event);
|
|
3674
|
+
if (!event.defaultPrevented && !isDisabled) onSelect(option);
|
|
3675
|
+
},
|
|
3676
|
+
onHoverIn: () => {
|
|
3677
|
+
child.props.onHoverIn?.();
|
|
3678
|
+
setIsHovered(true);
|
|
3679
|
+
},
|
|
3680
|
+
onHoverOut: () => {
|
|
3681
|
+
child.props.onHoverOut?.();
|
|
3682
|
+
setIsHovered(false);
|
|
3683
|
+
},
|
|
3684
|
+
style: [getOptionStyle(false), child.props.style]
|
|
3685
|
+
});
|
|
3551
3686
|
return /* @__PURE__ */ jsx(Pressable, {
|
|
3552
3687
|
disabled: isDisabled,
|
|
3553
3688
|
accessibilityRole: "button",
|
|
@@ -3560,24 +3695,19 @@ const SelectItemRow = ({ option, isSelected, isDisabled, optionStyle, onSelect }
|
|
|
3560
3695
|
onPress: () => onSelect(option),
|
|
3561
3696
|
onHoverIn: () => setIsHovered(true),
|
|
3562
3697
|
onHoverOut: () => setIsHovered(false),
|
|
3563
|
-
style: ({ pressed }) =>
|
|
3564
|
-
const optionState = getOptionState(pressed);
|
|
3565
|
-
return [
|
|
3566
|
-
styles.option,
|
|
3567
|
-
{
|
|
3568
|
-
backgroundColor: optionState.bg,
|
|
3569
|
-
borderColor: optionState.border
|
|
3570
|
-
},
|
|
3571
|
-
isDisabled && styles.optionDisabled,
|
|
3572
|
-
optionStyle
|
|
3573
|
-
];
|
|
3574
|
-
},
|
|
3698
|
+
style: ({ pressed }) => getOptionStyle(pressed),
|
|
3575
3699
|
children: ({ pressed }) => {
|
|
3576
3700
|
const optionFg = getOptionState(pressed).fg;
|
|
3577
3701
|
const descriptionFg = isSelected || pressed ? optionFg : theme.components.select.option.description.fg;
|
|
3578
|
-
return renderOption ? renderNodeOrText(renderOption(
|
|
3702
|
+
return renderOption ? renderNodeOrText(renderOption({
|
|
3703
|
+
option,
|
|
3579
3704
|
selected: isSelected,
|
|
3580
|
-
disabled: isDisabled
|
|
3705
|
+
disabled: isDisabled,
|
|
3706
|
+
active: isHovered,
|
|
3707
|
+
index: itemIndex,
|
|
3708
|
+
values: selectedValues,
|
|
3709
|
+
multiple,
|
|
3710
|
+
pressed
|
|
3581
3711
|
}), [styles.optionLabel, { color: optionFg }]) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3582
3712
|
option.icon && /* @__PURE__ */ jsx(View, {
|
|
3583
3713
|
style: styles.optionIcon,
|
|
@@ -3693,12 +3823,11 @@ const createPresentationStyles = (theme) => StyleSheet.create({
|
|
|
3693
3823
|
});
|
|
3694
3824
|
//#endregion
|
|
3695
3825
|
//#region src/components/Select/Presentation/SelectBackdrop.tsx
|
|
3696
|
-
const SelectBackdrop = ({
|
|
3826
|
+
const SelectBackdrop = ({ outsidePressProps }) => {
|
|
3827
|
+
const styles = useThemeStyles(createPresentationStyles);
|
|
3697
3828
|
return /* @__PURE__ */ jsx(Pressable, {
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
accessibilityRole: "button",
|
|
3701
|
-
accessibilityLabel: "Dismiss select"
|
|
3829
|
+
...outsidePressProps,
|
|
3830
|
+
style: styles.backdrop
|
|
3702
3831
|
});
|
|
3703
3832
|
};
|
|
3704
3833
|
SelectBackdrop.displayName = "Select.Backdrop";
|
|
@@ -3715,7 +3844,7 @@ const SelectHandle = () => {
|
|
|
3715
3844
|
SelectHandle.displayName = "Select.Handle";
|
|
3716
3845
|
//#endregion
|
|
3717
3846
|
//#region src/components/Select/Presentation/SelectModal.tsx
|
|
3718
|
-
const SelectModal = ({ visible, onClose,
|
|
3847
|
+
const SelectModal = ({ visible, onClose, outsidePressProps, zIndex, contentStyle, children }) => {
|
|
3719
3848
|
const styles = useThemeStyles(createPresentationStyles);
|
|
3720
3849
|
return /* @__PURE__ */ jsx(Modal$1, {
|
|
3721
3850
|
transparent: true,
|
|
@@ -3729,10 +3858,7 @@ const SelectModal = ({ visible, onClose, dismissOnBackdropPress, zIndex, content
|
|
|
3729
3858
|
Platform.OS === "web" && { zIndex }
|
|
3730
3859
|
],
|
|
3731
3860
|
testID: "select-content-root",
|
|
3732
|
-
children: [/* @__PURE__ */ jsx(SelectBackdrop, {
|
|
3733
|
-
onClose,
|
|
3734
|
-
dismissOnBackdropPress
|
|
3735
|
-
}), /* @__PURE__ */ jsx(View, {
|
|
3861
|
+
children: [/* @__PURE__ */ jsx(SelectBackdrop, { outsidePressProps }), /* @__PURE__ */ jsx(View, {
|
|
3736
3862
|
style: [
|
|
3737
3863
|
styles.content,
|
|
3738
3864
|
styles.modalPresentation,
|
|
@@ -3747,7 +3873,7 @@ const SelectModal = ({ visible, onClose, dismissOnBackdropPress, zIndex, content
|
|
|
3747
3873
|
SelectModal.displayName = "Select.Modal";
|
|
3748
3874
|
//#endregion
|
|
3749
3875
|
//#region src/components/Select/Presentation/SelectPopover.tsx
|
|
3750
|
-
const SelectPopover = ({ visible, onClose,
|
|
3876
|
+
const SelectPopover = ({ visible, onClose, outsidePressProps, zIndex, position, onFloatingLayout, matchTriggerWidth, triggerWidth, contentStyle, children }) => {
|
|
3751
3877
|
const styles = useThemeStyles(createPresentationStyles);
|
|
3752
3878
|
return /* @__PURE__ */ jsx(Modal$1, {
|
|
3753
3879
|
transparent: true,
|
|
@@ -3757,10 +3883,7 @@ const SelectPopover = ({ visible, onClose, dismissOnBackdropPress, zIndex, posit
|
|
|
3757
3883
|
children: /* @__PURE__ */ jsxs(View, {
|
|
3758
3884
|
style: [styles.modalRoot, Platform.OS === "web" && { zIndex }],
|
|
3759
3885
|
testID: "select-content-root",
|
|
3760
|
-
children: [/* @__PURE__ */ jsx(SelectBackdrop, {
|
|
3761
|
-
onClose,
|
|
3762
|
-
dismissOnBackdropPress
|
|
3763
|
-
}), /* @__PURE__ */ jsx(View, {
|
|
3886
|
+
children: [/* @__PURE__ */ jsx(SelectBackdrop, { outsidePressProps }), /* @__PURE__ */ jsx(View, {
|
|
3764
3887
|
onLayout: onFloatingLayout,
|
|
3765
3888
|
style: [
|
|
3766
3889
|
styles.content,
|
|
@@ -3782,7 +3905,7 @@ const SelectPopover = ({ visible, onClose, dismissOnBackdropPress, zIndex, posit
|
|
|
3782
3905
|
SelectPopover.displayName = "Select.Popover";
|
|
3783
3906
|
//#endregion
|
|
3784
3907
|
//#region src/components/Select/Presentation/SelectSheet.tsx
|
|
3785
|
-
const SelectSheet = ({ visible, onClose,
|
|
3908
|
+
const SelectSheet = ({ visible, onClose, outsidePressProps, zIndex, contentStyle, children }) => {
|
|
3786
3909
|
const styles = useThemeStyles(createPresentationStyles);
|
|
3787
3910
|
return /* @__PURE__ */ jsx(Modal$1, {
|
|
3788
3911
|
transparent: true,
|
|
@@ -3796,10 +3919,7 @@ const SelectSheet = ({ visible, onClose, dismissOnBackdropPress, zIndex, content
|
|
|
3796
3919
|
Platform.OS === "web" && { zIndex }
|
|
3797
3920
|
],
|
|
3798
3921
|
testID: "select-content-root",
|
|
3799
|
-
children: [/* @__PURE__ */ jsx(SelectBackdrop, {
|
|
3800
|
-
onClose,
|
|
3801
|
-
dismissOnBackdropPress
|
|
3802
|
-
}), /* @__PURE__ */ jsxs(View, {
|
|
3922
|
+
children: [/* @__PURE__ */ jsx(SelectBackdrop, { outsidePressProps }), /* @__PURE__ */ jsxs(View, {
|
|
3803
3923
|
style: [
|
|
3804
3924
|
styles.content,
|
|
3805
3925
|
styles.sheet,
|
|
@@ -3924,13 +4044,13 @@ const SelectContentSurface = () => {
|
|
|
3924
4044
|
const wasOpenRef = useRef(false);
|
|
3925
4045
|
const [openCycle, setOpenCycle] = useState(0);
|
|
3926
4046
|
const context = useSelectContext();
|
|
3927
|
-
const { isOpen, resolvedPresentation, zIndex, position, onFloatingLayout,
|
|
4047
|
+
const { isOpen, resolvedPresentation, zIndex, position, onFloatingLayout, contentStyle, matchTriggerWidth, triggerWidth, resolvedLabel, closeContent, getOutsidePressProps, searchable, loading, filteredRows, selectedValues, selectedOptions, maxSelected, optionStyle, selectOption, selectGroup, itemHeight, selectedRowIndex, query } = context;
|
|
3928
4048
|
const initialScrollIndex = Boolean(context.virtual) && selectedRowIndex > 0 && query === "" ? selectedRowIndex : void 0;
|
|
3929
4049
|
useEffect(() => {
|
|
3930
4050
|
if (isOpen && !wasOpenRef.current) setOpenCycle((cycle) => cycle + 1);
|
|
3931
4051
|
wasOpenRef.current = isOpen;
|
|
3932
4052
|
}, [isOpen]);
|
|
3933
|
-
const renderRow = ({ item }) => {
|
|
4053
|
+
const renderRow = ({ item, index }) => {
|
|
3934
4054
|
if (item.type === "group") {
|
|
3935
4055
|
if (item.selectable && context.multiple) {
|
|
3936
4056
|
const enabledGroupValues = item.itemValues.filter((value) => context.optionsByValue.get(value));
|
|
@@ -3952,6 +4072,9 @@ const SelectContentSurface = () => {
|
|
|
3952
4072
|
option: item.option,
|
|
3953
4073
|
isSelected,
|
|
3954
4074
|
isDisabled: Boolean(item.option.disabled || maxReached),
|
|
4075
|
+
itemIndex: index,
|
|
4076
|
+
selectedValues,
|
|
4077
|
+
multiple: context.multiple,
|
|
3955
4078
|
optionStyle,
|
|
3956
4079
|
onSelect: selectOption
|
|
3957
4080
|
});
|
|
@@ -4014,7 +4137,7 @@ const SelectContentSurface = () => {
|
|
|
4014
4137
|
if (resolvedPresentation === "sheet") return /* @__PURE__ */ jsx(SelectSheet, {
|
|
4015
4138
|
visible: isOpen,
|
|
4016
4139
|
onClose: closeContent,
|
|
4017
|
-
|
|
4140
|
+
outsidePressProps: getOutsidePressProps({ accessibilityLabel: "Dismiss select" }),
|
|
4018
4141
|
zIndex,
|
|
4019
4142
|
contentStyle,
|
|
4020
4143
|
children: body
|
|
@@ -4022,7 +4145,7 @@ const SelectContentSurface = () => {
|
|
|
4022
4145
|
if (resolvedPresentation === "popover") return /* @__PURE__ */ jsx(SelectPopover, {
|
|
4023
4146
|
visible: isOpen,
|
|
4024
4147
|
onClose: closeContent,
|
|
4025
|
-
|
|
4148
|
+
outsidePressProps: getOutsidePressProps({ accessibilityLabel: "Dismiss select" }),
|
|
4026
4149
|
position,
|
|
4027
4150
|
zIndex,
|
|
4028
4151
|
onFloatingLayout,
|
|
@@ -4034,7 +4157,7 @@ const SelectContentSurface = () => {
|
|
|
4034
4157
|
return /* @__PURE__ */ jsx(SelectModal, {
|
|
4035
4158
|
visible: isOpen,
|
|
4036
4159
|
onClose: closeContent,
|
|
4037
|
-
|
|
4160
|
+
outsidePressProps: getOutsidePressProps({ accessibilityLabel: "Dismiss select" }),
|
|
4038
4161
|
zIndex,
|
|
4039
4162
|
contentStyle,
|
|
4040
4163
|
children: body
|
|
@@ -4057,95 +4180,6 @@ const SelectItemIcon = createSelectSlot("itemIcon", "Select.ItemIcon");
|
|
|
4057
4180
|
//#region src/components/Select/Label/SelectLabel.tsx
|
|
4058
4181
|
const SelectLabel = createSelectSlot("label", "Select.Label");
|
|
4059
4182
|
//#endregion
|
|
4060
|
-
//#region src/hooks/behavior/select/useSelectCollection.ts
|
|
4061
|
-
const useSelectCollection = (children, optionsProp) => {
|
|
4062
|
-
const parsedChildren = useMemo(() => parseSelectChildren(children), [children]);
|
|
4063
|
-
const options = useMemo(() => [...optionsProp ?? [], ...parsedChildren.options], [optionsProp, parsedChildren.options]);
|
|
4064
|
-
return {
|
|
4065
|
-
options,
|
|
4066
|
-
rows: useMemo(() => {
|
|
4067
|
-
if (parsedChildren.rows.length > 0) return parsedChildren.rows;
|
|
4068
|
-
return options.map((option) => ({
|
|
4069
|
-
type: "item",
|
|
4070
|
-
key: `item-${option.value}`,
|
|
4071
|
-
option
|
|
4072
|
-
}));
|
|
4073
|
-
}, [options, parsedChildren.rows]),
|
|
4074
|
-
searchableFromChildren: parsedChildren.searchable,
|
|
4075
|
-
searchPlaceholderFromChildren: parsedChildren.searchPlaceholder,
|
|
4076
|
-
emptyFromChildren: parsedChildren.empty,
|
|
4077
|
-
loadingFromChildren: parsedChildren.loading
|
|
4078
|
-
};
|
|
4079
|
-
};
|
|
4080
|
-
//#endregion
|
|
4081
|
-
//#region src/hooks/behavior/select/useSelectSearch.ts
|
|
4082
|
-
const useSelectSearch = ({ rows, isOpen, searchable, searchableFromChildren, onSearch, filterOptions, filter = defaultSelectFilter }) => {
|
|
4083
|
-
const [query, setQuery] = useState("");
|
|
4084
|
-
const shouldSearch = searchable ?? searchableFromChildren ?? Boolean(onSearch);
|
|
4085
|
-
const shouldFilter = filterOptions ?? !onSearch;
|
|
4086
|
-
const filteredRows = useMemo(() => {
|
|
4087
|
-
if (!query || !shouldFilter) return rows;
|
|
4088
|
-
const visibleRows = [];
|
|
4089
|
-
let pendingGroup;
|
|
4090
|
-
rows.forEach((row) => {
|
|
4091
|
-
if (row.type === "group") {
|
|
4092
|
-
pendingGroup = row;
|
|
4093
|
-
return;
|
|
4094
|
-
}
|
|
4095
|
-
if (row.type === "separator") {
|
|
4096
|
-
if (visibleRows.length > 0 && visibleRows[visibleRows.length - 1]?.type !== "separator") visibleRows.push(row);
|
|
4097
|
-
return;
|
|
4098
|
-
}
|
|
4099
|
-
if (!filter(row.option, query)) return;
|
|
4100
|
-
if (pendingGroup) {
|
|
4101
|
-
visibleRows.push(pendingGroup);
|
|
4102
|
-
pendingGroup = void 0;
|
|
4103
|
-
}
|
|
4104
|
-
visibleRows.push(row);
|
|
4105
|
-
});
|
|
4106
|
-
return visibleRows.filter((row, index, collection) => {
|
|
4107
|
-
if (row.type !== "separator") return true;
|
|
4108
|
-
return index > 0 && index < collection.length - 1 && collection[index - 1]?.type !== "separator";
|
|
4109
|
-
});
|
|
4110
|
-
}, [
|
|
4111
|
-
filter,
|
|
4112
|
-
query,
|
|
4113
|
-
rows,
|
|
4114
|
-
shouldFilter
|
|
4115
|
-
]);
|
|
4116
|
-
useEffect(() => {
|
|
4117
|
-
if (!isOpen) {
|
|
4118
|
-
setQuery("");
|
|
4119
|
-
return;
|
|
4120
|
-
}
|
|
4121
|
-
if (shouldSearch) onSearch?.(query);
|
|
4122
|
-
}, [
|
|
4123
|
-
isOpen,
|
|
4124
|
-
onSearch,
|
|
4125
|
-
query,
|
|
4126
|
-
shouldSearch
|
|
4127
|
-
]);
|
|
4128
|
-
return {
|
|
4129
|
-
query,
|
|
4130
|
-
setQuery,
|
|
4131
|
-
shouldSearch,
|
|
4132
|
-
filteredRows
|
|
4133
|
-
};
|
|
4134
|
-
};
|
|
4135
|
-
//#endregion
|
|
4136
|
-
//#region src/components/Select/internal/resolveSelectAccessibility.ts
|
|
4137
|
-
const resolveSelectAccessibility = ({ accessibilityLabel, accessibilityHint, label, description, error, invalid, placeholder, selectedLabel, hasFieldContext, fieldDescribedBy }) => {
|
|
4138
|
-
const descriptionText = typeof description === "string" || typeof description === "number" ? String(description) : void 0;
|
|
4139
|
-
const errorText = typeof error === "string" || typeof error === "number" ? String(error) : void 0;
|
|
4140
|
-
return {
|
|
4141
|
-
resolvedLabel: accessibilityLabel ?? label ?? selectedLabel ?? placeholder ?? "Select",
|
|
4142
|
-
resolvedHint: accessibilityHint ?? (invalid && errorText ? errorText : descriptionText ? descriptionText : hasFieldContext && fieldDescribedBy ? "Opens a list of options" : void 0),
|
|
4143
|
-
announce: (message) => {
|
|
4144
|
-
AccessibilityInfo.announceForAccessibility?.(message);
|
|
4145
|
-
}
|
|
4146
|
-
};
|
|
4147
|
-
};
|
|
4148
|
-
//#endregion
|
|
4149
4183
|
//#region src/components/Select/Trigger/SelectTrigger.styles.ts
|
|
4150
4184
|
const createTriggerStyles = (theme) => StyleSheet.create({
|
|
4151
4185
|
container: {
|
|
@@ -4401,174 +4435,174 @@ function SelectTrigger({ displayText, isPlaceholder, isOpen, size = "md", color
|
|
|
4401
4435
|
}
|
|
4402
4436
|
SelectTrigger.displayName = "SelectTrigger";
|
|
4403
4437
|
//#endregion
|
|
4404
|
-
//#region src/
|
|
4405
|
-
|
|
4406
|
-
const
|
|
4407
|
-
const
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4438
|
+
//#region src/hooks/behavior/select/useSelectCollection.ts
|
|
4439
|
+
const useSelectCollection = (children, optionsProp) => {
|
|
4440
|
+
const parsedChildren = useMemo(() => parseSelectChildren(children), [children]);
|
|
4441
|
+
const options = useMemo(() => [...optionsProp ?? [], ...parsedChildren.options], [optionsProp, parsedChildren.options]);
|
|
4442
|
+
return {
|
|
4443
|
+
options,
|
|
4444
|
+
rows: useMemo(() => {
|
|
4445
|
+
if (parsedChildren.rows.length > 0) return parsedChildren.rows;
|
|
4446
|
+
return options.map((option) => ({
|
|
4447
|
+
type: "item",
|
|
4448
|
+
key: `item-${option.value}`,
|
|
4449
|
+
option
|
|
4450
|
+
}));
|
|
4451
|
+
}, [options, parsedChildren.rows]),
|
|
4452
|
+
searchableFromChildren: parsedChildren.searchable,
|
|
4453
|
+
searchPlaceholderFromChildren: parsedChildren.searchPlaceholder,
|
|
4454
|
+
emptyFromChildren: parsedChildren.empty,
|
|
4455
|
+
loadingFromChildren: parsedChildren.loading
|
|
4456
|
+
};
|
|
4457
|
+
};
|
|
4458
|
+
//#endregion
|
|
4459
|
+
//#region src/hooks/behavior/select/useSelectSearch.ts
|
|
4460
|
+
const useSelectSearch = ({ rows, isOpen, searchable, searchableFromChildren, onSearch, filterOptions, filter = defaultSelectFilter }) => {
|
|
4461
|
+
const [query, setQuery] = useState("");
|
|
4462
|
+
const shouldSearch = searchable ?? searchableFromChildren ?? Boolean(onSearch);
|
|
4463
|
+
const shouldFilter = filterOptions ?? !onSearch;
|
|
4464
|
+
const filteredRows = useMemo(() => {
|
|
4465
|
+
if (!query || !shouldFilter) return rows;
|
|
4466
|
+
const visibleRows = [];
|
|
4467
|
+
let pendingGroup;
|
|
4468
|
+
rows.forEach((row) => {
|
|
4469
|
+
if (row.type === "group") {
|
|
4470
|
+
pendingGroup = row;
|
|
4427
4471
|
return;
|
|
4428
4472
|
}
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
});
|
|
4444
|
-
const closeAndFocusTrigger = useCallback(() => {
|
|
4445
|
-
closeDropdown();
|
|
4446
|
-
restoreFocusAfterClose();
|
|
4447
|
-
}, [closeDropdown, restoreFocusAfterClose]);
|
|
4448
|
-
const selectedValues = useMemo(() => {
|
|
4449
|
-
if (props.multiple) return Array.isArray(selectedValue) ? selectedValue : [];
|
|
4450
|
-
return typeof selectedValue === "string" && selectedValue ? [selectedValue] : [];
|
|
4451
|
-
}, [props.multiple, selectedValue]);
|
|
4452
|
-
const selectedOption = options.find((option) => selectedValues.includes(option.value));
|
|
4453
|
-
const selectedOptions = options.filter((option) => selectedValues.includes(option.value));
|
|
4454
|
-
const optionsByValue = useMemo(() => new Map(options.filter((option) => !option.disabled).map((option) => [option.value, option])), [options]);
|
|
4455
|
-
const { query, setQuery, shouldSearch, filteredRows } = useSelectSearch({
|
|
4456
|
-
rows,
|
|
4457
|
-
isOpen,
|
|
4458
|
-
searchable: searchableProp,
|
|
4459
|
-
searchableFromChildren,
|
|
4460
|
-
onSearch,
|
|
4461
|
-
filterOptions,
|
|
4462
|
-
filter
|
|
4463
|
-
});
|
|
4464
|
-
const selectedFocusValue = selectedValues.includes(selectedFocusValueRef.current ?? "") ? selectedFocusValueRef.current : selectedValues[0];
|
|
4465
|
-
const selectedRowIndex = Math.max(0, filteredRows.findIndex((row) => row.type === "item" && row.option.value === selectedFocusValue));
|
|
4466
|
-
const itemHeight = typeof virtual === "object" ? virtual.estimatedItemSize ?? 46 : 46;
|
|
4467
|
-
const displayValue = useMemo(() => {
|
|
4468
|
-
if (renderValue) return renderValue(props.multiple ? selectedOptions : selectedOption ?? null, {
|
|
4469
|
-
placeholder,
|
|
4470
|
-
multiple: Boolean(props.multiple)
|
|
4473
|
+
if (row.type === "separator") {
|
|
4474
|
+
if (visibleRows.length > 0 && visibleRows[visibleRows.length - 1]?.type !== "separator") visibleRows.push(row);
|
|
4475
|
+
return;
|
|
4476
|
+
}
|
|
4477
|
+
if (!filter(row.option, query)) return;
|
|
4478
|
+
if (pendingGroup) {
|
|
4479
|
+
visibleRows.push(pendingGroup);
|
|
4480
|
+
pendingGroup = void 0;
|
|
4481
|
+
}
|
|
4482
|
+
visibleRows.push(row);
|
|
4483
|
+
});
|
|
4484
|
+
return visibleRows.filter((row, index, collection) => {
|
|
4485
|
+
if (row.type !== "separator") return true;
|
|
4486
|
+
return index > 0 && index < collection.length - 1 && collection[index - 1]?.type !== "separator";
|
|
4471
4487
|
});
|
|
4472
|
-
if (props.multiple && selectedOptions.length > 0) {
|
|
4473
|
-
const visibleLabels = selectedOptions.slice(0, 2).map((option) => option.label);
|
|
4474
|
-
return selectedOptions.length > 2 ? `${visibleLabels.join(", ")} +${selectedOptions.length - 2}` : visibleLabels.join(", ");
|
|
4475
|
-
}
|
|
4476
|
-
return selectedOption?.label ?? placeholder;
|
|
4477
|
-
}, [
|
|
4478
|
-
placeholder,
|
|
4479
|
-
props.multiple,
|
|
4480
|
-
renderValue,
|
|
4481
|
-
selectedOption,
|
|
4482
|
-
selectedOptions
|
|
4483
|
-
]);
|
|
4484
|
-
const { resolvedLabel, resolvedHint, announce } = resolveSelectAccessibility({
|
|
4485
|
-
accessibilityLabel,
|
|
4486
|
-
accessibilityHint,
|
|
4487
|
-
label: !hasOwnField ? void 0 : label,
|
|
4488
|
-
description: !hasOwnField ? field?.description : description,
|
|
4489
|
-
error: !hasOwnField ? field?.error : error,
|
|
4490
|
-
invalid: isInvalid,
|
|
4491
|
-
placeholder,
|
|
4492
|
-
selectedLabel: selectedOption?.label,
|
|
4493
|
-
hasFieldContext: !hasOwnField && Boolean(field),
|
|
4494
|
-
fieldDescribedBy: field?.ariaDescribedBy
|
|
4495
|
-
});
|
|
4496
|
-
const hasValue = selectedValues.length > 0;
|
|
4497
|
-
const dismiss = useOverlayDismiss({
|
|
4498
|
-
id: overlayId,
|
|
4499
|
-
active: isOpen,
|
|
4500
|
-
closeOnOutsidePress: dismissOnBackdropPress,
|
|
4501
|
-
requestClose: closeAndFocusTrigger
|
|
4502
|
-
});
|
|
4503
|
-
const clearValue = () => {
|
|
4504
|
-
selectedFocusValueRef.current = void 0;
|
|
4505
|
-
selectValue("");
|
|
4506
|
-
announce("Selection cleared");
|
|
4507
|
-
};
|
|
4508
|
-
const selectOption = useCallback((option) => {
|
|
4509
|
-
if (option.disabled) return;
|
|
4510
|
-
const selectedBefore = selectedValues.includes(option.value);
|
|
4511
|
-
if (Boolean(props.multiple) && !selectedBefore && typeof maxSelected === "number" && selectedValues.length >= maxSelected) return;
|
|
4512
|
-
selectedFocusValueRef.current = option.value;
|
|
4513
|
-
selectValue(option.value);
|
|
4514
|
-
announce(`${option.label} selected`);
|
|
4515
4488
|
}, [
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
selectedValues
|
|
4489
|
+
filter,
|
|
4490
|
+
query,
|
|
4491
|
+
rows,
|
|
4492
|
+
shouldFilter
|
|
4521
4493
|
]);
|
|
4522
|
-
|
|
4523
|
-
if (!
|
|
4524
|
-
|
|
4525
|
-
const selectedGroupValues = enabledValues.filter((value) => selectedValues.includes(value));
|
|
4526
|
-
const outsideSelectedCount = selectedValues.filter((value) => !enabledValues.includes(value)).length;
|
|
4527
|
-
const maxSelectableGroupCount = typeof maxSelected === "number" ? Math.max(0, Math.min(enabledValues.length, maxSelected - outsideSelectedCount)) : enabledValues.length;
|
|
4528
|
-
if (selectedGroupValues.length > 0 && selectedGroupValues.length >= maxSelectableGroupCount) {
|
|
4529
|
-
selectedFocusValueRef.current = void 0;
|
|
4530
|
-
setSelectedValue(selectedValues.filter((value) => !enabledValues.includes(value)));
|
|
4531
|
-
announce("Group selection cleared");
|
|
4494
|
+
useEffect(() => {
|
|
4495
|
+
if (!isOpen) {
|
|
4496
|
+
setQuery("");
|
|
4532
4497
|
return;
|
|
4533
4498
|
}
|
|
4534
|
-
|
|
4535
|
-
for (const value of enabledValues) {
|
|
4536
|
-
if (nextValues.includes(value)) continue;
|
|
4537
|
-
if (typeof maxSelected === "number" && nextValues.length >= maxSelected) break;
|
|
4538
|
-
nextValues.push(value);
|
|
4539
|
-
}
|
|
4540
|
-
setSelectedValue(nextValues);
|
|
4541
|
-
selectedFocusValueRef.current = nextValues.at(-1);
|
|
4542
|
-
announce("Group selected");
|
|
4543
|
-
if (closeOnSelect) closeAndFocusTrigger();
|
|
4499
|
+
if (shouldSearch) onSearch?.(query);
|
|
4544
4500
|
}, [
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
optionsByValue,
|
|
4550
|
-
props.multiple,
|
|
4551
|
-
selectedValues,
|
|
4552
|
-
setSelectedValue
|
|
4501
|
+
isOpen,
|
|
4502
|
+
onSearch,
|
|
4503
|
+
query,
|
|
4504
|
+
shouldSearch
|
|
4553
4505
|
]);
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4506
|
+
return {
|
|
4507
|
+
query,
|
|
4508
|
+
setQuery,
|
|
4509
|
+
shouldSearch,
|
|
4510
|
+
filteredRows
|
|
4511
|
+
};
|
|
4512
|
+
};
|
|
4513
|
+
//#endregion
|
|
4514
|
+
//#region src/components/Select/internal/resolveSelectAccessibility.ts
|
|
4515
|
+
const resolveSelectAccessibility = ({ accessibilityLabel, accessibilityHint, label, description, error, invalid, placeholder, selectedLabel, hasFieldContext, fieldDescribedBy }) => {
|
|
4516
|
+
const descriptionText = typeof description === "string" || typeof description === "number" ? String(description) : void 0;
|
|
4517
|
+
const errorText = typeof error === "string" || typeof error === "number" ? String(error) : void 0;
|
|
4518
|
+
return {
|
|
4519
|
+
resolvedLabel: accessibilityLabel ?? label ?? selectedLabel ?? placeholder ?? "Select",
|
|
4520
|
+
resolvedHint: accessibilityHint ?? (invalid && errorText ? errorText : descriptionText ? descriptionText : hasFieldContext && fieldDescribedBy ? "Opens a list of options" : void 0),
|
|
4521
|
+
announce: (message) => {
|
|
4522
|
+
AccessibilityInfo.announceForAccessibility?.(message);
|
|
4523
|
+
}
|
|
4524
|
+
};
|
|
4525
|
+
};
|
|
4526
|
+
//#endregion
|
|
4527
|
+
//#region src/components/Select/Root/useSelectRootActions.ts
|
|
4528
|
+
function useSelectRootActions({ multiple, maxSelected, closeOnSelect, selectedValues, optionsByValue, selectedFocusValueRef, selectValue, setSelectedValue, announce, closeAndFocusTrigger }) {
|
|
4529
|
+
return {
|
|
4530
|
+
clearValue: useCallback(() => {
|
|
4531
|
+
selectedFocusValueRef.current = void 0;
|
|
4532
|
+
selectValue("");
|
|
4533
|
+
announce("Selection cleared");
|
|
4534
|
+
}, [
|
|
4535
|
+
announce,
|
|
4536
|
+
selectValue,
|
|
4537
|
+
selectedFocusValueRef
|
|
4538
|
+
]),
|
|
4539
|
+
selectOption: useCallback((option) => {
|
|
4540
|
+
if (option.disabled) return;
|
|
4541
|
+
const selectedBefore = selectedValues.includes(option.value);
|
|
4542
|
+
if (multiple && !selectedBefore && typeof maxSelected === "number" && selectedValues.length >= maxSelected) return;
|
|
4543
|
+
selectedFocusValueRef.current = option.value;
|
|
4544
|
+
selectValue(option.value);
|
|
4545
|
+
announce(`${option.label} selected`);
|
|
4546
|
+
}, [
|
|
4547
|
+
announce,
|
|
4548
|
+
maxSelected,
|
|
4549
|
+
multiple,
|
|
4550
|
+
selectValue,
|
|
4551
|
+
selectedFocusValueRef,
|
|
4552
|
+
selectedValues
|
|
4553
|
+
]),
|
|
4554
|
+
selectGroup: useCallback((values) => {
|
|
4555
|
+
if (!multiple || values.length === 0) return;
|
|
4556
|
+
const enabledValues = values.filter((value) => optionsByValue.has(value));
|
|
4557
|
+
const selectedGroupValues = enabledValues.filter((value) => selectedValues.includes(value));
|
|
4558
|
+
const outsideSelectedCount = selectedValues.filter((value) => !enabledValues.includes(value)).length;
|
|
4559
|
+
const maxSelectableGroupCount = typeof maxSelected === "number" ? Math.max(0, Math.min(enabledValues.length, maxSelected - outsideSelectedCount)) : enabledValues.length;
|
|
4560
|
+
if (selectedGroupValues.length > 0 && selectedGroupValues.length >= maxSelectableGroupCount) {
|
|
4561
|
+
selectedFocusValueRef.current = void 0;
|
|
4562
|
+
setSelectedValue(selectedValues.filter((value) => !enabledValues.includes(value)));
|
|
4563
|
+
announce("Group selection cleared");
|
|
4564
|
+
return;
|
|
4565
|
+
}
|
|
4566
|
+
const nextValues = [...selectedValues];
|
|
4567
|
+
for (const value of enabledValues) {
|
|
4568
|
+
if (nextValues.includes(value)) continue;
|
|
4569
|
+
if (typeof maxSelected === "number" && nextValues.length >= maxSelected) break;
|
|
4570
|
+
nextValues.push(value);
|
|
4571
|
+
}
|
|
4572
|
+
setSelectedValue(nextValues);
|
|
4573
|
+
selectedFocusValueRef.current = nextValues.at(-1);
|
|
4574
|
+
announce("Group selected");
|
|
4575
|
+
if (closeOnSelect) closeAndFocusTrigger();
|
|
4576
|
+
}, [
|
|
4577
|
+
announce,
|
|
4578
|
+
closeAndFocusTrigger,
|
|
4579
|
+
closeOnSelect,
|
|
4580
|
+
maxSelected,
|
|
4581
|
+
multiple,
|
|
4582
|
+
optionsByValue,
|
|
4583
|
+
selectedFocusValueRef,
|
|
4584
|
+
selectedValues,
|
|
4585
|
+
setSelectedValue
|
|
4586
|
+
])
|
|
4587
|
+
};
|
|
4588
|
+
}
|
|
4589
|
+
//#endregion
|
|
4590
|
+
//#region src/components/Select/Root/useSelectRootContextValue.ts
|
|
4591
|
+
function useSelectRootContextValue({ color, variant, isOpen, loading, searchable, multiple, maxSelected, virtual, resolvedLabel, resolvedPresentation, zIndex, position, onFloatingLayout, matchTriggerWidth, triggerWidth, selectedValues, selectedOptions, optionsByValue, filteredRows, selectedRowIndex, itemHeight, query, searchPlaceholder, searchInputRef, empty, loadingContent, closeContent, getOutsidePressProps, selectOption, selectGroup, setQuery, renderOption, contentStyle, optionStyle, searchStyle }) {
|
|
4592
|
+
return useMemo(() => ({
|
|
4558
4593
|
color,
|
|
4559
4594
|
variant,
|
|
4560
4595
|
isOpen,
|
|
4561
4596
|
loading,
|
|
4562
|
-
searchable
|
|
4563
|
-
multiple
|
|
4597
|
+
searchable,
|
|
4598
|
+
multiple,
|
|
4564
4599
|
maxSelected,
|
|
4565
4600
|
virtual,
|
|
4566
4601
|
resolvedLabel,
|
|
4567
4602
|
resolvedPresentation,
|
|
4568
|
-
zIndex
|
|
4603
|
+
zIndex,
|
|
4569
4604
|
position,
|
|
4570
4605
|
onFloatingLayout,
|
|
4571
|
-
dismissOnBackdropPress,
|
|
4572
4606
|
matchTriggerWidth,
|
|
4573
4607
|
triggerWidth,
|
|
4574
4608
|
selectedValues,
|
|
@@ -4578,11 +4612,12 @@ function SelectRoot(props) {
|
|
|
4578
4612
|
selectedRowIndex,
|
|
4579
4613
|
itemHeight,
|
|
4580
4614
|
query,
|
|
4581
|
-
searchPlaceholder
|
|
4615
|
+
searchPlaceholder,
|
|
4582
4616
|
searchInputRef,
|
|
4583
|
-
empty
|
|
4584
|
-
loadingContent
|
|
4585
|
-
closeContent
|
|
4617
|
+
empty,
|
|
4618
|
+
loadingContent,
|
|
4619
|
+
closeContent,
|
|
4620
|
+
getOutsidePressProps,
|
|
4586
4621
|
selectOption,
|
|
4587
4622
|
selectGroup,
|
|
4588
4623
|
setQuery,
|
|
@@ -4595,16 +4630,15 @@ function SelectRoot(props) {
|
|
|
4595
4630
|
variant,
|
|
4596
4631
|
isOpen,
|
|
4597
4632
|
loading,
|
|
4598
|
-
|
|
4599
|
-
|
|
4633
|
+
searchable,
|
|
4634
|
+
multiple,
|
|
4600
4635
|
maxSelected,
|
|
4601
4636
|
virtual,
|
|
4602
4637
|
resolvedLabel,
|
|
4603
4638
|
resolvedPresentation,
|
|
4604
|
-
|
|
4639
|
+
zIndex,
|
|
4605
4640
|
position,
|
|
4606
4641
|
onFloatingLayout,
|
|
4607
|
-
dismissOnBackdropPress,
|
|
4608
4642
|
matchTriggerWidth,
|
|
4609
4643
|
triggerWidth,
|
|
4610
4644
|
selectedValues,
|
|
@@ -4614,11 +4648,12 @@ function SelectRoot(props) {
|
|
|
4614
4648
|
selectedRowIndex,
|
|
4615
4649
|
itemHeight,
|
|
4616
4650
|
query,
|
|
4617
|
-
|
|
4651
|
+
searchPlaceholder,
|
|
4618
4652
|
searchInputRef,
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4653
|
+
empty,
|
|
4654
|
+
loadingContent,
|
|
4655
|
+
closeContent,
|
|
4656
|
+
getOutsidePressProps,
|
|
4622
4657
|
selectOption,
|
|
4623
4658
|
selectGroup,
|
|
4624
4659
|
setQuery,
|
|
@@ -4627,11 +4662,229 @@ function SelectRoot(props) {
|
|
|
4627
4662
|
optionStyle,
|
|
4628
4663
|
searchStyle
|
|
4629
4664
|
]);
|
|
4665
|
+
}
|
|
4666
|
+
//#endregion
|
|
4667
|
+
//#region src/components/Select/Root/useSelectRootDisplayValue.ts
|
|
4668
|
+
function useSelectRootDisplayValue({ multiple, placeholder, renderValue, selectedOption, selectedOptions, selectedValues }) {
|
|
4669
|
+
return useMemo(() => {
|
|
4670
|
+
if (renderValue) return renderValue({
|
|
4671
|
+
option: selectedOption,
|
|
4672
|
+
options: selectedOptions,
|
|
4673
|
+
value: selectedValues[0] ?? "",
|
|
4674
|
+
values: selectedValues,
|
|
4675
|
+
placeholder,
|
|
4676
|
+
multiple
|
|
4677
|
+
});
|
|
4678
|
+
if (multiple && selectedOptions.length > 0) {
|
|
4679
|
+
const visibleLabels = selectedOptions.slice(0, 2).map((option) => option.label);
|
|
4680
|
+
return selectedOptions.length > 2 ? `${visibleLabels.join(", ")} +${selectedOptions.length - 2}` : visibleLabels.join(", ");
|
|
4681
|
+
}
|
|
4682
|
+
return selectedOption?.label ?? placeholder;
|
|
4683
|
+
}, [
|
|
4684
|
+
multiple,
|
|
4685
|
+
placeholder,
|
|
4686
|
+
renderValue,
|
|
4687
|
+
selectedOption,
|
|
4688
|
+
selectedOptions,
|
|
4689
|
+
selectedValues
|
|
4690
|
+
]);
|
|
4691
|
+
}
|
|
4692
|
+
//#endregion
|
|
4693
|
+
//#region src/components/Select/Root/useSelectRootSelection.ts
|
|
4694
|
+
function useSelectRootSelection({ props, options, isDisabled }) {
|
|
4695
|
+
const selection = useSelect({
|
|
4696
|
+
value: props.multiple ? props.value : props.value === null ? "" : props.value,
|
|
4697
|
+
defaultValue: props.multiple ? props.defaultValue : props.defaultValue === null ? "" : props.defaultValue,
|
|
4698
|
+
onValueChange: (nextValue) => {
|
|
4699
|
+
if (props.multiple) {
|
|
4700
|
+
props.onValueChange?.(Array.isArray(nextValue) ? nextValue : nextValue ? [nextValue] : []);
|
|
4701
|
+
return;
|
|
4702
|
+
}
|
|
4703
|
+
props.onValueChange?.(Array.isArray(nextValue) ? nextValue[0] ?? null : nextValue === "" ? null : nextValue);
|
|
4704
|
+
},
|
|
4705
|
+
options,
|
|
4706
|
+
multiple: props.multiple,
|
|
4707
|
+
maxSelected: props.maxSelected,
|
|
4708
|
+
closeOnSelect: props.closeOnSelect,
|
|
4709
|
+
disabled: isDisabled,
|
|
4710
|
+
open: props.open,
|
|
4711
|
+
defaultOpen: props.defaultOpen,
|
|
4712
|
+
onOpenChange: props.onOpenChange
|
|
4713
|
+
});
|
|
4714
|
+
const optionsByValue = useMemo(() => new Map(options.filter((option) => !option.disabled).map((option) => [option.value, option])), [options]);
|
|
4715
|
+
return {
|
|
4716
|
+
...selection,
|
|
4717
|
+
optionsByValue
|
|
4718
|
+
};
|
|
4719
|
+
}
|
|
4720
|
+
//#endregion
|
|
4721
|
+
//#region src/components/Select/Root/useSelectRootState.tsx
|
|
4722
|
+
function useSelectRootState(props) {
|
|
4723
|
+
const { label, description, error, invalid = false, required = false, disabled = false, placeholder = "Select...", color = "primary", variant = "outline", size, clearable = false, searchable: searchableProp, searchPlaceholder, loading = false, loadingText = "Loading...", onSearch, filterOptions, filter, empty, startIcon, endIcon, prefix, suffix, renderValue, renderOption, closeOnSelect, maxSelected, presentation = "auto", placement = "bottom-start", offset = 8, matchTriggerWidth = false, dismissOnBackdropPress = true, virtual, options: optionsProp, children, style, triggerStyle, textStyle, contentStyle, optionStyle, searchStyle, accessibilityLabel, accessibilityHint, testID } = props;
|
|
4724
|
+
const field = useFormFieldContext();
|
|
4725
|
+
const overlayId = useId();
|
|
4726
|
+
const hasOwnField = Boolean(label || description || error);
|
|
4727
|
+
const [triggerWidth, setTriggerWidth] = useState();
|
|
4728
|
+
const triggerRef = useRef(null);
|
|
4729
|
+
const searchInputRef = useRef(null);
|
|
4730
|
+
const selectedFocusValueRef = useRef(void 0);
|
|
4731
|
+
const resolvedPresentation = useOverlayPresentation(presentation);
|
|
4732
|
+
const { position, onFloatingLayout } = useNativeFloatingPosition(placement, offset);
|
|
4733
|
+
const { options, rows, searchableFromChildren, searchPlaceholderFromChildren, emptyFromChildren, loadingFromChildren } = useSelectCollection(children, optionsProp);
|
|
4734
|
+
const resolvedSize = size ?? field?.size ?? "md";
|
|
4735
|
+
const isInvalid = invalid || Boolean(error) || !hasOwnField && Boolean(field?.invalid);
|
|
4736
|
+
const isDisabled = disabled || !hasOwnField && Boolean(field?.disabled);
|
|
4737
|
+
const isRequired = required || !hasOwnField && Boolean(field?.required);
|
|
4738
|
+
const { setSelectedValue, selectedValues, selectedOption, selectedOptions, optionsByValue, isOpen, openDropdown, closeDropdown, selectValue } = useSelectRootSelection({
|
|
4739
|
+
props,
|
|
4740
|
+
options,
|
|
4741
|
+
isDisabled
|
|
4742
|
+
});
|
|
4743
|
+
const { restoreFocusAfterClose } = useOverlayFocusRestore({
|
|
4744
|
+
active: isOpen,
|
|
4745
|
+
triggerRef
|
|
4746
|
+
});
|
|
4747
|
+
const closeAndFocusTrigger = useCallback(() => {
|
|
4748
|
+
closeDropdown();
|
|
4749
|
+
restoreFocusAfterClose();
|
|
4750
|
+
}, [closeDropdown, restoreFocusAfterClose]);
|
|
4751
|
+
const { query, setQuery, shouldSearch, filteredRows } = useSelectSearch({
|
|
4752
|
+
rows,
|
|
4753
|
+
isOpen,
|
|
4754
|
+
searchable: searchableProp,
|
|
4755
|
+
searchableFromChildren,
|
|
4756
|
+
onSearch,
|
|
4757
|
+
filterOptions,
|
|
4758
|
+
filter
|
|
4759
|
+
});
|
|
4760
|
+
const selectedFocusValue = selectedValues.includes(selectedFocusValueRef.current ?? "") ? selectedFocusValueRef.current : selectedValues[0];
|
|
4761
|
+
const selectedRowIndex = Math.max(0, filteredRows.findIndex((row) => row.type === "item" && row.option.value === selectedFocusValue));
|
|
4762
|
+
const itemHeight = typeof virtual === "object" ? virtual.estimatedItemSize ?? 46 : 46;
|
|
4763
|
+
const displayValue = useSelectRootDisplayValue({
|
|
4764
|
+
multiple: Boolean(props.multiple),
|
|
4765
|
+
placeholder,
|
|
4766
|
+
renderValue,
|
|
4767
|
+
selectedOption,
|
|
4768
|
+
selectedOptions,
|
|
4769
|
+
selectedValues
|
|
4770
|
+
});
|
|
4771
|
+
const { resolvedLabel, resolvedHint, announce } = resolveSelectAccessibility({
|
|
4772
|
+
accessibilityLabel,
|
|
4773
|
+
accessibilityHint,
|
|
4774
|
+
label: !hasOwnField ? void 0 : label,
|
|
4775
|
+
description: !hasOwnField ? field?.description : description,
|
|
4776
|
+
error: !hasOwnField ? field?.error : error,
|
|
4777
|
+
invalid: isInvalid,
|
|
4778
|
+
placeholder,
|
|
4779
|
+
selectedLabel: selectedOption?.label,
|
|
4780
|
+
hasFieldContext: !hasOwnField && Boolean(field),
|
|
4781
|
+
fieldDescribedBy: field?.ariaDescribedBy
|
|
4782
|
+
});
|
|
4783
|
+
const hasValue = selectedValues.length > 0;
|
|
4784
|
+
const dismiss = useOverlayDismiss({
|
|
4785
|
+
id: overlayId,
|
|
4786
|
+
active: isOpen,
|
|
4787
|
+
closeOnOutsidePress: dismissOnBackdropPress,
|
|
4788
|
+
requestClose: closeAndFocusTrigger
|
|
4789
|
+
});
|
|
4790
|
+
const { clearValue, selectOption, selectGroup } = useSelectRootActions({
|
|
4791
|
+
multiple: Boolean(props.multiple),
|
|
4792
|
+
maxSelected,
|
|
4793
|
+
closeOnSelect,
|
|
4794
|
+
selectedValues,
|
|
4795
|
+
optionsByValue,
|
|
4796
|
+
selectedFocusValueRef,
|
|
4797
|
+
selectValue,
|
|
4798
|
+
setSelectedValue,
|
|
4799
|
+
announce,
|
|
4800
|
+
closeAndFocusTrigger
|
|
4801
|
+
});
|
|
4802
|
+
const resolvedSearchPlaceholder = searchPlaceholder ?? searchPlaceholderFromChildren ?? "Search...";
|
|
4803
|
+
const resolvedEmpty = empty ?? emptyFromChildren ?? "Nothing found";
|
|
4804
|
+
const resolvedLoadingContent = loadingFromChildren ?? loadingText;
|
|
4805
|
+
return {
|
|
4806
|
+
contextValue: useSelectRootContextValue({
|
|
4807
|
+
color,
|
|
4808
|
+
variant,
|
|
4809
|
+
isOpen,
|
|
4810
|
+
loading,
|
|
4811
|
+
searchable: shouldSearch,
|
|
4812
|
+
multiple: Boolean(props.multiple),
|
|
4813
|
+
maxSelected,
|
|
4814
|
+
virtual,
|
|
4815
|
+
resolvedLabel,
|
|
4816
|
+
resolvedPresentation,
|
|
4817
|
+
zIndex: dismiss.zIndex,
|
|
4818
|
+
position,
|
|
4819
|
+
onFloatingLayout,
|
|
4820
|
+
matchTriggerWidth,
|
|
4821
|
+
triggerWidth,
|
|
4822
|
+
selectedValues,
|
|
4823
|
+
selectedOptions,
|
|
4824
|
+
optionsByValue,
|
|
4825
|
+
filteredRows,
|
|
4826
|
+
selectedRowIndex,
|
|
4827
|
+
itemHeight,
|
|
4828
|
+
query,
|
|
4829
|
+
searchPlaceholder: resolvedSearchPlaceholder,
|
|
4830
|
+
searchInputRef,
|
|
4831
|
+
empty: resolvedEmpty,
|
|
4832
|
+
loadingContent: resolvedLoadingContent,
|
|
4833
|
+
closeContent: dismiss.requestClose,
|
|
4834
|
+
getOutsidePressProps: dismiss.getOutsidePressProps,
|
|
4835
|
+
selectOption,
|
|
4836
|
+
selectGroup,
|
|
4837
|
+
setQuery,
|
|
4838
|
+
renderOption,
|
|
4839
|
+
contentStyle,
|
|
4840
|
+
optionStyle,
|
|
4841
|
+
searchStyle
|
|
4842
|
+
}),
|
|
4843
|
+
displayValue,
|
|
4844
|
+
field,
|
|
4845
|
+
hasOwnField,
|
|
4846
|
+
hasValue,
|
|
4847
|
+
isDisabled,
|
|
4848
|
+
isInvalid,
|
|
4849
|
+
isOpen,
|
|
4850
|
+
isRequired,
|
|
4851
|
+
clearValue,
|
|
4852
|
+
openDropdown,
|
|
4853
|
+
resolvedHint,
|
|
4854
|
+
resolvedLabel,
|
|
4855
|
+
resolvedSize,
|
|
4856
|
+
setTriggerWidth,
|
|
4857
|
+
triggerRef,
|
|
4858
|
+
controlProps: {
|
|
4859
|
+
clearable,
|
|
4860
|
+
color,
|
|
4861
|
+
endIcon,
|
|
4862
|
+
loading,
|
|
4863
|
+
prefix,
|
|
4864
|
+
startIcon,
|
|
4865
|
+
suffix,
|
|
4866
|
+
testID,
|
|
4867
|
+
textStyle,
|
|
4868
|
+
triggerStyle,
|
|
4869
|
+
variant
|
|
4870
|
+
},
|
|
4871
|
+
formFieldProps: {
|
|
4872
|
+
description,
|
|
4873
|
+
error,
|
|
4874
|
+
label,
|
|
4875
|
+
style
|
|
4876
|
+
}
|
|
4877
|
+
};
|
|
4878
|
+
}
|
|
4879
|
+
//#endregion
|
|
4880
|
+
//#region src/components/Select/Root/SelectRoot.tsx
|
|
4881
|
+
function SelectRoot(props) {
|
|
4882
|
+
const { contextValue, controlProps, displayValue, field, formFieldProps, hasOwnField, hasValue, isDisabled, isInvalid, isOpen, isRequired, resolvedHint, resolvedLabel, resolvedSize, triggerRef, clearValue, openDropdown, setTriggerWidth } = useSelectRootState(props);
|
|
4630
4883
|
const control = /* @__PURE__ */ jsx(SelectContext.Provider, {
|
|
4631
4884
|
value: contextValue,
|
|
4632
4885
|
children: /* @__PURE__ */ jsxs(View, {
|
|
4633
4886
|
ref: triggerRef,
|
|
4634
|
-
testID,
|
|
4887
|
+
testID: controlProps.testID,
|
|
4635
4888
|
onLayout: (event) => setTriggerWidth(event.nativeEvent.layout.width),
|
|
4636
4889
|
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
4637
4890
|
displayText: displayValue,
|
|
@@ -4639,24 +4892,24 @@ function SelectRoot(props) {
|
|
|
4639
4892
|
isOpen,
|
|
4640
4893
|
hasValue,
|
|
4641
4894
|
size: resolvedSize,
|
|
4642
|
-
color,
|
|
4643
|
-
variant,
|
|
4895
|
+
color: controlProps.color,
|
|
4896
|
+
variant: controlProps.variant,
|
|
4644
4897
|
disabled: isDisabled,
|
|
4645
4898
|
required: isRequired,
|
|
4646
4899
|
hasError: isInvalid,
|
|
4647
|
-
loading,
|
|
4648
|
-
clearable,
|
|
4649
|
-
startIcon,
|
|
4650
|
-
endIcon,
|
|
4651
|
-
prefix,
|
|
4652
|
-
suffix,
|
|
4900
|
+
loading: controlProps.loading,
|
|
4901
|
+
clearable: controlProps.clearable,
|
|
4902
|
+
startIcon: controlProps.startIcon,
|
|
4903
|
+
endIcon: controlProps.endIcon,
|
|
4904
|
+
prefix: controlProps.prefix,
|
|
4905
|
+
suffix: controlProps.suffix,
|
|
4653
4906
|
nativeID: !hasOwnField ? field?.controlId : void 0,
|
|
4654
4907
|
accessibilityLabel: resolvedLabel,
|
|
4655
4908
|
accessibilityHint: resolvedHint,
|
|
4656
4909
|
accessibilityLabelledBy: !hasOwnField ? field?.labelId : void 0,
|
|
4657
4910
|
ariaDescribedBy: !hasOwnField ? field?.ariaDescribedBy : void 0,
|
|
4658
|
-
triggerStyle,
|
|
4659
|
-
textStyle,
|
|
4911
|
+
triggerStyle: controlProps.triggerStyle,
|
|
4912
|
+
textStyle: controlProps.textStyle,
|
|
4660
4913
|
onPress: openDropdown,
|
|
4661
4914
|
onClear: clearValue
|
|
4662
4915
|
}), /* @__PURE__ */ jsx(SelectContentSurface, {})]
|
|
@@ -4664,14 +4917,14 @@ function SelectRoot(props) {
|
|
|
4664
4917
|
});
|
|
4665
4918
|
if (!hasOwnField && field) return control;
|
|
4666
4919
|
return /* @__PURE__ */ jsx(FormField, {
|
|
4667
|
-
label,
|
|
4668
|
-
description,
|
|
4669
|
-
error,
|
|
4920
|
+
label: formFieldProps.label,
|
|
4921
|
+
description: formFieldProps.description,
|
|
4922
|
+
error: formFieldProps.error,
|
|
4670
4923
|
required: isRequired,
|
|
4671
4924
|
disabled: isDisabled,
|
|
4672
4925
|
invalid: isInvalid,
|
|
4673
4926
|
size: resolvedSize,
|
|
4674
|
-
style,
|
|
4927
|
+
style: formFieldProps.style,
|
|
4675
4928
|
children: control
|
|
4676
4929
|
});
|
|
4677
4930
|
}
|
|
@@ -5570,8 +5823,8 @@ const TooltipContent = ({ children, forceMount = false, withArrow = false, style
|
|
|
5570
5823
|
animationType: "fade",
|
|
5571
5824
|
onRequestClose: tooltip.requestClose,
|
|
5572
5825
|
children: /* @__PURE__ */ jsx(Pressable, {
|
|
5826
|
+
...tooltip.getOutsidePressProps({ accessibilityLabel: "Close tooltip" }),
|
|
5573
5827
|
style: styles.overlay,
|
|
5574
|
-
onPress: tooltip.requestOutsideClose,
|
|
5575
5828
|
children: bubble
|
|
5576
5829
|
})
|
|
5577
5830
|
});
|
|
@@ -5669,15 +5922,15 @@ const TooltipRoot = ({ children, open: openProp, defaultOpen = false, onOpenChan
|
|
|
5669
5922
|
hide,
|
|
5670
5923
|
zIndex: dismiss.zIndex,
|
|
5671
5924
|
requestClose: dismiss.requestClose,
|
|
5672
|
-
|
|
5925
|
+
getOutsidePressProps: dismiss.getOutsidePressProps,
|
|
5673
5926
|
onFloatingLayout
|
|
5674
5927
|
}), [
|
|
5675
5928
|
arrowPosition,
|
|
5676
5929
|
contentId,
|
|
5677
5930
|
disabled,
|
|
5678
5931
|
dismiss.zIndex,
|
|
5932
|
+
dismiss.getOutsidePressProps,
|
|
5679
5933
|
dismiss.requestClose,
|
|
5680
|
-
dismiss.requestOutsideClose,
|
|
5681
5934
|
hide,
|
|
5682
5935
|
open,
|
|
5683
5936
|
resolvedPlacement,
|
|
@@ -5724,11 +5977,6 @@ const Tooltip = Object.assign(TooltipRoot, {
|
|
|
5724
5977
|
});
|
|
5725
5978
|
Tooltip.displayName = "Tooltip";
|
|
5726
5979
|
//#endregion
|
|
5727
|
-
//#region src/utils/devWarning.ts
|
|
5728
|
-
const devWarning = (condition, message) => {
|
|
5729
|
-
if ((typeof __DEV__ === "undefined" || __DEV__) && !condition) console.warn(message);
|
|
5730
|
-
};
|
|
5731
|
-
//#endregion
|
|
5732
5980
|
//#region src/primitives/Button/Button.styles.ts
|
|
5733
5981
|
const fontWeight = (value) => value;
|
|
5734
5982
|
const createStyles$2 = (theme) => StyleSheet.create({
|
|
@@ -5747,9 +5995,14 @@ const createStyles$2 = (theme) => StyleSheet.create({
|
|
|
5747
5995
|
fontFamily: theme.tokens.typography.family.regular,
|
|
5748
5996
|
fontWeight: fontWeight(theme.tokens.typography.weight.regular),
|
|
5749
5997
|
lineHeight: theme.tokens.typography.lineHeight.md,
|
|
5998
|
+
textAlign: "center",
|
|
5750
5999
|
color: theme.components.button.primary.solid.default.fg
|
|
5751
6000
|
},
|
|
5752
|
-
labelSlot: {
|
|
6001
|
+
labelSlot: {
|
|
6002
|
+
position: "relative",
|
|
6003
|
+
alignItems: "center",
|
|
6004
|
+
justifyContent: "center"
|
|
6005
|
+
},
|
|
5753
6006
|
labelMeasure: {
|
|
5754
6007
|
position: "absolute",
|
|
5755
6008
|
opacity: 0
|
|
@@ -5796,22 +6049,22 @@ const createStyles$2 = (theme) => StyleSheet.create({
|
|
|
5796
6049
|
//#region src/primitives/Button/Button.tsx
|
|
5797
6050
|
const sizeMap = {
|
|
5798
6051
|
sm: {
|
|
5799
|
-
px:
|
|
5800
|
-
py:
|
|
6052
|
+
px: 16,
|
|
6053
|
+
py: 6,
|
|
5801
6054
|
height: 36,
|
|
5802
6055
|
fontSize: 12,
|
|
5803
6056
|
iconSize: 16
|
|
5804
6057
|
},
|
|
5805
6058
|
md: {
|
|
5806
|
-
px:
|
|
5807
|
-
py:
|
|
6059
|
+
px: 24,
|
|
6060
|
+
py: 8,
|
|
5808
6061
|
height: 44,
|
|
5809
6062
|
fontSize: 14,
|
|
5810
6063
|
iconSize: 20
|
|
5811
6064
|
},
|
|
5812
6065
|
lg: {
|
|
5813
|
-
px:
|
|
5814
|
-
py:
|
|
6066
|
+
px: 32,
|
|
6067
|
+
py: 10,
|
|
5815
6068
|
height: 52,
|
|
5816
6069
|
fontSize: 16,
|
|
5817
6070
|
iconSize: 24
|
|
@@ -5901,12 +6154,11 @@ function Button({ children, color = "primary", appearance = "solid", shape = "pi
|
|
|
5901
6154
|
}),
|
|
5902
6155
|
!loading && iconStart && renderIcon(iconStart, contentColor),
|
|
5903
6156
|
content && !iconOnly && /* @__PURE__ */ jsxs(View, {
|
|
5904
|
-
style: styles.labelSlot,
|
|
6157
|
+
style: [styles.labelSlot, labelWidth > 0 && { minWidth: labelWidth }],
|
|
5905
6158
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
5906
6159
|
onLayout: handleLabelLayout,
|
|
5907
6160
|
style: [
|
|
5908
6161
|
styles.text,
|
|
5909
|
-
labelWidth > 0 && { minWidth: labelWidth },
|
|
5910
6162
|
{
|
|
5911
6163
|
fontSize: config.fontSize,
|
|
5912
6164
|
color: contentColor
|