@mrmeg/expo-ui 0.1.4 → 0.1.6
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/LLM_USAGE.md +16 -2
- package/README.md +24 -20
- package/dist/components/Accordion.js +19 -16
- package/dist/components/Badge.js +5 -4
- package/dist/components/Button.d.ts +1 -1
- package/dist/components/Button.js +84 -51
- package/dist/components/Card.js +4 -3
- package/dist/components/Checkbox.js +6 -4
- package/dist/components/Collapsible.js +15 -14
- package/dist/components/Dialog.js +6 -6
- package/dist/components/Drawer.js +5 -5
- package/dist/components/DropdownMenu.js +119 -112
- package/dist/components/EmptyState.js +5 -3
- package/dist/components/InputOTP.js +3 -3
- package/dist/components/Label.js +5 -2
- package/dist/components/Notification.js +6 -6
- package/dist/components/Popover.js +2 -2
- package/dist/components/RadioGroup.js +6 -4
- package/dist/components/Select.js +35 -25
- package/dist/components/Slider.js +34 -24
- package/dist/components/StyledText.d.ts +15 -4
- package/dist/components/StyledText.js +28 -7
- package/dist/components/Switch.js +28 -28
- package/dist/components/Tabs.js +6 -3
- package/dist/components/TextInput.js +8 -10
- package/dist/components/Toggle.js +4 -2
- package/dist/components/ToggleGroup.js +3 -2
- package/dist/components/Tooltip.js +4 -4
- package/dist/constants/colors.d.ts +4 -0
- package/dist/constants/colors.js +9 -1
- package/dist/constants/spacing.d.ts +2 -1
- package/dist/constants/spacing.js +2 -1
- package/dist/hooks/useTheme.d.ts +3 -1
- package/dist/hooks/useTheme.js +46 -18
- package/dist/lib/i18n.d.ts +2 -2
- package/dist/lib/i18n.js +5 -5
- package/package.json +6 -7
|
@@ -21,14 +21,14 @@ function DialogRoot({ children, ...props }) {
|
|
|
21
21
|
}
|
|
22
22
|
function DialogContent({ portalHost, style, children, ...props }) {
|
|
23
23
|
const { theme, getShadowStyle, getContrastingColor } = useTheme();
|
|
24
|
-
const textColor = getContrastingColor(theme.colors.
|
|
24
|
+
const textColor = getContrastingColor(theme.colors.popover, palette.white, palette.black);
|
|
25
25
|
return (_jsx(DialogPrimitive.Portal, { hostName: portalHost, children: _jsx(FullWindowOverlay, { children: _jsx(DialogPrimitive.Overlay, { style: StyleSheet.flatten([
|
|
26
26
|
StyleSheet.absoluteFill,
|
|
27
27
|
{ backgroundColor: theme.colors.overlay },
|
|
28
28
|
Platform.OS === "web" && { zIndex: 50 },
|
|
29
29
|
]), children: _jsx(AnimatedView, { type: "fade", enterDuration: 200, children: _jsx(View, { style: overlayStyles.centeredContainer, children: _jsx(AnimatedView, { type: "scale", enterDuration: 250, children: _jsx(TextColorContext.Provider, { value: textColor, children: _jsx(TextClassContext.Provider, { value: "", children: _jsx(DialogPrimitive.Content, { style: StyleSheet.flatten([
|
|
30
30
|
{
|
|
31
|
-
backgroundColor: theme.colors.
|
|
31
|
+
backgroundColor: theme.colors.popover,
|
|
32
32
|
borderColor: theme.colors.border,
|
|
33
33
|
borderWidth: 1,
|
|
34
34
|
borderRadius: spacing.radiusLg,
|
|
@@ -61,7 +61,7 @@ function DialogTitle({ children, style, ...props }) {
|
|
|
61
61
|
{
|
|
62
62
|
fontSize: 18,
|
|
63
63
|
lineHeight: 24,
|
|
64
|
-
letterSpacing:
|
|
64
|
+
letterSpacing: 0,
|
|
65
65
|
color: theme.colors.text,
|
|
66
66
|
},
|
|
67
67
|
style,
|
|
@@ -98,14 +98,14 @@ function AlertDialogRoot({ children, ...props }) {
|
|
|
98
98
|
}
|
|
99
99
|
function AlertDialogContent({ portalHost, style, children, ...props }) {
|
|
100
100
|
const { theme, getShadowStyle, getContrastingColor } = useTheme();
|
|
101
|
-
const textColor = getContrastingColor(theme.colors.
|
|
101
|
+
const textColor = getContrastingColor(theme.colors.popover, palette.white, palette.black);
|
|
102
102
|
return (_jsx(AlertDialogPrimitive.Portal, { hostName: portalHost, children: _jsx(FullWindowOverlay, { children: _jsx(AlertDialogPrimitive.Overlay, { style: StyleSheet.flatten([
|
|
103
103
|
StyleSheet.absoluteFill,
|
|
104
104
|
{ backgroundColor: theme.colors.overlay },
|
|
105
105
|
Platform.OS === "web" && { zIndex: 52 },
|
|
106
106
|
]), children: _jsx(AnimatedView, { type: "fade", enterDuration: 200, children: _jsx(View, { style: overlayStyles.centeredContainer, children: _jsx(AnimatedView, { type: "scale", enterDuration: 250, children: _jsx(TextColorContext.Provider, { value: textColor, children: _jsx(TextClassContext.Provider, { value: "", children: _jsx(AlertDialogPrimitive.Content, { style: StyleSheet.flatten([
|
|
107
107
|
{
|
|
108
|
-
backgroundColor: theme.colors.
|
|
108
|
+
backgroundColor: theme.colors.popover,
|
|
109
109
|
borderColor: theme.colors.border,
|
|
110
110
|
borderWidth: 1,
|
|
111
111
|
borderRadius: spacing.radiusLg,
|
|
@@ -124,7 +124,7 @@ function AlertDialogTitle({ children, style, ...props }) {
|
|
|
124
124
|
{
|
|
125
125
|
fontSize: 18,
|
|
126
126
|
lineHeight: 24,
|
|
127
|
-
letterSpacing:
|
|
127
|
+
letterSpacing: 0,
|
|
128
128
|
color: theme.colors.text,
|
|
129
129
|
},
|
|
130
130
|
style,
|
|
@@ -70,9 +70,9 @@ function parseWidth(width) {
|
|
|
70
70
|
}
|
|
71
71
|
function drawerReducer(state, action) {
|
|
72
72
|
switch (action.type) {
|
|
73
|
-
case
|
|
74
|
-
case
|
|
75
|
-
case
|
|
73
|
+
case "OPEN": return true;
|
|
74
|
+
case "CLOSE": return false;
|
|
75
|
+
case "TOGGLE": return !state; // Always uses current state!
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
// ============================================================================
|
|
@@ -91,7 +91,7 @@ function DrawerRoot({ open: controlledOpen, onOpenChange: controlledOnOpenChange
|
|
|
91
91
|
controlledOnOpenChange?.(!controlledOpen);
|
|
92
92
|
}
|
|
93
93
|
else {
|
|
94
|
-
dispatch({ type:
|
|
94
|
+
dispatch({ type: "TOGGLE" });
|
|
95
95
|
}
|
|
96
96
|
};
|
|
97
97
|
// Handler for explicit open/close actions
|
|
@@ -100,7 +100,7 @@ function DrawerRoot({ open: controlledOpen, onOpenChange: controlledOnOpenChange
|
|
|
100
100
|
controlledOnOpenChange?.(newOpen);
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
103
|
-
dispatch({ type: newOpen ?
|
|
103
|
+
dispatch({ type: newOpen ? "OPEN" : "CLOSE" });
|
|
104
104
|
}
|
|
105
105
|
};
|
|
106
106
|
const parsedWidth = parseWidth(width);
|
|
@@ -3,7 +3,7 @@ import * as React from "react";
|
|
|
3
3
|
import { Platform, StyleSheet, Text, View } from "react-native";
|
|
4
4
|
import { Icon } from "./Icon.js";
|
|
5
5
|
import { AnimatedView } from "./AnimatedView.js";
|
|
6
|
-
import { TextClassContext } from "./StyledText.js";
|
|
6
|
+
import { TextClassContext, TextSelectabilityContext } from "./StyledText.js";
|
|
7
7
|
import { useTheme } from "../hooks/useTheme.js";
|
|
8
8
|
import { spacing } from "../constants/spacing.js";
|
|
9
9
|
import * as DropdownMenuPrimitive from "@rn-primitives/dropdown-menu";
|
|
@@ -22,28 +22,29 @@ function DropdownMenuSubTrigger({ inset = false, children, style: styleOverride,
|
|
|
22
22
|
const { theme } = useTheme();
|
|
23
23
|
const { open } = DropdownMenuPrimitive.useSubContext();
|
|
24
24
|
const iconName = Platform.OS === "web" ? "chevron-right" : open ? "chevron-up" : "chevron-down";
|
|
25
|
-
return (_jsx(TextClassContext.Provider, { value: "", children: _jsxs(DropdownMenuPrimitive.SubTrigger, { ...props, style: {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
25
|
+
return (_jsx(TextClassContext.Provider, { value: "", children: _jsx(TextSelectabilityContext.Provider, { value: false, children: _jsxs(DropdownMenuPrimitive.SubTrigger, { ...props, style: {
|
|
26
|
+
flexDirection: "row",
|
|
27
|
+
alignItems: "center",
|
|
28
|
+
borderRadius: spacing.radiusSm,
|
|
29
|
+
paddingHorizontal: spacing.sm,
|
|
30
|
+
paddingVertical: Platform.select({ web: spacing.xs, default: spacing.sm }),
|
|
31
|
+
backgroundColor: open ? theme.colors.muted : "transparent",
|
|
32
|
+
...(Platform.OS === "web" && {
|
|
33
|
+
cursor: "pointer",
|
|
34
|
+
outlineStyle: "none",
|
|
35
|
+
userSelect: "none",
|
|
36
|
+
}),
|
|
37
|
+
...(inset && { paddingLeft: spacing.xl }),
|
|
38
|
+
...(styleOverride && typeof styleOverride !== "function"
|
|
39
|
+
? StyleSheet.flatten(styleOverride)
|
|
40
|
+
: {}),
|
|
41
|
+
}, children: [typeof children === "function" ? null : children, _jsx(View, { style: { marginLeft: "auto" }, children: _jsx(Icon, { name: iconName, size: 16, color: theme.colors.text }) })] }) }) }));
|
|
41
42
|
}
|
|
42
43
|
function DropdownMenuSubContent({ style: styleOverride, ...props }) {
|
|
43
44
|
const { theme, getShadowStyle } = useTheme();
|
|
44
45
|
const shadowStyle = StyleSheet.flatten(getShadowStyle("soft"));
|
|
45
46
|
return (_jsx(AnimatedView, { type: "fade", children: _jsx(DropdownMenuPrimitive.SubContent, { ...props, style: {
|
|
46
|
-
backgroundColor: theme.colors.
|
|
47
|
+
backgroundColor: theme.colors.popover,
|
|
47
48
|
borderWidth: 1,
|
|
48
49
|
borderColor: theme.colors.border,
|
|
49
50
|
borderRadius: spacing.radiusMd,
|
|
@@ -66,108 +67,112 @@ function DropdownMenuContent({ side, align = "start", sideOffset = 4, portalHost
|
|
|
66
67
|
return (_jsx(DropdownMenuPrimitive.Portal, { hostName: portalHost, children: _jsx(FullWindowOverlay, { children: _jsx(DropdownMenuPrimitive.Overlay, { style: Platform.select({
|
|
67
68
|
native: StyleSheet.absoluteFill,
|
|
68
69
|
default: undefined,
|
|
69
|
-
}), children: _jsx(AnimatedView, { type: "fade", children: _jsx(TextClassContext.Provider, { value: "", children: _jsx(DropdownMenuPrimitive.Content, { side: side, align: align, sideOffset: sideOffset, insets: insets, avoidCollisions: true, ...props, style: {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
70
|
+
}), children: _jsx(AnimatedView, { type: "fade", children: _jsx(TextClassContext.Provider, { value: "", children: _jsx(TextSelectabilityContext.Provider, { value: false, children: _jsx(DropdownMenuPrimitive.Content, { side: side, align: align, sideOffset: sideOffset, insets: insets, avoidCollisions: true, ...props, style: {
|
|
71
|
+
backgroundColor: theme.colors.popover,
|
|
72
|
+
borderWidth: 1,
|
|
73
|
+
borderColor: theme.colors.border,
|
|
74
|
+
borderRadius: spacing.radiusSm,
|
|
75
|
+
padding: spacing.xs,
|
|
76
|
+
minWidth: 128,
|
|
77
|
+
overflow: "hidden",
|
|
78
|
+
...shadowStyle,
|
|
79
|
+
...(Platform.OS === "web" && {
|
|
80
|
+
zIndex: 50,
|
|
81
|
+
cursor: "default",
|
|
82
|
+
userSelect: "none",
|
|
83
|
+
}),
|
|
84
|
+
...(styleOverride && typeof styleOverride !== "function"
|
|
85
|
+
? StyleSheet.flatten(styleOverride)
|
|
86
|
+
: {}),
|
|
87
|
+
} }) }) }) }) }) }) }));
|
|
86
88
|
}
|
|
87
89
|
function DropdownMenuItem({ inset = false, variant = "default", style: styleOverride, ...props }) {
|
|
88
90
|
const { theme } = useTheme();
|
|
89
|
-
return (_jsx(TextClassContext.Provider, { value: "", children: _jsx(DropdownMenuPrimitive.Item, { ...props, style: {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
91
|
+
return (_jsx(TextClassContext.Provider, { value: "", children: _jsx(TextSelectabilityContext.Provider, { value: false, children: _jsx(DropdownMenuPrimitive.Item, { ...props, style: {
|
|
92
|
+
position: "relative",
|
|
93
|
+
flexDirection: "row",
|
|
94
|
+
alignItems: "center",
|
|
95
|
+
gap: spacing.sm,
|
|
96
|
+
borderRadius: spacing.radiusSm,
|
|
97
|
+
paddingHorizontal: spacing.sm,
|
|
98
|
+
paddingVertical: Platform.select({ web: spacing.xs, default: spacing.sm }),
|
|
99
|
+
backgroundColor: "transparent",
|
|
100
|
+
...(Platform.OS === "web" && {
|
|
101
|
+
cursor: props.disabled ? "not-allowed" : "pointer",
|
|
102
|
+
outlineStyle: "none",
|
|
103
|
+
userSelect: "none",
|
|
104
|
+
}),
|
|
105
|
+
...(props.disabled && { opacity: 0.5 }),
|
|
106
|
+
...(inset && { paddingLeft: spacing.xl }),
|
|
107
|
+
...(styleOverride && typeof styleOverride !== "function"
|
|
108
|
+
? StyleSheet.flatten(styleOverride)
|
|
109
|
+
: {}),
|
|
110
|
+
} }) }) }));
|
|
108
111
|
}
|
|
109
112
|
function DropdownMenuCheckboxItem({ children, style: styleOverride, ...props }) {
|
|
110
113
|
const { theme } = useTheme();
|
|
111
|
-
return (_jsx(TextClassContext.Provider, { value: "", children: _jsxs(DropdownMenuPrimitive.CheckboxItem, { ...props, style: {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
114
|
+
return (_jsx(TextClassContext.Provider, { value: "", children: _jsx(TextSelectabilityContext.Provider, { value: false, children: _jsxs(DropdownMenuPrimitive.CheckboxItem, { ...props, style: {
|
|
115
|
+
position: "relative",
|
|
116
|
+
flexDirection: "row",
|
|
117
|
+
alignItems: "center",
|
|
118
|
+
gap: spacing.sm,
|
|
119
|
+
borderRadius: spacing.radiusSm,
|
|
120
|
+
paddingVertical: Platform.select({ web: spacing.xs, default: spacing.sm }),
|
|
121
|
+
paddingLeft: spacing.xl,
|
|
122
|
+
paddingRight: spacing.sm,
|
|
123
|
+
backgroundColor: "transparent",
|
|
124
|
+
...(Platform.OS === "web" && {
|
|
125
|
+
cursor: props.disabled ? "not-allowed" : "pointer",
|
|
126
|
+
outlineStyle: "none",
|
|
127
|
+
userSelect: "none",
|
|
128
|
+
}),
|
|
129
|
+
...(props.disabled && { opacity: 0.5 }),
|
|
130
|
+
...(styleOverride && typeof styleOverride !== "function"
|
|
131
|
+
? StyleSheet.flatten(styleOverride)
|
|
132
|
+
: {}),
|
|
133
|
+
}, children: [_jsx(View, { style: {
|
|
134
|
+
position: "absolute",
|
|
135
|
+
left: spacing.sm,
|
|
136
|
+
height: 14,
|
|
137
|
+
width: 14,
|
|
138
|
+
alignItems: "center",
|
|
139
|
+
justifyContent: "center",
|
|
140
|
+
}, children: _jsx(DropdownMenuPrimitive.ItemIndicator, { children: _jsx(Icon, { name: "check", size: 16, color: theme.colors.text, ...(Platform.OS === "web" && { style: { pointerEvents: "none" } }) }) }) }), typeof children === "function" ? null : children] }) }) }));
|
|
137
141
|
}
|
|
138
142
|
function DropdownMenuRadioItem({ children, style: styleOverride, ...props }) {
|
|
139
143
|
const { theme } = useTheme();
|
|
140
|
-
return (_jsx(TextClassContext.Provider, { value: "", children: _jsxs(DropdownMenuPrimitive.RadioItem, { ...props, style: {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
144
|
+
return (_jsx(TextClassContext.Provider, { value: "", children: _jsx(TextSelectabilityContext.Provider, { value: false, children: _jsxs(DropdownMenuPrimitive.RadioItem, { ...props, style: {
|
|
145
|
+
position: "relative",
|
|
146
|
+
flexDirection: "row",
|
|
147
|
+
alignItems: "center",
|
|
148
|
+
gap: spacing.sm,
|
|
149
|
+
borderRadius: spacing.radiusSm,
|
|
150
|
+
paddingVertical: Platform.select({ web: spacing.xs, default: spacing.sm }),
|
|
151
|
+
paddingLeft: spacing.xl,
|
|
152
|
+
paddingRight: spacing.sm,
|
|
153
|
+
backgroundColor: "transparent",
|
|
154
|
+
...(Platform.OS === "web" && {
|
|
155
|
+
cursor: props.disabled ? "not-allowed" : "pointer",
|
|
156
|
+
outlineStyle: "none",
|
|
157
|
+
userSelect: "none",
|
|
158
|
+
}),
|
|
159
|
+
...(props.disabled && { opacity: 0.5 }),
|
|
160
|
+
...(styleOverride && typeof styleOverride !== "function"
|
|
161
|
+
? StyleSheet.flatten(styleOverride)
|
|
162
|
+
: {}),
|
|
163
|
+
}, children: [_jsx(View, { style: {
|
|
164
|
+
position: "absolute",
|
|
165
|
+
left: spacing.sm,
|
|
166
|
+
height: 14,
|
|
167
|
+
width: 14,
|
|
168
|
+
alignItems: "center",
|
|
169
|
+
justifyContent: "center",
|
|
170
|
+
}, children: _jsx(DropdownMenuPrimitive.ItemIndicator, { children: _jsx(View, { style: {
|
|
171
|
+
backgroundColor: theme.colors.text,
|
|
172
|
+
height: 8,
|
|
173
|
+
width: 8,
|
|
174
|
+
borderRadius: 4,
|
|
175
|
+
} }) }) }), typeof children === "function" ? null : children] }) }) }));
|
|
171
176
|
}
|
|
172
177
|
function DropdownMenuLabel({ inset = false, style: styleOverride, ...props }) {
|
|
173
178
|
const { theme } = useTheme();
|
|
@@ -177,6 +182,7 @@ function DropdownMenuLabel({ inset = false, style: styleOverride, ...props }) {
|
|
|
177
182
|
fontSize: 14,
|
|
178
183
|
fontWeight: "500",
|
|
179
184
|
color: theme.colors.text,
|
|
185
|
+
userSelect: "none",
|
|
180
186
|
...(inset && { paddingLeft: spacing.xl }),
|
|
181
187
|
...(styleOverride && typeof styleOverride !== "function"
|
|
182
188
|
? StyleSheet.flatten(styleOverride)
|
|
@@ -201,9 +207,10 @@ function DropdownMenuShortcut({ style: styleOverride, ...props }) {
|
|
|
201
207
|
{
|
|
202
208
|
marginLeft: "auto",
|
|
203
209
|
fontSize: 12,
|
|
204
|
-
letterSpacing:
|
|
210
|
+
letterSpacing: 0,
|
|
205
211
|
color: theme.colors.text,
|
|
206
212
|
opacity: 0.6,
|
|
213
|
+
userSelect: "none",
|
|
207
214
|
},
|
|
208
215
|
styleOverride,
|
|
209
216
|
] }));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
2
3
|
import { View, StyleSheet } from "react-native";
|
|
3
4
|
import { SansSerifBoldText, SansSerifText } from "./StyledText.js";
|
|
4
5
|
import { Button } from "./Button.js";
|
|
@@ -24,8 +25,8 @@ import { spacing } from "../constants/spacing.js";
|
|
|
24
25
|
*/
|
|
25
26
|
export function EmptyState({ icon, iconSize = 48, title, description, actionLabel, onAction, actionPreset = "default", style, children, }) {
|
|
26
27
|
const { theme } = useTheme();
|
|
27
|
-
const styles = createStyles(theme);
|
|
28
|
-
return (_jsxs(View, { style: [styles.container, style], children: [!!icon && (_jsx(View, { style: styles.iconWrapper, children: _jsx(Icon, { name: icon, size: iconSize, color: theme.colors.mutedForeground }) })), _jsx(SansSerifBoldText, { style: styles.title, children: title }), !!description && (_jsx(SansSerifText, { style: styles.description, children: description })), children, !!actionLabel && onAction && (_jsx(Button, { preset: actionPreset, onPress: onAction, style: styles.action, children: actionLabel }))] }));
|
|
28
|
+
const styles = useMemo(() => createStyles(theme), [theme]);
|
|
29
|
+
return (_jsxs(View, { style: [styles.container, style], children: [!!icon && (_jsx(View, { style: styles.iconWrapper, children: _jsx(Icon, { name: icon, size: iconSize, color: theme.colors.mutedForeground }) })), _jsx(SansSerifBoldText, { selectable: false, style: styles.title, children: title }), !!description && (_jsx(SansSerifText, { selectable: false, style: styles.description, children: description })), children, !!actionLabel && onAction && (_jsx(Button, { preset: actionPreset, onPress: onAction, style: styles.action, children: actionLabel }))] }));
|
|
29
30
|
}
|
|
30
31
|
const createStyles = (theme) => StyleSheet.create({
|
|
31
32
|
container: {
|
|
@@ -42,7 +43,7 @@ const createStyles = (theme) => StyleSheet.create({
|
|
|
42
43
|
lineHeight: 24,
|
|
43
44
|
color: theme.colors.foreground,
|
|
44
45
|
textAlign: "center",
|
|
45
|
-
letterSpacing:
|
|
46
|
+
letterSpacing: 0,
|
|
46
47
|
},
|
|
47
48
|
description: {
|
|
48
49
|
fontSize: 14,
|
|
@@ -54,5 +55,6 @@ const createStyles = (theme) => StyleSheet.create({
|
|
|
54
55
|
},
|
|
55
56
|
action: {
|
|
56
57
|
marginTop: spacing.lg,
|
|
58
|
+
alignSelf: "center",
|
|
57
59
|
},
|
|
58
60
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { useRef, useState, useCallback } from "react";
|
|
2
|
+
import React, { useMemo, useRef, useState, useCallback } from "react";
|
|
3
3
|
import { View, TextInput as RNTextInput, Pressable, StyleSheet, Platform, } from "react-native";
|
|
4
4
|
import Animated, { useSharedValue, useAnimatedStyle, withTiming, useReducedMotion, } from "react-native-reanimated";
|
|
5
5
|
import { useTheme } from "../hooks/useTheme.js";
|
|
@@ -33,7 +33,7 @@ function InputOTP({ length = 6, value = "", onChangeText, onComplete, error = fa
|
|
|
33
33
|
const reduceMotion = useReducedMotion();
|
|
34
34
|
const inputRef = useRef(null);
|
|
35
35
|
const [focused, setFocused] = useState(false);
|
|
36
|
-
const styles = createStyles(theme);
|
|
36
|
+
const styles = useMemo(() => createStyles(theme), [theme]);
|
|
37
37
|
const hasError = error || !!errorText;
|
|
38
38
|
// Active cell index: next empty cell, or last cell when full
|
|
39
39
|
const activeIndex = Math.min(value.length, length - 1);
|
|
@@ -121,7 +121,7 @@ function OTPCell({ index, total, char, isActive, hasError, disabled, theme, redu
|
|
|
121
121
|
opacity: disabled ? 0.5 : 1,
|
|
122
122
|
},
|
|
123
123
|
animatedStyle,
|
|
124
|
-
], children: _jsx(StyledText, { style: {
|
|
124
|
+
], children: _jsx(StyledText, { selectable: false, style: {
|
|
125
125
|
fontSize: CELL_FONT_SIZE,
|
|
126
126
|
fontWeight: CELL_FONT_WEIGHT,
|
|
127
127
|
fontFamily: fontFamilies.sansSerif.regular,
|
package/dist/components/Label.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
2
3
|
import { StyleSheet, Platform } from "react-native";
|
|
3
4
|
import * as LabelPrimitive from "@rn-primitives/label";
|
|
4
5
|
import { useTheme } from "../hooks/useTheme.js";
|
|
@@ -36,7 +37,7 @@ const SIZE_CONFIGS = {
|
|
|
36
37
|
*/
|
|
37
38
|
export function Label({ children, nativeID, required, size = "md", error, disabled, style, onPress, }) {
|
|
38
39
|
const { theme } = useTheme();
|
|
39
|
-
const styles = createStyles(theme);
|
|
40
|
+
const styles = useMemo(() => createStyles(theme), [theme]);
|
|
40
41
|
const sizeConfig = SIZE_CONFIGS[size];
|
|
41
42
|
const textStyle = StyleSheet.flatten([
|
|
42
43
|
styles.label,
|
|
@@ -48,7 +49,7 @@ export function Label({ children, nativeID, required, size = "md", error, disabl
|
|
|
48
49
|
return (_jsx(LabelPrimitive.Root, { nativeID: nativeID, onPress: onPress, style: {
|
|
49
50
|
...styles.root,
|
|
50
51
|
...(Platform.OS === "web" && onPress && { cursor: "pointer" }),
|
|
51
|
-
}, children: _jsxs(LabelPrimitive.Text, { style: textStyle, children: [children, required && _jsx(StyledText, { style: styles.required, children: " *" })] }) }));
|
|
52
|
+
}, children: _jsxs(LabelPrimitive.Text, { style: textStyle, children: [children, required && _jsx(StyledText, { selectable: false, style: styles.required, children: " *" })] }) }));
|
|
52
53
|
}
|
|
53
54
|
const createStyles = (theme) => StyleSheet.create({
|
|
54
55
|
root: {
|
|
@@ -58,10 +59,12 @@ const createStyles = (theme) => StyleSheet.create({
|
|
|
58
59
|
fontFamily: fontFamilies.sansSerif.regular,
|
|
59
60
|
fontWeight: "500",
|
|
60
61
|
color: theme.colors.text,
|
|
62
|
+
userSelect: "none",
|
|
61
63
|
},
|
|
62
64
|
required: {
|
|
63
65
|
color: theme.colors.destructive,
|
|
64
66
|
fontFamily: fontFamilies.sansSerif.bold,
|
|
67
|
+
userSelect: "none",
|
|
65
68
|
},
|
|
66
69
|
errorLabel: {
|
|
67
70
|
color: theme.colors.destructive,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useContext, useEffect, useRef } from "react";
|
|
2
|
+
import { useMemo, useCallback, useContext, useEffect, useRef } from "react";
|
|
3
3
|
import { StyleSheet, View, ActivityIndicator, Pressable, Platform } from "react-native";
|
|
4
4
|
import Animated, { useSharedValue, useAnimatedStyle, withTiming, runOnJS, useReducedMotion, Easing, } from "react-native-reanimated";
|
|
5
5
|
import { SafeAreaInsetsContext } from "react-native-safe-area-context";
|
|
@@ -40,7 +40,7 @@ export const Notification = () => {
|
|
|
40
40
|
const reduceMotion = useReducedMotion();
|
|
41
41
|
const insets = useContext(SafeAreaInsetsContext);
|
|
42
42
|
const { alert, hide } = globalUIStore();
|
|
43
|
-
const styles = createStyles(theme);
|
|
43
|
+
const styles = useMemo(() => createStyles(theme), [theme]);
|
|
44
44
|
const position = alert?.position ?? "top";
|
|
45
45
|
const isBottom = position === "bottom";
|
|
46
46
|
// Just opacity + translateY — no scale (scale = bouncy feel)
|
|
@@ -139,11 +139,11 @@ export const Notification = () => {
|
|
|
139
139
|
return alert.title;
|
|
140
140
|
switch (alert?.type) {
|
|
141
141
|
case "error":
|
|
142
|
-
return translateText("notification.error");
|
|
142
|
+
return translateText("notification.error", "Error");
|
|
143
143
|
case "success":
|
|
144
|
-
return translateText("notification.success");
|
|
144
|
+
return translateText("notification.success", "Success");
|
|
145
145
|
case "warning":
|
|
146
|
-
return translateText("notification.warning");
|
|
146
|
+
return translateText("notification.warning", "Warning");
|
|
147
147
|
case "info":
|
|
148
148
|
return "";
|
|
149
149
|
default:
|
|
@@ -164,7 +164,7 @@ export const Notification = () => {
|
|
|
164
164
|
styles.alert,
|
|
165
165
|
isBottom && styles.alertBottom,
|
|
166
166
|
getShadowStyle("base"),
|
|
167
|
-
], children: [_jsx(View, { style: [styles.iconBadge, { backgroundColor: iconBgColor }], children: alert?.loading ? (_jsx(ActivityIndicator, { size: "small", color: iconColor })) : (_jsx(Icon, { name: icon, size: 18, color: iconColor })) }), _jsxs(View, { style: styles.alertContent, children: [!!title && (_jsx(StyledText, { style: [styles.alertTitle, { color: theme.colors.foreground }], numberOfLines: 1, children: title })), hasMessage && (_jsx(StyledText, { style: [styles.alertDescription, { color: theme.colors.mutedForeground }], numberOfLines: 2, children: alert.messages[0] }))] }), _jsx(Pressable, { style: styles.closeButton, hitSlop: spacing.sm, onPress: animateOut, accessibilityLabel: "Dismiss notification", accessibilityRole: "button", children: _jsx(Icon, { name: "x", size: 16, color: theme.colors.mutedForeground }) })] }) }));
|
|
167
|
+
], children: [_jsx(View, { style: [styles.iconBadge, { backgroundColor: iconBgColor }], children: alert?.loading ? (_jsx(ActivityIndicator, { size: "small", color: iconColor })) : (_jsx(Icon, { name: icon, size: 18, color: iconColor })) }), _jsxs(View, { style: styles.alertContent, children: [!!title && (_jsx(StyledText, { selectable: false, style: [styles.alertTitle, { color: theme.colors.foreground }], numberOfLines: 1, children: title })), hasMessage && (_jsx(StyledText, { selectable: false, style: [styles.alertDescription, { color: theme.colors.mutedForeground }], numberOfLines: 2, children: alert.messages[0] }))] }), _jsx(Pressable, { style: styles.closeButton, hitSlop: spacing.sm, onPress: animateOut, accessibilityLabel: "Dismiss notification", accessibilityRole: "button", children: _jsx(Icon, { name: "x", size: 16, color: theme.colors.mutedForeground }) })] }) }));
|
|
168
168
|
};
|
|
169
169
|
const createStyles = (theme) => StyleSheet.create({
|
|
170
170
|
container: {
|
|
@@ -26,10 +26,10 @@ const FullWindowOverlay = Platform.OS === "ios" ? RNFullWindowOverlay : React.Fr
|
|
|
26
26
|
function PopoverContent({ side, align = "center", sideOffset = 4, portalHost, ...props }) {
|
|
27
27
|
const { theme, getShadowStyle, getContrastingColor } = useTheme();
|
|
28
28
|
// Calculate text color for popover content based on background
|
|
29
|
-
const textColor = getContrastingColor(theme.colors.
|
|
29
|
+
const textColor = getContrastingColor(theme.colors.popover, palette.white, palette.black);
|
|
30
30
|
const contentStyle = StyleSheet.flatten([
|
|
31
31
|
{
|
|
32
|
-
backgroundColor: theme.colors.
|
|
32
|
+
backgroundColor: theme.colors.popover,
|
|
33
33
|
borderColor: theme.colors.border,
|
|
34
34
|
borderWidth: 1,
|
|
35
35
|
borderRadius: spacing.radiusMd,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useContext, useEffect } from "react";
|
|
3
|
-
import { View, StyleSheet, Pressable } from "react-native";
|
|
3
|
+
import { View, StyleSheet, Pressable, Platform } from "react-native";
|
|
4
4
|
import Animated, { useSharedValue, useAnimatedStyle, withTiming, useReducedMotion, } from "react-native-reanimated";
|
|
5
5
|
import { StyledText } from "./StyledText.js";
|
|
6
6
|
import { useTheme } from "../hooks/useTheme.js";
|
|
@@ -78,7 +78,7 @@ function RadioGroupItem({ label, required = false, style: styleOverride, labelSt
|
|
|
78
78
|
const flattenedStyle = styleOverride ? StyleSheet.flatten(styleOverride) : undefined;
|
|
79
79
|
const radioElement = (_jsx(RadioGroupPrimitive.Item, { ...props, value: itemValue, disabled: disabled, onPress: handlePress, style: {
|
|
80
80
|
borderColor,
|
|
81
|
-
backgroundColor:
|
|
81
|
+
backgroundColor: theme.colors.background,
|
|
82
82
|
borderRadius: sizeConfig.outer / 2,
|
|
83
83
|
borderWidth: sizeConfig.borderWidth,
|
|
84
84
|
width: sizeConfig.outer,
|
|
@@ -86,6 +86,7 @@ function RadioGroupItem({ label, required = false, style: styleOverride, labelSt
|
|
|
86
86
|
justifyContent: "center",
|
|
87
87
|
alignItems: "center",
|
|
88
88
|
opacity: disabled ? 0.5 : 1,
|
|
89
|
+
...(Platform.OS === "web" && { cursor: disabled ? "not-allowed" : "pointer" }),
|
|
89
90
|
...(flattenedStyle || {}),
|
|
90
91
|
}, hitSlop: DEFAULT_HIT_SLOP, accessibilityLabel: label, children: _jsx(Animated.View, { style: [
|
|
91
92
|
dotStyle,
|
|
@@ -109,18 +110,19 @@ function RadioGroupItem({ label, required = false, style: styleOverride, labelSt
|
|
|
109
110
|
}, style: [styles.container, labelStyle], disabled: disabled, accessibilityRole: "radio", accessibilityState: {
|
|
110
111
|
checked: isChecked,
|
|
111
112
|
disabled: !!disabled,
|
|
112
|
-
}, accessibilityLabel: label, children: [radioElement, _jsx(View, { style: styles.labelContainer, children: _jsxs(StyledText, { style: [
|
|
113
|
+
}, accessibilityLabel: label, children: [radioElement, _jsx(View, { style: styles.labelContainer, children: _jsxs(StyledText, { selectable: false, style: [
|
|
113
114
|
styles.label,
|
|
114
115
|
{ color: theme.colors.text },
|
|
115
116
|
disabled && styles.disabledLabel,
|
|
116
117
|
error && { color: theme.colors.destructive },
|
|
117
|
-
], children: [label, required && (_jsx(StyledText, { style: [styles.required, { color: theme.colors.destructive }], children: " *" }))] }) })] }));
|
|
118
|
+
], children: [label, required && (_jsx(StyledText, { selectable: false, style: [styles.required, { color: theme.colors.destructive }], children: " *" }))] }) })] }));
|
|
118
119
|
}
|
|
119
120
|
const styles = StyleSheet.create({
|
|
120
121
|
container: {
|
|
121
122
|
flexDirection: "row",
|
|
122
123
|
alignItems: "center",
|
|
123
124
|
gap: spacing.sm,
|
|
125
|
+
minHeight: spacing.touchTarget,
|
|
124
126
|
},
|
|
125
127
|
labelContainer: {
|
|
126
128
|
flex: 1,
|