@idealyst/components 1.0.82 → 1.0.84
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/CLAUDE.md +199 -232
- package/README.md +5 -5
- package/package.json +25 -7
- package/plugin/README.md +272 -0
- package/plugin/test-cases.jsx +112 -0
- package/plugin/web-legacy.js +320 -0
- package/plugin/web.js +422 -124
- package/src/Accordion/Accordion.native.tsx +182 -0
- package/src/Accordion/Accordion.styles.tsx +260 -0
- package/src/Accordion/Accordion.web.tsx +147 -0
- package/src/Accordion/index.native.tsx +3 -0
- package/src/Accordion/index.ts +3 -0
- package/src/Accordion/index.web.tsx +3 -0
- package/src/Accordion/types.ts +23 -0
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +17 -12
- package/src/ActivityIndicator/ActivityIndicator.styles.tsx +83 -109
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +23 -17
- package/src/ActivityIndicator/index.ts +5 -2
- package/src/ActivityIndicator/index.web.ts +5 -2
- package/src/ActivityIndicator/types.ts +15 -10
- package/src/Alert/Alert.native.tsx +113 -0
- package/src/Alert/Alert.styles.tsx +304 -0
- package/src/Alert/Alert.web.tsx +123 -0
- package/src/Alert/index.native.ts +5 -0
- package/src/Alert/index.ts +5 -0
- package/src/Alert/index.web.ts +5 -0
- package/src/Alert/types.ts +21 -0
- package/src/Avatar/Avatar.native.tsx +8 -6
- package/src/Avatar/Avatar.styles.tsx +64 -58
- package/src/Avatar/Avatar.web.tsx +13 -8
- package/src/Avatar/index.ts +5 -2
- package/src/Avatar/index.web.ts +5 -2
- package/src/Avatar/types.ts +19 -13
- package/src/Badge/Badge.native.tsx +59 -14
- package/src/Badge/Badge.styles.tsx +125 -139
- package/src/Badge/Badge.web.tsx +72 -16
- package/src/Badge/index.ts +5 -2
- package/src/Badge/index.web.ts +5 -2
- package/src/Badge/types.ts +23 -11
- package/src/Breadcrumb/Breadcrumb.native.tsx +225 -0
- package/src/Breadcrumb/Breadcrumb.styles.tsx +234 -0
- package/src/Breadcrumb/Breadcrumb.web.tsx +268 -0
- package/src/Breadcrumb/index.native.ts +5 -0
- package/src/Breadcrumb/index.ts +5 -0
- package/src/Breadcrumb/index.web.ts +5 -0
- package/src/Breadcrumb/types.ts +56 -0
- package/src/Button/Button.native.tsx +75 -24
- package/src/Button/Button.styles.tsx +248 -205
- package/src/Button/Button.web.tsx +82 -25
- package/src/Button/index.ts +5 -5
- package/src/Button/index.web.ts +5 -3
- package/src/Button/types.ts +32 -15
- package/src/Card/Card.native.tsx +14 -11
- package/src/Card/Card.styles.tsx +146 -220
- package/src/Card/Card.web.tsx +20 -21
- package/src/Card/index.ts +5 -5
- package/src/Card/index.web.ts +5 -3
- package/src/Card/types.ts +24 -17
- package/src/Checkbox/Checkbox.native.tsx +24 -34
- package/src/Checkbox/Checkbox.styles.tsx +223 -275
- package/src/Checkbox/Checkbox.web.tsx +30 -37
- package/src/Checkbox/index.ts +5 -5
- package/src/Checkbox/index.web.ts +5 -3
- package/src/Checkbox/types.ts +26 -20
- package/src/Chip/Chip.native.tsx +126 -0
- package/src/Chip/Chip.styles.tsx +138 -0
- package/src/Chip/Chip.web.tsx +154 -0
- package/src/Chip/index.native.ts +5 -0
- package/src/Chip/index.ts +5 -0
- package/src/Chip/index.web.ts +5 -0
- package/src/Chip/types.ts +51 -0
- package/src/Dialog/Dialog.native.tsx +65 -12
- package/src/Dialog/Dialog.styles.tsx +154 -136
- package/src/Dialog/Dialog.web.tsx +16 -11
- package/src/Dialog/index.ts +5 -2
- package/src/Dialog/index.web.ts +5 -2
- package/src/Dialog/types.ts +22 -16
- package/src/Divider/Divider.native.tsx +19 -14
- package/src/Divider/Divider.styles.tsx +273 -595
- package/src/Divider/Divider.web.tsx +19 -12
- package/src/Divider/index.ts +5 -5
- package/src/Divider/index.web.ts +5 -3
- package/src/Divider/types.ts +28 -19
- package/src/Icon/Icon.native.tsx +17 -24
- package/src/Icon/Icon.styles.tsx +64 -48
- package/src/Icon/Icon.web.tsx +14 -11
- package/src/Icon/IconSvg/IconSvg.native.tsx +42 -0
- package/src/Icon/IconSvg/IconSvg.web.tsx +40 -0
- package/src/Icon/IconSvg/index.native.ts +1 -0
- package/src/Icon/IconSvg/index.ts +1 -0
- package/src/Icon/icon-resolver.native.ts +27 -0
- package/src/Icon/icon-resolver.ts +70 -0
- package/src/Icon/index.ts +5 -5
- package/src/Icon/index.web.ts +5 -3
- package/src/Icon/types.ts +17 -11
- package/src/Image/Image.native.tsx +86 -0
- package/src/Image/Image.styles.tsx +57 -0
- package/src/Image/Image.web.tsx +92 -0
- package/src/Image/index.native.ts +5 -0
- package/src/Image/index.ts +5 -0
- package/src/Image/types.ts +21 -0
- package/src/Input/Input.native.tsx +103 -26
- package/src/Input/Input.styles.tsx +240 -177
- package/src/Input/Input.web.tsx +141 -38
- package/src/Input/index.ts +5 -5
- package/src/Input/index.web.ts +5 -3
- package/src/Input/types.ts +43 -20
- package/src/List/List.native.tsx +56 -0
- package/src/List/List.styles.tsx +257 -0
- package/src/List/List.web.tsx +43 -0
- package/src/List/ListContext.tsx +16 -0
- package/src/List/ListItem.native.tsx +111 -0
- package/src/List/ListItem.web.tsx +110 -0
- package/src/List/ListSection.native.tsx +31 -0
- package/src/List/ListSection.web.tsx +33 -0
- package/src/List/index.native.tsx +5 -0
- package/src/List/index.ts +5 -0
- package/src/List/index.web.tsx +5 -0
- package/src/List/types.ts +42 -0
- package/src/Menu/Menu.native.tsx +150 -0
- package/src/Menu/Menu.styles.tsx +185 -0
- package/src/Menu/Menu.web.tsx +99 -0
- package/src/Menu/MenuItem.native.tsx +66 -0
- package/src/Menu/MenuItem.styles.tsx +119 -0
- package/src/Menu/MenuItem.web.tsx +67 -0
- package/src/Menu/index.native.ts +3 -0
- package/src/Menu/index.ts +3 -0
- package/src/Menu/index.web.ts +3 -0
- package/src/Menu/types.ts +30 -0
- package/src/Popover/Popover.native.tsx +102 -32
- package/src/Popover/Popover.styles.tsx +100 -67
- package/src/Popover/Popover.web.tsx +36 -260
- package/src/Popover/index.ts +5 -2
- package/src/Popover/index.web.ts +5 -2
- package/src/Popover/types.ts +14 -13
- package/src/Pressable/Pressable.native.tsx +7 -6
- package/src/Pressable/Pressable.web.tsx +8 -6
- package/src/Pressable/index.ts +5 -2
- package/src/Pressable/index.web.ts +5 -2
- package/src/Pressable/types.ts +11 -10
- package/src/Progress/Progress.native.tsx +179 -0
- package/src/Progress/Progress.styles.tsx +164 -0
- package/src/Progress/Progress.web.tsx +144 -0
- package/src/Progress/index.native.ts +1 -0
- package/src/Progress/index.ts +5 -0
- package/src/Progress/index.web.ts +5 -0
- package/src/Progress/types.ts +21 -0
- package/src/RadioButton/RadioButton.native.tsx +88 -0
- package/src/RadioButton/RadioButton.styles.tsx +163 -0
- package/src/RadioButton/RadioButton.web.tsx +85 -0
- package/src/RadioButton/RadioGroup.native.tsx +43 -0
- package/src/RadioButton/RadioGroup.web.tsx +49 -0
- package/src/RadioButton/index.native.ts +2 -0
- package/src/RadioButton/index.ts +2 -0
- package/src/RadioButton/index.web.ts +2 -0
- package/src/RadioButton/types.ts +29 -0
- package/src/SVGImage/SVGImage.native.tsx +9 -7
- package/src/SVGImage/SVGImage.styles.tsx +63 -55
- package/src/SVGImage/SVGImage.web.tsx +16 -13
- package/src/SVGImage/index.ts +5 -5
- package/src/SVGImage/index.web.ts +5 -2
- package/src/SVGImage/types.ts +7 -3
- package/src/Screen/Screen.native.tsx +43 -17
- package/src/Screen/Screen.styles.tsx +58 -54
- package/src/Screen/Screen.web.tsx +11 -5
- package/src/Screen/index.ts +5 -2
- package/src/Screen/index.web.ts +5 -2
- package/src/Screen/types.ts +23 -9
- package/src/Select/Select.native.tsx +347 -0
- package/src/Select/Select.styles.tsx +335 -0
- package/src/Select/Select.web.tsx +276 -0
- package/src/Select/index.native.ts +2 -0
- package/src/Select/index.ts +5 -0
- package/src/Select/index.web.ts +5 -0
- package/src/Select/types.ts +124 -0
- package/src/Skeleton/Skeleton.native.tsx +139 -0
- package/src/Skeleton/Skeleton.styles.tsx +59 -0
- package/src/Skeleton/Skeleton.web.tsx +112 -0
- package/src/Skeleton/index.native.ts +4 -0
- package/src/Skeleton/index.ts +5 -0
- package/src/Skeleton/index.web.ts +5 -0
- package/src/Skeleton/types.ts +75 -0
- package/src/Slider/Slider.native.tsx +248 -0
- package/src/Slider/Slider.styles.tsx +241 -0
- package/src/Slider/Slider.web.tsx +226 -0
- package/src/Slider/index.native.ts +3 -0
- package/src/Slider/index.ts +5 -0
- package/src/Slider/index.web.ts +5 -0
- package/src/Slider/types.ts +31 -0
- package/src/Switch/Switch.native.tsx +131 -0
- package/src/Switch/Switch.styles.tsx +169 -0
- package/src/Switch/Switch.web.tsx +121 -0
- package/src/Switch/index.native.ts +3 -0
- package/src/Switch/index.ts +5 -0
- package/src/Switch/index.web.ts +5 -0
- package/src/Switch/types.ts +21 -0
- package/src/TabBar/TabBar.native.tsx +142 -0
- package/src/TabBar/TabBar.styles.tsx +399 -0
- package/src/TabBar/TabBar.web.tsx +205 -0
- package/src/TabBar/index.native.tsx +3 -0
- package/src/TabBar/index.ts +3 -0
- package/src/TabBar/index.web.tsx +3 -0
- package/src/TabBar/types.ts +26 -0
- package/src/Table/Table.native.tsx +122 -0
- package/src/Table/Table.styles.tsx +283 -0
- package/src/Table/Table.web.tsx +112 -0
- package/src/Table/index.native.tsx +3 -0
- package/src/Table/index.ts +3 -0
- package/src/Table/index.web.tsx +3 -0
- package/src/Table/types.ts +28 -0
- package/src/Text/Text.native.tsx +12 -11
- package/src/Text/Text.styles.tsx +76 -64
- package/src/Text/Text.web.tsx +14 -9
- package/src/Text/index.ts +5 -5
- package/src/Text/index.web.ts +5 -3
- package/src/Text/types.ts +20 -13
- package/src/TextArea/TextArea.native.tsx +134 -0
- package/src/TextArea/TextArea.styles.tsx +175 -0
- package/src/TextArea/TextArea.web.tsx +156 -0
- package/src/TextArea/index.native.ts +3 -0
- package/src/TextArea/index.ts +3 -0
- package/src/TextArea/index.web.ts +3 -0
- package/src/TextArea/types.ts +30 -0
- package/src/Tooltip/Tooltip.native.tsx +165 -0
- package/src/Tooltip/Tooltip.styles.tsx +73 -0
- package/src/Tooltip/Tooltip.web.tsx +87 -0
- package/src/Tooltip/index.native.ts +3 -0
- package/src/Tooltip/index.ts +3 -0
- package/src/Tooltip/types.ts +18 -0
- package/src/Video/Video.native.tsx +105 -0
- package/src/Video/Video.styles.tsx +39 -0
- package/src/Video/Video.web.tsx +115 -0
- package/src/Video/index.native.ts +5 -0
- package/src/Video/index.ts +5 -0
- package/src/Video/types.ts +29 -0
- package/src/View/View.native.tsx +9 -14
- package/src/View/View.styles.tsx +101 -93
- package/src/View/View.web.tsx +16 -17
- package/src/View/index.ts +5 -5
- package/src/View/index.web.ts +5 -3
- package/src/View/types.ts +29 -21
- package/src/examples/AccordionExamples.tsx +126 -0
- package/src/examples/AlertExamples.tsx +280 -0
- package/src/examples/AvatarExamples.tsx +23 -23
- package/src/examples/BadgeExamples.tsx +109 -41
- package/src/examples/BreadcrumbExamples.tsx +312 -0
- package/src/examples/ButtonExamples.tsx +160 -33
- package/src/examples/CardExamples.tsx +40 -40
- package/src/examples/CheckboxExamples.tsx +12 -12
- package/src/examples/ChipExamples.tsx +197 -0
- package/src/examples/DialogExamples.tsx +22 -22
- package/src/examples/DividerExamples.tsx +49 -49
- package/src/examples/IconExamples.tsx +270 -54
- package/src/examples/ImageExamples.tsx +174 -0
- package/src/examples/InputExamples.tsx +75 -17
- package/src/examples/ListExamples.tsx +288 -0
- package/src/examples/MenuExamples.tsx +144 -0
- package/src/examples/PopoverExamples.tsx +69 -73
- package/src/examples/ProgressExamples.tsx +137 -0
- package/src/examples/RadioButtonExamples.tsx +161 -0
- package/src/examples/SVGImageExamples.tsx +19 -17
- package/src/examples/ScreenExamples.tsx +31 -31
- package/src/examples/SelectExamples.tsx +423 -0
- package/src/examples/SkeletonExamples.tsx +206 -0
- package/src/examples/SliderExamples.tsx +200 -0
- package/src/examples/SwitchExamples.tsx +182 -0
- package/src/examples/TabBarExamples.tsx +143 -0
- package/src/examples/TableExamples.tsx +280 -0
- package/src/examples/TextAreaExamples.tsx +173 -0
- package/src/examples/TextExamples.tsx +28 -32
- package/src/examples/ThemeExtensionExamples.tsx +10 -10
- package/src/examples/TooltipExamples.tsx +126 -0
- package/src/examples/VideoExamples.tsx +144 -0
- package/src/examples/ViewExamples.tsx +64 -56
- package/src/examples/index.ts +18 -3
- package/src/hooks/useMergeRefs.ts +16 -0
- package/src/hooks/useSmartPosition.native.ts +169 -0
- package/src/index.native.ts +80 -9
- package/src/index.ts +75 -1
- package/src/internal/BoundedModalContent.native.tsx +58 -0
- package/src/internal/PositionedPortal.tsx +254 -0
- package/src/internal/SafeAreaDebugOverlay.native.tsx +173 -0
- package/src/unistyles.d.ts +6 -0
- package/src/utils/buildSizeVariants.ts +16 -0
- package/src/utils/deepMerge.ts +43 -0
- package/src/utils/positionUtils.native.ts +280 -0
- package/src/utils/styleHelpers.ts +48 -0
- package/LLM-ACCESS-GUIDE.md +0 -143
- package/src/ActivityIndicator/README.md +0 -132
- package/src/Avatar/README.md +0 -139
- package/src/Badge/README.md +0 -170
- package/src/Button/Button.types.ts +0 -12
- package/src/Button/README.md +0 -262
- package/src/Card/README.md +0 -258
- package/src/Checkbox/README.md +0 -102
- package/src/Dialog/README.md +0 -210
- package/src/Divider/README.md +0 -108
- package/src/Icon/README.md +0 -81
- package/src/Input/README.md +0 -100
- package/src/SVGImage/README.md +0 -209
- package/src/Screen/README.md +0 -86
- package/src/Text/README.md +0 -94
- package/src/View/README.md +0 -107
- package/src/examples/AllExamples.tsx +0 -84
- package/src/examples/README.md +0 -136
- package/src/examples/ValidationExamples.tsx +0 -95
- package/src/examples/extendedTheme.ts +0 -329
- package/src/theme/breakpoints.ts +0 -8
- package/src/theme/colorResolver.ts +0 -218
- package/src/theme/colors.ts +0 -315
- package/src/theme/defaultThemes.ts +0 -326
- package/src/theme/index.ts +0 -188
- package/src/theme/themeBuilder.ts +0 -602
- package/src/theme/unistyles.d.ts +0 -6
- package/src/theme/variantHelpers.ts +0 -584
- package/src/theme/variants.ts +0 -56
|
@@ -1,215 +1,258 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
minHeight: 40,
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
// Dynamically generated intent variants
|
|
36
|
-
intent: generateIntentVariants(theme),
|
|
37
|
-
variant: {
|
|
2
|
+
import { Theme, Intent, Size, CompoundVariants} from '@idealyst/theme';
|
|
3
|
+
import { buildSizeVariants } from '../utils/buildSizeVariants';
|
|
4
|
+
|
|
5
|
+
type ButtonSize = Size;
|
|
6
|
+
type ButtonIntent = Intent;
|
|
7
|
+
type ButtonType = 'contained' | 'outlined' | 'text';
|
|
8
|
+
|
|
9
|
+
export type ButtonVariants = {
|
|
10
|
+
size: ButtonSize;
|
|
11
|
+
intent: ButtonIntent;
|
|
12
|
+
type: ButtonType;
|
|
13
|
+
disabled: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create intent variants (placeholder, colors handled by compound variants)
|
|
18
|
+
*/
|
|
19
|
+
function createIntentVariants(theme: Theme) {
|
|
20
|
+
const variants: any = {};
|
|
21
|
+
for (const intent in theme.intents) {
|
|
22
|
+
variants[intent] = {};
|
|
23
|
+
}
|
|
24
|
+
return variants;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Create type variants (structure only, colors handled by compound variants)
|
|
29
|
+
*/
|
|
30
|
+
function createTypeVariants(theme: Theme) {
|
|
31
|
+
return {
|
|
38
32
|
contained: {
|
|
39
|
-
|
|
40
|
-
border: 'none',
|
|
33
|
+
borderWidth: 0,
|
|
41
34
|
},
|
|
42
35
|
outlined: {
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
borderWidth: 2,
|
|
37
|
+
borderStyle: 'solid' ,
|
|
38
|
+
backgroundColor: 'transparent',
|
|
45
39
|
},
|
|
46
40
|
text: {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
disabled: {
|
|
52
|
-
true: {
|
|
53
|
-
opacity: 0.6,
|
|
54
|
-
},
|
|
55
|
-
false: {
|
|
56
|
-
opacity: 1,
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
// Dynamically generated compound variants for outlined and text variants
|
|
62
|
-
compoundVariants: generateButtonCompoundVariants(theme),
|
|
63
|
-
|
|
64
|
-
// Web-specific styles
|
|
65
|
-
_web: {
|
|
66
|
-
cursor: 'pointer',
|
|
67
|
-
outline: 'none',
|
|
68
|
-
display: 'flex',
|
|
69
|
-
boxSizing: 'border-box',
|
|
70
|
-
userSelect: 'none',
|
|
71
|
-
// Fix for Chromium-based browsers (Brave, Chrome) border rendering
|
|
72
|
-
WebkitAppearance: 'none',
|
|
73
|
-
MozAppearance: 'none',
|
|
74
|
-
appearance: 'none',
|
|
75
|
-
backfaceVisibility: 'hidden',
|
|
76
|
-
WebkitBackfaceVisibility: 'hidden',
|
|
77
|
-
transform: 'translateZ(0)', // Force hardware acceleration
|
|
78
|
-
_hover: {
|
|
79
|
-
opacity: 0.9,
|
|
80
|
-
},
|
|
81
|
-
_active: {
|
|
82
|
-
transform: 'scale(0.98) translateZ(0)', // Maintain hardware acceleration
|
|
83
|
-
},
|
|
84
|
-
_focus: {
|
|
85
|
-
outlineOffset: '2px',
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
// Separate text style for React Native (no borders, just text properties)
|
|
91
|
-
text: {
|
|
92
|
-
fontWeight: '600',
|
|
93
|
-
textAlign: 'center',
|
|
94
|
-
|
|
95
|
-
variants: {
|
|
96
|
-
size: {
|
|
97
|
-
small: {
|
|
98
|
-
fontSize: 14,
|
|
99
|
-
},
|
|
100
|
-
medium: {
|
|
101
|
-
fontSize: 16,
|
|
102
|
-
},
|
|
103
|
-
large: {
|
|
104
|
-
fontSize: 18,
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
intent: {
|
|
108
|
-
primary: {
|
|
109
|
-
color: theme.intents?.primary?.on || '#ffffff',
|
|
110
|
-
},
|
|
111
|
-
success: {
|
|
112
|
-
color: theme.intents?.success?.on || '#ffffff',
|
|
113
|
-
},
|
|
114
|
-
error: {
|
|
115
|
-
color: theme.intents?.error?.on || '#ffffff',
|
|
116
|
-
},
|
|
117
|
-
warning: {
|
|
118
|
-
color: theme.intents?.warning?.on || '#ffffff',
|
|
119
|
-
},
|
|
120
|
-
neutral: {
|
|
121
|
-
color: theme.intents?.neutral?.on || '#ffffff',
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
variant: {
|
|
125
|
-
contained: {},
|
|
126
|
-
outlined: {},
|
|
127
|
-
text: {},
|
|
128
|
-
},
|
|
129
|
-
disabled: {
|
|
130
|
-
true: {
|
|
131
|
-
opacity: 0.6,
|
|
132
|
-
},
|
|
133
|
-
false: {
|
|
134
|
-
opacity: 1,
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
// Compound variants for text colors in different variants
|
|
140
|
-
compoundVariants: [
|
|
141
|
-
// Outlined variant text colors
|
|
142
|
-
{
|
|
143
|
-
variant: 'outlined',
|
|
144
|
-
intent: 'primary',
|
|
145
|
-
styles: {
|
|
146
|
-
color: theme.intents?.primary?.main || '#3b82f6',
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
variant: 'outlined',
|
|
151
|
-
intent: 'success',
|
|
152
|
-
styles: {
|
|
153
|
-
color: theme.intents?.success?.main || '#22c55e',
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
variant: 'outlined',
|
|
158
|
-
intent: 'error',
|
|
159
|
-
styles: {
|
|
160
|
-
color: theme.intents?.error?.main || '#ef4444',
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
variant: 'outlined',
|
|
165
|
-
intent: 'warning',
|
|
166
|
-
styles: {
|
|
167
|
-
color: theme.intents?.warning?.main || '#f59e0b',
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
variant: 'outlined',
|
|
172
|
-
intent: 'neutral',
|
|
173
|
-
styles: {
|
|
174
|
-
color: theme.intents?.neutral?.main || '#6b7280',
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
// Text variant text colors
|
|
178
|
-
{
|
|
179
|
-
variant: 'text',
|
|
180
|
-
intent: 'primary',
|
|
181
|
-
styles: {
|
|
182
|
-
color: theme.intents?.primary?.main || '#3b82f6',
|
|
41
|
+
borderWidth: 0,
|
|
42
|
+
backgroundColor: 'transparent',
|
|
183
43
|
},
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
intent
|
|
195
|
-
|
|
196
|
-
|
|
44
|
+
} as const;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Create compound variants for intent+type combinations
|
|
49
|
+
*/
|
|
50
|
+
function createButtonCompoundVariants(theme: Theme): CompoundVariants<keyof ButtonVariants> {
|
|
51
|
+
const compoundVariants: CompoundVariants<keyof ButtonVariants> = [];
|
|
52
|
+
|
|
53
|
+
for (const intent in theme.intents) {
|
|
54
|
+
const intentValue = theme.intents[intent];
|
|
55
|
+
|
|
56
|
+
// Contained + intent
|
|
57
|
+
compoundVariants.push({
|
|
58
|
+
intent,
|
|
59
|
+
type: 'contained',
|
|
60
|
+
styles: {
|
|
61
|
+
backgroundColor: intentValue.primary,
|
|
62
|
+
color: intentValue.contrast,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Outlined + intent
|
|
67
|
+
compoundVariants.push({
|
|
68
|
+
intent,
|
|
69
|
+
type: 'outlined',
|
|
70
|
+
styles: {
|
|
71
|
+
color: intentValue.primary,
|
|
72
|
+
borderColor: intentValue.primary,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Text + intent
|
|
77
|
+
compoundVariants.push({
|
|
78
|
+
intent,
|
|
79
|
+
type: 'text',
|
|
80
|
+
styles: {
|
|
81
|
+
color: intentValue.primary,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return compoundVariants;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Create icon compound variants for intent+type combinations
|
|
91
|
+
*/
|
|
92
|
+
function createIconCompoundVariants(theme: Theme): CompoundVariants<keyof ButtonVariants> {
|
|
93
|
+
const compoundVariants: CompoundVariants<keyof ButtonVariants> = [];
|
|
94
|
+
|
|
95
|
+
for (const intent in theme.intents) {
|
|
96
|
+
const intentValue = theme.intents[intent as Intent];
|
|
97
|
+
|
|
98
|
+
// Contained + intent
|
|
99
|
+
compoundVariants.push({
|
|
100
|
+
intent,
|
|
101
|
+
type: 'contained',
|
|
102
|
+
styles: { color: intentValue.contrast },
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Outlined + intent
|
|
106
|
+
compoundVariants.push({
|
|
107
|
+
intent,
|
|
108
|
+
type: 'outlined',
|
|
109
|
+
styles: { color: intentValue.primary },
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Text + intent
|
|
113
|
+
compoundVariants.push({
|
|
114
|
+
intent,
|
|
115
|
+
type: 'text',
|
|
116
|
+
styles: { color: intentValue.primary },
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return compoundVariants;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Create icon color variants dynamically based on theme, intent, and type
|
|
125
|
+
*/
|
|
126
|
+
function createIconColorVariants(theme: Theme, intent: Intent) {
|
|
127
|
+
const intentValue = theme.intents[intent];
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
contained: {
|
|
131
|
+
color: intentValue.contrast,
|
|
197
132
|
},
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
variant: 'text',
|
|
201
|
-
intent: 'warning',
|
|
202
|
-
styles: {
|
|
203
|
-
color: theme.intents?.warning?.main || '#f59e0b',
|
|
133
|
+
outlined: {
|
|
134
|
+
color: intentValue.primary,
|
|
204
135
|
},
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
variant: 'text',
|
|
208
|
-
intent: 'neutral',
|
|
209
|
-
styles: {
|
|
210
|
-
color: theme.intents?.neutral?.main || '#6b7280',
|
|
136
|
+
text: {
|
|
137
|
+
color: intentValue.primary,
|
|
211
138
|
},
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
139
|
+
} as const;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Generate button icon styles
|
|
144
|
+
*/
|
|
145
|
+
const createButtonIconStyles = (theme: Theme) => {
|
|
146
|
+
return ({ intent }: Partial<ButtonVariants>) => {
|
|
147
|
+
return {
|
|
148
|
+
display: 'flex',
|
|
149
|
+
alignItems: 'center',
|
|
150
|
+
justifyContent: 'center',
|
|
151
|
+
variants: {
|
|
152
|
+
size: buildSizeVariants(theme, 'button', size => ({
|
|
153
|
+
width: size.iconSize,
|
|
154
|
+
height: size.iconSize,
|
|
155
|
+
})),
|
|
156
|
+
type: createIconColorVariants(theme, intent),
|
|
157
|
+
},
|
|
158
|
+
} as const;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Generate button text styles
|
|
164
|
+
*/
|
|
165
|
+
const createButtonTextStyles = (theme: Theme) => {
|
|
166
|
+
return ({ intent }: Partial<ButtonVariants>) => {
|
|
167
|
+
return {
|
|
168
|
+
fontWeight: '600',
|
|
169
|
+
textAlign: 'center',
|
|
170
|
+
variants: {
|
|
171
|
+
size: buildSizeVariants(theme, 'button', size => ({
|
|
172
|
+
fontSize: size.fontSize,
|
|
173
|
+
})),
|
|
174
|
+
type: createIconColorVariants(theme, intent), // Text uses same colors as icons
|
|
175
|
+
disabled: {
|
|
176
|
+
true: { opacity: 0.6 },
|
|
177
|
+
false: { opacity: 1 },
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
} as const;
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
|
|
185
|
+
// transform on native cannot resolve function calls to extract variant structures.
|
|
186
|
+
export const buttonStyles = StyleSheet.create((theme: Theme) => {
|
|
187
|
+
return {
|
|
188
|
+
button: {
|
|
189
|
+
alignItems: 'center',
|
|
190
|
+
justifyContent: 'center',
|
|
191
|
+
borderRadius: 8,
|
|
192
|
+
fontWeight: '600',
|
|
193
|
+
textAlign: 'center',
|
|
194
|
+
_web: {
|
|
195
|
+
display: 'flex',
|
|
196
|
+
transition: 'all 0.1s ease',
|
|
197
|
+
},
|
|
198
|
+
variants: {
|
|
199
|
+
size: buildSizeVariants(theme, 'button', size => ({
|
|
200
|
+
paddingVertical: size.paddingVertical,
|
|
201
|
+
paddingHorizontal: size.paddingHorizontal,
|
|
202
|
+
minHeight: size.minHeight,
|
|
203
|
+
})),
|
|
204
|
+
type: createTypeVariants(theme),
|
|
205
|
+
disabled: {
|
|
206
|
+
true: { opacity: 0.6 },
|
|
207
|
+
false: { opacity: 1, _web: {
|
|
208
|
+
cursor: 'pointer',
|
|
209
|
+
_hover: {
|
|
210
|
+
opacity: 0.90,
|
|
211
|
+
},
|
|
212
|
+
_active: {
|
|
213
|
+
opacity: 0.75,
|
|
214
|
+
},
|
|
215
|
+
} },
|
|
216
|
+
} as const,
|
|
217
|
+
} as const,
|
|
218
|
+
compoundVariants: createButtonCompoundVariants(theme),
|
|
219
|
+
} as const,
|
|
220
|
+
icon: {
|
|
221
|
+
display: 'flex',
|
|
222
|
+
alignItems: 'center',
|
|
223
|
+
justifyContent: 'center',
|
|
224
|
+
variants: {
|
|
225
|
+
size: buildSizeVariants(theme, 'button', size => ({
|
|
226
|
+
width: size.iconSize,
|
|
227
|
+
height: size.iconSize,
|
|
228
|
+
})),
|
|
229
|
+
intent: createIntentVariants(theme),
|
|
230
|
+
type: createTypeVariants(theme),
|
|
231
|
+
} as const,
|
|
232
|
+
compoundVariants: createIconCompoundVariants(theme),
|
|
233
|
+
} as const,
|
|
234
|
+
iconContainer: {
|
|
235
|
+
display: 'flex',
|
|
236
|
+
flexDirection: 'row',
|
|
237
|
+
alignItems: 'center',
|
|
238
|
+
justifyContent: 'center',
|
|
239
|
+
gap: 4,
|
|
240
|
+
} as const,
|
|
241
|
+
text: {
|
|
242
|
+
fontWeight: '600',
|
|
243
|
+
textAlign: 'center',
|
|
244
|
+
variants: {
|
|
245
|
+
size: buildSizeVariants(theme, 'button', size => ({
|
|
246
|
+
fontSize: size.fontSize,
|
|
247
|
+
})),
|
|
248
|
+
intent: createIntentVariants(theme),
|
|
249
|
+
type: createTypeVariants(theme),
|
|
250
|
+
disabled: {
|
|
251
|
+
true: { opacity: 0.6 },
|
|
252
|
+
false: { opacity: 1 },
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
compoundVariants: createIconCompoundVariants(theme), // Text uses same colors as icons
|
|
256
|
+
} as const,
|
|
257
|
+
};
|
|
258
|
+
});
|
|
@@ -1,56 +1,113 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { isValidElement, forwardRef } from 'react';
|
|
2
2
|
import { getWebProps } from 'react-native-unistyles/web';
|
|
3
3
|
import { ButtonProps } from './types';
|
|
4
4
|
import { buttonStyles } from './Button.styles';
|
|
5
|
+
import { IconSvg } from '../Icon/IconSvg/IconSvg.web';
|
|
6
|
+
import useMergeRefs from '../hooks/useMergeRefs';
|
|
7
|
+
|
|
8
|
+
// Extended props to include path props added by Babel plugin
|
|
9
|
+
interface InternalButtonProps extends ButtonProps {
|
|
10
|
+
leftIconPath?: string;
|
|
11
|
+
rightIconPath?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const Button = forwardRef<HTMLButtonElement, ButtonProps>((props: InternalButtonProps, ref) => {
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
title,
|
|
18
|
+
children,
|
|
19
|
+
onPress,
|
|
20
|
+
disabled = false,
|
|
21
|
+
type = 'contained',
|
|
22
|
+
intent = 'primary',
|
|
23
|
+
size = 'md',
|
|
24
|
+
leftIcon,
|
|
25
|
+
rightIcon,
|
|
26
|
+
leftIconPath,
|
|
27
|
+
rightIconPath,
|
|
28
|
+
style,
|
|
29
|
+
testID,
|
|
30
|
+
} = props;
|
|
31
|
+
|
|
32
|
+
buttonStyles.useVariants({
|
|
33
|
+
type,
|
|
34
|
+
intent,
|
|
35
|
+
size,
|
|
36
|
+
disabled
|
|
37
|
+
});
|
|
5
38
|
|
|
6
|
-
const Button: React.FC<ButtonProps> = ({
|
|
7
|
-
title,
|
|
8
|
-
children,
|
|
9
|
-
onPress,
|
|
10
|
-
disabled = false,
|
|
11
|
-
variant = 'contained',
|
|
12
|
-
intent = 'primary',
|
|
13
|
-
size = 'medium',
|
|
14
|
-
style,
|
|
15
|
-
testID,
|
|
16
|
-
}) => {
|
|
17
39
|
const handleClick = () => {
|
|
18
40
|
if (!disabled && onPress) {
|
|
19
41
|
onPress();
|
|
20
42
|
}
|
|
21
43
|
};
|
|
22
44
|
|
|
23
|
-
//
|
|
24
|
-
buttonStyles.useVariants({
|
|
25
|
-
size: size as 'small' | 'medium' | 'large',
|
|
26
|
-
intent: intent as 'primary' | 'success' | 'error' | 'warning' | 'neutral',
|
|
27
|
-
variant: variant as 'contained' | 'outlined' | 'text',
|
|
28
|
-
disabled: disabled as boolean,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// Create the style array following the official documentation pattern
|
|
45
|
+
// Compute dynamic styles
|
|
32
46
|
const buttonStyleArray = [
|
|
33
47
|
buttonStyles.button,
|
|
34
|
-
buttonStyles.text,
|
|
35
|
-
style,
|
|
48
|
+
buttonStyles.text,
|
|
49
|
+
style as any,
|
|
36
50
|
];
|
|
37
51
|
|
|
38
52
|
// Use getWebProps to generate className and ref for web
|
|
39
53
|
const webProps = getWebProps(buttonStyleArray);
|
|
40
54
|
|
|
55
|
+
// Icon container styles
|
|
56
|
+
const iconContainerProps = getWebProps([buttonStyles.iconContainer]);
|
|
57
|
+
|
|
58
|
+
// Icon styles with dynamic function
|
|
59
|
+
const iconStyleArray = [buttonStyles.icon];
|
|
60
|
+
const iconProps = getWebProps(iconStyleArray);
|
|
61
|
+
|
|
62
|
+
// Helper to render icon
|
|
63
|
+
const renderIcon = (icon: string | React.ReactNode, iconPath?: string) => {
|
|
64
|
+
if (typeof icon === 'string' && iconPath) {
|
|
65
|
+
// Render IconSvg directly with the path from Babel plugin
|
|
66
|
+
// Don't pass size - let the style control the dimensions
|
|
67
|
+
return (
|
|
68
|
+
<IconSvg
|
|
69
|
+
path={iconPath}
|
|
70
|
+
{...iconProps}
|
|
71
|
+
aria-label={icon}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
} else if (isValidElement(icon)) {
|
|
75
|
+
// Render custom component as-is
|
|
76
|
+
return icon;
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
};
|
|
80
|
+
|
|
41
81
|
// Use children if available, otherwise use title
|
|
42
82
|
const buttonContent = children || title;
|
|
43
83
|
|
|
84
|
+
// Determine if we need to wrap content in icon container
|
|
85
|
+
const hasIcons = leftIcon || rightIcon;
|
|
86
|
+
|
|
87
|
+
// Merge unistyles web ref with forwarded ref
|
|
88
|
+
const mergedRef = useMergeRefs(ref, webProps.ref);
|
|
89
|
+
|
|
44
90
|
return (
|
|
45
91
|
<button
|
|
46
92
|
{...webProps}
|
|
93
|
+
ref={mergedRef}
|
|
47
94
|
onClick={handleClick}
|
|
48
95
|
disabled={disabled}
|
|
49
96
|
data-testid={testID}
|
|
50
97
|
>
|
|
51
|
-
{
|
|
98
|
+
{hasIcons ? (
|
|
99
|
+
<div {...iconContainerProps}>
|
|
100
|
+
{leftIcon && renderIcon(leftIcon, leftIconPath)}
|
|
101
|
+
{buttonContent}
|
|
102
|
+
{rightIcon && renderIcon(rightIcon, rightIconPath)}
|
|
103
|
+
</div>
|
|
104
|
+
) : (
|
|
105
|
+
buttonContent
|
|
106
|
+
)}
|
|
52
107
|
</button>
|
|
53
108
|
);
|
|
54
|
-
};
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
Button.displayName = 'Button';
|
|
55
112
|
|
|
56
113
|
export default Button;
|
package/src/Button/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
export * from './types';
|
|
1
|
+
import ButtonComponent from './Button.web';
|
|
2
|
+
|
|
3
|
+
export default ButtonComponent;
|
|
4
|
+
export { ButtonComponent as Button };
|
|
5
|
+
export * from './types';
|
package/src/Button/index.web.ts
CHANGED
package/src/Button/types.ts
CHANGED
|
@@ -1,47 +1,64 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
import type { IconName } from '../Icon/icon-types';
|
|
4
|
+
import { Intent, Size } from '@idealyst/theme';
|
|
5
|
+
|
|
6
|
+
// Component-specific type aliases for future extensibility
|
|
7
|
+
export type ButtonType = 'contained' | 'outlined' | 'text';
|
|
8
|
+
export type ButtonIntentVariant = Intent;
|
|
9
|
+
export type ButtonSizeVariant = Size;
|
|
3
10
|
|
|
4
11
|
export interface ButtonProps {
|
|
5
12
|
/**
|
|
6
13
|
* The text or content to display inside the button
|
|
7
14
|
*/
|
|
8
15
|
children?: ReactNode;
|
|
9
|
-
|
|
16
|
+
|
|
10
17
|
/**
|
|
11
18
|
* The text title to display inside the button (for web)
|
|
12
19
|
*/
|
|
13
20
|
title?: string;
|
|
14
|
-
|
|
21
|
+
|
|
15
22
|
/**
|
|
16
23
|
* Called when the button is pressed
|
|
17
24
|
*/
|
|
18
25
|
onPress?: () => void;
|
|
19
|
-
|
|
26
|
+
|
|
20
27
|
/**
|
|
21
28
|
* Whether the button is disabled
|
|
22
29
|
*/
|
|
23
30
|
disabled?: boolean;
|
|
24
|
-
|
|
31
|
+
|
|
25
32
|
/**
|
|
26
|
-
* The visual style
|
|
33
|
+
* The visual style type of the button
|
|
27
34
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
type?: ButtonType;
|
|
36
|
+
|
|
30
37
|
/**
|
|
31
38
|
* The intent/color scheme of the button
|
|
32
39
|
*/
|
|
33
|
-
intent?:
|
|
34
|
-
|
|
40
|
+
intent?: ButtonIntentVariant;
|
|
41
|
+
|
|
35
42
|
/**
|
|
36
43
|
* The size of the button
|
|
37
44
|
*/
|
|
38
|
-
size?:
|
|
39
|
-
|
|
45
|
+
size?: ButtonSizeVariant;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Icon to display on the left side. Can be an icon name or custom component (ReactNode)
|
|
49
|
+
*/
|
|
50
|
+
leftIcon?: IconName | ReactNode;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Icon to display on the right side. Can be an icon name or custom component (ReactNode)
|
|
54
|
+
*/
|
|
55
|
+
rightIcon?: IconName | ReactNode;
|
|
56
|
+
|
|
40
57
|
/**
|
|
41
58
|
* Additional styles (platform-specific)
|
|
42
59
|
*/
|
|
43
|
-
style?:
|
|
44
|
-
|
|
60
|
+
style?: StyleProp<ViewStyle>;
|
|
61
|
+
|
|
45
62
|
/**
|
|
46
63
|
* Test ID for testing
|
|
47
64
|
*/
|