@vellira-ui/react-native 2.57.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 +1538 -965
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +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, createOverlayManagerStore, createOverlayZIndexPolicy, createRetainedResourceRegistry, deferOverlayFocusRestore, getCompoundSlot, markCompoundSlot, resolveOverlayPresentation } from "@vellira-ui/core";
|
|
4
5
|
import { darkTheme, highContrastTheme, lightTheme } from "@vellira-ui/tokens";
|
|
5
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
//#region src/theme/fontWeight.ts
|
|
@@ -23,314 +24,278 @@ function toNativeFontWeight(weight) {
|
|
|
23
24
|
return normalizedWeight;
|
|
24
25
|
}
|
|
25
26
|
//#endregion
|
|
26
|
-
//#region src/managers/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
function createPlacement(side, align) {
|
|
38
|
-
return align === "center" ? side : `${side}-${align}`;
|
|
39
|
-
}
|
|
40
|
-
function getOppositeSide(side) {
|
|
41
|
-
switch (side) {
|
|
42
|
-
case "top": return "bottom";
|
|
43
|
-
case "right": return "left";
|
|
44
|
-
case "bottom": return "top";
|
|
45
|
-
case "left": return "right";
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function computeBasePosition({ reference, floating, side, align, offset }) {
|
|
49
|
-
const referenceCenterX = reference.x + reference.width / 2;
|
|
50
|
-
const referenceCenterY = reference.y + reference.height / 2;
|
|
51
|
-
const alignedLeft = align === "start" ? reference.x : align === "end" ? reference.x + reference.width - floating.width : referenceCenterX - floating.width / 2;
|
|
52
|
-
const alignedTop = align === "start" ? reference.y : align === "end" ? reference.y + reference.height - floating.height : referenceCenterY - floating.height / 2;
|
|
53
|
-
switch (side) {
|
|
54
|
-
case "top": return {
|
|
55
|
-
top: reference.y - floating.height - offset,
|
|
56
|
-
left: alignedLeft
|
|
57
|
-
};
|
|
58
|
-
case "right": return {
|
|
59
|
-
top: alignedTop,
|
|
60
|
-
left: reference.x + reference.width + offset
|
|
61
|
-
};
|
|
62
|
-
case "bottom": return {
|
|
63
|
-
top: reference.y + reference.height + offset,
|
|
64
|
-
left: alignedLeft
|
|
65
|
-
};
|
|
66
|
-
case "left": return {
|
|
67
|
-
top: alignedTop,
|
|
68
|
-
left: reference.x - floating.width - offset
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
function getMainAxisOverflow({ side, position, floating, boundary, padding }) {
|
|
73
|
-
switch (side) {
|
|
74
|
-
case "top": return padding - position.top;
|
|
75
|
-
case "right": return position.left + floating.width + padding - boundary.width;
|
|
76
|
-
case "bottom": return position.top + floating.height + padding - boundary.height;
|
|
77
|
-
case "left": return padding - position.left;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function computeFloatingPosition({ reference, floating, boundary, placement, offset = 8, padding = 12, arrowPadding = 16, flip = true, shift = true }) {
|
|
81
|
-
const parsed = parsePlacement(placement);
|
|
82
|
-
let resolvedSide = parsed.side;
|
|
83
|
-
let position = computeBasePosition({
|
|
84
|
-
reference,
|
|
85
|
-
floating,
|
|
86
|
-
side: resolvedSide,
|
|
87
|
-
align: parsed.align,
|
|
88
|
-
offset
|
|
27
|
+
//#region src/managers/OverlayManager/NativeOverlayManager.ts
|
|
28
|
+
const nativeOverlayZIndexPolicy = createOverlayZIndexPolicy({
|
|
29
|
+
defaultLevel: "modal",
|
|
30
|
+
levels: { modal: lightTheme.tokens.zIndex.modal }
|
|
31
|
+
});
|
|
32
|
+
const nativeOverlayDiagnostics = createConsoleOverlayDiagnostics("NativeOverlayManager");
|
|
33
|
+
const createNativeOverlayManager = () => {
|
|
34
|
+
const store = createOverlayManagerStore({
|
|
35
|
+
diagnostics: nativeOverlayDiagnostics,
|
|
36
|
+
policy: nativeOverlayZIndexPolicy
|
|
89
37
|
});
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
boundary,
|
|
110
|
-
padding
|
|
111
|
-
}) <= 0) {
|
|
112
|
-
resolvedSide = oppositeSide;
|
|
113
|
-
position = oppositePosition;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (shift) position = {
|
|
117
|
-
top: clamp(position.top, padding, boundary.height - floating.height - padding),
|
|
118
|
-
left: clamp(position.left, padding, boundary.width - floating.width - padding)
|
|
38
|
+
const dismissHandlers = /* @__PURE__ */ new Map();
|
|
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;
|
|
119
57
|
};
|
|
120
|
-
const referenceCenterX = reference.x + reference.width / 2;
|
|
121
|
-
const referenceCenterY = reference.y + reference.height / 2;
|
|
122
|
-
const arrowPosition = resolvedSide === "top" || resolvedSide === "bottom" ? { left: clamp(referenceCenterX - position.left, arrowPadding, floating.width - arrowPadding) } : { top: clamp(referenceCenterY - position.top, arrowPadding, floating.height - arrowPadding) };
|
|
123
58
|
return {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
//#endregion
|
|
130
|
-
//#region src/managers/FloatingManager/useNativeFloatingPosition.ts
|
|
131
|
-
function useNativeFloatingPosition(placement = "top", offset = 8) {
|
|
132
|
-
const [result, setResult] = useState({
|
|
133
|
-
position: {
|
|
134
|
-
top: 0,
|
|
135
|
-
left: 0
|
|
59
|
+
register(id) {
|
|
60
|
+
const entry = store.register({ id });
|
|
61
|
+
return toNativeEntry(entry.id);
|
|
136
62
|
},
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const commitPosition = (containerX, containerY, containerWidth, containerHeight) => {
|
|
163
|
-
const nextResult = computeFloatingPosition({
|
|
164
|
-
reference: {
|
|
165
|
-
x: x - containerX,
|
|
166
|
-
y: y - containerY,
|
|
167
|
-
width,
|
|
168
|
-
height
|
|
169
|
-
},
|
|
170
|
-
floating: measuredSize,
|
|
171
|
-
boundary: {
|
|
172
|
-
width: containerWidth,
|
|
173
|
-
height: containerHeight
|
|
174
|
-
},
|
|
175
|
-
placement,
|
|
176
|
-
offset
|
|
177
|
-
});
|
|
178
|
-
setResult(nextResult);
|
|
63
|
+
unregister(id) {
|
|
64
|
+
dismissHandlers.delete(id);
|
|
65
|
+
outsidePressHandlers.delete(id);
|
|
66
|
+
store.unregister(id);
|
|
67
|
+
},
|
|
68
|
+
getSnapshot() {
|
|
69
|
+
return getNativeSnapshot();
|
|
70
|
+
},
|
|
71
|
+
isTop(id) {
|
|
72
|
+
return store.isTopmost(id);
|
|
73
|
+
},
|
|
74
|
+
getTop() {
|
|
75
|
+
return getNativeSnapshot().topmost;
|
|
76
|
+
},
|
|
77
|
+
getZIndex(id) {
|
|
78
|
+
return store.getZIndex(id) ?? nativeOverlayZIndexPolicy.levels[nativeOverlayZIndexPolicy.defaultLevel];
|
|
79
|
+
},
|
|
80
|
+
subscribe(listener) {
|
|
81
|
+
return store.subscribe(listener);
|
|
82
|
+
},
|
|
83
|
+
registerDismissHandler(id, handler) {
|
|
84
|
+
dismissHandlers.set(id, handler);
|
|
85
|
+
return () => {
|
|
86
|
+
if (dismissHandlers.get(id) !== handler) return;
|
|
87
|
+
dismissHandlers.delete(id);
|
|
179
88
|
};
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
89
|
+
},
|
|
90
|
+
registerOutsidePressHandler(id, handler) {
|
|
91
|
+
outsidePressHandlers.set(id, handler);
|
|
92
|
+
return () => {
|
|
93
|
+
if (outsidePressHandlers.get(id) !== handler) return;
|
|
94
|
+
outsidePressHandlers.delete(id);
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
dispatchTopDismiss() {
|
|
98
|
+
const top = this.getTop();
|
|
99
|
+
if (!top) return false;
|
|
100
|
+
const handler = dismissHandlers.get(top.id);
|
|
101
|
+
if (!handler) return false;
|
|
102
|
+
return handler();
|
|
103
|
+
},
|
|
104
|
+
dispatchTopOutsidePress() {
|
|
105
|
+
const top = this.getTop();
|
|
106
|
+
if (!top) return false;
|
|
107
|
+
const handler = outsidePressHandlers.get(top.id);
|
|
108
|
+
if (!handler) return false;
|
|
109
|
+
return handler();
|
|
110
|
+
},
|
|
111
|
+
clear() {
|
|
112
|
+
dismissHandlers.clear();
|
|
113
|
+
outsidePressHandlers.clear();
|
|
114
|
+
store.clear();
|
|
115
|
+
}
|
|
205
116
|
};
|
|
206
|
-
}
|
|
207
|
-
//#endregion
|
|
208
|
-
//#region src/managers/OverlayManager/NativeOverlayManager.ts
|
|
209
|
-
const BASE_LAYER = 1e3;
|
|
210
|
-
const LAYER_STEP = 10;
|
|
211
|
-
let stack = [];
|
|
212
|
-
const nativeOverlayManager = {
|
|
213
|
-
register(id) {
|
|
214
|
-
stack = stack.filter((item) => item.id !== id);
|
|
215
|
-
const entry = {
|
|
216
|
-
id,
|
|
217
|
-
layer: BASE_LAYER + stack.length * LAYER_STEP
|
|
218
|
-
};
|
|
219
|
-
stack.push(entry);
|
|
220
|
-
return entry;
|
|
221
|
-
},
|
|
222
|
-
unregister(id) {
|
|
223
|
-
stack = stack.filter((item) => item.id !== id);
|
|
224
|
-
},
|
|
225
|
-
isTop(id) {
|
|
226
|
-
return stack.at(-1)?.id === id;
|
|
227
|
-
},
|
|
228
|
-
getTop() {
|
|
229
|
-
return stack.at(-1);
|
|
230
|
-
},
|
|
231
|
-
getLayer(id) {
|
|
232
|
-
return stack.find((item) => item.id === id)?.layer ?? BASE_LAYER;
|
|
233
|
-
}
|
|
234
117
|
};
|
|
118
|
+
const nativeOverlayManager = createNativeOverlayManager();
|
|
235
119
|
//#endregion
|
|
236
|
-
//#region src/managers/OverlayManager/
|
|
237
|
-
const
|
|
238
|
-
|
|
120
|
+
//#region src/managers/OverlayManager/OverlayManagerProvider.tsx
|
|
121
|
+
const NativeOverlayManagerContext = createContext(null);
|
|
122
|
+
const useNativeOverlayManager = () => useContext(NativeOverlayManagerContext) ?? nativeOverlayManager;
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/hooks/behavior/overlay/useOverlayRegistration.ts
|
|
125
|
+
const useOverlayRegistration = ({ active, id }) => {
|
|
126
|
+
const nativeOverlayManager = useNativeOverlayManager();
|
|
127
|
+
const snapshot = useSyncExternalStore(nativeOverlayManager.subscribe, nativeOverlayManager.getSnapshot, nativeOverlayManager.getSnapshot);
|
|
239
128
|
useEffect(() => {
|
|
240
|
-
if (!
|
|
241
|
-
|
|
242
|
-
setLayer(entry.layer);
|
|
129
|
+
if (!active) return;
|
|
130
|
+
nativeOverlayManager.register(id);
|
|
243
131
|
return () => {
|
|
244
132
|
nativeOverlayManager.unregister(id);
|
|
245
133
|
};
|
|
246
|
-
}, [
|
|
134
|
+
}, [
|
|
135
|
+
active,
|
|
136
|
+
id,
|
|
137
|
+
nativeOverlayManager
|
|
138
|
+
]);
|
|
139
|
+
const isTopOverlay = useCallback(() => nativeOverlayManager.isTop(id), [id, nativeOverlayManager]);
|
|
247
140
|
return {
|
|
248
|
-
|
|
249
|
-
|
|
141
|
+
zIndex: snapshot.registry.get(id)?.zIndex ?? nativeOverlayManager.getZIndex(id),
|
|
142
|
+
isTopmost: snapshot.topmost?.id === id,
|
|
143
|
+
isTopOverlay
|
|
250
144
|
};
|
|
251
145
|
};
|
|
252
146
|
//#endregion
|
|
253
|
-
//#region src/hooks/behavior/overlay/useOverlayStack.ts
|
|
254
|
-
const useOverlayStack = ({ active, id }) => useNativeOverlayRegistration({
|
|
255
|
-
id,
|
|
256
|
-
visible: active
|
|
257
|
-
});
|
|
258
|
-
//#endregion
|
|
259
147
|
//#region src/hooks/behavior/overlay/useOverlayDismiss.ts
|
|
260
|
-
const
|
|
261
|
-
|
|
148
|
+
const dismissListeners = createRetainedResourceRegistry((manager) => {
|
|
149
|
+
if (Platform.OS === "web") {
|
|
150
|
+
const handleKeyDown = (event) => {
|
|
151
|
+
if (event.key !== "Escape") return;
|
|
152
|
+
manager.dispatchTopDismiss();
|
|
153
|
+
};
|
|
154
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
155
|
+
return () => {
|
|
156
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const subscription = BackHandler.addEventListener("hardwareBackPress", () => manager.dispatchTopDismiss());
|
|
160
|
+
return () => {
|
|
161
|
+
subscription.remove();
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
function retainDismissListener(manager) {
|
|
165
|
+
return dismissListeners.retain(manager);
|
|
166
|
+
}
|
|
167
|
+
const useOverlayDismiss = ({ active, closeOnEscape = true, closeOnOutsidePress = true, id, requestClose, requestOutsideClose }) => {
|
|
168
|
+
const nativeOverlayManager = useNativeOverlayManager();
|
|
169
|
+
const registration = useOverlayRegistration({
|
|
262
170
|
active,
|
|
263
171
|
id
|
|
264
172
|
});
|
|
173
|
+
const { isTopOverlay } = registration;
|
|
265
174
|
const requestTopClose = useCallback(() => {
|
|
266
175
|
if (!isTopOverlay()) return;
|
|
267
176
|
requestClose();
|
|
268
177
|
}, [isTopOverlay, requestClose]);
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
178
|
+
const requestOutsideTopClose = useCallback(() => {
|
|
179
|
+
nativeOverlayManager.dispatchTopOutsidePress();
|
|
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
|
+
]);
|
|
273
197
|
useEffect(() => {
|
|
274
|
-
if (!active
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (event.key !== "Escape") return;
|
|
278
|
-
requestTopClose();
|
|
279
|
-
};
|
|
280
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
281
|
-
return () => {
|
|
282
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
const subscription = BackHandler.addEventListener("hardwareBackPress", () => {
|
|
198
|
+
if (!active) return;
|
|
199
|
+
return nativeOverlayManager.registerOutsidePressHandler(id, () => {
|
|
200
|
+
if (!closeOnOutsidePress) return false;
|
|
286
201
|
if (!isTopOverlay()) return false;
|
|
202
|
+
if (requestOutsideClose) {
|
|
203
|
+
requestOutsideClose();
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
287
206
|
requestClose();
|
|
288
207
|
return true;
|
|
289
208
|
});
|
|
209
|
+
}, [
|
|
210
|
+
active,
|
|
211
|
+
closeOnOutsidePress,
|
|
212
|
+
id,
|
|
213
|
+
isTopOverlay,
|
|
214
|
+
nativeOverlayManager,
|
|
215
|
+
requestClose,
|
|
216
|
+
requestOutsideClose
|
|
217
|
+
]);
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
if (!active) return;
|
|
220
|
+
const releaseDismissListener = retainDismissListener(nativeOverlayManager);
|
|
221
|
+
const unregisterDismissHandler = nativeOverlayManager.registerDismissHandler(id, () => {
|
|
222
|
+
if (!closeOnEscape) return false;
|
|
223
|
+
requestTopClose();
|
|
224
|
+
return true;
|
|
225
|
+
});
|
|
290
226
|
return () => {
|
|
291
|
-
|
|
227
|
+
unregisterDismissHandler();
|
|
228
|
+
releaseDismissListener();
|
|
292
229
|
};
|
|
293
230
|
}, [
|
|
294
231
|
active,
|
|
295
232
|
closeOnEscape,
|
|
296
|
-
|
|
297
|
-
|
|
233
|
+
id,
|
|
234
|
+
nativeOverlayManager,
|
|
298
235
|
requestTopClose
|
|
299
236
|
]);
|
|
300
237
|
return {
|
|
238
|
+
zIndex: registration.zIndex,
|
|
301
239
|
isTopOverlay,
|
|
240
|
+
getOutsidePressProps,
|
|
302
241
|
requestClose: requestTopClose,
|
|
303
|
-
requestOutsideClose
|
|
242
|
+
requestOutsideClose: requestOutsideTopClose
|
|
304
243
|
};
|
|
305
244
|
};
|
|
306
245
|
//#endregion
|
|
307
246
|
//#region src/hooks/behavior/overlay/useOverlayFocusRestore.ts
|
|
308
|
-
|
|
247
|
+
function isFocusableWebNode(node) {
|
|
248
|
+
return typeof node === "object" && node !== null && "focus" in node && typeof node.focus === "function";
|
|
249
|
+
}
|
|
250
|
+
const useOverlayFocusRestore = ({ active = false, enabled = true, finalFocus, triggerRef }) => {
|
|
251
|
+
const previouslyFocusedRef = useRef(null);
|
|
252
|
+
const saveFocusSnapshot = useCallback(() => {
|
|
253
|
+
if (Platform.OS !== "web" || typeof document === "undefined") return;
|
|
254
|
+
previouslyFocusedRef.current = document.activeElement;
|
|
255
|
+
}, []);
|
|
309
256
|
const restoreFocus = useCallback(() => {
|
|
310
257
|
if (!enabled) return;
|
|
311
258
|
if (Platform.OS === "web") {
|
|
312
|
-
const
|
|
313
|
-
if (
|
|
259
|
+
const preferredNode = finalFocus?.current ?? triggerRef.current;
|
|
260
|
+
if (isFocusableWebNode(preferredNode)) {
|
|
261
|
+
preferredNode.focus();
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const previouslyFocused = previouslyFocusedRef.current;
|
|
265
|
+
if (previouslyFocused instanceof HTMLElement && previouslyFocused.isConnected) previouslyFocused.focus();
|
|
314
266
|
return;
|
|
315
267
|
}
|
|
316
268
|
if (typeof findNodeHandle !== "function") return;
|
|
317
|
-
const handle = findNodeHandle(triggerRef.current);
|
|
269
|
+
const handle = findNodeHandle(finalFocus?.current ?? triggerRef.current);
|
|
318
270
|
if (handle && AccessibilityInfo.setAccessibilityFocus) AccessibilityInfo.setAccessibilityFocus(handle);
|
|
319
|
-
}, [
|
|
271
|
+
}, [
|
|
272
|
+
enabled,
|
|
273
|
+
finalFocus,
|
|
274
|
+
triggerRef
|
|
275
|
+
]);
|
|
276
|
+
const restoreFocusAfterClose = useCallback(() => {
|
|
277
|
+
if (!enabled) return;
|
|
278
|
+
deferOverlayFocusRestore(restoreFocus, requestAnimationFrame);
|
|
279
|
+
}, [enabled, restoreFocus]);
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
if (!active) return;
|
|
282
|
+
saveFocusSnapshot();
|
|
283
|
+
}, [active, saveFocusSnapshot]);
|
|
320
284
|
return {
|
|
321
285
|
restoreFocus,
|
|
322
|
-
restoreFocusAfterClose
|
|
323
|
-
|
|
324
|
-
requestAnimationFrame(restoreFocus);
|
|
325
|
-
}, [enabled, restoreFocus])
|
|
286
|
+
restoreFocusAfterClose,
|
|
287
|
+
saveFocusSnapshot
|
|
326
288
|
};
|
|
327
289
|
};
|
|
328
290
|
//#endregion
|
|
329
291
|
//#region src/hooks/behavior/overlay/useOverlayPresentation.ts
|
|
330
292
|
function useOverlayPresentation(presentation = "auto", breakpoint = 768) {
|
|
331
293
|
const { width } = useWindowDimensions();
|
|
332
|
-
|
|
333
|
-
|
|
294
|
+
return resolveOverlayPresentation({
|
|
295
|
+
presentation,
|
|
296
|
+
defaultPresentation: "sheet",
|
|
297
|
+
autoPresentation: width >= breakpoint ? "popover" : "sheet"
|
|
298
|
+
});
|
|
334
299
|
}
|
|
335
300
|
//#endregion
|
|
336
301
|
//#region src/hooks/useControllableState.ts
|
|
@@ -582,11 +547,23 @@ const useModal = ({ open, defaultOpen = false, onOpenChange, closeOnEscape, clos
|
|
|
582
547
|
};
|
|
583
548
|
//#endregion
|
|
584
549
|
//#region src/hooks/useSelect.ts
|
|
585
|
-
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]);
|
|
586
563
|
const [selectedValue, setSelectedValue] = useControllableState({
|
|
587
564
|
value,
|
|
588
565
|
defaultValue: defaultValue ?? (multiple ? [] : ""),
|
|
589
|
-
onChange:
|
|
566
|
+
onChange: handleValueChange
|
|
590
567
|
});
|
|
591
568
|
const [isOpen, setIsOpen] = useControllableState({
|
|
592
569
|
value: open,
|
|
@@ -764,6 +741,16 @@ function useThemeStyles(createStyles) {
|
|
|
764
741
|
return useMemo(() => createStyles(theme), [createStyles, theme]);
|
|
765
742
|
}
|
|
766
743
|
//#endregion
|
|
744
|
+
//#region src/components/Dropdown/internal/DropdownContext.tsx
|
|
745
|
+
const DropdownContext = createContext(null);
|
|
746
|
+
const DropdownProvider = DropdownContext.Provider;
|
|
747
|
+
const useDropdownContext = () => {
|
|
748
|
+
const context = useContext(DropdownContext);
|
|
749
|
+
if (!context) throw new Error("Dropdown components must be used inside Dropdown");
|
|
750
|
+
return context;
|
|
751
|
+
};
|
|
752
|
+
DropdownContext.displayName = "DropdownContext";
|
|
753
|
+
//#endregion
|
|
767
754
|
//#region src/components/Dropdown/Content/DropdownContent.styles.ts
|
|
768
755
|
const createStyles$21 = (theme) => StyleSheet.create({
|
|
769
756
|
modalRoot: { flex: 1 },
|
|
@@ -848,13 +835,14 @@ const createStyles$21 = (theme) => StyleSheet.create({
|
|
|
848
835
|
//#region src/components/Dropdown/Content/DropdownContent.tsx
|
|
849
836
|
const nativePointerEventsBoxNone$1 = Platform.OS === "web" ? void 0 : { pointerEvents: "box-none" };
|
|
850
837
|
const webPointerEventsBoxNone$1 = Platform.OS === "web" ? { pointerEvents: "box-none" } : void 0;
|
|
851
|
-
function DropdownContent({
|
|
838
|
+
function DropdownContent({ children, contentStyle, accessibilityLabel }) {
|
|
839
|
+
const { open, color, presentation, zIndex, position, searchable, searchValue, searchPlaceholder, searchAccessibilityLabel, requestClose, getOutsidePressProps, onSearchChange, onFloatingLayout } = useDropdownContext();
|
|
852
840
|
const { theme } = useTheme();
|
|
853
841
|
const styles = useThemeStyles(createStyles$21);
|
|
854
842
|
const colorPalette = theme.components.dropdown[color];
|
|
855
843
|
const isSheet = presentation === "sheet";
|
|
856
844
|
const isPopover = presentation === "popover";
|
|
857
|
-
const animation = useRef(new Animated.Value(
|
|
845
|
+
const animation = useRef(new Animated.Value(open ? 1 : 0)).current;
|
|
858
846
|
const [reduceMotion, setReduceMotion] = useState(false);
|
|
859
847
|
useEffect(() => {
|
|
860
848
|
AccessibilityInfo.isReduceMotionEnabled?.().then(setReduceMotion);
|
|
@@ -864,7 +852,7 @@ function DropdownContent({ isOpen, children, onClose, color = "primary", content
|
|
|
864
852
|
};
|
|
865
853
|
}, []);
|
|
866
854
|
useEffect(() => {
|
|
867
|
-
if (!
|
|
855
|
+
if (!open) {
|
|
868
856
|
animation.setValue(0);
|
|
869
857
|
return;
|
|
870
858
|
}
|
|
@@ -880,7 +868,7 @@ function DropdownContent({ isOpen, children, onClose, color = "primary", content
|
|
|
880
868
|
}).start();
|
|
881
869
|
}, [
|
|
882
870
|
animation,
|
|
883
|
-
|
|
871
|
+
open,
|
|
884
872
|
isSheet,
|
|
885
873
|
reduceMotion
|
|
886
874
|
]);
|
|
@@ -904,11 +892,15 @@ function DropdownContent({ isOpen, children, onClose, color = "primary", content
|
|
|
904
892
|
}, [animation, isSheet]);
|
|
905
893
|
return /* @__PURE__ */ jsx(Modal$1, {
|
|
906
894
|
transparent: true,
|
|
907
|
-
visible:
|
|
895
|
+
visible: open,
|
|
908
896
|
animationType: "none",
|
|
909
|
-
onRequestClose:
|
|
897
|
+
onRequestClose: requestClose,
|
|
910
898
|
children: /* @__PURE__ */ jsxs(View, {
|
|
911
|
-
style: [
|
|
899
|
+
style: [
|
|
900
|
+
styles.modalRoot,
|
|
901
|
+
styles[presentation],
|
|
902
|
+
Platform.OS === "web" && { zIndex }
|
|
903
|
+
],
|
|
912
904
|
children: [/* @__PURE__ */ jsx(Animated.View, {
|
|
913
905
|
...nativePointerEventsBoxNone$1,
|
|
914
906
|
style: [
|
|
@@ -917,10 +909,8 @@ function DropdownContent({ isOpen, children, onClose, color = "primary", content
|
|
|
917
909
|
webPointerEventsBoxNone$1
|
|
918
910
|
],
|
|
919
911
|
children: /* @__PURE__ */ jsx(Pressable, {
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
style: StyleSheet.absoluteFill,
|
|
923
|
-
onPress: onClose
|
|
912
|
+
...getOutsidePressProps({ accessibilityLabel: "Close menu" }),
|
|
913
|
+
style: StyleSheet.absoluteFill
|
|
924
914
|
})
|
|
925
915
|
}), /* @__PURE__ */ jsxs(Animated.View, {
|
|
926
916
|
accessibilityRole: "menu",
|
|
@@ -968,7 +958,7 @@ DropdownContent.displayName = "DropdownContent";
|
|
|
968
958
|
//#region src/components/Dropdown/internal/DropdownCollection.ts
|
|
969
959
|
function createDropdownSlot(name, displayName) {
|
|
970
960
|
const Slot = () => null;
|
|
971
|
-
Slot
|
|
961
|
+
markCompoundSlot(Slot, name);
|
|
972
962
|
Slot.displayName = displayName;
|
|
973
963
|
return Slot;
|
|
974
964
|
}
|
|
@@ -996,11 +986,12 @@ function parseDropdownChildren(children) {
|
|
|
996
986
|
Children.forEach(node, (child) => {
|
|
997
987
|
if (!isValidElement(child)) return;
|
|
998
988
|
const type = child.type;
|
|
989
|
+
const slot = getCompoundSlot(type);
|
|
999
990
|
if (type.__velliraPortal) {
|
|
1000
991
|
visit(child.props.children);
|
|
1001
992
|
return;
|
|
1002
993
|
}
|
|
1003
|
-
switch (
|
|
994
|
+
switch (slot) {
|
|
1004
995
|
case "trigger":
|
|
1005
996
|
triggerProps = child.props;
|
|
1006
997
|
trigger = triggerProps.children;
|
|
@@ -1068,6 +1059,279 @@ function getItemLabel(children) {
|
|
|
1068
1059
|
return labelParts.join("").trim();
|
|
1069
1060
|
}
|
|
1070
1061
|
//#endregion
|
|
1062
|
+
//#region src/hooks/behavior/dropdown/useDropdownAccessibility.ts
|
|
1063
|
+
const useDropdownAccessibility = ({ accessibilityLabel, label, open }) => {
|
|
1064
|
+
const menuAccessibilityLabel = useMemo(() => {
|
|
1065
|
+
if (accessibilityLabel) return accessibilityLabel;
|
|
1066
|
+
return typeof label === "string" ? label : "Menu";
|
|
1067
|
+
}, [accessibilityLabel, label]);
|
|
1068
|
+
useEffect(() => {
|
|
1069
|
+
if (!open) return;
|
|
1070
|
+
AccessibilityInfo.announceForAccessibility(`${menuAccessibilityLabel} opened`);
|
|
1071
|
+
}, [menuAccessibilityLabel, open]);
|
|
1072
|
+
return { menuAccessibilityLabel };
|
|
1073
|
+
};
|
|
1074
|
+
//#endregion
|
|
1075
|
+
//#region src/hooks/behavior/dropdown/useDropdownEntries.ts
|
|
1076
|
+
const useDropdownEntries = ({ parsed, filteredParsed, loading, loadingText, isSearchable, empty }) => {
|
|
1077
|
+
return {
|
|
1078
|
+
navigableItems: useMemo(() => parsed.items.map((item) => ({
|
|
1079
|
+
disabled: item.disabled,
|
|
1080
|
+
label: item.label,
|
|
1081
|
+
value: item.id
|
|
1082
|
+
})), [parsed.items]),
|
|
1083
|
+
data: useMemo(() => {
|
|
1084
|
+
if (loading) return [{
|
|
1085
|
+
type: "loading",
|
|
1086
|
+
id: "loading",
|
|
1087
|
+
props: { children: loadingText }
|
|
1088
|
+
}];
|
|
1089
|
+
if (isSearchable && filteredParsed.items.length === 0) return [{
|
|
1090
|
+
type: "empty",
|
|
1091
|
+
id: "empty",
|
|
1092
|
+
props: { children: empty ?? "No actions found" }
|
|
1093
|
+
}];
|
|
1094
|
+
return filteredParsed.entries;
|
|
1095
|
+
}, [
|
|
1096
|
+
empty,
|
|
1097
|
+
filteredParsed.entries,
|
|
1098
|
+
filteredParsed.items.length,
|
|
1099
|
+
isSearchable,
|
|
1100
|
+
loading,
|
|
1101
|
+
loadingText
|
|
1102
|
+
])
|
|
1103
|
+
};
|
|
1104
|
+
};
|
|
1105
|
+
//#endregion
|
|
1106
|
+
//#region src/components/Dropdown/internal/DropdownUtils.ts
|
|
1107
|
+
function createDropdownSelectEvent() {
|
|
1108
|
+
let defaultPrevented = false;
|
|
1109
|
+
return {
|
|
1110
|
+
preventDefault: () => {
|
|
1111
|
+
defaultPrevented = true;
|
|
1112
|
+
},
|
|
1113
|
+
get defaultPrevented() {
|
|
1114
|
+
return defaultPrevented;
|
|
1115
|
+
}
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
function filterDropdownEntries(parsed, searchValue) {
|
|
1119
|
+
const normalizedSearch = searchValue.trim().toLocaleLowerCase();
|
|
1120
|
+
const matchedItems = new Set(parsed.items.filter((item) => item.label.toLocaleLowerCase().includes(normalizedSearch)).map((item) => item.id));
|
|
1121
|
+
return {
|
|
1122
|
+
...parsed,
|
|
1123
|
+
items: parsed.items.filter((item) => matchedItems.has(item.id)),
|
|
1124
|
+
entries: parsed.entries.filter((entry) => entry.type !== "item" || matchedItems.has(entry.id))
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
//#endregion
|
|
1128
|
+
//#region src/hooks/behavior/dropdown/useDropdownSearch.ts
|
|
1129
|
+
const useDropdownSearch = ({ parsed, searchable, command, searchValue, defaultSearchValue, onSearch }) => {
|
|
1130
|
+
const [uncontrolledSearchValue, setUncontrolledSearchValue] = useState(defaultSearchValue);
|
|
1131
|
+
const resolvedSearchValue = searchValue ?? uncontrolledSearchValue;
|
|
1132
|
+
const contentCommand = parsed.contentProps?.command ?? false;
|
|
1133
|
+
const isSearchable = searchable || command || contentCommand || Boolean(parsed.searchProps);
|
|
1134
|
+
return {
|
|
1135
|
+
contentCommand,
|
|
1136
|
+
filteredParsed: useMemo(() => {
|
|
1137
|
+
if (!isSearchable || !resolvedSearchValue.trim()) return parsed;
|
|
1138
|
+
return filterDropdownEntries(parsed, resolvedSearchValue);
|
|
1139
|
+
}, [
|
|
1140
|
+
isSearchable,
|
|
1141
|
+
parsed,
|
|
1142
|
+
resolvedSearchValue
|
|
1143
|
+
]),
|
|
1144
|
+
handleSearchChange: useCallback((value) => {
|
|
1145
|
+
if (searchValue === void 0) setUncontrolledSearchValue(value);
|
|
1146
|
+
onSearch?.(value);
|
|
1147
|
+
}, [onSearch, searchValue]),
|
|
1148
|
+
isSearchable,
|
|
1149
|
+
resolvedSearchValue
|
|
1150
|
+
};
|
|
1151
|
+
};
|
|
1152
|
+
//#endregion
|
|
1153
|
+
//#region src/managers/FloatingManager/computeFloatingPosition.ts
|
|
1154
|
+
function clamp(value, min, max) {
|
|
1155
|
+
return Math.min(Math.max(value, min), Math.max(min, max));
|
|
1156
|
+
}
|
|
1157
|
+
function parsePlacement(placement) {
|
|
1158
|
+
const [side, align = "center"] = placement.split("-");
|
|
1159
|
+
return {
|
|
1160
|
+
side,
|
|
1161
|
+
align
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
function createPlacement(side, align) {
|
|
1165
|
+
return align === "center" ? side : `${side}-${align}`;
|
|
1166
|
+
}
|
|
1167
|
+
function getOppositeSide(side) {
|
|
1168
|
+
switch (side) {
|
|
1169
|
+
case "top": return "bottom";
|
|
1170
|
+
case "right": return "left";
|
|
1171
|
+
case "bottom": return "top";
|
|
1172
|
+
case "left": return "right";
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
function computeBasePosition({ reference, floating, side, align, offset }) {
|
|
1176
|
+
const referenceCenterX = reference.x + reference.width / 2;
|
|
1177
|
+
const referenceCenterY = reference.y + reference.height / 2;
|
|
1178
|
+
const alignedLeft = align === "start" ? reference.x : align === "end" ? reference.x + reference.width - floating.width : referenceCenterX - floating.width / 2;
|
|
1179
|
+
const alignedTop = align === "start" ? reference.y : align === "end" ? reference.y + reference.height - floating.height : referenceCenterY - floating.height / 2;
|
|
1180
|
+
switch (side) {
|
|
1181
|
+
case "top": return {
|
|
1182
|
+
top: reference.y - floating.height - offset,
|
|
1183
|
+
left: alignedLeft
|
|
1184
|
+
};
|
|
1185
|
+
case "right": return {
|
|
1186
|
+
top: alignedTop,
|
|
1187
|
+
left: reference.x + reference.width + offset
|
|
1188
|
+
};
|
|
1189
|
+
case "bottom": return {
|
|
1190
|
+
top: reference.y + reference.height + offset,
|
|
1191
|
+
left: alignedLeft
|
|
1192
|
+
};
|
|
1193
|
+
case "left": return {
|
|
1194
|
+
top: alignedTop,
|
|
1195
|
+
left: reference.x - floating.width - offset
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
function getMainAxisOverflow({ side, position, floating, boundary, padding }) {
|
|
1200
|
+
switch (side) {
|
|
1201
|
+
case "top": return padding - position.top;
|
|
1202
|
+
case "right": return position.left + floating.width + padding - boundary.width;
|
|
1203
|
+
case "bottom": return position.top + floating.height + padding - boundary.height;
|
|
1204
|
+
case "left": return padding - position.left;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
function computeFloatingPosition({ reference, floating, boundary, placement, offset = 8, padding = 12, arrowPadding = 16, flip = true, shift = true }) {
|
|
1208
|
+
const parsed = parsePlacement(placement);
|
|
1209
|
+
let resolvedSide = parsed.side;
|
|
1210
|
+
let position = computeBasePosition({
|
|
1211
|
+
reference,
|
|
1212
|
+
floating,
|
|
1213
|
+
side: resolvedSide,
|
|
1214
|
+
align: parsed.align,
|
|
1215
|
+
offset
|
|
1216
|
+
});
|
|
1217
|
+
if (flip && getMainAxisOverflow({
|
|
1218
|
+
side: resolvedSide,
|
|
1219
|
+
position,
|
|
1220
|
+
floating,
|
|
1221
|
+
boundary,
|
|
1222
|
+
padding
|
|
1223
|
+
}) > 0) {
|
|
1224
|
+
const oppositeSide = getOppositeSide(resolvedSide);
|
|
1225
|
+
const oppositePosition = computeBasePosition({
|
|
1226
|
+
reference,
|
|
1227
|
+
floating,
|
|
1228
|
+
side: oppositeSide,
|
|
1229
|
+
align: parsed.align,
|
|
1230
|
+
offset
|
|
1231
|
+
});
|
|
1232
|
+
if (getMainAxisOverflow({
|
|
1233
|
+
side: oppositeSide,
|
|
1234
|
+
position: oppositePosition,
|
|
1235
|
+
floating,
|
|
1236
|
+
boundary,
|
|
1237
|
+
padding
|
|
1238
|
+
}) <= 0) {
|
|
1239
|
+
resolvedSide = oppositeSide;
|
|
1240
|
+
position = oppositePosition;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
if (shift) position = {
|
|
1244
|
+
top: clamp(position.top, padding, boundary.height - floating.height - padding),
|
|
1245
|
+
left: clamp(position.left, padding, boundary.width - floating.width - padding)
|
|
1246
|
+
};
|
|
1247
|
+
const referenceCenterX = reference.x + reference.width / 2;
|
|
1248
|
+
const referenceCenterY = reference.y + reference.height / 2;
|
|
1249
|
+
const arrowPosition = resolvedSide === "top" || resolvedSide === "bottom" ? { left: clamp(referenceCenterX - position.left, arrowPadding, floating.width - arrowPadding) } : { top: clamp(referenceCenterY - position.top, arrowPadding, floating.height - arrowPadding) };
|
|
1250
|
+
return {
|
|
1251
|
+
position,
|
|
1252
|
+
arrowPosition,
|
|
1253
|
+
placement: createPlacement(resolvedSide, parsed.align)
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
//#endregion
|
|
1257
|
+
//#region src/managers/FloatingManager/useNativeFloatingPosition.ts
|
|
1258
|
+
function useNativeFloatingPosition(placement = "top", offset = 8) {
|
|
1259
|
+
const [result, setResult] = useState({
|
|
1260
|
+
position: {
|
|
1261
|
+
top: 0,
|
|
1262
|
+
left: 0
|
|
1263
|
+
},
|
|
1264
|
+
arrowPosition: {},
|
|
1265
|
+
placement
|
|
1266
|
+
});
|
|
1267
|
+
const floatingSizeRef = useRef({
|
|
1268
|
+
width: 0,
|
|
1269
|
+
height: 0
|
|
1270
|
+
});
|
|
1271
|
+
const lastTriggerRef = useRef(null);
|
|
1272
|
+
const lastContainerRef = useRef(null);
|
|
1273
|
+
const updatePosition = useCallback((triggerRef, containerRef, measuredSize = floatingSizeRef.current) => {
|
|
1274
|
+
lastTriggerRef.current = triggerRef;
|
|
1275
|
+
lastContainerRef.current = containerRef ?? null;
|
|
1276
|
+
const triggerNode = triggerRef.current;
|
|
1277
|
+
const containerNode = containerRef?.current;
|
|
1278
|
+
if (!triggerNode || typeof triggerNode.measureInWindow !== "function") {
|
|
1279
|
+
setResult((current) => ({
|
|
1280
|
+
...current,
|
|
1281
|
+
position: {
|
|
1282
|
+
top: 0,
|
|
1283
|
+
left: 0
|
|
1284
|
+
}
|
|
1285
|
+
}));
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
triggerNode.measureInWindow((x, y, width, height) => {
|
|
1289
|
+
const commitPosition = (containerX, containerY, containerWidth, containerHeight) => {
|
|
1290
|
+
const nextResult = computeFloatingPosition({
|
|
1291
|
+
reference: {
|
|
1292
|
+
x: x - containerX,
|
|
1293
|
+
y: y - containerY,
|
|
1294
|
+
width,
|
|
1295
|
+
height
|
|
1296
|
+
},
|
|
1297
|
+
floating: measuredSize,
|
|
1298
|
+
boundary: {
|
|
1299
|
+
width: containerWidth,
|
|
1300
|
+
height: containerHeight
|
|
1301
|
+
},
|
|
1302
|
+
placement,
|
|
1303
|
+
offset
|
|
1304
|
+
});
|
|
1305
|
+
setResult(nextResult);
|
|
1306
|
+
};
|
|
1307
|
+
if (!containerNode || typeof containerNode.measureInWindow !== "function") {
|
|
1308
|
+
const window = Dimensions.get("window");
|
|
1309
|
+
commitPosition(0, 0, window.width, window.height);
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
1312
|
+
containerNode.measureInWindow((containerX, containerY, containerWidth, containerHeight) => {
|
|
1313
|
+
commitPosition(containerX, containerY, containerWidth, containerHeight);
|
|
1314
|
+
});
|
|
1315
|
+
});
|
|
1316
|
+
}, [placement, offset]);
|
|
1317
|
+
const onFloatingLayout = useCallback((event) => {
|
|
1318
|
+
const { width, height } = event.nativeEvent.layout;
|
|
1319
|
+
const nextSize = {
|
|
1320
|
+
width,
|
|
1321
|
+
height
|
|
1322
|
+
};
|
|
1323
|
+
floatingSizeRef.current = nextSize;
|
|
1324
|
+
if (lastTriggerRef.current) updatePosition(lastTriggerRef.current, lastContainerRef.current ?? void 0, nextSize);
|
|
1325
|
+
}, [updatePosition]);
|
|
1326
|
+
return {
|
|
1327
|
+
position: result.position,
|
|
1328
|
+
arrowPosition: result.arrowPosition,
|
|
1329
|
+
placement: result.placement,
|
|
1330
|
+
updatePosition,
|
|
1331
|
+
onFloatingLayout
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
//#endregion
|
|
1071
1335
|
//#region src/components/Dropdown/Dropdown.styles.ts
|
|
1072
1336
|
const createStyles$20 = (theme) => StyleSheet.create({
|
|
1073
1337
|
root: { alignSelf: "flex-start" },
|
|
@@ -1103,27 +1367,10 @@ function DropdownGroup({ label }) {
|
|
|
1103
1367
|
}
|
|
1104
1368
|
DropdownGroup.displayName = "DropdownGroup";
|
|
1105
1369
|
//#endregion
|
|
1106
|
-
//#region src/
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
preventDefault: () => {
|
|
1111
|
-
defaultPrevented = true;
|
|
1112
|
-
},
|
|
1113
|
-
get defaultPrevented() {
|
|
1114
|
-
return defaultPrevented;
|
|
1115
|
-
}
|
|
1116
|
-
};
|
|
1117
|
-
}
|
|
1118
|
-
function filterDropdownEntries(parsed, searchValue) {
|
|
1119
|
-
const normalizedSearch = searchValue.trim().toLocaleLowerCase();
|
|
1120
|
-
const matchedItems = new Set(parsed.items.filter((item) => item.label.toLocaleLowerCase().includes(normalizedSearch)).map((item) => item.id));
|
|
1121
|
-
return {
|
|
1122
|
-
...parsed,
|
|
1123
|
-
items: parsed.items.filter((item) => matchedItems.has(item.id)),
|
|
1124
|
-
entries: parsed.entries.filter((entry) => entry.type !== "item" || matchedItems.has(entry.id))
|
|
1125
|
-
};
|
|
1126
|
-
}
|
|
1370
|
+
//#region src/utils/devWarning.ts
|
|
1371
|
+
const devWarning = (condition, message) => {
|
|
1372
|
+
if ((typeof __DEV__ === "undefined" || __DEV__) && !condition) console.warn(message);
|
|
1373
|
+
};
|
|
1127
1374
|
//#endregion
|
|
1128
1375
|
//#region src/components/Dropdown/Item/DropdownItem.styles.ts
|
|
1129
1376
|
const createStyles$18 = (theme) => StyleSheet.create({
|
|
@@ -1149,7 +1396,8 @@ const createStyles$18 = (theme) => StyleSheet.create({
|
|
|
1149
1396
|
});
|
|
1150
1397
|
//#endregion
|
|
1151
1398
|
//#region src/components/Dropdown/Item/DropdownItem.tsx
|
|
1152
|
-
function DropdownItem({ label, value,
|
|
1399
|
+
function DropdownItem({ label, value, asChild = false, children, color = "default", icon, disabled = false, textWrap = "truncate", onSelect }) {
|
|
1400
|
+
const { color: rootColor, itemStyle, textStyle } = useDropdownContext();
|
|
1153
1401
|
const { theme } = useTheme();
|
|
1154
1402
|
const styles = useThemeStyles(createStyles$18);
|
|
1155
1403
|
const rootColorPalette = theme.components.dropdown[rootColor];
|
|
@@ -1173,6 +1421,24 @@ function DropdownItem({ label, value, rootColor = "primary", color = "default",
|
|
|
1173
1421
|
const accessibilityLabel = typeof label === "string" ? label : value;
|
|
1174
1422
|
const numberOfLines = textWrap === "wrap" ? void 0 : 1;
|
|
1175
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
|
+
});
|
|
1176
1442
|
return /* @__PURE__ */ jsx(Pressable, {
|
|
1177
1443
|
disabled,
|
|
1178
1444
|
accessibilityRole: "menuitem",
|
|
@@ -1182,11 +1448,7 @@ function DropdownItem({ label, value, rootColor = "primary", color = "default",
|
|
|
1182
1448
|
if (disabled) return;
|
|
1183
1449
|
onSelect(value);
|
|
1184
1450
|
},
|
|
1185
|
-
style: ({ pressed }) =>
|
|
1186
|
-
styles.item,
|
|
1187
|
-
{ backgroundColor: getBackgroundColor(pressed) },
|
|
1188
|
-
itemStyle
|
|
1189
|
-
],
|
|
1451
|
+
style: ({ pressed }) => getItemStyle(pressed),
|
|
1190
1452
|
children: ({ pressed }) => {
|
|
1191
1453
|
const contentColor = getContentColor(pressed);
|
|
1192
1454
|
return /* @__PURE__ */ jsxs(Fragment, { children: [icon ? renderColoredNode(icon, contentColor) : null, /* @__PURE__ */ jsx(Text, {
|
|
@@ -1303,7 +1565,8 @@ const createStyles$16 = (theme) => StyleSheet.create({
|
|
|
1303
1565
|
});
|
|
1304
1566
|
//#endregion
|
|
1305
1567
|
//#region src/components/Dropdown/Trigger/DropdownTrigger.tsx
|
|
1306
|
-
function DropdownTrigger({ asChild = false, label, trigger, children, icon, arrowIcon, showArrow = true,
|
|
1568
|
+
function DropdownTrigger({ asChild = false, label, trigger, children, icon, arrowIcon, showArrow = true, triggerStyle, triggerRef, accessibilityLabel, accessibilityHint }) {
|
|
1569
|
+
const { open, color, disabled, size, toggle } = useDropdownContext();
|
|
1307
1570
|
const { theme } = useTheme();
|
|
1308
1571
|
const styles = useThemeStyles(createStyles$16);
|
|
1309
1572
|
const colorPalette = theme.components.dropdown[color];
|
|
@@ -1320,14 +1583,14 @@ function DropdownTrigger({ asChild = false, label, trigger, children, icon, arro
|
|
|
1320
1583
|
const hasIcon = Boolean(icon);
|
|
1321
1584
|
const isIconOnly = !trigger && hasIcon && !showArrow;
|
|
1322
1585
|
const [isPressed, setIsPressed] = useState(false);
|
|
1323
|
-
const rotateAnim = useRef(new Animated.Value(
|
|
1586
|
+
const rotateAnim = useRef(new Animated.Value(open ? 1 : 0)).current;
|
|
1324
1587
|
useEffect(() => {
|
|
1325
1588
|
Animated.timing(rotateAnim, {
|
|
1326
|
-
toValue:
|
|
1589
|
+
toValue: open ? 1 : 0,
|
|
1327
1590
|
duration: 180,
|
|
1328
1591
|
useNativeDriver: Platform.OS !== "web"
|
|
1329
1592
|
}).start();
|
|
1330
|
-
}, [
|
|
1593
|
+
}, [open, rotateAnim]);
|
|
1331
1594
|
const arrowRotate = rotateAnim.interpolate({
|
|
1332
1595
|
inputRange: [0, 1],
|
|
1333
1596
|
outputRange: ["0deg", "180deg"]
|
|
@@ -1363,12 +1626,12 @@ function DropdownTrigger({ asChild = false, label, trigger, children, icon, arro
|
|
|
1363
1626
|
accessibilityLabel: accessibilityLabel ?? (typeof label === "string" ? label : void 0),
|
|
1364
1627
|
accessibilityHint,
|
|
1365
1628
|
accessibilityState: {
|
|
1366
|
-
expanded:
|
|
1629
|
+
expanded: open,
|
|
1367
1630
|
disabled: isChildDisabled
|
|
1368
1631
|
},
|
|
1369
1632
|
onPress: () => {
|
|
1370
1633
|
child.props.onPress?.();
|
|
1371
|
-
if (!isChildDisabled)
|
|
1634
|
+
if (!isChildDisabled) toggle();
|
|
1372
1635
|
}
|
|
1373
1636
|
});
|
|
1374
1637
|
}
|
|
@@ -1379,10 +1642,10 @@ function DropdownTrigger({ asChild = false, label, trigger, children, icon, arro
|
|
|
1379
1642
|
accessibilityLabel: accessibilityLabel ?? (typeof label === "string" ? label : void 0),
|
|
1380
1643
|
accessibilityHint,
|
|
1381
1644
|
accessibilityState: {
|
|
1382
|
-
expanded:
|
|
1645
|
+
expanded: open,
|
|
1383
1646
|
disabled
|
|
1384
1647
|
},
|
|
1385
|
-
onPress,
|
|
1648
|
+
onPress: toggle,
|
|
1386
1649
|
onPressIn: () => setIsPressed(true),
|
|
1387
1650
|
onPressOut: () => setIsPressed(false),
|
|
1388
1651
|
style: [
|
|
@@ -1429,8 +1692,6 @@ DropdownTrigger.displayName = "DropdownTrigger";
|
|
|
1429
1692
|
function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, showArrow = true, open, defaultOpen = false, onOpenChange, presentation = "auto", placement = "bottom-start", offset = 8, closeOnSelect = true, color = "primary", disabled = false, loading = false, loadingText = "Loading actions...", searchable = false, command = false, searchValue, defaultSearchValue = "", searchPlaceholder, onSearch, empty, size = "md", style, triggerStyle, contentStyle, itemStyle, textStyle, accessibilityLabel, accessibilityHint }) {
|
|
1430
1693
|
const styles = useThemeStyles(createStyles$20);
|
|
1431
1694
|
const overlayId = useId();
|
|
1432
|
-
const [uncontrolledSearchValue, setUncontrolledSearchValue] = useState(defaultSearchValue);
|
|
1433
|
-
const resolvedSearchValue = searchValue ?? uncontrolledSearchValue;
|
|
1434
1695
|
const triggerRef = useRef(null);
|
|
1435
1696
|
const setTriggerRef = useCallback((node) => {
|
|
1436
1697
|
if (node && typeof node === "object" && "measureInWindow" in node && typeof node.measureInWindow === "function") {
|
|
@@ -1440,29 +1701,26 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
|
|
|
1440
1701
|
triggerRef.current = null;
|
|
1441
1702
|
}, []);
|
|
1442
1703
|
const parsed = useMemo(() => parseDropdownChildren(children), [children]);
|
|
1443
|
-
const contentCommand
|
|
1444
|
-
|
|
1704
|
+
const { contentCommand, filteredParsed, handleSearchChange, isSearchable, resolvedSearchValue } = useDropdownSearch({
|
|
1705
|
+
parsed,
|
|
1706
|
+
searchable,
|
|
1707
|
+
command,
|
|
1708
|
+
searchValue,
|
|
1709
|
+
defaultSearchValue,
|
|
1710
|
+
onSearch
|
|
1711
|
+
});
|
|
1712
|
+
const { navigableItems, data } = useDropdownEntries({
|
|
1713
|
+
parsed,
|
|
1714
|
+
filteredParsed,
|
|
1715
|
+
loading,
|
|
1716
|
+
loadingText,
|
|
1717
|
+
isSearchable,
|
|
1718
|
+
empty
|
|
1719
|
+
});
|
|
1445
1720
|
const resolvedPresentation = useOverlayPresentation(presentation);
|
|
1446
1721
|
const contentStyleFromSlot = parsed.contentProps?.style;
|
|
1447
1722
|
const contentPresentation = (parsed.contentProps?.presentation === "auto" ? void 0 : parsed.contentProps?.presentation) ?? resolvedPresentation;
|
|
1448
1723
|
const { position, updatePosition, onFloatingLayout } = useNativeFloatingPosition(placement, offset);
|
|
1449
|
-
const menuAccessibilityLabel = useMemo(() => {
|
|
1450
|
-
if (accessibilityLabel) return accessibilityLabel;
|
|
1451
|
-
return typeof label === "string" ? label : "Menu";
|
|
1452
|
-
}, [accessibilityLabel, label]);
|
|
1453
|
-
const navigableItems = useMemo(() => parsed.items.map((item) => ({
|
|
1454
|
-
disabled: item.disabled,
|
|
1455
|
-
label: item.label,
|
|
1456
|
-
value: item.id
|
|
1457
|
-
})), [parsed.items]);
|
|
1458
|
-
const filteredParsed = useMemo(() => {
|
|
1459
|
-
if (!isSearchable || !resolvedSearchValue.trim()) return parsed;
|
|
1460
|
-
return filterDropdownEntries(parsed, resolvedSearchValue);
|
|
1461
|
-
}, [
|
|
1462
|
-
isSearchable,
|
|
1463
|
-
parsed,
|
|
1464
|
-
resolvedSearchValue
|
|
1465
|
-
]);
|
|
1466
1724
|
const { isOpen, closeDropdown, toggleDropdown } = useDropdown({
|
|
1467
1725
|
items: navigableItems,
|
|
1468
1726
|
open,
|
|
@@ -1472,6 +1730,11 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
|
|
|
1472
1730
|
getItemValue: (item) => item.value,
|
|
1473
1731
|
getItemText: (item) => typeof item.label === "string" ? item.label : item.value
|
|
1474
1732
|
});
|
|
1733
|
+
const { menuAccessibilityLabel } = useDropdownAccessibility({
|
|
1734
|
+
accessibilityLabel,
|
|
1735
|
+
label,
|
|
1736
|
+
open: isOpen
|
|
1737
|
+
});
|
|
1475
1738
|
useEffect(() => {
|
|
1476
1739
|
if (!isOpen || contentPresentation !== "popover") return;
|
|
1477
1740
|
updatePosition(triggerRef);
|
|
@@ -1480,11 +1743,10 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
|
|
|
1480
1743
|
contentPresentation,
|
|
1481
1744
|
updatePosition
|
|
1482
1745
|
]);
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
}
|
|
1487
|
-
const { restoreFocusAfterClose } = useOverlayFocusRestore({ triggerRef });
|
|
1746
|
+
const { restoreFocusAfterClose } = useOverlayFocusRestore({
|
|
1747
|
+
active: isOpen,
|
|
1748
|
+
triggerRef
|
|
1749
|
+
});
|
|
1488
1750
|
const closeAndFocusTrigger = useCallback(() => {
|
|
1489
1751
|
closeDropdown();
|
|
1490
1752
|
restoreFocusAfterClose();
|
|
@@ -1508,10 +1770,6 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
|
|
|
1508
1770
|
const handleTriggerPress = useCallback(() => {
|
|
1509
1771
|
toggleDropdown();
|
|
1510
1772
|
}, [toggleDropdown]);
|
|
1511
|
-
const handleSearchChange = useCallback((value) => {
|
|
1512
|
-
if (searchValue === void 0) setUncontrolledSearchValue(value);
|
|
1513
|
-
onSearch?.(value);
|
|
1514
|
-
}, [onSearch, searchValue]);
|
|
1515
1773
|
const renderEntry = useCallback(({ item }) => {
|
|
1516
1774
|
if (item.type === "label") return /* @__PURE__ */ jsx(DropdownGroup, { label: item.props.children });
|
|
1517
1775
|
if (item.type === "separator") return /* @__PURE__ */ jsx(DropdownSeparator, {});
|
|
@@ -1524,73 +1782,86 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
|
|
|
1524
1782
|
children: item.props.children
|
|
1525
1783
|
});
|
|
1526
1784
|
return /* @__PURE__ */ jsx(DropdownItem, {
|
|
1785
|
+
asChild: item.props.asChild,
|
|
1527
1786
|
label: item.props.children,
|
|
1528
1787
|
value: item.props.value ?? item.id,
|
|
1529
|
-
rootColor: color,
|
|
1530
1788
|
color: item.props.color,
|
|
1531
1789
|
icon: item.props.icon,
|
|
1532
1790
|
disabled: item.props.disabled,
|
|
1533
1791
|
textWrap: item.props.textWrap,
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
onSelect: () => handleSelect(item)
|
|
1792
|
+
onSelect: () => handleSelect(item),
|
|
1793
|
+
children: item.props.children
|
|
1537
1794
|
});
|
|
1538
|
-
}, [
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
type: "loading",
|
|
1547
|
-
id: "loading",
|
|
1548
|
-
props: { children: loadingText }
|
|
1549
|
-
}] : isSearchable && filteredParsed.items.length === 0 ? [{
|
|
1550
|
-
type: "empty",
|
|
1551
|
-
id: "empty",
|
|
1552
|
-
props: { children: empty ?? "No actions found" }
|
|
1553
|
-
}] : filteredParsed.entries;
|
|
1554
|
-
return /* @__PURE__ */ jsxs(View, {
|
|
1555
|
-
style: [styles.root, style],
|
|
1556
|
-
children: [/* @__PURE__ */ jsx(DropdownTrigger, {
|
|
1557
|
-
asChild: Boolean(parsed.trigger),
|
|
1558
|
-
label,
|
|
1559
|
-
trigger: trigger ?? parsed.trigger,
|
|
1560
|
-
icon,
|
|
1561
|
-
arrowIcon,
|
|
1562
|
-
showArrow,
|
|
1795
|
+
}, [handleSelect, styles.emptyText]);
|
|
1796
|
+
const resolvedSearchPlaceholder = parsed.searchProps?.placeholder ?? searchPlaceholder ?? (command || contentCommand ? "Type a command..." : "Search actions...");
|
|
1797
|
+
const searchAccessibilityLabel = parsed.searchProps?.accessibilityLabel;
|
|
1798
|
+
return /* @__PURE__ */ jsx(DropdownProvider, {
|
|
1799
|
+
value: useMemo(() => ({
|
|
1800
|
+
open: isOpen,
|
|
1801
|
+
disabled,
|
|
1802
|
+
loading,
|
|
1563
1803
|
color,
|
|
1564
|
-
disabled: disabled || parsed.triggerProps?.disabled,
|
|
1565
|
-
isOpen,
|
|
1566
1804
|
size,
|
|
1567
|
-
triggerRef: setTriggerRef,
|
|
1568
|
-
triggerStyle,
|
|
1569
|
-
accessibilityLabel,
|
|
1570
|
-
accessibilityHint,
|
|
1571
|
-
onPress: handleTriggerPress
|
|
1572
|
-
}), /* @__PURE__ */ jsx(DropdownContent, {
|
|
1573
|
-
isOpen,
|
|
1574
|
-
onClose: dismiss.requestClose,
|
|
1575
|
-
color,
|
|
1576
|
-
contentStyle: [contentStyle, contentStyleFromSlot],
|
|
1577
|
-
accessibilityLabel: menuAccessibilityLabel,
|
|
1578
1805
|
presentation: contentPresentation,
|
|
1579
1806
|
position,
|
|
1580
|
-
|
|
1807
|
+
zIndex: dismiss.zIndex,
|
|
1581
1808
|
searchable: isSearchable,
|
|
1582
1809
|
searchValue: resolvedSearchValue,
|
|
1583
|
-
searchPlaceholder:
|
|
1584
|
-
searchAccessibilityLabel
|
|
1810
|
+
searchPlaceholder: resolvedSearchPlaceholder,
|
|
1811
|
+
searchAccessibilityLabel,
|
|
1812
|
+
itemStyle,
|
|
1813
|
+
textStyle,
|
|
1814
|
+
requestClose: dismiss.requestClose,
|
|
1815
|
+
getOutsidePressProps: dismiss.getOutsidePressProps,
|
|
1816
|
+
toggle: handleTriggerPress,
|
|
1585
1817
|
onSearchChange: handleSearchChange,
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1818
|
+
onFloatingLayout
|
|
1819
|
+
}), [
|
|
1820
|
+
color,
|
|
1821
|
+
contentPresentation,
|
|
1822
|
+
disabled,
|
|
1823
|
+
dismiss.zIndex,
|
|
1824
|
+
dismiss.getOutsidePressProps,
|
|
1825
|
+
dismiss.requestClose,
|
|
1826
|
+
handleSearchChange,
|
|
1827
|
+
handleTriggerPress,
|
|
1828
|
+
isOpen,
|
|
1829
|
+
isSearchable,
|
|
1830
|
+
itemStyle,
|
|
1831
|
+
loading,
|
|
1832
|
+
onFloatingLayout,
|
|
1833
|
+
position,
|
|
1834
|
+
resolvedSearchPlaceholder,
|
|
1835
|
+
resolvedSearchValue,
|
|
1836
|
+
searchAccessibilityLabel,
|
|
1837
|
+
size,
|
|
1838
|
+
textStyle
|
|
1839
|
+
]),
|
|
1840
|
+
children: /* @__PURE__ */ jsxs(View, {
|
|
1841
|
+
style: [styles.root, style],
|
|
1842
|
+
children: [/* @__PURE__ */ jsx(DropdownTrigger, {
|
|
1843
|
+
asChild: Boolean(parsed.trigger),
|
|
1844
|
+
label,
|
|
1845
|
+
trigger: trigger ?? parsed.trigger,
|
|
1846
|
+
icon,
|
|
1847
|
+
arrowIcon,
|
|
1848
|
+
showArrow,
|
|
1849
|
+
triggerRef: setTriggerRef,
|
|
1850
|
+
triggerStyle,
|
|
1851
|
+
accessibilityLabel,
|
|
1852
|
+
accessibilityHint
|
|
1853
|
+
}), /* @__PURE__ */ jsx(DropdownContent, {
|
|
1854
|
+
contentStyle: [contentStyle, contentStyleFromSlot],
|
|
1855
|
+
accessibilityLabel: menuAccessibilityLabel,
|
|
1856
|
+
children: /* @__PURE__ */ jsx(FlatList, {
|
|
1857
|
+
data,
|
|
1858
|
+
keyExtractor: (item) => item.id,
|
|
1859
|
+
renderItem: renderEntry,
|
|
1860
|
+
keyboardShouldPersistTaps: "handled",
|
|
1861
|
+
removeClippedSubviews: data.length > 24
|
|
1862
|
+
})
|
|
1863
|
+
})]
|
|
1864
|
+
})
|
|
1594
1865
|
});
|
|
1595
1866
|
}
|
|
1596
1867
|
DropdownRoot.displayName = "Dropdown";
|
|
@@ -1662,13 +1933,23 @@ const createStyles$14 = (theme) => StyleSheet.create({
|
|
|
1662
1933
|
justifyContent: "space-between",
|
|
1663
1934
|
paddingBottom: theme.components.modal.header.paddingBottom
|
|
1664
1935
|
},
|
|
1665
|
-
|
|
1936
|
+
headerContent: {
|
|
1666
1937
|
flex: 1,
|
|
1938
|
+
gap: theme.tokens.spacing["1"]
|
|
1939
|
+
},
|
|
1940
|
+
title: {
|
|
1667
1941
|
color: theme.components.modal.title.fg,
|
|
1668
1942
|
fontFamily: theme.tokens.typography.family.semibold,
|
|
1669
1943
|
fontSize: theme.tokens.typography.size.lg,
|
|
1670
1944
|
lineHeight: theme.tokens.typography.lineHeight.md
|
|
1671
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
|
+
},
|
|
1672
1953
|
closeButton: {
|
|
1673
1954
|
width: theme.components.modal.closeButton.size,
|
|
1674
1955
|
height: theme.components.modal.closeButton.size,
|
|
@@ -1682,20 +1963,21 @@ const createStyles$14 = (theme) => StyleSheet.create({
|
|
|
1682
1963
|
});
|
|
1683
1964
|
//#endregion
|
|
1684
1965
|
//#region src/components/Modal/internal/ModalContext.tsx
|
|
1685
|
-
const ModalContext = createContext(
|
|
1686
|
-
|
|
1966
|
+
const ModalContext = createContext(null);
|
|
1967
|
+
const ModalProvider = ModalContext.Provider;
|
|
1687
1968
|
const useModalContext = () => {
|
|
1688
1969
|
const context = useContext(ModalContext);
|
|
1689
1970
|
if (!context) throw new Error("Modal compound components must be used inside Modal");
|
|
1690
1971
|
return context;
|
|
1691
1972
|
};
|
|
1973
|
+
ModalContext.displayName = "ModalContext";
|
|
1692
1974
|
//#endregion
|
|
1693
1975
|
//#region src/components/Modal/Close/ModalClose.tsx
|
|
1694
|
-
const ModalClose = ({ children, accessibilityLabel, style }) => {
|
|
1976
|
+
const ModalClose = ({ asChild = false, children, accessibilityLabel, style }) => {
|
|
1695
1977
|
const { theme } = useTheme();
|
|
1696
1978
|
const styles = useThemeStyles(createStyles$14);
|
|
1697
1979
|
const { onClose } = useModalContext();
|
|
1698
|
-
if (isValidElement(children)) return cloneElement(children, {
|
|
1980
|
+
if ((asChild || children !== void 0) && isValidElement(children)) return cloneElement(children, {
|
|
1699
1981
|
accessibilityLabel: children.props.accessibilityLabel ?? accessibilityLabel,
|
|
1700
1982
|
onPress: (event) => {
|
|
1701
1983
|
children.props.onPress?.(event);
|
|
@@ -1788,19 +2070,46 @@ const ModalFooter = ({ children, style }) => {
|
|
|
1788
2070
|
};
|
|
1789
2071
|
ModalFooter.displayName = "ModalFooter";
|
|
1790
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
|
|
1791
2082
|
//#region src/components/Modal/Header/ModalHeader.tsx
|
|
1792
2083
|
const ModalHeader = ({ children, style, textStyle }) => {
|
|
1793
2084
|
const styles = useThemeStyles(createStyles$14);
|
|
2085
|
+
const isPlainTitle = typeof children === "string" || typeof children === "number";
|
|
1794
2086
|
return /* @__PURE__ */ jsxs(View, {
|
|
1795
2087
|
style: [styles.header, style],
|
|
1796
|
-
children: [/* @__PURE__ */ jsx(Text, {
|
|
1797
|
-
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,
|
|
1798
2097
|
children
|
|
1799
2098
|
}), /* @__PURE__ */ jsx(ModalClose, {})]
|
|
1800
2099
|
});
|
|
1801
2100
|
};
|
|
1802
2101
|
ModalHeader.displayName = "ModalHeader";
|
|
1803
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
|
|
1804
2113
|
//#region src/components/Modal/Modal.styles.ts
|
|
1805
2114
|
const createStyles$11 = (theme) => StyleSheet.create({
|
|
1806
2115
|
overlay: {
|
|
@@ -1818,7 +2127,7 @@ const createStyles$11 = (theme) => StyleSheet.create({
|
|
|
1818
2127
|
//#region src/components/Modal/Overlay/ModalOverlay.tsx
|
|
1819
2128
|
const ModalOverlay = ({ children, overlayStyle }) => {
|
|
1820
2129
|
const styles = useThemeStyles(createStyles$11);
|
|
1821
|
-
const { animation, animationProgress,
|
|
2130
|
+
const { animation, animationProgress, zIndex, onClose, getOutsidePressProps, shouldRender } = useModalContext();
|
|
1822
2131
|
const backdropStyle = animation === "none" ? void 0 : { opacity: animationProgress };
|
|
1823
2132
|
return /* @__PURE__ */ jsx(Modal$1, {
|
|
1824
2133
|
visible: shouldRender,
|
|
@@ -1826,22 +2135,24 @@ const ModalOverlay = ({ children, overlayStyle }) => {
|
|
|
1826
2135
|
animationType: "none",
|
|
1827
2136
|
onRequestClose: onClose,
|
|
1828
2137
|
children: /* @__PURE__ */ jsxs(View, {
|
|
1829
|
-
style: [
|
|
2138
|
+
style: [
|
|
2139
|
+
styles.overlay,
|
|
2140
|
+
Platform.OS === "web" && { zIndex },
|
|
2141
|
+
overlayStyle
|
|
2142
|
+
],
|
|
1830
2143
|
children: [/* @__PURE__ */ jsx(Animated.View, {
|
|
1831
2144
|
style: [styles.backdrop, backdropStyle],
|
|
1832
2145
|
children: /* @__PURE__ */ jsx(Pressable, {
|
|
1833
2146
|
testID: "modal-backdrop",
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
style: StyleSheet.absoluteFill,
|
|
1837
|
-
onPress: closeOnOutsidePress ? onOutsideClose : void 0
|
|
2147
|
+
...getOutsidePressProps({ accessibilityLabel: "Close modal" }),
|
|
2148
|
+
style: StyleSheet.absoluteFill
|
|
1838
2149
|
})
|
|
1839
2150
|
}), children]
|
|
1840
2151
|
})
|
|
1841
2152
|
});
|
|
1842
2153
|
};
|
|
1843
2154
|
//#endregion
|
|
1844
|
-
//#region src/components/Modal/Root/
|
|
2155
|
+
//#region src/components/Modal/Root/useModalRootAnimation.ts
|
|
1845
2156
|
const linearEasing = (value) => value;
|
|
1846
2157
|
const easingMap = {
|
|
1847
2158
|
standard: Easing?.bezier?.(.22, 1, .36, 1) ?? linearEasing,
|
|
@@ -1862,23 +2173,10 @@ const resolveDuration = (duration) => {
|
|
|
1862
2173
|
open: duration?.open ?? parseDuration(nativeThemes.light.components.modal.motion.openDuration)
|
|
1863
2174
|
};
|
|
1864
2175
|
};
|
|
1865
|
-
|
|
1866
|
-
const
|
|
1867
|
-
const
|
|
1868
|
-
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);
|
|
1869
2179
|
const [reduceMotion, setReduceMotion] = useState(false);
|
|
1870
|
-
const modal = useModal({
|
|
1871
|
-
open,
|
|
1872
|
-
defaultOpen,
|
|
1873
|
-
onOpenChange,
|
|
1874
|
-
closeOnOutsidePress
|
|
1875
|
-
});
|
|
1876
|
-
const dismiss = useOverlayDismiss({
|
|
1877
|
-
id: modal.contentId,
|
|
1878
|
-
active: modal.open,
|
|
1879
|
-
closeOnOutsidePress: modal.closeOnOutsidePress,
|
|
1880
|
-
requestClose: modal.requestClose
|
|
1881
|
-
});
|
|
1882
2180
|
const animationDuration = resolveDuration(duration);
|
|
1883
2181
|
const shouldAnimate = animation !== "none" && !reduceMotion;
|
|
1884
2182
|
useEffect(() => {
|
|
@@ -1890,7 +2188,7 @@ const ModalRoot = ({ open, defaultOpen = false, onOpenChange, animation = "scale
|
|
|
1890
2188
|
}, []);
|
|
1891
2189
|
useEffect(() => {
|
|
1892
2190
|
const progress = animationProgress.current;
|
|
1893
|
-
if (
|
|
2191
|
+
if (open) {
|
|
1894
2192
|
setShouldRender(true);
|
|
1895
2193
|
if (!shouldAnimate) {
|
|
1896
2194
|
progress.setValue(1);
|
|
@@ -1922,19 +2220,61 @@ const ModalRoot = ({ open, defaultOpen = false, onOpenChange, animation = "scale
|
|
|
1922
2220
|
animationDuration.close,
|
|
1923
2221
|
animationDuration.open,
|
|
1924
2222
|
easing,
|
|
1925
|
-
|
|
2223
|
+
open,
|
|
1926
2224
|
shouldAnimate
|
|
1927
2225
|
]);
|
|
1928
|
-
return
|
|
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
|
+
});
|
|
2267
|
+
return /* @__PURE__ */ jsx(ModalProvider, {
|
|
1929
2268
|
value: {
|
|
1930
2269
|
animation,
|
|
1931
|
-
animationProgress
|
|
1932
|
-
|
|
2270
|
+
animationProgress,
|
|
2271
|
+
zIndex: dismiss.zIndex,
|
|
1933
2272
|
onClose: dismiss.requestClose,
|
|
1934
|
-
|
|
2273
|
+
getOutsidePressProps: dismiss.getOutsidePressProps,
|
|
1935
2274
|
open: modal.open,
|
|
1936
2275
|
setOpen: modal.setOpen,
|
|
1937
|
-
shouldRender
|
|
2276
|
+
shouldRender,
|
|
2277
|
+
triggerRef
|
|
1938
2278
|
},
|
|
1939
2279
|
children
|
|
1940
2280
|
});
|
|
@@ -1942,15 +2282,26 @@ const ModalRoot = ({ open, defaultOpen = false, onOpenChange, animation = "scale
|
|
|
1942
2282
|
ModalRoot.displayName = "ModalRoot";
|
|
1943
2283
|
//#endregion
|
|
1944
2284
|
//#region src/components/Modal/Trigger/ModalTrigger.tsx
|
|
2285
|
+
const composeRefs = (...refs) => (node) => {
|
|
2286
|
+
for (const ref of refs) {
|
|
2287
|
+
if (typeof ref === "function") {
|
|
2288
|
+
ref(node);
|
|
2289
|
+
continue;
|
|
2290
|
+
}
|
|
2291
|
+
if (ref) ref.current = node;
|
|
2292
|
+
}
|
|
2293
|
+
};
|
|
1945
2294
|
const ModalTrigger = ({ children, asChild = false, disabled = false, accessibilityLabel, style, testID }) => {
|
|
1946
2295
|
const root = useModalContext();
|
|
1947
2296
|
const child = asChild && isValidElement(children) ? children : void 0;
|
|
2297
|
+
const composedTriggerRef = child ? composeRefs(root.triggerRef, child.props.ref) : root.triggerRef;
|
|
1948
2298
|
const handlePress = (event) => {
|
|
1949
2299
|
if (disabled || child?.props.disabled) return;
|
|
1950
2300
|
child?.props.onPress?.(event);
|
|
1951
2301
|
root.setOpen(true);
|
|
1952
2302
|
};
|
|
1953
2303
|
if (child) return cloneElement(child, {
|
|
2304
|
+
ref: composedTriggerRef,
|
|
1954
2305
|
onPress: handlePress,
|
|
1955
2306
|
accessibilityRole: child.props.accessibilityRole ?? "button",
|
|
1956
2307
|
accessibilityState: {
|
|
@@ -1963,6 +2314,7 @@ const ModalTrigger = ({ children, asChild = false, disabled = false, accessibili
|
|
|
1963
2314
|
style: child.props.style
|
|
1964
2315
|
});
|
|
1965
2316
|
return /* @__PURE__ */ jsx(Pressable, {
|
|
2317
|
+
ref: root.triggerRef,
|
|
1966
2318
|
accessibilityRole: "button",
|
|
1967
2319
|
accessibilityState: {
|
|
1968
2320
|
expanded: root.open,
|
|
@@ -1984,6 +2336,8 @@ const Modal = Object.assign(ModalRoot, {
|
|
|
1984
2336
|
Overlay: ModalOverlay,
|
|
1985
2337
|
Content: ModalContent,
|
|
1986
2338
|
Header: ModalHeader,
|
|
2339
|
+
Title: ModalTitle,
|
|
2340
|
+
Description: ModalDescription,
|
|
1987
2341
|
Body: ModalBody,
|
|
1988
2342
|
Footer: ModalFooter,
|
|
1989
2343
|
Close: ModalClose
|
|
@@ -2132,7 +2486,7 @@ PortalProvider.displayName = "PortalProvider";
|
|
|
2132
2486
|
//#endregion
|
|
2133
2487
|
//#region src/components/Popover/Content/PopoverContent.styles.ts
|
|
2134
2488
|
const styles = StyleSheet.create({
|
|
2135
|
-
|
|
2489
|
+
root: { flex: 1 },
|
|
2136
2490
|
backdrop: StyleSheet.absoluteFill,
|
|
2137
2491
|
content: { position: "absolute" }
|
|
2138
2492
|
});
|
|
@@ -2164,7 +2518,7 @@ function PopoverContent({ children, style, ...contentProps }) {
|
|
|
2164
2518
|
const { theme } = useTheme();
|
|
2165
2519
|
const layerRef = useRef(null);
|
|
2166
2520
|
const themedStyles = useMemo(() => createPopoverContentStyles(theme), [theme]);
|
|
2167
|
-
const { open, position, onFloatingLayout, updatePosition,
|
|
2521
|
+
const { open, zIndex, position, onFloatingLayout, updatePosition, requestClose, getOutsidePressProps } = usePopoverContext("Popover.Content");
|
|
2168
2522
|
useEffect(() => {
|
|
2169
2523
|
if (!open) return;
|
|
2170
2524
|
requestAnimationFrame(() => {
|
|
@@ -2173,20 +2527,14 @@ function PopoverContent({ children, style, ...contentProps }) {
|
|
|
2173
2527
|
}, [open, updatePosition]);
|
|
2174
2528
|
return /* @__PURE__ */ jsx(Portal, {
|
|
2175
2529
|
visible: open,
|
|
2176
|
-
onRequestClose:
|
|
2177
|
-
setOpen(false, { reason: "escape-key" });
|
|
2178
|
-
},
|
|
2530
|
+
onRequestClose: requestClose,
|
|
2179
2531
|
children: /* @__PURE__ */ jsxs(View, {
|
|
2180
2532
|
ref: layerRef,
|
|
2181
2533
|
pointerEvents: "box-none",
|
|
2182
|
-
style: styles.
|
|
2534
|
+
style: [styles.root, { zIndex }],
|
|
2183
2535
|
children: [/* @__PURE__ */ jsx(Pressable, {
|
|
2184
2536
|
testID: "popover-backdrop",
|
|
2185
|
-
accessibilityLabel:
|
|
2186
|
-
accessibilityRole: closeOnOutsidePress ? "button" : void 0,
|
|
2187
|
-
onPress: closeOnOutsidePress ? () => {
|
|
2188
|
-
setOpen(false, { reason: "outside-press" });
|
|
2189
|
-
} : void 0,
|
|
2537
|
+
...getOutsidePressProps({ accessibilityLabel: "Close popover" }),
|
|
2190
2538
|
style: styles.backdrop
|
|
2191
2539
|
}), /* @__PURE__ */ jsx(View, {
|
|
2192
2540
|
...contentProps,
|
|
@@ -2232,6 +2580,7 @@ function getNativePlacement(side, align) {
|
|
|
2232
2580
|
function PopoverRoot({ children, open: openProp, defaultOpen = false, onOpenChange, side = "bottom", align = "center", sideOffset = 8, closeOnOutsidePress = true }) {
|
|
2233
2581
|
const triggerRef = useRef(null);
|
|
2234
2582
|
const anchorRef = useRef(null);
|
|
2583
|
+
const overlayId = useId();
|
|
2235
2584
|
const getReferenceRef = useCallback(() => anchorRef.current ? anchorRef : triggerRef, []);
|
|
2236
2585
|
const openChangeDetailsRef = useRef({ reason: "programmatic" });
|
|
2237
2586
|
const [open, setOpenState] = useControllableState({
|
|
@@ -2241,26 +2590,45 @@ function PopoverRoot({ children, open: openProp, defaultOpen = false, onOpenChan
|
|
|
2241
2590
|
onOpenChange?.(nextOpen, openChangeDetailsRef.current);
|
|
2242
2591
|
}
|
|
2243
2592
|
});
|
|
2593
|
+
const { restoreFocusAfterClose } = useOverlayFocusRestore({
|
|
2594
|
+
active: open,
|
|
2595
|
+
triggerRef
|
|
2596
|
+
});
|
|
2244
2597
|
const { position, arrowPosition, placement, updatePosition: updateFloatingPosition, onFloatingLayout } = useNativeFloatingPosition(getNativePlacement(side, align), sideOffset);
|
|
2245
2598
|
const setOpen = useCallback((nextOpen, details) => {
|
|
2246
2599
|
openChangeDetailsRef.current = details;
|
|
2247
2600
|
setOpenState(nextOpen);
|
|
2248
|
-
|
|
2601
|
+
if (!nextOpen) restoreFocusAfterClose();
|
|
2602
|
+
}, [restoreFocusAfterClose, setOpenState]);
|
|
2603
|
+
const dismiss = useOverlayDismiss({
|
|
2604
|
+
id: overlayId,
|
|
2605
|
+
active: open,
|
|
2606
|
+
closeOnOutsidePress,
|
|
2607
|
+
requestClose: () => {
|
|
2608
|
+
setOpen(false, { reason: "escape-key" });
|
|
2609
|
+
},
|
|
2610
|
+
requestOutsideClose: () => {
|
|
2611
|
+
setOpen(false, { reason: "outside-press" });
|
|
2612
|
+
}
|
|
2613
|
+
});
|
|
2614
|
+
const updatePosition = useCallback((containerRef) => {
|
|
2615
|
+
updateFloatingPosition(getReferenceRef(), containerRef);
|
|
2616
|
+
}, [getReferenceRef, updateFloatingPosition]);
|
|
2249
2617
|
return /* @__PURE__ */ jsx(PopoverProvider, {
|
|
2250
2618
|
value: {
|
|
2251
2619
|
open,
|
|
2252
|
-
closeOnOutsidePress,
|
|
2253
2620
|
triggerRef,
|
|
2254
2621
|
anchorRef,
|
|
2255
2622
|
side,
|
|
2256
2623
|
align,
|
|
2257
2624
|
placement,
|
|
2625
|
+
zIndex: dismiss.zIndex,
|
|
2258
2626
|
position,
|
|
2259
2627
|
arrowPosition,
|
|
2628
|
+
requestClose: dismiss.requestClose,
|
|
2629
|
+
getOutsidePressProps: dismiss.getOutsidePressProps,
|
|
2260
2630
|
onFloatingLayout,
|
|
2261
|
-
updatePosition
|
|
2262
|
-
updateFloatingPosition(getReferenceRef(), containerRef);
|
|
2263
|
-
}, [getReferenceRef, updateFloatingPosition]),
|
|
2631
|
+
updatePosition,
|
|
2264
2632
|
setOpen
|
|
2265
2633
|
},
|
|
2266
2634
|
children
|
|
@@ -2384,8 +2752,8 @@ const createStyles$10 = (theme) => StyleSheet.create({
|
|
|
2384
2752
|
});
|
|
2385
2753
|
//#endregion
|
|
2386
2754
|
//#region src/primitives/Radio/Radio.tsx
|
|
2387
|
-
const nativePointerEventsNone$
|
|
2388
|
-
const webPointerEventsNone$
|
|
2755
|
+
const nativePointerEventsNone$3 = Platform.OS === "web" ? void 0 : { pointerEvents: "none" };
|
|
2756
|
+
const webPointerEventsNone$3 = Platform.OS === "web" ? { pointerEvents: "none" } : void 0;
|
|
2389
2757
|
const Radio = forwardRef(({ value, checked, defaultChecked = false, disabled: disabledProp = false, required: requiredProp = false, size: sizeProp, color: colorProp, onCheckedChange, label, description, icon, error, accessibilityLabel, accessibilityHint, containerStyle, labelStyle, descriptionStyle, errorStyle, style, ...rest }, ref) => {
|
|
2390
2758
|
const { theme } = useTheme();
|
|
2391
2759
|
const styles = createStyles$10(theme);
|
|
@@ -2444,10 +2812,10 @@ const Radio = forwardRef(({ value, checked, defaultChecked = false, disabled: di
|
|
|
2444
2812
|
onPress: handlePress,
|
|
2445
2813
|
style: resolvePressableStyle,
|
|
2446
2814
|
children: (state) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(View, {
|
|
2447
|
-
...nativePointerEventsNone$
|
|
2815
|
+
...nativePointerEventsNone$3,
|
|
2448
2816
|
style: [
|
|
2449
2817
|
styles.control,
|
|
2450
|
-
webPointerEventsNone$
|
|
2818
|
+
webPointerEventsNone$3,
|
|
2451
2819
|
{
|
|
2452
2820
|
width: radioSize.controlSize,
|
|
2453
2821
|
height: radioSize.controlSize,
|
|
@@ -2476,8 +2844,8 @@ const Radio = forwardRef(({ value, checked, defaultChecked = false, disabled: di
|
|
|
2476
2844
|
resolvedDisabled && styles.indicatorDisabled
|
|
2477
2845
|
] }))
|
|
2478
2846
|
}), (label || description) && /* @__PURE__ */ jsxs(View, {
|
|
2479
|
-
...nativePointerEventsNone$
|
|
2480
|
-
style: [styles.content, webPointerEventsNone$
|
|
2847
|
+
...nativePointerEventsNone$3,
|
|
2848
|
+
style: [styles.content, webPointerEventsNone$3],
|
|
2481
2849
|
children: [label && (typeof label === "string" ? /* @__PURE__ */ jsx(Text, {
|
|
2482
2850
|
style: [
|
|
2483
2851
|
styles.label,
|
|
@@ -2884,23 +3252,92 @@ const RadioGroupRoot = forwardRef(({ value, defaultValue = "", onValueChange, di
|
|
|
2884
3252
|
})
|
|
2885
3253
|
});
|
|
2886
3254
|
});
|
|
2887
|
-
RadioGroupRoot.displayName = "RadioGroup.Root";
|
|
2888
|
-
//#endregion
|
|
2889
|
-
//#region src/components/RadioGroup/RadioGroup.tsx
|
|
2890
|
-
const RadioGroup = Object.assign(RadioGroupRoot, { Item: RadioGroupItem });
|
|
2891
|
-
RadioGroup.displayName = "RadioGroup";
|
|
2892
|
-
//#endregion
|
|
2893
|
-
//#region src/components/Select/
|
|
2894
|
-
const
|
|
3255
|
+
RadioGroupRoot.displayName = "RadioGroup.Root";
|
|
3256
|
+
//#endregion
|
|
3257
|
+
//#region src/components/RadioGroup/RadioGroup.tsx
|
|
3258
|
+
const RadioGroup = Object.assign(RadioGroupRoot, { Item: RadioGroupItem });
|
|
3259
|
+
RadioGroup.displayName = "RadioGroup";
|
|
3260
|
+
//#endregion
|
|
3261
|
+
//#region src/components/Select/Content/SelectContent.styles.ts
|
|
3262
|
+
const createContentStyles = (theme) => StyleSheet.create({
|
|
3263
|
+
toolbar: {
|
|
3264
|
+
minHeight: 52,
|
|
3265
|
+
flexDirection: "row",
|
|
3266
|
+
alignItems: "center",
|
|
3267
|
+
justifyContent: "space-between",
|
|
3268
|
+
paddingHorizontal: theme.tokens.spacing[4],
|
|
3269
|
+
borderBottomColor: theme.components.select.dropdown.separator.bg,
|
|
3270
|
+
borderBottomWidth: 1
|
|
3271
|
+
},
|
|
3272
|
+
title: {
|
|
3273
|
+
flex: 1,
|
|
3274
|
+
marginHorizontal: theme.tokens.spacing[3],
|
|
3275
|
+
color: theme.components.select.dropdown.fg,
|
|
3276
|
+
fontFamily: theme.tokens.typography.family.medium,
|
|
3277
|
+
fontSize: theme.tokens.typography.size.md,
|
|
3278
|
+
lineHeight: theme.tokens.typography.lineHeight.md,
|
|
3279
|
+
textAlign: "center"
|
|
3280
|
+
},
|
|
3281
|
+
toolbarAction: {
|
|
3282
|
+
minWidth: 64,
|
|
3283
|
+
minHeight: 44,
|
|
3284
|
+
alignItems: "center",
|
|
3285
|
+
justifyContent: "center"
|
|
3286
|
+
},
|
|
3287
|
+
cancelText: {
|
|
3288
|
+
color: theme.components.select.trigger.placeholder.fg,
|
|
3289
|
+
fontFamily: theme.tokens.typography.family.medium,
|
|
3290
|
+
fontSize: theme.tokens.typography.size.md,
|
|
3291
|
+
lineHeight: theme.tokens.typography.lineHeight.md
|
|
3292
|
+
},
|
|
3293
|
+
doneText: {
|
|
3294
|
+
color: theme.semantic.text.interactive,
|
|
3295
|
+
fontFamily: theme.tokens.typography.family.medium,
|
|
3296
|
+
fontSize: theme.tokens.typography.size.md,
|
|
3297
|
+
lineHeight: theme.tokens.typography.lineHeight.md
|
|
3298
|
+
},
|
|
3299
|
+
list: { maxHeight: 420 },
|
|
3300
|
+
listContent: {
|
|
3301
|
+
paddingHorizontal: theme.tokens.spacing[2],
|
|
3302
|
+
paddingVertical: theme.tokens.spacing[2]
|
|
3303
|
+
},
|
|
3304
|
+
empty: {
|
|
3305
|
+
minHeight: 72,
|
|
3306
|
+
alignItems: "center",
|
|
3307
|
+
justifyContent: "center",
|
|
3308
|
+
padding: theme.tokens.spacing[4]
|
|
3309
|
+
},
|
|
3310
|
+
emptyText: {
|
|
3311
|
+
color: theme.components.select.dropdown.empty.fg,
|
|
3312
|
+
fontFamily: theme.tokens.typography.family.regular,
|
|
3313
|
+
fontSize: theme.tokens.typography.size.md,
|
|
3314
|
+
lineHeight: theme.tokens.typography.lineHeight.md,
|
|
3315
|
+
textAlign: "center"
|
|
3316
|
+
},
|
|
3317
|
+
loading: {
|
|
3318
|
+
minHeight: 72,
|
|
3319
|
+
flexDirection: "row",
|
|
3320
|
+
alignItems: "center",
|
|
3321
|
+
justifyContent: "center",
|
|
3322
|
+
gap: theme.tokens.spacing[2],
|
|
3323
|
+
padding: theme.tokens.spacing[4]
|
|
3324
|
+
},
|
|
3325
|
+
loadingText: {
|
|
3326
|
+
color: theme.components.select.dropdown.fg,
|
|
3327
|
+
fontFamily: theme.tokens.typography.family.regular,
|
|
3328
|
+
fontSize: theme.tokens.typography.size.md,
|
|
3329
|
+
lineHeight: theme.tokens.typography.lineHeight.md
|
|
3330
|
+
}
|
|
3331
|
+
});
|
|
2895
3332
|
//#endregion
|
|
2896
3333
|
//#region src/components/Select/internal/SelectCollection.ts
|
|
2897
3334
|
const createSelectSlot = (name, displayName) => {
|
|
2898
3335
|
const Slot = (_props) => null;
|
|
2899
|
-
Slot
|
|
3336
|
+
markCompoundSlot(Slot, name);
|
|
2900
3337
|
Slot.displayName = displayName;
|
|
2901
3338
|
return Slot;
|
|
2902
3339
|
};
|
|
2903
|
-
const getSelectSlot = (type) => type
|
|
3340
|
+
const getSelectSlot = (type) => getCompoundSlot(type);
|
|
2904
3341
|
const defaultSelectFilter = (option, query) => option.label.toLowerCase().includes(query.trim().toLowerCase());
|
|
2905
3342
|
const getTextFromNode = (node) => {
|
|
2906
3343
|
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
@@ -2989,6 +3426,8 @@ const parseSelectChildren = (children) => {
|
|
|
2989
3426
|
const option = {
|
|
2990
3427
|
value: props.value,
|
|
2991
3428
|
label: props.label,
|
|
3429
|
+
asChild: props.asChild,
|
|
3430
|
+
children: props.children,
|
|
2992
3431
|
disabled: props.disabled,
|
|
2993
3432
|
description: props.description,
|
|
2994
3433
|
icon: props.icon,
|
|
@@ -3017,6 +3456,33 @@ const parseSelectChildren = (children) => {
|
|
|
3017
3456
|
};
|
|
3018
3457
|
};
|
|
3019
3458
|
//#endregion
|
|
3459
|
+
//#region src/components/Select/internal/SelectContext.tsx
|
|
3460
|
+
const SelectContext = createContext(null);
|
|
3461
|
+
const useSelectContext = () => {
|
|
3462
|
+
const context = useContext(SelectContext);
|
|
3463
|
+
if (!context) throw new Error("Select compound components must be used inside Select");
|
|
3464
|
+
return context;
|
|
3465
|
+
};
|
|
3466
|
+
//#endregion
|
|
3467
|
+
//#region src/components/Select/Empty/SelectEmpty.tsx
|
|
3468
|
+
const renderText$1 = (node, style) => {
|
|
3469
|
+
if (typeof node === "string" || typeof node === "number") return /* @__PURE__ */ jsx(Text, {
|
|
3470
|
+
style,
|
|
3471
|
+
children: node
|
|
3472
|
+
});
|
|
3473
|
+
return node;
|
|
3474
|
+
};
|
|
3475
|
+
const SelectEmpty = createSelectSlot("empty", "Select.Empty");
|
|
3476
|
+
const SelectEmptyState = () => {
|
|
3477
|
+
const styles = useThemeStyles(createContentStyles);
|
|
3478
|
+
const { empty } = useSelectContext();
|
|
3479
|
+
return /* @__PURE__ */ jsx(View, {
|
|
3480
|
+
style: styles.empty,
|
|
3481
|
+
children: renderText$1(empty, styles.emptyText)
|
|
3482
|
+
});
|
|
3483
|
+
};
|
|
3484
|
+
SelectEmptyState.displayName = "Select.EmptyState";
|
|
3485
|
+
//#endregion
|
|
3020
3486
|
//#region src/components/Select/Group/SelectGroup.styles.ts
|
|
3021
3487
|
const createGroupStyles = (theme) => StyleSheet.create({
|
|
3022
3488
|
groupLabel: {
|
|
@@ -3100,24 +3566,6 @@ const SelectGroupActionRow = ({ label, selectLabel, selectedCount, itemCount, on
|
|
|
3100
3566
|
SelectGroupLabelRow.displayName = "Select.GroupLabelRow";
|
|
3101
3567
|
SelectGroupActionRow.displayName = "Select.GroupActionRow";
|
|
3102
3568
|
//#endregion
|
|
3103
|
-
//#region src/components/Select/Group/SelectLabel.tsx
|
|
3104
|
-
const SelectLabel = createSelectSlot("label", "Select.Label");
|
|
3105
|
-
//#endregion
|
|
3106
|
-
//#region src/components/Select/Group/SelectSeparator.tsx
|
|
3107
|
-
const SelectSeparator = createSelectSlot("separator", "Select.Separator");
|
|
3108
|
-
const SelectSeparatorRow = () => {
|
|
3109
|
-
return /* @__PURE__ */ jsx(View, { style: useThemeStyles(createGroupStyles).separator });
|
|
3110
|
-
};
|
|
3111
|
-
SelectSeparatorRow.displayName = "Select.SeparatorRow";
|
|
3112
|
-
//#endregion
|
|
3113
|
-
//#region src/components/Select/internal/SelectContext.tsx
|
|
3114
|
-
const SelectContext = createContext(null);
|
|
3115
|
-
const useSelectContext = () => {
|
|
3116
|
-
const context = useContext(SelectContext);
|
|
3117
|
-
if (!context) throw new Error("Select compound components must be used inside Select");
|
|
3118
|
-
return context;
|
|
3119
|
-
};
|
|
3120
|
-
//#endregion
|
|
3121
3569
|
//#region src/components/Select/Item/SelectItem.styles.ts
|
|
3122
3570
|
const createItemStyles = (theme) => StyleSheet.create({
|
|
3123
3571
|
option: {
|
|
@@ -3187,17 +3635,54 @@ const renderNodeOrText = (node, textStyle, fallback) => {
|
|
|
3187
3635
|
}) : null);
|
|
3188
3636
|
};
|
|
3189
3637
|
const SelectItem = createSelectSlot("item", "Select.Item");
|
|
3190
|
-
const SelectItemRow = ({ option, isSelected, isDisabled, optionStyle, onSelect }) => {
|
|
3638
|
+
const SelectItemRow = ({ option, isSelected, isDisabled, itemIndex, selectedValues, multiple, optionStyle, onSelect }) => {
|
|
3191
3639
|
const { theme } = useTheme();
|
|
3192
3640
|
const styles = useThemeStyles(createItemStyles);
|
|
3193
3641
|
const { color, variant, renderOption } = useSelectContext();
|
|
3194
3642
|
const [isHovered, setIsHovered] = useState(false);
|
|
3643
|
+
const child = option.asChild && isValidElement(option.children) ? option.children : void 0;
|
|
3195
3644
|
const optionPalette = theme.components.select[option.color ?? color][variant].option;
|
|
3196
3645
|
const getOptionState = (pressed) => {
|
|
3197
3646
|
if (isDisabled) return theme.components.select.option.disabled;
|
|
3198
3647
|
if (isSelected) return pressed ? optionPalette.selectedPressed : isHovered ? optionPalette.selectedHover : optionPalette.selected;
|
|
3199
3648
|
return pressed ? optionPalette.pressed : isHovered ? optionPalette.hover : theme.components.select.option.default;
|
|
3200
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
|
+
});
|
|
3201
3686
|
return /* @__PURE__ */ jsx(Pressable, {
|
|
3202
3687
|
disabled: isDisabled,
|
|
3203
3688
|
accessibilityRole: "button",
|
|
@@ -3210,24 +3695,19 @@ const SelectItemRow = ({ option, isSelected, isDisabled, optionStyle, onSelect }
|
|
|
3210
3695
|
onPress: () => onSelect(option),
|
|
3211
3696
|
onHoverIn: () => setIsHovered(true),
|
|
3212
3697
|
onHoverOut: () => setIsHovered(false),
|
|
3213
|
-
style: ({ pressed }) =>
|
|
3214
|
-
const optionState = getOptionState(pressed);
|
|
3215
|
-
return [
|
|
3216
|
-
styles.option,
|
|
3217
|
-
{
|
|
3218
|
-
backgroundColor: optionState.bg,
|
|
3219
|
-
borderColor: optionState.border
|
|
3220
|
-
},
|
|
3221
|
-
isDisabled && styles.optionDisabled,
|
|
3222
|
-
optionStyle
|
|
3223
|
-
];
|
|
3224
|
-
},
|
|
3698
|
+
style: ({ pressed }) => getOptionStyle(pressed),
|
|
3225
3699
|
children: ({ pressed }) => {
|
|
3226
3700
|
const optionFg = getOptionState(pressed).fg;
|
|
3227
3701
|
const descriptionFg = isSelected || pressed ? optionFg : theme.components.select.option.description.fg;
|
|
3228
|
-
return renderOption ? renderNodeOrText(renderOption(
|
|
3702
|
+
return renderOption ? renderNodeOrText(renderOption({
|
|
3703
|
+
option,
|
|
3229
3704
|
selected: isSelected,
|
|
3230
|
-
disabled: isDisabled
|
|
3705
|
+
disabled: isDisabled,
|
|
3706
|
+
active: isHovered,
|
|
3707
|
+
index: itemIndex,
|
|
3708
|
+
values: selectedValues,
|
|
3709
|
+
multiple,
|
|
3710
|
+
pressed
|
|
3231
3711
|
}), [styles.optionLabel, { color: optionFg }]) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3232
3712
|
option.icon && /* @__PURE__ */ jsx(View, {
|
|
3233
3713
|
style: styles.optionIcon,
|
|
@@ -3269,14 +3749,29 @@ const SelectItemRow = ({ option, isSelected, isDisabled, optionStyle, onSelect }
|
|
|
3269
3749
|
};
|
|
3270
3750
|
SelectItemRow.displayName = "Select.ItemRow";
|
|
3271
3751
|
//#endregion
|
|
3272
|
-
//#region src/components/Select/
|
|
3273
|
-
const
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3752
|
+
//#region src/components/Select/Loading/SelectLoading.tsx
|
|
3753
|
+
const renderText = (node, style) => {
|
|
3754
|
+
if (typeof node === "string" || typeof node === "number") return /* @__PURE__ */ jsx(Text, {
|
|
3755
|
+
style,
|
|
3756
|
+
children: node
|
|
3757
|
+
});
|
|
3758
|
+
return node;
|
|
3759
|
+
};
|
|
3760
|
+
const SelectLoading = createSelectSlot("loading", "Select.Loading");
|
|
3761
|
+
const SelectLoadingState = () => {
|
|
3762
|
+
const { theme } = useTheme();
|
|
3763
|
+
const styles = useThemeStyles(createContentStyles);
|
|
3764
|
+
const { loadingContent } = useSelectContext();
|
|
3765
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
3766
|
+
style: styles.loading,
|
|
3767
|
+
children: [/* @__PURE__ */ jsx(ActivityIndicator, {
|
|
3768
|
+
testID: "select-content-loading-indicator",
|
|
3769
|
+
size: "small",
|
|
3770
|
+
color: theme.components.select.dropdown.fg
|
|
3771
|
+
}), renderText(loadingContent, styles.loadingText)]
|
|
3772
|
+
});
|
|
3773
|
+
};
|
|
3774
|
+
SelectLoadingState.displayName = "Select.LoadingState";
|
|
3280
3775
|
//#endregion
|
|
3281
3776
|
//#region src/components/Select/Presentation/SelectPresentation.styles.ts
|
|
3282
3777
|
const createPresentationStyles = (theme) => StyleSheet.create({
|
|
@@ -3328,12 +3823,11 @@ const createPresentationStyles = (theme) => StyleSheet.create({
|
|
|
3328
3823
|
});
|
|
3329
3824
|
//#endregion
|
|
3330
3825
|
//#region src/components/Select/Presentation/SelectBackdrop.tsx
|
|
3331
|
-
const SelectBackdrop = ({
|
|
3826
|
+
const SelectBackdrop = ({ outsidePressProps }) => {
|
|
3827
|
+
const styles = useThemeStyles(createPresentationStyles);
|
|
3332
3828
|
return /* @__PURE__ */ jsx(Pressable, {
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
accessibilityRole: "button",
|
|
3336
|
-
accessibilityLabel: "Dismiss select"
|
|
3829
|
+
...outsidePressProps,
|
|
3830
|
+
style: styles.backdrop
|
|
3337
3831
|
});
|
|
3338
3832
|
};
|
|
3339
3833
|
SelectBackdrop.displayName = "Select.Backdrop";
|
|
@@ -3350,7 +3844,7 @@ const SelectHandle = () => {
|
|
|
3350
3844
|
SelectHandle.displayName = "Select.Handle";
|
|
3351
3845
|
//#endregion
|
|
3352
3846
|
//#region src/components/Select/Presentation/SelectModal.tsx
|
|
3353
|
-
const SelectModal = ({ visible, onClose,
|
|
3847
|
+
const SelectModal = ({ visible, onClose, outsidePressProps, zIndex, contentStyle, children }) => {
|
|
3354
3848
|
const styles = useThemeStyles(createPresentationStyles);
|
|
3355
3849
|
return /* @__PURE__ */ jsx(Modal$1, {
|
|
3356
3850
|
transparent: true,
|
|
@@ -3358,12 +3852,13 @@ const SelectModal = ({ visible, onClose, dismissOnBackdropPress, contentStyle, c
|
|
|
3358
3852
|
animationType: "slide",
|
|
3359
3853
|
onRequestClose: onClose,
|
|
3360
3854
|
children: /* @__PURE__ */ jsxs(View, {
|
|
3361
|
-
style: [
|
|
3855
|
+
style: [
|
|
3856
|
+
styles.modalRoot,
|
|
3857
|
+
styles.modalPresentationRoot,
|
|
3858
|
+
Platform.OS === "web" && { zIndex }
|
|
3859
|
+
],
|
|
3362
3860
|
testID: "select-content-root",
|
|
3363
|
-
children: [/* @__PURE__ */ jsx(SelectBackdrop, {
|
|
3364
|
-
onClose,
|
|
3365
|
-
dismissOnBackdropPress
|
|
3366
|
-
}), /* @__PURE__ */ jsx(View, {
|
|
3861
|
+
children: [/* @__PURE__ */ jsx(SelectBackdrop, { outsidePressProps }), /* @__PURE__ */ jsx(View, {
|
|
3367
3862
|
style: [
|
|
3368
3863
|
styles.content,
|
|
3369
3864
|
styles.modalPresentation,
|
|
@@ -3378,7 +3873,7 @@ const SelectModal = ({ visible, onClose, dismissOnBackdropPress, contentStyle, c
|
|
|
3378
3873
|
SelectModal.displayName = "Select.Modal";
|
|
3379
3874
|
//#endregion
|
|
3380
3875
|
//#region src/components/Select/Presentation/SelectPopover.tsx
|
|
3381
|
-
const SelectPopover = ({ visible, onClose,
|
|
3876
|
+
const SelectPopover = ({ visible, onClose, outsidePressProps, zIndex, position, onFloatingLayout, matchTriggerWidth, triggerWidth, contentStyle, children }) => {
|
|
3382
3877
|
const styles = useThemeStyles(createPresentationStyles);
|
|
3383
3878
|
return /* @__PURE__ */ jsx(Modal$1, {
|
|
3384
3879
|
transparent: true,
|
|
@@ -3386,12 +3881,9 @@ const SelectPopover = ({ visible, onClose, dismissOnBackdropPress, position, onF
|
|
|
3386
3881
|
animationType: "fade",
|
|
3387
3882
|
onRequestClose: onClose,
|
|
3388
3883
|
children: /* @__PURE__ */ jsxs(View, {
|
|
3389
|
-
style: styles.modalRoot,
|
|
3884
|
+
style: [styles.modalRoot, Platform.OS === "web" && { zIndex }],
|
|
3390
3885
|
testID: "select-content-root",
|
|
3391
|
-
children: [/* @__PURE__ */ jsx(SelectBackdrop, {
|
|
3392
|
-
onClose,
|
|
3393
|
-
dismissOnBackdropPress
|
|
3394
|
-
}), /* @__PURE__ */ jsx(View, {
|
|
3886
|
+
children: [/* @__PURE__ */ jsx(SelectBackdrop, { outsidePressProps }), /* @__PURE__ */ jsx(View, {
|
|
3395
3887
|
onLayout: onFloatingLayout,
|
|
3396
3888
|
style: [
|
|
3397
3889
|
styles.content,
|
|
@@ -3411,151 +3903,37 @@ const SelectPopover = ({ visible, onClose, dismissOnBackdropPress, position, onF
|
|
|
3411
3903
|
});
|
|
3412
3904
|
};
|
|
3413
3905
|
SelectPopover.displayName = "Select.Popover";
|
|
3414
|
-
//#endregion
|
|
3415
|
-
//#region src/components/Select/Presentation/SelectSheet.tsx
|
|
3416
|
-
const SelectSheet = ({ visible, onClose,
|
|
3417
|
-
const styles = useThemeStyles(createPresentationStyles);
|
|
3418
|
-
return /* @__PURE__ */ jsx(Modal$1, {
|
|
3419
|
-
transparent: true,
|
|
3420
|
-
visible,
|
|
3421
|
-
animationType: "slide",
|
|
3422
|
-
onRequestClose: onClose,
|
|
3423
|
-
children: /* @__PURE__ */ jsxs(View, {
|
|
3424
|
-
style: [
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
styles.
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
};
|
|
3441
|
-
SelectSheet.displayName = "Select.Sheet";
|
|
3442
|
-
//#endregion
|
|
3443
|
-
//#region src/components/Select/Content/SelectContent.styles.ts
|
|
3444
|
-
const createContentStyles = (theme) => StyleSheet.create({
|
|
3445
|
-
toolbar: {
|
|
3446
|
-
minHeight: 52,
|
|
3447
|
-
flexDirection: "row",
|
|
3448
|
-
alignItems: "center",
|
|
3449
|
-
justifyContent: "space-between",
|
|
3450
|
-
paddingHorizontal: theme.tokens.spacing[4],
|
|
3451
|
-
borderBottomColor: theme.components.select.dropdown.separator.bg,
|
|
3452
|
-
borderBottomWidth: 1
|
|
3453
|
-
},
|
|
3454
|
-
title: {
|
|
3455
|
-
flex: 1,
|
|
3456
|
-
marginHorizontal: theme.tokens.spacing[3],
|
|
3457
|
-
color: theme.components.select.dropdown.fg,
|
|
3458
|
-
fontFamily: theme.tokens.typography.family.medium,
|
|
3459
|
-
fontSize: theme.tokens.typography.size.md,
|
|
3460
|
-
lineHeight: theme.tokens.typography.lineHeight.md,
|
|
3461
|
-
textAlign: "center"
|
|
3462
|
-
},
|
|
3463
|
-
toolbarAction: {
|
|
3464
|
-
minWidth: 64,
|
|
3465
|
-
minHeight: 44,
|
|
3466
|
-
alignItems: "center",
|
|
3467
|
-
justifyContent: "center"
|
|
3468
|
-
},
|
|
3469
|
-
cancelText: {
|
|
3470
|
-
color: theme.components.select.trigger.placeholder.fg,
|
|
3471
|
-
fontFamily: theme.tokens.typography.family.medium,
|
|
3472
|
-
fontSize: theme.tokens.typography.size.md,
|
|
3473
|
-
lineHeight: theme.tokens.typography.lineHeight.md
|
|
3474
|
-
},
|
|
3475
|
-
doneText: {
|
|
3476
|
-
color: theme.semantic.text.interactive,
|
|
3477
|
-
fontFamily: theme.tokens.typography.family.medium,
|
|
3478
|
-
fontSize: theme.tokens.typography.size.md,
|
|
3479
|
-
lineHeight: theme.tokens.typography.lineHeight.md
|
|
3480
|
-
},
|
|
3481
|
-
list: { maxHeight: 420 },
|
|
3482
|
-
listContent: {
|
|
3483
|
-
paddingHorizontal: theme.tokens.spacing[2],
|
|
3484
|
-
paddingVertical: theme.tokens.spacing[2]
|
|
3485
|
-
},
|
|
3486
|
-
empty: {
|
|
3487
|
-
minHeight: 72,
|
|
3488
|
-
alignItems: "center",
|
|
3489
|
-
justifyContent: "center",
|
|
3490
|
-
padding: theme.tokens.spacing[4]
|
|
3491
|
-
},
|
|
3492
|
-
emptyText: {
|
|
3493
|
-
color: theme.components.select.dropdown.empty.fg,
|
|
3494
|
-
fontFamily: theme.tokens.typography.family.regular,
|
|
3495
|
-
fontSize: theme.tokens.typography.size.md,
|
|
3496
|
-
lineHeight: theme.tokens.typography.lineHeight.md,
|
|
3497
|
-
textAlign: "center"
|
|
3498
|
-
},
|
|
3499
|
-
loading: {
|
|
3500
|
-
minHeight: 72,
|
|
3501
|
-
flexDirection: "row",
|
|
3502
|
-
alignItems: "center",
|
|
3503
|
-
justifyContent: "center",
|
|
3504
|
-
gap: theme.tokens.spacing[2],
|
|
3505
|
-
padding: theme.tokens.spacing[4]
|
|
3506
|
-
},
|
|
3507
|
-
loadingText: {
|
|
3508
|
-
color: theme.components.select.dropdown.fg,
|
|
3509
|
-
fontFamily: theme.tokens.typography.family.regular,
|
|
3510
|
-
fontSize: theme.tokens.typography.size.md,
|
|
3511
|
-
lineHeight: theme.tokens.typography.lineHeight.md
|
|
3512
|
-
}
|
|
3513
|
-
});
|
|
3514
|
-
//#endregion
|
|
3515
|
-
//#region src/components/Select/Content/SelectEmpty.tsx
|
|
3516
|
-
const renderText$1 = (node, style) => {
|
|
3517
|
-
if (typeof node === "string" || typeof node === "number") return /* @__PURE__ */ jsx(Text, {
|
|
3518
|
-
style,
|
|
3519
|
-
children: node
|
|
3520
|
-
});
|
|
3521
|
-
return node;
|
|
3522
|
-
};
|
|
3523
|
-
const SelectEmpty = createSelectSlot("empty", "Select.Empty");
|
|
3524
|
-
const SelectEmptyState = () => {
|
|
3525
|
-
const styles = useThemeStyles(createContentStyles);
|
|
3526
|
-
const { empty } = useSelectContext();
|
|
3527
|
-
return /* @__PURE__ */ jsx(View, {
|
|
3528
|
-
style: styles.empty,
|
|
3529
|
-
children: renderText$1(empty, styles.emptyText)
|
|
3530
|
-
});
|
|
3531
|
-
};
|
|
3532
|
-
SelectEmptyState.displayName = "Select.EmptyState";
|
|
3533
|
-
//#endregion
|
|
3534
|
-
//#region src/components/Select/Content/SelectLoading.tsx
|
|
3535
|
-
const renderText = (node, style) => {
|
|
3536
|
-
if (typeof node === "string" || typeof node === "number") return /* @__PURE__ */ jsx(Text, {
|
|
3537
|
-
style,
|
|
3538
|
-
children: node
|
|
3539
|
-
});
|
|
3540
|
-
return node;
|
|
3541
|
-
};
|
|
3542
|
-
const SelectLoading = createSelectSlot("loading", "Select.Loading");
|
|
3543
|
-
const SelectLoadingState = () => {
|
|
3544
|
-
const { theme } = useTheme();
|
|
3545
|
-
const styles = useThemeStyles(createContentStyles);
|
|
3546
|
-
const { loadingContent } = useSelectContext();
|
|
3547
|
-
return /* @__PURE__ */ jsxs(View, {
|
|
3548
|
-
style: styles.loading,
|
|
3549
|
-
children: [/* @__PURE__ */ jsx(ActivityIndicator, {
|
|
3550
|
-
testID: "select-content-loading-indicator",
|
|
3551
|
-
size: "small",
|
|
3552
|
-
color: theme.components.select.dropdown.fg
|
|
3553
|
-
}), renderText(loadingContent, styles.loadingText)]
|
|
3906
|
+
//#endregion
|
|
3907
|
+
//#region src/components/Select/Presentation/SelectSheet.tsx
|
|
3908
|
+
const SelectSheet = ({ visible, onClose, outsidePressProps, zIndex, contentStyle, children }) => {
|
|
3909
|
+
const styles = useThemeStyles(createPresentationStyles);
|
|
3910
|
+
return /* @__PURE__ */ jsx(Modal$1, {
|
|
3911
|
+
transparent: true,
|
|
3912
|
+
visible,
|
|
3913
|
+
animationType: "slide",
|
|
3914
|
+
onRequestClose: onClose,
|
|
3915
|
+
children: /* @__PURE__ */ jsxs(View, {
|
|
3916
|
+
style: [
|
|
3917
|
+
styles.modalRoot,
|
|
3918
|
+
styles.sheetRoot,
|
|
3919
|
+
Platform.OS === "web" && { zIndex }
|
|
3920
|
+
],
|
|
3921
|
+
testID: "select-content-root",
|
|
3922
|
+
children: [/* @__PURE__ */ jsx(SelectBackdrop, { outsidePressProps }), /* @__PURE__ */ jsxs(View, {
|
|
3923
|
+
style: [
|
|
3924
|
+
styles.content,
|
|
3925
|
+
styles.sheet,
|
|
3926
|
+
contentStyle
|
|
3927
|
+
],
|
|
3928
|
+
testID: "select-sheet",
|
|
3929
|
+
children: [/* @__PURE__ */ jsx(SelectHandle, {}), children]
|
|
3930
|
+
})]
|
|
3931
|
+
})
|
|
3554
3932
|
});
|
|
3555
3933
|
};
|
|
3556
|
-
|
|
3934
|
+
SelectSheet.displayName = "Select.Sheet";
|
|
3557
3935
|
//#endregion
|
|
3558
|
-
//#region src/components/Select/
|
|
3936
|
+
//#region src/components/Select/Search/SelectSearch.styles.ts
|
|
3559
3937
|
const createSearchStyles = (theme) => StyleSheet.create({
|
|
3560
3938
|
searchWrap: {
|
|
3561
3939
|
flexDirection: "row",
|
|
@@ -3597,7 +3975,7 @@ const createSearchStyles = (theme) => StyleSheet.create({
|
|
|
3597
3975
|
}
|
|
3598
3976
|
});
|
|
3599
3977
|
//#endregion
|
|
3600
|
-
//#region src/components/Select/
|
|
3978
|
+
//#region src/components/Select/Search/SelectSearch.tsx
|
|
3601
3979
|
const SelectSearch = createSelectSlot("search", "Select.Search");
|
|
3602
3980
|
const SelectSearchField = () => {
|
|
3603
3981
|
const { theme } = useTheme();
|
|
@@ -3652,6 +4030,13 @@ const SelectSearchField = () => {
|
|
|
3652
4030
|
};
|
|
3653
4031
|
SelectSearchField.displayName = "Select.SearchField";
|
|
3654
4032
|
//#endregion
|
|
4033
|
+
//#region src/components/Select/Separator/SelectSeparator.tsx
|
|
4034
|
+
const SelectSeparator = createSelectSlot("separator", "Select.Separator");
|
|
4035
|
+
const SelectSeparatorRow = () => {
|
|
4036
|
+
return /* @__PURE__ */ jsx(View, { style: useThemeStyles(createGroupStyles).separator });
|
|
4037
|
+
};
|
|
4038
|
+
SelectSeparatorRow.displayName = "Select.SeparatorRow";
|
|
4039
|
+
//#endregion
|
|
3655
4040
|
//#region src/components/Select/Content/SelectContent.tsx
|
|
3656
4041
|
const SelectContent = createSelectSlot("content", "Select.Content");
|
|
3657
4042
|
const SelectContentSurface = () => {
|
|
@@ -3659,13 +4044,13 @@ const SelectContentSurface = () => {
|
|
|
3659
4044
|
const wasOpenRef = useRef(false);
|
|
3660
4045
|
const [openCycle, setOpenCycle] = useState(0);
|
|
3661
4046
|
const context = useSelectContext();
|
|
3662
|
-
const { isOpen, resolvedPresentation, 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;
|
|
3663
4048
|
const initialScrollIndex = Boolean(context.virtual) && selectedRowIndex > 0 && query === "" ? selectedRowIndex : void 0;
|
|
3664
4049
|
useEffect(() => {
|
|
3665
4050
|
if (isOpen && !wasOpenRef.current) setOpenCycle((cycle) => cycle + 1);
|
|
3666
4051
|
wasOpenRef.current = isOpen;
|
|
3667
4052
|
}, [isOpen]);
|
|
3668
|
-
const renderRow = ({ item }) => {
|
|
4053
|
+
const renderRow = ({ item, index }) => {
|
|
3669
4054
|
if (item.type === "group") {
|
|
3670
4055
|
if (item.selectable && context.multiple) {
|
|
3671
4056
|
const enabledGroupValues = item.itemValues.filter((value) => context.optionsByValue.get(value));
|
|
@@ -3687,6 +4072,9 @@ const SelectContentSurface = () => {
|
|
|
3687
4072
|
option: item.option,
|
|
3688
4073
|
isSelected,
|
|
3689
4074
|
isDisabled: Boolean(item.option.disabled || maxReached),
|
|
4075
|
+
itemIndex: index,
|
|
4076
|
+
selectedValues,
|
|
4077
|
+
multiple: context.multiple,
|
|
3690
4078
|
optionStyle,
|
|
3691
4079
|
onSelect: selectOption
|
|
3692
4080
|
});
|
|
@@ -3749,15 +4137,17 @@ const SelectContentSurface = () => {
|
|
|
3749
4137
|
if (resolvedPresentation === "sheet") return /* @__PURE__ */ jsx(SelectSheet, {
|
|
3750
4138
|
visible: isOpen,
|
|
3751
4139
|
onClose: closeContent,
|
|
3752
|
-
|
|
4140
|
+
outsidePressProps: getOutsidePressProps({ accessibilityLabel: "Dismiss select" }),
|
|
4141
|
+
zIndex,
|
|
3753
4142
|
contentStyle,
|
|
3754
4143
|
children: body
|
|
3755
4144
|
});
|
|
3756
4145
|
if (resolvedPresentation === "popover") return /* @__PURE__ */ jsx(SelectPopover, {
|
|
3757
4146
|
visible: isOpen,
|
|
3758
4147
|
onClose: closeContent,
|
|
3759
|
-
|
|
4148
|
+
outsidePressProps: getOutsidePressProps({ accessibilityLabel: "Dismiss select" }),
|
|
3760
4149
|
position,
|
|
4150
|
+
zIndex,
|
|
3761
4151
|
onFloatingLayout,
|
|
3762
4152
|
matchTriggerWidth,
|
|
3763
4153
|
triggerWidth,
|
|
@@ -3767,104 +4157,28 @@ const SelectContentSurface = () => {
|
|
|
3767
4157
|
return /* @__PURE__ */ jsx(SelectModal, {
|
|
3768
4158
|
visible: isOpen,
|
|
3769
4159
|
onClose: closeContent,
|
|
3770
|
-
|
|
4160
|
+
outsidePressProps: getOutsidePressProps({ accessibilityLabel: "Dismiss select" }),
|
|
4161
|
+
zIndex,
|
|
3771
4162
|
contentStyle,
|
|
3772
4163
|
children: body
|
|
3773
4164
|
});
|
|
3774
4165
|
};
|
|
3775
4166
|
SelectContentSurface.displayName = "Select.ContentSurface";
|
|
3776
4167
|
//#endregion
|
|
3777
|
-
//#region src/components/Select/
|
|
3778
|
-
const
|
|
3779
|
-
const descriptionText = typeof description === "string" || typeof description === "number" ? String(description) : void 0;
|
|
3780
|
-
const errorText = typeof error === "string" || typeof error === "number" ? String(error) : void 0;
|
|
3781
|
-
return {
|
|
3782
|
-
resolvedLabel: accessibilityLabel ?? label ?? selectedLabel ?? placeholder ?? "Select",
|
|
3783
|
-
resolvedHint: accessibilityHint ?? (invalid && errorText ? errorText : descriptionText ? descriptionText : hasFieldContext && fieldDescribedBy ? "Opens a list of options" : void 0),
|
|
3784
|
-
announce: (message) => {
|
|
3785
|
-
AccessibilityInfo.announceForAccessibility?.(message);
|
|
3786
|
-
}
|
|
3787
|
-
};
|
|
3788
|
-
};
|
|
4168
|
+
//#region src/components/Select/Icon/SelectIcon.tsx
|
|
4169
|
+
const SelectIcon = createSelectSlot("icon", "Select.Icon");
|
|
3789
4170
|
//#endregion
|
|
3790
|
-
//#region src/components/Select/
|
|
3791
|
-
const
|
|
3792
|
-
const parsedChildren = useMemo(() => parseSelectChildren(children), [children]);
|
|
3793
|
-
const options = useMemo(() => [...optionsProp ?? [], ...parsedChildren.options], [optionsProp, parsedChildren.options]);
|
|
3794
|
-
return {
|
|
3795
|
-
options,
|
|
3796
|
-
rows: useMemo(() => {
|
|
3797
|
-
if (parsedChildren.rows.length > 0) return parsedChildren.rows;
|
|
3798
|
-
return options.map((option) => ({
|
|
3799
|
-
type: "item",
|
|
3800
|
-
key: `item-${option.value}`,
|
|
3801
|
-
option
|
|
3802
|
-
}));
|
|
3803
|
-
}, [options, parsedChildren.rows]),
|
|
3804
|
-
searchableFromChildren: parsedChildren.searchable,
|
|
3805
|
-
searchPlaceholderFromChildren: parsedChildren.searchPlaceholder,
|
|
3806
|
-
emptyFromChildren: parsedChildren.empty,
|
|
3807
|
-
loadingFromChildren: parsedChildren.loading
|
|
3808
|
-
};
|
|
3809
|
-
};
|
|
4171
|
+
//#region src/components/Select/ItemBadge/SelectItemBadge.tsx
|
|
4172
|
+
const SelectItemBadge = createSelectSlot("itemBadge", "Select.ItemBadge");
|
|
3810
4173
|
//#endregion
|
|
3811
|
-
//#region src/components/Select/
|
|
3812
|
-
const
|
|
3813
|
-
const [query, setQuery] = useState("");
|
|
3814
|
-
const shouldSearch = searchable ?? searchableFromChildren ?? Boolean(onSearch);
|
|
3815
|
-
const shouldFilter = filterOptions ?? !onSearch;
|
|
3816
|
-
const filteredRows = useMemo(() => {
|
|
3817
|
-
if (!query || !shouldFilter) return rows;
|
|
3818
|
-
const visibleRows = [];
|
|
3819
|
-
let pendingGroup;
|
|
3820
|
-
rows.forEach((row) => {
|
|
3821
|
-
if (row.type === "group") {
|
|
3822
|
-
pendingGroup = row;
|
|
3823
|
-
return;
|
|
3824
|
-
}
|
|
3825
|
-
if (row.type === "separator") {
|
|
3826
|
-
if (visibleRows.length > 0 && visibleRows[visibleRows.length - 1]?.type !== "separator") visibleRows.push(row);
|
|
3827
|
-
return;
|
|
3828
|
-
}
|
|
3829
|
-
if (!filter(row.option, query)) return;
|
|
3830
|
-
if (pendingGroup) {
|
|
3831
|
-
visibleRows.push(pendingGroup);
|
|
3832
|
-
pendingGroup = void 0;
|
|
3833
|
-
}
|
|
3834
|
-
visibleRows.push(row);
|
|
3835
|
-
});
|
|
3836
|
-
return visibleRows.filter((row, index, collection) => {
|
|
3837
|
-
if (row.type !== "separator") return true;
|
|
3838
|
-
return index > 0 && index < collection.length - 1 && collection[index - 1]?.type !== "separator";
|
|
3839
|
-
});
|
|
3840
|
-
}, [
|
|
3841
|
-
filter,
|
|
3842
|
-
query,
|
|
3843
|
-
rows,
|
|
3844
|
-
shouldFilter
|
|
3845
|
-
]);
|
|
3846
|
-
useEffect(() => {
|
|
3847
|
-
if (!isOpen) {
|
|
3848
|
-
setQuery("");
|
|
3849
|
-
return;
|
|
3850
|
-
}
|
|
3851
|
-
if (shouldSearch) onSearch?.(query);
|
|
3852
|
-
}, [
|
|
3853
|
-
isOpen,
|
|
3854
|
-
onSearch,
|
|
3855
|
-
query,
|
|
3856
|
-
shouldSearch
|
|
3857
|
-
]);
|
|
3858
|
-
return {
|
|
3859
|
-
query,
|
|
3860
|
-
setQuery,
|
|
3861
|
-
shouldSearch,
|
|
3862
|
-
filteredRows
|
|
3863
|
-
};
|
|
3864
|
-
};
|
|
4174
|
+
//#region src/components/Select/ItemDescription/SelectItemDescription.tsx
|
|
4175
|
+
const SelectItemDescription = createSelectSlot("itemDescription", "Select.ItemDescription");
|
|
3865
4176
|
//#endregion
|
|
3866
|
-
//#region src/components/Select/
|
|
3867
|
-
const
|
|
4177
|
+
//#region src/components/Select/ItemIcon/SelectItemIcon.tsx
|
|
4178
|
+
const SelectItemIcon = createSelectSlot("itemIcon", "Select.ItemIcon");
|
|
4179
|
+
//#endregion
|
|
4180
|
+
//#region src/components/Select/Label/SelectLabel.tsx
|
|
4181
|
+
const SelectLabel = createSelectSlot("label", "Select.Label");
|
|
3868
4182
|
//#endregion
|
|
3869
4183
|
//#region src/components/Select/Trigger/SelectTrigger.styles.ts
|
|
3870
4184
|
const createTriggerStyles = (theme) => StyleSheet.create({
|
|
@@ -3961,9 +4275,9 @@ const createTriggerStyles = (theme) => StyleSheet.create({
|
|
|
3961
4275
|
//#endregion
|
|
3962
4276
|
//#region src/components/Select/Trigger/SelectTrigger.tsx
|
|
3963
4277
|
const SelectTriggerSlot = createSelectSlot("trigger", "Select.Trigger");
|
|
3964
|
-
const nativePointerEventsNone$
|
|
4278
|
+
const nativePointerEventsNone$2 = Platform.OS === "web" ? void 0 : { pointerEvents: "none" };
|
|
3965
4279
|
const nativePointerEventsBoxNone = Platform.OS === "web" ? void 0 : { pointerEvents: "box-none" };
|
|
3966
|
-
const webPointerEventsNone$
|
|
4280
|
+
const webPointerEventsNone$2 = Platform.OS === "web" ? { pointerEvents: "none" } : void 0;
|
|
3967
4281
|
const webPointerEventsBoxNone = Platform.OS === "web" ? { pointerEvents: "box-none" } : void 0;
|
|
3968
4282
|
function SelectTrigger({ displayText, isPlaceholder, isOpen, size = "md", color = "primary", variant = "outline", disabled = false, required = false, hasError = false, hasValue = false, loading = false, clearable = false, startIcon, endIcon, prefix, suffix, accessibilityLabel, accessibilityHint, nativeID, accessibilityLabelledBy, ariaDescribedBy, triggerStyle, textStyle, onPress, onClear }) {
|
|
3969
4283
|
const { theme } = useTheme();
|
|
@@ -4058,8 +4372,8 @@ function SelectTrigger({ displayText, isPlaceholder, isOpen, size = "md", color
|
|
|
4058
4372
|
],
|
|
4059
4373
|
children: [
|
|
4060
4374
|
startIcon && /* @__PURE__ */ jsx(View, {
|
|
4061
|
-
...nativePointerEventsNone$
|
|
4062
|
-
style: [styles.startIcon, webPointerEventsNone$
|
|
4375
|
+
...nativePointerEventsNone$2,
|
|
4376
|
+
style: [styles.startIcon, webPointerEventsNone$2],
|
|
4063
4377
|
accessibilityElementsHidden: true,
|
|
4064
4378
|
importantForAccessibility: "no",
|
|
4065
4379
|
children: renderIcon(startIcon)
|
|
@@ -4081,8 +4395,8 @@ function SelectTrigger({ displayText, isPlaceholder, isOpen, size = "md", color
|
|
|
4081
4395
|
size: "small",
|
|
4082
4396
|
color: iconColor
|
|
4083
4397
|
}) : showClearButton ? null : endIcon ? /* @__PURE__ */ jsx(View, {
|
|
4084
|
-
...nativePointerEventsNone$
|
|
4085
|
-
style: [styles.endIcon, webPointerEventsNone$
|
|
4398
|
+
...nativePointerEventsNone$2,
|
|
4399
|
+
style: [styles.endIcon, webPointerEventsNone$2],
|
|
4086
4400
|
accessibilityElementsHidden: true,
|
|
4087
4401
|
importantForAccessibility: "no",
|
|
4088
4402
|
children: renderIcon(endIcon)
|
|
@@ -4119,51 +4433,321 @@ function SelectTrigger({ displayText, isPlaceholder, isOpen, size = "md", color
|
|
|
4119
4433
|
})]
|
|
4120
4434
|
});
|
|
4121
4435
|
}
|
|
4122
|
-
SelectTrigger.displayName = "SelectTrigger";
|
|
4436
|
+
SelectTrigger.displayName = "SelectTrigger";
|
|
4437
|
+
//#endregion
|
|
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;
|
|
4471
|
+
return;
|
|
4472
|
+
}
|
|
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";
|
|
4487
|
+
});
|
|
4488
|
+
}, [
|
|
4489
|
+
filter,
|
|
4490
|
+
query,
|
|
4491
|
+
rows,
|
|
4492
|
+
shouldFilter
|
|
4493
|
+
]);
|
|
4494
|
+
useEffect(() => {
|
|
4495
|
+
if (!isOpen) {
|
|
4496
|
+
setQuery("");
|
|
4497
|
+
return;
|
|
4498
|
+
}
|
|
4499
|
+
if (shouldSearch) onSearch?.(query);
|
|
4500
|
+
}, [
|
|
4501
|
+
isOpen,
|
|
4502
|
+
onSearch,
|
|
4503
|
+
query,
|
|
4504
|
+
shouldSearch
|
|
4505
|
+
]);
|
|
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(() => ({
|
|
4593
|
+
color,
|
|
4594
|
+
variant,
|
|
4595
|
+
isOpen,
|
|
4596
|
+
loading,
|
|
4597
|
+
searchable,
|
|
4598
|
+
multiple,
|
|
4599
|
+
maxSelected,
|
|
4600
|
+
virtual,
|
|
4601
|
+
resolvedLabel,
|
|
4602
|
+
resolvedPresentation,
|
|
4603
|
+
zIndex,
|
|
4604
|
+
position,
|
|
4605
|
+
onFloatingLayout,
|
|
4606
|
+
matchTriggerWidth,
|
|
4607
|
+
triggerWidth,
|
|
4608
|
+
selectedValues,
|
|
4609
|
+
selectedOptions,
|
|
4610
|
+
optionsByValue,
|
|
4611
|
+
filteredRows,
|
|
4612
|
+
selectedRowIndex,
|
|
4613
|
+
itemHeight,
|
|
4614
|
+
query,
|
|
4615
|
+
searchPlaceholder,
|
|
4616
|
+
searchInputRef,
|
|
4617
|
+
empty,
|
|
4618
|
+
loadingContent,
|
|
4619
|
+
closeContent,
|
|
4620
|
+
getOutsidePressProps,
|
|
4621
|
+
selectOption,
|
|
4622
|
+
selectGroup,
|
|
4623
|
+
setQuery,
|
|
4624
|
+
renderOption,
|
|
4625
|
+
contentStyle,
|
|
4626
|
+
optionStyle,
|
|
4627
|
+
searchStyle
|
|
4628
|
+
}), [
|
|
4629
|
+
color,
|
|
4630
|
+
variant,
|
|
4631
|
+
isOpen,
|
|
4632
|
+
loading,
|
|
4633
|
+
searchable,
|
|
4634
|
+
multiple,
|
|
4635
|
+
maxSelected,
|
|
4636
|
+
virtual,
|
|
4637
|
+
resolvedLabel,
|
|
4638
|
+
resolvedPresentation,
|
|
4639
|
+
zIndex,
|
|
4640
|
+
position,
|
|
4641
|
+
onFloatingLayout,
|
|
4642
|
+
matchTriggerWidth,
|
|
4643
|
+
triggerWidth,
|
|
4644
|
+
selectedValues,
|
|
4645
|
+
selectedOptions,
|
|
4646
|
+
optionsByValue,
|
|
4647
|
+
filteredRows,
|
|
4648
|
+
selectedRowIndex,
|
|
4649
|
+
itemHeight,
|
|
4650
|
+
query,
|
|
4651
|
+
searchPlaceholder,
|
|
4652
|
+
searchInputRef,
|
|
4653
|
+
empty,
|
|
4654
|
+
loadingContent,
|
|
4655
|
+
closeContent,
|
|
4656
|
+
getOutsidePressProps,
|
|
4657
|
+
selectOption,
|
|
4658
|
+
selectGroup,
|
|
4659
|
+
setQuery,
|
|
4660
|
+
renderOption,
|
|
4661
|
+
contentStyle,
|
|
4662
|
+
optionStyle,
|
|
4663
|
+
searchStyle
|
|
4664
|
+
]);
|
|
4665
|
+
}
|
|
4123
4666
|
//#endregion
|
|
4124
|
-
//#region src/components/Select/
|
|
4125
|
-
|
|
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
|
+
}
|
|
4126
4692
|
//#endregion
|
|
4127
|
-
//#region src/components/Select/Root/
|
|
4128
|
-
function
|
|
4129
|
-
const
|
|
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;
|
|
4130
4724
|
const field = useFormFieldContext();
|
|
4131
4725
|
const overlayId = useId();
|
|
4132
4726
|
const hasOwnField = Boolean(label || description || error);
|
|
4133
4727
|
const [triggerWidth, setTriggerWidth] = useState();
|
|
4134
4728
|
const triggerRef = useRef(null);
|
|
4135
|
-
const { position, placement: resolvedPlacement, updatePosition, onFloatingLayout } = useNativeFloatingPosition(placement, offset);
|
|
4136
4729
|
const searchInputRef = useRef(null);
|
|
4137
4730
|
const selectedFocusValueRef = useRef(void 0);
|
|
4138
4731
|
const resolvedPresentation = useOverlayPresentation(presentation);
|
|
4732
|
+
const { position, onFloatingLayout } = useNativeFloatingPosition(placement, offset);
|
|
4139
4733
|
const { options, rows, searchableFromChildren, searchPlaceholderFromChildren, emptyFromChildren, loadingFromChildren } = useSelectCollection(children, optionsProp);
|
|
4140
4734
|
const resolvedSize = size ?? field?.size ?? "md";
|
|
4141
4735
|
const isInvalid = invalid || Boolean(error) || !hasOwnField && Boolean(field?.invalid);
|
|
4142
4736
|
const isDisabled = disabled || !hasOwnField && Boolean(field?.disabled);
|
|
4143
4737
|
const isRequired = required || !hasOwnField && Boolean(field?.required);
|
|
4144
|
-
const {
|
|
4145
|
-
|
|
4146
|
-
defaultValue: props.multiple ? props.defaultValue : props.defaultValue === null ? "" : props.defaultValue,
|
|
4147
|
-
onValueChange: (nextValue) => {
|
|
4148
|
-
if (props.multiple) {
|
|
4149
|
-
props.onValueChange?.(nextValue);
|
|
4150
|
-
return;
|
|
4151
|
-
}
|
|
4152
|
-
props.onValueChange?.(nextValue === "" ? null : nextValue);
|
|
4153
|
-
},
|
|
4738
|
+
const { setSelectedValue, selectedValues, selectedOption, selectedOptions, optionsByValue, isOpen, openDropdown, closeDropdown, selectValue } = useSelectRootSelection({
|
|
4739
|
+
props,
|
|
4154
4740
|
options,
|
|
4155
|
-
|
|
4156
|
-
maxSelected,
|
|
4157
|
-
closeOnSelect,
|
|
4158
|
-
disabled: isDisabled,
|
|
4159
|
-
open,
|
|
4160
|
-
defaultOpen,
|
|
4161
|
-
onOpenChange
|
|
4741
|
+
isDisabled
|
|
4162
4742
|
});
|
|
4163
|
-
const
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4743
|
+
const { restoreFocusAfterClose } = useOverlayFocusRestore({
|
|
4744
|
+
active: isOpen,
|
|
4745
|
+
triggerRef
|
|
4746
|
+
});
|
|
4747
|
+
const closeAndFocusTrigger = useCallback(() => {
|
|
4748
|
+
closeDropdown();
|
|
4749
|
+
restoreFocusAfterClose();
|
|
4750
|
+
}, [closeDropdown, restoreFocusAfterClose]);
|
|
4167
4751
|
const { query, setQuery, shouldSearch, filteredRows } = useSelectSearch({
|
|
4168
4752
|
rows,
|
|
4169
4753
|
isOpen,
|
|
@@ -4176,24 +4760,15 @@ function SelectRoot(props) {
|
|
|
4176
4760
|
const selectedFocusValue = selectedValues.includes(selectedFocusValueRef.current ?? "") ? selectedFocusValueRef.current : selectedValues[0];
|
|
4177
4761
|
const selectedRowIndex = Math.max(0, filteredRows.findIndex((row) => row.type === "item" && row.option.value === selectedFocusValue));
|
|
4178
4762
|
const itemHeight = typeof virtual === "object" ? virtual.estimatedItemSize ?? 46 : 46;
|
|
4179
|
-
const displayValue =
|
|
4180
|
-
|
|
4181
|
-
placeholder,
|
|
4182
|
-
multiple: Boolean(props.multiple)
|
|
4183
|
-
});
|
|
4184
|
-
if (props.multiple && selectedOptions.length > 0) {
|
|
4185
|
-
const visibleLabels = selectedOptions.slice(0, 2).map((option) => option.label);
|
|
4186
|
-
return selectedOptions.length > 2 ? `${visibleLabels.join(", ")} +${selectedOptions.length - 2}` : visibleLabels.join(", ");
|
|
4187
|
-
}
|
|
4188
|
-
return selectedOption?.label ?? placeholder;
|
|
4189
|
-
}, [
|
|
4763
|
+
const displayValue = useSelectRootDisplayValue({
|
|
4764
|
+
multiple: Boolean(props.multiple),
|
|
4190
4765
|
placeholder,
|
|
4191
|
-
props.multiple,
|
|
4192
4766
|
renderValue,
|
|
4193
4767
|
selectedOption,
|
|
4194
|
-
selectedOptions
|
|
4195
|
-
|
|
4196
|
-
|
|
4768
|
+
selectedOptions,
|
|
4769
|
+
selectedValues
|
|
4770
|
+
});
|
|
4771
|
+
const { resolvedLabel, resolvedHint, announce } = resolveSelectAccessibility({
|
|
4197
4772
|
accessibilityLabel,
|
|
4198
4773
|
accessibilityHint,
|
|
4199
4774
|
label: !hasOwnField ? void 0 : label,
|
|
@@ -4210,111 +4785,106 @@ function SelectRoot(props) {
|
|
|
4210
4785
|
id: overlayId,
|
|
4211
4786
|
active: isOpen,
|
|
4212
4787
|
closeOnOutsidePress: dismissOnBackdropPress,
|
|
4213
|
-
requestClose:
|
|
4788
|
+
requestClose: closeAndFocusTrigger
|
|
4214
4789
|
});
|
|
4215
|
-
const clearValue = (
|
|
4216
|
-
selectedFocusValueRef.current = void 0;
|
|
4217
|
-
selectValue("");
|
|
4218
|
-
announce("Selection cleared");
|
|
4219
|
-
};
|
|
4220
|
-
const selectOption = (option) => {
|
|
4221
|
-
if (option.disabled) return;
|
|
4222
|
-
const selectedBefore = selectedValues.includes(option.value);
|
|
4223
|
-
if (Boolean(props.multiple) && !selectedBefore && typeof maxSelected === "number" && selectedValues.length >= maxSelected) return;
|
|
4224
|
-
selectedFocusValueRef.current = option.value;
|
|
4225
|
-
selectValue(option.value);
|
|
4226
|
-
announce(`${option.label} selected`);
|
|
4227
|
-
};
|
|
4228
|
-
const selectGroup = (values) => {
|
|
4229
|
-
if (!props.multiple || values.length === 0) return;
|
|
4230
|
-
const enabledValues = values.filter((value) => optionsByValue.has(value));
|
|
4231
|
-
const selectedGroupValues = enabledValues.filter((value) => selectedValues.includes(value));
|
|
4232
|
-
const outsideSelectedCount = selectedValues.filter((value) => !enabledValues.includes(value)).length;
|
|
4233
|
-
const maxSelectableGroupCount = typeof maxSelected === "number" ? Math.max(0, Math.min(enabledValues.length, maxSelected - outsideSelectedCount)) : enabledValues.length;
|
|
4234
|
-
if (selectedGroupValues.length > 0 && selectedGroupValues.length >= maxSelectableGroupCount) {
|
|
4235
|
-
selectedFocusValueRef.current = void 0;
|
|
4236
|
-
setSelectedValue(selectedValues.filter((value) => !enabledValues.includes(value)));
|
|
4237
|
-
announce("Group selection cleared");
|
|
4238
|
-
return;
|
|
4239
|
-
}
|
|
4240
|
-
const nextValues = [...selectedValues];
|
|
4241
|
-
for (const value of enabledValues) {
|
|
4242
|
-
if (nextValues.includes(value)) continue;
|
|
4243
|
-
if (typeof maxSelected === "number" && nextValues.length >= maxSelected) break;
|
|
4244
|
-
nextValues.push(value);
|
|
4245
|
-
}
|
|
4246
|
-
setSelectedValue(nextValues);
|
|
4247
|
-
selectedFocusValueRef.current = nextValues.at(-1);
|
|
4248
|
-
announce("Group selected");
|
|
4249
|
-
if (closeOnSelect) closeDropdown();
|
|
4250
|
-
};
|
|
4251
|
-
const openContent = () => {
|
|
4252
|
-
updatePosition(triggerRef);
|
|
4253
|
-
openDropdown();
|
|
4254
|
-
};
|
|
4255
|
-
const contextValue = {
|
|
4256
|
-
label,
|
|
4257
|
-
description,
|
|
4258
|
-
error,
|
|
4259
|
-
placeholder,
|
|
4260
|
-
color,
|
|
4261
|
-
variant,
|
|
4262
|
-
size: resolvedSize,
|
|
4263
|
-
isOpen,
|
|
4264
|
-
hasValue,
|
|
4265
|
-
loading,
|
|
4266
|
-
clearable,
|
|
4267
|
-
searchable: shouldSearch,
|
|
4790
|
+
const { clearValue, selectOption, selectGroup } = useSelectRootActions({
|
|
4268
4791
|
multiple: Boolean(props.multiple),
|
|
4269
4792
|
maxSelected,
|
|
4270
|
-
|
|
4271
|
-
resolvedLabel,
|
|
4272
|
-
resolvedHint,
|
|
4273
|
-
resolvedPresentation,
|
|
4274
|
-
placement: resolvedPlacement,
|
|
4275
|
-
position,
|
|
4276
|
-
onFloatingLayout,
|
|
4277
|
-
dismissOnBackdropPress,
|
|
4278
|
-
matchTriggerWidth,
|
|
4279
|
-
triggerWidth,
|
|
4793
|
+
closeOnSelect,
|
|
4280
4794
|
selectedValues,
|
|
4281
|
-
selectedOptions,
|
|
4282
4795
|
optionsByValue,
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
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,
|
|
4294
4851
|
clearValue,
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
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
|
+
}
|
|
4312
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);
|
|
4313
4883
|
const control = /* @__PURE__ */ jsx(SelectContext.Provider, {
|
|
4314
4884
|
value: contextValue,
|
|
4315
4885
|
children: /* @__PURE__ */ jsxs(View, {
|
|
4316
4886
|
ref: triggerRef,
|
|
4317
|
-
testID,
|
|
4887
|
+
testID: controlProps.testID,
|
|
4318
4888
|
onLayout: (event) => setTriggerWidth(event.nativeEvent.layout.width),
|
|
4319
4889
|
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
4320
4890
|
displayText: displayValue,
|
|
@@ -4322,24 +4892,24 @@ function SelectRoot(props) {
|
|
|
4322
4892
|
isOpen,
|
|
4323
4893
|
hasValue,
|
|
4324
4894
|
size: resolvedSize,
|
|
4325
|
-
color,
|
|
4326
|
-
variant,
|
|
4895
|
+
color: controlProps.color,
|
|
4896
|
+
variant: controlProps.variant,
|
|
4327
4897
|
disabled: isDisabled,
|
|
4328
4898
|
required: isRequired,
|
|
4329
4899
|
hasError: isInvalid,
|
|
4330
|
-
loading,
|
|
4331
|
-
clearable,
|
|
4332
|
-
startIcon,
|
|
4333
|
-
endIcon,
|
|
4334
|
-
prefix,
|
|
4335
|
-
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,
|
|
4336
4906
|
nativeID: !hasOwnField ? field?.controlId : void 0,
|
|
4337
4907
|
accessibilityLabel: resolvedLabel,
|
|
4338
4908
|
accessibilityHint: resolvedHint,
|
|
4339
4909
|
accessibilityLabelledBy: !hasOwnField ? field?.labelId : void 0,
|
|
4340
4910
|
ariaDescribedBy: !hasOwnField ? field?.ariaDescribedBy : void 0,
|
|
4341
|
-
triggerStyle,
|
|
4342
|
-
textStyle,
|
|
4911
|
+
triggerStyle: controlProps.triggerStyle,
|
|
4912
|
+
textStyle: controlProps.textStyle,
|
|
4343
4913
|
onPress: openDropdown,
|
|
4344
4914
|
onClear: clearValue
|
|
4345
4915
|
}), /* @__PURE__ */ jsx(SelectContentSurface, {})]
|
|
@@ -4347,19 +4917,22 @@ function SelectRoot(props) {
|
|
|
4347
4917
|
});
|
|
4348
4918
|
if (!hasOwnField && field) return control;
|
|
4349
4919
|
return /* @__PURE__ */ jsx(FormField, {
|
|
4350
|
-
label,
|
|
4351
|
-
description,
|
|
4352
|
-
error,
|
|
4920
|
+
label: formFieldProps.label,
|
|
4921
|
+
description: formFieldProps.description,
|
|
4922
|
+
error: formFieldProps.error,
|
|
4353
4923
|
required: isRequired,
|
|
4354
4924
|
disabled: isDisabled,
|
|
4355
4925
|
invalid: isInvalid,
|
|
4356
4926
|
size: resolvedSize,
|
|
4357
|
-
style,
|
|
4927
|
+
style: formFieldProps.style,
|
|
4358
4928
|
children: control
|
|
4359
4929
|
});
|
|
4360
4930
|
}
|
|
4361
4931
|
SelectRoot.displayName = "Select";
|
|
4362
4932
|
//#endregion
|
|
4933
|
+
//#region src/components/Select/Value/SelectValue.tsx
|
|
4934
|
+
const SelectValue = createSelectSlot("value", "Select.Value");
|
|
4935
|
+
//#endregion
|
|
4363
4936
|
//#region src/components/Select/Select.tsx
|
|
4364
4937
|
const Select = Object.assign(SelectRoot, {
|
|
4365
4938
|
Trigger: SelectTriggerSlot,
|
|
@@ -4378,7 +4951,7 @@ const Select = Object.assign(SelectRoot, {
|
|
|
4378
4951
|
Loading: SelectLoading
|
|
4379
4952
|
});
|
|
4380
4953
|
//#endregion
|
|
4381
|
-
//#region src/components/Tabs/TabsContext.tsx
|
|
4954
|
+
//#region src/components/Tabs/internal/TabsContext.tsx
|
|
4382
4955
|
const TabsContext = createContext(null);
|
|
4383
4956
|
const TabsProvider = TabsContext.Provider;
|
|
4384
4957
|
const useTabs = () => {
|
|
@@ -4441,8 +5014,8 @@ const COLLAPSED_SIZE = 8;
|
|
|
4441
5014
|
const LINE_ANIMATION_DURATION = 360;
|
|
4442
5015
|
const SURFACE_ANIMATION_DURATION = 220;
|
|
4443
5016
|
const easing = Easing?.bezier?.(.22, 1, .36, 1) ?? ((value) => value);
|
|
4444
|
-
const nativePointerEventsNone$
|
|
4445
|
-
const webPointerEventsNone$
|
|
5017
|
+
const nativePointerEventsNone$1 = Platform.OS === "web" ? void 0 : { pointerEvents: "none" };
|
|
5018
|
+
const webPointerEventsNone$1 = Platform.OS === "web" ? { pointerEvents: "none" } : void 0;
|
|
4446
5019
|
const animateValue = (value, toValue, duration) => Animated.timing(value, {
|
|
4447
5020
|
toValue,
|
|
4448
5021
|
duration,
|
|
@@ -4645,8 +5218,8 @@ const TabsIndicator = ({ children, style }) => {
|
|
|
4645
5218
|
return /* @__PURE__ */ jsx(Animated.View, {
|
|
4646
5219
|
accessibilityElementsHidden: true,
|
|
4647
5220
|
importantForAccessibility: "no-hide-descendants",
|
|
4648
|
-
...nativePointerEventsNone$
|
|
4649
|
-
style: [indicatorStyle, webPointerEventsNone$
|
|
5221
|
+
...nativePointerEventsNone$1,
|
|
5222
|
+
style: [indicatorStyle, webPointerEventsNone$1],
|
|
4650
5223
|
children
|
|
4651
5224
|
});
|
|
4652
5225
|
};
|
|
@@ -5148,13 +5721,45 @@ const useTooltipContext = () => {
|
|
|
5148
5721
|
};
|
|
5149
5722
|
TooltipContext.displayName = "TooltipContext";
|
|
5150
5723
|
//#endregion
|
|
5724
|
+
//#region src/components/Tooltip/Arrow/TooltipArrow.tsx
|
|
5725
|
+
function TooltipArrow() {
|
|
5726
|
+
const { theme } = useTheme();
|
|
5727
|
+
const tooltip = useTooltipContext();
|
|
5728
|
+
const size = theme.components.tooltip.arrow.size;
|
|
5729
|
+
const side = tooltip.placement.split("-")[0];
|
|
5730
|
+
const staticSide = {
|
|
5731
|
+
top: "bottom",
|
|
5732
|
+
right: "left",
|
|
5733
|
+
bottom: "top",
|
|
5734
|
+
left: "right"
|
|
5735
|
+
}[side];
|
|
5736
|
+
const crossAxisStyle = side === "left" || side === "right" ? {
|
|
5737
|
+
top: tooltip.arrowPosition.top ?? 0,
|
|
5738
|
+
marginTop: -size / 2
|
|
5739
|
+
} : {
|
|
5740
|
+
left: tooltip.arrowPosition.left ?? 0,
|
|
5741
|
+
marginLeft: -size / 2
|
|
5742
|
+
};
|
|
5743
|
+
return /* @__PURE__ */ jsx(View, {
|
|
5744
|
+
pointerEvents: "none",
|
|
5745
|
+
style: {
|
|
5746
|
+
position: "absolute",
|
|
5747
|
+
width: size,
|
|
5748
|
+
height: size,
|
|
5749
|
+
backgroundColor: theme.components.tooltip.arrow.bg,
|
|
5750
|
+
transform: [{ rotate: "45deg" }],
|
|
5751
|
+
[staticSide]: -size / 2,
|
|
5752
|
+
...crossAxisStyle
|
|
5753
|
+
}
|
|
5754
|
+
});
|
|
5755
|
+
}
|
|
5756
|
+
//#endregion
|
|
5151
5757
|
//#region src/components/Tooltip/Tooltip.styles.ts
|
|
5152
5758
|
const createStyles$3 = (theme) => StyleSheet.create({
|
|
5153
5759
|
root: { alignSelf: "flex-start" },
|
|
5154
5760
|
overlay: { ...StyleSheet.absoluteFill },
|
|
5155
5761
|
bubble: {
|
|
5156
5762
|
position: "absolute",
|
|
5157
|
-
zIndex: 1e3,
|
|
5158
5763
|
maxWidth: theme.components.tooltip.content.maxWidth,
|
|
5159
5764
|
paddingHorizontal: theme.components.tooltip.content.paddingX,
|
|
5160
5765
|
paddingVertical: theme.components.tooltip.content.paddingY,
|
|
@@ -5187,8 +5792,6 @@ const createStyles$3 = (theme) => StyleSheet.create({
|
|
|
5187
5792
|
});
|
|
5188
5793
|
//#endregion
|
|
5189
5794
|
//#region src/components/Tooltip/Content/TooltipContent.tsx
|
|
5190
|
-
const nativePointerEventsNone$1 = Platform.OS === "web" ? void 0 : { pointerEvents: "none" };
|
|
5191
|
-
const webPointerEventsNone$1 = Platform.OS === "web" ? { pointerEvents: "none" } : void 0;
|
|
5192
5795
|
const TooltipContent = ({ children, forceMount = false, withArrow = false, style, textStyle }) => {
|
|
5193
5796
|
const styles = useThemeStyles(createStyles$3);
|
|
5194
5797
|
const tooltip = useTooltipContext();
|
|
@@ -5196,13 +5799,13 @@ const TooltipContent = ({ children, forceMount = false, withArrow = false, style
|
|
|
5196
5799
|
if (!forceMount && !visible) return null;
|
|
5197
5800
|
const bubble = /* @__PURE__ */ jsxs(View, {
|
|
5198
5801
|
nativeID: tooltip.contentId,
|
|
5199
|
-
|
|
5802
|
+
pointerEvents: "none",
|
|
5200
5803
|
style: [
|
|
5201
5804
|
styles.bubble,
|
|
5202
|
-
webPointerEventsNone$1,
|
|
5203
5805
|
{
|
|
5204
5806
|
top: tooltip.position.top,
|
|
5205
|
-
left: tooltip.position.left
|
|
5807
|
+
left: tooltip.position.left,
|
|
5808
|
+
zIndex: tooltip.zIndex
|
|
5206
5809
|
},
|
|
5207
5810
|
!visible && { display: "none" },
|
|
5208
5811
|
style
|
|
@@ -5211,7 +5814,7 @@ const TooltipContent = ({ children, forceMount = false, withArrow = false, style
|
|
|
5211
5814
|
children: [Children.map(children, (child) => typeof child === "string" || typeof child === "number" ? /* @__PURE__ */ jsx(Text, {
|
|
5212
5815
|
style: [styles.text, textStyle],
|
|
5213
5816
|
children: child
|
|
5214
|
-
}) : child), withArrow && /* @__PURE__ */ jsx(
|
|
5817
|
+
}) : child), withArrow && /* @__PURE__ */ jsx(TooltipArrow, {})]
|
|
5215
5818
|
});
|
|
5216
5819
|
if (!visible) return bubble;
|
|
5217
5820
|
return /* @__PURE__ */ jsx(Modal$1, {
|
|
@@ -5220,46 +5823,15 @@ const TooltipContent = ({ children, forceMount = false, withArrow = false, style
|
|
|
5220
5823
|
animationType: "fade",
|
|
5221
5824
|
onRequestClose: tooltip.requestClose,
|
|
5222
5825
|
children: /* @__PURE__ */ jsx(Pressable, {
|
|
5826
|
+
...tooltip.getOutsidePressProps({ accessibilityLabel: "Close tooltip" }),
|
|
5223
5827
|
style: styles.overlay,
|
|
5224
|
-
onPress: tooltip.requestOutsideClose,
|
|
5225
5828
|
children: bubble
|
|
5226
5829
|
})
|
|
5227
5830
|
});
|
|
5228
5831
|
};
|
|
5229
5832
|
TooltipContent.displayName = "Tooltip.Content";
|
|
5230
|
-
function InternalArrow() {
|
|
5231
|
-
const { theme } = useTheme();
|
|
5232
|
-
const tooltip = useTooltipContext();
|
|
5233
|
-
const size = theme.components.tooltip.arrow.size;
|
|
5234
|
-
const side = tooltip.placement.split("-")[0];
|
|
5235
|
-
const staticSide = {
|
|
5236
|
-
top: "bottom",
|
|
5237
|
-
right: "left",
|
|
5238
|
-
bottom: "top",
|
|
5239
|
-
left: "right"
|
|
5240
|
-
}[side];
|
|
5241
|
-
const crossAxisStyle = side === "left" || side === "right" ? {
|
|
5242
|
-
top: tooltip.arrowPosition.top ?? 0,
|
|
5243
|
-
marginTop: -size / 2
|
|
5244
|
-
} : {
|
|
5245
|
-
left: tooltip.arrowPosition.left ?? 0,
|
|
5246
|
-
marginLeft: -size / 2
|
|
5247
|
-
};
|
|
5248
|
-
return /* @__PURE__ */ jsx(View, {
|
|
5249
|
-
...nativePointerEventsNone$1,
|
|
5250
|
-
style: [{
|
|
5251
|
-
position: "absolute",
|
|
5252
|
-
width: size,
|
|
5253
|
-
height: size,
|
|
5254
|
-
backgroundColor: theme.components.tooltip.arrow.bg,
|
|
5255
|
-
transform: [{ rotate: "45deg" }],
|
|
5256
|
-
[staticSide]: -size / 2,
|
|
5257
|
-
...crossAxisStyle
|
|
5258
|
-
}, webPointerEventsNone$1]
|
|
5259
|
-
});
|
|
5260
|
-
}
|
|
5261
5833
|
//#endregion
|
|
5262
|
-
//#region src/components/Tooltip/internal/
|
|
5834
|
+
//#region src/components/Tooltip/internal/resolveTooltipDelay.ts
|
|
5263
5835
|
const resolveTooltipDelay = (delay) => {
|
|
5264
5836
|
if (typeof delay === "number") return {
|
|
5265
5837
|
open: delay,
|
|
@@ -5348,15 +5920,17 @@ const TooltipRoot = ({ children, open: openProp, defaultOpen = false, onOpenChan
|
|
|
5348
5920
|
setOpen,
|
|
5349
5921
|
show,
|
|
5350
5922
|
hide,
|
|
5923
|
+
zIndex: dismiss.zIndex,
|
|
5351
5924
|
requestClose: dismiss.requestClose,
|
|
5352
|
-
|
|
5925
|
+
getOutsidePressProps: dismiss.getOutsidePressProps,
|
|
5353
5926
|
onFloatingLayout
|
|
5354
5927
|
}), [
|
|
5355
5928
|
arrowPosition,
|
|
5356
5929
|
contentId,
|
|
5357
5930
|
disabled,
|
|
5931
|
+
dismiss.zIndex,
|
|
5932
|
+
dismiss.getOutsidePressProps,
|
|
5358
5933
|
dismiss.requestClose,
|
|
5359
|
-
dismiss.requestOutsideClose,
|
|
5360
5934
|
hide,
|
|
5361
5935
|
open,
|
|
5362
5936
|
resolvedPlacement,
|
|
@@ -5403,11 +5977,6 @@ const Tooltip = Object.assign(TooltipRoot, {
|
|
|
5403
5977
|
});
|
|
5404
5978
|
Tooltip.displayName = "Tooltip";
|
|
5405
5979
|
//#endregion
|
|
5406
|
-
//#region src/utils/devWarning.ts
|
|
5407
|
-
const devWarning = (condition, message) => {
|
|
5408
|
-
if ((typeof __DEV__ === "undefined" || __DEV__) && !condition) console.warn(message);
|
|
5409
|
-
};
|
|
5410
|
-
//#endregion
|
|
5411
5980
|
//#region src/primitives/Button/Button.styles.ts
|
|
5412
5981
|
const fontWeight = (value) => value;
|
|
5413
5982
|
const createStyles$2 = (theme) => StyleSheet.create({
|
|
@@ -5426,9 +5995,14 @@ const createStyles$2 = (theme) => StyleSheet.create({
|
|
|
5426
5995
|
fontFamily: theme.tokens.typography.family.regular,
|
|
5427
5996
|
fontWeight: fontWeight(theme.tokens.typography.weight.regular),
|
|
5428
5997
|
lineHeight: theme.tokens.typography.lineHeight.md,
|
|
5998
|
+
textAlign: "center",
|
|
5429
5999
|
color: theme.components.button.primary.solid.default.fg
|
|
5430
6000
|
},
|
|
5431
|
-
labelSlot: {
|
|
6001
|
+
labelSlot: {
|
|
6002
|
+
position: "relative",
|
|
6003
|
+
alignItems: "center",
|
|
6004
|
+
justifyContent: "center"
|
|
6005
|
+
},
|
|
5432
6006
|
labelMeasure: {
|
|
5433
6007
|
position: "absolute",
|
|
5434
6008
|
opacity: 0
|
|
@@ -5475,22 +6049,22 @@ const createStyles$2 = (theme) => StyleSheet.create({
|
|
|
5475
6049
|
//#region src/primitives/Button/Button.tsx
|
|
5476
6050
|
const sizeMap = {
|
|
5477
6051
|
sm: {
|
|
5478
|
-
px:
|
|
5479
|
-
py:
|
|
6052
|
+
px: 16,
|
|
6053
|
+
py: 6,
|
|
5480
6054
|
height: 36,
|
|
5481
6055
|
fontSize: 12,
|
|
5482
6056
|
iconSize: 16
|
|
5483
6057
|
},
|
|
5484
6058
|
md: {
|
|
5485
|
-
px:
|
|
5486
|
-
py:
|
|
6059
|
+
px: 24,
|
|
6060
|
+
py: 8,
|
|
5487
6061
|
height: 44,
|
|
5488
6062
|
fontSize: 14,
|
|
5489
6063
|
iconSize: 20
|
|
5490
6064
|
},
|
|
5491
6065
|
lg: {
|
|
5492
|
-
px:
|
|
5493
|
-
py:
|
|
6066
|
+
px: 32,
|
|
6067
|
+
py: 10,
|
|
5494
6068
|
height: 52,
|
|
5495
6069
|
fontSize: 16,
|
|
5496
6070
|
iconSize: 24
|
|
@@ -5580,12 +6154,11 @@ function Button({ children, color = "primary", appearance = "solid", shape = "pi
|
|
|
5580
6154
|
}),
|
|
5581
6155
|
!loading && iconStart && renderIcon(iconStart, contentColor),
|
|
5582
6156
|
content && !iconOnly && /* @__PURE__ */ jsxs(View, {
|
|
5583
|
-
style: styles.labelSlot,
|
|
6157
|
+
style: [styles.labelSlot, labelWidth > 0 && { minWidth: labelWidth }],
|
|
5584
6158
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
5585
6159
|
onLayout: handleLabelLayout,
|
|
5586
6160
|
style: [
|
|
5587
6161
|
styles.text,
|
|
5588
|
-
labelWidth > 0 && { minWidth: labelWidth },
|
|
5589
6162
|
{
|
|
5590
6163
|
fontSize: config.fontSize,
|
|
5591
6164
|
color: contentColor
|