@idealyst/components 1.0.83 → 1.0.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +199 -232
- package/README.md +5 -5
- package/package.json +20 -2
- package/plugin/README.md +272 -0
- package/plugin/test-cases.jsx +112 -0
- package/plugin/web-legacy.js +320 -0
- package/plugin/web.js +422 -124
- package/src/Accordion/Accordion.native.tsx +182 -0
- package/src/Accordion/Accordion.styles.tsx +260 -0
- package/src/Accordion/Accordion.web.tsx +147 -0
- package/src/Accordion/index.native.tsx +3 -0
- package/src/Accordion/index.ts +3 -0
- package/src/Accordion/index.web.tsx +3 -0
- package/src/Accordion/types.ts +23 -0
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +17 -12
- package/src/ActivityIndicator/ActivityIndicator.styles.tsx +83 -109
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +23 -17
- package/src/ActivityIndicator/index.ts +5 -2
- package/src/ActivityIndicator/index.web.ts +5 -2
- package/src/ActivityIndicator/types.ts +15 -10
- package/src/Alert/Alert.native.tsx +113 -0
- package/src/Alert/Alert.styles.tsx +304 -0
- package/src/Alert/Alert.web.tsx +123 -0
- package/src/Alert/index.native.ts +5 -0
- package/src/Alert/index.ts +5 -0
- package/src/Alert/index.web.ts +5 -0
- package/src/Alert/types.ts +21 -0
- package/src/Avatar/Avatar.native.tsx +8 -6
- package/src/Avatar/Avatar.styles.tsx +64 -58
- package/src/Avatar/Avatar.web.tsx +13 -8
- package/src/Avatar/index.ts +5 -2
- package/src/Avatar/index.web.ts +5 -2
- package/src/Avatar/types.ts +19 -13
- package/src/Badge/Badge.native.tsx +59 -14
- package/src/Badge/Badge.styles.tsx +125 -139
- package/src/Badge/Badge.web.tsx +72 -16
- package/src/Badge/index.ts +5 -2
- package/src/Badge/index.web.ts +5 -2
- package/src/Badge/types.ts +23 -11
- package/src/Breadcrumb/Breadcrumb.native.tsx +225 -0
- package/src/Breadcrumb/Breadcrumb.styles.tsx +234 -0
- package/src/Breadcrumb/Breadcrumb.web.tsx +268 -0
- package/src/Breadcrumb/index.native.ts +5 -0
- package/src/Breadcrumb/index.ts +5 -0
- package/src/Breadcrumb/index.web.ts +5 -0
- package/src/Breadcrumb/types.ts +56 -0
- package/src/Button/Button.native.tsx +75 -24
- package/src/Button/Button.styles.tsx +248 -205
- package/src/Button/Button.web.tsx +82 -25
- package/src/Button/index.ts +5 -5
- package/src/Button/index.web.ts +5 -3
- package/src/Button/types.ts +32 -15
- package/src/Card/Card.native.tsx +14 -11
- package/src/Card/Card.styles.tsx +146 -220
- package/src/Card/Card.web.tsx +20 -21
- package/src/Card/index.ts +5 -5
- package/src/Card/index.web.ts +5 -3
- package/src/Card/types.ts +24 -17
- package/src/Checkbox/Checkbox.native.tsx +24 -34
- package/src/Checkbox/Checkbox.styles.tsx +223 -275
- package/src/Checkbox/Checkbox.web.tsx +30 -37
- package/src/Checkbox/index.ts +5 -5
- package/src/Checkbox/index.web.ts +5 -3
- package/src/Checkbox/types.ts +26 -20
- package/src/Chip/Chip.native.tsx +126 -0
- package/src/Chip/Chip.styles.tsx +138 -0
- package/src/Chip/Chip.web.tsx +154 -0
- package/src/Chip/index.native.ts +5 -0
- package/src/Chip/index.ts +5 -0
- package/src/Chip/index.web.ts +5 -0
- package/src/Chip/types.ts +51 -0
- package/src/Dialog/Dialog.native.tsx +65 -12
- package/src/Dialog/Dialog.styles.tsx +154 -136
- package/src/Dialog/Dialog.web.tsx +16 -11
- package/src/Dialog/index.ts +5 -2
- package/src/Dialog/index.web.ts +5 -2
- package/src/Dialog/types.ts +22 -16
- package/src/Divider/Divider.native.tsx +19 -14
- package/src/Divider/Divider.styles.tsx +273 -595
- package/src/Divider/Divider.web.tsx +19 -12
- package/src/Divider/index.ts +5 -5
- package/src/Divider/index.web.ts +5 -3
- package/src/Divider/types.ts +28 -19
- package/src/Icon/Icon.native.tsx +17 -24
- package/src/Icon/Icon.styles.tsx +64 -48
- package/src/Icon/Icon.web.tsx +14 -11
- package/src/Icon/IconSvg/IconSvg.native.tsx +42 -0
- package/src/Icon/IconSvg/IconSvg.web.tsx +40 -0
- package/src/Icon/IconSvg/index.native.ts +1 -0
- package/src/Icon/IconSvg/index.ts +1 -0
- package/src/Icon/icon-resolver.native.ts +27 -0
- package/src/Icon/icon-resolver.ts +70 -0
- package/src/Icon/index.ts +5 -5
- package/src/Icon/index.web.ts +5 -3
- package/src/Icon/types.ts +17 -11
- package/src/Image/Image.native.tsx +86 -0
- package/src/Image/Image.styles.tsx +57 -0
- package/src/Image/Image.web.tsx +92 -0
- package/src/Image/index.native.ts +5 -0
- package/src/Image/index.ts +5 -0
- package/src/Image/types.ts +21 -0
- package/src/Input/Input.native.tsx +103 -26
- package/src/Input/Input.styles.tsx +240 -177
- package/src/Input/Input.web.tsx +141 -38
- package/src/Input/index.ts +5 -5
- package/src/Input/index.web.ts +5 -3
- package/src/Input/types.ts +43 -20
- package/src/List/List.native.tsx +56 -0
- package/src/List/List.styles.tsx +257 -0
- package/src/List/List.web.tsx +43 -0
- package/src/List/ListContext.tsx +16 -0
- package/src/List/ListItem.native.tsx +111 -0
- package/src/List/ListItem.web.tsx +110 -0
- package/src/List/ListSection.native.tsx +31 -0
- package/src/List/ListSection.web.tsx +33 -0
- package/src/List/index.native.tsx +5 -0
- package/src/List/index.ts +5 -0
- package/src/List/index.web.tsx +5 -0
- package/src/List/types.ts +42 -0
- package/src/Menu/Menu.native.tsx +150 -0
- package/src/Menu/Menu.styles.tsx +185 -0
- package/src/Menu/Menu.web.tsx +99 -0
- package/src/Menu/MenuItem.native.tsx +66 -0
- package/src/Menu/MenuItem.styles.tsx +119 -0
- package/src/Menu/MenuItem.web.tsx +67 -0
- package/src/Menu/index.native.ts +3 -0
- package/src/Menu/index.ts +3 -0
- package/src/Menu/index.web.ts +3 -0
- package/src/Menu/types.ts +30 -0
- package/src/Popover/Popover.native.tsx +102 -32
- package/src/Popover/Popover.styles.tsx +100 -67
- package/src/Popover/Popover.web.tsx +36 -260
- package/src/Popover/index.ts +5 -2
- package/src/Popover/index.web.ts +5 -2
- package/src/Popover/types.ts +14 -13
- package/src/Pressable/Pressable.native.tsx +7 -6
- package/src/Pressable/Pressable.web.tsx +8 -6
- package/src/Pressable/index.ts +5 -2
- package/src/Pressable/index.web.ts +5 -2
- package/src/Pressable/types.ts +11 -10
- package/src/Progress/Progress.native.tsx +179 -0
- package/src/Progress/Progress.styles.tsx +164 -0
- package/src/Progress/Progress.web.tsx +144 -0
- package/src/Progress/index.native.ts +1 -0
- package/src/Progress/index.ts +5 -0
- package/src/Progress/index.web.ts +5 -0
- package/src/Progress/types.ts +21 -0
- package/src/RadioButton/RadioButton.native.tsx +88 -0
- package/src/RadioButton/RadioButton.styles.tsx +163 -0
- package/src/RadioButton/RadioButton.web.tsx +85 -0
- package/src/RadioButton/RadioGroup.native.tsx +43 -0
- package/src/RadioButton/RadioGroup.web.tsx +49 -0
- package/src/RadioButton/index.native.ts +2 -0
- package/src/RadioButton/index.ts +2 -0
- package/src/RadioButton/index.web.ts +2 -0
- package/src/RadioButton/types.ts +29 -0
- package/src/SVGImage/SVGImage.native.tsx +9 -7
- package/src/SVGImage/SVGImage.styles.tsx +63 -55
- package/src/SVGImage/SVGImage.web.tsx +16 -13
- package/src/SVGImage/index.ts +5 -5
- package/src/SVGImage/index.web.ts +5 -2
- package/src/SVGImage/types.ts +7 -3
- package/src/Screen/Screen.native.tsx +43 -17
- package/src/Screen/Screen.styles.tsx +58 -54
- package/src/Screen/Screen.web.tsx +11 -5
- package/src/Screen/index.ts +5 -2
- package/src/Screen/index.web.ts +5 -2
- package/src/Screen/types.ts +23 -9
- package/src/Select/Select.native.tsx +140 -63
- package/src/Select/Select.styles.tsx +312 -302
- package/src/Select/Select.web.tsx +156 -316
- package/src/Select/index.ts +5 -2
- package/src/Select/index.web.ts +5 -2
- package/src/Select/types.ts +13 -7
- package/src/Skeleton/Skeleton.native.tsx +139 -0
- package/src/Skeleton/Skeleton.styles.tsx +59 -0
- package/src/Skeleton/Skeleton.web.tsx +112 -0
- package/src/Skeleton/index.native.ts +4 -0
- package/src/Skeleton/index.ts +5 -0
- package/src/Skeleton/index.web.ts +5 -0
- package/src/Skeleton/types.ts +75 -0
- package/src/Slider/Slider.native.tsx +248 -0
- package/src/Slider/Slider.styles.tsx +241 -0
- package/src/Slider/Slider.web.tsx +226 -0
- package/src/Slider/index.native.ts +3 -0
- package/src/Slider/index.ts +5 -0
- package/src/Slider/index.web.ts +5 -0
- package/src/Slider/types.ts +31 -0
- package/src/Switch/Switch.native.tsx +131 -0
- package/src/Switch/Switch.styles.tsx +169 -0
- package/src/Switch/Switch.web.tsx +121 -0
- package/src/Switch/index.native.ts +3 -0
- package/src/Switch/index.ts +5 -0
- package/src/Switch/index.web.ts +5 -0
- package/src/Switch/types.ts +21 -0
- package/src/TabBar/TabBar.native.tsx +142 -0
- package/src/TabBar/TabBar.styles.tsx +399 -0
- package/src/TabBar/TabBar.web.tsx +205 -0
- package/src/TabBar/index.native.tsx +3 -0
- package/src/TabBar/index.ts +3 -0
- package/src/TabBar/index.web.tsx +3 -0
- package/src/TabBar/types.ts +26 -0
- package/src/Table/Table.native.tsx +122 -0
- package/src/Table/Table.styles.tsx +283 -0
- package/src/Table/Table.web.tsx +112 -0
- package/src/Table/index.native.tsx +3 -0
- package/src/Table/index.ts +3 -0
- package/src/Table/index.web.tsx +3 -0
- package/src/Table/types.ts +28 -0
- package/src/Text/Text.native.tsx +12 -11
- package/src/Text/Text.styles.tsx +76 -64
- package/src/Text/Text.web.tsx +14 -9
- package/src/Text/index.ts +5 -5
- package/src/Text/index.web.ts +5 -3
- package/src/Text/types.ts +20 -13
- package/src/TextArea/TextArea.native.tsx +134 -0
- package/src/TextArea/TextArea.styles.tsx +175 -0
- package/src/TextArea/TextArea.web.tsx +156 -0
- package/src/TextArea/index.native.ts +3 -0
- package/src/TextArea/index.ts +3 -0
- package/src/TextArea/index.web.ts +3 -0
- package/src/TextArea/types.ts +30 -0
- package/src/Tooltip/Tooltip.native.tsx +165 -0
- package/src/Tooltip/Tooltip.styles.tsx +73 -0
- package/src/Tooltip/Tooltip.web.tsx +87 -0
- package/src/Tooltip/index.native.ts +3 -0
- package/src/Tooltip/index.ts +3 -0
- package/src/Tooltip/types.ts +18 -0
- package/src/Video/Video.native.tsx +105 -0
- package/src/Video/Video.styles.tsx +39 -0
- package/src/Video/Video.web.tsx +115 -0
- package/src/Video/index.native.ts +5 -0
- package/src/Video/index.ts +5 -0
- package/src/Video/types.ts +29 -0
- package/src/View/View.native.tsx +9 -14
- package/src/View/View.styles.tsx +101 -93
- package/src/View/View.web.tsx +16 -17
- package/src/View/index.ts +5 -5
- package/src/View/index.web.ts +5 -3
- package/src/View/types.ts +29 -21
- package/src/examples/AccordionExamples.tsx +126 -0
- package/src/examples/AlertExamples.tsx +280 -0
- package/src/examples/AvatarExamples.tsx +23 -23
- package/src/examples/BadgeExamples.tsx +109 -41
- package/src/examples/BreadcrumbExamples.tsx +312 -0
- package/src/examples/ButtonExamples.tsx +160 -33
- package/src/examples/CardExamples.tsx +40 -40
- package/src/examples/CheckboxExamples.tsx +12 -12
- package/src/examples/ChipExamples.tsx +197 -0
- package/src/examples/DialogExamples.tsx +22 -22
- package/src/examples/DividerExamples.tsx +49 -49
- package/src/examples/IconExamples.tsx +270 -54
- package/src/examples/ImageExamples.tsx +174 -0
- package/src/examples/InputExamples.tsx +75 -17
- package/src/examples/ListExamples.tsx +288 -0
- package/src/examples/MenuExamples.tsx +144 -0
- package/src/examples/PopoverExamples.tsx +69 -73
- package/src/examples/ProgressExamples.tsx +137 -0
- package/src/examples/RadioButtonExamples.tsx +161 -0
- package/src/examples/SVGImageExamples.tsx +19 -17
- package/src/examples/ScreenExamples.tsx +31 -31
- package/src/examples/SelectExamples.tsx +67 -67
- package/src/examples/SkeletonExamples.tsx +206 -0
- package/src/examples/SliderExamples.tsx +200 -0
- package/src/examples/SwitchExamples.tsx +182 -0
- package/src/examples/TabBarExamples.tsx +143 -0
- package/src/examples/TableExamples.tsx +280 -0
- package/src/examples/TextAreaExamples.tsx +173 -0
- package/src/examples/TextExamples.tsx +28 -32
- package/src/examples/ThemeExtensionExamples.tsx +10 -10
- package/src/examples/TooltipExamples.tsx +126 -0
- package/src/examples/VideoExamples.tsx +144 -0
- package/src/examples/ViewExamples.tsx +64 -56
- package/src/examples/index.ts +17 -3
- package/src/hooks/useMergeRefs.ts +16 -0
- package/src/hooks/useSmartPosition.native.ts +169 -0
- package/src/index.native.ts +80 -9
- package/src/index.ts +71 -1
- package/src/internal/BoundedModalContent.native.tsx +58 -0
- package/src/internal/PositionedPortal.tsx +254 -0
- package/src/internal/SafeAreaDebugOverlay.native.tsx +173 -0
- package/src/unistyles.d.ts +6 -0
- package/src/utils/buildSizeVariants.ts +16 -0
- package/src/utils/deepMerge.ts +43 -0
- package/src/utils/positionUtils.native.ts +280 -0
- package/src/utils/styleHelpers.ts +48 -0
- package/LLM-ACCESS-GUIDE.md +0 -143
- package/src/ActivityIndicator/README.md +0 -132
- package/src/Avatar/README.md +0 -139
- package/src/Badge/README.md +0 -170
- package/src/Button/Button.types.ts +0 -12
- package/src/Button/README.md +0 -262
- package/src/Card/README.md +0 -258
- package/src/Checkbox/README.md +0 -102
- package/src/Dialog/README.md +0 -210
- package/src/Divider/README.md +0 -108
- package/src/Icon/README.md +0 -81
- package/src/Input/README.md +0 -100
- package/src/SVGImage/README.md +0 -209
- package/src/Screen/README.md +0 -86
- package/src/Select/README.md +0 -166
- package/src/Text/README.md +0 -94
- package/src/View/README.md +0 -107
- package/src/examples/AllExamples.tsx +0 -88
- package/src/examples/README.md +0 -136
- package/src/examples/ValidationExamples.tsx +0 -95
- package/src/examples/extendedTheme.ts +0 -329
- package/src/theme/breakpoints.ts +0 -8
- package/src/theme/colorResolver.ts +0 -218
- package/src/theme/colors.ts +0 -315
- package/src/theme/defaultThemes.ts +0 -326
- package/src/theme/index.ts +0 -188
- package/src/theme/themeBuilder.ts +0 -602
- package/src/theme/unistyles.d.ts +0 -6
- package/src/theme/variantHelpers.ts +0 -584
- package/src/theme/variants.ts +0 -56
|
@@ -1,51 +1,55 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
2
|
import { getWebProps } from 'react-native-unistyles/web';
|
|
3
3
|
import { DividerProps } from './types';
|
|
4
4
|
import { dividerStyles } from './Divider.styles';
|
|
5
|
+
import useMergeRefs from '../hooks/useMergeRefs';
|
|
5
6
|
|
|
6
|
-
const Divider
|
|
7
|
+
const Divider = forwardRef<HTMLDivElement, DividerProps>(({
|
|
7
8
|
orientation = 'horizontal',
|
|
8
|
-
|
|
9
|
+
type = 'solid',
|
|
9
10
|
thickness = 'thin',
|
|
10
11
|
intent = 'neutral',
|
|
11
12
|
length = 'full',
|
|
12
|
-
spacing = '
|
|
13
|
+
spacing = 'md',
|
|
13
14
|
children,
|
|
14
15
|
style,
|
|
15
16
|
testID,
|
|
16
17
|
accessibilityLabel,
|
|
17
|
-
}) => {
|
|
18
|
+
}, ref) => {
|
|
18
19
|
// Apply variants for main divider
|
|
19
20
|
dividerStyles.useVariants({
|
|
20
21
|
orientation,
|
|
21
22
|
thickness,
|
|
22
|
-
|
|
23
|
+
type,
|
|
23
24
|
intent,
|
|
24
25
|
length: typeof length === 'number' ? 'auto' : length,
|
|
25
26
|
spacing,
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
// Create style arrays
|
|
29
|
-
const dividerStyleArray = [
|
|
30
|
-
dividerStyles.divider,
|
|
31
|
-
style,
|
|
32
|
-
].filter(Boolean);
|
|
33
30
|
|
|
34
31
|
const containerStyleArray = [dividerStyles.container];
|
|
35
32
|
const contentStyleArray = [dividerStyles.content];
|
|
36
33
|
const lineStyleArray = [dividerStyles.line];
|
|
37
34
|
|
|
38
35
|
// Generate web props
|
|
39
|
-
const dividerProps = getWebProps(
|
|
36
|
+
const dividerProps = getWebProps([
|
|
37
|
+
dividerStyles.divider,
|
|
38
|
+
style as any,
|
|
39
|
+
]);
|
|
40
40
|
const containerProps = getWebProps(containerStyleArray);
|
|
41
41
|
const contentProps = getWebProps(contentStyleArray);
|
|
42
42
|
const lineProps = getWebProps(lineStyleArray);
|
|
43
43
|
|
|
44
|
+
const mergedDividerRef = useMergeRefs(ref, dividerProps.ref);
|
|
45
|
+
const mergedContainerRef = useMergeRefs(ref, containerProps.ref);
|
|
46
|
+
|
|
44
47
|
// If no children, render simple divider
|
|
45
48
|
if (!children) {
|
|
46
49
|
return (
|
|
47
50
|
<div
|
|
48
51
|
{...dividerProps}
|
|
52
|
+
ref={mergedDividerRef}
|
|
49
53
|
data-testid={testID}
|
|
50
54
|
aria-label={accessibilityLabel}
|
|
51
55
|
role="separator"
|
|
@@ -57,6 +61,7 @@ const Divider: React.FC<DividerProps> = ({
|
|
|
57
61
|
return (
|
|
58
62
|
<div
|
|
59
63
|
{...containerProps}
|
|
64
|
+
ref={mergedContainerRef}
|
|
60
65
|
data-testid={testID}
|
|
61
66
|
aria-label={accessibilityLabel}
|
|
62
67
|
role="separator"
|
|
@@ -68,6 +73,8 @@ const Divider: React.FC<DividerProps> = ({
|
|
|
68
73
|
<div {...lineProps} />
|
|
69
74
|
</div>
|
|
70
75
|
);
|
|
71
|
-
};
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
Divider.displayName = 'Divider';
|
|
72
79
|
|
|
73
80
|
export default Divider;
|
package/src/Divider/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
export * from './types';
|
|
1
|
+
import DividerComponent from './Divider.web';
|
|
2
|
+
|
|
3
|
+
export default DividerComponent;
|
|
4
|
+
export { DividerComponent as Divider };
|
|
5
|
+
export * from './types';
|
package/src/Divider/index.web.ts
CHANGED
package/src/Divider/types.ts
CHANGED
|
@@ -1,52 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
1
|
+
import { Intent, Size } from '@idealyst/theme';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
4
|
+
|
|
5
|
+
// Component-specific type aliases for future extensibility
|
|
6
|
+
export type DividerIntentVariant = Intent;
|
|
7
|
+
export type DividerOrientationVariant = 'horizontal' | 'vertical';
|
|
8
|
+
export type DividerType = 'solid' | 'dashed' | 'dotted';
|
|
9
|
+
export type DividerThicknessVariant = 'thin' | 'md' | 'thick';
|
|
10
|
+
export type DividerLengthVariant = 'full' | 'auto' | number;
|
|
11
|
+
export type DividerSpacingVariant = 'none' | Size;
|
|
3
12
|
|
|
4
13
|
export interface DividerProps {
|
|
5
14
|
/**
|
|
6
15
|
* The orientation of the divider
|
|
7
16
|
*/
|
|
8
|
-
orientation?:
|
|
9
|
-
|
|
17
|
+
orientation?: DividerOrientationVariant;
|
|
18
|
+
|
|
10
19
|
/**
|
|
11
|
-
* The visual style
|
|
20
|
+
* The visual style type of the divider
|
|
12
21
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
type?: DividerType;
|
|
23
|
+
|
|
15
24
|
/**
|
|
16
25
|
* The thickness of the divider
|
|
17
26
|
*/
|
|
18
|
-
thickness?:
|
|
19
|
-
|
|
27
|
+
thickness?: DividerThicknessVariant;
|
|
28
|
+
|
|
20
29
|
/**
|
|
21
30
|
* The color intent of the divider
|
|
22
31
|
*/
|
|
23
|
-
intent?:
|
|
24
|
-
|
|
32
|
+
intent?: DividerIntentVariant;
|
|
33
|
+
|
|
25
34
|
/**
|
|
26
35
|
* The length of the divider (percentage or fixed)
|
|
27
36
|
*/
|
|
28
|
-
length?:
|
|
29
|
-
|
|
37
|
+
length?: DividerLengthVariant;
|
|
38
|
+
|
|
30
39
|
/**
|
|
31
40
|
* Spacing around the divider
|
|
32
41
|
*/
|
|
33
|
-
spacing?:
|
|
34
|
-
|
|
42
|
+
spacing?: DividerSpacingVariant;
|
|
43
|
+
|
|
35
44
|
/**
|
|
36
45
|
* Content to display in the center of the divider (for horizontal dividers)
|
|
37
46
|
*/
|
|
38
47
|
children?: ReactNode;
|
|
39
|
-
|
|
48
|
+
|
|
40
49
|
/**
|
|
41
50
|
* Additional styles (platform-specific)
|
|
42
51
|
*/
|
|
43
|
-
style?:
|
|
44
|
-
|
|
52
|
+
style?: StyleProp<ViewStyle>;
|
|
53
|
+
|
|
45
54
|
/**
|
|
46
55
|
* Test ID for testing
|
|
47
56
|
*/
|
|
48
57
|
testID?: string;
|
|
49
|
-
|
|
58
|
+
|
|
50
59
|
/**
|
|
51
60
|
* Accessibility label
|
|
52
61
|
*/
|
package/src/Icon/Icon.native.tsx
CHANGED
|
@@ -1,42 +1,35 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
2
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
|
3
3
|
import { IconProps } from './types';
|
|
4
|
-
import iconStyles from './Icon.styles';
|
|
4
|
+
import { iconStyles } from './Icon.styles';
|
|
5
5
|
|
|
6
|
-
const Icon
|
|
6
|
+
const Icon = forwardRef<any, IconProps>(({
|
|
7
7
|
name,
|
|
8
8
|
size = 'md',
|
|
9
9
|
color,
|
|
10
|
+
intent,
|
|
10
11
|
style,
|
|
11
12
|
testID,
|
|
12
13
|
accessibilityLabel,
|
|
13
|
-
}: IconProps) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const sizeMap = {
|
|
22
|
-
xs: 12,
|
|
23
|
-
sm: 16,
|
|
24
|
-
md: 24,
|
|
25
|
-
lg: 32,
|
|
26
|
-
xl: 48,
|
|
27
|
-
};
|
|
28
|
-
return sizeMap[size];
|
|
29
|
-
}, [])
|
|
30
|
-
|
|
14
|
+
}: IconProps, ref) => {
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
// Call dynamic style with variants
|
|
18
|
+
const iconStyle = iconStyles.icon({ color, intent, size });
|
|
19
|
+
|
|
20
|
+
// Get fontSize from styles for numeric size prop
|
|
21
|
+
|
|
31
22
|
return (
|
|
32
23
|
<MaterialCommunityIcons
|
|
24
|
+
ref={ref}
|
|
33
25
|
name={name}
|
|
34
|
-
|
|
35
|
-
style={[styles.icon, style]}
|
|
26
|
+
style={[iconStyle, style]}
|
|
36
27
|
testID={testID}
|
|
37
28
|
accessibilityLabel={accessibilityLabel}
|
|
38
29
|
/>
|
|
39
30
|
);
|
|
40
|
-
};
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
Icon.displayName = 'Icon';
|
|
41
34
|
|
|
42
35
|
export default Icon;
|
package/src/Icon/Icon.styles.tsx
CHANGED
|
@@ -1,51 +1,67 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
import {
|
|
2
|
+
import { Theme, StylesheetStyles, Intent, Color, getColorFromString } from '@idealyst/theme';
|
|
3
|
+
import { buildSizeVariants } from '../utils/buildSizeVariants';
|
|
4
|
+
import { IconSizeVariant } from './types';
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// Default theme-based color
|
|
11
|
-
color: theme.colors?.text || '#000000',
|
|
12
|
-
|
|
13
|
-
// Variants for different color schemes and sizes
|
|
14
|
-
variants: {
|
|
15
|
-
// Dynamically generated color variants using generateColorVariants helper
|
|
16
|
-
color: generateColorVariants(theme),
|
|
17
|
-
size: {
|
|
18
|
-
xs: {
|
|
19
|
-
width: 12,
|
|
20
|
-
height: 12,
|
|
21
|
-
},
|
|
22
|
-
sm: {
|
|
23
|
-
width: 16,
|
|
24
|
-
height: 16,
|
|
25
|
-
},
|
|
26
|
-
md: {
|
|
27
|
-
width: 24,
|
|
28
|
-
height: 24,
|
|
29
|
-
},
|
|
30
|
-
lg: {
|
|
31
|
-
width: 32,
|
|
32
|
-
height: 32,
|
|
33
|
-
},
|
|
34
|
-
xl: {
|
|
35
|
-
width: 48,
|
|
36
|
-
height: 48,
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
// Web-specific styles
|
|
42
|
-
_web: {
|
|
43
|
-
display: 'inline-block',
|
|
44
|
-
verticalAlign: 'middle',
|
|
45
|
-
flexShrink: 0,
|
|
46
|
-
lineHeight: 0, // Remove extra space below the icon
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
}));
|
|
6
|
+
type IconVariants = {
|
|
7
|
+
size: IconSizeVariant;
|
|
8
|
+
intent?: Intent;
|
|
9
|
+
color?: Color;
|
|
10
|
+
}
|
|
50
11
|
|
|
51
|
-
export
|
|
12
|
+
export type ExpandedIconStyles = StylesheetStyles<keyof IconVariants>;
|
|
13
|
+
|
|
14
|
+
export type IconStylesheet = {
|
|
15
|
+
icon: ExpandedIconStyles;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create color variants for icon
|
|
20
|
+
*/
|
|
21
|
+
function getIconColor(theme: Theme, color?: Color, intent?: Intent): string {
|
|
22
|
+
if (intent) {
|
|
23
|
+
return theme.intents[intent]?.primary
|
|
24
|
+
} else if (color) {
|
|
25
|
+
return getColorFromString(theme, color);
|
|
26
|
+
}
|
|
27
|
+
return theme.colors.text.primary;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function buildIconSize(theme: Theme, size: IconSizeVariant) {
|
|
31
|
+
const iconSize = theme.sizes.icon[size];
|
|
32
|
+
if (typeof iconSize === 'number') {
|
|
33
|
+
return {
|
|
34
|
+
width: iconSize,
|
|
35
|
+
height: iconSize,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return buildSizeVariants(theme, 'icon', (size) => ({
|
|
39
|
+
width: size.width,
|
|
40
|
+
height: size.height,
|
|
41
|
+
}))[size];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function createIconStyles(theme: Theme) {
|
|
45
|
+
return ({ color, intent, size }: Partial<IconVariants>) => {
|
|
46
|
+
const iconSize = buildIconSize(theme, size);
|
|
47
|
+
return {
|
|
48
|
+
width: iconSize.width,
|
|
49
|
+
height: iconSize.height,
|
|
50
|
+
color: getIconColor(theme, color, intent),
|
|
51
|
+
_web: {
|
|
52
|
+
display: 'inline-block',
|
|
53
|
+
verticalAlign: 'middle',
|
|
54
|
+
flexShrink: 0,
|
|
55
|
+
lineHeight: 0,
|
|
56
|
+
},
|
|
57
|
+
} as const;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
|
|
62
|
+
// transform on native cannot resolve function calls to extract variant structures.
|
|
63
|
+
export const iconStyles = StyleSheet.create((theme: Theme) => {
|
|
64
|
+
return {
|
|
65
|
+
icon: createIconStyles(theme),
|
|
66
|
+
} as const;
|
|
67
|
+
});
|
package/src/Icon/Icon.web.tsx
CHANGED
|
@@ -1,36 +1,38 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
2
|
import MdiIcon from '@mdi/react';
|
|
3
3
|
import { IconProps } from './types';
|
|
4
|
-
import iconStyles from './Icon.styles';
|
|
4
|
+
import { iconStyles } from './Icon.styles';
|
|
5
5
|
import { getWebProps } from 'react-native-unistyles/web';
|
|
6
|
+
import useMergeRefs from '../hooks/useMergeRefs';
|
|
6
7
|
|
|
7
8
|
// Internal props that include the transformed path from Babel plugin
|
|
8
9
|
interface InternalIconProps extends IconProps {
|
|
9
10
|
path?: string; // Added by Babel plugin transformation
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
const Icon
|
|
13
|
+
const Icon = forwardRef<HTMLDivElement, IconProps>((props: InternalIconProps, ref) => {
|
|
13
14
|
const {
|
|
14
15
|
name,
|
|
15
16
|
size = 'md',
|
|
16
17
|
color,
|
|
18
|
+
intent,
|
|
17
19
|
style,
|
|
18
20
|
testID,
|
|
19
21
|
accessibilityLabel,
|
|
20
22
|
...restProps
|
|
21
23
|
} = props;
|
|
22
24
|
|
|
23
|
-
// Use Unistyles v3 with color and size variants
|
|
24
|
-
const styles = iconStyles.useVariants({ color, size });
|
|
25
|
-
|
|
26
25
|
// Check if we have a path prop (from Babel plugin transformation)
|
|
27
26
|
const { path } = restProps as { path?: string };
|
|
28
|
-
const iconProps = getWebProps(
|
|
29
|
-
|
|
27
|
+
const iconProps = getWebProps(iconStyles.icon({ intent, color, size }));
|
|
28
|
+
|
|
29
|
+
const mergedRef = useMergeRefs(ref, iconProps.ref);
|
|
30
|
+
|
|
30
31
|
// Use MDI React icon when path is provided (transformed by Babel plugin)
|
|
31
32
|
return (
|
|
32
33
|
<div
|
|
33
|
-
{...iconProps}
|
|
34
|
+
{...iconProps}
|
|
35
|
+
ref={mergedRef}>
|
|
34
36
|
<MdiIcon
|
|
35
37
|
path={path}
|
|
36
38
|
size={'100%'}
|
|
@@ -40,7 +42,8 @@ const Icon: React.FC<IconProps> = (props: InternalIconProps) => {
|
|
|
40
42
|
/>
|
|
41
43
|
</div>
|
|
42
44
|
);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
Icon.displayName = 'Icon';
|
|
45
48
|
|
|
46
49
|
export default Icon;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import Svg, { Path } from 'react-native-svg';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Internal component for rendering SVG icons directly from MDI paths.
|
|
7
|
+
* This is used internally by components like Button, Badge, etc. to render icons
|
|
8
|
+
* without going through the full Icon component.
|
|
9
|
+
*
|
|
10
|
+
* The path prop should be provided by the Babel plugin transformation.
|
|
11
|
+
*/
|
|
12
|
+
interface IconSvgProps {
|
|
13
|
+
path?: string; // MDI icon path, provided by Babel plugin
|
|
14
|
+
size?: string | number;
|
|
15
|
+
color?: string;
|
|
16
|
+
style?: any;
|
|
17
|
+
'aria-label'?: string;
|
|
18
|
+
'data-testid'?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const IconSvg = React.forwardRef<View, IconSvgProps>(({
|
|
22
|
+
path,
|
|
23
|
+
size = 24,
|
|
24
|
+
color = 'currentColor',
|
|
25
|
+
style,
|
|
26
|
+
'data-testid': testID,
|
|
27
|
+
}, ref) => {
|
|
28
|
+
// Convert size to number if it's a string
|
|
29
|
+
const sizeNum = typeof size === 'string' ? parseFloat(size) : size;
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<View ref={ref} style={[{ width: sizeNum, height: sizeNum }, style]} testID={testID}>
|
|
33
|
+
<Svg viewBox="0 0 24 24" width={sizeNum} height={sizeNum}>
|
|
34
|
+
<Path d={path} fill={color} />
|
|
35
|
+
</Svg>
|
|
36
|
+
</View>
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
IconSvg.displayName = 'IconSvg';
|
|
41
|
+
|
|
42
|
+
export default IconSvg;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import MdiIcon from '@mdi/react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Internal component for rendering SVG icons directly from MDI paths.
|
|
6
|
+
* This is used internally by components like Button, Badge, etc. to render icons
|
|
7
|
+
* without going through the full Icon component.
|
|
8
|
+
*
|
|
9
|
+
* The path prop should be provided by the Babel plugin transformation.
|
|
10
|
+
*/
|
|
11
|
+
interface IconSvgProps {
|
|
12
|
+
path?: string; // MDI icon path, provided by Babel plugin
|
|
13
|
+
size?: string | number;
|
|
14
|
+
color?: string;
|
|
15
|
+
style?: React.CSSProperties;
|
|
16
|
+
'aria-label'?: string;
|
|
17
|
+
'data-testid'?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const IconSvg: React.FC<IconSvgProps> = ({
|
|
21
|
+
path,
|
|
22
|
+
color = 'currentColor',
|
|
23
|
+
style,
|
|
24
|
+
'aria-label': ariaLabel,
|
|
25
|
+
'data-testid': testID,
|
|
26
|
+
...rest
|
|
27
|
+
}) => {
|
|
28
|
+
return (
|
|
29
|
+
<MdiIcon
|
|
30
|
+
style={style}
|
|
31
|
+
path={path}
|
|
32
|
+
color={color}
|
|
33
|
+
aria-label={ariaLabel}
|
|
34
|
+
data-testid={testID}
|
|
35
|
+
{...rest}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default IconSvg;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { IconSvg, default } from './IconSvg.native';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { IconSvg, default } from './IconSvg.web';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native stub for icon-resolver.
|
|
3
|
+
* This file should not be used on React Native as we use react-native-vector-icons instead.
|
|
4
|
+
* If you're seeing this file being imported, check your import paths.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Stub implementation for React Native.
|
|
9
|
+
* Always returns undefined as this utility is web-only.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveIconPath(iconName: string): string | undefined {
|
|
12
|
+
if (__DEV__) {
|
|
13
|
+
console.warn(
|
|
14
|
+
`[icon-resolver.native] resolveIconPath("${iconName}") was called on React Native. ` +
|
|
15
|
+
`This is a web-only utility. Use react-native-vector-icons directly instead.`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Type guard to check if a value is an icon name string.
|
|
23
|
+
* This implementation works cross-platform.
|
|
24
|
+
*/
|
|
25
|
+
export function isIconName(icon: any): icon is string {
|
|
26
|
+
return typeof icon === 'string';
|
|
27
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime utility for resolving MDI icon names to their SVG paths.
|
|
3
|
+
* This is used when icon names are passed dynamically (e.g., in arrays)
|
|
4
|
+
* and cannot be transformed by the Babel plugin at build time.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as mdiIcons from '@mdi/js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Formats an icon name from kebab-case to the MDI export name format.
|
|
11
|
+
* Examples:
|
|
12
|
+
* "home" -> "mdiHome"
|
|
13
|
+
* "account-circle" -> "mdiAccountCircle"
|
|
14
|
+
* "star-outline" -> "mdiStarOutline"
|
|
15
|
+
*/
|
|
16
|
+
function formatIconName(name: string): string {
|
|
17
|
+
if (!name || typeof name !== 'string') {
|
|
18
|
+
return 'mdiHelpCircle';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Remove mdi: prefix if present
|
|
22
|
+
const cleanName = name.startsWith('mdi:') ? name.substring(4) : name;
|
|
23
|
+
|
|
24
|
+
// Check if the name contains only valid characters
|
|
25
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(cleanName)) {
|
|
26
|
+
console.warn(
|
|
27
|
+
`[icon-resolver] Invalid icon name "${name}" (contains special characters), using "help-circle" as fallback`
|
|
28
|
+
);
|
|
29
|
+
return 'mdiHelpCircle';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Convert kebab-case to PascalCase
|
|
33
|
+
const pascalCase = cleanName
|
|
34
|
+
.split('-')
|
|
35
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
36
|
+
.join('');
|
|
37
|
+
|
|
38
|
+
return `mdi${pascalCase}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Resolves an icon name to its SVG path data.
|
|
43
|
+
* Returns undefined if the icon is not found.
|
|
44
|
+
*
|
|
45
|
+
* @param iconName - The icon name in kebab-case (e.g., "home", "account-circle")
|
|
46
|
+
* @returns The SVG path string or undefined if not found
|
|
47
|
+
*/
|
|
48
|
+
export function resolveIconPath(iconName: string): string | undefined {
|
|
49
|
+
const mdiIconName = formatIconName(iconName);
|
|
50
|
+
const iconPath = (mdiIcons as any)[mdiIconName];
|
|
51
|
+
|
|
52
|
+
if (!iconPath) {
|
|
53
|
+
console.warn(
|
|
54
|
+
`[icon-resolver] Icon "${iconName}" (${mdiIconName}) not found in @mdi/js, using help-circle as fallback`
|
|
55
|
+
);
|
|
56
|
+
return (mdiIcons as any).mdiHelpCircle;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return iconPath;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Checks if a given value is an icon name (string) or a React component.
|
|
64
|
+
*
|
|
65
|
+
* @param icon - The icon value to check
|
|
66
|
+
* @returns true if the icon is a string (icon name), false otherwise
|
|
67
|
+
*/
|
|
68
|
+
export function isIconName(icon: any): icon is string {
|
|
69
|
+
return typeof icon === 'string';
|
|
70
|
+
}
|
package/src/Icon/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
export * from './types';
|
|
1
|
+
import IconComponent from './Icon.web';
|
|
2
|
+
|
|
3
|
+
export default IconComponent;
|
|
4
|
+
export { IconComponent as Icon };
|
|
5
|
+
export * from './types';
|
package/src/Icon/index.web.ts
CHANGED