@mrmeg/expo-ui 0.11.0 → 0.13.0-rsd.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/CHANGELOG.md +19 -0
- package/LLM_USAGE.md +1 -0
- package/README.md +2 -1
- package/dist/components/Accordion.d.ts +38 -18
- package/dist/components/Accordion.js +137 -121
- package/dist/components/AnimatedView.d.ts +13 -24
- package/dist/components/AnimatedView.js +70 -29
- package/dist/components/Badge.d.ts +2 -2
- package/dist/components/Badge.js +45 -47
- package/dist/components/BottomSheet.d.ts +30 -73
- package/dist/components/BottomSheet.js +240 -188
- package/dist/components/Button.d.ts +43 -56
- package/dist/components/Button.js +189 -203
- package/dist/components/Card.d.ts +7 -10
- package/dist/components/Card.js +90 -105
- package/dist/components/Checkbox.d.ts +20 -8
- package/dist/components/Checkbox.js +77 -80
- package/dist/components/Collapsible.d.ts +47 -47
- package/dist/components/Collapsible.js +108 -29
- package/dist/components/Dialog.d.ts +80 -121
- package/dist/components/Dialog.js +225 -132
- package/dist/components/DismissKeyboard.d.ts +1 -1
- package/dist/components/DismissKeyboard.js +73 -22
- package/dist/components/Drawer.d.ts +37 -76
- package/dist/components/Drawer.js +252 -486
- package/dist/components/DropdownMenu.d.ts +106 -113
- package/dist/components/DropdownMenu.js +350 -204
- package/dist/components/EmptyState.d.ts +2 -2
- package/dist/components/EmptyState.js +41 -34
- package/dist/components/InputOTP.d.ts +19 -53
- package/dist/components/InputOTP.js +81 -102
- package/dist/components/KeyboardAvoidingView.d.ts +23 -0
- package/dist/components/KeyboardAvoidingView.js +33 -0
- package/dist/components/Label.d.ts +12 -17
- package/dist/components/Label.js +38 -51
- package/dist/components/MaxWidthContainer.d.ts +5 -16
- package/dist/components/MaxWidthContainer.js +28 -29
- package/dist/components/Notification.d.ts +5 -9
- package/dist/components/Notification.js +190 -187
- package/dist/components/Popover.d.ts +38 -66
- package/dist/components/Popover.js +158 -69
- package/dist/components/Progress.d.ts +5 -4
- package/dist/components/Progress.js +65 -77
- package/dist/components/RadioGroup.d.ts +30 -24
- package/dist/components/RadioGroup.js +90 -94
- package/dist/components/Select.d.ts +62 -74
- package/dist/components/Select.js +241 -154
- package/dist/components/Separator.d.ts +13 -23
- package/dist/components/Separator.js +29 -36
- package/dist/components/Skeleton.d.ts +8 -7
- package/dist/components/Skeleton.js +74 -61
- package/dist/components/StyledText.context.d.ts +6 -2
- package/dist/components/StyledText.context.js +3 -0
- package/dist/components/StyledText.d.ts +29 -7
- package/dist/components/StyledText.js +92 -29
- package/dist/components/Switch.d.ts +18 -6
- package/dist/components/Switch.js +112 -106
- package/dist/components/Tabs.d.ts +26 -16
- package/dist/components/Tabs.js +189 -91
- package/dist/components/TextInput.d.ts +6 -19
- package/dist/components/TextInput.js +261 -195
- package/dist/components/Toggle.d.ts +23 -41
- package/dist/components/Toggle.js +84 -98
- package/dist/components/ToggleGroup.d.ts +37 -29
- package/dist/components/ToggleGroup.js +113 -108
- package/dist/components/Tooltip.d.ts +41 -111
- package/dist/components/Tooltip.js +156 -118
- package/dist/components/UIProvider.d.ts +13 -2
- package/dist/components/UIProvider.js +7 -3
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/keyboardFocusRegistry.d.ts +15 -0
- package/dist/components/keyboardFocusRegistry.js +27 -0
- package/dist/hooks/useTheme.d.ts +34 -10
- package/dist/hooks/useTheme.js +20 -8
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.js +2 -0
- package/dist/lib/portal.d.ts +16 -0
- package/dist/lib/portal.js +84 -0
- package/dist/lib/styles.d.ts +32 -0
- package/dist/lib/styles.js +91 -0
- package/dist/lib/useAnchoredPosition.d.ts +57 -0
- package/dist/lib/useAnchoredPosition.js +120 -0
- package/llms-full.md +9 -4
- package/package.json +4 -22
package/dist/components/Badge.js
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React
|
|
3
|
-
import {
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { css, html } from "react-strict-dom";
|
|
4
4
|
import { useTheme } from "../hooks/useTheme.js";
|
|
5
|
-
import { spacing } from "../constants/spacing.js";
|
|
6
5
|
import { StyledText } from "./StyledText.js";
|
|
6
|
+
import { sanitizeWebStyle } from "../lib/styles.js";
|
|
7
|
+
// Static structure + function rules for theme-driven colors. The pill radius is
|
|
8
|
+
// a static literal (spacing.radiusFull = 9999) so StyleX can inline it; theme
|
|
9
|
+
// colors flow through function rules. No flex-child props on the outer element.
|
|
10
|
+
const styles = css.create({
|
|
11
|
+
badge: {
|
|
12
|
+
alignSelf: "flex-start",
|
|
13
|
+
borderRadius: 9999,
|
|
14
|
+
paddingLeft: 10,
|
|
15
|
+
paddingRight: 10,
|
|
16
|
+
paddingTop: 2,
|
|
17
|
+
paddingBottom: 2,
|
|
18
|
+
},
|
|
19
|
+
solid: (backgroundColor) => ({ backgroundColor }),
|
|
20
|
+
outline: (borderColor) => ({
|
|
21
|
+
backgroundColor: "transparent",
|
|
22
|
+
borderWidth: 1,
|
|
23
|
+
borderStyle: "solid",
|
|
24
|
+
borderColor,
|
|
25
|
+
}),
|
|
26
|
+
});
|
|
27
|
+
const TEXT_STYLE = {
|
|
28
|
+
fontSize: 12,
|
|
29
|
+
fontWeight: "500",
|
|
30
|
+
lineHeight: 18,
|
|
31
|
+
userSelect: "none",
|
|
32
|
+
};
|
|
7
33
|
/**
|
|
8
34
|
* Badge Component
|
|
9
35
|
*
|
|
@@ -19,15 +45,15 @@ import { StyledText } from "./StyledText.js";
|
|
|
19
45
|
*/
|
|
20
46
|
function Badge({ children, text, variant = "default", style: styleOverride }) {
|
|
21
47
|
const { theme } = useTheme();
|
|
22
|
-
const styles = useMemo(() => createStyles(theme), [theme]);
|
|
23
48
|
const badgeContent = text ?? children;
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
variant === "
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
49
|
+
const textColor = variant === "default"
|
|
50
|
+
? theme.colors.primaryForeground
|
|
51
|
+
: variant === "secondary"
|
|
52
|
+
? theme.colors.secondaryForeground
|
|
53
|
+
: variant === "destructive"
|
|
54
|
+
? theme.colors.destructiveForeground
|
|
55
|
+
: theme.colors.foreground;
|
|
56
|
+
const textStyle = { ...TEXT_STYLE, color: textColor };
|
|
31
57
|
const normalizedChildren = React.Children.toArray(badgeContent);
|
|
32
58
|
const hasOnlyTextChildren = normalizedChildren.every((child) => typeof child === "string" || typeof child === "number");
|
|
33
59
|
const content = hasOnlyTextChildren ? (_jsx(StyledText, { selectable: false, style: textStyle, children: normalizedChildren.join("") })) : (React.Children.map(badgeContent, (child) => {
|
|
@@ -36,41 +62,13 @@ function Badge({ children, text, variant = "default", style: styleOverride }) {
|
|
|
36
62
|
}
|
|
37
63
|
return child;
|
|
38
64
|
}));
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
variant === "
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
const background = variant === "default"
|
|
66
|
+
? styles.solid(theme.colors.primary)
|
|
67
|
+
: variant === "secondary"
|
|
68
|
+
? styles.solid(theme.colors.secondary)
|
|
69
|
+
: variant === "destructive"
|
|
70
|
+
? styles.solid(theme.colors.destructive)
|
|
71
|
+
: styles.outline(theme.colors.border);
|
|
72
|
+
return (_jsx(html.div, { style: [styles.badge, background, sanitizeWebStyle(styleOverride)], children: content }));
|
|
47
73
|
}
|
|
48
|
-
const createStyles = (theme) => StyleSheet.create({
|
|
49
|
-
badge: {
|
|
50
|
-
alignSelf: "flex-start",
|
|
51
|
-
borderRadius: spacing.radiusFull,
|
|
52
|
-
paddingHorizontal: 10,
|
|
53
|
-
paddingVertical: 2,
|
|
54
|
-
},
|
|
55
|
-
default: {
|
|
56
|
-
backgroundColor: theme.colors.primary,
|
|
57
|
-
},
|
|
58
|
-
secondary: {
|
|
59
|
-
backgroundColor: theme.colors.secondary,
|
|
60
|
-
},
|
|
61
|
-
outline: {
|
|
62
|
-
backgroundColor: "transparent",
|
|
63
|
-
borderWidth: 1,
|
|
64
|
-
borderColor: theme.colors.border,
|
|
65
|
-
},
|
|
66
|
-
destructive: {
|
|
67
|
-
backgroundColor: theme.colors.destructive,
|
|
68
|
-
},
|
|
69
|
-
text: {
|
|
70
|
-
fontSize: 12,
|
|
71
|
-
fontWeight: "500",
|
|
72
|
-
lineHeight: 18,
|
|
73
|
-
userSelect: "none",
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
74
|
export { Badge };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import {
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ScrollViewProps } from "react-native";
|
|
3
|
+
import { type LooseStyle } from "../lib/styles";
|
|
3
4
|
/**
|
|
4
5
|
* BottomSheet — a sliding bottom sheet with a compound API, backed by the
|
|
5
6
|
* platform's native sheet via `@expo/ui/community/bottom-sheet`:
|
|
@@ -8,49 +9,22 @@ import { ViewProps, StyleProp, ViewStyle, ScrollViewProps } from "react-native";
|
|
|
8
9
|
* - Android: Material3 `ModalBottomSheet`
|
|
9
10
|
* - Web: `vaul` drawer (bundled with @expo/ui)
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* - `.Handle` replaces the native drag indicator with a pressable equivalent.
|
|
19
|
-
* Pressing it walks through the configured snap points, reversing direction
|
|
20
|
-
* at either end. Dragging the sheet continues to use the platform gesture.
|
|
21
|
-
* - `swipeEnabled` / `avoidKeyboard` / `dismissKeyboardOnDrag` are accepted
|
|
22
|
-
* for call-site ergonomics but have no effect — the platform handles them.
|
|
23
|
-
* - Sheet *chrome* (corner radius, system background, safe area) is the
|
|
24
|
-
* platform's on native; theming reaches the content + background color.
|
|
25
|
-
* - On Android only two snap states exist (partial / expanded); extra snap
|
|
26
|
-
* points map to the nearest of those two.
|
|
27
|
-
*
|
|
28
|
-
* Scrollable bodies: the native sheet doesn't bound the hosted RN content to
|
|
29
|
-
* the detent height, so a tall `Body` overflows and clips its footer/tail. When
|
|
30
|
-
* `Body` detects overflow, `Content` caps the column to the detent height so the
|
|
31
|
-
* `ScrollView` actually scrolls to the bottom. Swipe-to-dismiss still works (the
|
|
32
|
-
* native sheet coordinates the pan: a pull at the top of the scroll view
|
|
33
|
-
* dismisses, elsewhere it scrolls). A close affordance is also surfaced for
|
|
34
|
-
* scrollable sheets so there's a one-tap close: the `Header` renders a trailing
|
|
35
|
-
* X, or — if there's no `Header` — `Content` floats one in the top-right corner.
|
|
36
|
-
* No extra props required.
|
|
12
|
+
* react-strict-dom port: the sheet itself stays @expo/ui (vaul on web — not
|
|
13
|
+
* RNW); the compound chrome (Content column / Header / Footer / Handle / Close /
|
|
14
|
+
* Trigger / close button) is html.* so web is RNW-free. The scrollable Body is
|
|
15
|
+
* the one platform split: RSD html.div maps to a NON-scrolling RN View on
|
|
16
|
+
* native, so native keeps RN ScrollView (with its onLayout/onContentSizeChange
|
|
17
|
+
* overflow detection); web uses an html.div with overflow:auto and measures
|
|
18
|
+
* scrollHeight vs clientHeight.
|
|
37
19
|
*
|
|
38
20
|
* @example
|
|
39
21
|
* ```tsx
|
|
40
22
|
* <BottomSheet open={open} onOpenChange={setOpen} snapPoints={["50%"]}>
|
|
41
|
-
* <BottomSheet.Trigger asChild>
|
|
42
|
-
* <Button>Open</Button>
|
|
43
|
-
* </BottomSheet.Trigger>
|
|
23
|
+
* <BottomSheet.Trigger asChild><Button>Open</Button></BottomSheet.Trigger>
|
|
44
24
|
* <BottomSheet.Content>
|
|
45
|
-
* <BottomSheet.Header>
|
|
46
|
-
*
|
|
47
|
-
* </BottomSheet.
|
|
48
|
-
* <BottomSheet.Body>
|
|
49
|
-
* <SansSerifText>Content</SansSerifText>
|
|
50
|
-
* </BottomSheet.Body>
|
|
51
|
-
* <BottomSheet.Footer>
|
|
52
|
-
* <Button>Action</Button>
|
|
53
|
-
* </BottomSheet.Footer>
|
|
25
|
+
* <BottomSheet.Header><SansSerifBoldText>Title</SansSerifBoldText></BottomSheet.Header>
|
|
26
|
+
* <BottomSheet.Body><SansSerifText>Content</SansSerifText></BottomSheet.Body>
|
|
27
|
+
* <BottomSheet.Footer><Button>Action</Button></BottomSheet.Footer>
|
|
54
28
|
* </BottomSheet.Content>
|
|
55
29
|
* </BottomSheet>
|
|
56
30
|
* ```
|
|
@@ -65,19 +39,10 @@ interface BottomSheetContextValue {
|
|
|
65
39
|
setSnapIndex: (index: number) => void;
|
|
66
40
|
cycleSnapPoint: () => void;
|
|
67
41
|
closeOnBackdropPress: boolean;
|
|
68
|
-
/**
|
|
69
|
-
* True when a `Body`'s content overflows its viewport (is genuinely
|
|
70
|
-
* scrollable). Drives two things: `Content` caps the column to the detent
|
|
71
|
-
* height so the `ScrollView` can reach its bottom, and a close affordance is
|
|
72
|
-
* surfaced (a `Header` X, or floating if there's no `Header`) so a long sheet
|
|
73
|
-
* always has a one-tap close. Set by `Body`.
|
|
74
|
-
*/
|
|
75
42
|
scrollable: boolean;
|
|
76
43
|
setScrollable: (scrollable: boolean) => void;
|
|
77
|
-
/** Whether a `Header` is mounted, so `Content` knows to render a fallback close. */
|
|
78
44
|
hasHeader: boolean;
|
|
79
45
|
setHasHeader: (present: boolean) => void;
|
|
80
|
-
/** Whether a `Footer` is mounted, so `Body` can own the bottom safe-area inset when it isn't. */
|
|
81
46
|
hasFooter: boolean;
|
|
82
47
|
setHasFooter: (present: boolean) => void;
|
|
83
48
|
}
|
|
@@ -90,62 +55,54 @@ interface BottomSheetProps {
|
|
|
90
55
|
defaultOpen?: boolean;
|
|
91
56
|
/** Snap point heights (px or percentage strings). Default: ["50%"]. */
|
|
92
57
|
snapPoints?: SnapPoint[];
|
|
93
|
-
/**
|
|
94
|
-
* Whether swiping/pulling down (or tapping the backdrop) dismisses the sheet.
|
|
95
|
-
* Maps to the native sheet's `enablePanDownToClose` (iOS
|
|
96
|
-
* `interactiveDismissDisabled`). Default: true.
|
|
97
|
-
*
|
|
98
|
-
* Works with scrollable bodies — the native sheet coordinates the pan (pull at
|
|
99
|
-
* the top of the scroll view dismisses, elsewhere it scrolls). Set to `false`
|
|
100
|
-
* to disable dismiss entirely; the sheet then surfaces an explicit close
|
|
101
|
-
* affordance automatically (a `Header` X, or a floating X if there's no
|
|
102
|
-
* `Header`). Scrollable sheets also get that close affordance regardless, so
|
|
103
|
-
* there's always a one-tap close.
|
|
104
|
-
*/
|
|
58
|
+
/** Whether swiping down / tapping the backdrop dismisses the sheet. Default: true. */
|
|
105
59
|
closeOnBackdropPress?: boolean;
|
|
106
60
|
children: React.ReactNode;
|
|
107
61
|
}
|
|
108
62
|
interface BottomSheetTriggerProps {
|
|
109
63
|
asChild?: boolean;
|
|
110
64
|
children: React.ReactNode;
|
|
111
|
-
style?:
|
|
65
|
+
style?: LooseStyle;
|
|
112
66
|
}
|
|
113
|
-
interface BottomSheetContentProps
|
|
67
|
+
interface BottomSheetContentProps {
|
|
114
68
|
/** Accepted for call-site ergonomics; ignored (platform owns gestures). */
|
|
115
69
|
swipeEnabled?: boolean;
|
|
116
70
|
/** Accepted for call-site ergonomics; ignored (platform owns keyboard avoidance). */
|
|
117
71
|
avoidKeyboard?: boolean;
|
|
118
72
|
/** Accepted for call-site ergonomics; ignored (platform owns keyboard). */
|
|
119
73
|
dismissKeyboardOnDrag?: boolean;
|
|
120
|
-
style?:
|
|
74
|
+
style?: LooseStyle;
|
|
121
75
|
children: React.ReactNode;
|
|
122
76
|
}
|
|
123
|
-
interface BottomSheetHeaderProps
|
|
77
|
+
interface BottomSheetHeaderProps {
|
|
124
78
|
children: React.ReactNode;
|
|
79
|
+
style?: LooseStyle;
|
|
125
80
|
}
|
|
126
81
|
interface BottomSheetBodyProps extends ScrollViewProps {
|
|
127
82
|
children: React.ReactNode;
|
|
83
|
+
testID?: string;
|
|
128
84
|
}
|
|
129
|
-
interface BottomSheetFooterProps
|
|
85
|
+
interface BottomSheetFooterProps {
|
|
130
86
|
children: React.ReactNode;
|
|
87
|
+
style?: LooseStyle;
|
|
131
88
|
}
|
|
132
89
|
interface BottomSheetHandleProps {
|
|
133
|
-
style?:
|
|
90
|
+
style?: LooseStyle;
|
|
134
91
|
}
|
|
135
92
|
interface BottomSheetCloseProps {
|
|
136
93
|
asChild?: boolean;
|
|
137
94
|
children: React.ReactNode;
|
|
138
|
-
style?:
|
|
95
|
+
style?: LooseStyle;
|
|
139
96
|
}
|
|
140
97
|
declare function useBottomSheetContext(): BottomSheetContextValue;
|
|
141
98
|
declare function BottomSheetRoot({ open: controlledOpen, onOpenChange: controlledOnOpenChange, defaultOpen, snapPoints, closeOnBackdropPress, children, }: BottomSheetProps): React.JSX.Element;
|
|
142
|
-
declare function BottomSheetTrigger({ asChild, children, style
|
|
99
|
+
declare function BottomSheetTrigger({ asChild, children, style }: BottomSheetTriggerProps): React.JSX.Element;
|
|
143
100
|
declare function BottomSheetContent({ swipeEnabled: _swipeEnabled, avoidKeyboard: _avoidKeyboard, dismissKeyboardOnDrag: _dismissKeyboardOnDrag, style: styleOverride, children, }: BottomSheetContentProps): React.JSX.Element;
|
|
144
101
|
declare function BottomSheetHandle({ style }: BottomSheetHandleProps): React.JSX.Element;
|
|
145
|
-
declare function BottomSheetHeader({ children, style
|
|
146
|
-
declare function BottomSheetBody(
|
|
147
|
-
declare function BottomSheetFooter({ children, style
|
|
148
|
-
declare function BottomSheetClose({ asChild, children, style
|
|
102
|
+
declare function BottomSheetHeader({ children, style }: BottomSheetHeaderProps): React.JSX.Element;
|
|
103
|
+
declare function BottomSheetBody(props: BottomSheetBodyProps): React.JSX.Element;
|
|
104
|
+
declare function BottomSheetFooter({ children, style }: BottomSheetFooterProps): React.JSX.Element;
|
|
105
|
+
declare function BottomSheetClose({ asChild, children, style }: BottomSheetCloseProps): React.JSX.Element;
|
|
149
106
|
declare const BottomSheet: typeof BottomSheetRoot & {
|
|
150
107
|
Trigger: typeof BottomSheetTrigger;
|
|
151
108
|
Content: typeof BottomSheetContent;
|