@praxiis/ui 0.0.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/dist/index.d.mts +52556 -0
- package/dist/index.d.ts +52556 -0
- package/dist/index.js +8753 -0
- package/dist/index.mjs +8777 -0
- package/package.json +70 -0
- package/src/__test-utils__/index.tsx +39 -0
- package/src/components/CalendarStrip/CalendarStrip.helpers.ts +106 -0
- package/src/components/CalendarStrip/CalendarStrip.tsx +83 -0
- package/src/components/CalendarStrip/CalendarStrip.types.ts +133 -0
- package/src/components/CalendarStrip/DayCard/DayCard.helpers.ts +44 -0
- package/src/components/CalendarStrip/DayCard/DayCard.tsx +71 -0
- package/src/components/CalendarStrip/DayCard/DayCard.types.ts +134 -0
- package/src/components/CalendarStrip/DayCard/index.ts +2 -0
- package/src/components/CalendarStrip/DayCard/useDayCardLogic.ts +45 -0
- package/src/components/CalendarStrip/index.ts +9 -0
- package/src/components/CalendarStrip/useCalendarStripLogic.ts +53 -0
- package/src/components/EmptyState/EmptyState.helpers.ts +104 -0
- package/src/components/EmptyState/EmptyState.tsx +205 -0
- package/src/components/EmptyState/EmptyState.types.ts +213 -0
- package/src/components/EmptyState/index.ts +44 -0
- package/src/components/EmptyState/useEmptyStateLogic.ts +131 -0
- package/src/components/Header/Header.helpers.ts +93 -0
- package/src/components/Header/Header.tsx +185 -0
- package/src/components/Header/Header.types.ts +153 -0
- package/src/components/Header/index.ts +44 -0
- package/src/components/Header/useHeaderLogic.ts +146 -0
- package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.helpers.ts +50 -0
- package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.tsx +78 -0
- package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.types.ts +99 -0
- package/src/components/ScheduleItem/ScheduleItem/index.ts +16 -0
- package/src/components/ScheduleItem/ScheduleItem/useScheduleItemLogic.ts +31 -0
- package/src/components/ScheduleItem/index.ts +15 -0
- package/src/components/index.ts +40 -0
- package/src/core/index.ts +34 -0
- package/src/core/restyle/RestyleThemeProviderWrapper.tsx +31 -0
- package/src/core/restyle/index.ts +38 -0
- package/src/core/restyle/restylePresetRegistry.ts +195 -0
- package/src/core/restyle/restyleTheme.ts +1352 -0
- package/src/core/restyle/restyleTypes.ts +8 -0
- package/src/core/restyle/useRestyleTheme.ts +10 -0
- package/src/hooks/animations/index.ts +3 -0
- package/src/hooks/animations/useAnimatedValue.ts +10 -0
- package/src/hooks/animations/useEntranceAnimation.ts +106 -0
- package/src/hooks/animations/usePulseAnimation.ts +63 -0
- package/src/hooks/index.ts +30 -0
- package/src/hooks/useReducedMotion.ts +60 -0
- package/src/i18n/index.ts +2 -0
- package/src/i18n/labels/en.ts +120 -0
- package/src/i18n/labels/es.ts +120 -0
- package/src/i18n/labels/index.ts +6 -0
- package/src/i18n/labels/types.ts +165 -0
- package/src/index.tsx +215 -0
- package/src/primitives/actions/Button/Button.helpers.ts +243 -0
- package/src/primitives/actions/Button/Button.tsx +198 -0
- package/src/primitives/actions/Button/Button.types.ts +207 -0
- package/src/primitives/actions/Button/index.ts +41 -0
- package/src/primitives/actions/Button/useButtonLogic.ts +160 -0
- package/src/primitives/actions/IconButton/IconButton.helpers.ts +235 -0
- package/src/primitives/actions/IconButton/IconButton.tsx +177 -0
- package/src/primitives/actions/IconButton/IconButton.types.ts +273 -0
- package/src/primitives/actions/IconButton/index.ts +30 -0
- package/src/primitives/actions/IconButton/useIconButtonLogic.ts +172 -0
- package/src/primitives/actions/index.ts +20 -0
- package/src/primitives/content/Avatar/Avatar.helpers.ts +177 -0
- package/src/primitives/content/Avatar/Avatar.tsx +199 -0
- package/src/primitives/content/Avatar/Avatar.types.ts +222 -0
- package/src/primitives/content/Avatar/index.ts +46 -0
- package/src/primitives/content/Avatar/useAvatarLogic.ts +149 -0
- package/src/primitives/content/Badge/Badge.helpers.ts +175 -0
- package/src/primitives/content/Badge/Badge.tsx +174 -0
- package/src/primitives/content/Badge/Badge.types.ts +223 -0
- package/src/primitives/content/Badge/index.ts +40 -0
- package/src/primitives/content/Badge/useBadgeLogic.ts +128 -0
- package/src/primitives/content/Card/Card.helpers.ts +27 -0
- package/src/primitives/content/Card/Card.tsx +123 -0
- package/src/primitives/content/Card/Card.types.ts +95 -0
- package/src/primitives/content/Card/index.ts +20 -0
- package/src/primitives/content/Card/useCardLogic.ts +48 -0
- package/src/primitives/content/Chip/Chip.helpers.ts +304 -0
- package/src/primitives/content/Chip/Chip.tsx +205 -0
- package/src/primitives/content/Chip/Chip.types.ts +234 -0
- package/src/primitives/content/Chip/index.ts +47 -0
- package/src/primitives/content/Chip/useChipLogic.ts +167 -0
- package/src/primitives/content/Icon/Icon.helpers.ts +54 -0
- package/src/primitives/content/Icon/Icon.tsx +110 -0
- package/src/primitives/content/Icon/Icon.types.ts +95 -0
- package/src/primitives/content/Icon/index.ts +20 -0
- package/src/primitives/content/Icon/useIconLogic.ts +73 -0
- package/src/primitives/content/index.ts +45 -0
- package/src/primitives/feedback/ProgressBar/ProgressBar.helpers.ts +122 -0
- package/src/primitives/feedback/ProgressBar/ProgressBar.tsx +154 -0
- package/src/primitives/feedback/ProgressBar/ProgressBar.types.ts +178 -0
- package/src/primitives/feedback/ProgressBar/index.ts +17 -0
- package/src/primitives/feedback/ProgressBar/useProgressBarLogic.ts +120 -0
- package/src/primitives/feedback/Skeleton/Skeleton.helpers.ts +145 -0
- package/src/primitives/feedback/Skeleton/Skeleton.tsx +155 -0
- package/src/primitives/feedback/Skeleton/Skeleton.types.ts +223 -0
- package/src/primitives/feedback/Skeleton/index.ts +44 -0
- package/src/primitives/feedback/Skeleton/useSkeletonLogic.ts +125 -0
- package/src/primitives/feedback/Spinner/Spinner.helpers.ts +40 -0
- package/src/primitives/feedback/Spinner/Spinner.tsx +105 -0
- package/src/primitives/feedback/Spinner/Spinner.types.ts +114 -0
- package/src/primitives/feedback/Spinner/index.ts +18 -0
- package/src/primitives/feedback/Spinner/useSpinnerLogic.ts +84 -0
- package/src/primitives/feedback/Toast/Toast.helpers.ts +163 -0
- package/src/primitives/feedback/Toast/Toast.tsx +190 -0
- package/src/primitives/feedback/Toast/Toast.types.ts +270 -0
- package/src/primitives/feedback/Toast/ToastContext.tsx +96 -0
- package/src/primitives/feedback/Toast/ToastProvider.tsx +241 -0
- package/src/primitives/feedback/Toast/index.ts +59 -0
- package/src/primitives/feedback/Toast/useToastLogic.ts +112 -0
- package/src/primitives/feedback/index.ts +45 -0
- package/src/primitives/index.ts +158 -0
- package/src/primitives/inputs/Checkbox/Checkbox.helpers.ts +132 -0
- package/src/primitives/inputs/Checkbox/Checkbox.tsx +150 -0
- package/src/primitives/inputs/Checkbox/Checkbox.types.ts +106 -0
- package/src/primitives/inputs/Checkbox/index.ts +30 -0
- package/src/primitives/inputs/Checkbox/useCheckboxLogic.ts +121 -0
- package/src/primitives/inputs/RadioButton/RadioButton.helpers.ts +123 -0
- package/src/primitives/inputs/RadioButton/RadioButton.tsx +159 -0
- package/src/primitives/inputs/RadioButton/RadioButton.types.ts +106 -0
- package/src/primitives/inputs/RadioButton/index.ts +25 -0
- package/src/primitives/inputs/RadioButton/useRadioButtonLogic.ts +117 -0
- package/src/primitives/inputs/SegmentedControl/SegmentedControl.helpers.ts +174 -0
- package/src/primitives/inputs/SegmentedControl/SegmentedControl.tsx +224 -0
- package/src/primitives/inputs/SegmentedControl/SegmentedControl.types.ts +187 -0
- package/src/primitives/inputs/SegmentedControl/index.ts +39 -0
- package/src/primitives/inputs/SegmentedControl/useSegmentedControlLogic.ts +151 -0
- package/src/primitives/inputs/SelectSheet/SelectSheet.helpers.ts +147 -0
- package/src/primitives/inputs/SelectSheet/SelectSheet.tsx +247 -0
- package/src/primitives/inputs/SelectSheet/SelectSheet.types.ts +196 -0
- package/src/primitives/inputs/SelectSheet/SelectSheetOption.tsx +177 -0
- package/src/primitives/inputs/SelectSheet/index.ts +48 -0
- package/src/primitives/inputs/SelectSheet/useSelectSheetLogic.ts +309 -0
- package/src/primitives/inputs/Switch/Switch.helpers.ts +109 -0
- package/src/primitives/inputs/Switch/Switch.tsx +191 -0
- package/src/primitives/inputs/Switch/Switch.types.ts +154 -0
- package/src/primitives/inputs/Switch/index.ts +40 -0
- package/src/primitives/inputs/Switch/useSwitchLogic.ts +192 -0
- package/src/primitives/inputs/TextInput/TextInput.helpers.ts +206 -0
- package/src/primitives/inputs/TextInput/TextInput.tsx +392 -0
- package/src/primitives/inputs/TextInput/TextInput.types.ts +216 -0
- package/src/primitives/inputs/TextInput/index.ts +37 -0
- package/src/primitives/inputs/TextInput/useTextInputLogic.ts +195 -0
- package/src/primitives/inputs/index.ts +52 -0
- package/src/primitives/layout/AnimatedBox.tsx +44 -0
- package/src/primitives/layout/Box.tsx +71 -0
- package/src/primitives/layout/Divider/Divider.helpers.ts +115 -0
- package/src/primitives/layout/Divider/Divider.tsx +139 -0
- package/src/primitives/layout/Divider/Divider.types.ts +178 -0
- package/src/primitives/layout/Divider/index.ts +24 -0
- package/src/primitives/layout/Divider/useDividerLogic.ts +109 -0
- package/src/primitives/layout/FlatList.tsx +66 -0
- package/src/primitives/layout/Pressable.tsx +74 -0
- package/src/primitives/layout/ScrollView.tsx +63 -0
- package/src/primitives/layout/Stack.tsx +69 -0
- package/src/primitives/layout/index.ts +40 -0
- package/src/primitives/navigation/index.ts +6 -0
- package/src/primitives/overlays/Modal/Modal.helpers.ts +31 -0
- package/src/primitives/overlays/Modal/Modal.tsx +264 -0
- package/src/primitives/overlays/Modal/Modal.types.ts +193 -0
- package/src/primitives/overlays/Modal/index.ts +43 -0
- package/src/primitives/overlays/Modal/useModalLogic.ts +103 -0
- package/src/primitives/overlays/index.ts +12 -0
- package/src/primitives/typography/Text.tsx +51 -0
- package/src/primitives/typography/index.ts +1 -0
- package/src/provider/DesignSystemContext.ts +22 -0
- package/src/provider/DesignSystemProvider.tsx +121 -0
- package/src/provider/index.ts +7 -0
- package/src/providers/ThemeProvider/createTheme.ts +304 -0
- package/src/providers/ThemeProvider/defaultTheme.ts +70 -0
- package/src/providers/ThemeProvider/index.ts +34 -0
- package/src/providers/ThemeProvider/types.ts +249 -0
- package/src/providers/index.ts +29 -0
- package/src/tokens/colors.ts +371 -0
- package/src/tokens/index.ts +145 -0
- package/src/tokens/motion.ts +176 -0
- package/src/tokens/radii.ts +82 -0
- package/src/tokens/scales.ts +588 -0
- package/src/tokens/shadows.ts +190 -0
- package/src/tokens/spacing.ts +140 -0
- package/src/tokens/tokens.json +207 -0
- package/src/tokens/typography.ts +251 -0
- package/src/types.ts +50 -0
- package/src/utils/accessibility.ts +169 -0
- package/src/utils/index.ts +25 -0
- package/src/utils/platform.ts +72 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { BoxProps, ResponsiveValue } from "@shopify/restyle";
|
|
2
|
+
import { StyleProp, TextInput as RNTextInput, TextInputProps as RNTextInputProps, ViewProps, ViewStyle } from "react-native";
|
|
3
|
+
import { RestyleTheme } from "../../../core/restyle";
|
|
4
|
+
import { RestyleColor } from "../../../types";
|
|
5
|
+
import { IconName, IconSize } from "../../content/Icon";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Size variant for the TextInput component.
|
|
9
|
+
* Derived from the restyle theme's `textInputSizes` keys.
|
|
10
|
+
*
|
|
11
|
+
* - `sm`: 40px height - Compact forms, dense UIs
|
|
12
|
+
* - `md`: 48px height - Default mobile size
|
|
13
|
+
* - `lg`: 56px height - Tablets, emphasized inputs
|
|
14
|
+
*/
|
|
15
|
+
export type TextInputSize = Exclude<keyof RestyleTheme["textInputSizes"], "defaults">;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Visual variant for the TextInput component.
|
|
19
|
+
* Derived from the restyle theme's `textInputVariants` keys.
|
|
20
|
+
*
|
|
21
|
+
* - `outlined`: Border with transparent background
|
|
22
|
+
* - `filled`: Filled background with subtle border
|
|
23
|
+
* - `textarea`: Multi-line text input with configurable height, cursor starts at top
|
|
24
|
+
*/
|
|
25
|
+
export type TextInputVariant = Exclude<keyof RestyleTheme["textInputVariants"], "defaults">;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Text variant type for labels and helper text.
|
|
29
|
+
*/
|
|
30
|
+
export type TextInputTextVariant = Exclude<keyof RestyleTheme["textVariants"], "defaults">;
|
|
31
|
+
|
|
32
|
+
/** Ref type for the TextInput component — the underlying React Native TextInput instance. */
|
|
33
|
+
export type TextInputRef = RNTextInput;
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Props for the base TextInput container with Restyle support.
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export type BaseTextInputContainerProps = BoxProps<RestyleTheme> & ViewProps;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Base props for the TextInput container component.
|
|
44
|
+
*/
|
|
45
|
+
export interface BaseTextInputProps
|
|
46
|
+
extends BoxProps<RestyleTheme>,
|
|
47
|
+
Omit<RNTextInputProps, "style"> {}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Props for the TextInput component.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Basic usage
|
|
54
|
+
* <TextInput label="Email" value={email} onChangeText={setEmail} />
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* // With icons and validation
|
|
58
|
+
* <TextInput
|
|
59
|
+
* label="Email"
|
|
60
|
+
* value={email}
|
|
61
|
+
* onChangeText={setEmail}
|
|
62
|
+
* leftIconName="email"
|
|
63
|
+
* rightIconName={isValid ? "check-circle" : undefined}
|
|
64
|
+
* size={{ phone: "md", tablet: "lg" }}
|
|
65
|
+
* variant="outlined"
|
|
66
|
+
* error={emailError}
|
|
67
|
+
* helperText="Enter your email address"
|
|
68
|
+
* required
|
|
69
|
+
* showCharCount
|
|
70
|
+
* maxLength={100}
|
|
71
|
+
* accessibilityLabel="Email address"
|
|
72
|
+
* accessibilityHint="Enter a valid email address"
|
|
73
|
+
* />
|
|
74
|
+
*/
|
|
75
|
+
export interface TextInputProps extends BaseTextInputProps {
|
|
76
|
+
/** Label text displayed above the input */
|
|
77
|
+
label?: string;
|
|
78
|
+
/** Helper text displayed below the input */
|
|
79
|
+
helperText?: string;
|
|
80
|
+
/** Error message (displays in red, replaces helperText) */
|
|
81
|
+
error?: string;
|
|
82
|
+
/** Size of the input (supports responsive values) */
|
|
83
|
+
size?: ResponsiveValue<TextInputSize, RestyleTheme["breakpoints"]>;
|
|
84
|
+
/** Visual variant of the input (supports responsive values) */
|
|
85
|
+
variant?: ResponsiveValue<TextInputVariant, RestyleTheme["breakpoints"]>;
|
|
86
|
+
/** Height for textarea variant (default: 120). */
|
|
87
|
+
textareaHeight?: number;
|
|
88
|
+
/** Icon name for left icon */
|
|
89
|
+
leftIconName?: IconName;
|
|
90
|
+
/** Icon name for right icon */
|
|
91
|
+
rightIconName?: IconName;
|
|
92
|
+
/** Whether the input is disabled */
|
|
93
|
+
disabled?: boolean;
|
|
94
|
+
/** Whether the input is required */
|
|
95
|
+
required?: boolean;
|
|
96
|
+
/** Whether to show character count */
|
|
97
|
+
showCharCount?: boolean;
|
|
98
|
+
/** Primary color for focus state */
|
|
99
|
+
color?: RestyleColor;
|
|
100
|
+
/** Container style overrides */
|
|
101
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
102
|
+
/** Input container style overrides */
|
|
103
|
+
inputContainerStyle?: StyleProp<ViewStyle>;
|
|
104
|
+
/** Test ID for testing */
|
|
105
|
+
testID?: string;
|
|
106
|
+
/** Accessibility label */
|
|
107
|
+
accessibilityLabel?: string;
|
|
108
|
+
/** Accessibility hint */
|
|
109
|
+
accessibilityHint?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Parameters for the useTextInputLogic hook.
|
|
114
|
+
*/
|
|
115
|
+
export interface UseTextInputLogicParams {
|
|
116
|
+
variant: ResponsiveValue<TextInputVariant, RestyleTheme["breakpoints"]>;
|
|
117
|
+
size: ResponsiveValue<TextInputSize, RestyleTheme["breakpoints"]>;
|
|
118
|
+
color: RestyleColor;
|
|
119
|
+
disabled: boolean;
|
|
120
|
+
error?: string;
|
|
121
|
+
isFocused: boolean;
|
|
122
|
+
leftIconName?: IconName;
|
|
123
|
+
rightIconName?: IconName;
|
|
124
|
+
label?: string;
|
|
125
|
+
accessibilityLabel?: string;
|
|
126
|
+
accessibilityHint?: string;
|
|
127
|
+
required?: boolean;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Return value from the useTextInputLogic hook.
|
|
132
|
+
*/
|
|
133
|
+
export interface UseTextInputLogicReturn {
|
|
134
|
+
/** Whether the input is disabled */
|
|
135
|
+
isDisabled: boolean;
|
|
136
|
+
/** Whether the input has an error */
|
|
137
|
+
hasError: boolean;
|
|
138
|
+
/** Container opacity */
|
|
139
|
+
opacity: number;
|
|
140
|
+
/** Background color key */
|
|
141
|
+
finalBackgroundColor: RestyleColor | "transparent";
|
|
142
|
+
/** Border color key */
|
|
143
|
+
finalBorderColor: RestyleColor;
|
|
144
|
+
/** Text color key */
|
|
145
|
+
finalTextColor: RestyleColor;
|
|
146
|
+
/** Placeholder color key */
|
|
147
|
+
finalPlaceholderColor: RestyleColor;
|
|
148
|
+
/** Label color key */
|
|
149
|
+
finalLabelColor: RestyleColor;
|
|
150
|
+
/** Border width */
|
|
151
|
+
borderWidth: number;
|
|
152
|
+
/** Left icon size */
|
|
153
|
+
leftIconSize: IconSize | undefined;
|
|
154
|
+
/** Right icon size */
|
|
155
|
+
rightIconSize: IconSize | undefined;
|
|
156
|
+
/** Icon color key */
|
|
157
|
+
iconColor: RestyleColor;
|
|
158
|
+
/** Accessibility props */
|
|
159
|
+
a11yProps: TextInputA11yProps;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Parameters for the getTextInputA11y function.
|
|
164
|
+
*/
|
|
165
|
+
export interface TextInputA11yParams {
|
|
166
|
+
label?: string;
|
|
167
|
+
accessibilityLabel?: string;
|
|
168
|
+
accessibilityHint?: string;
|
|
169
|
+
disabled: boolean;
|
|
170
|
+
error?: string;
|
|
171
|
+
required?: boolean;
|
|
172
|
+
fallbackLabel: string;
|
|
173
|
+
requiredLabel: string;
|
|
174
|
+
errorPrefixLabel: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Accessibility props returned by getTextInputA11y.
|
|
179
|
+
*/
|
|
180
|
+
export interface TextInputA11yProps {
|
|
181
|
+
accessibilityLabel: string;
|
|
182
|
+
accessibilityHint?: string;
|
|
183
|
+
accessibilityState: { disabled: boolean };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Parameters for resolveTextInputStyle function.
|
|
188
|
+
*/
|
|
189
|
+
export interface ResolveTextInputStyleParams {
|
|
190
|
+
variant: TextInputVariant;
|
|
191
|
+
disabled: boolean;
|
|
192
|
+
error?: string;
|
|
193
|
+
isFocused: boolean;
|
|
194
|
+
color: RestyleColor;
|
|
195
|
+
theme: RestyleTheme;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Result from resolveTextInputStyle function.
|
|
200
|
+
*/
|
|
201
|
+
export interface TextInputStyleResult {
|
|
202
|
+
backgroundColor: string;
|
|
203
|
+
borderColor: string;
|
|
204
|
+
borderWidth: number;
|
|
205
|
+
opacity: number;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Size configuration for TextInput.
|
|
210
|
+
*/
|
|
211
|
+
export interface TextInputSizeConfig {
|
|
212
|
+
height: number;
|
|
213
|
+
paddingHorizontal: number;
|
|
214
|
+
fontSize: number;
|
|
215
|
+
iconSize: number;
|
|
216
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TextInput Module
|
|
3
|
+
*
|
|
4
|
+
* Molecule component for text entry with labels, icons, and validation.
|
|
5
|
+
*
|
|
6
|
+
* Combines Icon, Text, and Box atoms into a complete form field.
|
|
7
|
+
*
|
|
8
|
+
* ## Variants
|
|
9
|
+
* - `outlined`: Border with transparent background (default)
|
|
10
|
+
* - `filled`: Filled background with subtle border
|
|
11
|
+
* - `textarea`: Multi-line with configurable height
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* import { TextInput } from "@/design-system/primitives/inputs/TextInput";
|
|
15
|
+
*
|
|
16
|
+
* <TextInput
|
|
17
|
+
* label="Email"
|
|
18
|
+
* value={email}
|
|
19
|
+
* onChangeText={setEmail}
|
|
20
|
+
* leftIconName="email"
|
|
21
|
+
* error={emailError}
|
|
22
|
+
* required
|
|
23
|
+
* />
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export { TextInput } from "./TextInput";
|
|
27
|
+
|
|
28
|
+
export type {
|
|
29
|
+
TextInputProps,
|
|
30
|
+
TextInputRef,
|
|
31
|
+
TextInputSize,
|
|
32
|
+
TextInputVariant,
|
|
33
|
+
TextInputA11yParams,
|
|
34
|
+
TextInputA11yProps,
|
|
35
|
+
} from "./TextInput.types";
|
|
36
|
+
|
|
37
|
+
export { getTextInputA11y } from "./TextInput.a11y";
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { useDesignSystem } from "../../../provider";
|
|
2
|
+
import { useResponsiveProp } from "@shopify/restyle";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { RestyleColor } from "../../../types";
|
|
5
|
+
import { getTextInputA11y } from "./TextInput.a11y";
|
|
6
|
+
import {
|
|
7
|
+
getTextInputIconColor,
|
|
8
|
+
getTextInputIconSize,
|
|
9
|
+
} from "./TextInput.helpers";
|
|
10
|
+
import {
|
|
11
|
+
TextInputSize,
|
|
12
|
+
TextInputVariant,
|
|
13
|
+
UseTextInputLogicParams,
|
|
14
|
+
UseTextInputLogicReturn,
|
|
15
|
+
} from "./TextInput.types";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Orchestrates TextInput rendering logic and state management.
|
|
19
|
+
*
|
|
20
|
+
* Handles:
|
|
21
|
+
* - Responsive size and variant resolution
|
|
22
|
+
* - State-based color calculations (error, focus, disabled)
|
|
23
|
+
* - Background and border color computation
|
|
24
|
+
* - Icon sizing and color coordination
|
|
25
|
+
* - Label variant selection
|
|
26
|
+
* - Border width adjustment on focus (1px → 2px)
|
|
27
|
+
* - Accessibility props generation
|
|
28
|
+
*
|
|
29
|
+
* @param params - Configuration object for text input behavior
|
|
30
|
+
* @param params.variant - Visual variant ('outlined' | 'filled' | 'textarea')
|
|
31
|
+
* @param params.size - Size variant ('sm' | 'md' | 'lg')
|
|
32
|
+
* @param params.color - Theme color token for focus state
|
|
33
|
+
* @param params.disabled - Whether input is disabled
|
|
34
|
+
* @param params.error - Error message (presence triggers error state)
|
|
35
|
+
* @param params.isFocused - Whether input has focus
|
|
36
|
+
* @param params.leftIconName - Optional left icon
|
|
37
|
+
* @param params.rightIconName - Optional right icon
|
|
38
|
+
* @param params.label - Input label text
|
|
39
|
+
* @param params.accessibilityLabel - Custom a11y label
|
|
40
|
+
* @param params.accessibilityHint - Describes expected input
|
|
41
|
+
* @param params.required - Whether field is required
|
|
42
|
+
*
|
|
43
|
+
* @returns Computed values for rendering TextInput
|
|
44
|
+
* @returns {boolean} isDisabled - Disabled state flag
|
|
45
|
+
* @returns {boolean} hasError - Error state flag
|
|
46
|
+
* @returns {number} opacity - Container opacity (0.5 when disabled)
|
|
47
|
+
* @returns {string} finalBackgroundColor - Background color token
|
|
48
|
+
* @returns {string} finalBorderColor - Border color token
|
|
49
|
+
* @returns {string} finalTextColor - Text color token
|
|
50
|
+
* @returns {string} finalPlaceholderColor - Placeholder color token
|
|
51
|
+
* @returns {string} finalLabelColor - Label color token
|
|
52
|
+
* @returns {number} borderWidth - Border width (1 or 2)
|
|
53
|
+
* @returns {number} leftIconSize - Left icon size in pixels
|
|
54
|
+
* @returns {number} rightIconSize - Right icon size in pixels
|
|
55
|
+
* @returns {string} iconColor - Icon color token
|
|
56
|
+
* @returns {object} a11yProps - Accessibility props
|
|
57
|
+
*
|
|
58
|
+
* @performance This hook uses useMemo() for expensive calculations
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* const {
|
|
62
|
+
* finalBackgroundColor,
|
|
63
|
+
* finalBorderColor,
|
|
64
|
+
* borderWidth,
|
|
65
|
+
* leftIconSize,
|
|
66
|
+
* a11yProps
|
|
67
|
+
* } = useTextInputLogic({
|
|
68
|
+
* variant: "outlined",
|
|
69
|
+
* size: "md",
|
|
70
|
+
* color: "accentPrimary",
|
|
71
|
+
* isFocused: true,
|
|
72
|
+
* leftIconName: "search",
|
|
73
|
+
* label: "Search products",
|
|
74
|
+
* });
|
|
75
|
+
*/
|
|
76
|
+
export function useTextInputLogic(
|
|
77
|
+
params: UseTextInputLogicParams
|
|
78
|
+
): UseTextInputLogicReturn {
|
|
79
|
+
const {
|
|
80
|
+
variant,
|
|
81
|
+
size,
|
|
82
|
+
color,
|
|
83
|
+
disabled,
|
|
84
|
+
error,
|
|
85
|
+
isFocused,
|
|
86
|
+
leftIconName,
|
|
87
|
+
rightIconName,
|
|
88
|
+
label,
|
|
89
|
+
accessibilityLabel,
|
|
90
|
+
accessibilityHint,
|
|
91
|
+
required,
|
|
92
|
+
} = params;
|
|
93
|
+
|
|
94
|
+
const { labels: t } = useDesignSystem();
|
|
95
|
+
const resolvedSize = (useResponsiveProp(size) ?? "md") as TextInputSize;
|
|
96
|
+
const resolvedVariant = (useResponsiveProp(variant) ?? "outlined") as TextInputVariant;
|
|
97
|
+
|
|
98
|
+
const isDisabled = disabled;
|
|
99
|
+
const hasError = !!error;
|
|
100
|
+
const opacity = isDisabled ? 0.5 : 1;
|
|
101
|
+
|
|
102
|
+
// Icon sizes (only if icons provided)
|
|
103
|
+
const leftIconSize = leftIconName
|
|
104
|
+
? getTextInputIconSize(resolvedSize)
|
|
105
|
+
: undefined;
|
|
106
|
+
const rightIconSize = rightIconName
|
|
107
|
+
? getTextInputIconSize(resolvedSize)
|
|
108
|
+
: undefined;
|
|
109
|
+
|
|
110
|
+
// Icon color
|
|
111
|
+
const iconColor = getTextInputIconColor(hasError, isFocused, color);
|
|
112
|
+
|
|
113
|
+
// Background color
|
|
114
|
+
// Use backgroundTertiary for filled variant to ensure distinction in dark mode
|
|
115
|
+
// Textarea uses same background as outlined
|
|
116
|
+
const finalBackgroundColor = useMemo(():
|
|
117
|
+
| RestyleColor
|
|
118
|
+
| "transparent" => {
|
|
119
|
+
if (isDisabled) {
|
|
120
|
+
return "interactiveDisabled";
|
|
121
|
+
}
|
|
122
|
+
if (resolvedVariant === "filled") {
|
|
123
|
+
return "backgroundTertiary";
|
|
124
|
+
}
|
|
125
|
+
// Both outlined and textarea use surfacePrimary
|
|
126
|
+
return "surfacePrimary";
|
|
127
|
+
}, [resolvedVariant, isDisabled]);
|
|
128
|
+
|
|
129
|
+
// Border color
|
|
130
|
+
const finalBorderColor = useMemo((): RestyleColor => {
|
|
131
|
+
if (isDisabled) {
|
|
132
|
+
return "borderSubtle";
|
|
133
|
+
}
|
|
134
|
+
if (hasError) {
|
|
135
|
+
return "feedbackError";
|
|
136
|
+
}
|
|
137
|
+
if (isFocused) {
|
|
138
|
+
return color;
|
|
139
|
+
}
|
|
140
|
+
return "borderDefault";
|
|
141
|
+
}, [isDisabled, hasError, isFocused, color]);
|
|
142
|
+
|
|
143
|
+
// Text color
|
|
144
|
+
const finalTextColor: RestyleColor = isDisabled ? "textDisabled" : "textPrimary";
|
|
145
|
+
|
|
146
|
+
// Placeholder color
|
|
147
|
+
const finalPlaceholderColor: RestyleColor = "textTertiary";
|
|
148
|
+
|
|
149
|
+
// Label color
|
|
150
|
+
const finalLabelColor = useMemo((): RestyleColor => {
|
|
151
|
+
if (hasError) {
|
|
152
|
+
return "feedbackError";
|
|
153
|
+
}
|
|
154
|
+
if (isFocused) {
|
|
155
|
+
return color;
|
|
156
|
+
}
|
|
157
|
+
return "textPrimary";
|
|
158
|
+
}, [hasError, isFocused, color]);
|
|
159
|
+
|
|
160
|
+
// Border width
|
|
161
|
+
const borderWidth = isFocused ? 2 : 1;
|
|
162
|
+
|
|
163
|
+
// Accessibility props
|
|
164
|
+
const a11yProps = useMemo(
|
|
165
|
+
() =>
|
|
166
|
+
getTextInputA11y({
|
|
167
|
+
label,
|
|
168
|
+
accessibilityLabel,
|
|
169
|
+
accessibilityHint,
|
|
170
|
+
disabled: isDisabled,
|
|
171
|
+
error,
|
|
172
|
+
required,
|
|
173
|
+
fallbackLabel: t.designSystem.textInput.fallbackLabel,
|
|
174
|
+
requiredLabel: t.designSystem.textInput.required,
|
|
175
|
+
errorPrefixLabel: t.designSystem.textInput.errorPrefix,
|
|
176
|
+
}),
|
|
177
|
+
[label, accessibilityLabel, accessibilityHint, isDisabled, error, required, t]
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
isDisabled,
|
|
182
|
+
hasError,
|
|
183
|
+
opacity,
|
|
184
|
+
finalBackgroundColor,
|
|
185
|
+
finalBorderColor,
|
|
186
|
+
finalTextColor,
|
|
187
|
+
finalPlaceholderColor,
|
|
188
|
+
finalLabelColor,
|
|
189
|
+
borderWidth,
|
|
190
|
+
leftIconSize,
|
|
191
|
+
rightIconSize,
|
|
192
|
+
iconColor,
|
|
193
|
+
a11yProps,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inputs Components Module
|
|
3
|
+
*
|
|
4
|
+
* Components that capture user data and selections.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
TextInput,
|
|
9
|
+
type TextInputProps,
|
|
10
|
+
type TextInputRef,
|
|
11
|
+
type TextInputSize,
|
|
12
|
+
type TextInputVariant,
|
|
13
|
+
|
|
14
|
+
} from "./TextInput";
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
Checkbox,
|
|
18
|
+
type CheckboxProps,
|
|
19
|
+
type CheckboxRef,
|
|
20
|
+
type CheckboxSize,
|
|
21
|
+
} from "./Checkbox";
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
RadioButton,
|
|
25
|
+
type RadioButtonProps,
|
|
26
|
+
type RadioButtonRef,
|
|
27
|
+
type RadioButtonSize,
|
|
28
|
+
} from "./RadioButton";
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
Switch,
|
|
32
|
+
type SwitchProps,
|
|
33
|
+
type SwitchRef,
|
|
34
|
+
type SwitchSize,
|
|
35
|
+
} from "./Switch";
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
SegmentedControl,
|
|
39
|
+
type SegmentedControlProps,
|
|
40
|
+
type SegmentedControlSize,
|
|
41
|
+
type SegmentedControlVariant,
|
|
42
|
+
type SegmentOption,
|
|
43
|
+
} from "./SegmentedControl";
|
|
44
|
+
|
|
45
|
+
export {
|
|
46
|
+
SelectSheet,
|
|
47
|
+
type SelectSheetProps,
|
|
48
|
+
type SelectSheetOption,
|
|
49
|
+
type SelectSheetMode,
|
|
50
|
+
type SelectSheetPosition,
|
|
51
|
+
type SelectSheetIndicatorPosition,
|
|
52
|
+
} from "./SelectSheet";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AnimatedBox Component
|
|
3
|
+
*
|
|
4
|
+
* @description Animated version of Box for Animated API integration - Atom
|
|
5
|
+
*
|
|
6
|
+
* AnimatedBox wraps Box with React Native's Animated API, enabling
|
|
7
|
+
* smooth transitions and animations while maintaining Restyle props.
|
|
8
|
+
*
|
|
9
|
+
* ## Usage
|
|
10
|
+
* Use AnimatedBox when you need to animate layout properties using
|
|
11
|
+
* React Native's Animated API (Animated.Value, Animated.timing, etc.).
|
|
12
|
+
*
|
|
13
|
+
* ## Features
|
|
14
|
+
* - All Box/Restyle props available
|
|
15
|
+
* - Compatible with Animated.Value for transforms, opacity, etc.
|
|
16
|
+
* - Use with interpolate() for complex animations
|
|
17
|
+
*
|
|
18
|
+
* @see Box.tsx - Base component without animation
|
|
19
|
+
* @see https://reactnative.dev/docs/animated - Animated API docs
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Fade animation
|
|
23
|
+
* const opacity = useRef(new Animated.Value(0)).current;
|
|
24
|
+
*
|
|
25
|
+
* <AnimatedBox style={{ opacity }} padding="lg">
|
|
26
|
+
* <Text>Fading content</Text>
|
|
27
|
+
* </AnimatedBox>
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // Transform animation
|
|
31
|
+
* const translateX = useRef(new Animated.Value(-100)).current;
|
|
32
|
+
*
|
|
33
|
+
* <AnimatedBox
|
|
34
|
+
* style={{ transform: [{ translateX }] }}
|
|
35
|
+
* backgroundColor="surfacePrimary"
|
|
36
|
+
* >
|
|
37
|
+
* <Text>Sliding content</Text>
|
|
38
|
+
* </AnimatedBox>
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import { Animated } from "react-native";
|
|
42
|
+
import { Box } from "./Box";
|
|
43
|
+
|
|
44
|
+
export const AnimatedBox = Animated.createAnimatedComponent(Box);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Box Component
|
|
3
|
+
*
|
|
4
|
+
* @description Fundamental layout primitive with Restyle integration - Atom
|
|
5
|
+
*
|
|
6
|
+
* Box is the most basic building block of the design system.
|
|
7
|
+
* It's a View with all Restyle layout, spacing, and color props.
|
|
8
|
+
*
|
|
9
|
+
* ## Usage
|
|
10
|
+
* Use Box for any layout needs: containers, wrappers, spacers, etc.
|
|
11
|
+
* It provides type-safe access to all theme tokens.
|
|
12
|
+
*
|
|
13
|
+
* ## Available Props (from Restyle)
|
|
14
|
+
* - **Layout**: width, height, flex, flexDirection, alignItems, justifyContent, etc.
|
|
15
|
+
* - **Spacing**: margin, padding, gap (with theme tokens: xs, sm, md, lg, xl, etc.)
|
|
16
|
+
* - **Colors**: backgroundColor, borderColor (with theme color tokens)
|
|
17
|
+
* - **Borders**: borderWidth, borderRadius (with theme radii tokens)
|
|
18
|
+
*
|
|
19
|
+
* @see https://github.com/Shopify/restyle - Restyle documentation
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Basic container
|
|
23
|
+
* <Box padding="lg" backgroundColor="surfacePrimary">
|
|
24
|
+
* <Text>Content</Text>
|
|
25
|
+
* </Box>
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // Flex layout
|
|
29
|
+
* <Box flexDirection="row" alignItems="center" gap="sm">
|
|
30
|
+
* <Icon name="check" />
|
|
31
|
+
* <Text>Label</Text>
|
|
32
|
+
* </Box>
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Responsive padding
|
|
36
|
+
* <Box padding={{ phone: "md", tablet: "xl" }}>
|
|
37
|
+
* <Text>Responsive content</Text>
|
|
38
|
+
* </Box>
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import { createBox } from "@shopify/restyle";
|
|
42
|
+
import { ComponentProps } from "react";
|
|
43
|
+
import { RestyleTheme } from "../../core";
|
|
44
|
+
|
|
45
|
+
export const Box = createBox<RestyleTheme>();
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* BoxRestyleProps — Reusable type for Box Restyle props.
|
|
49
|
+
*
|
|
50
|
+
* Use this type when creating components with a root Box
|
|
51
|
+
* to allow consumers to pass layout/styling props.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* interface MyCardProps extends BoxRestyleProps {
|
|
56
|
+
* title: string;
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
* function MyCard({ title, ...boxProps }: MyCardProps) {
|
|
60
|
+
* return (
|
|
61
|
+
* <Box padding="lg" {...boxProps}>
|
|
62
|
+
* <Text>{title}</Text>
|
|
63
|
+
* </Box>
|
|
64
|
+
* );
|
|
65
|
+
* }
|
|
66
|
+
*
|
|
67
|
+
* // Usage
|
|
68
|
+
* <MyCard title="Hello" marginTop="md" backgroundColor="surfacePrimary" />
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export type BoxRestyleProps = ComponentProps<typeof Box>;
|