@vellira-ui/react-native 2.53.0 → 2.54.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/README.md +49 -110
- package/dist/index.d.ts +2 -0
- package/dist/index.js +353 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,41 +1,24 @@
|
|
|
1
1
|
# @vellira-ui/react-native
|
|
2
2
|
|
|
3
|
-
React Native
|
|
3
|
+
React Native implementation of the Vellira design system.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- Button
|
|
10
|
-
- Checkbox
|
|
11
|
-
- Input
|
|
12
|
-
- FormField
|
|
13
|
-
- Radio
|
|
14
|
-
- RadioGroup
|
|
15
|
-
- Select
|
|
16
|
-
- Dropdown
|
|
17
|
-
- Tabs
|
|
18
|
-
- Tooltip
|
|
19
|
-
- Modal
|
|
20
|
-
|
|
21
|
-
Each public native component has React Native Storybook coverage and Vitest unit coverage.
|
|
22
|
-
|
|
23
|
-
For detailed props, shared types, examples, and compound component APIs, see
|
|
24
|
-
[Native Component API](./API.md).
|
|
5
|
+
It extends shared contracts from `@vellira-ui/types`, uses shared tokens from
|
|
6
|
+
`@vellira-ui/tokens`, shares renderer-neutral behavior through
|
|
7
|
+
`@vellira-ui/core`, and keeps native rendering, accessibility, layout, and
|
|
8
|
+
interaction behavior inside the React Native layer.
|
|
25
9
|
|
|
26
10
|
## Installation
|
|
27
11
|
|
|
12
|
+
Requires React and React Native.
|
|
13
|
+
|
|
28
14
|
```bash
|
|
29
15
|
pnpm add @vellira-ui/react-native
|
|
30
16
|
```
|
|
31
17
|
|
|
32
|
-
Peer dependencies:
|
|
33
|
-
|
|
34
|
-
- `react`
|
|
35
|
-
- `react-native`
|
|
36
|
-
|
|
37
18
|
## Usage
|
|
38
19
|
|
|
20
|
+
Use the components directly in your React Native application:
|
|
21
|
+
|
|
39
22
|
```tsx
|
|
40
23
|
import { Button, Checkbox, Input } from '@vellira-ui/react-native';
|
|
41
24
|
import { useState } from 'react';
|
|
@@ -47,7 +30,12 @@ export function Example() {
|
|
|
47
30
|
|
|
48
31
|
return (
|
|
49
32
|
<View style={{ gap: 16 }}>
|
|
50
|
-
<Input
|
|
33
|
+
<Input
|
|
34
|
+
label='Email'
|
|
35
|
+
value={email}
|
|
36
|
+
onValueChange={setEmail}
|
|
37
|
+
placeholder='name@example.com'
|
|
38
|
+
/>
|
|
51
39
|
<Checkbox
|
|
52
40
|
label='Accept terms'
|
|
53
41
|
description='Required to create an account.'
|
|
@@ -62,105 +50,56 @@ export function Example() {
|
|
|
62
50
|
}
|
|
63
51
|
```
|
|
64
52
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Use `accessibilityLabel` for icon-only native buttons:
|
|
68
|
-
|
|
69
|
-
```tsx
|
|
70
|
-
import { Search } from '@vellira-ui/icons';
|
|
71
|
-
|
|
72
|
-
<Button accessibilityLabel='Search' iconOnly iconStart={<Search />} />;
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Button icons are React elements from `@vellira-ui/icons`; the component injects
|
|
76
|
-
the current icon color and size. `loading` disables interaction and can replace
|
|
77
|
-
the visible label with `loadingText`.
|
|
78
|
-
|
|
79
|
-
### Checkbox Notes
|
|
80
|
-
|
|
81
|
-
Use `description` for settings-style helper text when the checkbox is not
|
|
82
|
-
wrapped in `FormField`. For checkbox rows without a visible label, provide
|
|
83
|
-
`accessibilityLabel`.
|
|
84
|
-
|
|
85
|
-
### Select Notes
|
|
53
|
+
## Components
|
|
86
54
|
|
|
87
|
-
|
|
88
|
-
visible choices, and `Dropdown` for action menus. Native `Select` opens a
|
|
89
|
-
sheet, modal, or popover and renders options with a FlatList-backed native
|
|
90
|
-
content surface.
|
|
55
|
+
### Inputs
|
|
91
56
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
57
|
+
- Button
|
|
58
|
+
- Checkbox
|
|
59
|
+
- Input
|
|
60
|
+
- Radio
|
|
61
|
+
- RadioGroup
|
|
62
|
+
- Select
|
|
95
63
|
|
|
96
|
-
|
|
97
|
-
const [role, setRole] = useState('editor');
|
|
64
|
+
### Overlays
|
|
98
65
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
onValueChange={(nextRole) => setRole(nextRole ?? '')}
|
|
104
|
-
searchable
|
|
105
|
-
clearable
|
|
106
|
-
>
|
|
107
|
-
<Select.Item value='admin' label='Admin' />
|
|
108
|
-
<Select.Item value='editor' label='Editor' />
|
|
109
|
-
<Select.Item value='viewer' label='Viewer' />
|
|
110
|
-
</Select>
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### Dropdown Notes
|
|
66
|
+
- Dropdown
|
|
67
|
+
- Tooltip
|
|
68
|
+
- Popover
|
|
69
|
+
- Modal
|
|
116
70
|
|
|
117
|
-
|
|
118
|
-
menus with `Dropdown.Trigger`, `Dropdown.Content`, `Dropdown.Item`, groups,
|
|
119
|
-
labels, and separators. Use `open`, `defaultOpen`, and `onOpenChange` for menu
|
|
120
|
-
state. Use root `color` for the semantic trigger and menu palette, and
|
|
121
|
-
`Dropdown.Item danger` for destructive commands.
|
|
71
|
+
### Forms
|
|
122
72
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
<Dropdown color='primary' label='Actions'>
|
|
127
|
-
<Dropdown.Content>
|
|
128
|
-
<Dropdown.Label>File</Dropdown.Label>
|
|
129
|
-
<Dropdown.Item value='duplicate' onSelect={duplicate}>
|
|
130
|
-
Duplicate
|
|
131
|
-
</Dropdown.Item>
|
|
132
|
-
<Dropdown.Separator />
|
|
133
|
-
<Dropdown.Item value='delete' danger onSelect={deleteFile}>
|
|
134
|
-
Delete
|
|
135
|
-
</Dropdown.Item>
|
|
136
|
-
</Dropdown.Content>
|
|
137
|
-
</Dropdown>;
|
|
138
|
-
```
|
|
73
|
+
- FormField
|
|
74
|
+
- Tabs
|
|
139
75
|
|
|
140
|
-
|
|
76
|
+
Every public component includes React Native Storybook stories and Vitest unit
|
|
77
|
+
tests.
|
|
141
78
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
or `RadioGroup`. The wrapped control should provide its own
|
|
145
|
-
`accessibilityLabel`, role, disabled/editable state and interaction behavior.
|
|
146
|
-
`FormField` only provides layout, text styling, required mark, disabled root
|
|
147
|
-
state and polite error announcement.
|
|
79
|
+
For detailed props, shared types, examples, and compound component APIs, see
|
|
80
|
+
[Native Component API](./API.md).
|
|
148
81
|
|
|
149
|
-
##
|
|
82
|
+
## Infrastructure
|
|
150
83
|
|
|
151
|
-
|
|
84
|
+
The package also exports native infrastructure used by components and
|
|
85
|
+
applications:
|
|
152
86
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
87
|
+
- `Portal`
|
|
88
|
+
- `PortalProvider`
|
|
89
|
+
- `ThemeProvider`
|
|
90
|
+
- `useTheme`
|
|
91
|
+
- `nativeThemes`
|
|
156
92
|
|
|
157
|
-
|
|
93
|
+
## Documentation
|
|
158
94
|
|
|
159
|
-
|
|
95
|
+
- [Getting Started](https://docs.vellira.dev/start/getting-started)
|
|
96
|
+
- [React Native](https://docs.vellira.dev/react-native/)
|
|
97
|
+
- [Native Component API](./API.md)
|
|
160
98
|
|
|
161
99
|
## Storybook
|
|
162
100
|
|
|
163
|
-
Native stories live next to components as `*.stories.tsx` and are consumed by
|
|
101
|
+
Native stories live next to components as `*.stories.tsx` and are consumed by
|
|
102
|
+
`apps/native-storybook`.
|
|
164
103
|
|
|
165
104
|
Run on-device Storybook from the workspace root:
|
|
166
105
|
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export { Dropdown } from './components/Dropdown';
|
|
|
2
2
|
export type { DropdownContentProps, DropdownEmptyProps, DropdownGroupProps, DropdownItemProps, DropdownLabelProps, DropdownPresentation, DropdownProps, DropdownSelectEvent, DropdownSeparatorProps, DropdownTriggerProps, } from './components/Dropdown/types';
|
|
3
3
|
export type { ModalProps } from './components/Modal';
|
|
4
4
|
export { Modal } from './components/Modal';
|
|
5
|
+
export type { PopoverAnchorProps, PopoverArrowProps, PopoverCloseProps, PopoverContentProps, PopoverDescriptionProps, PopoverProps, PopoverTitleProps, PopoverTriggerProps, } from './components/Popover';
|
|
6
|
+
export { Popover } from './components/Popover';
|
|
5
7
|
export type { RadioGroupProps } from './components/RadioGroup';
|
|
6
8
|
export { RadioGroup } from './components/RadioGroup';
|
|
7
9
|
export type { SelectOption, SelectProps } from './components/Select';
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,26 @@ 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/theme/fontWeight.ts
|
|
7
|
+
const nativeFontWeights = /* @__PURE__ */ new Set([
|
|
8
|
+
"normal",
|
|
9
|
+
"bold",
|
|
10
|
+
"100",
|
|
11
|
+
"200",
|
|
12
|
+
"300",
|
|
13
|
+
"400",
|
|
14
|
+
"500",
|
|
15
|
+
"600",
|
|
16
|
+
"700",
|
|
17
|
+
"800",
|
|
18
|
+
"900"
|
|
19
|
+
]);
|
|
20
|
+
function toNativeFontWeight(weight) {
|
|
21
|
+
const normalizedWeight = String(weight);
|
|
22
|
+
if (!nativeFontWeights.has(normalizedWeight)) return "normal";
|
|
23
|
+
return normalizedWeight;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
6
26
|
//#region src/managers/FloatingManager/computeFloatingPosition.ts
|
|
7
27
|
function clamp(value, min, max) {
|
|
8
28
|
return Math.min(Math.max(value, min), Math.max(min, max));
|
|
@@ -1882,6 +1902,338 @@ const Modal = Object.assign(ModalRoot, {
|
|
|
1882
1902
|
});
|
|
1883
1903
|
Modal.displayName = "Modal";
|
|
1884
1904
|
//#endregion
|
|
1905
|
+
//#region src/components/Popover/internal/PopoverContext.tsx
|
|
1906
|
+
const PopoverContext = createContext(null);
|
|
1907
|
+
function PopoverProvider({ children, value }) {
|
|
1908
|
+
return /* @__PURE__ */ jsx(PopoverContext.Provider, {
|
|
1909
|
+
value,
|
|
1910
|
+
children
|
|
1911
|
+
});
|
|
1912
|
+
}
|
|
1913
|
+
function usePopoverContext(componentName) {
|
|
1914
|
+
const context = useContext(PopoverContext);
|
|
1915
|
+
if (!context) throw new Error(`${componentName} must be used within Popover.`);
|
|
1916
|
+
return context;
|
|
1917
|
+
}
|
|
1918
|
+
//#endregion
|
|
1919
|
+
//#region src/components/Popover/Anchor/PopoverAnchor.tsx
|
|
1920
|
+
function PopoverAnchor({ children, asChild = false, ...anchorProps }) {
|
|
1921
|
+
const { anchorRef } = usePopoverContext("Popover.Anchor");
|
|
1922
|
+
if (asChild) return cloneElement(children, { ref: anchorRef });
|
|
1923
|
+
return /* @__PURE__ */ jsx(View, {
|
|
1924
|
+
...anchorProps,
|
|
1925
|
+
ref: anchorRef,
|
|
1926
|
+
children
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
PopoverAnchor.displayName = "Popover.Anchor";
|
|
1930
|
+
//#endregion
|
|
1931
|
+
//#region src/components/Popover/Arrow/PopoverArrow.styles.ts
|
|
1932
|
+
function createPopoverArrowStyles({ theme, side, arrowPosition }) {
|
|
1933
|
+
const tokens = theme.components.popover.arrow;
|
|
1934
|
+
const halfSize = tokens.size / 2;
|
|
1935
|
+
const position = side === "top" || side === "bottom" ? {
|
|
1936
|
+
left: arrowPosition.left ?? 0,
|
|
1937
|
+
transform: [{ translateX: -halfSize }, { rotate: "45deg" }]
|
|
1938
|
+
} : {
|
|
1939
|
+
top: arrowPosition.top ?? 0,
|
|
1940
|
+
transform: [{ translateY: -halfSize }, { rotate: "45deg" }]
|
|
1941
|
+
};
|
|
1942
|
+
const border = { borderColor: tokens.border };
|
|
1943
|
+
switch (side) {
|
|
1944
|
+
case "top":
|
|
1945
|
+
position.bottom = -halfSize;
|
|
1946
|
+
border.borderRightWidth = 1;
|
|
1947
|
+
border.borderBottomWidth = 1;
|
|
1948
|
+
break;
|
|
1949
|
+
case "bottom":
|
|
1950
|
+
position.top = -halfSize;
|
|
1951
|
+
border.borderLeftWidth = 1;
|
|
1952
|
+
border.borderTopWidth = 1;
|
|
1953
|
+
break;
|
|
1954
|
+
case "left":
|
|
1955
|
+
position.right = -halfSize;
|
|
1956
|
+
border.borderRightWidth = 1;
|
|
1957
|
+
border.borderTopWidth = 1;
|
|
1958
|
+
break;
|
|
1959
|
+
case "right":
|
|
1960
|
+
position.left = -halfSize;
|
|
1961
|
+
border.borderLeftWidth = 1;
|
|
1962
|
+
border.borderBottomWidth = 1;
|
|
1963
|
+
break;
|
|
1964
|
+
}
|
|
1965
|
+
return StyleSheet.create({ arrow: {
|
|
1966
|
+
position: "absolute",
|
|
1967
|
+
width: tokens.size,
|
|
1968
|
+
height: tokens.size,
|
|
1969
|
+
backgroundColor: tokens.bg,
|
|
1970
|
+
...position,
|
|
1971
|
+
...border
|
|
1972
|
+
} });
|
|
1973
|
+
}
|
|
1974
|
+
//#endregion
|
|
1975
|
+
//#region src/components/Popover/Arrow/PopoverArrow.tsx
|
|
1976
|
+
function PopoverArrow({ style }) {
|
|
1977
|
+
const { theme } = useTheme();
|
|
1978
|
+
const { placement, arrowPosition } = usePopoverContext("Popover.Arrow");
|
|
1979
|
+
const side = placement.split("-")[0];
|
|
1980
|
+
return /* @__PURE__ */ jsx(View, {
|
|
1981
|
+
accessible: false,
|
|
1982
|
+
pointerEvents: "none",
|
|
1983
|
+
style: [useMemo(() => createPopoverArrowStyles({
|
|
1984
|
+
theme,
|
|
1985
|
+
side,
|
|
1986
|
+
arrowPosition
|
|
1987
|
+
}), [
|
|
1988
|
+
theme,
|
|
1989
|
+
side,
|
|
1990
|
+
arrowPosition
|
|
1991
|
+
]).arrow, style]
|
|
1992
|
+
});
|
|
1993
|
+
}
|
|
1994
|
+
PopoverArrow.displayName = "Popover.Arrow";
|
|
1995
|
+
//#endregion
|
|
1996
|
+
//#region src/components/Popover/Close/PopoverClose.tsx
|
|
1997
|
+
const PopoverClose = ({ children, asChild = false, onPress, ...closeProps }) => {
|
|
1998
|
+
const { setOpen } = usePopoverContext("Popover.Close");
|
|
1999
|
+
const handlePress = (event) => {
|
|
2000
|
+
children.props.onPress?.(event);
|
|
2001
|
+
onPress?.(event);
|
|
2002
|
+
if (event.defaultPrevented) return;
|
|
2003
|
+
setOpen(false, { reason: "close" });
|
|
2004
|
+
};
|
|
2005
|
+
if (asChild) return cloneElement(children, { onPress: handlePress });
|
|
2006
|
+
return /* @__PURE__ */ jsx(Pressable, {
|
|
2007
|
+
...closeProps,
|
|
2008
|
+
onPress: handlePress,
|
|
2009
|
+
children
|
|
2010
|
+
});
|
|
2011
|
+
};
|
|
2012
|
+
PopoverClose.displayName = "PopoverClose";
|
|
2013
|
+
//#endregion
|
|
2014
|
+
//#region src/primitives/Portal/Portal.tsx
|
|
2015
|
+
const PortalContext = createContext(null);
|
|
2016
|
+
const styles$1 = StyleSheet.create({ host: { flex: 1 } });
|
|
2017
|
+
const PortalProvider = ({ children, container = null }) => /* @__PURE__ */ jsx(PortalContext.Provider, {
|
|
2018
|
+
value: container,
|
|
2019
|
+
children
|
|
2020
|
+
});
|
|
2021
|
+
const Portal = ({ children, visible = true, animationType = "none", hardwareAccelerated = true, navigationBarTranslucent = true, statusBarTranslucent = true, onDismiss, onRequestClose }) => {
|
|
2022
|
+
useContext(PortalContext);
|
|
2023
|
+
if (!visible) return null;
|
|
2024
|
+
return /* @__PURE__ */ jsx(Modal$1, {
|
|
2025
|
+
animationType,
|
|
2026
|
+
hardwareAccelerated,
|
|
2027
|
+
navigationBarTranslucent,
|
|
2028
|
+
onDismiss,
|
|
2029
|
+
onRequestClose,
|
|
2030
|
+
presentationStyle: "overFullScreen",
|
|
2031
|
+
statusBarTranslucent,
|
|
2032
|
+
transparent: true,
|
|
2033
|
+
visible: true,
|
|
2034
|
+
children: /* @__PURE__ */ jsx(View, {
|
|
2035
|
+
pointerEvents: "box-none",
|
|
2036
|
+
style: styles$1.host,
|
|
2037
|
+
children
|
|
2038
|
+
})
|
|
2039
|
+
});
|
|
2040
|
+
};
|
|
2041
|
+
Portal.__velliraPortal = true;
|
|
2042
|
+
Portal.displayName = "Portal";
|
|
2043
|
+
PortalProvider.displayName = "PortalProvider";
|
|
2044
|
+
//#endregion
|
|
2045
|
+
//#region src/components/Popover/Content/PopoverContent.styles.ts
|
|
2046
|
+
const styles = StyleSheet.create({
|
|
2047
|
+
layer: { flex: 1 },
|
|
2048
|
+
backdrop: StyleSheet.absoluteFill,
|
|
2049
|
+
content: { position: "absolute" }
|
|
2050
|
+
});
|
|
2051
|
+
function createPopoverContentStyles(theme) {
|
|
2052
|
+
const tokens = theme.components.popover.content;
|
|
2053
|
+
const shadow = tokens.shadow.native;
|
|
2054
|
+
return StyleSheet.create({ content: {
|
|
2055
|
+
minWidth: tokens.minWidth,
|
|
2056
|
+
maxWidth: tokens.maxWidth,
|
|
2057
|
+
padding: tokens.padding,
|
|
2058
|
+
gap: tokens.gap,
|
|
2059
|
+
backgroundColor: tokens.bg,
|
|
2060
|
+
borderColor: tokens.border,
|
|
2061
|
+
borderWidth: tokens.borderWidth,
|
|
2062
|
+
borderRadius: tokens.radius,
|
|
2063
|
+
shadowColor: shadow.color,
|
|
2064
|
+
shadowOpacity: shadow.opacity,
|
|
2065
|
+
shadowRadius: shadow.blur,
|
|
2066
|
+
shadowOffset: {
|
|
2067
|
+
width: shadow.x,
|
|
2068
|
+
height: shadow.y
|
|
2069
|
+
},
|
|
2070
|
+
elevation: shadow.elevation
|
|
2071
|
+
} });
|
|
2072
|
+
}
|
|
2073
|
+
//#endregion
|
|
2074
|
+
//#region src/components/Popover/Content/PopoverContent.tsx
|
|
2075
|
+
function PopoverContent({ children, style, ...contentProps }) {
|
|
2076
|
+
const { theme } = useTheme();
|
|
2077
|
+
const layerRef = useRef(null);
|
|
2078
|
+
const themedStyles = useMemo(() => createPopoverContentStyles(theme), [theme]);
|
|
2079
|
+
const { open, position, onFloatingLayout, updatePosition, setOpen, closeOnOutsidePress } = usePopoverContext("Popover.Content");
|
|
2080
|
+
useEffect(() => {
|
|
2081
|
+
if (!open) return;
|
|
2082
|
+
requestAnimationFrame(() => {
|
|
2083
|
+
updatePosition(layerRef);
|
|
2084
|
+
});
|
|
2085
|
+
}, [open, updatePosition]);
|
|
2086
|
+
return /* @__PURE__ */ jsx(Portal, {
|
|
2087
|
+
visible: open,
|
|
2088
|
+
onRequestClose: () => {
|
|
2089
|
+
setOpen(false, { reason: "escape-key" });
|
|
2090
|
+
},
|
|
2091
|
+
children: /* @__PURE__ */ jsxs(View, {
|
|
2092
|
+
ref: layerRef,
|
|
2093
|
+
pointerEvents: "box-none",
|
|
2094
|
+
style: styles.layer,
|
|
2095
|
+
children: [/* @__PURE__ */ jsx(Pressable, {
|
|
2096
|
+
testID: "popover-backdrop",
|
|
2097
|
+
accessibilityLabel: closeOnOutsidePress ? "Close popover" : void 0,
|
|
2098
|
+
accessibilityRole: closeOnOutsidePress ? "button" : void 0,
|
|
2099
|
+
onPress: closeOnOutsidePress ? () => {
|
|
2100
|
+
setOpen(false, { reason: "outside-press" });
|
|
2101
|
+
} : void 0,
|
|
2102
|
+
style: styles.backdrop
|
|
2103
|
+
}), /* @__PURE__ */ jsx(View, {
|
|
2104
|
+
...contentProps,
|
|
2105
|
+
onLayout: onFloatingLayout,
|
|
2106
|
+
style: [
|
|
2107
|
+
styles.content,
|
|
2108
|
+
themedStyles.content,
|
|
2109
|
+
position,
|
|
2110
|
+
style
|
|
2111
|
+
],
|
|
2112
|
+
children
|
|
2113
|
+
})]
|
|
2114
|
+
})
|
|
2115
|
+
});
|
|
2116
|
+
}
|
|
2117
|
+
//#endregion
|
|
2118
|
+
//#region src/components/Popover/Description/PopoverDescription.styles.ts
|
|
2119
|
+
function createPopoverDescriptionStyles(theme) {
|
|
2120
|
+
return StyleSheet.create({ description: {
|
|
2121
|
+
color: theme.components.popover.description.fg,
|
|
2122
|
+
fontSize: theme.tokens.typography.size.sm
|
|
2123
|
+
} });
|
|
2124
|
+
}
|
|
2125
|
+
//#endregion
|
|
2126
|
+
//#region src/components/Popover/Description/PopoverDescription.tsx
|
|
2127
|
+
const PopoverDescription = ({ children, style, ...descriptionProps }) => {
|
|
2128
|
+
const { theme } = useTheme();
|
|
2129
|
+
const styles = useMemo(() => createPopoverDescriptionStyles(theme), [theme]);
|
|
2130
|
+
return /* @__PURE__ */ jsx(Text, {
|
|
2131
|
+
...descriptionProps,
|
|
2132
|
+
style: [styles.description, style],
|
|
2133
|
+
children
|
|
2134
|
+
});
|
|
2135
|
+
};
|
|
2136
|
+
PopoverDescription.displayName = "PopoverDescription";
|
|
2137
|
+
//#endregion
|
|
2138
|
+
//#region src/components/Popover/Root/PopoverRoot.tsx
|
|
2139
|
+
function getNativePlacement(side, align) {
|
|
2140
|
+
if (!side) return "bottom";
|
|
2141
|
+
if (!align || align === "center") return side;
|
|
2142
|
+
return `${side}-${align}`;
|
|
2143
|
+
}
|
|
2144
|
+
function PopoverRoot({ children, open: openProp, defaultOpen = false, onOpenChange, side = "bottom", align = "center", sideOffset = 8, closeOnOutsidePress = true }) {
|
|
2145
|
+
const triggerRef = useRef(null);
|
|
2146
|
+
const anchorRef = useRef(null);
|
|
2147
|
+
const getReferenceRef = useCallback(() => anchorRef.current ? anchorRef : triggerRef, []);
|
|
2148
|
+
const openChangeDetailsRef = useRef({ reason: "programmatic" });
|
|
2149
|
+
const [open, setOpenState] = useControllableState({
|
|
2150
|
+
value: openProp,
|
|
2151
|
+
defaultValue: defaultOpen,
|
|
2152
|
+
onChange: (nextOpen) => {
|
|
2153
|
+
onOpenChange?.(nextOpen, openChangeDetailsRef.current);
|
|
2154
|
+
}
|
|
2155
|
+
});
|
|
2156
|
+
const { position, arrowPosition, placement, updatePosition: updateFloatingPosition, onFloatingLayout } = useNativeFloatingPosition(getNativePlacement(side, align), sideOffset);
|
|
2157
|
+
const setOpen = useCallback((nextOpen, details) => {
|
|
2158
|
+
openChangeDetailsRef.current = details;
|
|
2159
|
+
setOpenState(nextOpen);
|
|
2160
|
+
}, [setOpenState]);
|
|
2161
|
+
return /* @__PURE__ */ jsx(PopoverProvider, {
|
|
2162
|
+
value: {
|
|
2163
|
+
open,
|
|
2164
|
+
closeOnOutsidePress,
|
|
2165
|
+
triggerRef,
|
|
2166
|
+
anchorRef,
|
|
2167
|
+
side,
|
|
2168
|
+
align,
|
|
2169
|
+
placement,
|
|
2170
|
+
position,
|
|
2171
|
+
arrowPosition,
|
|
2172
|
+
onFloatingLayout,
|
|
2173
|
+
updatePosition: useCallback((containerRef) => {
|
|
2174
|
+
updateFloatingPosition(getReferenceRef(), containerRef);
|
|
2175
|
+
}, [getReferenceRef, updateFloatingPosition]),
|
|
2176
|
+
setOpen
|
|
2177
|
+
},
|
|
2178
|
+
children
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2181
|
+
PopoverRoot.displayName = "Popover.Root";
|
|
2182
|
+
//#endregion
|
|
2183
|
+
//#region src/components/Popover/Title/PopoverTitle.styles.ts
|
|
2184
|
+
function createPopoverTitleStyles(theme) {
|
|
2185
|
+
return StyleSheet.create({ title: {
|
|
2186
|
+
color: theme.components.popover.title.fg,
|
|
2187
|
+
fontSize: theme.tokens.typography.size.md,
|
|
2188
|
+
fontWeight: toNativeFontWeight(theme.tokens.typography.weight.semibold)
|
|
2189
|
+
} });
|
|
2190
|
+
}
|
|
2191
|
+
//#endregion
|
|
2192
|
+
//#region src/components/Popover/Title/PopoverTitle.tsx
|
|
2193
|
+
const PopoverTitle = ({ children, style, ...titleProps }) => {
|
|
2194
|
+
const { theme } = useTheme();
|
|
2195
|
+
const styles = useMemo(() => createPopoverTitleStyles(theme), [theme]);
|
|
2196
|
+
return /* @__PURE__ */ jsx(Text, {
|
|
2197
|
+
...titleProps,
|
|
2198
|
+
style: [styles.title, style],
|
|
2199
|
+
children
|
|
2200
|
+
});
|
|
2201
|
+
};
|
|
2202
|
+
PopoverTitle.displayName = "PopoverTitle";
|
|
2203
|
+
//#endregion
|
|
2204
|
+
//#region src/components/Popover/Trigger/PopoverTrigger.tsx
|
|
2205
|
+
function PopoverTrigger({ children, asChild = false, onPress, ...triggerProps }) {
|
|
2206
|
+
const { open, setOpen, triggerRef } = usePopoverContext("Popover.Trigger");
|
|
2207
|
+
const handlePress = (event) => {
|
|
2208
|
+
children.props.onPress?.(event);
|
|
2209
|
+
onPress?.(event);
|
|
2210
|
+
if (event.defaultPrevented) return;
|
|
2211
|
+
setOpen(!open, { reason: "trigger" });
|
|
2212
|
+
};
|
|
2213
|
+
if (asChild) return cloneElement(children, {
|
|
2214
|
+
ref: triggerRef,
|
|
2215
|
+
onPress: handlePress
|
|
2216
|
+
});
|
|
2217
|
+
return /* @__PURE__ */ jsx(Pressable, {
|
|
2218
|
+
...triggerProps,
|
|
2219
|
+
ref: triggerRef,
|
|
2220
|
+
onPress: handlePress,
|
|
2221
|
+
children
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
2224
|
+
//#endregion
|
|
2225
|
+
//#region src/components/Popover/Popover.tsx
|
|
2226
|
+
const Popover = Object.assign(PopoverRoot, {
|
|
2227
|
+
Anchor: PopoverAnchor,
|
|
2228
|
+
Trigger: PopoverTrigger,
|
|
2229
|
+
Content: PopoverContent,
|
|
2230
|
+
Arrow: PopoverArrow,
|
|
2231
|
+
Close: PopoverClose,
|
|
2232
|
+
Title: PopoverTitle,
|
|
2233
|
+
Description: PopoverDescription
|
|
2234
|
+
});
|
|
2235
|
+
Popover.displayName = "Popover";
|
|
2236
|
+
//#endregion
|
|
1885
2237
|
//#region src/components/RadioGroup/internal/RadioGroupContext.tsx
|
|
1886
2238
|
const RadioGroupContext = createContext(null);
|
|
1887
2239
|
const RadioGroupProvider = RadioGroupContext.Provider;
|
|
@@ -5783,35 +6135,4 @@ const Input = forwardRef(({ label, description, value, defaultValue, onValueChan
|
|
|
5783
6135
|
});
|
|
5784
6136
|
Input.displayName = "Input";
|
|
5785
6137
|
//#endregion
|
|
5786
|
-
|
|
5787
|
-
const PortalContext = createContext(null);
|
|
5788
|
-
const styles = StyleSheet.create({ host: { flex: 1 } });
|
|
5789
|
-
const PortalProvider = ({ children, container = null }) => /* @__PURE__ */ jsx(PortalContext.Provider, {
|
|
5790
|
-
value: container,
|
|
5791
|
-
children
|
|
5792
|
-
});
|
|
5793
|
-
const Portal = ({ children, visible = true, animationType = "none", hardwareAccelerated = true, navigationBarTranslucent = true, statusBarTranslucent = true, onDismiss, onRequestClose }) => {
|
|
5794
|
-
useContext(PortalContext);
|
|
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
|
-
});
|
|
5812
|
-
};
|
|
5813
|
-
Portal.__velliraPortal = true;
|
|
5814
|
-
Portal.displayName = "Portal";
|
|
5815
|
-
PortalProvider.displayName = "PortalProvider";
|
|
5816
|
-
//#endregion
|
|
5817
|
-
export { Button, Checkbox, Dropdown, FormField, Input, Modal, Portal, PortalProvider, Radio, RadioGroup, Select, Tabs, ThemeProvider, Tooltip, nativeThemes, useTheme };
|
|
6138
|
+
export { Button, Checkbox, Dropdown, FormField, Input, Modal, Popover, Portal, PortalProvider, Radio, RadioGroup, Select, Tabs, ThemeProvider, Tooltip, nativeThemes, useTheme };
|