@idealyst/components 1.2.29 → 1.2.30
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 +3 -3
- package/package.json +3 -3
- package/plugin/__tests__/web.test.ts +2 -2
- package/src/Accordion/Accordion.native.tsx +3 -2
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -2
- package/src/ActivityIndicator/ActivityIndicator.styles.tsx +25 -26
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +2 -1
- package/src/Alert/Alert.native.tsx +20 -10
- package/src/Alert/Alert.styles.tsx +148 -86
- package/src/Alert/Alert.web.tsx +10 -5
- package/src/Alert/types.ts +53 -3
- package/src/Avatar/Avatar.native.tsx +3 -2
- package/src/Avatar/Avatar.web.tsx +2 -1
- package/src/Avatar/types.ts +1 -1
- package/src/Badge/Badge.native.tsx +18 -6
- package/src/Badge/Badge.styles.tsx +22 -5
- package/src/Badge/Badge.web.tsx +12 -4
- package/src/Badge/types.ts +14 -2
- package/src/Breadcrumb/Breadcrumb.native.tsx +3 -2
- package/src/Button/Button.native.tsx +16 -6
- package/src/Button/Button.styles.tsx +2 -2
- package/src/Button/Button.web.tsx +19 -15
- package/src/Button/types.ts +6 -10
- package/src/Card/Card.native.tsx +27 -3
- package/src/Card/Card.web.tsx +30 -4
- package/src/Card/types.ts +15 -0
- package/src/Checkbox/Checkbox.native.tsx +5 -4
- package/src/Checkbox/Checkbox.styles.tsx +62 -52
- package/src/Checkbox/Checkbox.web.tsx +4 -3
- package/src/Checkbox/types.ts +1 -1
- package/src/Chip/Chip.native.tsx +30 -7
- package/src/Chip/Chip.styles.tsx +142 -124
- package/src/Chip/Chip.web.tsx +28 -5
- package/src/Chip/types.ts +15 -0
- package/src/Dialog/Dialog.native.tsx +6 -6
- package/src/Dialog/Dialog.web.tsx +5 -5
- package/src/Dialog/types.ts +2 -2
- package/src/Divider/Divider.native.tsx +20 -17
- package/src/Divider/Divider.styles.tsx +51 -29
- package/src/Divider/Divider.web.tsx +5 -4
- package/src/Divider/types.ts +3 -3
- package/src/Icon/Icon.native.tsx +3 -2
- package/src/Icon/Icon.web.tsx +2 -1
- package/src/Icon/IconSvg/IconSvg.native.tsx +3 -2
- package/src/Image/Image.native.tsx +3 -2
- package/src/Input/Input.native.tsx +42 -290
- package/src/Input/Input.styles.tsx +1 -1
- package/src/Input/Input.web.tsx +37 -288
- package/src/Input/index.native.ts +9 -2
- package/src/Input/index.ts +8 -1
- package/src/Input/index.web.ts +8 -1
- package/src/Input/types.ts +1 -1
- package/src/List/List.native.tsx +3 -2
- package/src/List/ListItem.native.tsx +3 -2
- package/src/List/ListSection.native.tsx +3 -2
- package/src/Menu/Menu.native.tsx +2 -1
- package/src/Menu/Menu.styles.tsx +79 -29
- package/src/Menu/Menu.web.tsx +2 -1
- package/src/Menu/MenuItem.native.tsx +4 -3
- package/src/Menu/MenuItem.styles.tsx +81 -32
- package/src/Menu/MenuItem.web.tsx +2 -1
- package/src/Menu/docs.ts +1 -1
- package/src/Popover/Popover.native.tsx +2 -1
- package/src/Popover/Popover.web.tsx +2 -1
- package/src/Popover/types.ts +15 -4
- package/src/Pressable/Pressable.native.tsx +3 -2
- package/src/Pressable/Pressable.web.tsx +3 -5
- package/src/Progress/Progress.native.tsx +5 -4
- package/src/Progress/Progress.web.tsx +3 -3
- package/src/Progress/types.ts +3 -3
- package/src/RadioButton/RadioButton.native.tsx +4 -3
- package/src/RadioButton/RadioButton.styles.tsx +53 -33
- package/src/RadioButton/RadioGroup.native.tsx +3 -2
- package/src/SVGImage/SVGImage.native.tsx +5 -4
- package/src/SVGImage/SVGImage.styles.tsx +44 -10
- package/src/SVGImage/SVGImage.web.tsx +2 -1
- package/src/Screen/Screen.native.tsx +2 -1
- package/src/Screen/Screen.web.tsx +2 -1
- package/src/Select/Select.native.tsx +6 -5
- package/src/Select/Select.styles.tsx +1 -1
- package/src/Select/Select.web.tsx +4 -3
- package/src/Select/types.ts +1 -1
- package/src/Skeleton/Skeleton.native.tsx +2 -1
- package/src/Slider/Slider.native.tsx +9 -8
- package/src/Slider/Slider.web.tsx +10 -9
- package/src/Slider/types.ts +9 -2
- package/src/Switch/Switch.native.tsx +7 -6
- package/src/Switch/Switch.styles.tsx +35 -17
- package/src/Switch/Switch.web.tsx +8 -7
- package/src/Switch/types.ts +44 -4
- package/src/TabBar/TabBar.native.tsx +3 -2
- package/src/Text/Text.native.tsx +3 -2
- package/src/Text/Text.web.tsx +2 -1
- package/src/TextArea/TextArea.native.tsx +3 -2
- package/src/TextArea/TextArea.styles.tsx +2 -2
- package/src/TextArea/TextArea.web.tsx +2 -1
- package/src/TextInput/TextInput.native.tsx +300 -0
- package/src/TextInput/TextInput.styles.tsx +207 -0
- package/src/TextInput/TextInput.web.tsx +301 -0
- package/src/TextInput/index.native.ts +3 -0
- package/src/TextInput/index.ts +5 -0
- package/src/TextInput/index.web.ts +5 -0
- package/src/TextInput/types.ts +163 -0
- package/src/Tooltip/Tooltip.native.tsx +3 -2
- package/src/Video/Video.native.tsx +4 -3
- package/src/View/View.native.tsx +2 -1
- package/src/View/View.web.tsx +2 -1
- package/src/examples/AlertExamples.tsx +5 -5
- package/src/examples/ButtonExamples.tsx +12 -12
- package/src/examples/CardExamples.tsx +1 -1
- package/src/examples/CheckboxExamples.tsx +2 -2
- package/src/examples/ChipExamples.tsx +6 -6
- package/src/examples/DialogExamples.tsx +1 -1
- package/src/examples/DividerExamples.tsx +1 -1
- package/src/examples/InputExamples.tsx +1 -1
- package/src/examples/LinkExamples.tsx +1 -1
- package/src/examples/ListExamples.tsx +1 -1
- package/src/examples/MenuExamples.tsx +2 -2
- package/src/examples/ProgressExamples.tsx +1 -1
- package/src/examples/RadioButtonExamples.tsx +5 -5
- package/src/examples/SVGImageExamples.tsx +1 -1
- package/src/examples/SelectExamples.tsx +1 -1
- package/src/examples/SliderExamples.tsx +5 -5
- package/src/examples/SwitchExamples.tsx +2 -2
- package/src/examples/TableExamples.tsx +1 -1
- package/src/examples/TooltipExamples.tsx +2 -2
- package/src/extensions/index.ts +1 -0
- package/src/extensions/types.ts +10 -3
- package/src/index.ts +23 -2
- package/src/utils/index.ts +12 -0
- package/src/utils/refTypes.ts +50 -0
|
@@ -67,63 +67,61 @@ export const checkboxStyles = defineStyle('Checkbox', (theme: Theme) => ({
|
|
|
67
67
|
},
|
|
68
68
|
}),
|
|
69
69
|
|
|
70
|
-
checkbox: (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
borderWidth,
|
|
88
|
-
borderStyle: 'solid' as const,
|
|
89
|
-
opacity: disabled ? 0.5 : 1,
|
|
90
|
-
variants: {
|
|
91
|
-
size: {
|
|
92
|
-
xs: { width: 14, height: 14 },
|
|
93
|
-
sm: { width: 16, height: 16 },
|
|
94
|
-
md: { width: 20, height: 20 },
|
|
95
|
-
lg: { width: 24, height: 24 },
|
|
96
|
-
xl: { width: 28, height: 28 },
|
|
97
|
-
},
|
|
70
|
+
checkbox: (_props: CheckboxDynamicProps) => ({
|
|
71
|
+
alignItems: 'center' as const,
|
|
72
|
+
justifyContent: 'center' as const,
|
|
73
|
+
borderRadius: 4,
|
|
74
|
+
position: 'relative' as const,
|
|
75
|
+
borderStyle: 'solid' as const,
|
|
76
|
+
variants: {
|
|
77
|
+
size: {
|
|
78
|
+
xs: { width: 14, height: 14 },
|
|
79
|
+
sm: { width: 16, height: 16 },
|
|
80
|
+
md: { width: 20, height: 20 },
|
|
81
|
+
lg: { width: 24, height: 24 },
|
|
82
|
+
xl: { width: 28, height: 28 },
|
|
83
|
+
},
|
|
84
|
+
type: {
|
|
85
|
+
default: { borderWidth: 1 },
|
|
86
|
+
outlined: { borderWidth: 2 },
|
|
98
87
|
},
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
userSelect: 'none',
|
|
104
|
-
WebkitAppearance: 'none',
|
|
105
|
-
MozAppearance: 'none',
|
|
106
|
-
appearance: 'none',
|
|
107
|
-
transition: 'all 0.2s ease',
|
|
108
|
-
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
109
|
-
border: `${borderWidth}px solid ${borderColor}`,
|
|
110
|
-
_focus: {
|
|
111
|
-
outline: `2px solid ${theme.intents.primary.primary}`,
|
|
112
|
-
outlineOffset: '2px',
|
|
88
|
+
checked: {
|
|
89
|
+
true: {
|
|
90
|
+
backgroundColor: theme.$intents.primary,
|
|
91
|
+
borderColor: theme.$intents.primary,
|
|
113
92
|
},
|
|
114
|
-
|
|
115
|
-
|
|
93
|
+
false: {
|
|
94
|
+
backgroundColor: 'transparent',
|
|
95
|
+
borderColor: theme.colors.border.primary,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
disabled: {
|
|
99
|
+
true: { opacity: 0.5 },
|
|
100
|
+
false: { opacity: 1 },
|
|
116
101
|
},
|
|
117
|
-
}
|
|
118
|
-
|
|
102
|
+
},
|
|
103
|
+
_web: {
|
|
104
|
+
outline: 'none',
|
|
105
|
+
display: 'flex',
|
|
106
|
+
boxSizing: 'border-box',
|
|
107
|
+
userSelect: 'none',
|
|
108
|
+
WebkitAppearance: 'none',
|
|
109
|
+
MozAppearance: 'none',
|
|
110
|
+
appearance: 'none',
|
|
111
|
+
transition: 'all 0.2s ease',
|
|
112
|
+
_focus: {
|
|
113
|
+
outline: `2px solid ${theme.intents.primary.primary}`,
|
|
114
|
+
outlineOffset: '2px',
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
}),
|
|
119
118
|
|
|
120
|
-
checkmark: (
|
|
119
|
+
checkmark: (_props: CheckboxDynamicProps) => ({
|
|
121
120
|
position: 'absolute' as const,
|
|
122
121
|
display: 'flex' as const,
|
|
123
122
|
alignItems: 'center' as const,
|
|
124
123
|
justifyContent: 'center' as const,
|
|
125
124
|
color: '#ffffff',
|
|
126
|
-
opacity: checked ? 1 : 0,
|
|
127
125
|
variants: {
|
|
128
126
|
size: {
|
|
129
127
|
xs: { width: 10, height: 10 },
|
|
@@ -132,12 +130,15 @@ export const checkboxStyles = defineStyle('Checkbox', (theme: Theme) => ({
|
|
|
132
130
|
lg: { width: 16, height: 16 },
|
|
133
131
|
xl: { width: 20, height: 20 },
|
|
134
132
|
},
|
|
133
|
+
checked: {
|
|
134
|
+
true: { opacity: 1 },
|
|
135
|
+
false: { opacity: 0 },
|
|
136
|
+
},
|
|
135
137
|
},
|
|
136
138
|
}),
|
|
137
139
|
|
|
138
|
-
label: (
|
|
140
|
+
label: (_props: CheckboxDynamicProps) => ({
|
|
139
141
|
color: theme.colors.text.primary,
|
|
140
|
-
opacity: disabled ? 0.5 : 1,
|
|
141
142
|
variants: {
|
|
142
143
|
size: {
|
|
143
144
|
xs: { fontSize: 12 },
|
|
@@ -146,6 +147,10 @@ export const checkboxStyles = defineStyle('Checkbox', (theme: Theme) => ({
|
|
|
146
147
|
lg: { fontSize: 18 },
|
|
147
148
|
xl: { fontSize: 20 },
|
|
148
149
|
},
|
|
150
|
+
disabled: {
|
|
151
|
+
true: { opacity: 0.5 },
|
|
152
|
+
false: { opacity: 1 },
|
|
153
|
+
},
|
|
149
154
|
},
|
|
150
155
|
_web: {
|
|
151
156
|
display: 'block',
|
|
@@ -155,9 +160,14 @@ export const checkboxStyles = defineStyle('Checkbox', (theme: Theme) => ({
|
|
|
155
160
|
},
|
|
156
161
|
}),
|
|
157
162
|
|
|
158
|
-
helperText: (
|
|
163
|
+
helperText: (_props: CheckboxDynamicProps) => ({
|
|
159
164
|
fontSize: 14,
|
|
160
|
-
color: error ? theme.intents.error.primary : theme.colors.text.secondary,
|
|
161
165
|
marginTop: 2,
|
|
166
|
+
variants: {
|
|
167
|
+
error: {
|
|
168
|
+
true: { color: theme.intents.danger.primary },
|
|
169
|
+
false: { color: theme.colors.text.secondary },
|
|
170
|
+
},
|
|
171
|
+
},
|
|
162
172
|
}),
|
|
163
173
|
}));
|
|
@@ -5,16 +5,17 @@ import { checkboxStyles } from './Checkbox.styles';
|
|
|
5
5
|
import { IconSvg } from '../Icon/IconSvg/IconSvg.web';
|
|
6
6
|
import useMergeRefs from '../hooks/useMergeRefs';
|
|
7
7
|
import { getWebSelectionAriaProps, generateAccessibilityId, combineIds } from '../utils/accessibility';
|
|
8
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Checkbox input for boolean selection with support for indeterminate state.
|
|
11
12
|
* Includes label, helper text, and error display options.
|
|
12
13
|
*/
|
|
13
|
-
const Checkbox = forwardRef<
|
|
14
|
+
const Checkbox = forwardRef<IdealystElement, CheckboxProps>(({
|
|
14
15
|
checked = false,
|
|
15
16
|
indeterminate = false,
|
|
16
17
|
disabled = false,
|
|
17
|
-
|
|
18
|
+
onChange,
|
|
18
19
|
size = 'md',
|
|
19
20
|
intent = 'primary',
|
|
20
21
|
variant = 'default',
|
|
@@ -56,7 +57,7 @@ const Checkbox = forwardRef<HTMLDivElement, CheckboxProps>(({
|
|
|
56
57
|
|
|
57
58
|
const newChecked = event.target.checked;
|
|
58
59
|
setInternalChecked(newChecked);
|
|
59
|
-
|
|
60
|
+
onChange?.(newChecked);
|
|
60
61
|
};
|
|
61
62
|
|
|
62
63
|
// Generate unique IDs for accessibility
|
package/src/Checkbox/types.ts
CHANGED
|
@@ -32,7 +32,7 @@ export interface CheckboxProps extends FormInputStyleProps, SelectionAccessibili
|
|
|
32
32
|
/**
|
|
33
33
|
* Called when the checkbox state changes
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
onChange?: (checked: boolean) => void;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* The size of the checkbox
|
package/src/Chip/Chip.native.tsx
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { isValidElement, forwardRef,
|
|
1
|
+
import { isValidElement, forwardRef, useEffect, useRef } from 'react';
|
|
2
2
|
import { Pressable, Text, View } from 'react-native';
|
|
3
3
|
import MaterialDesignIcons from '@react-native-vector-icons/material-design-icons';
|
|
4
4
|
import { chipStyles } from './Chip.styles';
|
|
5
5
|
import { isIconName } from '../Icon/icon-resolver';
|
|
6
6
|
import type { ChipProps } from './types';
|
|
7
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
// Track if we've logged the onClick deprecation warning (log once per session)
|
|
10
|
+
let hasLoggedOnClickWarning = false;
|
|
11
|
+
|
|
12
|
+
const Chip = forwardRef<IdealystElement, ChipProps>(({
|
|
9
13
|
label,
|
|
10
14
|
type = 'filled',
|
|
11
15
|
intent = 'primary',
|
|
@@ -16,6 +20,7 @@ const Chip = forwardRef<ComponentRef<typeof Pressable>, ChipProps>(({
|
|
|
16
20
|
selectable = false,
|
|
17
21
|
selected = false,
|
|
18
22
|
onPress,
|
|
23
|
+
onClick,
|
|
19
24
|
disabled = false,
|
|
20
25
|
style,
|
|
21
26
|
testID,
|
|
@@ -24,10 +29,28 @@ const Chip = forwardRef<ComponentRef<typeof Pressable>, ChipProps>(({
|
|
|
24
29
|
accessibilityLabel,
|
|
25
30
|
accessibilityChecked,
|
|
26
31
|
}, ref) => {
|
|
32
|
+
const hasWarnedRef = useRef(false);
|
|
33
|
+
|
|
34
|
+
// Warn about onClick usage (deprecated)
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (onClick && !hasWarnedRef.current && !hasLoggedOnClickWarning) {
|
|
37
|
+
hasWarnedRef.current = true;
|
|
38
|
+
hasLoggedOnClickWarning = true;
|
|
39
|
+
console.warn(
|
|
40
|
+
'[Chip] onClick is deprecated. Use onPress instead.\n' +
|
|
41
|
+
'Chip is a cross-platform component that follows React Native conventions.\n' +
|
|
42
|
+
'onClick will be removed in a future version.\n\n' +
|
|
43
|
+
'Migration: Replace onClick={handler} with onPress={handler}'
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}, [onClick]);
|
|
47
|
+
|
|
27
48
|
const handlePress = () => {
|
|
28
49
|
if (disabled) return;
|
|
29
|
-
|
|
30
|
-
|
|
50
|
+
// Prefer onPress, fall back to deprecated onClick
|
|
51
|
+
const handler = onPress ?? onClick;
|
|
52
|
+
if (handler) {
|
|
53
|
+
handler();
|
|
31
54
|
}
|
|
32
55
|
};
|
|
33
56
|
|
|
@@ -72,7 +95,7 @@ const Chip = forwardRef<ComponentRef<typeof Pressable>, ChipProps>(({
|
|
|
72
95
|
return null;
|
|
73
96
|
};
|
|
74
97
|
|
|
75
|
-
const isClickable = (onPress && !disabled) || (selectable && !disabled);
|
|
98
|
+
const isClickable = ((onPress || onClick) && !disabled) || (selectable && !disabled);
|
|
76
99
|
|
|
77
100
|
const innerContent = (
|
|
78
101
|
<>
|
|
@@ -102,7 +125,7 @@ const Chip = forwardRef<ComponentRef<typeof Pressable>, ChipProps>(({
|
|
|
102
125
|
if (isClickable) {
|
|
103
126
|
return (
|
|
104
127
|
<Pressable
|
|
105
|
-
ref={ref}
|
|
128
|
+
ref={ref as any}
|
|
106
129
|
nativeID={id}
|
|
107
130
|
onPress={handlePress}
|
|
108
131
|
disabled={disabled}
|
|
@@ -122,7 +145,7 @@ const Chip = forwardRef<ComponentRef<typeof Pressable>, ChipProps>(({
|
|
|
122
145
|
}
|
|
123
146
|
|
|
124
147
|
return (
|
|
125
|
-
<View ref={ref} nativeID={id} style={[containerStyle, style]} testID={testID}>
|
|
148
|
+
<View ref={ref as any} nativeID={id} style={[containerStyle, style]} testID={testID}>
|
|
126
149
|
{innerContent}
|
|
127
150
|
</View>
|
|
128
151
|
);
|
package/src/Chip/Chip.styles.tsx
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Chip styles using defineStyle with
|
|
2
|
+
* Chip styles using defineStyle with variant expansion.
|
|
3
|
+
*
|
|
4
|
+
* Chip has compound logic between type+selected+intent that's handled via
|
|
5
|
+
* nested variants. The $intents iterator expands for all intent values.
|
|
3
6
|
*/
|
|
4
7
|
import { StyleSheet } from 'react-native-unistyles';
|
|
5
8
|
import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
|
|
@@ -22,129 +25,144 @@ export type ChipDynamicProps = {
|
|
|
22
25
|
};
|
|
23
26
|
|
|
24
27
|
/**
|
|
25
|
-
* Chip styles with size/intent/type/selected
|
|
28
|
+
* Chip styles with variant expansion for size/intent/type/selected.
|
|
26
29
|
*/
|
|
27
30
|
export const chipStyles = defineStyle('Chip', (theme: Theme) => ({
|
|
28
|
-
container: (
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
31
|
+
container: (_props: ChipDynamicProps) => ({
|
|
32
|
+
display: 'flex' as const,
|
|
33
|
+
flexDirection: 'row' as const,
|
|
34
|
+
alignItems: 'center' as const,
|
|
35
|
+
justifyContent: 'center' as const,
|
|
36
|
+
gap: 4,
|
|
37
|
+
borderStyle: 'solid' as const,
|
|
38
|
+
variants: {
|
|
39
|
+
size: {
|
|
40
|
+
paddingHorizontal: theme.sizes.$chip.paddingHorizontal,
|
|
41
|
+
paddingVertical: theme.sizes.$chip.paddingVertical,
|
|
42
|
+
minHeight: theme.sizes.$chip.minHeight,
|
|
43
|
+
borderRadius: theme.sizes.$chip.borderRadius,
|
|
44
|
+
},
|
|
45
|
+
type: {
|
|
46
|
+
filled: {
|
|
47
|
+
borderWidth: 1,
|
|
48
|
+
backgroundColor: theme.$intents.primary,
|
|
49
|
+
borderColor: 'transparent',
|
|
50
|
+
},
|
|
51
|
+
outlined: {
|
|
52
|
+
borderWidth: 1,
|
|
53
|
+
backgroundColor: 'transparent',
|
|
54
|
+
borderColor: theme.$intents.primary,
|
|
55
|
+
},
|
|
56
|
+
soft: {
|
|
57
|
+
borderWidth: 0,
|
|
58
|
+
backgroundColor: theme.$intents.light,
|
|
59
|
+
borderColor: 'transparent',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
selected: {
|
|
63
|
+
true: {},
|
|
64
|
+
false: {},
|
|
65
|
+
},
|
|
66
|
+
disabled: {
|
|
67
|
+
true: { opacity: 0.5 },
|
|
68
|
+
false: { opacity: 1 },
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
compoundVariants: [
|
|
72
|
+
// filled + selected: swap bg/border
|
|
73
|
+
{ type: 'filled', selected: true, styles: { backgroundColor: theme.$intents.contrast, borderColor: theme.$intents.primary } },
|
|
74
|
+
// outlined + selected: fill with primary
|
|
75
|
+
{ type: 'outlined', selected: true, styles: { backgroundColor: theme.$intents.primary } },
|
|
76
|
+
// soft + selected: fill with primary
|
|
77
|
+
{ type: 'soft', selected: true, styles: { backgroundColor: theme.$intents.primary } },
|
|
78
|
+
],
|
|
79
|
+
}),
|
|
80
|
+
|
|
81
|
+
label: (_props: ChipDynamicProps) => ({
|
|
82
|
+
fontFamily: 'inherit' as const,
|
|
83
|
+
fontWeight: '500' as const,
|
|
84
|
+
variants: {
|
|
85
|
+
size: {
|
|
86
|
+
fontSize: theme.sizes.$chip.fontSize,
|
|
87
|
+
lineHeight: theme.sizes.$chip.lineHeight,
|
|
88
|
+
},
|
|
89
|
+
type: {
|
|
90
|
+
filled: { color: theme.$intents.contrast },
|
|
91
|
+
outlined: { color: theme.$intents.primary },
|
|
92
|
+
soft: { color: theme.$intents.dark },
|
|
93
|
+
},
|
|
94
|
+
selected: {
|
|
95
|
+
true: {},
|
|
96
|
+
false: {},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
compoundVariants: [
|
|
100
|
+
{ type: 'filled', selected: true, styles: { color: theme.$intents.primary } },
|
|
101
|
+
{ type: 'outlined', selected: true, styles: { color: theme.colors.text.inverse } },
|
|
102
|
+
{ type: 'soft', selected: true, styles: { color: theme.colors.text.inverse } },
|
|
103
|
+
],
|
|
104
|
+
}),
|
|
105
|
+
|
|
106
|
+
icon: (_props: ChipDynamicProps) => ({
|
|
107
|
+
display: 'flex' as const,
|
|
108
|
+
alignItems: 'center' as const,
|
|
109
|
+
justifyContent: 'center' as const,
|
|
110
|
+
variants: {
|
|
111
|
+
size: {
|
|
112
|
+
width: theme.sizes.$chip.iconSize,
|
|
113
|
+
height: theme.sizes.$chip.iconSize,
|
|
114
|
+
},
|
|
115
|
+
type: {
|
|
116
|
+
filled: { color: theme.$intents.contrast },
|
|
117
|
+
outlined: { color: theme.$intents.primary },
|
|
118
|
+
soft: { color: theme.$intents.dark },
|
|
119
|
+
},
|
|
120
|
+
selected: {
|
|
121
|
+
true: {},
|
|
122
|
+
false: {},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
compoundVariants: [
|
|
126
|
+
{ type: 'filled', selected: true, styles: { color: theme.$intents.primary } },
|
|
127
|
+
{ type: 'outlined', selected: true, styles: { color: theme.colors.text.inverse } },
|
|
128
|
+
{ type: 'soft', selected: true, styles: { color: theme.colors.text.inverse } },
|
|
129
|
+
],
|
|
130
|
+
}),
|
|
131
|
+
|
|
132
|
+
deleteButton: (_props: ChipDynamicProps) => ({
|
|
133
|
+
display: 'flex' as const,
|
|
134
|
+
alignItems: 'center' as const,
|
|
135
|
+
justifyContent: 'center' as const,
|
|
136
|
+
padding: 0,
|
|
137
|
+
marginLeft: 4,
|
|
138
|
+
borderRadius: 12,
|
|
139
|
+
variants: {
|
|
140
|
+
size: {
|
|
141
|
+
width: theme.sizes.$chip.iconSize,
|
|
142
|
+
height: theme.sizes.$chip.iconSize,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
}),
|
|
146
|
+
|
|
147
|
+
deleteIcon: (_props: ChipDynamicProps) => ({
|
|
148
|
+
variants: {
|
|
149
|
+
size: {
|
|
150
|
+
fontSize: theme.sizes.$chip.iconSize,
|
|
151
|
+
},
|
|
152
|
+
type: {
|
|
153
|
+
filled: { color: theme.$intents.contrast },
|
|
154
|
+
outlined: { color: theme.$intents.primary },
|
|
155
|
+
soft: { color: theme.$intents.dark },
|
|
156
|
+
},
|
|
157
|
+
selected: {
|
|
158
|
+
true: {},
|
|
159
|
+
false: {},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
compoundVariants: [
|
|
163
|
+
{ type: 'filled', selected: true, styles: { color: theme.$intents.primary } },
|
|
164
|
+
{ type: 'outlined', selected: true, styles: { color: theme.colors.text.inverse } },
|
|
165
|
+
{ type: 'soft', selected: true, styles: { color: theme.colors.text.inverse } },
|
|
166
|
+
],
|
|
167
|
+
}),
|
|
150
168
|
}));
|
package/src/Chip/Chip.web.tsx
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import React, { isValidElement, forwardRef } from 'react';
|
|
1
|
+
import React, { isValidElement, forwardRef, useEffect, useRef } from 'react';
|
|
2
2
|
import { getWebProps } from 'react-native-unistyles/web';
|
|
3
3
|
import { chipStyles } from './Chip.styles';
|
|
4
4
|
import type { ChipProps } from './types';
|
|
5
5
|
import { IconSvg } from '../Icon/IconSvg/IconSvg.web';
|
|
6
6
|
import { isIconName } from '../Icon/icon-resolver';
|
|
7
7
|
import useMergeRefs from '../hooks/useMergeRefs';
|
|
8
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
9
|
+
|
|
10
|
+
// Track if we've logged the onClick deprecation warning (log once per session)
|
|
11
|
+
let hasLoggedOnClickWarning = false;
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* Compact interactive element for tags, filters, or selections.
|
|
11
15
|
* Supports icons, selection state, and delete functionality.
|
|
12
16
|
*/
|
|
13
|
-
const Chip = forwardRef<
|
|
17
|
+
const Chip = forwardRef<IdealystElement, ChipProps>(({
|
|
14
18
|
label,
|
|
15
19
|
type = 'filled',
|
|
16
20
|
intent = 'primary',
|
|
@@ -22,6 +26,7 @@ const Chip = forwardRef<HTMLDivElement, ChipProps>(({
|
|
|
22
26
|
selectable = false,
|
|
23
27
|
selected = false,
|
|
24
28
|
onPress,
|
|
29
|
+
onClick,
|
|
25
30
|
disabled = false,
|
|
26
31
|
style,
|
|
27
32
|
testID,
|
|
@@ -30,6 +35,22 @@ const Chip = forwardRef<HTMLDivElement, ChipProps>(({
|
|
|
30
35
|
accessibilityLabel,
|
|
31
36
|
accessibilityChecked,
|
|
32
37
|
}, ref) => {
|
|
38
|
+
const hasWarnedRef = useRef(false);
|
|
39
|
+
|
|
40
|
+
// Warn about onClick usage (deprecated)
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (onClick && !hasWarnedRef.current && !hasLoggedOnClickWarning) {
|
|
43
|
+
hasWarnedRef.current = true;
|
|
44
|
+
hasLoggedOnClickWarning = true;
|
|
45
|
+
console.warn(
|
|
46
|
+
'[Chip] onClick is deprecated. Use onPress instead.\n' +
|
|
47
|
+
'Chip is a cross-platform component that follows React Native conventions.\n' +
|
|
48
|
+
'onClick will be removed in a future version.\n\n' +
|
|
49
|
+
'Migration: Replace onClick={handler} with onPress={handler}'
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}, [onClick]);
|
|
53
|
+
|
|
33
54
|
// Compute actual selected state
|
|
34
55
|
const isSelected = selectable ? selected : false;
|
|
35
56
|
|
|
@@ -42,8 +63,10 @@ const Chip = forwardRef<HTMLDivElement, ChipProps>(({
|
|
|
42
63
|
|
|
43
64
|
const handleClick = () => {
|
|
44
65
|
if (disabled) return;
|
|
45
|
-
|
|
46
|
-
|
|
66
|
+
// Prefer onPress, fall back to deprecated onClick
|
|
67
|
+
const handler = onPress ?? onClick;
|
|
68
|
+
if (handler) {
|
|
69
|
+
handler();
|
|
47
70
|
}
|
|
48
71
|
};
|
|
49
72
|
|
|
@@ -91,7 +114,7 @@ const Chip = forwardRef<HTMLDivElement, ChipProps>(({
|
|
|
91
114
|
return null;
|
|
92
115
|
};
|
|
93
116
|
|
|
94
|
-
const isClickable = (onPress && !disabled) || (selectable && !disabled);
|
|
117
|
+
const isClickable = ((onPress || onClick) && !disabled) || (selectable && !disabled);
|
|
95
118
|
|
|
96
119
|
const mergedRef = useMergeRefs(ref, containerProps.ref);
|
|
97
120
|
|
package/src/Chip/types.ts
CHANGED
|
@@ -46,6 +46,21 @@ export interface ChipProps extends BaseProps, SelectionAccessibilityProps {
|
|
|
46
46
|
/** Callback when chip is pressed */
|
|
47
47
|
onPress?: () => void;
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @deprecated Use `onPress` instead. This is a cross-platform component - use React Native conventions.
|
|
51
|
+
*
|
|
52
|
+
* Using `onClick` will trigger a console warning in development.
|
|
53
|
+
* This prop exists only for migration convenience and will be removed in a future version.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // ❌ Don't use onClick
|
|
57
|
+
* <Chip label="Tag" onClick={() => {}} />
|
|
58
|
+
*
|
|
59
|
+
* // ✅ Use onPress instead
|
|
60
|
+
* <Chip label="Tag" onPress={() => {}} />
|
|
61
|
+
*/
|
|
62
|
+
onClick?: () => void;
|
|
63
|
+
|
|
49
64
|
/** Whether the chip is disabled */
|
|
50
65
|
disabled?: boolean;
|
|
51
66
|
|