@vellira-ui/react-native 2.51.0 → 2.53.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.js +184 -57
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,75 +3,185 @@ import { Check, ChevronDown, Close, Search } from "@vellira-ui/icons";
|
|
|
3
3
|
import { AccessibilityInfo, ActivityIndicator, Animated, Dimensions, Easing, FlatList, Modal as Modal$1, Platform, Pressable, ScrollView, StyleSheet, Text, TextInput, View, findNodeHandle, useWindowDimensions } from "react-native";
|
|
4
4
|
import { darkTheme, highContrastTheme, lightTheme } from "@vellira-ui/tokens";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/managers/FloatingManager/computeFloatingPosition.ts
|
|
7
|
+
function clamp(value, min, max) {
|
|
8
|
+
return Math.min(Math.max(value, min), Math.max(min, max));
|
|
9
|
+
}
|
|
10
|
+
function parsePlacement(placement) {
|
|
11
|
+
const [side, align = "center"] = placement.split("-");
|
|
12
|
+
return {
|
|
13
|
+
side,
|
|
14
|
+
align
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function createPlacement(side, align) {
|
|
18
|
+
return align === "center" ? side : `${side}-${align}`;
|
|
19
|
+
}
|
|
20
|
+
function getOppositeSide(side) {
|
|
21
|
+
switch (side) {
|
|
22
|
+
case "top": return "bottom";
|
|
23
|
+
case "right": return "left";
|
|
24
|
+
case "bottom": return "top";
|
|
25
|
+
case "left": return "right";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function computeBasePosition({ reference, floating, side, align, offset }) {
|
|
29
|
+
const referenceCenterX = reference.x + reference.width / 2;
|
|
30
|
+
const referenceCenterY = reference.y + reference.height / 2;
|
|
31
|
+
const alignedLeft = align === "start" ? reference.x : align === "end" ? reference.x + reference.width - floating.width : referenceCenterX - floating.width / 2;
|
|
32
|
+
const alignedTop = align === "start" ? reference.y : align === "end" ? reference.y + reference.height - floating.height : referenceCenterY - floating.height / 2;
|
|
33
|
+
switch (side) {
|
|
34
|
+
case "top": return {
|
|
35
|
+
top: reference.y - floating.height - offset,
|
|
36
|
+
left: alignedLeft
|
|
37
|
+
};
|
|
38
|
+
case "right": return {
|
|
39
|
+
top: alignedTop,
|
|
40
|
+
left: reference.x + reference.width + offset
|
|
41
|
+
};
|
|
42
|
+
case "bottom": return {
|
|
43
|
+
top: reference.y + reference.height + offset,
|
|
44
|
+
left: alignedLeft
|
|
45
|
+
};
|
|
46
|
+
case "left": return {
|
|
47
|
+
top: alignedTop,
|
|
48
|
+
left: reference.x - floating.width - offset
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function getMainAxisOverflow({ side, position, floating, boundary, padding }) {
|
|
53
|
+
switch (side) {
|
|
54
|
+
case "top": return padding - position.top;
|
|
55
|
+
case "right": return position.left + floating.width + padding - boundary.width;
|
|
56
|
+
case "bottom": return position.top + floating.height + padding - boundary.height;
|
|
57
|
+
case "left": return padding - position.left;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function computeFloatingPosition({ reference, floating, boundary, placement, offset = 8, padding = 12, arrowPadding = 16, flip = true, shift = true }) {
|
|
61
|
+
const parsed = parsePlacement(placement);
|
|
62
|
+
let resolvedSide = parsed.side;
|
|
63
|
+
let position = computeBasePosition({
|
|
64
|
+
reference,
|
|
65
|
+
floating,
|
|
66
|
+
side: resolvedSide,
|
|
67
|
+
align: parsed.align,
|
|
68
|
+
offset
|
|
69
|
+
});
|
|
70
|
+
if (flip && getMainAxisOverflow({
|
|
71
|
+
side: resolvedSide,
|
|
72
|
+
position,
|
|
73
|
+
floating,
|
|
74
|
+
boundary,
|
|
75
|
+
padding
|
|
76
|
+
}) > 0) {
|
|
77
|
+
const oppositeSide = getOppositeSide(resolvedSide);
|
|
78
|
+
const oppositePosition = computeBasePosition({
|
|
79
|
+
reference,
|
|
80
|
+
floating,
|
|
81
|
+
side: oppositeSide,
|
|
82
|
+
align: parsed.align,
|
|
83
|
+
offset
|
|
84
|
+
});
|
|
85
|
+
if (getMainAxisOverflow({
|
|
86
|
+
side: oppositeSide,
|
|
87
|
+
position: oppositePosition,
|
|
88
|
+
floating,
|
|
89
|
+
boundary,
|
|
90
|
+
padding
|
|
91
|
+
}) <= 0) {
|
|
92
|
+
resolvedSide = oppositeSide;
|
|
93
|
+
position = oppositePosition;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (shift) position = {
|
|
97
|
+
top: clamp(position.top, padding, boundary.height - floating.height - padding),
|
|
98
|
+
left: clamp(position.left, padding, boundary.width - floating.width - padding)
|
|
99
|
+
};
|
|
100
|
+
const referenceCenterX = reference.x + reference.width / 2;
|
|
101
|
+
const referenceCenterY = reference.y + reference.height / 2;
|
|
102
|
+
const arrowPosition = resolvedSide === "top" || resolvedSide === "bottom" ? { left: clamp(referenceCenterX - position.left, arrowPadding, floating.width - arrowPadding) } : { top: clamp(referenceCenterY - position.top, arrowPadding, floating.height - arrowPadding) };
|
|
103
|
+
return {
|
|
104
|
+
position,
|
|
105
|
+
arrowPosition,
|
|
106
|
+
placement: createPlacement(resolvedSide, parsed.align)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
6
110
|
//#region src/managers/FloatingManager/useNativeFloatingPosition.ts
|
|
7
|
-
const safePadding = 12;
|
|
8
111
|
function useNativeFloatingPosition(placement = "top", offset = 8) {
|
|
9
|
-
const [
|
|
10
|
-
|
|
11
|
-
|
|
112
|
+
const [result, setResult] = useState({
|
|
113
|
+
position: {
|
|
114
|
+
top: 0,
|
|
115
|
+
left: 0
|
|
116
|
+
},
|
|
117
|
+
arrowPosition: {},
|
|
118
|
+
placement
|
|
12
119
|
});
|
|
13
120
|
const floatingSizeRef = useRef({
|
|
14
121
|
width: 0,
|
|
15
122
|
height: 0
|
|
16
123
|
});
|
|
17
124
|
const lastTriggerRef = useRef(null);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
}, []);
|
|
21
|
-
const calculatePosition = useCallback((triggerRect, size) => {
|
|
22
|
-
const { width: screenWidth, height: screenHeight } = Dimensions.get("window");
|
|
23
|
-
const [side, align = "center"] = placement.split("-");
|
|
24
|
-
const horizontalTop = side === "bottom" ? triggerRect.y + triggerRect.height + offset : triggerRect.y - size.height - offset;
|
|
25
|
-
const verticalTop = align === "start" ? triggerRect.y : align === "end" ? triggerRect.y + triggerRect.height - size.height : triggerRect.y + triggerRect.height / 2 - size.height / 2;
|
|
26
|
-
const horizontalLeft = align === "start" ? triggerRect.x : align === "end" ? triggerRect.x + triggerRect.width - size.width : triggerRect.x + triggerRect.width / 2 - size.width / 2;
|
|
27
|
-
const verticalLeft = side === "right" ? triggerRect.x + triggerRect.width + offset : triggerRect.x - size.width - offset;
|
|
28
|
-
const rawPosition = side === "left" || side === "right" ? {
|
|
29
|
-
top: verticalTop,
|
|
30
|
-
left: verticalLeft
|
|
31
|
-
} : {
|
|
32
|
-
top: horizontalTop,
|
|
33
|
-
left: horizontalLeft
|
|
34
|
-
};
|
|
35
|
-
return {
|
|
36
|
-
top: clamp(rawPosition.top, safePadding, screenHeight - size.height - safePadding),
|
|
37
|
-
left: clamp(rawPosition.left, safePadding, screenWidth - size.width - safePadding)
|
|
38
|
-
};
|
|
39
|
-
}, [
|
|
40
|
-
placement,
|
|
41
|
-
offset,
|
|
42
|
-
clamp
|
|
43
|
-
]);
|
|
44
|
-
const updatePosition = useCallback((triggerRef, measuredSize = floatingSizeRef.current) => {
|
|
125
|
+
const lastContainerRef = useRef(null);
|
|
126
|
+
const updatePosition = useCallback((triggerRef, containerRef, measuredSize = floatingSizeRef.current) => {
|
|
45
127
|
lastTriggerRef.current = triggerRef;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
128
|
+
lastContainerRef.current = containerRef ?? null;
|
|
129
|
+
const triggerNode = triggerRef.current;
|
|
130
|
+
const containerNode = containerRef?.current;
|
|
131
|
+
if (!triggerNode || typeof triggerNode.measureInWindow !== "function") {
|
|
132
|
+
setResult((current) => ({
|
|
133
|
+
...current,
|
|
134
|
+
position: {
|
|
135
|
+
top: 0,
|
|
136
|
+
left: 0
|
|
137
|
+
}
|
|
138
|
+
}));
|
|
52
139
|
return;
|
|
53
140
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
141
|
+
triggerNode.measureInWindow((x, y, width, height) => {
|
|
142
|
+
const commitPosition = (containerX, containerY, containerWidth, containerHeight) => {
|
|
143
|
+
const nextResult = computeFloatingPosition({
|
|
144
|
+
reference: {
|
|
145
|
+
x: x - containerX,
|
|
146
|
+
y: y - containerY,
|
|
147
|
+
width,
|
|
148
|
+
height
|
|
149
|
+
},
|
|
150
|
+
floating: measuredSize,
|
|
151
|
+
boundary: {
|
|
152
|
+
width: containerWidth,
|
|
153
|
+
height: containerHeight
|
|
154
|
+
},
|
|
155
|
+
placement,
|
|
156
|
+
offset
|
|
157
|
+
});
|
|
158
|
+
setResult(nextResult);
|
|
159
|
+
};
|
|
160
|
+
if (!containerNode || typeof containerNode.measureInWindow !== "function") {
|
|
161
|
+
const window = Dimensions.get("window");
|
|
162
|
+
commitPosition(0, 0, window.width, window.height);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
containerNode.measureInWindow((containerX, containerY, containerWidth, containerHeight) => {
|
|
166
|
+
commitPosition(containerX, containerY, containerWidth, containerHeight);
|
|
167
|
+
});
|
|
61
168
|
});
|
|
62
|
-
}, [
|
|
169
|
+
}, [placement, offset]);
|
|
170
|
+
const onFloatingLayout = useCallback((event) => {
|
|
171
|
+
const { width, height } = event.nativeEvent.layout;
|
|
172
|
+
const nextSize = {
|
|
173
|
+
width,
|
|
174
|
+
height
|
|
175
|
+
};
|
|
176
|
+
floatingSizeRef.current = nextSize;
|
|
177
|
+
if (lastTriggerRef.current) updatePosition(lastTriggerRef.current, lastContainerRef.current ?? void 0, nextSize);
|
|
178
|
+
}, [updatePosition]);
|
|
63
179
|
return {
|
|
64
|
-
position,
|
|
180
|
+
position: result.position,
|
|
181
|
+
arrowPosition: result.arrowPosition,
|
|
182
|
+
placement: result.placement,
|
|
65
183
|
updatePosition,
|
|
66
|
-
onFloatingLayout
|
|
67
|
-
const { width, height } = event.nativeEvent.layout;
|
|
68
|
-
const nextSize = {
|
|
69
|
-
width,
|
|
70
|
-
height
|
|
71
|
-
};
|
|
72
|
-
floatingSizeRef.current = nextSize;
|
|
73
|
-
if (lastTriggerRef.current) updatePosition(lastTriggerRef.current, nextSize);
|
|
74
|
-
}, [updatePosition])
|
|
184
|
+
onFloatingLayout
|
|
75
185
|
};
|
|
76
186
|
}
|
|
77
187
|
//#endregion
|
|
@@ -5675,13 +5785,30 @@ Input.displayName = "Input";
|
|
|
5675
5785
|
//#endregion
|
|
5676
5786
|
//#region src/primitives/Portal/Portal.tsx
|
|
5677
5787
|
const PortalContext = createContext(null);
|
|
5788
|
+
const styles = StyleSheet.create({ host: { flex: 1 } });
|
|
5678
5789
|
const PortalProvider = ({ children, container = null }) => /* @__PURE__ */ jsx(PortalContext.Provider, {
|
|
5679
5790
|
value: container,
|
|
5680
5791
|
children
|
|
5681
5792
|
});
|
|
5682
|
-
const Portal = ({ children }) => {
|
|
5793
|
+
const Portal = ({ children, visible = true, animationType = "none", hardwareAccelerated = true, navigationBarTranslucent = true, statusBarTranslucent = true, onDismiss, onRequestClose }) => {
|
|
5683
5794
|
useContext(PortalContext);
|
|
5684
|
-
|
|
5795
|
+
if (!visible) return null;
|
|
5796
|
+
return /* @__PURE__ */ jsx(Modal$1, {
|
|
5797
|
+
animationType,
|
|
5798
|
+
hardwareAccelerated,
|
|
5799
|
+
navigationBarTranslucent,
|
|
5800
|
+
onDismiss,
|
|
5801
|
+
onRequestClose,
|
|
5802
|
+
presentationStyle: "overFullScreen",
|
|
5803
|
+
statusBarTranslucent,
|
|
5804
|
+
transparent: true,
|
|
5805
|
+
visible: true,
|
|
5806
|
+
children: /* @__PURE__ */ jsx(View, {
|
|
5807
|
+
pointerEvents: "box-none",
|
|
5808
|
+
style: styles.host,
|
|
5809
|
+
children
|
|
5810
|
+
})
|
|
5811
|
+
});
|
|
5685
5812
|
};
|
|
5686
5813
|
Portal.__velliraPortal = true;
|
|
5687
5814
|
Portal.displayName = "Portal";
|