@cdx-ui/components 0.0.1-beta.64 → 0.0.1-beta.66
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/lib/commonjs/components/AlertDialog/index.js +12 -10
- package/lib/commonjs/components/AlertDialog/index.js.map +1 -1
- package/lib/commonjs/components/Avatar/index.js +125 -25
- package/lib/commonjs/components/Avatar/index.js.map +1 -1
- package/lib/commonjs/components/Button/index.js +127 -28
- package/lib/commonjs/components/Button/index.js.map +1 -1
- package/lib/commonjs/components/Button/styles.js +9 -3
- package/lib/commonjs/components/Button/styles.js.map +1 -1
- package/lib/commonjs/components/CLAUDE.md +115 -11
- package/lib/commonjs/components/Checkbox/index.js +69 -22
- package/lib/commonjs/components/Checkbox/index.js.map +1 -1
- package/lib/commonjs/components/Checkbox/styles.js +1 -1
- package/lib/commonjs/components/Checkbox/styles.js.map +1 -1
- package/lib/commonjs/components/Chip/index.js +44 -36
- package/lib/commonjs/components/Chip/index.js.map +1 -1
- package/lib/commonjs/components/Chip/styles.js +6 -35
- package/lib/commonjs/components/Chip/styles.js.map +1 -1
- package/lib/commonjs/components/Dialog/index.js +92 -72
- package/lib/commonjs/components/Dialog/index.js.map +1 -1
- package/lib/commonjs/components/Field/index.js +70 -26
- package/lib/commonjs/components/Field/index.js.map +1 -1
- package/lib/commonjs/components/Form/index.js +5 -12
- package/lib/commonjs/components/Form/index.js.map +1 -1
- package/lib/commonjs/components/IconButton/index.js +5 -33
- package/lib/commonjs/components/IconButton/index.js.map +1 -1
- package/lib/commonjs/components/Input/index.js +50 -20
- package/lib/commonjs/components/Input/index.js.map +1 -1
- package/lib/commonjs/components/Link/index.js +14 -7
- package/lib/commonjs/components/Link/index.js.map +1 -1
- package/lib/commonjs/components/ListItem/index.js +129 -54
- package/lib/commonjs/components/ListItem/index.js.map +1 -1
- package/lib/commonjs/components/OtpInput/index.js +94 -28
- package/lib/commonjs/components/OtpInput/index.js.map +1 -1
- package/lib/commonjs/components/ProgressBar/index.js +8 -13
- package/lib/commonjs/components/ProgressBar/index.js.map +1 -1
- package/lib/commonjs/components/Radio/index.js +51 -53
- package/lib/commonjs/components/Radio/index.js.map +1 -1
- package/lib/commonjs/components/Select/index.js +112 -46
- package/lib/commonjs/components/Select/index.js.map +1 -1
- package/lib/commonjs/components/Select/styles.js +2 -2
- package/lib/commonjs/components/Select/styles.js.map +1 -1
- package/lib/commonjs/components/Skeleton/index.js +37 -0
- package/lib/commonjs/components/Skeleton/index.js.map +1 -0
- package/lib/commonjs/components/Skeleton/styles.js +9 -0
- package/lib/commonjs/components/Skeleton/styles.js.map +1 -0
- package/lib/commonjs/components/Switch/BaseSwitch.js +23 -13
- package/lib/commonjs/components/Switch/BaseSwitch.js.map +1 -1
- package/lib/commonjs/components/Switch/BaseSwitch.web.js +25 -21
- package/lib/commonjs/components/Switch/BaseSwitch.web.js.map +1 -1
- package/lib/commonjs/components/Switch/index.js +34 -3
- package/lib/commonjs/components/Switch/index.js.map +1 -1
- package/lib/commonjs/components/Tile/index.js +150 -77
- package/lib/commonjs/components/Tile/index.js.map +1 -1
- package/lib/commonjs/components/index.js +12 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/figma/Chip.figma.js +2 -2
- package/lib/commonjs/figma/Chip.figma.js.map +1 -1
- package/lib/commonjs/utils/positionToDataIcon.js +41 -0
- package/lib/commonjs/utils/positionToDataIcon.js.map +1 -0
- package/lib/module/components/AlertDialog/index.js +13 -11
- package/lib/module/components/AlertDialog/index.js.map +1 -1
- package/lib/module/components/Avatar/index.js +128 -28
- package/lib/module/components/Avatar/index.js.map +1 -1
- package/lib/module/components/Button/index.js +130 -32
- package/lib/module/components/Button/index.js.map +1 -1
- package/lib/module/components/Button/styles.js +8 -2
- package/lib/module/components/Button/styles.js.map +1 -1
- package/lib/module/components/CLAUDE.md +115 -11
- package/lib/module/components/Checkbox/index.js +72 -25
- package/lib/module/components/Checkbox/index.js.map +1 -1
- package/lib/module/components/Checkbox/styles.js +1 -1
- package/lib/module/components/Checkbox/styles.js.map +1 -1
- package/lib/module/components/Chip/index.js +47 -39
- package/lib/module/components/Chip/index.js.map +1 -1
- package/lib/module/components/Chip/styles.js +6 -35
- package/lib/module/components/Chip/styles.js.map +1 -1
- package/lib/module/components/Dialog/index.js +96 -76
- package/lib/module/components/Dialog/index.js.map +1 -1
- package/lib/module/components/Field/index.js +74 -31
- package/lib/module/components/Field/index.js.map +1 -1
- package/lib/module/components/Form/index.js +7 -14
- package/lib/module/components/Form/index.js.map +1 -1
- package/lib/module/components/IconButton/index.js +6 -34
- package/lib/module/components/IconButton/index.js.map +1 -1
- package/lib/module/components/Input/index.js +53 -23
- package/lib/module/components/Input/index.js.map +1 -1
- package/lib/module/components/Link/index.js +16 -8
- package/lib/module/components/Link/index.js.map +1 -1
- package/lib/module/components/ListItem/index.js +134 -59
- package/lib/module/components/ListItem/index.js.map +1 -1
- package/lib/module/components/OtpInput/index.js +94 -28
- package/lib/module/components/OtpInput/index.js.map +1 -1
- package/lib/module/components/ProgressBar/index.js +9 -14
- package/lib/module/components/ProgressBar/index.js.map +1 -1
- package/lib/module/components/Radio/index.js +54 -57
- package/lib/module/components/Radio/index.js.map +1 -1
- package/lib/module/components/Select/index.js +118 -52
- package/lib/module/components/Select/index.js.map +1 -1
- package/lib/module/components/Select/styles.js +2 -2
- package/lib/module/components/Select/styles.js.map +1 -1
- package/lib/module/components/Skeleton/index.js +32 -0
- package/lib/module/components/Skeleton/index.js.map +1 -0
- package/lib/module/components/Skeleton/styles.js +5 -0
- package/lib/module/components/Skeleton/styles.js.map +1 -0
- package/lib/module/components/Switch/BaseSwitch.js +24 -14
- package/lib/module/components/Switch/BaseSwitch.js.map +1 -1
- package/lib/module/components/Switch/BaseSwitch.web.js +26 -22
- package/lib/module/components/Switch/BaseSwitch.web.js.map +1 -1
- package/lib/module/components/Switch/index.js +35 -4
- package/lib/module/components/Switch/index.js.map +1 -1
- package/lib/module/components/Tile/index.js +155 -83
- package/lib/module/components/Tile/index.js.map +1 -1
- package/lib/module/components/index.js +1 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/figma/Chip.figma.js +2 -2
- package/lib/module/figma/Chip.figma.js.map +1 -1
- package/lib/module/utils/positionToDataIcon.js +38 -0
- package/lib/module/utils/positionToDataIcon.js.map +1 -0
- package/lib/typescript/components/AlertDialog/index.d.ts.map +1 -1
- package/lib/typescript/components/Avatar/index.d.ts +6 -2
- package/lib/typescript/components/Avatar/index.d.ts.map +1 -1
- package/lib/typescript/components/Button/index.d.ts +31 -8
- package/lib/typescript/components/Button/index.d.ts.map +1 -1
- package/lib/typescript/components/Button/styles.d.ts +2 -1
- package/lib/typescript/components/Button/styles.d.ts.map +1 -1
- package/lib/typescript/components/Checkbox/index.d.ts +3 -1
- package/lib/typescript/components/Checkbox/index.d.ts.map +1 -1
- package/lib/typescript/components/Chip/index.d.ts +19 -9
- package/lib/typescript/components/Chip/index.d.ts.map +1 -1
- package/lib/typescript/components/Chip/styles.d.ts +0 -1
- package/lib/typescript/components/Chip/styles.d.ts.map +1 -1
- package/lib/typescript/components/Dialog/index.d.ts +12 -6
- package/lib/typescript/components/Dialog/index.d.ts.map +1 -1
- package/lib/typescript/components/Dialog/styles.d.ts +1 -1
- package/lib/typescript/components/Field/index.d.ts +14 -7
- package/lib/typescript/components/Field/index.d.ts.map +1 -1
- package/lib/typescript/components/Form/index.d.ts +4 -4
- package/lib/typescript/components/Form/index.d.ts.map +1 -1
- package/lib/typescript/components/IconButton/index.d.ts.map +1 -1
- package/lib/typescript/components/Input/index.d.ts +11 -3
- package/lib/typescript/components/Input/index.d.ts.map +1 -1
- package/lib/typescript/components/Link/index.d.ts +2 -0
- package/lib/typescript/components/Link/index.d.ts.map +1 -1
- package/lib/typescript/components/ListItem/index.d.ts +28 -6
- package/lib/typescript/components/ListItem/index.d.ts.map +1 -1
- package/lib/typescript/components/OtpInput/index.d.ts +1 -1
- package/lib/typescript/components/OtpInput/index.d.ts.map +1 -1
- package/lib/typescript/components/ProgressBar/index.d.ts +4 -4
- package/lib/typescript/components/ProgressBar/index.d.ts.map +1 -1
- package/lib/typescript/components/Radio/index.d.ts +4 -0
- package/lib/typescript/components/Radio/index.d.ts.map +1 -1
- package/lib/typescript/components/Select/index.d.ts +35 -2
- package/lib/typescript/components/Select/index.d.ts.map +1 -1
- package/lib/typescript/components/Select/styles.d.ts.map +1 -1
- package/lib/typescript/components/Skeleton/index.d.ts +9 -0
- package/lib/typescript/components/Skeleton/index.d.ts.map +1 -0
- package/lib/typescript/components/Skeleton/styles.d.ts +4 -0
- package/lib/typescript/components/Skeleton/styles.d.ts.map +1 -0
- package/lib/typescript/components/Switch/BaseSwitch.d.ts +12 -5
- package/lib/typescript/components/Switch/BaseSwitch.d.ts.map +1 -1
- package/lib/typescript/components/Switch/BaseSwitch.web.d.ts +11 -5
- package/lib/typescript/components/Switch/BaseSwitch.web.d.ts.map +1 -1
- package/lib/typescript/components/Switch/index.d.ts +5 -1
- package/lib/typescript/components/Switch/index.d.ts.map +1 -1
- package/lib/typescript/components/Tile/index.d.ts +8 -2
- package/lib/typescript/components/Tile/index.d.ts.map +1 -1
- package/lib/typescript/components/index.d.ts +1 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/utils/positionToDataIcon.d.ts +29 -0
- package/lib/typescript/utils/positionToDataIcon.d.ts.map +1 -0
- package/package.json +5 -5
- package/src/components/AlertDialog/index.tsx +13 -14
- package/src/components/Avatar/index.tsx +134 -44
- package/src/components/Button/index.tsx +216 -44
- package/src/components/Button/styles.ts +50 -38
- package/src/components/CLAUDE.md +115 -11
- package/src/components/Checkbox/index.tsx +93 -32
- package/src/components/Checkbox/styles.ts +1 -1
- package/src/components/Chip/index.tsx +88 -61
- package/src/components/Chip/styles.ts +6 -18
- package/src/components/Dialog/index.tsx +139 -99
- package/src/components/Field/index.tsx +113 -49
- package/src/components/Form/index.tsx +18 -14
- package/src/components/IconButton/index.tsx +7 -31
- package/src/components/Input/index.tsx +75 -32
- package/src/components/Link/index.tsx +38 -12
- package/src/components/ListItem/index.tsx +158 -73
- package/src/components/OtpInput/index.tsx +126 -43
- package/src/components/ProgressBar/index.tsx +11 -16
- package/src/components/Radio/index.tsx +76 -54
- package/src/components/Select/index.tsx +174 -59
- package/src/components/Select/styles.ts +1 -2
- package/src/components/Skeleton/index.tsx +42 -0
- package/src/components/Skeleton/styles.ts +5 -0
- package/src/components/Switch/BaseSwitch.tsx +38 -16
- package/src/components/Switch/BaseSwitch.web.tsx +28 -35
- package/src/components/Switch/index.tsx +51 -4
- package/src/components/Tile/index.tsx +145 -94
- package/src/components/index.ts +1 -0
- package/src/utils/positionToDataIcon.ts +34 -0
- package/lib/commonjs/components/Field/FieldLabel.js +0 -33
- package/lib/commonjs/components/Field/FieldLabel.js.map +0 -1
- package/lib/commonjs/components/Field/FieldLabel.web.js +0 -22
- package/lib/commonjs/components/Field/FieldLabel.web.js.map +0 -1
- package/lib/commonjs/components/Form/FormRoot.js +0 -25
- package/lib/commonjs/components/Form/FormRoot.js.map +0 -1
- package/lib/commonjs/components/Form/FormRoot.web.js +0 -17
- package/lib/commonjs/components/Form/FormRoot.web.js.map +0 -1
- package/lib/commonjs/components/Input/BaseInput.android.js +0 -20
- package/lib/commonjs/components/Input/BaseInput.android.js.map +0 -1
- package/lib/commonjs/components/Input/BaseInput.js +0 -13
- package/lib/commonjs/components/Input/BaseInput.js.map +0 -1
- package/lib/commonjs/components/Input/BaseInput.web.js +0 -50
- package/lib/commonjs/components/Input/BaseInput.web.js.map +0 -1
- package/lib/commonjs/components/Select/SelectTriggerHost.js +0 -10
- package/lib/commonjs/components/Select/SelectTriggerHost.js.map +0 -1
- package/lib/commonjs/components/Select/SelectTriggerHost.web.js +0 -102
- package/lib/commonjs/components/Select/SelectTriggerHost.web.js.map +0 -1
- package/lib/module/components/Field/FieldLabel.js +0 -29
- package/lib/module/components/Field/FieldLabel.js.map +0 -1
- package/lib/module/components/Field/FieldLabel.web.js +0 -17
- package/lib/module/components/Field/FieldLabel.web.js.map +0 -1
- package/lib/module/components/Form/FormRoot.js +0 -21
- package/lib/module/components/Form/FormRoot.js.map +0 -1
- package/lib/module/components/Form/FormRoot.web.js +0 -12
- package/lib/module/components/Form/FormRoot.web.js.map +0 -1
- package/lib/module/components/Input/BaseInput.android.js +0 -16
- package/lib/module/components/Input/BaseInput.android.js.map +0 -1
- package/lib/module/components/Input/BaseInput.js +0 -4
- package/lib/module/components/Input/BaseInput.js.map +0 -1
- package/lib/module/components/Input/BaseInput.web.js +0 -45
- package/lib/module/components/Input/BaseInput.web.js.map +0 -1
- package/lib/module/components/Select/SelectTriggerHost.js +0 -7
- package/lib/module/components/Select/SelectTriggerHost.js.map +0 -1
- package/lib/module/components/Select/SelectTriggerHost.web.js +0 -97
- package/lib/module/components/Select/SelectTriggerHost.web.js.map +0 -1
- package/lib/typescript/components/Field/FieldLabel.d.ts +0 -18
- package/lib/typescript/components/Field/FieldLabel.d.ts.map +0 -1
- package/lib/typescript/components/Field/FieldLabel.web.d.ts +0 -16
- package/lib/typescript/components/Field/FieldLabel.web.d.ts.map +0 -1
- package/lib/typescript/components/Form/FormRoot.d.ts +0 -14
- package/lib/typescript/components/Form/FormRoot.d.ts.map +0 -1
- package/lib/typescript/components/Form/FormRoot.web.d.ts +0 -10
- package/lib/typescript/components/Form/FormRoot.web.d.ts.map +0 -1
- package/lib/typescript/components/Input/BaseInput.android.d.ts +0 -3
- package/lib/typescript/components/Input/BaseInput.android.d.ts.map +0 -1
- package/lib/typescript/components/Input/BaseInput.d.ts +0 -2
- package/lib/typescript/components/Input/BaseInput.d.ts.map +0 -1
- package/lib/typescript/components/Input/BaseInput.web.d.ts +0 -3
- package/lib/typescript/components/Input/BaseInput.web.d.ts.map +0 -1
- package/lib/typescript/components/Select/SelectTriggerHost.d.ts +0 -3
- package/lib/typescript/components/Select/SelectTriggerHost.d.ts.map +0 -1
- package/lib/typescript/components/Select/SelectTriggerHost.web.d.ts +0 -16
- package/lib/typescript/components/Select/SelectTriggerHost.web.d.ts.map +0 -1
- package/src/components/Field/FieldLabel.tsx +0 -33
- package/src/components/Field/FieldLabel.web.tsx +0 -25
- package/src/components/Form/FormRoot.tsx +0 -20
- package/src/components/Form/FormRoot.web.tsx +0 -12
- package/src/components/Input/BaseInput.android.tsx +0 -13
- package/src/components/Input/BaseInput.tsx +0 -1
- package/src/components/Input/BaseInput.web.tsx +0 -41
- package/src/components/Select/SelectTriggerHost.tsx +0 -4
- package/src/components/Select/SelectTriggerHost.web.tsx +0 -143
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import { forwardRef, type ReactNode } from 'react';
|
|
1
|
+
import { forwardRef, useEffect, useMemo, type ReactNode } from 'react';
|
|
2
2
|
import { Image, Text, View, type ImageProps, type TextProps, type ViewProps } from 'react-native';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
AvatarRoot as AvatarRootPrimitive,
|
|
5
|
+
Slot,
|
|
6
|
+
dataAttributes,
|
|
7
|
+
mergeDataAttributes,
|
|
8
|
+
useAvatarContext,
|
|
9
|
+
type IAvatarImageProps,
|
|
10
|
+
type IAvatarProps,
|
|
11
|
+
} from '@cdx-ui/primitives';
|
|
12
|
+
import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
|
|
5
13
|
import { Icon as IconComponent, type IconProps } from '../Icon';
|
|
6
14
|
import {
|
|
7
15
|
type AvatarVariantProps,
|
|
@@ -14,17 +22,29 @@ import {
|
|
|
14
22
|
|
|
15
23
|
const SCOPE = 'AVATAR';
|
|
16
24
|
|
|
17
|
-
const Root = withStyleContext(View, SCOPE);
|
|
18
|
-
|
|
19
25
|
const useAvatarStyleContext = () => useStyleContext(SCOPE) as AvatarVariantProps;
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// UTILITIES
|
|
29
|
+
// =============================================================================
|
|
30
|
+
|
|
31
|
+
function getInitials(name: string): string {
|
|
32
|
+
const trimmed = name.trim();
|
|
33
|
+
const words = trimmed.split(/\s+/);
|
|
34
|
+
|
|
35
|
+
if (words.length === 1 && trimmed.length <= 2) {
|
|
36
|
+
return trimmed.toUpperCase();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let result = '';
|
|
40
|
+
for (const word of words) {
|
|
41
|
+
if (word.length > 0) {
|
|
42
|
+
result += word.charAt(0);
|
|
43
|
+
}
|
|
44
|
+
if (result.length >= 2) break;
|
|
45
|
+
}
|
|
46
|
+
return result.toUpperCase();
|
|
47
|
+
}
|
|
28
48
|
|
|
29
49
|
// =============================================================================
|
|
30
50
|
// AVATAR ROOT
|
|
@@ -39,16 +59,21 @@ const AvatarRoot = forwardRef<View, AvatarProps>(
|
|
|
39
59
|
({ size = 'md', className, children, style, ...props }, ref) => {
|
|
40
60
|
const computedClassName = cn(avatarRootVariants({ size }), className);
|
|
41
61
|
|
|
62
|
+
const parent = useParentContext();
|
|
63
|
+
const ctx = useMemo(() => ({ ...parent, [SCOPE]: { size } }), [parent, size]);
|
|
64
|
+
|
|
42
65
|
return (
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
66
|
+
<ParentContext.Provider value={ctx}>
|
|
67
|
+
<AvatarRootPrimitive
|
|
68
|
+
ref={ref}
|
|
69
|
+
className={computedClassName}
|
|
70
|
+
style={style}
|
|
71
|
+
{...props}
|
|
72
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'avatar' }))}
|
|
73
|
+
>
|
|
74
|
+
{children}
|
|
75
|
+
</AvatarRootPrimitive>
|
|
76
|
+
</ParentContext.Provider>
|
|
52
77
|
);
|
|
53
78
|
},
|
|
54
79
|
);
|
|
@@ -60,21 +85,52 @@ AvatarRoot.displayName = 'Avatar';
|
|
|
60
85
|
// =============================================================================
|
|
61
86
|
|
|
62
87
|
export interface AvatarImageProps extends Omit<ImageProps, 'source'>, IAvatarImageProps {
|
|
88
|
+
asChild?: boolean;
|
|
63
89
|
className?: string;
|
|
64
90
|
}
|
|
65
91
|
|
|
66
|
-
const AvatarImage = forwardRef<Image, AvatarImageProps>(
|
|
67
|
-
|
|
92
|
+
const AvatarImage = forwardRef<Image, AvatarImageProps>(
|
|
93
|
+
({ asChild, className, style, src, source, onLoad, onError, ...props }, ref) => {
|
|
94
|
+
const { imageError, setImageLoaded, setImageError } = useAvatarContext();
|
|
95
|
+
const computedClassName = cn(avatarImageVariants(), className);
|
|
68
96
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
97
|
+
const resolvedSource = useMemo(() => (src ? { uri: src } : source), [src, source]);
|
|
98
|
+
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (!resolvedSource) {
|
|
101
|
+
setImageError(true);
|
|
102
|
+
} else {
|
|
103
|
+
setImageError(false);
|
|
104
|
+
setImageLoaded(false);
|
|
105
|
+
}
|
|
106
|
+
}, [resolvedSource, setImageError, setImageLoaded]);
|
|
107
|
+
|
|
108
|
+
if (!resolvedSource || imageError) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const Comp = asChild ? Slot : Image;
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<Comp
|
|
116
|
+
ref={ref}
|
|
117
|
+
source={resolvedSource}
|
|
118
|
+
className={computedClassName}
|
|
119
|
+
style={style}
|
|
120
|
+
onLoad={(e: unknown) => {
|
|
121
|
+
setImageLoaded(true);
|
|
122
|
+
if (onLoad) (onLoad as (e: unknown) => void)(e);
|
|
123
|
+
}}
|
|
124
|
+
onError={(e: unknown) => {
|
|
125
|
+
setImageError(true);
|
|
126
|
+
if (onError) (onError as (e: unknown) => void)(e);
|
|
127
|
+
}}
|
|
128
|
+
{...props}
|
|
129
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'avatar-image' }))}
|
|
130
|
+
/>
|
|
131
|
+
);
|
|
132
|
+
},
|
|
133
|
+
);
|
|
78
134
|
|
|
79
135
|
AvatarImage.displayName = 'Avatar.Image';
|
|
80
136
|
|
|
@@ -83,24 +139,32 @@ AvatarImage.displayName = 'Avatar.Image';
|
|
|
83
139
|
// =============================================================================
|
|
84
140
|
|
|
85
141
|
export interface AvatarTextProps extends TextProps {
|
|
142
|
+
asChild?: boolean;
|
|
86
143
|
className?: string;
|
|
87
144
|
children?: ReactNode;
|
|
88
145
|
}
|
|
89
146
|
|
|
90
147
|
const AvatarText = forwardRef<Text, AvatarTextProps>(
|
|
91
|
-
({ className, children, style, ...props }, ref) => {
|
|
148
|
+
({ asChild, className, children, style, ...props }, ref) => {
|
|
92
149
|
const { size } = useAvatarStyleContext();
|
|
150
|
+
const { imageLoaded, imageError } = useAvatarContext();
|
|
151
|
+
const visible = !imageLoaded || imageError;
|
|
93
152
|
const computedClassName = cn(avatarTextVariants({ size }), className);
|
|
94
153
|
|
|
154
|
+
const text = typeof children === 'string' ? getInitials(children) : children;
|
|
155
|
+
|
|
156
|
+
const Comp = asChild ? Slot : Text;
|
|
157
|
+
|
|
95
158
|
return (
|
|
96
|
-
<
|
|
97
|
-
ref={ref
|
|
159
|
+
<Comp
|
|
160
|
+
ref={ref}
|
|
98
161
|
className={computedClassName}
|
|
99
|
-
style={style}
|
|
162
|
+
style={[style, !visible && { opacity: 0 }]}
|
|
100
163
|
{...props}
|
|
164
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'avatar-text' }))}
|
|
101
165
|
>
|
|
102
|
-
{
|
|
103
|
-
</
|
|
166
|
+
{text}
|
|
167
|
+
</Comp>
|
|
104
168
|
);
|
|
105
169
|
},
|
|
106
170
|
);
|
|
@@ -112,14 +176,35 @@ AvatarText.displayName = 'Avatar.Text';
|
|
|
112
176
|
// =============================================================================
|
|
113
177
|
|
|
114
178
|
export interface AvatarIconProps extends Omit<IconProps, 'children'> {
|
|
179
|
+
asChild?: boolean;
|
|
115
180
|
className?: string;
|
|
116
181
|
}
|
|
117
182
|
|
|
118
|
-
const AvatarIcon = ({ className, style, ...props }: AvatarIconProps) => {
|
|
183
|
+
const AvatarIcon = ({ asChild, className, style, ...props }: AvatarIconProps) => {
|
|
119
184
|
const { size } = useAvatarStyleContext();
|
|
185
|
+
const { imageLoaded, imageError } = useAvatarContext();
|
|
186
|
+
const visible = !imageLoaded || imageError;
|
|
120
187
|
const computedClassName = cn(avatarIconVariants({ size }), className);
|
|
121
188
|
|
|
122
|
-
|
|
189
|
+
if (asChild) {
|
|
190
|
+
return (
|
|
191
|
+
<Slot
|
|
192
|
+
className={computedClassName}
|
|
193
|
+
style={[style, !visible && { opacity: 0 }]}
|
|
194
|
+
{...props}
|
|
195
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'avatar-icon' }))}
|
|
196
|
+
/>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return (
|
|
201
|
+
<IconComponent
|
|
202
|
+
className={computedClassName}
|
|
203
|
+
style={[style, !visible && { opacity: 0 }]}
|
|
204
|
+
{...props}
|
|
205
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'avatar-icon' }))}
|
|
206
|
+
/>
|
|
207
|
+
);
|
|
123
208
|
};
|
|
124
209
|
|
|
125
210
|
AvatarIcon.displayName = 'Avatar.Icon';
|
|
@@ -129,24 +214,27 @@ AvatarIcon.displayName = 'Avatar.Icon';
|
|
|
129
214
|
// =============================================================================
|
|
130
215
|
|
|
131
216
|
export interface AvatarBadgeProps extends ViewProps {
|
|
217
|
+
asChild?: boolean;
|
|
132
218
|
className?: string;
|
|
133
219
|
children?: ReactNode;
|
|
134
220
|
}
|
|
135
221
|
|
|
136
222
|
const AvatarBadge = forwardRef<View, AvatarBadgeProps>(
|
|
137
|
-
({ className, children, style, ...props }, ref) => {
|
|
223
|
+
({ asChild, className, children, style, ...props }, ref) => {
|
|
138
224
|
const { size } = useAvatarStyleContext();
|
|
139
225
|
const computedClassName = cn(avatarBadgeVariants({ size }), className);
|
|
226
|
+
const Comp = asChild ? Slot : View;
|
|
140
227
|
|
|
141
228
|
return (
|
|
142
|
-
<
|
|
143
|
-
ref={ref
|
|
229
|
+
<Comp
|
|
230
|
+
ref={ref}
|
|
144
231
|
className={computedClassName}
|
|
145
232
|
style={style}
|
|
146
233
|
{...props}
|
|
234
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'avatar-badge' }))}
|
|
147
235
|
>
|
|
148
236
|
{children}
|
|
149
|
-
</
|
|
237
|
+
</Comp>
|
|
150
238
|
);
|
|
151
239
|
},
|
|
152
240
|
);
|
|
@@ -170,3 +258,5 @@ export const Avatar = Object.assign(AvatarRoot, {
|
|
|
170
258
|
Icon: AvatarIcon,
|
|
171
259
|
Badge: AvatarBadge,
|
|
172
260
|
}) as AvatarCompoundComponent;
|
|
261
|
+
|
|
262
|
+
export type { AvatarVariantProps };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { forwardRef, useEffect, type ReactElement, type ReactNode } from 'react';
|
|
1
|
+
import React, { forwardRef, useEffect, useMemo, type ReactElement, type ReactNode } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
ActivityIndicator,
|
|
4
|
-
Pressable,
|
|
5
4
|
Text,
|
|
6
5
|
View,
|
|
7
6
|
type ActivityIndicatorProps,
|
|
@@ -9,33 +8,37 @@ import {
|
|
|
9
8
|
type ViewProps,
|
|
10
9
|
type TextProps,
|
|
11
10
|
} from 'react-native';
|
|
12
|
-
import {
|
|
13
|
-
|
|
11
|
+
import {
|
|
12
|
+
ButtonRoot as ButtonRootPrimitive,
|
|
13
|
+
Slot,
|
|
14
|
+
dataAttributes,
|
|
15
|
+
mergeDataAttributes,
|
|
16
|
+
type IButtonProps,
|
|
17
|
+
} from '@cdx-ui/primitives';
|
|
18
|
+
import {
|
|
19
|
+
cn,
|
|
20
|
+
flattenChildren,
|
|
21
|
+
ParentContext,
|
|
22
|
+
useParentContext,
|
|
23
|
+
useStyleContext,
|
|
24
|
+
} from '@cdx-ui/utils';
|
|
14
25
|
import { Icon, IconProps } from '../Icon';
|
|
26
|
+
import { positionToDataIcon, type IconSlotPosition } from '../../utils/positionToDataIcon';
|
|
15
27
|
import {
|
|
16
28
|
type ButtonGroupVariantProps,
|
|
17
29
|
type ButtonVariantProps,
|
|
18
30
|
buttonGroupVariants,
|
|
19
31
|
buttonIconVariants,
|
|
20
32
|
buttonRootVariants,
|
|
33
|
+
buttonSpinnerColorVariants,
|
|
21
34
|
buttonSpinnerVariants,
|
|
22
35
|
buttonTextVariants,
|
|
23
36
|
} from './styles';
|
|
24
37
|
|
|
25
38
|
const SCOPE = 'BUTTON';
|
|
26
39
|
|
|
27
|
-
const Root = withStyleContext(Pressable, SCOPE);
|
|
28
|
-
|
|
29
40
|
const useButtonStyleContext = () => useStyleContext(SCOPE) as ButtonVariantProps;
|
|
30
41
|
|
|
31
|
-
const ButtonPrimitive = createButton({
|
|
32
|
-
Root,
|
|
33
|
-
Text,
|
|
34
|
-
Group: View,
|
|
35
|
-
Spinner: ActivityIndicator,
|
|
36
|
-
Icon: View,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
42
|
// =============================================================================
|
|
40
43
|
// STYLED ROOT COMPONENT
|
|
41
44
|
// =============================================================================
|
|
@@ -98,16 +101,24 @@ const ButtonRoot = forwardRef<View, ButtonProps>(
|
|
|
98
101
|
className,
|
|
99
102
|
);
|
|
100
103
|
|
|
104
|
+
const parent = useParentContext();
|
|
105
|
+
const ctx = useMemo(
|
|
106
|
+
() => ({ ...parent, [SCOPE]: { variant, color, size, fullWidth } }),
|
|
107
|
+
[parent, variant, color, size, fullWidth],
|
|
108
|
+
);
|
|
109
|
+
|
|
101
110
|
return (
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
+
<ParentContext.Provider value={ctx}>
|
|
112
|
+
<ButtonRootPrimitive
|
|
113
|
+
ref={ref}
|
|
114
|
+
className={computedClassName}
|
|
115
|
+
style={style}
|
|
116
|
+
{...props}
|
|
117
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'button' }))}
|
|
118
|
+
>
|
|
119
|
+
{children}
|
|
120
|
+
</ButtonRootPrimitive>
|
|
121
|
+
</ParentContext.Provider>
|
|
111
122
|
);
|
|
112
123
|
},
|
|
113
124
|
);
|
|
@@ -115,92 +126,253 @@ const ButtonRoot = forwardRef<View, ButtonProps>(
|
|
|
115
126
|
ButtonRoot.displayName = 'Button';
|
|
116
127
|
|
|
117
128
|
// =============================================================================
|
|
118
|
-
// STYLED
|
|
129
|
+
// STYLED LABEL COMPONENT
|
|
119
130
|
// =============================================================================
|
|
120
131
|
|
|
121
|
-
export interface
|
|
132
|
+
export interface ButtonLabelProps extends TextProps {
|
|
133
|
+
asChild?: boolean;
|
|
122
134
|
className?: string;
|
|
123
135
|
children?: ReactNode;
|
|
124
136
|
}
|
|
125
137
|
|
|
126
|
-
const ButtonLabel = forwardRef<Text,
|
|
127
|
-
({ className, children, style, ...props }, ref) => {
|
|
138
|
+
const ButtonLabel = forwardRef<Text, ButtonLabelProps>(
|
|
139
|
+
({ asChild, className, children, style, ...props }, ref) => {
|
|
128
140
|
const { variant, color, size } = useButtonStyleContext();
|
|
129
|
-
|
|
130
141
|
const computedClassName = cn(buttonTextVariants({ variant, color, size }), className);
|
|
142
|
+
const Comp = asChild ? Slot : Text;
|
|
131
143
|
|
|
132
144
|
return (
|
|
133
|
-
<
|
|
145
|
+
<Comp
|
|
146
|
+
ref={ref}
|
|
147
|
+
className={computedClassName}
|
|
148
|
+
style={style}
|
|
149
|
+
{...props}
|
|
150
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'button-label' }))}
|
|
151
|
+
>
|
|
134
152
|
{children}
|
|
135
|
-
</
|
|
153
|
+
</Comp>
|
|
136
154
|
);
|
|
137
155
|
},
|
|
138
156
|
);
|
|
139
157
|
|
|
140
158
|
ButtonLabel.displayName = 'Button.Label';
|
|
141
159
|
|
|
160
|
+
// =============================================================================
|
|
161
|
+
// STYLED GROUP COMPONENT
|
|
162
|
+
// =============================================================================
|
|
163
|
+
|
|
142
164
|
// TODO: Use ButtonGroupVariantProps
|
|
143
165
|
export interface ButtonGroupProps extends Omit<ViewProps, 'children'> {
|
|
166
|
+
asChild?: boolean;
|
|
144
167
|
className?: string;
|
|
145
168
|
children: ReactElement | ReactElement[];
|
|
146
169
|
flexDirection?: 'row' | 'column' | 'row-reverse' | 'column-reverse';
|
|
147
170
|
isDisabled?: boolean;
|
|
148
171
|
isAttached?: boolean;
|
|
149
172
|
reversed?: boolean;
|
|
173
|
+
isReversed?: boolean;
|
|
150
174
|
}
|
|
151
175
|
|
|
152
176
|
const ButtonGroup = forwardRef<View, ButtonGroupProps>(
|
|
153
|
-
(
|
|
177
|
+
(
|
|
178
|
+
{
|
|
179
|
+
asChild,
|
|
180
|
+
className,
|
|
181
|
+
children,
|
|
182
|
+
style,
|
|
183
|
+
flexDirection = 'row',
|
|
184
|
+
isAttached,
|
|
185
|
+
isDisabled,
|
|
186
|
+
isReversed,
|
|
187
|
+
reversed,
|
|
188
|
+
...props
|
|
189
|
+
},
|
|
190
|
+
ref,
|
|
191
|
+
) => {
|
|
192
|
+
const direction = flexDirection.includes('reverse')
|
|
193
|
+
? flexDirection === 'column-reverse'
|
|
194
|
+
? 'column'
|
|
195
|
+
: 'row'
|
|
196
|
+
: flexDirection;
|
|
197
|
+
|
|
198
|
+
let childrenArray = React.Children.toArray(flattenChildren(children));
|
|
199
|
+
childrenArray = isReversed || reversed ? [...childrenArray].reverse() : childrenArray;
|
|
200
|
+
|
|
201
|
+
const computedChildren = childrenArray.map((child: any, index: number) => {
|
|
202
|
+
if (typeof child === 'string' || typeof child === 'number') {
|
|
203
|
+
return child;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const attachedStyles: Record<string, number> = {};
|
|
207
|
+
|
|
208
|
+
if (index === 0) {
|
|
209
|
+
if (direction === 'column') {
|
|
210
|
+
attachedStyles.borderBottomLeftRadius = 0;
|
|
211
|
+
attachedStyles.borderBottomRightRadius = 0;
|
|
212
|
+
} else {
|
|
213
|
+
attachedStyles.borderTopRightRadius = 0;
|
|
214
|
+
attachedStyles.borderBottomRightRadius = 0;
|
|
215
|
+
}
|
|
216
|
+
} else if (index === childrenArray.length - 1) {
|
|
217
|
+
if (direction === 'column') {
|
|
218
|
+
attachedStyles.borderTopLeftRadius = 0;
|
|
219
|
+
attachedStyles.borderTopRightRadius = 0;
|
|
220
|
+
} else {
|
|
221
|
+
attachedStyles.borderTopLeftRadius = 0;
|
|
222
|
+
attachedStyles.borderBottomLeftRadius = 0;
|
|
223
|
+
}
|
|
224
|
+
} else {
|
|
225
|
+
attachedStyles.borderRadius = 0;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const childProps = {
|
|
229
|
+
isDisabled,
|
|
230
|
+
...child.props,
|
|
231
|
+
style: {
|
|
232
|
+
...(isAttached ? attachedStyles : {}),
|
|
233
|
+
...child.props.style,
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
return (
|
|
238
|
+
<React.Fragment key={child.key ?? `spaced-child-${index.toString()}`}>
|
|
239
|
+
{React.cloneElement(child, childProps)}
|
|
240
|
+
</React.Fragment>
|
|
241
|
+
);
|
|
242
|
+
});
|
|
243
|
+
|
|
154
244
|
const groupClassName = cn(
|
|
155
245
|
buttonGroupVariants({ flexDirection, isAttached: !!isAttached }),
|
|
156
246
|
className,
|
|
157
247
|
);
|
|
248
|
+
const Comp = asChild ? Slot : View;
|
|
249
|
+
const gapProp = isAttached ? { gap: 0 } : {};
|
|
158
250
|
|
|
159
251
|
return (
|
|
160
|
-
<
|
|
252
|
+
<Comp
|
|
161
253
|
ref={ref}
|
|
162
254
|
className={groupClassName}
|
|
163
|
-
style={[{ flexDirection }, style]}
|
|
164
|
-
isAttached={isAttached}
|
|
255
|
+
style={[{ flexDirection }, style, gapProp]}
|
|
165
256
|
{...props}
|
|
257
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'button-group' }))}
|
|
166
258
|
>
|
|
167
|
-
{
|
|
168
|
-
</
|
|
259
|
+
{computedChildren}
|
|
260
|
+
</Comp>
|
|
169
261
|
);
|
|
170
262
|
},
|
|
171
263
|
);
|
|
172
264
|
|
|
173
265
|
ButtonGroup.displayName = 'Button.Group';
|
|
174
266
|
|
|
175
|
-
|
|
267
|
+
// =============================================================================
|
|
268
|
+
// STYLED ICON COMPONENT
|
|
269
|
+
// =============================================================================
|
|
176
270
|
|
|
177
|
-
|
|
178
|
-
|
|
271
|
+
export interface ButtonIconProps extends Omit<IconProps, 'children' | 'as'> {
|
|
272
|
+
asChild?: boolean;
|
|
273
|
+
/**
|
|
274
|
+
* Forge icon component to render. Required unless `asChild` is set, in which
|
|
275
|
+
* case the consumer's substituted element is rendered instead.
|
|
276
|
+
*/
|
|
277
|
+
as?: IconProps['as'];
|
|
278
|
+
/**
|
|
279
|
+
* Position hint that emits `data-icon="inline-start"` or `data-icon="inline-end"`.
|
|
280
|
+
* CVA uses this attribute to apply leading/trailing padding logically (RTL-aware).
|
|
281
|
+
* Omit to apply the symmetric baseline gap.
|
|
282
|
+
*/
|
|
283
|
+
position?: IconSlotPosition;
|
|
284
|
+
}
|
|
179
285
|
|
|
286
|
+
const ButtonIcon = ({ asChild, className, style, as, position, ...props }: ButtonIconProps) => {
|
|
287
|
+
const { variant, color, size } = useButtonStyleContext();
|
|
180
288
|
const computedClassName = cn(buttonIconVariants({ variant, color, size }), className);
|
|
181
289
|
|
|
182
|
-
|
|
290
|
+
if (asChild) {
|
|
291
|
+
return (
|
|
292
|
+
<Slot
|
|
293
|
+
className={computedClassName}
|
|
294
|
+
style={style}
|
|
295
|
+
{...props}
|
|
296
|
+
{...mergeDataAttributes(
|
|
297
|
+
props,
|
|
298
|
+
dataAttributes({ slot: 'button-icon' }),
|
|
299
|
+
positionToDataIcon(position),
|
|
300
|
+
)}
|
|
301
|
+
/>
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (!as) {
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return (
|
|
310
|
+
<Icon
|
|
311
|
+
as={as}
|
|
312
|
+
className={computedClassName}
|
|
313
|
+
style={style}
|
|
314
|
+
{...props}
|
|
315
|
+
{...mergeDataAttributes(
|
|
316
|
+
props,
|
|
317
|
+
dataAttributes({ slot: 'button-icon' }),
|
|
318
|
+
positionToDataIcon(position),
|
|
319
|
+
)}
|
|
320
|
+
/>
|
|
321
|
+
);
|
|
183
322
|
};
|
|
184
323
|
|
|
185
324
|
ButtonIcon.displayName = 'Button.Icon';
|
|
186
325
|
|
|
326
|
+
// =============================================================================
|
|
327
|
+
// STYLED SPINNER COMPONENT
|
|
328
|
+
// =============================================================================
|
|
329
|
+
|
|
187
330
|
export interface ButtonSpinnerProps extends ActivityIndicatorProps {
|
|
331
|
+
asChild?: boolean;
|
|
188
332
|
className?: string;
|
|
189
333
|
colorClassName?: string;
|
|
334
|
+
/**
|
|
335
|
+
* Position hint that emits `data-icon="inline-start"` or `data-icon="inline-end"`.
|
|
336
|
+
* CVA uses this attribute to apply leading/trailing padding logically (RTL-aware).
|
|
337
|
+
* Omit to apply the symmetric baseline gap.
|
|
338
|
+
*/
|
|
339
|
+
position?: IconSlotPosition;
|
|
190
340
|
}
|
|
191
341
|
|
|
192
342
|
const ButtonSpinner = forwardRef<ActivityIndicator, ButtonSpinnerProps>(
|
|
193
|
-
(
|
|
343
|
+
(
|
|
344
|
+
{
|
|
345
|
+
asChild,
|
|
346
|
+
className,
|
|
347
|
+
colorClassName,
|
|
348
|
+
style,
|
|
349
|
+
position,
|
|
350
|
+
accessibilityLabel = 'Loading',
|
|
351
|
+
...props
|
|
352
|
+
},
|
|
353
|
+
ref,
|
|
354
|
+
) => {
|
|
194
355
|
const { variant, color } = useButtonStyleContext();
|
|
195
|
-
const
|
|
356
|
+
const computedClassName = cn(buttonSpinnerVariants(), className);
|
|
357
|
+
const computedColorClassName = cn(
|
|
358
|
+
buttonSpinnerColorVariants({ variant, color }),
|
|
359
|
+
colorClassName,
|
|
360
|
+
);
|
|
361
|
+
const Comp = asChild ? Slot : ActivityIndicator;
|
|
196
362
|
|
|
197
363
|
return (
|
|
198
|
-
<
|
|
364
|
+
<Comp
|
|
199
365
|
ref={ref}
|
|
200
|
-
className={
|
|
366
|
+
className={computedClassName}
|
|
201
367
|
colorClassName={computedColorClassName}
|
|
202
368
|
style={style}
|
|
369
|
+
accessibilityLabel={accessibilityLabel}
|
|
203
370
|
{...props}
|
|
371
|
+
{...mergeDataAttributes(
|
|
372
|
+
props,
|
|
373
|
+
dataAttributes({ slot: 'button-spinner' }),
|
|
374
|
+
positionToDataIcon(position),
|
|
375
|
+
)}
|
|
204
376
|
/>
|
|
205
377
|
);
|
|
206
378
|
},
|