@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
package/README.md
CHANGED
|
@@ -198,15 +198,15 @@ The library includes a comprehensive theme system with light and dark mode suppo
|
|
|
198
198
|
All components use a consistent intent-based color system:
|
|
199
199
|
|
|
200
200
|
- `primary`: Main brand actions
|
|
201
|
-
- `neutral`: Secondary actions
|
|
201
|
+
- `neutral`: Secondary actions
|
|
202
202
|
- `success`: Positive actions (save, confirm)
|
|
203
|
-
- `
|
|
203
|
+
- `danger`: Destructive actions (delete, cancel)
|
|
204
204
|
- `warning`: Caution actions
|
|
205
205
|
|
|
206
206
|
```tsx
|
|
207
207
|
<Button variant="contained" intent="primary">Primary Action</Button>
|
|
208
208
|
<Button variant="contained" intent="success">Save</Button>
|
|
209
|
-
<Button variant="contained" intent="
|
|
209
|
+
<Button variant="contained" intent="danger">Delete</Button>
|
|
210
210
|
```
|
|
211
211
|
|
|
212
212
|
### Theme Integration
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idealyst/components",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.30",
|
|
4
4
|
"description": "Shared component library for React and React Native",
|
|
5
5
|
"documentation": "https://github.com/IdealystIO/idealyst-framework/tree/main/packages/components#readme",
|
|
6
6
|
"readme": "README.md",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"publish:npm": "npm publish"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@idealyst/theme": "^1.2.
|
|
59
|
+
"@idealyst/theme": "^1.2.30",
|
|
60
60
|
"@mdi/js": ">=7.0.0",
|
|
61
61
|
"@mdi/react": ">=1.0.0",
|
|
62
62
|
"@react-native-vector-icons/common": ">=12.0.0",
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
|
-
"@idealyst/theme": "^1.2.
|
|
109
|
+
"@idealyst/theme": "^1.2.30",
|
|
110
110
|
"@idealyst/tooling": "^1.2.4",
|
|
111
111
|
"@mdi/react": "^1.6.1",
|
|
112
112
|
"@types/react": "^19.1.0",
|
|
@@ -468,12 +468,12 @@ describe('MDI Icon Registry Babel Plugin', () => {
|
|
|
468
468
|
|
|
469
469
|
it('does not detect icon-like strings in other props', () => {
|
|
470
470
|
const code = `
|
|
471
|
-
<Button
|
|
471
|
+
<Button data-name="home" aria-label="eye">Click me</Button>
|
|
472
472
|
`;
|
|
473
473
|
const result = transform(code);
|
|
474
474
|
const icons = getDetectedIcons(result?.code);
|
|
475
475
|
|
|
476
|
-
//
|
|
476
|
+
// data-name and aria-label are not icon props
|
|
477
477
|
expect(icons).not.toContain('home');
|
|
478
478
|
expect(icons).not.toContain('eye');
|
|
479
479
|
});
|
|
@@ -6,6 +6,7 @@ import { accordionStyles } from './Accordion.styles';
|
|
|
6
6
|
import Text from '../Text';
|
|
7
7
|
import type { AccordionProps, AccordionItem as AccordionItemType } from './types';
|
|
8
8
|
import { getNativeAccessibilityProps } from '../utils/accessibility';
|
|
9
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
9
10
|
|
|
10
11
|
interface AccordionItemProps {
|
|
11
12
|
item: AccordionItemType;
|
|
@@ -135,7 +136,7 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
|
|
|
135
136
|
);
|
|
136
137
|
};
|
|
137
138
|
|
|
138
|
-
const Accordion = forwardRef<
|
|
139
|
+
const Accordion = forwardRef<IdealystElement, AccordionProps>(({
|
|
139
140
|
items,
|
|
140
141
|
allowMultiple = false,
|
|
141
142
|
defaultExpanded = [],
|
|
@@ -204,7 +205,7 @@ const Accordion = forwardRef<View, AccordionProps>(({
|
|
|
204
205
|
const containerStyle = (accordionStyles.container as any)({});
|
|
205
206
|
|
|
206
207
|
return (
|
|
207
|
-
<View ref={ref} nativeID={id} style={[containerStyle, style]} testID={testID} {...nativeA11yProps}>
|
|
208
|
+
<View ref={ref as any} nativeID={id} style={[containerStyle, style]} testID={testID} {...nativeA11yProps}>
|
|
208
209
|
{items.map((item, index) => (
|
|
209
210
|
<AccordionItem
|
|
210
211
|
key={item.id}
|
|
@@ -3,8 +3,9 @@ import { ActivityIndicator as RNActivityIndicator, View } from 'react-native';
|
|
|
3
3
|
import { ActivityIndicatorProps } from './types';
|
|
4
4
|
import { activityIndicatorStyles } from './ActivityIndicator.styles';
|
|
5
5
|
import { getNativeLiveRegionAccessibilityProps } from '../utils/accessibility';
|
|
6
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
6
7
|
|
|
7
|
-
const ActivityIndicator = forwardRef<
|
|
8
|
+
const ActivityIndicator = forwardRef<IdealystElement, ActivityIndicatorProps>(({
|
|
8
9
|
animating = true,
|
|
9
10
|
size = 'md',
|
|
10
11
|
intent = 'primary',
|
|
@@ -55,7 +56,7 @@ const ActivityIndicator = forwardRef<View, ActivityIndicatorProps>(({
|
|
|
55
56
|
},
|
|
56
57
|
style
|
|
57
58
|
]}
|
|
58
|
-
ref={ref}
|
|
59
|
+
ref={ref as any}
|
|
59
60
|
nativeID={id}
|
|
60
61
|
testID={testID}
|
|
61
62
|
{...nativeA11yProps}
|
|
@@ -37,32 +37,31 @@ export const activityIndicatorStyles = defineStyle('ActivityIndicator', (theme:
|
|
|
37
37
|
},
|
|
38
38
|
}),
|
|
39
39
|
|
|
40
|
-
spinner: (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
variants: {
|
|
49
|
-
size: {
|
|
50
|
-
width: theme.sizes.$activityIndicator.size,
|
|
51
|
-
height: theme.sizes.$activityIndicator.size,
|
|
52
|
-
borderWidth: theme.sizes.$activityIndicator.borderWidth,
|
|
53
|
-
},
|
|
54
|
-
animating: {
|
|
55
|
-
true: {},
|
|
56
|
-
false: {},
|
|
57
|
-
},
|
|
40
|
+
spinner: (_props: ActivityIndicatorDynamicProps) => ({
|
|
41
|
+
borderRadius: 9999,
|
|
42
|
+
borderStyle: 'solid' as const,
|
|
43
|
+
variants: {
|
|
44
|
+
size: {
|
|
45
|
+
width: theme.sizes.$activityIndicator.size,
|
|
46
|
+
height: theme.sizes.$activityIndicator.size,
|
|
47
|
+
borderWidth: theme.sizes.$activityIndicator.borderWidth,
|
|
58
48
|
},
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
49
|
+
animating: {
|
|
50
|
+
true: {},
|
|
51
|
+
false: {},
|
|
52
|
+
},
|
|
53
|
+
intent: {
|
|
54
|
+
color: theme.$intents.primary,
|
|
55
|
+
_web: {
|
|
56
|
+
borderColor: 'transparent',
|
|
57
|
+
borderTopColor: theme.$intents.primary,
|
|
58
|
+
borderRightColor: theme.$intents.primary,
|
|
59
|
+
},
|
|
65
60
|
},
|
|
66
|
-
}
|
|
67
|
-
|
|
61
|
+
},
|
|
62
|
+
_web: {
|
|
63
|
+
animation: 'spin 1s linear infinite',
|
|
64
|
+
boxSizing: 'border-box',
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
68
67
|
}));
|
|
@@ -4,12 +4,13 @@ import { ActivityIndicatorProps } from './types';
|
|
|
4
4
|
import { activityIndicatorStyles } from './ActivityIndicator.styles';
|
|
5
5
|
import useMergeRefs from '../hooks/useMergeRefs';
|
|
6
6
|
import { getWebLiveRegionAriaProps } from '../utils/accessibility';
|
|
7
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Spinning loading indicator for async operations and content loading.
|
|
10
11
|
* Supports intent-based coloring and automatic hiding when stopped.
|
|
11
12
|
*/
|
|
12
|
-
const ActivityIndicator = forwardRef<
|
|
13
|
+
const ActivityIndicator = forwardRef<IdealystElement, ActivityIndicatorProps>(({
|
|
13
14
|
animating = true,
|
|
14
15
|
size = 'md',
|
|
15
16
|
intent = 'primary',
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { isValidElement, forwardRef
|
|
1
|
+
import { isValidElement, forwardRef } from 'react';
|
|
2
2
|
import { View, Text, TouchableOpacity } from 'react-native';
|
|
3
3
|
import MaterialDesignIcons from '@react-native-vector-icons/material-design-icons';
|
|
4
|
-
import { alertStyles } from './Alert.styles';
|
|
4
|
+
import { alertStyles, alertSizeConfig } from './Alert.styles';
|
|
5
5
|
import { isIconName } from '../Icon/icon-resolver';
|
|
6
6
|
import type { AlertProps } from './types';
|
|
7
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
7
8
|
|
|
8
9
|
// Default icon names for each intent
|
|
9
10
|
const defaultIcons: Record<string, string> = {
|
|
@@ -15,12 +16,13 @@ const defaultIcons: Record<string, string> = {
|
|
|
15
16
|
neutral: 'circle',
|
|
16
17
|
};
|
|
17
18
|
|
|
18
|
-
const Alert = forwardRef<
|
|
19
|
+
const Alert = forwardRef<IdealystElement, AlertProps>(({
|
|
19
20
|
title,
|
|
20
21
|
message,
|
|
21
22
|
children,
|
|
22
23
|
intent = 'neutral',
|
|
23
24
|
type = 'soft',
|
|
25
|
+
size = 'md',
|
|
24
26
|
icon,
|
|
25
27
|
showIcon = true,
|
|
26
28
|
dismissible = false,
|
|
@@ -30,17 +32,25 @@ const Alert = forwardRef<ComponentRef<typeof View>, AlertProps>(({
|
|
|
30
32
|
testID,
|
|
31
33
|
id,
|
|
32
34
|
}, ref) => {
|
|
35
|
+
// Apply variants for size
|
|
36
|
+
alertStyles.useVariants({ size });
|
|
37
|
+
|
|
33
38
|
// Call all styles as functions to get theme-reactive styles
|
|
34
|
-
const dynamicProps = { intent, type };
|
|
39
|
+
const dynamicProps = { intent, type, size };
|
|
35
40
|
const containerStyle = (alertStyles.container as any)(dynamicProps);
|
|
36
41
|
const iconContainerStyle = (alertStyles.iconContainer as any)(dynamicProps);
|
|
37
42
|
const titleStyle = (alertStyles.title as any)(dynamicProps);
|
|
38
43
|
const messageStyle = (alertStyles.message as any)(dynamicProps);
|
|
39
|
-
const contentStyle = (alertStyles.content as any)(
|
|
40
|
-
const actionsStyle = (alertStyles.actions as any)(
|
|
41
|
-
const closeButtonStyle = (alertStyles.closeButton as any)(
|
|
44
|
+
const contentStyle = (alertStyles.content as any)(dynamicProps);
|
|
45
|
+
const actionsStyle = (alertStyles.actions as any)(dynamicProps);
|
|
46
|
+
const closeButtonStyle = (alertStyles.closeButton as any)(dynamicProps);
|
|
42
47
|
const closeIconStyle = (alertStyles.closeIcon as any)(dynamicProps);
|
|
43
48
|
|
|
49
|
+
// Get size-specific icon dimensions
|
|
50
|
+
const sizeConfig = alertSizeConfig[size];
|
|
51
|
+
const iconSize = sizeConfig.iconSize;
|
|
52
|
+
const closeIconSize = sizeConfig.closeIconSize;
|
|
53
|
+
|
|
44
54
|
const displayIcon = icon !== undefined ? icon : (showIcon ? defaultIcons[intent] : null);
|
|
45
55
|
|
|
46
56
|
// Helper to render icon
|
|
@@ -51,7 +61,7 @@ const Alert = forwardRef<ComponentRef<typeof View>, AlertProps>(({
|
|
|
51
61
|
return (
|
|
52
62
|
<MaterialDesignIcons
|
|
53
63
|
name={displayIcon}
|
|
54
|
-
size={
|
|
64
|
+
size={iconSize}
|
|
55
65
|
style={iconContainerStyle}
|
|
56
66
|
/>
|
|
57
67
|
);
|
|
@@ -63,7 +73,7 @@ const Alert = forwardRef<ComponentRef<typeof View>, AlertProps>(({
|
|
|
63
73
|
|
|
64
74
|
return (
|
|
65
75
|
<View
|
|
66
|
-
ref={ref}
|
|
76
|
+
ref={ref as any}
|
|
67
77
|
nativeID={id}
|
|
68
78
|
style={[containerStyle, style]}
|
|
69
79
|
testID={testID}
|
|
@@ -112,7 +122,7 @@ const Alert = forwardRef<ComponentRef<typeof View>, AlertProps>(({
|
|
|
112
122
|
>
|
|
113
123
|
<MaterialDesignIcons
|
|
114
124
|
name="close"
|
|
115
|
-
size={
|
|
125
|
+
size={closeIconSize}
|
|
116
126
|
style={closeIconStyle}
|
|
117
127
|
/>
|
|
118
128
|
</TouchableOpacity>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Alert styles using defineStyle with
|
|
2
|
+
* Alert styles using defineStyle with $iterator expansion for size variants.
|
|
3
3
|
*/
|
|
4
4
|
import { StyleSheet } from 'react-native-unistyles';
|
|
5
5
|
import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
|
|
6
|
-
import type { Theme as BaseTheme, Intent } from '@idealyst/theme';
|
|
6
|
+
import type { Theme as BaseTheme, Intent, Size } from '@idealyst/theme';
|
|
7
7
|
|
|
8
8
|
// Required: Unistyles must see StyleSheet usage in original source to process this file
|
|
9
9
|
void StyleSheet;
|
|
@@ -16,98 +16,136 @@ type AlertType = 'filled' | 'outlined' | 'soft';
|
|
|
16
16
|
export type AlertDynamicProps = {
|
|
17
17
|
intent?: Intent;
|
|
18
18
|
type?: AlertType;
|
|
19
|
+
size?: Size;
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
|
-
* Alert styles with
|
|
23
|
+
* Alert styles with $iterator expansion for size variants.
|
|
24
|
+
*
|
|
25
|
+
* Intent/type combinations use dynamic functions with inlined theme accesses
|
|
26
|
+
* so Unistyles can trace all possible theme paths.
|
|
23
27
|
*/
|
|
24
28
|
export const alertStyles = defineStyle('Alert', (theme: Theme) => ({
|
|
25
|
-
container: (
|
|
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
|
-
iconContainer: ({ intent = 'neutral', type = 'soft' }: AlertDynamicProps) => {
|
|
55
|
-
const intentValue = theme.intents[intent];
|
|
56
|
-
const color = type === 'filled' ? intentValue.contrast : intentValue.primary;
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
display: 'flex' as const,
|
|
60
|
-
alignItems: 'center' as const,
|
|
61
|
-
justifyContent: 'center' as const,
|
|
62
|
-
alignSelf: 'flex-start' as const,
|
|
63
|
-
flexShrink: 0,
|
|
64
|
-
width: 24,
|
|
65
|
-
height: 24,
|
|
66
|
-
marginTop: 2,
|
|
67
|
-
color,
|
|
68
|
-
} as const;
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
title: ({ intent = 'neutral', type = 'soft' }: AlertDynamicProps) => {
|
|
72
|
-
const intentValue = theme.intents[intent];
|
|
73
|
-
const color = type === 'filled' ? intentValue.contrast : intentValue.primary;
|
|
29
|
+
container: (_props: AlertDynamicProps) => ({
|
|
30
|
+
display: 'flex' as const,
|
|
31
|
+
flexDirection: 'row' as const,
|
|
32
|
+
alignItems: 'flex-start' as const,
|
|
33
|
+
borderWidth: 1,
|
|
34
|
+
borderStyle: 'solid' as const,
|
|
35
|
+
variants: {
|
|
36
|
+
type: {
|
|
37
|
+
filled: {
|
|
38
|
+
backgroundColor: theme.$intents.primary,
|
|
39
|
+
borderColor: theme.$intents.primary,
|
|
40
|
+
},
|
|
41
|
+
outlined: {
|
|
42
|
+
backgroundColor: 'transparent',
|
|
43
|
+
borderColor: theme.$intents.primary,
|
|
44
|
+
},
|
|
45
|
+
soft: {
|
|
46
|
+
backgroundColor: theme.$intents.light,
|
|
47
|
+
borderColor: theme.$intents.light,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
size: {
|
|
51
|
+
gap: theme.sizes.$alert.gap,
|
|
52
|
+
padding: theme.sizes.$alert.padding,
|
|
53
|
+
borderRadius: theme.sizes.$alert.borderRadius,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
74
57
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
58
|
+
iconContainer: (_props: AlertDynamicProps) => ({
|
|
59
|
+
display: 'flex' as const,
|
|
60
|
+
alignItems: 'center' as const,
|
|
61
|
+
justifyContent: 'center' as const,
|
|
62
|
+
alignSelf: 'flex-start' as const,
|
|
63
|
+
flexShrink: 0,
|
|
64
|
+
marginTop: 2,
|
|
65
|
+
variants: {
|
|
66
|
+
type: {
|
|
67
|
+
filled: {
|
|
68
|
+
color: theme.$intents.contrast,
|
|
69
|
+
},
|
|
70
|
+
outlined: {
|
|
71
|
+
color: theme.$intents.primary,
|
|
72
|
+
},
|
|
73
|
+
soft: {
|
|
74
|
+
color: theme.$intents.primary,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
size: {
|
|
78
|
+
width: theme.sizes.$alert.iconSize,
|
|
79
|
+
height: theme.sizes.$alert.iconSize,
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
title: (_props: AlertDynamicProps) => ({
|
|
85
|
+
fontWeight: '600' as const,
|
|
86
|
+
variants: {
|
|
87
|
+
type: {
|
|
88
|
+
filled: {
|
|
89
|
+
color: theme.$intents.contrast,
|
|
90
|
+
},
|
|
91
|
+
outlined: {
|
|
92
|
+
color: theme.$intents.primary,
|
|
93
|
+
},
|
|
94
|
+
soft: {
|
|
95
|
+
color: theme.$intents.primary,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
size: {
|
|
99
|
+
fontSize: theme.sizes.$alert.titleFontSize,
|
|
100
|
+
lineHeight: theme.sizes.$alert.titleLineHeight,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
}),
|
|
86
104
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
105
|
+
message: (_props: AlertDynamicProps) => ({
|
|
106
|
+
variants: {
|
|
107
|
+
type: {
|
|
108
|
+
filled: {
|
|
109
|
+
color: theme.$intents.contrast,
|
|
110
|
+
},
|
|
111
|
+
outlined: {
|
|
112
|
+
color: theme.colors.text.primary,
|
|
113
|
+
},
|
|
114
|
+
soft: {
|
|
115
|
+
color: theme.colors.text.primary,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
size: {
|
|
119
|
+
fontSize: theme.sizes.$alert.messageFontSize,
|
|
120
|
+
lineHeight: theme.sizes.$alert.messageLineHeight,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
}),
|
|
93
124
|
|
|
94
125
|
content: (_props: AlertDynamicProps) => ({
|
|
95
126
|
flex: 1,
|
|
96
127
|
display: 'flex' as const,
|
|
97
128
|
flexDirection: 'column' as const,
|
|
98
|
-
|
|
129
|
+
variants: {
|
|
130
|
+
size: {
|
|
131
|
+
// Gap is half of the main gap
|
|
132
|
+
gap: theme.sizes.$alert.gap,
|
|
133
|
+
},
|
|
134
|
+
},
|
|
99
135
|
}),
|
|
100
136
|
|
|
101
137
|
actions: (_props: AlertDynamicProps) => ({
|
|
102
|
-
marginTop: 4,
|
|
103
138
|
display: 'flex' as const,
|
|
104
139
|
flexDirection: 'row' as const,
|
|
105
|
-
|
|
140
|
+
variants: {
|
|
141
|
+
size: {
|
|
142
|
+
marginTop: theme.sizes.$alert.gap,
|
|
143
|
+
gap: theme.sizes.$alert.gap,
|
|
144
|
+
},
|
|
145
|
+
},
|
|
106
146
|
}),
|
|
107
147
|
|
|
108
148
|
closeButton: (_props: AlertDynamicProps) => ({
|
|
109
|
-
padding: 4,
|
|
110
|
-
borderRadius: 4,
|
|
111
149
|
display: 'flex' as const,
|
|
112
150
|
alignItems: 'center' as const,
|
|
113
151
|
justifyContent: 'center' as const,
|
|
@@ -126,19 +164,43 @@ export const alertStyles = defineStyle('Alert', (theme: Theme) => ({
|
|
|
126
164
|
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
|
127
165
|
},
|
|
128
166
|
},
|
|
167
|
+
variants: {
|
|
168
|
+
size: {
|
|
169
|
+
padding: theme.sizes.$alert.padding,
|
|
170
|
+
borderRadius: theme.sizes.$alert.borderRadius,
|
|
171
|
+
},
|
|
172
|
+
},
|
|
129
173
|
}),
|
|
130
174
|
|
|
131
|
-
closeIcon: (
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
175
|
+
closeIcon: (_props: AlertDynamicProps) => ({
|
|
176
|
+
display: 'flex' as const,
|
|
177
|
+
alignItems: 'center' as const,
|
|
178
|
+
justifyContent: 'center' as const,
|
|
179
|
+
variants: {
|
|
180
|
+
type: {
|
|
181
|
+
filled: {
|
|
182
|
+
color: theme.$intents.contrast,
|
|
183
|
+
},
|
|
184
|
+
outlined: {
|
|
185
|
+
color: theme.$intents.primary,
|
|
186
|
+
},
|
|
187
|
+
soft: {
|
|
188
|
+
color: theme.$intents.primary,
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
size: {
|
|
192
|
+
width: theme.sizes.$alert.closeIconSize,
|
|
193
|
+
height: theme.sizes.$alert.closeIconSize,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
}),
|
|
144
197
|
}));
|
|
198
|
+
|
|
199
|
+
// Export theme sizes for use in components (for icon sizing in native)
|
|
200
|
+
export const alertSizeConfig = {
|
|
201
|
+
xs: { padding: 8, gap: 6, borderRadius: 4, titleFontSize: 12, titleLineHeight: 16, messageFontSize: 11, messageLineHeight: 14, iconSize: 16, closeIconSize: 12 },
|
|
202
|
+
sm: { padding: 12, gap: 8, borderRadius: 6, titleFontSize: 14, titleLineHeight: 20, messageFontSize: 12, messageLineHeight: 16, iconSize: 20, closeIconSize: 14 },
|
|
203
|
+
md: { padding: 16, gap: 10, borderRadius: 8, titleFontSize: 16, titleLineHeight: 24, messageFontSize: 14, messageLineHeight: 20, iconSize: 24, closeIconSize: 16 },
|
|
204
|
+
lg: { padding: 20, gap: 12, borderRadius: 10, titleFontSize: 18, titleLineHeight: 28, messageFontSize: 16, messageLineHeight: 24, iconSize: 28, closeIconSize: 18 },
|
|
205
|
+
xl: { padding: 24, gap: 14, borderRadius: 12, titleFontSize: 20, titleLineHeight: 32, messageFontSize: 18, messageLineHeight: 28, iconSize: 32, closeIconSize: 20 },
|
|
206
|
+
};
|
package/src/Alert/Alert.web.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import type { AlertProps } 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';
|
|
8
9
|
|
|
9
10
|
// Default icons for each intent
|
|
10
11
|
const defaultIcons: Record<string, string> = {
|
|
@@ -20,12 +21,13 @@ const defaultIcons: Record<string, string> = {
|
|
|
20
21
|
* Notification banner for displaying important messages, warnings, or status updates.
|
|
21
22
|
* Supports multiple intents, dismissibility, and custom actions.
|
|
22
23
|
*/
|
|
23
|
-
const Alert = forwardRef<
|
|
24
|
+
const Alert = forwardRef<IdealystElement, AlertProps>(({
|
|
24
25
|
title,
|
|
25
26
|
message,
|
|
26
27
|
children,
|
|
27
28
|
intent = 'neutral',
|
|
28
29
|
type = 'soft',
|
|
30
|
+
size = 'md',
|
|
29
31
|
icon,
|
|
30
32
|
showIcon = true,
|
|
31
33
|
dismissible = false,
|
|
@@ -35,14 +37,17 @@ const Alert = forwardRef<HTMLDivElement, AlertProps>(({
|
|
|
35
37
|
testID,
|
|
36
38
|
id,
|
|
37
39
|
}, ref) => {
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
+
// Apply variants for size
|
|
41
|
+
alertStyles.useVariants({ size });
|
|
42
|
+
|
|
43
|
+
// Compute dynamic styles with intent, type, and size
|
|
44
|
+
const dynamicProps = { intent, type, size };
|
|
40
45
|
const containerProps = getWebProps([(alertStyles.container as any)(dynamicProps), style as any]);
|
|
41
46
|
const iconContainerProps = getWebProps([(alertStyles.iconContainer as any)(dynamicProps)]);
|
|
42
|
-
const contentProps = getWebProps([(alertStyles.content as any)(
|
|
47
|
+
const contentProps = getWebProps([(alertStyles.content as any)(dynamicProps)]);
|
|
43
48
|
const titleProps = getWebProps([(alertStyles.title as any)(dynamicProps)]);
|
|
44
49
|
const messageProps = getWebProps([(alertStyles.message as any)(dynamicProps)]);
|
|
45
|
-
const actionsProps = getWebProps([(alertStyles.actions as any)(
|
|
50
|
+
const actionsProps = getWebProps([(alertStyles.actions as any)(dynamicProps)]);
|
|
46
51
|
const closeButtonProps = getWebProps([(alertStyles.closeButton as any)(dynamicProps)]);
|
|
47
52
|
const closeIconProps = getWebProps([(alertStyles.closeIcon as any)(dynamicProps)]);
|
|
48
53
|
|
package/src/Alert/types.ts
CHANGED
|
@@ -1,29 +1,79 @@
|
|
|
1
1
|
import type { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
-
import type { Intent } from '@idealyst/theme';
|
|
2
|
+
import type { Intent, Size } from '@idealyst/theme';
|
|
3
3
|
import { BaseProps } from '../utils/viewStyleProps';
|
|
4
4
|
|
|
5
5
|
// Component-specific type aliases for future extensibility
|
|
6
6
|
export type AlertIntentVariant = Intent;
|
|
7
|
-
export type
|
|
7
|
+
export type AlertSizeVariant = Size;
|
|
8
|
+
export type AlertType = 'filled' | 'outlined' | 'soft';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Feedback message component for displaying important information to users.
|
|
11
|
-
* Supports multiple intent colors, dismissible behavior, and custom actions.
|
|
12
|
+
* Supports multiple intent colors, sizes, dismissible behavior, and custom actions.
|
|
12
13
|
*/
|
|
13
14
|
export interface AlertProps extends BaseProps {
|
|
14
15
|
/**
|
|
15
16
|
* The title of the alert
|
|
16
17
|
*/
|
|
17
18
|
title?: string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The message content of the alert
|
|
22
|
+
*/
|
|
18
23
|
message?: string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Custom content to display in the alert
|
|
27
|
+
*/
|
|
19
28
|
children?: React.ReactNode;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The intent/color scheme of the alert
|
|
32
|
+
*/
|
|
20
33
|
intent?: AlertIntentVariant;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The visual style type of the alert
|
|
37
|
+
*/
|
|
21
38
|
type?: AlertType;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The size of the alert
|
|
42
|
+
*/
|
|
43
|
+
size?: AlertSizeVariant;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Custom icon to display. Pass `null` to hide icon.
|
|
47
|
+
*/
|
|
22
48
|
icon?: React.ReactNode;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Whether to show the default intent icon
|
|
52
|
+
*/
|
|
23
53
|
showIcon?: boolean;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Whether the alert can be dismissed
|
|
57
|
+
*/
|
|
24
58
|
dismissible?: boolean;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Called when the alert is dismissed
|
|
62
|
+
*/
|
|
25
63
|
onDismiss?: () => void;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Action buttons to display at the bottom of the alert
|
|
67
|
+
*/
|
|
26
68
|
actions?: React.ReactNode;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Additional styles
|
|
72
|
+
*/
|
|
27
73
|
style?: StyleProp<ViewStyle>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Test ID for testing
|
|
77
|
+
*/
|
|
28
78
|
testID?: string;
|
|
29
79
|
}
|