@idealyst/components 1.1.6 → 1.1.7
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/package.json +8 -3
- package/src/Accordion/Accordion.native.tsx +15 -9
- package/src/Accordion/Accordion.styles.tsx +193 -168
- package/src/Accordion/Accordion.web.tsx +12 -7
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -2
- package/src/ActivityIndicator/ActivityIndicator.styles.tsx +22 -11
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +2 -2
- package/src/Alert/Alert.native.tsx +11 -10
- package/src/Alert/Alert.styles.tsx +162 -253
- package/src/Alert/Alert.web.tsx +6 -10
- package/src/Avatar/Avatar.native.tsx +5 -2
- package/src/Avatar/Avatar.styles.tsx +48 -18
- package/src/Avatar/Avatar.web.tsx +2 -2
- package/src/Badge/Badge.native.tsx +2 -2
- package/src/Badge/Badge.styles.tsx +37 -16
- package/src/Badge/Badge.web.tsx +6 -6
- package/src/Breadcrumb/Breadcrumb.native.tsx +12 -5
- package/src/Breadcrumb/Breadcrumb.styles.tsx +59 -58
- package/src/Breadcrumb/Breadcrumb.web.tsx +13 -6
- package/src/Button/Button.native.tsx +39 -14
- package/src/Button/Button.styles.tsx +106 -208
- package/src/Button/Button.web.tsx +10 -8
- package/src/Card/Card.native.tsx +14 -6
- package/src/Card/Card.styles.tsx +64 -62
- package/src/Card/Card.web.tsx +5 -4
- package/src/Checkbox/Checkbox.native.tsx +7 -3
- package/src/Checkbox/Checkbox.styles.tsx +49 -25
- package/src/Checkbox/Checkbox.web.tsx +3 -3
- package/src/Chip/Chip.native.tsx +5 -5
- package/src/Chip/Chip.styles.tsx +71 -21
- package/src/Chip/Chip.web.tsx +5 -5
- package/src/Dialog/Dialog.native.tsx +10 -4
- package/src/Dialog/Dialog.styles.tsx +130 -90
- package/src/Dialog/Dialog.web.tsx +4 -4
- package/src/Divider/Divider.native.tsx +29 -42
- package/src/Divider/Divider.styles.tsx +138 -242
- package/src/Divider/Divider.web.tsx +17 -14
- package/src/Icon/Icon.native.tsx +11 -3
- package/src/Icon/Icon.styles.tsx +10 -4
- package/src/Image/Image.styles.tsx +53 -37
- package/src/Input/Input.native.tsx +6 -7
- package/src/Input/Input.styles.tsx +194 -174
- package/src/Input/Input.web.tsx +5 -8
- package/src/Link/Link.native.tsx +4 -1
- package/src/List/List.styles.tsx +79 -105
- package/src/List/ListItem.native.tsx +5 -3
- package/src/List/ListItem.web.tsx +4 -3
- package/src/Menu/Menu.native.tsx +1 -1
- package/src/Menu/Menu.styles.tsx +53 -37
- package/src/Menu/Menu.web.tsx +2 -2
- package/src/Menu/MenuItem.native.tsx +5 -3
- package/src/Menu/MenuItem.styles.tsx +68 -69
- package/src/Menu/MenuItem.web.tsx +16 -3
- package/src/Popover/Popover.native.tsx +1 -1
- package/src/Popover/Popover.styles.tsx +40 -29
- package/src/Popover/Popover.web.tsx +1 -1
- package/src/Pressable/Pressable.native.tsx +3 -1
- package/src/Pressable/Pressable.styles.tsx +20 -13
- package/src/Pressable/Pressable.web.tsx +1 -1
- package/src/Progress/Progress.native.tsx +15 -6
- package/src/Progress/Progress.styles.tsx +125 -85
- package/src/Progress/Progress.web.tsx +10 -9
- package/src/RadioButton/RadioButton.native.tsx +8 -3
- package/src/RadioButton/RadioButton.styles.tsx +44 -37
- package/src/RadioButton/RadioButton.web.tsx +3 -3
- package/src/SVGImage/SVGImage.styles.tsx +28 -16
- package/src/Screen/Screen.native.tsx +23 -13
- package/src/Screen/Screen.styles.tsx +57 -46
- package/src/Screen/Screen.web.tsx +1 -1
- package/src/Select/Select.native.tsx +11 -5
- package/src/Select/Select.styles.tsx +72 -52
- package/src/Select/Select.web.tsx +5 -5
- package/src/Skeleton/Skeleton.styles.tsx +26 -14
- package/src/Slider/Slider.native.tsx +9 -5
- package/src/Slider/Slider.styles.tsx +59 -48
- package/src/Slider/Slider.web.tsx +5 -5
- package/src/Switch/Switch.native.tsx +6 -2
- package/src/Switch/Switch.styles.tsx +46 -19
- package/src/Switch/Switch.web.tsx +4 -4
- package/src/TabBar/TabBar.native.tsx +23 -31
- package/src/TabBar/TabBar.styles.tsx +215 -371
- package/src/TabBar/TabBar.web.tsx +21 -33
- package/src/Table/Table.native.tsx +1 -1
- package/src/Table/Table.styles.tsx +11 -4
- package/src/Table/Table.web.tsx +1 -1
- package/src/Text/Text.native.tsx +3 -4
- package/src/Text/Text.styles.tsx +7 -1
- package/src/Text/Text.web.tsx +1 -1
- package/src/TextArea/TextArea.styles.tsx +90 -58
- package/src/Tooltip/Tooltip.native.tsx +2 -2
- package/src/Tooltip/Tooltip.styles.tsx +21 -12
- package/src/Tooltip/Tooltip.web.tsx +2 -2
- package/src/Video/Video.styles.tsx +39 -23
- package/src/View/View.native.tsx +4 -2
- package/src/View/View.styles.tsx +33 -22
- package/src/View/View.web.tsx +13 -2
- package/src/extensions/applyExtension.ts +210 -0
- package/src/extensions/extendComponent.ts +377 -0
- package/src/extensions/index.ts +102 -0
- package/src/extensions/types.ts +497 -0
- package/src/globals.ts +16 -0
- package/src/index.native.ts +4 -0
- package/src/index.ts +28 -0
- package/src/utils/deepMerge.ts +54 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
2
|
import { Theme, StylesheetStyles} from '@idealyst/theme';
|
|
3
|
+
import { applyExtensions } from '../extensions/applyExtension';
|
|
3
4
|
|
|
4
5
|
type ImageVariants = {}
|
|
5
6
|
|
|
@@ -13,45 +14,60 @@ export type ImageStylesheet = {
|
|
|
13
14
|
loadingIndicator: ExpandedImageStyles;
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
// Style creators for extension support
|
|
18
|
+
function createContainerStyles(theme: Theme) {
|
|
19
|
+
return () => ({
|
|
20
|
+
position: 'relative' as const,
|
|
21
|
+
overflow: 'hidden' as const,
|
|
22
|
+
backgroundColor: theme.colors['gray.200'],
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function createImageStyles() {
|
|
27
|
+
return () => ({
|
|
28
|
+
width: '100%' as const,
|
|
29
|
+
height: '100%' as const,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
16
33
|
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
|
|
17
34
|
// transform on native cannot resolve function calls to extract variant structures.
|
|
18
35
|
// @ts-ignore - TS language server needs restart to pick up theme structure changes
|
|
19
36
|
export const imageStyles = StyleSheet.create((theme: Theme) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
};
|
|
37
|
+
// Apply extensions to main visual elements
|
|
38
|
+
const extended = applyExtensions('Image', theme, {
|
|
39
|
+
container: createContainerStyles(theme),
|
|
40
|
+
image: createImageStyles(),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
...extended,
|
|
45
|
+
// Minor utility styles (not extended)
|
|
46
|
+
placeholder: {
|
|
47
|
+
position: 'absolute',
|
|
48
|
+
top: 0,
|
|
49
|
+
left: 0,
|
|
50
|
+
right: 0,
|
|
51
|
+
bottom: 0,
|
|
52
|
+
display: 'flex',
|
|
53
|
+
alignItems: 'center',
|
|
54
|
+
justifyContent: 'center',
|
|
55
|
+
backgroundColor: theme.colors['gray.200'],
|
|
56
|
+
},
|
|
57
|
+
fallback: {
|
|
58
|
+
position: 'absolute',
|
|
59
|
+
top: 0,
|
|
60
|
+
left: 0,
|
|
61
|
+
right: 0,
|
|
62
|
+
bottom: 0,
|
|
63
|
+
display: 'flex',
|
|
64
|
+
alignItems: 'center',
|
|
65
|
+
justifyContent: 'center',
|
|
66
|
+
backgroundColor: theme.colors['gray.300'],
|
|
67
|
+
color: theme.colors['gray.600'],
|
|
68
|
+
},
|
|
69
|
+
loadingIndicator: {
|
|
70
|
+
color: theme.colors['gray.600'],
|
|
71
|
+
},
|
|
72
|
+
};
|
|
57
73
|
});
|
|
@@ -82,18 +82,17 @@ const Input = React.forwardRef<TextInput, InputProps>(({
|
|
|
82
82
|
setIsPasswordVisible(!isPasswordVisible);
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
-
// Apply variants to the stylesheet
|
|
85
|
+
// Apply variants to the stylesheet (for size and spacing)
|
|
86
86
|
inputStyles.useVariants({
|
|
87
87
|
size,
|
|
88
|
-
type,
|
|
89
|
-
focused: isFocused,
|
|
90
|
-
hasError,
|
|
91
|
-
disabled,
|
|
92
88
|
margin,
|
|
93
89
|
marginVertical,
|
|
94
90
|
marginHorizontal,
|
|
95
91
|
});
|
|
96
92
|
|
|
93
|
+
// Compute dynamic container styles
|
|
94
|
+
const containerStyle = (inputStyles.container as any)({ type, focused: isFocused, hasError, disabled });
|
|
95
|
+
|
|
97
96
|
// Generate native accessibility props
|
|
98
97
|
const nativeA11yProps = useMemo(() => {
|
|
99
98
|
// Derive invalid state from hasError or explicit accessibilityInvalid
|
|
@@ -161,7 +160,7 @@ const Input = React.forwardRef<TextInput, InputProps>(({
|
|
|
161
160
|
};
|
|
162
161
|
|
|
163
162
|
return (
|
|
164
|
-
<View style={[
|
|
163
|
+
<View style={[containerStyle, style]} testID={testID} nativeID={id}>
|
|
165
164
|
{/* Left Icon */}
|
|
166
165
|
{leftIcon && (
|
|
167
166
|
<View style={inputStyles.leftIconContainer}>
|
|
@@ -182,7 +181,7 @@ const Input = React.forwardRef<TextInput, InputProps>(({
|
|
|
182
181
|
autoCapitalize={autoCapitalize}
|
|
183
182
|
onFocus={handleFocus}
|
|
184
183
|
onBlur={handleBlur}
|
|
185
|
-
style={inputStyles.input}
|
|
184
|
+
style={(inputStyles.input as any)({})}
|
|
186
185
|
placeholderTextColor="#999999"
|
|
187
186
|
{...nativeA11yProps}
|
|
188
187
|
/>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
import { Theme, Size
|
|
2
|
+
import { Theme, Size } from '@idealyst/theme';
|
|
3
3
|
import { buildSizeVariants } from '../utils/buildSizeVariants';
|
|
4
4
|
import {
|
|
5
5
|
buildMarginVariants,
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
buildMarginHorizontalVariants,
|
|
8
8
|
} from '../utils/buildViewStyleVariants';
|
|
9
9
|
import { InputSize, InputType } from './types';
|
|
10
|
+
import { applyExtensions } from '../extensions/applyExtension';
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
export type InputVariants = {
|
|
@@ -17,182 +18,157 @@ export type InputVariants = {
|
|
|
17
18
|
disabled: boolean;
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
type InputDynamicProps = {
|
|
22
|
+
type?: InputType;
|
|
23
|
+
focused?: boolean;
|
|
24
|
+
hasError?: boolean;
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
20
28
|
/**
|
|
21
|
-
*
|
|
29
|
+
* Get container border/background styles based on type, focused, hasError, disabled
|
|
22
30
|
*/
|
|
23
|
-
function
|
|
31
|
+
function getContainerDynamicStyles(theme: Theme, props: InputDynamicProps) {
|
|
32
|
+
const { type = 'outlined', focused = false, hasError = false, disabled = false } = props;
|
|
33
|
+
const focusColor = theme.intents.primary.primary;
|
|
34
|
+
const errorColor = theme.intents.error.primary;
|
|
35
|
+
|
|
36
|
+
// Base styles by type
|
|
37
|
+
let backgroundColor = 'transparent';
|
|
38
|
+
let borderWidth = 1;
|
|
39
|
+
let borderColor = theme.colors.border.primary;
|
|
40
|
+
let borderStyle = 'solid' as const;
|
|
41
|
+
|
|
42
|
+
if (type === 'filled') {
|
|
43
|
+
backgroundColor = theme.colors.surface.secondary;
|
|
44
|
+
borderWidth = 0;
|
|
45
|
+
} else if (type === 'bare') {
|
|
46
|
+
backgroundColor = 'transparent';
|
|
47
|
+
borderWidth = 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Error state takes precedence
|
|
51
|
+
if (hasError) {
|
|
52
|
+
borderColor = errorColor;
|
|
53
|
+
borderWidth = 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Focus state (error still takes precedence for color)
|
|
57
|
+
if (focused && !hasError) {
|
|
58
|
+
borderColor = focusColor;
|
|
59
|
+
borderWidth = 1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Disabled state
|
|
63
|
+
if (disabled) {
|
|
64
|
+
backgroundColor = theme.colors.surface.secondary;
|
|
65
|
+
}
|
|
66
|
+
|
|
24
67
|
return {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
_web: {
|
|
31
|
-
border: `1px solid ${theme.colors.border.primary}`,
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
filled: {
|
|
35
|
-
backgroundColor: theme.colors.surface.secondary,
|
|
36
|
-
borderWidth: 0,
|
|
37
|
-
_web: {
|
|
38
|
-
border: 'none',
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
bare: {
|
|
42
|
-
backgroundColor: 'transparent',
|
|
43
|
-
borderWidth: 0,
|
|
44
|
-
_web: {
|
|
45
|
-
border: 'none',
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
} as const;
|
|
68
|
+
backgroundColor,
|
|
69
|
+
borderWidth,
|
|
70
|
+
borderColor,
|
|
71
|
+
borderStyle,
|
|
72
|
+
};
|
|
49
73
|
}
|
|
50
74
|
|
|
51
75
|
/**
|
|
52
|
-
* Create
|
|
76
|
+
* Create dynamic container styles
|
|
53
77
|
*/
|
|
54
|
-
function
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
78
|
+
function createContainerStyles(theme: Theme) {
|
|
79
|
+
return (props: InputDynamicProps) => {
|
|
80
|
+
const { type = 'outlined', focused = false, hasError = false, disabled = false } = props;
|
|
81
|
+
const dynamicStyles = getContainerDynamicStyles(theme, props);
|
|
82
|
+
const focusColor = theme.intents.primary.primary;
|
|
83
|
+
const errorColor = theme.intents.error.primary;
|
|
58
84
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
hasError: true,
|
|
63
|
-
styles: {
|
|
64
|
-
borderColor: errorColor,
|
|
65
|
-
_web: {
|
|
66
|
-
border: `1px solid ${errorColor}`,
|
|
67
|
-
boxShadow: `0 0 0 2px ${errorColor}20`,
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
});
|
|
85
|
+
// Web-specific border and shadow
|
|
86
|
+
let webBorder = `1px solid ${dynamicStyles.borderColor}`;
|
|
87
|
+
let webBoxShadow = 'none';
|
|
71
88
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
focused: true,
|
|
76
|
-
hasError: false,
|
|
77
|
-
styles: {
|
|
78
|
-
borderColor: focusColor,
|
|
79
|
-
_web: {
|
|
80
|
-
border: `1px solid ${focusColor}`,
|
|
81
|
-
boxShadow: `0 0 0 2px ${focusColor}20`,
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
});
|
|
89
|
+
if (type === 'filled' || type === 'bare') {
|
|
90
|
+
webBorder = 'none';
|
|
91
|
+
}
|
|
85
92
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
boxShadow: `0 0 0 2px ${focusColor}20`,
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
});
|
|
93
|
+
if (hasError) {
|
|
94
|
+
webBorder = `1px solid ${errorColor}`;
|
|
95
|
+
if (focused) {
|
|
96
|
+
webBoxShadow = `0 0 0 2px ${errorColor}20`;
|
|
97
|
+
}
|
|
98
|
+
} else if (focused) {
|
|
99
|
+
webBorder = `1px solid ${focusColor}`;
|
|
100
|
+
webBoxShadow = `0 0 0 2px ${focusColor}20`;
|
|
101
|
+
}
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
return {
|
|
104
|
+
display: 'flex',
|
|
105
|
+
flexDirection: 'row',
|
|
106
|
+
alignItems: 'center',
|
|
107
|
+
width: '100%',
|
|
108
|
+
minWidth: 0,
|
|
109
|
+
borderRadius: 8,
|
|
110
|
+
...dynamicStyles,
|
|
111
|
+
opacity: disabled ? 0.6 : 1,
|
|
112
|
+
variants: {
|
|
113
|
+
size: buildSizeVariants(theme, 'input', (size) => ({
|
|
114
|
+
height: size.height,
|
|
115
|
+
paddingHorizontal: size.paddingHorizontal,
|
|
116
|
+
})),
|
|
117
|
+
// Spacing variants from FormInputStyleProps
|
|
118
|
+
margin: buildMarginVariants(theme),
|
|
119
|
+
marginVertical: buildMarginVerticalVariants(theme),
|
|
120
|
+
marginHorizontal: buildMarginHorizontalVariants(theme),
|
|
121
|
+
},
|
|
106
122
|
_web: {
|
|
107
|
-
|
|
123
|
+
boxSizing: 'border-box',
|
|
124
|
+
transition: 'border-color 0.2s ease, box-shadow 0.2s ease',
|
|
125
|
+
border: webBorder,
|
|
126
|
+
boxShadow: webBoxShadow,
|
|
127
|
+
cursor: disabled ? 'not-allowed' : 'text',
|
|
108
128
|
},
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return compoundVariants;
|
|
129
|
+
} as const;
|
|
130
|
+
};
|
|
113
131
|
}
|
|
114
132
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
display: 'flex',
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
width: '100%',
|
|
124
|
-
minWidth: 0,
|
|
125
|
-
borderRadius: 8,
|
|
126
|
-
variants: {
|
|
127
|
-
size: buildSizeVariants(theme, 'input', (size) => ({
|
|
128
|
-
height: size.height,
|
|
129
|
-
paddingHorizontal: size.paddingHorizontal,
|
|
130
|
-
})),
|
|
131
|
-
type: createContainerTypeVariants(theme),
|
|
132
|
-
focused: {
|
|
133
|
-
true: {},
|
|
134
|
-
false: {},
|
|
135
|
-
},
|
|
136
|
-
hasError: {
|
|
137
|
-
true: {
|
|
138
|
-
borderColor: theme.intents.error.primary,
|
|
139
|
-
_web: {
|
|
140
|
-
border: `1px solid ${theme.intents.error.primary}`,
|
|
141
|
-
},
|
|
142
|
-
},
|
|
143
|
-
false: {},
|
|
144
|
-
},
|
|
145
|
-
disabled: {
|
|
146
|
-
true: {
|
|
147
|
-
opacity: 0.6,
|
|
148
|
-
backgroundColor: theme.colors.surface.secondary,
|
|
149
|
-
_web: {
|
|
150
|
-
cursor: 'not-allowed',
|
|
151
|
-
},
|
|
152
|
-
},
|
|
153
|
-
false: {
|
|
154
|
-
_web: {
|
|
155
|
-
cursor: 'text',
|
|
156
|
-
_hover: {
|
|
157
|
-
borderColor: theme.intents.primary.primary,
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
// Spacing variants from FormInputStyleProps
|
|
163
|
-
margin: buildMarginVariants(theme),
|
|
164
|
-
marginVertical: buildMarginVerticalVariants(theme),
|
|
165
|
-
marginHorizontal: buildMarginHorizontalVariants(theme),
|
|
166
|
-
},
|
|
167
|
-
compoundVariants: createFocusedCompoundVariants(theme),
|
|
168
|
-
_web: {
|
|
169
|
-
boxSizing: 'border-box',
|
|
170
|
-
transition: 'border-color 0.2s ease, box-shadow 0.2s ease',
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
leftIconContainer: {
|
|
174
|
-
display: 'flex',
|
|
175
|
-
alignItems: 'center',
|
|
176
|
-
justifyContent: 'center',
|
|
133
|
+
/**
|
|
134
|
+
* Create left icon container styles
|
|
135
|
+
*/
|
|
136
|
+
function createLeftIconContainerStyles(theme: Theme) {
|
|
137
|
+
return () => ({
|
|
138
|
+
display: 'flex' as const,
|
|
139
|
+
alignItems: 'center' as const,
|
|
140
|
+
justifyContent: 'center' as const,
|
|
177
141
|
flexShrink: 0,
|
|
178
142
|
variants: {
|
|
179
143
|
size: buildSizeVariants(theme, 'input', (size) => ({
|
|
180
144
|
marginRight: size.iconMargin,
|
|
181
145
|
})),
|
|
182
146
|
},
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Create right icon container styles
|
|
152
|
+
*/
|
|
153
|
+
function createRightIconContainerStyles(theme: Theme) {
|
|
154
|
+
return () => ({
|
|
155
|
+
display: 'flex' as const,
|
|
156
|
+
alignItems: 'center' as const,
|
|
157
|
+
justifyContent: 'center' as const,
|
|
188
158
|
flexShrink: 0,
|
|
189
159
|
variants: {
|
|
190
160
|
size: buildSizeVariants(theme, 'input', (size) => ({
|
|
191
161
|
marginLeft: size.iconMargin,
|
|
192
162
|
})),
|
|
193
163
|
},
|
|
194
|
-
}
|
|
195
|
-
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Create left icon styles
|
|
169
|
+
*/
|
|
170
|
+
function createLeftIconStyles(theme: Theme) {
|
|
171
|
+
return () => ({
|
|
196
172
|
color: theme.colors.text.secondary,
|
|
197
173
|
variants: {
|
|
198
174
|
size: buildSizeVariants(theme, 'input', (size) => ({
|
|
@@ -201,25 +177,37 @@ export const inputStyles = StyleSheet.create((theme: Theme) => {
|
|
|
201
177
|
height: size.iconSize,
|
|
202
178
|
})),
|
|
203
179
|
},
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Create right icon styles
|
|
185
|
+
*/
|
|
186
|
+
function createRightIconStyles(theme: Theme) {
|
|
187
|
+
return () => ({
|
|
188
|
+
display: 'flex' as const,
|
|
189
|
+
alignItems: 'center' as const,
|
|
190
|
+
justifyContent: 'center' as const,
|
|
209
191
|
flexShrink: 0,
|
|
210
192
|
color: theme.colors.text.secondary,
|
|
211
193
|
variants: {
|
|
212
194
|
size: buildSizeVariants(theme, 'input', (size) => ({
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
195
|
+
fontSize: size.iconSize,
|
|
196
|
+
width: size.iconSize,
|
|
197
|
+
height: size.iconSize,
|
|
198
|
+
})),
|
|
217
199
|
},
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Create password toggle styles
|
|
205
|
+
*/
|
|
206
|
+
function createPasswordToggleStyles(theme: Theme) {
|
|
207
|
+
return () => ({
|
|
208
|
+
display: 'flex' as const,
|
|
209
|
+
alignItems: 'center' as const,
|
|
210
|
+
justifyContent: 'center' as const,
|
|
223
211
|
flexShrink: 0,
|
|
224
212
|
padding: 0,
|
|
225
213
|
variants: {
|
|
@@ -238,11 +226,17 @@ export const inputStyles = StyleSheet.create((theme: Theme) => {
|
|
|
238
226
|
opacity: 0.5,
|
|
239
227
|
},
|
|
240
228
|
},
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Create password toggle icon styles
|
|
234
|
+
*/
|
|
235
|
+
function createPasswordToggleIconStyles(theme: Theme) {
|
|
236
|
+
return () => ({
|
|
237
|
+
display: 'flex' as const,
|
|
238
|
+
alignItems: 'center' as const,
|
|
239
|
+
justifyContent: 'center' as const,
|
|
246
240
|
flexShrink: 0,
|
|
247
241
|
color: theme.colors.text.secondary,
|
|
248
242
|
variants: {
|
|
@@ -252,13 +246,19 @@ export const inputStyles = StyleSheet.create((theme: Theme) => {
|
|
|
252
246
|
height: size.iconSize,
|
|
253
247
|
})),
|
|
254
248
|
},
|
|
255
|
-
}
|
|
256
|
-
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Create input styles
|
|
254
|
+
*/
|
|
255
|
+
function createInputStyles(theme: Theme) {
|
|
256
|
+
return () => ({
|
|
257
257
|
flex: 1,
|
|
258
258
|
minWidth: 0,
|
|
259
259
|
backgroundColor: 'transparent',
|
|
260
260
|
color: theme.colors.text.primary,
|
|
261
|
-
fontWeight: '400',
|
|
261
|
+
fontWeight: '400' as const,
|
|
262
262
|
variants: {
|
|
263
263
|
size: buildSizeVariants(theme, 'input', (size) => ({
|
|
264
264
|
fontSize: size.fontSize,
|
|
@@ -269,6 +269,26 @@ export const inputStyles = StyleSheet.create((theme: Theme) => {
|
|
|
269
269
|
outline: 'none',
|
|
270
270
|
fontFamily: 'inherit',
|
|
271
271
|
},
|
|
272
|
-
}
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
|
|
276
|
+
// transform on native cannot resolve function calls to extract variant structures.
|
|
277
|
+
export const inputStyles = StyleSheet.create((theme: Theme) => {
|
|
278
|
+
// Apply extensions to main visual elements
|
|
279
|
+
const extended = applyExtensions('Input', theme, {
|
|
280
|
+
container: createContainerStyles(theme),
|
|
281
|
+
input: createInputStyles(theme),
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
...extended,
|
|
286
|
+
// Minor utility styles (not extended)
|
|
287
|
+
leftIconContainer: createLeftIconContainerStyles(theme)(),
|
|
288
|
+
rightIconContainer: createRightIconContainerStyles(theme)(),
|
|
289
|
+
leftIcon: createLeftIconStyles(theme)(),
|
|
290
|
+
rightIcon: createRightIconStyles(theme)(),
|
|
291
|
+
passwordToggle: createPasswordToggleStyles(theme)(),
|
|
292
|
+
passwordToggleIcon: createPasswordToggleIconStyles(theme)(),
|
|
273
293
|
};
|
|
274
|
-
});
|
|
294
|
+
});
|
package/src/Input/Input.web.tsx
CHANGED
|
@@ -111,20 +111,17 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(({
|
|
|
111
111
|
setIsPasswordVisible(!isPasswordVisible);
|
|
112
112
|
};
|
|
113
113
|
|
|
114
|
-
// Apply variants for
|
|
114
|
+
// Apply variants (for size and spacing)
|
|
115
115
|
inputStyles.useVariants({
|
|
116
116
|
size,
|
|
117
|
-
type,
|
|
118
|
-
focused: isFocused,
|
|
119
|
-
hasError,
|
|
120
|
-
disabled,
|
|
121
117
|
margin,
|
|
122
118
|
marginVertical,
|
|
123
119
|
marginHorizontal,
|
|
124
120
|
});
|
|
125
121
|
|
|
126
|
-
// Get web props for all styled elements
|
|
127
|
-
const
|
|
122
|
+
// Get web props for all styled elements (container uses dynamic function)
|
|
123
|
+
const dynamicContainerStyle = (inputStyles.container as any)({ type, focused: isFocused, hasError, disabled });
|
|
124
|
+
const {ref: containerStyleRef, ...containerProps} = getWebProps([dynamicContainerStyle, style]);
|
|
128
125
|
const leftIconContainerProps = getWebProps([inputStyles.leftIconContainer]);
|
|
129
126
|
const rightIconContainerProps = getWebProps([inputStyles.rightIconContainer]);
|
|
130
127
|
const leftIconProps = getWebProps([inputStyles.leftIcon]);
|
|
@@ -133,7 +130,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(({
|
|
|
133
130
|
const passwordToggleIconProps = getWebProps([inputStyles.passwordToggleIcon]);
|
|
134
131
|
|
|
135
132
|
// Get input props
|
|
136
|
-
const inputWebProps = getWebProps([inputStyles.input]);
|
|
133
|
+
const inputWebProps = getWebProps([(inputStyles.input as any)({})]);
|
|
137
134
|
|
|
138
135
|
// Generate accessibility props
|
|
139
136
|
const ariaProps = useMemo(() => {
|
package/src/Link/Link.native.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { useNavigator } from '@idealyst/navigation';
|
|
3
3
|
import { Pressable } from '../Pressable';
|
|
4
4
|
import type { LinkProps } from './types';
|
|
5
|
+
import { Text } from 'react-native';
|
|
5
6
|
|
|
6
7
|
const Link: React.FC<LinkProps> = ({
|
|
7
8
|
to,
|
|
@@ -22,6 +23,8 @@ const Link: React.FC<LinkProps> = ({
|
|
|
22
23
|
onPress?.();
|
|
23
24
|
navigator.navigate({ path: to, vars });
|
|
24
25
|
};
|
|
26
|
+
|
|
27
|
+
console.log("Rendering Link to:", to, "children:", children);
|
|
25
28
|
|
|
26
29
|
return (
|
|
27
30
|
<Pressable
|
|
@@ -33,7 +36,7 @@ const Link: React.FC<LinkProps> = ({
|
|
|
33
36
|
accessibilityLabel={accessibilityLabel}
|
|
34
37
|
accessibilityRole="link"
|
|
35
38
|
>
|
|
36
|
-
{children}
|
|
39
|
+
{typeof children === 'string' ? <Text>{children}</Text> : children}
|
|
37
40
|
</Pressable>
|
|
38
41
|
);
|
|
39
42
|
};
|