@gryt/ui-native 0.1.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 +86 -0
- package/dist/components/Accordion/Accordion.d.ts +35 -0
- package/dist/components/Accordion/Accordion.d.ts.map +1 -0
- package/dist/components/Accordion/Accordion.js +66 -0
- package/dist/components/Alert/Alert.d.ts +21 -0
- package/dist/components/Alert/Alert.d.ts.map +1 -0
- package/dist/components/Alert/Alert.js +35 -0
- package/dist/components/AlertDialog/AlertDialog.d.ts +38 -0
- package/dist/components/AlertDialog/AlertDialog.d.ts.map +1 -0
- package/dist/components/AlertDialog/AlertDialog.js +15 -0
- package/dist/components/Avatar/Avatar.d.ts +10 -0
- package/dist/components/Avatar/Avatar.d.ts.map +1 -0
- package/dist/components/Avatar/Avatar.js +57 -0
- package/dist/components/Badge/Badge.d.ts +13 -0
- package/dist/components/Badge/Badge.d.ts.map +1 -0
- package/dist/components/Badge/Badge.js +28 -0
- package/dist/components/Button/Button.d.ts +24 -0
- package/dist/components/Button/Button.d.ts.map +1 -0
- package/dist/components/Button/Button.js +61 -0
- package/dist/components/Card/Card.d.ts +19 -0
- package/dist/components/Card/Card.d.ts.map +1 -0
- package/dist/components/Card/Card.js +45 -0
- package/dist/components/Checkbox/Checkbox.d.ts +24 -0
- package/dist/components/Checkbox/Checkbox.d.ts.map +1 -0
- package/dist/components/Checkbox/Checkbox.js +43 -0
- package/dist/components/Chip/Chip.d.ts +17 -0
- package/dist/components/Chip/Chip.d.ts.map +1 -0
- package/dist/components/Chip/Chip.js +38 -0
- package/dist/components/Collapsible/Collapsible.d.ts +31 -0
- package/dist/components/Collapsible/Collapsible.d.ts.map +1 -0
- package/dist/components/Collapsible/Collapsible.js +34 -0
- package/dist/components/Dialog/Dialog.d.ts +67 -0
- package/dist/components/Dialog/Dialog.d.ts.map +1 -0
- package/dist/components/Dialog/Dialog.js +112 -0
- package/dist/components/Divider/Divider.d.ts +16 -0
- package/dist/components/Divider/Divider.d.ts.map +1 -0
- package/dist/components/Divider/Divider.js +21 -0
- package/dist/components/Drawer/Drawer.d.ts +44 -0
- package/dist/components/Drawer/Drawer.d.ts.map +1 -0
- package/dist/components/Drawer/Drawer.js +83 -0
- package/dist/components/Menu/Menu.d.ts +56 -0
- package/dist/components/Menu/Menu.d.ts.map +1 -0
- package/dist/components/Menu/Menu.js +76 -0
- package/dist/components/Meter/Meter.d.ts +21 -0
- package/dist/components/Meter/Meter.d.ts.map +1 -0
- package/dist/components/Meter/Meter.js +32 -0
- package/dist/components/NumberField/NumberField.d.ts +23 -0
- package/dist/components/NumberField/NumberField.d.ts.map +1 -0
- package/dist/components/NumberField/NumberField.js +56 -0
- package/dist/components/OtpField/OtpField.d.ts +24 -0
- package/dist/components/OtpField/OtpField.d.ts.map +1 -0
- package/dist/components/OtpField/OtpField.js +49 -0
- package/dist/components/Popover/Popover.d.ts +48 -0
- package/dist/components/Popover/Popover.d.ts.map +1 -0
- package/dist/components/Popover/Popover.js +54 -0
- package/dist/components/Progress/Progress.d.ts +18 -0
- package/dist/components/Progress/Progress.d.ts.map +1 -0
- package/dist/components/Progress/Progress.js +30 -0
- package/dist/components/Radio/Radio.d.ts +28 -0
- package/dist/components/Radio/Radio.d.ts.map +1 -0
- package/dist/components/Radio/Radio.js +53 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts +22 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts.map +1 -0
- package/dist/components/ScrollArea/ScrollArea.js +17 -0
- package/dist/components/Select/Select.d.ts +34 -0
- package/dist/components/Select/Select.d.ts.map +1 -0
- package/dist/components/Select/Select.js +71 -0
- package/dist/components/Skeleton/Skeleton.d.ts +18 -0
- package/dist/components/Skeleton/Skeleton.d.ts.map +1 -0
- package/dist/components/Skeleton/Skeleton.js +28 -0
- package/dist/components/Slider/Slider.d.ts +29 -0
- package/dist/components/Slider/Slider.d.ts.map +1 -0
- package/dist/components/Slider/Slider.js +94 -0
- package/dist/components/Spinner/Spinner.d.ts +20 -0
- package/dist/components/Spinner/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner/Spinner.js +18 -0
- package/dist/components/Surface/Surface.d.ts +17 -0
- package/dist/components/Surface/Surface.d.ts.map +1 -0
- package/dist/components/Surface/Surface.js +22 -0
- package/dist/components/Switch/Switch.d.ts +25 -0
- package/dist/components/Switch/Switch.d.ts.map +1 -0
- package/dist/components/Switch/Switch.js +65 -0
- package/dist/components/Tabs/Tabs.d.ts +51 -0
- package/dist/components/Tabs/Tabs.d.ts.map +1 -0
- package/dist/components/Tabs/Tabs.js +82 -0
- package/dist/components/TextField/TextField.d.ts +15 -0
- package/dist/components/TextField/TextField.d.ts.map +1 -0
- package/dist/components/TextField/TextField.js +47 -0
- package/dist/components/Toast/Toast.d.ts +31 -0
- package/dist/components/Toast/Toast.d.ts.map +1 -0
- package/dist/components/Toast/Toast.js +86 -0
- package/dist/components/Toggle/Toggle.d.ts +19 -0
- package/dist/components/Toggle/Toggle.d.ts.map +1 -0
- package/dist/components/Toggle/Toggle.js +41 -0
- package/dist/components/Toolbar/Toolbar.d.ts +25 -0
- package/dist/components/Toolbar/Toolbar.d.ts.map +1 -0
- package/dist/components/Toolbar/Toolbar.js +35 -0
- package/dist/components/Tooltip/Tooltip.d.ts +40 -0
- package/dist/components/Tooltip/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip/Tooltip.js +52 -0
- package/dist/hooks/useReducedMotion.d.ts +10 -0
- package/dist/hooks/useReducedMotion.d.ts.map +1 -0
- package/dist/hooks/useReducedMotion.js +26 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/overlay/AnchoredPopup.d.ts +26 -0
- package/dist/overlay/AnchoredPopup.d.ts.map +1 -0
- package/dist/overlay/AnchoredPopup.js +36 -0
- package/dist/overlay/placePopup.d.ts +51 -0
- package/dist/overlay/placePopup.d.ts.map +1 -0
- package/dist/overlay/placePopup.js +63 -0
- package/dist/overlay/useAnchoredPosition.d.ts +18 -0
- package/dist/overlay/useAnchoredPosition.d.ts.map +1 -0
- package/dist/overlay/useAnchoredPosition.js +25 -0
- package/dist/overlay/useOpenState.d.ts +17 -0
- package/dist/overlay/useOpenState.d.ts.map +1 -0
- package/dist/overlay/useOpenState.js +12 -0
- package/dist/theme/ThemeProvider.d.ts +17 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +17 -0
- package/dist/theme/createNativeTheme.d.ts +82 -0
- package/dist/theme/createNativeTheme.d.ts.map +1 -0
- package/dist/theme/createNativeTheme.js +65 -0
- package/dist/theme/index.d.ts +6 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +5 -0
- package/dist/theme/themeContext.d.ts +9 -0
- package/dist/theme/themeContext.d.ts.map +1 -0
- package/dist/theme/themeContext.js +9 -0
- package/dist/theme/tones.d.ts +15 -0
- package/dist/theme/tones.d.ts.map +1 -0
- package/dist/theme/tones.js +11 -0
- package/dist/theme/useTheme.d.ts +8 -0
- package/dist/theme/useTheme.d.ts.map +1 -0
- package/dist/theme/useTheme.js +10 -0
- package/package.json +46 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Text, TextInput, View, } from "react-native";
|
|
4
|
+
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
const SIZES = {
|
|
6
|
+
small: { minHeight: 36, fontSize: 14, paddingH: 12 },
|
|
7
|
+
medium: { minHeight: 40, fontSize: 14, paddingH: 14 },
|
|
8
|
+
};
|
|
9
|
+
export function TextField({ label, helperText, error = false, size = "medium", multiline = false, minRows = 3, style, editable, ...rest }) {
|
|
10
|
+
const theme = useTheme();
|
|
11
|
+
const [focused, setFocused] = useState(false);
|
|
12
|
+
const metrics = SIZES[size];
|
|
13
|
+
const disabled = editable === false;
|
|
14
|
+
// The web shows focus with an outline, which sits outside the box and does not
|
|
15
|
+
// move anything. React Native has no outline, so the border changes colour
|
|
16
|
+
// instead of a second ring appearing, which would shift the layout.
|
|
17
|
+
const borderColor = error
|
|
18
|
+
? theme.color.danger
|
|
19
|
+
: focused
|
|
20
|
+
? theme.color.accent
|
|
21
|
+
: theme.color.border;
|
|
22
|
+
return (_jsxs(View, { style: [{ gap: theme.space(1.5) }, style], children: [label ? (_jsx(Text, { style: { color: theme.color.muted, fontSize: 13, fontWeight: "500" }, children: label })) : null, _jsx(View, { style: {
|
|
23
|
+
borderWidth: 1,
|
|
24
|
+
borderColor,
|
|
25
|
+
borderRadius: theme.radius.md,
|
|
26
|
+
backgroundColor: theme.color.surface,
|
|
27
|
+
opacity: disabled ? 0.5 : 1,
|
|
28
|
+
}, children: _jsx(TextInput, { multiline: multiline, editable: editable, onFocus: (e) => {
|
|
29
|
+
setFocused(true);
|
|
30
|
+
rest.onFocus?.(e);
|
|
31
|
+
}, onBlur: (e) => {
|
|
32
|
+
setFocused(false);
|
|
33
|
+
rest.onBlur?.(e);
|
|
34
|
+
}, placeholderTextColor: theme.color.muted, style: {
|
|
35
|
+
color: theme.color.text,
|
|
36
|
+
fontSize: metrics.fontSize,
|
|
37
|
+
paddingHorizontal: metrics.paddingH,
|
|
38
|
+
minHeight: multiline
|
|
39
|
+
? metrics.minHeight + metrics.fontSize * 1.4 * (minRows - 1)
|
|
40
|
+
: metrics.minHeight,
|
|
41
|
+
textAlignVertical: multiline ? "top" : "center",
|
|
42
|
+
paddingVertical: multiline ? theme.space(2) : 0,
|
|
43
|
+
}, ...rest }) }), helperText ? (_jsx(Text, { style: {
|
|
44
|
+
color: error ? theme.scales.danger[10] : theme.color.muted,
|
|
45
|
+
fontSize: 12,
|
|
46
|
+
}, children: helperText })) : null] }));
|
|
47
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type StyleProp, type ViewStyle } from "react-native";
|
|
3
|
+
export type ToastSeverity = "info" | "success" | "warning" | "error";
|
|
4
|
+
export interface ToastOptions {
|
|
5
|
+
title?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
severity?: ToastSeverity;
|
|
8
|
+
/** Milliseconds. Null keeps it up until it is dismissed. */
|
|
9
|
+
duration?: number | null;
|
|
10
|
+
}
|
|
11
|
+
interface ToastContextValue {
|
|
12
|
+
show: (toast: ToastOptions) => number;
|
|
13
|
+
dismiss: (id: number) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Toasts need somewhere to live, which on the web is a portal at the document
|
|
17
|
+
* root and here is a provider near the top of the tree.
|
|
18
|
+
*
|
|
19
|
+
* They are deliberately not built on `Modal` like the dialogs are. A modal
|
|
20
|
+
* intercepts touches for the whole screen, and a toast that blocked the app
|
|
21
|
+
* until it faded would be worse than no toast.
|
|
22
|
+
*/
|
|
23
|
+
export declare function ToastProvider({ children }: {
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
}): import("react").JSX.Element;
|
|
26
|
+
export declare function useToast(): ToastContextValue;
|
|
27
|
+
export interface ToastProps {
|
|
28
|
+
style?: StyleProp<ViewStyle>;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=Toast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/components/Toast/Toast.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5G,OAAO,EAAmC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAK/F,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAMD,UAAU,iBAAiB;IACzB,IAAI,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,CAAC;IACtC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAID;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,+BAoBnE;AAED,wBAAgB,QAAQ,IAAI,iBAAiB,CAI5C;AAmGD,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Animated, Pressable, Text, View } from "react-native";
|
|
4
|
+
import { useReducedMotion } from "../../hooks/useReducedMotion.js";
|
|
5
|
+
import { useTheme } from "../../theme/index.js";
|
|
6
|
+
const ToastContext = createContext(null);
|
|
7
|
+
/**
|
|
8
|
+
* Toasts need somewhere to live, which on the web is a portal at the document
|
|
9
|
+
* root and here is a provider near the top of the tree.
|
|
10
|
+
*
|
|
11
|
+
* They are deliberately not built on `Modal` like the dialogs are. A modal
|
|
12
|
+
* intercepts touches for the whole screen, and a toast that blocked the app
|
|
13
|
+
* until it faded would be worse than no toast.
|
|
14
|
+
*/
|
|
15
|
+
export function ToastProvider({ children }) {
|
|
16
|
+
const [toasts, setToasts] = useState([]);
|
|
17
|
+
const nextId = useRef(1);
|
|
18
|
+
const dismiss = useCallback((id) => {
|
|
19
|
+
setToasts((current) => current.filter((t) => t.id !== id));
|
|
20
|
+
}, []);
|
|
21
|
+
const show = useCallback((toast) => {
|
|
22
|
+
const id = nextId.current++;
|
|
23
|
+
setToasts((current) => [...current, { ...toast, id }]);
|
|
24
|
+
return id;
|
|
25
|
+
}, []);
|
|
26
|
+
return (_jsxs(ToastContext.Provider, { value: { show, dismiss }, children: [children, _jsx(Viewport, { toasts: toasts, onDismiss: dismiss })] }));
|
|
27
|
+
}
|
|
28
|
+
export function useToast() {
|
|
29
|
+
const value = useContext(ToastContext);
|
|
30
|
+
if (!value)
|
|
31
|
+
throw new Error("useToast must be used inside a <ToastProvider>.");
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
const RAMP = {
|
|
35
|
+
info: "accent",
|
|
36
|
+
success: "success",
|
|
37
|
+
warning: "warning",
|
|
38
|
+
error: "danger",
|
|
39
|
+
};
|
|
40
|
+
function Viewport({ toasts, onDismiss, }) {
|
|
41
|
+
const theme = useTheme();
|
|
42
|
+
if (toasts.length === 0)
|
|
43
|
+
return null;
|
|
44
|
+
return (_jsx(View
|
|
45
|
+
// Only the toasts take touches; the gaps between them do not.
|
|
46
|
+
, {
|
|
47
|
+
// Only the toasts take touches; the gaps between them do not.
|
|
48
|
+
pointerEvents: "box-none", style: {
|
|
49
|
+
position: "absolute",
|
|
50
|
+
left: 0,
|
|
51
|
+
right: 0,
|
|
52
|
+
bottom: theme.space(6),
|
|
53
|
+
paddingHorizontal: theme.space(4),
|
|
54
|
+
gap: theme.space(2),
|
|
55
|
+
}, children: toasts.map((toast) => (_jsx(ToastItem, { toast: toast, onDismiss: onDismiss }, toast.id))) }));
|
|
56
|
+
}
|
|
57
|
+
function ToastItem({ toast, onDismiss, }) {
|
|
58
|
+
const theme = useTheme();
|
|
59
|
+
const reducedMotion = useReducedMotion();
|
|
60
|
+
const [opacity] = useState(() => new Animated.Value(reducedMotion ? 1 : 0));
|
|
61
|
+
const ramp = theme.scales[RAMP[toast.severity ?? "info"]];
|
|
62
|
+
const duration = toast.duration === undefined ? 4000 : toast.duration;
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!reducedMotion) {
|
|
65
|
+
Animated.timing(opacity, {
|
|
66
|
+
toValue: 1,
|
|
67
|
+
duration: 150,
|
|
68
|
+
useNativeDriver: true,
|
|
69
|
+
}).start();
|
|
70
|
+
}
|
|
71
|
+
if (duration === null)
|
|
72
|
+
return;
|
|
73
|
+
const timer = setTimeout(() => onDismiss(toast.id), duration);
|
|
74
|
+
return () => clearTimeout(timer);
|
|
75
|
+
}, [duration, onDismiss, opacity, reducedMotion, toast.id]);
|
|
76
|
+
return (_jsx(Animated.View, { style: { opacity }, children: _jsxs(Pressable, { accessibilityRole: "alert", accessibilityLiveRegion: toast.severity === "error" || toast.severity === "warning" ? "assertive" : "polite", onPress: () => onDismiss(toast.id), style: {
|
|
77
|
+
backgroundColor: theme.color.surfaceRaised,
|
|
78
|
+
borderRadius: theme.radius.md,
|
|
79
|
+
borderWidth: 1,
|
|
80
|
+
borderLeftWidth: 3,
|
|
81
|
+
borderColor: theme.color.border,
|
|
82
|
+
borderLeftColor: ramp[8],
|
|
83
|
+
padding: theme.space(3),
|
|
84
|
+
gap: theme.space(0.5),
|
|
85
|
+
}, children: [toast.title ? (_jsx(Text, { style: { color: theme.color.text, fontSize: 14, fontWeight: "600" }, children: toast.title })) : null, toast.description ? (_jsx(Text, { style: { color: theme.color.muted, fontSize: 13, lineHeight: 18 }, children: toast.description })) : null] }) }));
|
|
86
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type StyleProp, type ViewStyle } from "react-native";
|
|
3
|
+
import { type ComponentTone } from "../../theme/index.js";
|
|
4
|
+
export type ToggleTone = Extract<ComponentTone, "primary" | "secondary" | "neutral" | "danger">;
|
|
5
|
+
export type ToggleSize = "xsmall" | "small" | "medium" | "large";
|
|
6
|
+
export interface ToggleProps {
|
|
7
|
+
pressed?: boolean;
|
|
8
|
+
defaultPressed?: boolean;
|
|
9
|
+
onPressedChange?: (pressed: boolean) => void;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
tone?: ToggleTone;
|
|
12
|
+
size?: ToggleSize;
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
style?: StyleProp<ViewStyle>;
|
|
15
|
+
accessibilityLabel?: string;
|
|
16
|
+
}
|
|
17
|
+
/** A button that stays down. Mute, deafen, and the rest of the call controls. */
|
|
18
|
+
export declare function Toggle({ pressed: controlled, defaultPressed, onPressedChange, disabled, tone, size, children, style, accessibilityLabel, }: ToggleProps): import("react").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=Toggle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toggle.d.ts","sourceRoot":"","sources":["../../../src/components/Toggle/Toggle.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAmB,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE/E,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAErE,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC,CAAC;AAChG,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AASjE,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,iFAAiF;AACjF,wBAAgB,MAAM,CAAC,EACrB,OAAO,EAAE,UAAU,EACnB,cAAsB,EACtB,eAAe,EACf,QAAQ,EACR,IAAgB,EAChB,IAAe,EACf,QAAQ,EACR,KAAK,EACL,kBAAkB,GACnB,EAAE,WAAW,+BAgDb"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Pressable, Text } from "react-native";
|
|
4
|
+
import { toneRamp, useTheme } from "../../theme/index.js";
|
|
5
|
+
const SIZES = {
|
|
6
|
+
xsmall: { minHeight: 32, paddingH: 10, fontSize: 12 },
|
|
7
|
+
small: { minHeight: 36, paddingH: 12, fontSize: 14 },
|
|
8
|
+
medium: { minHeight: 40, paddingH: 14, fontSize: 14 },
|
|
9
|
+
large: { minHeight: 48, paddingH: 18, fontSize: 16 },
|
|
10
|
+
};
|
|
11
|
+
/** A button that stays down. Mute, deafen, and the rest of the call controls. */
|
|
12
|
+
export function Toggle({ pressed: controlled, defaultPressed = false, onPressedChange, disabled, tone = "primary", size = "medium", children, style, accessibilityLabel, }) {
|
|
13
|
+
const theme = useTheme();
|
|
14
|
+
const [uncontrolled, setUncontrolled] = useState(defaultPressed);
|
|
15
|
+
const on = controlled ?? uncontrolled;
|
|
16
|
+
const metrics = SIZES[size];
|
|
17
|
+
const ramp = toneRamp(theme, tone);
|
|
18
|
+
return (_jsx(Pressable, { accessibilityRole: "button", accessibilityState: { selected: on, disabled: !!disabled }, accessibilityLabel: accessibilityLabel, disabled: disabled, onPress: () => {
|
|
19
|
+
const next = !on;
|
|
20
|
+
if (controlled === undefined)
|
|
21
|
+
setUncontrolled(next);
|
|
22
|
+
onPressedChange?.(next);
|
|
23
|
+
}, style: [
|
|
24
|
+
{
|
|
25
|
+
minHeight: metrics.minHeight,
|
|
26
|
+
paddingHorizontal: metrics.paddingH,
|
|
27
|
+
flexDirection: "row",
|
|
28
|
+
alignItems: "center",
|
|
29
|
+
justifyContent: "center",
|
|
30
|
+
gap: theme.space(2),
|
|
31
|
+
borderRadius: theme.radius.full,
|
|
32
|
+
backgroundColor: on ? ramp[2] : "transparent",
|
|
33
|
+
opacity: disabled ? 0.5 : 1,
|
|
34
|
+
},
|
|
35
|
+
style,
|
|
36
|
+
], children: typeof children === "string" ? (_jsx(Text, { style: {
|
|
37
|
+
color: on ? ramp[10] : theme.color.muted,
|
|
38
|
+
fontSize: metrics.fontSize,
|
|
39
|
+
fontWeight: "600",
|
|
40
|
+
}, children: children })) : (children) }));
|
|
41
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { type StyleProp, type ViewStyle } from "react-native";
|
|
3
|
+
export interface ToolbarProps {
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
orientation?: "horizontal" | "vertical";
|
|
6
|
+
style?: StyleProp<ViewStyle>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A row of controls that reads as one thing.
|
|
10
|
+
*
|
|
11
|
+
* The web's Toolbar manages roving focus, so arrow keys move between the
|
|
12
|
+
* buttons and the group takes one tab stop. There is no roving focus to manage
|
|
13
|
+
* here, so what is left is the grouping: the accessibility role, and the
|
|
14
|
+
* spacing.
|
|
15
|
+
*
|
|
16
|
+
* Kept rather than dropped because the role is what tells a screen reader these
|
|
17
|
+
* controls belong together, which is most of what the web version was for.
|
|
18
|
+
*/
|
|
19
|
+
export declare function Toolbar({ children, orientation, style }: ToolbarProps): import("react").JSX.Element;
|
|
20
|
+
export interface ToolbarSeparatorProps {
|
|
21
|
+
orientation?: "horizontal" | "vertical";
|
|
22
|
+
style?: StyleProp<ViewStyle>;
|
|
23
|
+
}
|
|
24
|
+
export declare function ToolbarSeparator({ orientation, style, }: ToolbarSeparatorProps): import("react").JSX.Element;
|
|
25
|
+
//# sourceMappingURL=Toolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../../src/components/Toolbar/Toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAQ,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAIpE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,WAA0B,EAAE,KAAK,EAAE,EAAE,YAAY,+BAiBpF;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,WAAwB,EACxB,KAAK,GACN,EAAE,qBAAqB,+BAavB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { useTheme } from "../../theme/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* A row of controls that reads as one thing.
|
|
6
|
+
*
|
|
7
|
+
* The web's Toolbar manages roving focus, so arrow keys move between the
|
|
8
|
+
* buttons and the group takes one tab stop. There is no roving focus to manage
|
|
9
|
+
* here, so what is left is the grouping: the accessibility role, and the
|
|
10
|
+
* spacing.
|
|
11
|
+
*
|
|
12
|
+
* Kept rather than dropped because the role is what tells a screen reader these
|
|
13
|
+
* controls belong together, which is most of what the web version was for.
|
|
14
|
+
*/
|
|
15
|
+
export function Toolbar({ children, orientation = "horizontal", style }) {
|
|
16
|
+
const theme = useTheme();
|
|
17
|
+
return (_jsx(View, { accessibilityRole: "toolbar", style: [
|
|
18
|
+
{
|
|
19
|
+
flexDirection: orientation === "horizontal" ? "row" : "column",
|
|
20
|
+
alignItems: "center",
|
|
21
|
+
gap: theme.space(1),
|
|
22
|
+
},
|
|
23
|
+
style,
|
|
24
|
+
], children: children }));
|
|
25
|
+
}
|
|
26
|
+
export function ToolbarSeparator({ orientation = "vertical", style, }) {
|
|
27
|
+
const theme = useTheme();
|
|
28
|
+
return (_jsx(View, { style: [
|
|
29
|
+
orientation === "vertical"
|
|
30
|
+
? { width: 1, alignSelf: "stretch", marginVertical: theme.space(1.5) }
|
|
31
|
+
: { height: 1, alignSelf: "stretch", marginHorizontal: theme.space(1.5) },
|
|
32
|
+
{ backgroundColor: theme.color.border },
|
|
33
|
+
style,
|
|
34
|
+
] }));
|
|
35
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type StyleProp, type ViewStyle } from "react-native";
|
|
3
|
+
import type { Align, Side } from "../../overlay/placePopup.js";
|
|
4
|
+
import { type OpenStateProps } from "../../overlay/useOpenState.js";
|
|
5
|
+
export interface TooltipRootProps extends OpenStateProps {
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
declare function Root({ children, ...openProps }: TooltipRootProps): import("react").JSX.Element;
|
|
9
|
+
export interface TooltipTriggerProps {
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
/** Still fires on a normal tap, so the tooltip does not eat the action. */
|
|
12
|
+
onPress?: () => void;
|
|
13
|
+
style?: StyleProp<ViewStyle>;
|
|
14
|
+
}
|
|
15
|
+
declare function Trigger({ children, onPress, style }: TooltipTriggerProps): import("react").JSX.Element;
|
|
16
|
+
declare function Portal({ children }: {
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
export interface TooltipPopupProps {
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
side?: Side;
|
|
22
|
+
align?: Align;
|
|
23
|
+
sideOffset?: number;
|
|
24
|
+
style?: StyleProp<ViewStyle>;
|
|
25
|
+
}
|
|
26
|
+
declare function Popup({ children, style, ...options }: TooltipPopupProps): import("react").JSX.Element;
|
|
27
|
+
/** The web's Provider shares a delay timer between tooltips. There is no delay here. */
|
|
28
|
+
declare function Provider({ children }: {
|
|
29
|
+
children?: ReactNode;
|
|
30
|
+
}): import("react").JSX.Element;
|
|
31
|
+
export declare const Tooltip: {
|
|
32
|
+
Root: typeof Root;
|
|
33
|
+
Trigger: typeof Trigger;
|
|
34
|
+
Portal: typeof Portal;
|
|
35
|
+
Popup: typeof Popup;
|
|
36
|
+
Provider: typeof Provider;
|
|
37
|
+
};
|
|
38
|
+
export declare const TooltipProvider: typeof Provider;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=Tooltip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvF,OAAO,EAAyB,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGrF,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAgC/E,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,iBAAS,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAS,EAAE,EAAE,gBAAgB,+BAQzD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAED,iBAAS,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,mBAAmB,+BAoBjE;AAED,iBAAS,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,+BAErD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAED,iBAAS,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,EAAE,iBAAiB,+BA8BhE;AAED,wFAAwF;AACxF,iBAAS,QAAQ,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,+BAEvD;AAED,eAAO,MAAM,OAAO;;;;;;CAA6C,CAAC;AAClE,eAAO,MAAM,eAAe,iBAAW,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useContext, useRef } from "react";
|
|
3
|
+
import { Pressable, Text } from "react-native";
|
|
4
|
+
import { AnchoredPopup } from "../../overlay/AnchoredPopup.js";
|
|
5
|
+
import { useAnchorMeasure } from "../../overlay/useAnchoredPosition.js";
|
|
6
|
+
import { useOpenState } from "../../overlay/useOpenState.js";
|
|
7
|
+
import { useTheme } from "../../theme/index.js";
|
|
8
|
+
const TooltipContext = createContext(null);
|
|
9
|
+
function useTooltip(part) {
|
|
10
|
+
const value = useContext(TooltipContext);
|
|
11
|
+
if (!value)
|
|
12
|
+
throw new Error(`Tooltip.${part} must be rendered inside Tooltip.Root.`);
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
function Root({ children, ...openProps }) {
|
|
16
|
+
const { open, setOpen } = useOpenState(openProps);
|
|
17
|
+
const { anchor, measure } = useAnchorMeasure();
|
|
18
|
+
return (_jsx(TooltipContext.Provider, { value: { open, setOpen, anchor, measure }, children: children }));
|
|
19
|
+
}
|
|
20
|
+
function Trigger({ children, onPress, style }) {
|
|
21
|
+
const { setOpen, measure } = useTooltip("Trigger");
|
|
22
|
+
const ref = useRef(null);
|
|
23
|
+
const show = useCallback(() => {
|
|
24
|
+
measure(ref.current);
|
|
25
|
+
setOpen(true);
|
|
26
|
+
}, [measure, setOpen]);
|
|
27
|
+
return (_jsx(Pressable, { ref: ref, onPress: onPress, onLongPress: show, onPressOut: () => setOpen(false), style: style, children: children }));
|
|
28
|
+
}
|
|
29
|
+
function Portal({ children }) {
|
|
30
|
+
return _jsx(_Fragment, { children: children });
|
|
31
|
+
}
|
|
32
|
+
function Popup({ children, style, ...options }) {
|
|
33
|
+
const { open, setOpen, anchor } = useTooltip("Popup");
|
|
34
|
+
const theme = useTheme();
|
|
35
|
+
return (_jsx(AnchoredPopup, { open: open, anchor: anchor, onDismiss: () => setOpen(false), side: "top",
|
|
36
|
+
// A tooltip is never the thing you are trying to touch.
|
|
37
|
+
pointerEvents: "none", style: [
|
|
38
|
+
{
|
|
39
|
+
paddingHorizontal: theme.space(2.5),
|
|
40
|
+
paddingVertical: theme.space(1.5),
|
|
41
|
+
maxWidth: 260,
|
|
42
|
+
backgroundColor: theme.scales.neutral[4],
|
|
43
|
+
},
|
|
44
|
+
style,
|
|
45
|
+
], ...options, children: typeof children === "string" ? (_jsx(Text, { style: { color: theme.color.text, fontSize: 12 }, children: children })) : (children) }));
|
|
46
|
+
}
|
|
47
|
+
/** The web's Provider shares a delay timer between tooltips. There is no delay here. */
|
|
48
|
+
function Provider({ children }) {
|
|
49
|
+
return _jsx(_Fragment, { children: children });
|
|
50
|
+
}
|
|
51
|
+
export const Tooltip = { Root, Trigger, Portal, Popup, Provider };
|
|
52
|
+
export const TooltipProvider = Provider;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The web gets this from `motion-safe:`, which Tailwind compiles to a
|
|
3
|
+
* `prefers-reduced-motion` media query. React Native has the same setting and no
|
|
4
|
+
* way to express it in a style, so it has to be read and subscribed to.
|
|
5
|
+
*
|
|
6
|
+
* Assumes motion is allowed until told otherwise, which matches the web: the
|
|
7
|
+
* media query only matches once the OS says to reduce.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useReducedMotion(): boolean;
|
|
10
|
+
//# sourceMappingURL=useReducedMotion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useReducedMotion.d.ts","sourceRoot":"","sources":["../../src/hooks/useReducedMotion.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAmB1C"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { AccessibilityInfo } from "react-native";
|
|
3
|
+
/**
|
|
4
|
+
* The web gets this from `motion-safe:`, which Tailwind compiles to a
|
|
5
|
+
* `prefers-reduced-motion` media query. React Native has the same setting and no
|
|
6
|
+
* way to express it in a style, so it has to be read and subscribed to.
|
|
7
|
+
*
|
|
8
|
+
* Assumes motion is allowed until told otherwise, which matches the web: the
|
|
9
|
+
* media query only matches once the OS says to reduce.
|
|
10
|
+
*/
|
|
11
|
+
export function useReducedMotion() {
|
|
12
|
+
const [reduced, setReduced] = useState(false);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
let cancelled = false;
|
|
15
|
+
AccessibilityInfo.isReduceMotionEnabled().then((value) => {
|
|
16
|
+
if (!cancelled)
|
|
17
|
+
setReduced(value);
|
|
18
|
+
});
|
|
19
|
+
const sub = AccessibilityInfo.addEventListener("reduceMotionChanged", setReduced);
|
|
20
|
+
return () => {
|
|
21
|
+
cancelled = true;
|
|
22
|
+
sub.remove();
|
|
23
|
+
};
|
|
24
|
+
}, []);
|
|
25
|
+
return reduced;
|
|
26
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export { createNativeTheme, darkTheme, GrytThemeProvider, lightTheme, useTheme, type GrytAppearance, type GrytThemeProviderProps, type NativeTheme, type NativeThemeOptions, type Ramp, toneRamp, type ComponentTone, } from "./theme/index.js";
|
|
2
|
+
export { AlertDialog, type AlertDialogPopupProps, type AlertDialogRootProps, } from "./components/AlertDialog/AlertDialog.js";
|
|
3
|
+
export { Alert, type AlertProps, type AlertSeverity } from "./components/Alert/Alert.js";
|
|
4
|
+
export { Avatar, type AvatarProps, type AvatarSize } from "./components/Avatar/Avatar.js";
|
|
5
|
+
export { Badge, type BadgeProps, type BadgeTone } from "./components/Badge/Badge.js";
|
|
6
|
+
export { Button, type ButtonProps, type ButtonSize, type ButtonTone } from "./components/Button/Button.js";
|
|
7
|
+
export { Card, CardActions, CardContent, CardHeader, type CardHeaderProps, type CardProps, } from "./components/Card/Card.js";
|
|
8
|
+
export { Checkbox, type CheckboxProps, type CheckboxTone } from "./components/Checkbox/Checkbox.js";
|
|
9
|
+
export { Chip, type ChipProps, type ChipTone, type ChipVariant } from "./components/Chip/Chip.js";
|
|
10
|
+
export { Dialog, type DialogPopupProps, type DialogRootProps, type DialogTriggerProps, } from "./components/Dialog/Dialog.js";
|
|
11
|
+
export { Collapsible, type CollapsibleRootProps, } from "./components/Collapsible/Collapsible.js";
|
|
12
|
+
export { Divider, type DividerProps } from "./components/Divider/Divider.js";
|
|
13
|
+
export { Menu, type MenuItemProps, type MenuPopupProps, type MenuRootProps } from "./components/Menu/Menu.js";
|
|
14
|
+
export { Meter, type MeterProps } from "./components/Meter/Meter.js";
|
|
15
|
+
export { Popover, type PopoverPopupProps, type PopoverRootProps } from "./components/Popover/Popover.js";
|
|
16
|
+
export { Progress, type ProgressProps } from "./components/Progress/Progress.js";
|
|
17
|
+
export { Radio, RadioGroup, type RadioGroupProps, type RadioProps, type RadioTone } from "./components/Radio/Radio.js";
|
|
18
|
+
export { Select, type SelectOption, type SelectProps, type SelectSize, } from "./components/Select/Select.js";
|
|
19
|
+
export { Slider, type SliderProps, type SliderTone, } from "./components/Slider/Slider.js";
|
|
20
|
+
export { Skeleton, type SkeletonProps } from "./components/Skeleton/Skeleton.js";
|
|
21
|
+
export { Spinner, type SpinnerProps } from "./components/Spinner/Spinner.js";
|
|
22
|
+
export { Surface, type SurfaceLevel, type SurfaceProps } from "./components/Surface/Surface.js";
|
|
23
|
+
export { Switch, type SwitchProps, type SwitchTone } from "./components/Switch/Switch.js";
|
|
24
|
+
export { Tab, Tabs, type TabProps, type TabsListProps, type TabsPanelProps, type TabsProps, } from "./components/Tabs/Tabs.js";
|
|
25
|
+
export { TextField, type TextFieldProps, type TextFieldSize } from "./components/TextField/TextField.js";
|
|
26
|
+
export { Toggle, type ToggleProps, type ToggleSize, type ToggleTone } from "./components/Toggle/Toggle.js";
|
|
27
|
+
export { Tooltip, TooltipProvider, type TooltipPopupProps, type TooltipRootProps, type TooltipTriggerProps, } from "./components/Tooltip/Tooltip.js";
|
|
28
|
+
export { Accordion, type AccordionItemProps, type AccordionRootProps, } from "./components/Accordion/Accordion.js";
|
|
29
|
+
export { Drawer, type DrawerPopupProps, type DrawerRootProps, type DrawerSide, } from "./components/Drawer/Drawer.js";
|
|
30
|
+
export { NumberField, type NumberFieldProps } from "./components/NumberField/NumberField.js";
|
|
31
|
+
export { OtpField, type OtpFieldProps } from "./components/OtpField/OtpField.js";
|
|
32
|
+
export { ScrollArea, type ScrollAreaProps } from "./components/ScrollArea/ScrollArea.js";
|
|
33
|
+
export { ToastProvider, useToast, type ToastOptions, type ToastSeverity, } from "./components/Toast/Toast.js";
|
|
34
|
+
export { Toolbar, ToolbarSeparator, type ToolbarProps, type ToolbarSeparatorProps, } from "./components/Toolbar/Toolbar.js";
|
|
35
|
+
export { AnchoredPopup, type AnchoredPopupProps } from "./overlay/AnchoredPopup.js";
|
|
36
|
+
export { placePopup, type Align, type AnchorOptions, type AnchorRect, type PopupPlacement, type Side, } from "./overlay/placePopup.js";
|
|
37
|
+
export { useOpenState, type OpenStateProps } from "./overlay/useOpenState.js";
|
|
38
|
+
export { useReducedMotion } from "./hooks/useReducedMotion.js";
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export { createNativeTheme, darkTheme, GrytThemeProvider, lightTheme, useTheme, toneRamp, } from "./theme/index.js";
|
|
2
|
+
export { AlertDialog, } from "./components/AlertDialog/AlertDialog.js";
|
|
3
|
+
export { Alert } from "./components/Alert/Alert.js";
|
|
4
|
+
export { Avatar } from "./components/Avatar/Avatar.js";
|
|
5
|
+
export { Badge } from "./components/Badge/Badge.js";
|
|
6
|
+
export { Button } from "./components/Button/Button.js";
|
|
7
|
+
export { Card, CardActions, CardContent, CardHeader, } from "./components/Card/Card.js";
|
|
8
|
+
export { Checkbox } from "./components/Checkbox/Checkbox.js";
|
|
9
|
+
export { Chip } from "./components/Chip/Chip.js";
|
|
10
|
+
export { Dialog, } from "./components/Dialog/Dialog.js";
|
|
11
|
+
export { Collapsible, } from "./components/Collapsible/Collapsible.js";
|
|
12
|
+
export { Divider } from "./components/Divider/Divider.js";
|
|
13
|
+
export { Menu } from "./components/Menu/Menu.js";
|
|
14
|
+
export { Meter } from "./components/Meter/Meter.js";
|
|
15
|
+
export { Popover } from "./components/Popover/Popover.js";
|
|
16
|
+
export { Progress } from "./components/Progress/Progress.js";
|
|
17
|
+
export { Radio, RadioGroup } from "./components/Radio/Radio.js";
|
|
18
|
+
export { Select, } from "./components/Select/Select.js";
|
|
19
|
+
export { Slider, } from "./components/Slider/Slider.js";
|
|
20
|
+
export { Skeleton } from "./components/Skeleton/Skeleton.js";
|
|
21
|
+
export { Spinner } from "./components/Spinner/Spinner.js";
|
|
22
|
+
export { Surface } from "./components/Surface/Surface.js";
|
|
23
|
+
export { Switch } from "./components/Switch/Switch.js";
|
|
24
|
+
export { Tab, Tabs, } from "./components/Tabs/Tabs.js";
|
|
25
|
+
export { TextField } from "./components/TextField/TextField.js";
|
|
26
|
+
export { Toggle } from "./components/Toggle/Toggle.js";
|
|
27
|
+
export { Tooltip, TooltipProvider, } from "./components/Tooltip/Tooltip.js";
|
|
28
|
+
export { Accordion, } from "./components/Accordion/Accordion.js";
|
|
29
|
+
export { Drawer, } from "./components/Drawer/Drawer.js";
|
|
30
|
+
export { NumberField } from "./components/NumberField/NumberField.js";
|
|
31
|
+
export { OtpField } from "./components/OtpField/OtpField.js";
|
|
32
|
+
export { ScrollArea } from "./components/ScrollArea/ScrollArea.js";
|
|
33
|
+
export { ToastProvider, useToast, } from "./components/Toast/Toast.js";
|
|
34
|
+
export { Toolbar, ToolbarSeparator, } from "./components/Toolbar/Toolbar.js";
|
|
35
|
+
export { AnchoredPopup } from "./overlay/AnchoredPopup.js";
|
|
36
|
+
export { placePopup, } from "./overlay/placePopup.js";
|
|
37
|
+
export { useOpenState } from "./overlay/useOpenState.js";
|
|
38
|
+
export { useReducedMotion } from "./hooks/useReducedMotion.js";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type StyleProp, type ViewStyle } from "react-native";
|
|
3
|
+
import { type AnchorOptions, type AnchorRect } from "./placePopup.js";
|
|
4
|
+
/**
|
|
5
|
+
* The shared body of every popup that hangs off a trigger.
|
|
6
|
+
*
|
|
7
|
+
* Menu, Popover, Tooltip and Select all need the same three things: render above
|
|
8
|
+
* everything, close on an outside press, and sit next to a measured anchor
|
|
9
|
+
* without falling off the screen. Base UI's Positioner does this for all of them
|
|
10
|
+
* on the web, so there is one of them here too.
|
|
11
|
+
*
|
|
12
|
+
* It renders once invisibly to find out how big it is, then again in place. That
|
|
13
|
+
* is the cost of having no layout engine to ask: the popup's size depends on its
|
|
14
|
+
* content, and the position depends on the size.
|
|
15
|
+
*/
|
|
16
|
+
export interface AnchoredPopupProps extends AnchorOptions {
|
|
17
|
+
open: boolean;
|
|
18
|
+
anchor: AnchorRect | null;
|
|
19
|
+
onDismiss: () => void;
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
style?: StyleProp<ViewStyle>;
|
|
22
|
+
/** Tooltips do not take presses; menus do. */
|
|
23
|
+
pointerEvents?: "auto" | "none";
|
|
24
|
+
}
|
|
25
|
+
export declare function AnchoredPopup({ open, anchor, onDismiss, children, style, pointerEvents, ...options }: AnchoredPopupProps): import("react").JSX.Element | null;
|
|
26
|
+
//# sourceMappingURL=AnchoredPopup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnchoredPopup.d.ts","sourceRoot":"","sources":["../../src/overlay/AnchoredPopup.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAkD,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9G,OAAO,EAAc,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/E;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,8CAA8C;IAC9C,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACjC;AAED,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,MAAM,EACN,SAAS,EACT,QAAQ,EACR,KAAK,EACL,aAAsB,EACtB,GAAG,OAAO,EACX,EAAE,kBAAkB,sCA6CpB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Modal, Pressable, View } from "react-native";
|
|
4
|
+
import { placePopup } from "./placePopup.js";
|
|
5
|
+
import { screenSize } from "./useAnchoredPosition.js";
|
|
6
|
+
import { useTheme } from "../theme/index.js";
|
|
7
|
+
export function AnchoredPopup({ open, anchor, onDismiss, children, style, pointerEvents = "auto", ...options }) {
|
|
8
|
+
const theme = useTheme();
|
|
9
|
+
const [size, setSize] = useState(null);
|
|
10
|
+
const onLayout = (e) => {
|
|
11
|
+
const { width, height } = e.nativeEvent.layout;
|
|
12
|
+
if (!size || size.width !== width || size.height !== height) {
|
|
13
|
+
setSize({ width, height });
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
if (!open || !anchor)
|
|
17
|
+
return null;
|
|
18
|
+
const placement = size
|
|
19
|
+
? placePopup(anchor, size, screenSize(), options)
|
|
20
|
+
: null;
|
|
21
|
+
return (_jsx(Modal, { visible: true, transparent: true, animationType: "none", onRequestClose: onDismiss, children: _jsx(Pressable, { style: { flex: 1 }, onPress: onDismiss, children: _jsx(View, { onLayout: onLayout, pointerEvents: pointerEvents, style: [
|
|
22
|
+
{
|
|
23
|
+
position: "absolute",
|
|
24
|
+
// Off-screen for the measuring pass, so nothing flashes in the
|
|
25
|
+
// wrong place before the position is known.
|
|
26
|
+
top: placement?.top ?? -9999,
|
|
27
|
+
left: placement?.left ?? -9999,
|
|
28
|
+
maxHeight: placement?.maxHeight,
|
|
29
|
+
backgroundColor: theme.color.surfaceRaised,
|
|
30
|
+
borderRadius: theme.radius.md,
|
|
31
|
+
borderWidth: 1,
|
|
32
|
+
borderColor: theme.color.border,
|
|
33
|
+
},
|
|
34
|
+
style,
|
|
35
|
+
], children: _jsx(Pressable, { onPress: () => { }, children: children }) }) }) }));
|
|
36
|
+
}
|