@mrmeg/expo-ui 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.
Files changed (112) hide show
  1. package/README.md +96 -0
  2. package/dist/components/Accordion.d.ts +54 -0
  3. package/dist/components/Accordion.js +149 -0
  4. package/dist/components/Alert.d.ts +30 -0
  5. package/dist/components/Alert.js +25 -0
  6. package/dist/components/AnimatedView.d.ts +55 -0
  7. package/dist/components/AnimatedView.js +39 -0
  8. package/dist/components/Badge.d.ts +23 -0
  9. package/dist/components/Badge.js +74 -0
  10. package/dist/components/BottomSheet.d.ts +74 -0
  11. package/dist/components/BottomSheet.js +513 -0
  12. package/dist/components/Button.d.ts +129 -0
  13. package/dist/components/Button.js +216 -0
  14. package/dist/components/Card.d.ts +42 -0
  15. package/dist/components/Card.js +126 -0
  16. package/dist/components/Checkbox.d.ts +39 -0
  17. package/dist/components/Checkbox.js +96 -0
  18. package/dist/components/Collapsible.d.ts +67 -0
  19. package/dist/components/Collapsible.js +38 -0
  20. package/dist/components/Dialog.d.ts +140 -0
  21. package/dist/components/Dialog.js +167 -0
  22. package/dist/components/DismissKeyboard.d.ts +15 -0
  23. package/dist/components/DismissKeyboard.js +13 -0
  24. package/dist/components/Drawer.d.ts +74 -0
  25. package/dist/components/Drawer.js +423 -0
  26. package/dist/components/DropdownMenu.d.ts +120 -0
  27. package/dist/components/DropdownMenu.js +211 -0
  28. package/dist/components/EmptyState.d.ts +42 -0
  29. package/dist/components/EmptyState.js +58 -0
  30. package/dist/components/ErrorBoundary.d.ts +53 -0
  31. package/dist/components/ErrorBoundary.js +75 -0
  32. package/dist/components/Icon.d.ts +46 -0
  33. package/dist/components/Icon.js +40 -0
  34. package/dist/components/InputOTP.d.ts +72 -0
  35. package/dist/components/InputOTP.js +155 -0
  36. package/dist/components/Label.d.ts +61 -0
  37. package/dist/components/Label.js +72 -0
  38. package/dist/components/MaxWidthContainer.d.ts +58 -0
  39. package/dist/components/MaxWidthContainer.js +64 -0
  40. package/dist/components/Notification.d.ts +26 -0
  41. package/dist/components/Notification.js +230 -0
  42. package/dist/components/Popover.d.ts +79 -0
  43. package/dist/components/Popover.js +91 -0
  44. package/dist/components/Progress.d.ts +28 -0
  45. package/dist/components/Progress.js +107 -0
  46. package/dist/components/RadioGroup.d.ts +65 -0
  47. package/dist/components/RadioGroup.js +142 -0
  48. package/dist/components/Select.d.ts +88 -0
  49. package/dist/components/Select.js +172 -0
  50. package/dist/components/Separator.d.ts +83 -0
  51. package/dist/components/Separator.js +85 -0
  52. package/dist/components/Skeleton.d.ts +68 -0
  53. package/dist/components/Skeleton.js +99 -0
  54. package/dist/components/Slider.d.ts +24 -0
  55. package/dist/components/Slider.js +162 -0
  56. package/dist/components/StatusBar.d.ts +1 -0
  57. package/dist/components/StatusBar.js +19 -0
  58. package/dist/components/StyledText.d.ts +161 -0
  59. package/dist/components/StyledText.js +193 -0
  60. package/dist/components/Switch.d.ts +44 -0
  61. package/dist/components/Switch.js +129 -0
  62. package/dist/components/Tabs.d.ts +31 -0
  63. package/dist/components/Tabs.js +127 -0
  64. package/dist/components/TextInput.d.ts +120 -0
  65. package/dist/components/TextInput.js +263 -0
  66. package/dist/components/Toggle.d.ts +106 -0
  67. package/dist/components/Toggle.js +150 -0
  68. package/dist/components/ToggleGroup.d.ts +80 -0
  69. package/dist/components/ToggleGroup.js +189 -0
  70. package/dist/components/Tooltip.d.ts +121 -0
  71. package/dist/components/Tooltip.js +132 -0
  72. package/dist/components/index.d.ts +35 -0
  73. package/dist/components/index.js +35 -0
  74. package/dist/constants/colors.d.ts +82 -0
  75. package/dist/constants/colors.js +116 -0
  76. package/dist/constants/fonts.d.ts +32 -0
  77. package/dist/constants/fonts.js +91 -0
  78. package/dist/constants/index.d.ts +3 -0
  79. package/dist/constants/index.js +3 -0
  80. package/dist/constants/spacing.d.ts +40 -0
  81. package/dist/constants/spacing.js +48 -0
  82. package/dist/hooks/index.d.ts +6 -0
  83. package/dist/hooks/index.js +6 -0
  84. package/dist/hooks/useDimensions.d.ts +19 -0
  85. package/dist/hooks/useDimensions.js +55 -0
  86. package/dist/hooks/useReduceMotion.d.ts +5 -0
  87. package/dist/hooks/useReduceMotion.js +64 -0
  88. package/dist/hooks/useResources.d.ts +12 -0
  89. package/dist/hooks/useResources.js +56 -0
  90. package/dist/hooks/useScalePress.d.ts +57 -0
  91. package/dist/hooks/useScalePress.js +55 -0
  92. package/dist/hooks/useStaggeredEntrance.d.ts +67 -0
  93. package/dist/hooks/useStaggeredEntrance.js +74 -0
  94. package/dist/hooks/useTheme.d.ts +88 -0
  95. package/dist/hooks/useTheme.js +328 -0
  96. package/dist/index.d.ts +5 -0
  97. package/dist/index.js +5 -0
  98. package/dist/lib/animations.d.ts +1 -0
  99. package/dist/lib/animations.js +3 -0
  100. package/dist/lib/haptics.d.ts +3 -0
  101. package/dist/lib/haptics.js +29 -0
  102. package/dist/lib/index.d.ts +3 -0
  103. package/dist/lib/index.js +3 -0
  104. package/dist/lib/sentry.d.ts +16 -0
  105. package/dist/lib/sentry.js +55 -0
  106. package/dist/state/globalUIStore.d.ts +30 -0
  107. package/dist/state/globalUIStore.js +8 -0
  108. package/dist/state/index.d.ts +2 -0
  109. package/dist/state/index.js +2 -0
  110. package/dist/state/themeStore.d.ts +6 -0
  111. package/dist/state/themeStore.js +38 -0
  112. package/package.json +92 -0
@@ -0,0 +1,106 @@
1
+ import * as TogglePrimitive from "@rn-primitives/toggle";
2
+ import { ViewStyle, StyleProp } from "react-native";
3
+ import type { IconName } from "./Icon";
4
+ export type ToggleVariant = "default" | "outline";
5
+ export type ToggleSize = "sm" | "default" | "lg";
6
+ export type ToggleShape = "default" | "square" | "circle";
7
+ interface ToggleProps extends Omit<TogglePrimitive.RootProps, "style"> {
8
+ /**
9
+ * Visual style variant
10
+ * - default: transparent background with subtle border
11
+ * - outline: primary border with transparent background
12
+ * @default "default"
13
+ */
14
+ variant?: ToggleVariant;
15
+ /**
16
+ * Size of the toggle button
17
+ * - sm: 32px height
18
+ * - default: 40px height
19
+ * - lg: 48px height
20
+ * @default "default"
21
+ */
22
+ size?: ToggleSize;
23
+ /**
24
+ * Shape of the toggle button
25
+ * - default: rounded corners (radiusMd)
26
+ * - square: sharp corners (0)
27
+ * - circle: fully rounded (radiusFull)
28
+ * @default "default"
29
+ */
30
+ shape?: ToggleShape;
31
+ /**
32
+ * Whether the toggle is in a loading state
33
+ * Shows spinner and disables interaction
34
+ */
35
+ loading?: boolean;
36
+ /**
37
+ * Whether the toggle is icon-only (equal padding)
38
+ * Optimizes padding for icon buttons
39
+ */
40
+ iconOnly?: boolean;
41
+ /**
42
+ * Custom style override (uses StyleSheet.flatten for web compatibility)
43
+ */
44
+ style?: StyleProp<ViewStyle>;
45
+ }
46
+ /**
47
+ * Enhanced Toggle Component
48
+ *
49
+ * Features:
50
+ * - 2 variants (default, outline)
51
+ * - 3 sizes (sm, default, lg)
52
+ * - 3 shapes (default, square, circle)
53
+ * - Loading state with spinner
54
+ * - Icon-only optimization
55
+ * - Style prop support
56
+ * - Full accessibility
57
+ *
58
+ * Usage:
59
+ * ```tsx
60
+ * // Basic
61
+ * const [pressed, setPressed] = useState(false);
62
+ * <Toggle pressed={pressed} onPressedChange={setPressed}>
63
+ * <SansSerifText>Toggle Me</SansSerifText>
64
+ * </Toggle>
65
+ *
66
+ * // With icon
67
+ * <Toggle pressed={pressed} onPressedChange={setPressed} iconOnly>
68
+ * <ToggleIcon name="bold" />
69
+ * </Toggle>
70
+ *
71
+ * // Different shapes
72
+ * <Toggle shape="square" pressed={pressed} onPressedChange={setPressed}>
73
+ * <SansSerifText>Square</SansSerifText>
74
+ * </Toggle>
75
+ *
76
+ * <Toggle shape="circle" iconOnly pressed={pressed} onPressedChange={setPressed}>
77
+ * <ToggleIcon name="bold" />
78
+ * </Toggle>
79
+ *
80
+ * // Loading state
81
+ * <Toggle loading pressed={pressed} onPressedChange={setPressed}>
82
+ * <SansSerifText>Loading...</SansSerifText>
83
+ * </Toggle>
84
+ * ```
85
+ */
86
+ declare function Toggle({ variant, size, shape, loading, iconOnly, style: styleOverride, ...props }: ToggleProps): import("react/jsx-runtime").JSX.Element;
87
+ /**
88
+ * ToggleIcon Component
89
+ * Icon wrapper for use inside Toggle buttons
90
+ * Automatically inherits sizing from parent Toggle
91
+ *
92
+ * Usage:
93
+ * ```tsx
94
+ * <Toggle pressed={pressed} onPressedChange={setPressed}>
95
+ * <ToggleIcon name="bold" />
96
+ * </Toggle>
97
+ * ```
98
+ */
99
+ interface ToggleIconProps {
100
+ name: IconName;
101
+ size?: number;
102
+ color?: string;
103
+ }
104
+ declare function ToggleIcon({ name, size, color }: ToggleIconProps): import("react/jsx-runtime").JSX.Element;
105
+ export { Toggle, ToggleIcon };
106
+ export type { ToggleProps };
@@ -0,0 +1,150 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import { Icon } from "./Icon";
4
+ import { TextClassContext, TextColorContext } from "./StyledText";
5
+ import { useTheme } from "../hooks/useTheme";
6
+ import { spacing } from "../constants/spacing";
7
+ import * as TogglePrimitive from "@rn-primitives/toggle";
8
+ import { Platform, StyleSheet, ActivityIndicator } from "react-native";
9
+ import { palette } from "../constants/colors";
10
+ const DEFAULT_HIT_SLOP = 8;
11
+ // Size configurations
12
+ const TOGGLE_SIZES = {
13
+ sm: {
14
+ height: 32,
15
+ minWidth: 32,
16
+ paddingHorizontal: spacing.sm,
17
+ fontSize: 12,
18
+ iconSize: spacing.iconSm,
19
+ },
20
+ default: {
21
+ height: 36,
22
+ minWidth: 36,
23
+ paddingHorizontal: spacing.md,
24
+ fontSize: 13,
25
+ iconSize: spacing.iconMd,
26
+ },
27
+ lg: {
28
+ height: 40,
29
+ minWidth: 40,
30
+ paddingHorizontal: spacing.lg,
31
+ fontSize: 14,
32
+ iconSize: spacing.iconMd,
33
+ },
34
+ };
35
+ /**
36
+ * Enhanced Toggle Component
37
+ *
38
+ * Features:
39
+ * - 2 variants (default, outline)
40
+ * - 3 sizes (sm, default, lg)
41
+ * - 3 shapes (default, square, circle)
42
+ * - Loading state with spinner
43
+ * - Icon-only optimization
44
+ * - Style prop support
45
+ * - Full accessibility
46
+ *
47
+ * Usage:
48
+ * ```tsx
49
+ * // Basic
50
+ * const [pressed, setPressed] = useState(false);
51
+ * <Toggle pressed={pressed} onPressedChange={setPressed}>
52
+ * <SansSerifText>Toggle Me</SansSerifText>
53
+ * </Toggle>
54
+ *
55
+ * // With icon
56
+ * <Toggle pressed={pressed} onPressedChange={setPressed} iconOnly>
57
+ * <ToggleIcon name="bold" />
58
+ * </Toggle>
59
+ *
60
+ * // Different shapes
61
+ * <Toggle shape="square" pressed={pressed} onPressedChange={setPressed}>
62
+ * <SansSerifText>Square</SansSerifText>
63
+ * </Toggle>
64
+ *
65
+ * <Toggle shape="circle" iconOnly pressed={pressed} onPressedChange={setPressed}>
66
+ * <ToggleIcon name="bold" />
67
+ * </Toggle>
68
+ *
69
+ * // Loading state
70
+ * <Toggle loading pressed={pressed} onPressedChange={setPressed}>
71
+ * <SansSerifText>Loading...</SansSerifText>
72
+ * </Toggle>
73
+ * ```
74
+ */
75
+ function Toggle({ variant = "default", size = "default", shape = "default", loading = false, iconOnly = false, style: styleOverride, ...props }) {
76
+ const { theme, getContrastingColor, withAlpha } = useTheme();
77
+ const sizeConfig = TOGGLE_SIZES[size];
78
+ // Calculate text color based on state and variant
79
+ const getTextColor = () => {
80
+ if (props.pressed) {
81
+ if (variant === "outline") {
82
+ // When pressed with outline variant, background is primary
83
+ return getContrastingColor(theme.colors.primary, palette.white, palette.black);
84
+ }
85
+ // When pressed with default variant, use primary color
86
+ return theme.colors.primary;
87
+ }
88
+ // When not pressed, use base content or primary for outline
89
+ return variant === "outline" ? theme.colors.primary : theme.colors.text;
90
+ };
91
+ const textColor = getTextColor();
92
+ // Determine border radius based on shape
93
+ const getBorderRadius = () => {
94
+ if (shape === "square")
95
+ return 0;
96
+ if (shape === "circle")
97
+ return spacing.radiusFull;
98
+ return spacing.radiusMd;
99
+ };
100
+ // Flatten style override for web compatibility
101
+ const flattenedStyle = styleOverride ? StyleSheet.flatten(styleOverride) : undefined;
102
+ const isDisabled = props.disabled || loading;
103
+ return (_jsx(TextColorContext.Provider, { value: textColor, children: _jsx(TextClassContext.Provider, { value: "", children: _jsx(TogglePrimitive.Root, { ...props, disabled: isDisabled, style: {
104
+ flexDirection: "row",
105
+ alignItems: "center",
106
+ justifyContent: "center",
107
+ gap: spacing.sm,
108
+ height: sizeConfig.height,
109
+ minWidth: sizeConfig.minWidth,
110
+ paddingHorizontal: iconOnly ? sizeConfig.height / 2 - sizeConfig.iconSize / 2 : sizeConfig.paddingHorizontal,
111
+ borderRadius: getBorderRadius(),
112
+ borderWidth: 1,
113
+ // Base variant styles
114
+ ...(variant === "default" && !props.pressed && {
115
+ backgroundColor: "transparent",
116
+ borderColor: theme.colors.border,
117
+ }),
118
+ ...(variant === "default" && props.pressed && {
119
+ backgroundColor: withAlpha(theme.colors.primary, 0.1),
120
+ borderColor: theme.colors.primary,
121
+ }),
122
+ // Outline variant styles
123
+ ...(variant === "outline" && !props.pressed && {
124
+ backgroundColor: "transparent",
125
+ borderColor: theme.colors.primary,
126
+ }),
127
+ ...(variant === "outline" && props.pressed && {
128
+ backgroundColor: theme.colors.primary,
129
+ borderColor: theme.colors.primary,
130
+ }),
131
+ // Disabled state
132
+ opacity: isDisabled ? 0.5 : 1,
133
+ // Web-specific styles
134
+ ...(Platform.OS === "web" && {
135
+ cursor: isDisabled ? "not-allowed" : "pointer",
136
+ transition: "all 150ms",
137
+ }),
138
+ // Apply custom style override
139
+ ...(flattenedStyle || {}),
140
+ }, hitSlop: DEFAULT_HIT_SLOP, accessibilityRole: "button", accessibilityState: {
141
+ selected: props.pressed,
142
+ disabled: !!isDisabled,
143
+ busy: loading,
144
+ }, children: loading ? (_jsx(ActivityIndicator, { size: "small", color: textColor })) : (props.children) }) }) }));
145
+ }
146
+ function ToggleIcon({ name, size, color }) {
147
+ const contextColor = React.useContext(TextColorContext);
148
+ return _jsx(Icon, { name: name, size: size || spacing.iconMd, color: color || contextColor });
149
+ }
150
+ export { Toggle, ToggleIcon };
@@ -0,0 +1,80 @@
1
+ import type { IconName } from "./Icon";
2
+ import * as ToggleGroupPrimitive from "@rn-primitives/toggle-group";
3
+ type ToggleGroupVariant = "default" | "outline";
4
+ type ToggleGroupSize = "sm" | "default" | "lg";
5
+ type ToggleGroupProps = ToggleGroupPrimitive.RootProps & {
6
+ /**
7
+ * Visual style variant
8
+ * - default: transparent background with subtle border
9
+ * - outline: primary border with grouped appearance
10
+ */
11
+ variant?: ToggleGroupVariant;
12
+ /**
13
+ * Size of the toggle buttons
14
+ * - sm: 32px height
15
+ * - default: 40px height
16
+ * - lg: 48px height
17
+ */
18
+ size?: ToggleGroupSize;
19
+ };
20
+ /**
21
+ * ToggleGroup Component
22
+ * A group of toggle buttons for single or multiple selection
23
+ * Using @rn-primitives/toggle-group with DaisyUI theme integration
24
+ *
25
+ * Usage (Single Selection):
26
+ * ```tsx
27
+ * const [alignment, setAlignment] = useState('left');
28
+ * <ToggleGroup type="single" value={alignment} onValueChange={setAlignment}>
29
+ * <ToggleGroupItem value="left">Left</ToggleGroupItem>
30
+ * <ToggleGroupItem value="center">Center</ToggleGroupItem>
31
+ * <ToggleGroupItem value="right">Right</ToggleGroupItem>
32
+ * </ToggleGroup>
33
+ * ```
34
+ *
35
+ * Usage (Multiple Selection):
36
+ * ```tsx
37
+ * const [formats, setFormats] = useState(['bold']);
38
+ * <ToggleGroup type="multiple" value={formats} onValueChange={setFormats}>
39
+ * <ToggleGroupItem value="bold">Bold</ToggleGroupItem>
40
+ * <ToggleGroupItem value="italic">Italic</ToggleGroupItem>
41
+ * </ToggleGroup>
42
+ * ```
43
+ */
44
+ declare function ToggleGroup({ variant, size, children, ...props }: ToggleGroupProps): import("react/jsx-runtime").JSX.Element;
45
+ type ToggleGroupItemProps = ToggleGroupPrimitive.ItemProps & {
46
+ /**
47
+ * Automatically set by ToggleGroup parent - don't set manually
48
+ */
49
+ isFirst?: boolean;
50
+ /**
51
+ * Automatically set by ToggleGroup parent - don't set manually
52
+ */
53
+ isLast?: boolean;
54
+ };
55
+ /**
56
+ * ToggleGroupItem Component
57
+ * Individual toggle button within a ToggleGroup
58
+ * Position (first/last) is automatically detected for rounded corners
59
+ */
60
+ declare function ToggleGroupItem({ isFirst, isLast, children, ...props }: ToggleGroupItemProps): import("react/jsx-runtime").JSX.Element;
61
+ /**
62
+ * ToggleGroupIcon Component
63
+ * Icon wrapper for use inside ToggleGroup items
64
+ * Automatically inherits sizing from parent ToggleGroup
65
+ *
66
+ * Usage:
67
+ * ```tsx
68
+ * <ToggleGroupItem value="bold">
69
+ * <ToggleGroupIcon name="bold" />
70
+ * </ToggleGroupItem>
71
+ * ```
72
+ */
73
+ interface ToggleGroupIconProps {
74
+ name: IconName;
75
+ size?: number;
76
+ color?: string;
77
+ }
78
+ declare function ToggleGroupIcon({ name, size, color }: ToggleGroupIconProps): import("react/jsx-runtime").JSX.Element;
79
+ export { ToggleGroup, ToggleGroupIcon, ToggleGroupItem };
80
+ export type { ToggleGroupProps, ToggleGroupSize, ToggleGroupVariant };
@@ -0,0 +1,189 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Icon } from "./Icon";
3
+ import { TextClassContext, TextColorContext } from "./StyledText";
4
+ import { spacing } from "../constants/spacing";
5
+ import { useTheme } from "../hooks/useTheme";
6
+ import * as ToggleGroupPrimitive from "@rn-primitives/toggle-group";
7
+ import * as React from "react";
8
+ import { Platform } from "react-native";
9
+ const DEFAULT_HIT_SLOP = 8;
10
+ // Size configurations (same as Toggle)
11
+ const TOGGLE_GROUP_SIZES = {
12
+ sm: {
13
+ height: 32,
14
+ minWidth: 32,
15
+ paddingHorizontal: spacing.sm,
16
+ fontSize: 12,
17
+ iconSize: spacing.iconSm,
18
+ },
19
+ default: {
20
+ height: 36,
21
+ minWidth: 36,
22
+ paddingHorizontal: spacing.md,
23
+ fontSize: 13,
24
+ iconSize: spacing.iconMd,
25
+ },
26
+ lg: {
27
+ height: 40,
28
+ minWidth: 40,
29
+ paddingHorizontal: spacing.lg,
30
+ fontSize: 14,
31
+ iconSize: spacing.iconMd,
32
+ },
33
+ };
34
+ const ToggleGroupContext = React.createContext(null);
35
+ function useToggleGroupContext() {
36
+ const context = React.useContext(ToggleGroupContext);
37
+ if (context === null) {
38
+ throw new Error("ToggleGroup compound components cannot be rendered outside the ToggleGroup component");
39
+ }
40
+ return context;
41
+ }
42
+ /**
43
+ * ToggleGroup Component
44
+ * A group of toggle buttons for single or multiple selection
45
+ * Using @rn-primitives/toggle-group with DaisyUI theme integration
46
+ *
47
+ * Usage (Single Selection):
48
+ * ```tsx
49
+ * const [alignment, setAlignment] = useState('left');
50
+ * <ToggleGroup type="single" value={alignment} onValueChange={setAlignment}>
51
+ * <ToggleGroupItem value="left">Left</ToggleGroupItem>
52
+ * <ToggleGroupItem value="center">Center</ToggleGroupItem>
53
+ * <ToggleGroupItem value="right">Right</ToggleGroupItem>
54
+ * </ToggleGroup>
55
+ * ```
56
+ *
57
+ * Usage (Multiple Selection):
58
+ * ```tsx
59
+ * const [formats, setFormats] = useState(['bold']);
60
+ * <ToggleGroup type="multiple" value={formats} onValueChange={setFormats}>
61
+ * <ToggleGroupItem value="bold">Bold</ToggleGroupItem>
62
+ * <ToggleGroupItem value="italic">Italic</ToggleGroupItem>
63
+ * </ToggleGroup>
64
+ * ```
65
+ */
66
+ function ToggleGroup({ variant = "default", size = "default", children, ...props }) {
67
+ const { theme } = useTheme();
68
+ // Count valid children for first/last detection
69
+ const childrenArray = React.Children.toArray(children);
70
+ const validChildren = childrenArray.filter((child) => React.isValidElement(child) && child.type === ToggleGroupItem);
71
+ const childCount = validChildren.length;
72
+ // Clone children with position props
73
+ let itemIndex = 0;
74
+ const enhancedChildren = React.Children.map(children, (child) => {
75
+ if (React.isValidElement(child) && child.type === ToggleGroupItem) {
76
+ const isFirst = itemIndex === 0;
77
+ const isLast = itemIndex === childCount - 1;
78
+ itemIndex++;
79
+ return React.cloneElement(child, {
80
+ isFirst,
81
+ isLast,
82
+ });
83
+ }
84
+ return child;
85
+ });
86
+ return (_jsx(ToggleGroupPrimitive.Root, { ...props, style: {
87
+ flexDirection: "row",
88
+ alignItems: "center",
89
+ borderRadius: spacing.radiusMd,
90
+ // No shadow on Android - causes text background artifact
91
+ ...(variant === "outline" && Platform.OS === "ios" && {
92
+ shadowColor: theme.colors.overlay,
93
+ shadowOffset: { width: 0, height: 1 },
94
+ shadowOpacity: 0.05,
95
+ shadowRadius: 2,
96
+ }),
97
+ ...(Platform.OS === "web" && {
98
+ width: "fit-content",
99
+ }),
100
+ }, children: _jsx(ToggleGroupContext.Provider, { value: { variant, size }, children: enhancedChildren }) }));
101
+ }
102
+ /**
103
+ * ToggleGroupItem Component
104
+ * Individual toggle button within a ToggleGroup
105
+ * Position (first/last) is automatically detected for rounded corners
106
+ */
107
+ function ToggleGroupItem({ isFirst = false, isLast = false, children, ...props }) {
108
+ const { theme, withAlpha, getContrastingColor } = useTheme();
109
+ const context = useToggleGroupContext();
110
+ const { value: groupValue } = ToggleGroupPrimitive.useRootContext();
111
+ const sizeConfig = TOGGLE_GROUP_SIZES[context.size];
112
+ // Check if this item is selected
113
+ const isSelected = ToggleGroupPrimitive.utils.getIsSelected(groupValue, props.value);
114
+ // Determine the actual background color for this item
115
+ const itemBgColor = (() => {
116
+ if (context.variant === "outline" && isSelected)
117
+ return theme.colors.primary;
118
+ if (context.variant === "default" && isSelected)
119
+ return theme.colors.background;
120
+ return theme.colors.background;
121
+ })();
122
+ // Calculate text color with contrast against the actual background
123
+ const textColor = isSelected
124
+ ? getContrastingColor(itemBgColor, theme.colors.foreground, theme.colors.background)
125
+ : theme.colors.foreground;
126
+ return (_jsx(TextColorContext.Provider, { value: textColor, children: _jsx(TextClassContext.Provider, { value: "", children: _jsx(ToggleGroupPrimitive.Item, { ...props, style: {
127
+ flexDirection: "row",
128
+ alignItems: "center",
129
+ justifyContent: "center",
130
+ gap: spacing.sm,
131
+ height: sizeConfig.height,
132
+ minWidth: sizeConfig.minWidth,
133
+ paddingHorizontal: sizeConfig.paddingHorizontal,
134
+ borderWidth: 1,
135
+ flexShrink: 0,
136
+ // Base variant styles
137
+ ...(context.variant === "default" && !isSelected && {
138
+ backgroundColor: "transparent",
139
+ borderColor: theme.colors.border,
140
+ }),
141
+ ...(context.variant === "default" && isSelected && {
142
+ backgroundColor: withAlpha(theme.colors.primary, 0.1),
143
+ borderColor: theme.colors.primary,
144
+ }),
145
+ // Outline variant styles
146
+ ...(context.variant === "outline" && !isSelected && {
147
+ backgroundColor: "transparent",
148
+ borderColor: theme.colors.border,
149
+ }),
150
+ ...(context.variant === "outline" && isSelected && {
151
+ backgroundColor: theme.colors.primary,
152
+ borderColor: theme.colors.primary,
153
+ }),
154
+ // Remove borders between items (except first)
155
+ ...(context.variant === "outline" && !isFirst && {
156
+ borderLeftWidth: 0,
157
+ }),
158
+ // Border radius handling
159
+ borderRadius: 0, // Remove all radius by default
160
+ ...(isFirst && {
161
+ borderTopLeftRadius: spacing.radiusMd,
162
+ borderBottomLeftRadius: spacing.radiusMd,
163
+ }),
164
+ ...(isLast && {
165
+ borderTopRightRadius: spacing.radiusMd,
166
+ borderBottomRightRadius: spacing.radiusMd,
167
+ }),
168
+ // Single item (both first and last)
169
+ ...(isFirst && isLast && {
170
+ borderRadius: spacing.radiusMd,
171
+ }),
172
+ // Disabled state
173
+ opacity: props.disabled ? 0.5 : 1,
174
+ // Web-specific styles
175
+ ...(Platform.OS === "web" && {
176
+ cursor: props.disabled ? "not-allowed" : "pointer",
177
+ transition: "all 150ms",
178
+ // Ensure proper z-index on focus
179
+ ...(isSelected && {
180
+ zIndex: 10,
181
+ }),
182
+ }),
183
+ }, hitSlop: DEFAULT_HIT_SLOP, children: children }) }) }));
184
+ }
185
+ function ToggleGroupIcon({ name, size, color }) {
186
+ const contextColor = React.useContext(TextColorContext);
187
+ return _jsx(Icon, { name: name, size: size || spacing.iconMd, color: color || contextColor });
188
+ }
189
+ export { ToggleGroup, ToggleGroupIcon, ToggleGroupItem };
@@ -0,0 +1,121 @@
1
+ import * as React from "react";
2
+ import { View, ViewProps } from "react-native";
3
+ import * as TooltipPrimitive from "@rn-primitives/tooltip";
4
+ /**
5
+ * Tooltip Trigger Component
6
+ * The element that triggers the tooltip to appear on hover (web) or press (native)
7
+ */
8
+ declare const TooltipTrigger: {
9
+ ({ asChild, onPress: onPressProp, disabled, ref, ...props }: Omit<import("react-native").PressableProps & React.RefAttributes<View>, "ref"> & {
10
+ asChild?: boolean;
11
+ } & {
12
+ onKeyDown?: (ev: React.KeyboardEvent) => void;
13
+ onKeyUp?: (ev: React.KeyboardEvent) => void;
14
+ } & React.RefAttributes<import("@rn-primitives/tooltip").TriggerRef>): React.JSX.Element;
15
+ displayName: string;
16
+ };
17
+ /**
18
+ * Tooltip variant styles
19
+ */
20
+ export type TooltipVariant = "default" | "dark" | "light";
21
+ interface TooltipContentProps extends TooltipPrimitive.ContentProps {
22
+ /**
23
+ * Optional portal host name for custom portal mounting
24
+ */
25
+ portalHost?: string;
26
+ /**
27
+ * Visual variant
28
+ * @default "default"
29
+ */
30
+ variant?: TooltipVariant;
31
+ }
32
+ /**
33
+ * Tooltip Content Component
34
+ * The content that appears in the tooltip overlay
35
+ * Supports smart positioning, animations, and theme integration
36
+ *
37
+ * Features:
38
+ * - Side positioning (top, bottom, left, right - left/right web only)
39
+ * - Alignment options (start, center, end)
40
+ * - Visual variants (default, dark, light)
41
+ * - Smooth animations
42
+ * - Portal-based rendering for proper z-index
43
+ */
44
+ declare function TooltipContent({ side, align, sideOffset, portalHost, variant, ...props }: TooltipContentProps): import("react/jsx-runtime").JSX.Element;
45
+ /**
46
+ * Tooltip Body Component
47
+ * Simple wrapper for tooltip content with padding
48
+ */
49
+ interface TooltipBodyProps extends ViewProps {
50
+ children: React.ReactNode;
51
+ }
52
+ declare function TooltipBody({ children, style, ...props }: TooltipBodyProps): import("react/jsx-runtime").JSX.Element;
53
+ interface TooltipProps extends TooltipPrimitive.RootProps {
54
+ /**
55
+ * Time to wait before showing tooltip (web only)
56
+ * @default 700
57
+ */
58
+ delayDuration?: number;
59
+ /**
60
+ * Time between tooltips when moving cursor (web only)
61
+ * @default 300
62
+ */
63
+ skipDelayDuration?: number;
64
+ }
65
+ /**
66
+ * Tooltip Root Component
67
+ * Manages tooltip state and provides context for trigger and content
68
+ *
69
+ * Usage:
70
+ * ```tsx
71
+ * // Basic tooltip
72
+ * <Tooltip>
73
+ * <TooltipTrigger asChild>
74
+ * <Button><Text>Hover me</Text></Button>
75
+ * </TooltipTrigger>
76
+ * <TooltipContent>
77
+ * <StyledText>Tooltip text</StyledText>
78
+ * </TooltipContent>
79
+ * </Tooltip>
80
+ *
81
+ * // With positioning
82
+ * <Tooltip>
83
+ * <TooltipTrigger asChild>
84
+ * <Icon as={Info} size={20} />
85
+ * </TooltipTrigger>
86
+ * <TooltipContent side="bottom" align="start">
87
+ * <StyledText>Information tooltip</StyledText>
88
+ * </TooltipContent>
89
+ * </Tooltip>
90
+ *
91
+ * // Dark variant
92
+ * <Tooltip>
93
+ * <TooltipTrigger asChild>
94
+ * <Button><Text>Help</Text></Button>
95
+ * </TooltipTrigger>
96
+ * <TooltipContent variant="dark">
97
+ * <StyledText>Dark tooltip</StyledText>
98
+ * </TooltipContent>
99
+ * </Tooltip>
100
+ * ```
101
+ */
102
+ declare function Tooltip({ delayDuration, skipDelayDuration, ...props }: TooltipProps): import("react/jsx-runtime").JSX.Element;
103
+ /**
104
+ * Tooltip Component with Sub-components
105
+ * Properly typed interface for dot notation access (e.g., Tooltip.Trigger)
106
+ */
107
+ declare const TooltipComponent: typeof Tooltip & {
108
+ Trigger: {
109
+ ({ asChild, onPress: onPressProp, disabled, ref, ...props }: Omit<import("react-native").PressableProps & React.RefAttributes<View>, "ref"> & {
110
+ asChild?: boolean;
111
+ } & {
112
+ onKeyDown?: (ev: React.KeyboardEvent) => void;
113
+ onKeyUp?: (ev: React.KeyboardEvent) => void;
114
+ } & React.RefAttributes<import("@rn-primitives/tooltip").TriggerRef>): React.JSX.Element;
115
+ displayName: string;
116
+ };
117
+ Content: typeof TooltipContent;
118
+ Body: typeof TooltipBody;
119
+ };
120
+ export { TooltipComponent as Tooltip, TooltipTrigger, TooltipContent, TooltipBody, };
121
+ export type { TooltipContentProps, TooltipBodyProps, TooltipProps, };