@idealyst/components 1.2.29 → 1.2.31
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 +4 -4
- package/plugin/__tests__/web.test.ts +2 -2
- package/plugin/web.js +2 -0
- package/src/Accordion/Accordion.native.tsx +3 -2
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +4 -2
- package/src/ActivityIndicator/ActivityIndicator.styles.tsx +22 -27
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +17 -29
- package/src/Alert/Alert.native.tsx +20 -10
- package/src/Alert/Alert.styles.tsx +173 -86
- package/src/Alert/Alert.web.tsx +34 -30
- 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.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/IconButton/IconButton.native.tsx +219 -0
- package/src/IconButton/IconButton.styles.tsx +127 -0
- package/src/IconButton/IconButton.web.tsx +198 -0
- package/src/IconButton/index.native.ts +5 -0
- package/src/IconButton/index.ts +5 -0
- package/src/IconButton/index.web.ts +5 -0
- package/src/IconButton/types.ts +84 -0
- 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/Skeleton/Skeleton.web.tsx +1 -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 +52 -17
- package/src/Switch/Switch.web.tsx +15 -16
- 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.styles.tsx +1 -0
- package/src/View/View.web.tsx +9 -2
- package/src/examples/ActivityIndicatorExamples.tsx +177 -0
- 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 +26 -26
- package/src/examples/TableExamples.tsx +1 -1
- package/src/examples/TooltipExamples.tsx +2 -2
- package/src/examples/index.ts +1 -0
- package/src/extensions/index.ts +1 -0
- package/src/extensions/types.ts +22 -3
- package/src/index.native.ts +4 -0
- package/src/index.ts +27 -2
- package/src/utils/index.ts +12 -0
- package/src/utils/refTypes.ts +50 -0
package/src/Card/Card.native.tsx
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import { forwardRef,
|
|
1
|
+
import { forwardRef, useMemo, useEffect, useRef } from 'react';
|
|
2
2
|
import { View, Pressable } from 'react-native';
|
|
3
3
|
import { CardProps } from './types';
|
|
4
4
|
import { cardStyles } from './Card.styles';
|
|
5
5
|
import { getNativeInteractiveAccessibilityProps } from '../utils/accessibility';
|
|
6
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
// Track if we've logged the onClick deprecation warning (log once per session)
|
|
9
|
+
let hasLoggedOnClickWarning = false;
|
|
10
|
+
|
|
11
|
+
const Card = forwardRef<IdealystElement, CardProps>(({
|
|
8
12
|
children,
|
|
9
13
|
type = 'elevated',
|
|
10
14
|
radius = 'md',
|
|
11
15
|
intent: _intent = 'neutral',
|
|
12
16
|
clickable = false,
|
|
13
17
|
onPress,
|
|
18
|
+
onClick,
|
|
14
19
|
disabled = false,
|
|
15
20
|
// Spacing variants from ContainerStyleProps
|
|
16
21
|
gap,
|
|
@@ -31,6 +36,22 @@ const Card = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pressabl
|
|
|
31
36
|
accessibilityRole,
|
|
32
37
|
accessibilityPressed,
|
|
33
38
|
}, ref) => {
|
|
39
|
+
const hasWarnedRef = useRef(false);
|
|
40
|
+
|
|
41
|
+
// Warn about onClick usage (deprecated)
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (onClick && !hasWarnedRef.current && !hasLoggedOnClickWarning) {
|
|
44
|
+
hasWarnedRef.current = true;
|
|
45
|
+
hasLoggedOnClickWarning = true;
|
|
46
|
+
console.warn(
|
|
47
|
+
'[Card] onClick is deprecated. Use onPress instead.\n' +
|
|
48
|
+
'Card is a cross-platform component that follows React Native conventions.\n' +
|
|
49
|
+
'onClick will be removed in a future version.\n\n' +
|
|
50
|
+
'Migration: Replace onClick={handler} with onPress={handler}'
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}, [onClick]);
|
|
54
|
+
|
|
34
55
|
// Generate native accessibility props
|
|
35
56
|
const nativeA11yProps = useMemo(() => {
|
|
36
57
|
return getNativeInteractiveAccessibilityProps({
|
|
@@ -64,6 +85,9 @@ const Card = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pressabl
|
|
|
64
85
|
// Use appropriate component based on clickable state
|
|
65
86
|
const Component = clickable ? Pressable : View;
|
|
66
87
|
|
|
88
|
+
// Prefer onPress, fall back to deprecated onClick
|
|
89
|
+
const pressHandler = onPress ?? onClick;
|
|
90
|
+
|
|
67
91
|
const componentProps = {
|
|
68
92
|
ref,
|
|
69
93
|
nativeID: id,
|
|
@@ -71,7 +95,7 @@ const Card = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pressabl
|
|
|
71
95
|
testID,
|
|
72
96
|
...nativeA11yProps,
|
|
73
97
|
...(clickable && {
|
|
74
|
-
onPress: disabled ? undefined :
|
|
98
|
+
onPress: disabled ? undefined : pressHandler,
|
|
75
99
|
disabled,
|
|
76
100
|
android_ripple: { color: 'rgba(0, 0, 0, 0.1)' },
|
|
77
101
|
}),
|
package/src/Card/Card.web.tsx
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import { forwardRef, useMemo } from 'react';
|
|
1
|
+
import { forwardRef, useMemo, useEffect, useRef } from 'react';
|
|
2
2
|
import { getWebProps } from 'react-native-unistyles/web';
|
|
3
3
|
import { CardProps } from './types';
|
|
4
4
|
import { cardStyles } from './Card.styles';
|
|
5
5
|
import useMergeRefs from '../hooks/useMergeRefs';
|
|
6
6
|
import { getWebInteractiveAriaProps } from '../utils/accessibility';
|
|
7
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
8
|
+
|
|
9
|
+
// Track if we've logged the onClick deprecation warning (log once per session)
|
|
10
|
+
let hasLoggedOnClickWarning = false;
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* Container component for grouping related content with elevation and styling options.
|
|
10
14
|
* Supports elevated, outlined, and filled variants with optional click interaction.
|
|
11
15
|
*/
|
|
12
|
-
const Card = forwardRef<
|
|
16
|
+
const Card = forwardRef<IdealystElement, CardProps>(({
|
|
13
17
|
children,
|
|
14
18
|
type: typeProp,
|
|
15
19
|
variant,
|
|
@@ -17,6 +21,7 @@ const Card = forwardRef<HTMLDivElement | HTMLButtonElement, CardProps>(({
|
|
|
17
21
|
intent: _intent,
|
|
18
22
|
clickable = false,
|
|
19
23
|
onPress,
|
|
24
|
+
onClick,
|
|
20
25
|
disabled = false,
|
|
21
26
|
// Spacing variants from ContainerStyleProps
|
|
22
27
|
gap,
|
|
@@ -37,6 +42,22 @@ const Card = forwardRef<HTMLDivElement | HTMLButtonElement, CardProps>(({
|
|
|
37
42
|
accessibilityRole,
|
|
38
43
|
accessibilityPressed,
|
|
39
44
|
}, ref) => {
|
|
45
|
+
const hasWarnedRef = useRef(false);
|
|
46
|
+
|
|
47
|
+
// Warn about onClick usage (deprecated)
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (onClick && !hasWarnedRef.current && !hasLoggedOnClickWarning) {
|
|
50
|
+
hasWarnedRef.current = true;
|
|
51
|
+
hasLoggedOnClickWarning = true;
|
|
52
|
+
console.warn(
|
|
53
|
+
'[Card] onClick is deprecated. Use onPress instead.\n' +
|
|
54
|
+
'Card is a cross-platform component that follows React Native conventions.\n' +
|
|
55
|
+
'onClick will be removed in a future version.\n\n' +
|
|
56
|
+
'Migration: Replace onClick={handler} with onPress={handler}'
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}, [onClick]);
|
|
60
|
+
|
|
40
61
|
// variant is an alias for type - variant takes precedence if both are set
|
|
41
62
|
const type = variant ?? typeProp ?? 'elevated';
|
|
42
63
|
// Generate ARIA props
|
|
@@ -50,9 +71,14 @@ const Card = forwardRef<HTMLDivElement | HTMLButtonElement, CardProps>(({
|
|
|
50
71
|
accessibilityPressed,
|
|
51
72
|
});
|
|
52
73
|
}, [accessibilityLabel, accessibilityHint, accessibilityDisabled, disabled, accessibilityHidden, accessibilityRole, clickable, accessibilityPressed]);
|
|
74
|
+
|
|
53
75
|
const handleClick = () => {
|
|
54
|
-
if (!disabled && clickable
|
|
55
|
-
onPress
|
|
76
|
+
if (!disabled && clickable) {
|
|
77
|
+
// Prefer onPress, fall back to deprecated onClick
|
|
78
|
+
const handler = onPress ?? onClick;
|
|
79
|
+
if (handler) {
|
|
80
|
+
handler();
|
|
81
|
+
}
|
|
56
82
|
}
|
|
57
83
|
};
|
|
58
84
|
|
package/src/Card/types.ts
CHANGED
|
@@ -49,6 +49,21 @@ export interface CardProps extends ContainerStyleProps, InteractiveAccessibility
|
|
|
49
49
|
*/
|
|
50
50
|
onPress?: () => void;
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @deprecated Use `onPress` instead. This is a cross-platform component - use React Native conventions.
|
|
54
|
+
*
|
|
55
|
+
* Using `onClick` will trigger a console warning in development.
|
|
56
|
+
* This prop exists only for migration convenience and will be removed in a future version.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // ❌ Don't use onClick
|
|
60
|
+
* <Card clickable onClick={() => {}} />
|
|
61
|
+
*
|
|
62
|
+
* // ✅ Use onPress instead
|
|
63
|
+
* <Card clickable onPress={() => {}} />
|
|
64
|
+
*/
|
|
65
|
+
onClick?: () => void;
|
|
66
|
+
|
|
52
67
|
/**
|
|
53
68
|
* Whether the card is disabled
|
|
54
69
|
*/
|
|
@@ -4,12 +4,13 @@ import MaterialDesignIcons from '@react-native-vector-icons/material-design-icon
|
|
|
4
4
|
import { CheckboxProps } from './types';
|
|
5
5
|
import { checkboxStyles } from './Checkbox.styles';
|
|
6
6
|
import { getNativeSelectionAccessibilityProps } from '../utils/accessibility';
|
|
7
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
7
8
|
|
|
8
|
-
const Checkbox = forwardRef<
|
|
9
|
+
const Checkbox = forwardRef<IdealystElement, CheckboxProps>(({
|
|
9
10
|
checked = false,
|
|
10
11
|
indeterminate = false,
|
|
11
12
|
disabled = false,
|
|
12
|
-
|
|
13
|
+
onChange,
|
|
13
14
|
size = 'md',
|
|
14
15
|
intent = 'primary',
|
|
15
16
|
variant = 'default',
|
|
@@ -46,7 +47,7 @@ const Checkbox = forwardRef<View, CheckboxProps>(({
|
|
|
46
47
|
|
|
47
48
|
const newChecked = !internalChecked;
|
|
48
49
|
setInternalChecked(newChecked);
|
|
49
|
-
|
|
50
|
+
onChange?.(newChecked);
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
// Generate native accessibility props
|
|
@@ -108,7 +109,7 @@ const Checkbox = forwardRef<View, CheckboxProps>(({
|
|
|
108
109
|
const helperTextStyle = (checkboxStyles.helperText as any)({ error: !!error });
|
|
109
110
|
|
|
110
111
|
return (
|
|
111
|
-
<View ref={ref} nativeID={id} style={[wrapperStyle, style]}>
|
|
112
|
+
<View ref={ref as any} nativeID={id} style={[wrapperStyle, style]}>
|
|
112
113
|
<Pressable
|
|
113
114
|
onPress={handlePress}
|
|
114
115
|
disabled={disabled}
|
|
@@ -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.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
|
|
|
@@ -7,7 +7,7 @@ import { getNativeInteractiveAccessibilityProps } from '../utils/accessibility';
|
|
|
7
7
|
|
|
8
8
|
const Dialog = forwardRef<View, DialogProps>(({
|
|
9
9
|
open,
|
|
10
|
-
|
|
10
|
+
onClose,
|
|
11
11
|
title,
|
|
12
12
|
children,
|
|
13
13
|
size = 'md',
|
|
@@ -76,22 +76,22 @@ const Dialog = forwardRef<View, DialogProps>(({
|
|
|
76
76
|
if (!open) return;
|
|
77
77
|
|
|
78
78
|
const handleBackPress = () => {
|
|
79
|
-
|
|
79
|
+
onClose();
|
|
80
80
|
return true; // Prevent default back behavior
|
|
81
81
|
};
|
|
82
82
|
|
|
83
83
|
const backHandler = BackHandler.addEventListener('hardwareBackPress', handleBackPress);
|
|
84
84
|
return () => backHandler.remove();
|
|
85
|
-
}, [open,
|
|
85
|
+
}, [open, onClose]);
|
|
86
86
|
|
|
87
87
|
const handleBackdropPress = () => {
|
|
88
88
|
if (closeOnBackdropClick) {
|
|
89
|
-
|
|
89
|
+
onClose();
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
92
|
|
|
93
93
|
const handleClosePress = () => {
|
|
94
|
-
|
|
94
|
+
onClose();
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
// Apply variants
|
|
@@ -129,7 +129,7 @@ const Dialog = forwardRef<View, DialogProps>(({
|
|
|
129
129
|
visible={open}
|
|
130
130
|
transparent
|
|
131
131
|
animationType="none"
|
|
132
|
-
onRequestClose={() =>
|
|
132
|
+
onRequestClose={() => onClose()}
|
|
133
133
|
statusBarTranslucent
|
|
134
134
|
testID={testID}
|
|
135
135
|
>
|
|
@@ -13,7 +13,7 @@ import { getWebInteractiveAriaProps, generateAccessibilityId } from '../utils/ac
|
|
|
13
13
|
*/
|
|
14
14
|
const Dialog = forwardRef<HTMLDivElement, DialogProps>(({
|
|
15
15
|
open,
|
|
16
|
-
|
|
16
|
+
onClose,
|
|
17
17
|
title,
|
|
18
18
|
children,
|
|
19
19
|
size = 'md',
|
|
@@ -81,13 +81,13 @@ const Dialog = forwardRef<HTMLDivElement, DialogProps>(({
|
|
|
81
81
|
|
|
82
82
|
const handleEscape = (event: KeyboardEvent) => {
|
|
83
83
|
if (event.key === 'Escape') {
|
|
84
|
-
|
|
84
|
+
onClose();
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
87
|
|
|
88
88
|
document.addEventListener('keydown', handleEscape);
|
|
89
89
|
return () => document.removeEventListener('keydown', handleEscape);
|
|
90
|
-
}, [open, closeOnEscapeKey,
|
|
90
|
+
}, [open, closeOnEscapeKey, onClose]);
|
|
91
91
|
|
|
92
92
|
// Handle focus management
|
|
93
93
|
useEffect(() => {
|
|
@@ -122,12 +122,12 @@ const Dialog = forwardRef<HTMLDivElement, DialogProps>(({
|
|
|
122
122
|
|
|
123
123
|
const handleBackdropClick = (event: React.MouseEvent) => {
|
|
124
124
|
if (closeOnBackdropClick && event.target === event.currentTarget) {
|
|
125
|
-
|
|
125
|
+
onClose();
|
|
126
126
|
}
|
|
127
127
|
};
|
|
128
128
|
|
|
129
129
|
const handleCloseClick = () => {
|
|
130
|
-
|
|
130
|
+
onClose();
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
// Apply variants
|
package/src/Dialog/types.ts
CHANGED
|
@@ -19,9 +19,9 @@ export interface DialogProps extends BaseProps, InteractiveAccessibilityProps {
|
|
|
19
19
|
open: boolean;
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Called when the dialog should be
|
|
22
|
+
* Called when the dialog should be closed
|
|
23
23
|
*/
|
|
24
|
-
|
|
24
|
+
onClose: () => void;
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Optional title for the dialog
|