@cdx-ui/components 0.0.1-alpha.1
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 +34 -0
- package/lib/commonjs/components/Box/Box.js +30 -0
- package/lib/commonjs/components/Box/Box.js.map +1 -0
- package/lib/commonjs/components/Box/index.js +17 -0
- package/lib/commonjs/components/Box/index.js.map +1 -0
- package/lib/commonjs/components/Button/index.js +155 -0
- package/lib/commonjs/components/Button/index.js.map +1 -0
- package/lib/commonjs/components/Button/styles.js +312 -0
- package/lib/commonjs/components/Button/styles.js.map +1 -0
- package/lib/commonjs/components/Input/BaseInput.js +13 -0
- package/lib/commonjs/components/Input/BaseInput.js.map +1 -0
- package/lib/commonjs/components/Input/BaseInput.web.js +50 -0
- package/lib/commonjs/components/Input/BaseInput.web.js.map +1 -0
- package/lib/commonjs/components/Input/index.js +142 -0
- package/lib/commonjs/components/Input/index.js.map +1 -0
- package/lib/commonjs/components/Input/styles.js +62 -0
- package/lib/commonjs/components/Input/styles.js.map +1 -0
- package/lib/commonjs/components/Select/index.js +213 -0
- package/lib/commonjs/components/Select/index.js.map +1 -0
- package/lib/commonjs/components/Select/styles.js +120 -0
- package/lib/commonjs/components/Select/styles.js.map +1 -0
- package/lib/commonjs/components/Spinner/Spinner.js +15 -0
- package/lib/commonjs/components/Spinner/Spinner.js.map +1 -0
- package/lib/commonjs/components/Spinner/index.js +17 -0
- package/lib/commonjs/components/Spinner/index.js.map +1 -0
- package/lib/commonjs/components/Stack/HStack.js +45 -0
- package/lib/commonjs/components/Stack/HStack.js.map +1 -0
- package/lib/commonjs/components/Stack/VStack.js +45 -0
- package/lib/commonjs/components/Stack/VStack.js.map +1 -0
- package/lib/commonjs/components/Stack/index.js +20 -0
- package/lib/commonjs/components/Stack/index.js.map +1 -0
- package/lib/commonjs/components/Text/Text.js +30 -0
- package/lib/commonjs/components/Text/Text.js.map +1 -0
- package/lib/commonjs/components/Text/index.js +17 -0
- package/lib/commonjs/components/Text/index.js.map +1 -0
- package/lib/commonjs/components/index.js +83 -0
- package/lib/commonjs/components/index.js.map +1 -0
- package/lib/commonjs/index.js +17 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/styles.css +6 -0
- package/lib/commonjs/utils/WrapStringChild.js +22 -0
- package/lib/commonjs/utils/WrapStringChild.js.map +1 -0
- package/lib/module/components/Box/Box.js +26 -0
- package/lib/module/components/Box/Box.js.map +1 -0
- package/lib/module/components/Box/index.js +4 -0
- package/lib/module/components/Box/index.js.map +1 -0
- package/lib/module/components/Button/index.js +151 -0
- package/lib/module/components/Button/index.js.map +1 -0
- package/lib/module/components/Button/styles.js +309 -0
- package/lib/module/components/Button/styles.js.map +1 -0
- package/lib/module/components/Input/BaseInput.js +4 -0
- package/lib/module/components/Input/BaseInput.js.map +1 -0
- package/lib/module/components/Input/BaseInput.web.js +45 -0
- package/lib/module/components/Input/BaseInput.web.js.map +1 -0
- package/lib/module/components/Input/index.js +138 -0
- package/lib/module/components/Input/index.js.map +1 -0
- package/lib/module/components/Input/styles.js +58 -0
- package/lib/module/components/Input/styles.js.map +1 -0
- package/lib/module/components/Select/index.js +209 -0
- package/lib/module/components/Select/index.js.map +1 -0
- package/lib/module/components/Select/styles.js +117 -0
- package/lib/module/components/Select/styles.js.map +1 -0
- package/lib/module/components/Spinner/Spinner.js +11 -0
- package/lib/module/components/Spinner/Spinner.js.map +1 -0
- package/lib/module/components/Spinner/index.js +4 -0
- package/lib/module/components/Spinner/index.js.map +1 -0
- package/lib/module/components/Stack/HStack.js +41 -0
- package/lib/module/components/Stack/HStack.js.map +1 -0
- package/lib/module/components/Stack/VStack.js +41 -0
- package/lib/module/components/Stack/VStack.js.map +1 -0
- package/lib/module/components/Stack/index.js +5 -0
- package/lib/module/components/Stack/index.js.map +1 -0
- package/lib/module/components/Text/Text.js +26 -0
- package/lib/module/components/Text/Text.js.map +1 -0
- package/lib/module/components/Text/index.js +4 -0
- package/lib/module/components/Text/index.js.map +1 -0
- package/lib/module/components/index.js +9 -0
- package/lib/module/components/index.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/styles.css +6 -0
- package/lib/module/utils/WrapStringChild.js +18 -0
- package/lib/module/utils/WrapStringChild.js.map +1 -0
- package/lib/typescript/components/Box/Box.d.ts +8 -0
- package/lib/typescript/components/Box/Box.d.ts.map +1 -0
- package/lib/typescript/components/Box/index.d.ts +2 -0
- package/lib/typescript/components/Box/index.d.ts.map +1 -0
- package/lib/typescript/components/Button/index.d.ts +41 -0
- package/lib/typescript/components/Button/index.d.ts.map +1 -0
- package/lib/typescript/components/Button/styles.d.ts +23 -0
- package/lib/typescript/components/Button/styles.d.ts.map +1 -0
- package/lib/typescript/components/Input/BaseInput.d.ts +2 -0
- package/lib/typescript/components/Input/BaseInput.d.ts.map +1 -0
- package/lib/typescript/components/Input/BaseInput.web.d.ts +3 -0
- package/lib/typescript/components/Input/BaseInput.web.d.ts.map +1 -0
- package/lib/typescript/components/Input/index.d.ts +32 -0
- package/lib/typescript/components/Input/index.d.ts.map +1 -0
- package/lib/typescript/components/Input/styles.d.ts +17 -0
- package/lib/typescript/components/Input/styles.d.ts.map +1 -0
- package/lib/typescript/components/Select/index.d.ts +45 -0
- package/lib/typescript/components/Select/index.d.ts.map +1 -0
- package/lib/typescript/components/Select/styles.d.ts +22 -0
- package/lib/typescript/components/Select/styles.d.ts.map +1 -0
- package/lib/typescript/components/Spinner/Spinner.d.ts +5 -0
- package/lib/typescript/components/Spinner/Spinner.d.ts.map +1 -0
- package/lib/typescript/components/Spinner/index.d.ts +2 -0
- package/lib/typescript/components/Spinner/index.d.ts.map +1 -0
- package/lib/typescript/components/Stack/HStack.d.ts +20 -0
- package/lib/typescript/components/Stack/HStack.d.ts.map +1 -0
- package/lib/typescript/components/Stack/VStack.d.ts +20 -0
- package/lib/typescript/components/Stack/VStack.d.ts.map +1 -0
- package/lib/typescript/components/Stack/index.d.ts +3 -0
- package/lib/typescript/components/Stack/index.d.ts.map +1 -0
- package/lib/typescript/components/Text/Text.d.ts +11 -0
- package/lib/typescript/components/Text/Text.d.ts.map +1 -0
- package/lib/typescript/components/Text/index.d.ts +2 -0
- package/lib/typescript/components/Text/index.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +7 -0
- package/lib/typescript/components/index.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/utils/WrapStringChild.d.ts +10 -0
- package/lib/typescript/utils/WrapStringChild.d.ts.map +1 -0
- package/package.json +90 -0
- package/src/components/Box/Box.tsx +21 -0
- package/src/components/Box/index.ts +1 -0
- package/src/components/Button/index.tsx +186 -0
- package/src/components/Button/styles.ts +410 -0
- package/src/components/Input/BaseInput.tsx +1 -0
- package/src/components/Input/BaseInput.web.tsx +41 -0
- package/src/components/Input/index.tsx +161 -0
- package/src/components/Input/styles.ts +83 -0
- package/src/components/Select/index.tsx +215 -0
- package/src/components/Select/styles.ts +168 -0
- package/src/components/Spinner/Spinner.tsx +10 -0
- package/src/components/Spinner/index.ts +1 -0
- package/src/components/Stack/HStack.tsx +42 -0
- package/src/components/Stack/VStack.tsx +46 -0
- package/src/components/Stack/index.ts +2 -0
- package/src/components/Text/Text.tsx +58 -0
- package/src/components/Text/index.ts +1 -0
- package/src/components/index.ts +6 -0
- package/src/index.ts +1 -0
- package/src/styles.css +6 -0
- package/src/utils/WrapStringChild.tsx +25 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { forwardRef, type ReactNode } from 'react';
|
|
2
|
+
import { Pressable, Text, type TextProps, View, type ViewProps } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
createSelect,
|
|
5
|
+
type ISelectContentProps,
|
|
6
|
+
type ISelectItemLabelProps,
|
|
7
|
+
type ISelectItemProps,
|
|
8
|
+
type ISelectProps,
|
|
9
|
+
type ISelectTriggerProps,
|
|
10
|
+
type ISelectValueProps,
|
|
11
|
+
} from '@cdx-ui/primitives';
|
|
12
|
+
import { cn, useStyleContext, withStyleContext } from '@cdx-ui/utils';
|
|
13
|
+
import {
|
|
14
|
+
type SelectVariantProps,
|
|
15
|
+
selectContentVariants,
|
|
16
|
+
selectIconVariants,
|
|
17
|
+
selectItemLabelVariants,
|
|
18
|
+
selectItemVariants,
|
|
19
|
+
selectTriggerVariants,
|
|
20
|
+
selectValueVariants,
|
|
21
|
+
} from './styles';
|
|
22
|
+
|
|
23
|
+
const SCOPE = 'SELECT';
|
|
24
|
+
|
|
25
|
+
const Root = withStyleContext(View, SCOPE);
|
|
26
|
+
|
|
27
|
+
const useSelectStyleContext = () => useStyleContext(SCOPE) as SelectVariantProps;
|
|
28
|
+
|
|
29
|
+
const SelectPrimitive = createSelect({
|
|
30
|
+
Root,
|
|
31
|
+
Trigger: Pressable,
|
|
32
|
+
Value: Text,
|
|
33
|
+
Icon: View,
|
|
34
|
+
Content: View,
|
|
35
|
+
Item: Pressable,
|
|
36
|
+
ItemLabel: Text,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// STYLED ROOT COMPONENT
|
|
41
|
+
// =============================================================================
|
|
42
|
+
|
|
43
|
+
export interface SelectProps extends ViewProps, ISelectProps, SelectVariantProps {
|
|
44
|
+
className?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const SelectRoot = forwardRef<View, SelectProps>(
|
|
48
|
+
({ variant = 'outline', size = 'md', className, children, style, ...props }, ref) => {
|
|
49
|
+
return (
|
|
50
|
+
<SelectPrimitive
|
|
51
|
+
ref={ref}
|
|
52
|
+
className={className}
|
|
53
|
+
style={style}
|
|
54
|
+
context={{ variant, size }}
|
|
55
|
+
{...props}
|
|
56
|
+
>
|
|
57
|
+
{children}
|
|
58
|
+
</SelectPrimitive>
|
|
59
|
+
);
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
SelectRoot.displayName = 'Select';
|
|
64
|
+
|
|
65
|
+
// =============================================================================
|
|
66
|
+
// STYLED TRIGGER COMPONENT
|
|
67
|
+
// =============================================================================
|
|
68
|
+
|
|
69
|
+
export interface SelectTriggerProps extends ISelectTriggerProps {
|
|
70
|
+
className?: string;
|
|
71
|
+
children?: ReactNode;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const SelectTrigger = forwardRef<View, SelectTriggerProps>(
|
|
75
|
+
({ className, children, style, ...props }, ref) => {
|
|
76
|
+
const { variant, size } = useSelectStyleContext();
|
|
77
|
+
|
|
78
|
+
const computedClassName = cn(selectTriggerVariants({ variant, size }), className);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<SelectPrimitive.Trigger ref={ref} className={computedClassName} style={style} {...props}>
|
|
82
|
+
{children}
|
|
83
|
+
</SelectPrimitive.Trigger>
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
SelectTrigger.displayName = 'Select.Trigger';
|
|
89
|
+
|
|
90
|
+
// =============================================================================
|
|
91
|
+
// STYLED VALUE COMPONENT
|
|
92
|
+
// =============================================================================
|
|
93
|
+
|
|
94
|
+
export interface SelectValueProps extends TextProps, ISelectValueProps {
|
|
95
|
+
className?: string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const SelectValue = forwardRef<Text, SelectValueProps>(({ className, style, ...props }, ref) => {
|
|
99
|
+
const { variant, size } = useSelectStyleContext();
|
|
100
|
+
|
|
101
|
+
const computedClassName = cn(selectValueVariants({ variant, size }), className);
|
|
102
|
+
|
|
103
|
+
return <SelectPrimitive.Value ref={ref} className={computedClassName} style={style} {...props} />;
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
SelectValue.displayName = 'Select.Value';
|
|
107
|
+
|
|
108
|
+
// =============================================================================
|
|
109
|
+
// STYLED ICON COMPONENT
|
|
110
|
+
// =============================================================================
|
|
111
|
+
|
|
112
|
+
export interface SelectIconProps extends ViewProps {
|
|
113
|
+
className?: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const SelectIcon = forwardRef<View, SelectIconProps>(({ className, style, ...props }, ref) => {
|
|
117
|
+
const { variant, size } = useSelectStyleContext();
|
|
118
|
+
|
|
119
|
+
const computedClassName = cn(selectIconVariants({ variant, size }), className);
|
|
120
|
+
|
|
121
|
+
return <SelectPrimitive.Icon ref={ref} className={computedClassName} style={style} {...props} />;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
SelectIcon.displayName = 'Select.Icon';
|
|
125
|
+
|
|
126
|
+
// =============================================================================
|
|
127
|
+
// STYLED CONTENT COMPONENT
|
|
128
|
+
// =============================================================================
|
|
129
|
+
|
|
130
|
+
export interface SelectContentProps extends ViewProps, ISelectContentProps {
|
|
131
|
+
className?: string;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const SelectContent = forwardRef<View, SelectContentProps>(
|
|
135
|
+
({ className, style, ...props }, ref) => {
|
|
136
|
+
const computedClassName = cn(selectContentVariants(), className);
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<SelectPrimitive.Content ref={ref} className={computedClassName} style={style} {...props} />
|
|
140
|
+
);
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
SelectContent.displayName = 'Select.Content';
|
|
145
|
+
|
|
146
|
+
// =============================================================================
|
|
147
|
+
// STYLED ITEM COMPONENT
|
|
148
|
+
// =============================================================================
|
|
149
|
+
|
|
150
|
+
export interface SelectItemProps extends ISelectItemProps {
|
|
151
|
+
className?: string;
|
|
152
|
+
children?: ReactNode;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const SelectItem = forwardRef<View, SelectItemProps>(
|
|
156
|
+
({ className, children, style, ...props }, ref) => {
|
|
157
|
+
const { size } = useSelectStyleContext();
|
|
158
|
+
|
|
159
|
+
const computedClassName = cn(selectItemVariants({ size }), className);
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<SelectPrimitive.Item ref={ref} className={computedClassName} style={style} {...props}>
|
|
163
|
+
{children}
|
|
164
|
+
</SelectPrimitive.Item>
|
|
165
|
+
);
|
|
166
|
+
},
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
SelectItem.displayName = 'Select.Item';
|
|
170
|
+
|
|
171
|
+
// =============================================================================
|
|
172
|
+
// STYLED ITEM LABEL COMPONENT
|
|
173
|
+
// =============================================================================
|
|
174
|
+
|
|
175
|
+
export interface SelectItemLabelProps extends TextProps, ISelectItemLabelProps {
|
|
176
|
+
className?: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const SelectItemLabel = forwardRef<Text, SelectItemLabelProps>(
|
|
180
|
+
({ className, style, ...props }, ref) => {
|
|
181
|
+
const { size } = useSelectStyleContext();
|
|
182
|
+
|
|
183
|
+
const computedClassName = cn(selectItemLabelVariants({ size }), className);
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<SelectPrimitive.ItemLabel ref={ref} className={computedClassName} style={style} {...props} />
|
|
187
|
+
);
|
|
188
|
+
},
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
SelectItemLabel.displayName = 'Select.ItemLabel';
|
|
192
|
+
|
|
193
|
+
// =============================================================================
|
|
194
|
+
// COMPOUND COMPONENT
|
|
195
|
+
// =============================================================================
|
|
196
|
+
|
|
197
|
+
type SelectCompoundComponent = typeof SelectRoot & {
|
|
198
|
+
Trigger: typeof SelectTrigger;
|
|
199
|
+
Value: typeof SelectValue;
|
|
200
|
+
Icon: typeof SelectIcon;
|
|
201
|
+
Content: typeof SelectContent;
|
|
202
|
+
Item: typeof SelectItem;
|
|
203
|
+
ItemLabel: typeof SelectItemLabel;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
export const Select = Object.assign(SelectRoot, {
|
|
207
|
+
Trigger: SelectTrigger,
|
|
208
|
+
Value: SelectValue,
|
|
209
|
+
Icon: SelectIcon,
|
|
210
|
+
Content: SelectContent,
|
|
211
|
+
Item: SelectItem,
|
|
212
|
+
ItemLabel: SelectItemLabel,
|
|
213
|
+
}) as SelectCompoundComponent;
|
|
214
|
+
|
|
215
|
+
export type { SelectVariantProps } from './styles';
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
3
|
+
|
|
4
|
+
// ── Trigger ─────────────────────────────────────────────────
|
|
5
|
+
|
|
6
|
+
export const selectTriggerVariants = cva(
|
|
7
|
+
[
|
|
8
|
+
'flex-row items-center justify-between',
|
|
9
|
+
'rounded-lg',
|
|
10
|
+
'transition-colors duration-150',
|
|
11
|
+
'data-[disabled=true]:opacity-60 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:pointer-events-none',
|
|
12
|
+
'data-[readonly=true]:cursor-default',
|
|
13
|
+
'data-[focus-visible=true]:ring-2 data-[focus-visible=true]:ring-blue-500 data-[focus-visible=true]:ring-offset-2',
|
|
14
|
+
],
|
|
15
|
+
{
|
|
16
|
+
variants: {
|
|
17
|
+
variant: {
|
|
18
|
+
outline: [
|
|
19
|
+
'bg-white border border-gray-300',
|
|
20
|
+
Platform.select({
|
|
21
|
+
default: 'data-[active=true]:border-gray-400',
|
|
22
|
+
web: 'data-[hover=true]:border-gray-400 data-[active=true]:data-[hover=true]:border-gray-500',
|
|
23
|
+
}),
|
|
24
|
+
'data-[state=open]:data-[invalid=false]:border-blue-500',
|
|
25
|
+
'data-[invalid=true]:border-red-500',
|
|
26
|
+
'data-[readonly=true]:bg-gray-50',
|
|
27
|
+
],
|
|
28
|
+
filled: [
|
|
29
|
+
'bg-gray-100 border border-transparent',
|
|
30
|
+
Platform.select({
|
|
31
|
+
default: 'data-[active=true]:bg-gray-200',
|
|
32
|
+
web: 'data-[hover=true]:bg-gray-200 data-[active=true]:data-[hover=true]:bg-gray-300',
|
|
33
|
+
}),
|
|
34
|
+
'data-[state=open]:border-blue-500',
|
|
35
|
+
'data-[invalid=true]:border-red-500 data-[invalid=true]:border',
|
|
36
|
+
'data-[readonly=true]:bg-gray-200',
|
|
37
|
+
],
|
|
38
|
+
ghost: [
|
|
39
|
+
'bg-transparent border border-transparent',
|
|
40
|
+
Platform.select({
|
|
41
|
+
default: 'data-[active=true]:bg-gray-100',
|
|
42
|
+
web: 'data-[hover=true]:bg-gray-50 data-[active=true]:data-[hover=true]:bg-gray-100',
|
|
43
|
+
}),
|
|
44
|
+
'data-[invalid=true]:border-red-500 data-[invalid=true]:border',
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
size: {
|
|
48
|
+
sm: 'h-8 px-2.5 gap-1.5',
|
|
49
|
+
md: 'h-10 px-3 gap-2',
|
|
50
|
+
lg: 'h-12 px-4 gap-2.5',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
defaultVariants: {
|
|
54
|
+
variant: 'outline',
|
|
55
|
+
size: 'md',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// ── Value ───────────────────────────────────────────────────
|
|
61
|
+
|
|
62
|
+
export const selectValueVariants = cva(
|
|
63
|
+
['flex-1', 'data-[placeholder=true]:text-gray-400', 'data-[invalid=true]:text-red-600'],
|
|
64
|
+
{
|
|
65
|
+
variants: {
|
|
66
|
+
variant: {
|
|
67
|
+
outline: 'text-gray-900',
|
|
68
|
+
filled: 'text-gray-900',
|
|
69
|
+
ghost: 'text-gray-900',
|
|
70
|
+
},
|
|
71
|
+
size: {
|
|
72
|
+
sm: 'text-sm',
|
|
73
|
+
md: 'text-base',
|
|
74
|
+
lg: 'text-lg',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
defaultVariants: {
|
|
78
|
+
variant: 'outline',
|
|
79
|
+
size: 'md',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// ── Icon ────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
export const selectIconVariants = cva(
|
|
87
|
+
['items-center justify-center', 'data-[invalid=true]:text-red-500'],
|
|
88
|
+
{
|
|
89
|
+
variants: {
|
|
90
|
+
variant: {
|
|
91
|
+
outline: 'text-gray-500',
|
|
92
|
+
filled: 'text-gray-500',
|
|
93
|
+
ghost: 'text-gray-400',
|
|
94
|
+
},
|
|
95
|
+
size: {
|
|
96
|
+
sm: 'h-4 w-4',
|
|
97
|
+
md: 'h-5 w-5',
|
|
98
|
+
lg: 'h-6 w-6',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
defaultVariants: {
|
|
102
|
+
variant: 'outline',
|
|
103
|
+
size: 'md',
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// ── Content ─────────────────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
export const selectContentVariants = cva([
|
|
111
|
+
'bg-white',
|
|
112
|
+
'border border-gray-200',
|
|
113
|
+
'overflow-hidden',
|
|
114
|
+
'rounded-lg',
|
|
115
|
+
Platform.select({
|
|
116
|
+
web: 'shadow-lg',
|
|
117
|
+
default: '',
|
|
118
|
+
}),
|
|
119
|
+
'max-h-60',
|
|
120
|
+
'py-1',
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
// ── Item ────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
export const selectItemVariants = cva(
|
|
126
|
+
[
|
|
127
|
+
'flex-row items-center',
|
|
128
|
+
'transition-colors duration-100',
|
|
129
|
+
'data-[disabled=true]:opacity-50 data-[disabled=true]:pointer-events-none',
|
|
130
|
+
'data-[state=checked]:bg-blue-50',
|
|
131
|
+
Platform.select({
|
|
132
|
+
default: 'data-[active=true]:bg-gray-100',
|
|
133
|
+
web: 'data-[hover=true]:bg-gray-100 data-[active=true]:data-[hover=true]:bg-gray-200 data-[highlighted=true]:bg-blue-50',
|
|
134
|
+
}),
|
|
135
|
+
],
|
|
136
|
+
{
|
|
137
|
+
variants: {
|
|
138
|
+
size: {
|
|
139
|
+
sm: 'px-2.5 py-1.5',
|
|
140
|
+
md: 'px-3 py-2',
|
|
141
|
+
lg: 'px-4 py-2.5',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
defaultVariants: {
|
|
145
|
+
size: 'md',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// ── ItemLabel ───────────────────────────────────────────────
|
|
151
|
+
|
|
152
|
+
export const selectItemLabelVariants = cva(
|
|
153
|
+
['text-gray-900', 'data-[state=checked]:font-semibold', 'data-[state=checked]:text-blue-700'],
|
|
154
|
+
{
|
|
155
|
+
variants: {
|
|
156
|
+
size: {
|
|
157
|
+
sm: 'text-sm',
|
|
158
|
+
md: 'text-base',
|
|
159
|
+
lg: 'text-lg',
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
defaultVariants: {
|
|
163
|
+
size: 'md',
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
export type SelectVariantProps = VariantProps<typeof selectTriggerVariants>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ForwardedRef, forwardRef } from 'react';
|
|
2
|
+
import { ActivityIndicator, type ActivityIndicatorProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface SpinnerProps extends ActivityIndicatorProps {}
|
|
5
|
+
|
|
6
|
+
export const Spinner = forwardRef<ActivityIndicator, SpinnerProps>(
|
|
7
|
+
(props, ref: ForwardedRef<ActivityIndicator>) => <ActivityIndicator ref={ref} {...props} />,
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
Spinner.displayName = 'Spinner';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Spinner';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ForwardedRef } from 'react';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { View, type ViewProps } from 'react-native';
|
|
4
|
+
// import { spacing } from '@cdx-ui/tokens';
|
|
5
|
+
|
|
6
|
+
// TODO: Integrate with tokens (multiply by spacing)
|
|
7
|
+
const spaceScale = {
|
|
8
|
+
xs: 1,
|
|
9
|
+
sm: 2,
|
|
10
|
+
md: 3,
|
|
11
|
+
lg: 4,
|
|
12
|
+
xl: 5,
|
|
13
|
+
'2xl': 6,
|
|
14
|
+
'3xl': 7,
|
|
15
|
+
'4xl': 8,
|
|
16
|
+
} as const;
|
|
17
|
+
|
|
18
|
+
type StackSpace = keyof typeof spaceScale;
|
|
19
|
+
|
|
20
|
+
export interface HStackProps extends ViewProps {
|
|
21
|
+
className?: string;
|
|
22
|
+
space?: StackSpace;
|
|
23
|
+
reversed?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const HStack = forwardRef<View, HStackProps>(
|
|
27
|
+
({ space, reversed, style, className, children, ...restProps }, ref: ForwardedRef<View>) => {
|
|
28
|
+
const gap = space ? spaceScale[space] : undefined;
|
|
29
|
+
return (
|
|
30
|
+
<View
|
|
31
|
+
ref={ref}
|
|
32
|
+
className={className}
|
|
33
|
+
style={[{ flexDirection: reversed ? 'row-reverse' : 'row' }, gap ? { gap } : null, style]}
|
|
34
|
+
{...restProps}
|
|
35
|
+
>
|
|
36
|
+
{children}
|
|
37
|
+
</View>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
HStack.displayName = 'HStack';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ForwardedRef } from 'react';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { View, type ViewProps } from 'react-native';
|
|
4
|
+
// import { spacing } from '@cdx-ui/tokens';
|
|
5
|
+
|
|
6
|
+
// TODO: Integrate with tokens (multiply by spacing)
|
|
7
|
+
const spaceScale = {
|
|
8
|
+
xs: 1,
|
|
9
|
+
sm: 2,
|
|
10
|
+
md: 3,
|
|
11
|
+
lg: 4,
|
|
12
|
+
xl: 5,
|
|
13
|
+
'2xl': 6,
|
|
14
|
+
'3xl': 7,
|
|
15
|
+
'4xl': 8,
|
|
16
|
+
} as const;
|
|
17
|
+
|
|
18
|
+
type StackSpace = keyof typeof spaceScale;
|
|
19
|
+
|
|
20
|
+
export interface VStackProps extends ViewProps {
|
|
21
|
+
className?: string;
|
|
22
|
+
space?: StackSpace;
|
|
23
|
+
reversed?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const VStack = forwardRef<View, VStackProps>(
|
|
27
|
+
({ space, reversed, style, className, children, ...restProps }, ref: ForwardedRef<View>) => {
|
|
28
|
+
const gap = space ? spaceScale[space] : undefined;
|
|
29
|
+
return (
|
|
30
|
+
<View
|
|
31
|
+
ref={ref}
|
|
32
|
+
className={className}
|
|
33
|
+
style={[
|
|
34
|
+
{ flexDirection: reversed ? 'column-reverse' : 'column' },
|
|
35
|
+
gap ? { gap } : null,
|
|
36
|
+
style,
|
|
37
|
+
]}
|
|
38
|
+
{...restProps}
|
|
39
|
+
>
|
|
40
|
+
{children}
|
|
41
|
+
</View>
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
VStack.displayName = 'VStack';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
import { Text as RNText, type TextProps as RNTextProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
type TypographyVariant =
|
|
5
|
+
| 'h1'
|
|
6
|
+
| 'h2'
|
|
7
|
+
| 'h3'
|
|
8
|
+
| 'h4'
|
|
9
|
+
| 'h5'
|
|
10
|
+
| 'h6'
|
|
11
|
+
| 'subtitle1'
|
|
12
|
+
| 'subtitle2'
|
|
13
|
+
| 'body1'
|
|
14
|
+
| 'body2'
|
|
15
|
+
| 'caption'
|
|
16
|
+
| 'button'
|
|
17
|
+
| 'overline'
|
|
18
|
+
| 'display1'
|
|
19
|
+
| 'display2';
|
|
20
|
+
|
|
21
|
+
interface VariantProps {
|
|
22
|
+
variant?: TypographyVariant;
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface TextProps extends RNTextProps, VariantProps {}
|
|
27
|
+
|
|
28
|
+
const joinClassNames = (...parts: (string | undefined | false)[]) =>
|
|
29
|
+
parts.filter(Boolean).join(' ');
|
|
30
|
+
|
|
31
|
+
const buildTypographyClassName = (variant: TypographyVariant) =>
|
|
32
|
+
joinClassNames(
|
|
33
|
+
`[font-family:var(--type-${variant}-family)]`,
|
|
34
|
+
`[font-weight:var(--type-${variant}-weight)]`,
|
|
35
|
+
`text-[var(--type-${variant}-size)]`,
|
|
36
|
+
`leading-[var(--type-${variant}-lineHeight)]`,
|
|
37
|
+
`tracking-[var(--type-${variant}-letterSpacing)]`,
|
|
38
|
+
variant === 'overline' ? 'uppercase' : 'normal-case',
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export const Text = forwardRef<RNText, TextProps>(
|
|
42
|
+
({ variant, children, style, className, ...restProps }, ref) => {
|
|
43
|
+
const variantKey = variant ?? 'body1';
|
|
44
|
+
const variantClassName = buildTypographyClassName(variantKey);
|
|
45
|
+
return (
|
|
46
|
+
<RNText
|
|
47
|
+
ref={ref}
|
|
48
|
+
className={joinClassNames(variantClassName, className)}
|
|
49
|
+
style={style}
|
|
50
|
+
{...restProps}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</RNText>
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
Text.displayName = 'Text';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Text';
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './components';
|
package/src/styles.css
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Children, Fragment, isValidElement, type ReactNode } from 'react';
|
|
2
|
+
import { Text, type TextProps } from '../components/Text';
|
|
3
|
+
|
|
4
|
+
interface WrapStringChildProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
textProps?: TextProps;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** @deprecated Users should wrap their own children in a Text component themselves */
|
|
10
|
+
export function WrapStringChild({ children, textProps }: WrapStringChildProps): ReactNode {
|
|
11
|
+
return Children.map(children, (child) => {
|
|
12
|
+
return typeof child === 'string' ||
|
|
13
|
+
typeof child === 'number' ||
|
|
14
|
+
(isValidElement(child) &&
|
|
15
|
+
child.type === Fragment &&
|
|
16
|
+
child.props &&
|
|
17
|
+
typeof child.props === 'object' &&
|
|
18
|
+
'children' in child.props &&
|
|
19
|
+
(typeof child.props.children === 'string' || typeof child.props.children === 'number')) ? (
|
|
20
|
+
<Text {...textProps}>{child}</Text>
|
|
21
|
+
) : (
|
|
22
|
+
child
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
}
|