@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,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StayEasy Design System - Typography Tokens
|
|
3
|
+
*
|
|
4
|
+
* Typography philosophy:
|
|
5
|
+
* - System fonts first for performance and native feel
|
|
6
|
+
* - Clear hierarchy with distinct sizes
|
|
7
|
+
* - Generous line heights for readability
|
|
8
|
+
* - Consistent letter spacing
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* <Text variant="bodyLarge">Content</Text>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { Platform, TextStyle } from 'react-native';
|
|
15
|
+
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// FONT FAMILIES
|
|
18
|
+
// =============================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* System font stack
|
|
22
|
+
* Uses platform-native fonts for optimal performance and native feel
|
|
23
|
+
*/
|
|
24
|
+
export const fontFamily = {
|
|
25
|
+
// Primary system font
|
|
26
|
+
regular: Platform.select({
|
|
27
|
+
ios: 'System',
|
|
28
|
+
android: 'Roboto',
|
|
29
|
+
default: 'System',
|
|
30
|
+
}),
|
|
31
|
+
|
|
32
|
+
// Medium weight
|
|
33
|
+
medium: Platform.select({
|
|
34
|
+
ios: 'System',
|
|
35
|
+
android: 'Roboto-Medium',
|
|
36
|
+
default: 'System',
|
|
37
|
+
}),
|
|
38
|
+
|
|
39
|
+
// Semibold weight
|
|
40
|
+
semibold: Platform.select({
|
|
41
|
+
ios: 'System',
|
|
42
|
+
android: 'Roboto-Medium', // Android doesn't have semibold
|
|
43
|
+
default: 'System',
|
|
44
|
+
}),
|
|
45
|
+
|
|
46
|
+
// Bold weight
|
|
47
|
+
bold: Platform.select({
|
|
48
|
+
ios: 'System',
|
|
49
|
+
android: 'Roboto-Bold',
|
|
50
|
+
default: 'System',
|
|
51
|
+
}),
|
|
52
|
+
|
|
53
|
+
// Monospace (for code snippets)
|
|
54
|
+
mono: Platform.select({
|
|
55
|
+
ios: 'Menlo',
|
|
56
|
+
android: 'monospace',
|
|
57
|
+
default: 'monospace',
|
|
58
|
+
}),
|
|
59
|
+
} as const;
|
|
60
|
+
|
|
61
|
+
// =============================================================================
|
|
62
|
+
// FONT WEIGHTS
|
|
63
|
+
// =============================================================================
|
|
64
|
+
|
|
65
|
+
export const fontWeight = {
|
|
66
|
+
regular: '400' as TextStyle['fontWeight'],
|
|
67
|
+
medium: '500' as TextStyle['fontWeight'],
|
|
68
|
+
semibold: '600' as TextStyle['fontWeight'],
|
|
69
|
+
bold: '700' as TextStyle['fontWeight'],
|
|
70
|
+
} as const;
|
|
71
|
+
|
|
72
|
+
// =============================================================================
|
|
73
|
+
// FONT SIZES (in points)
|
|
74
|
+
// =============================================================================
|
|
75
|
+
|
|
76
|
+
export const fontSize = {
|
|
77
|
+
xs: 11,
|
|
78
|
+
sm: 13,
|
|
79
|
+
md: 15,
|
|
80
|
+
lg: 17,
|
|
81
|
+
xl: 20,
|
|
82
|
+
'2xl': 24,
|
|
83
|
+
'3xl': 30,
|
|
84
|
+
'4xl': 36,
|
|
85
|
+
'5xl': 48,
|
|
86
|
+
} as const;
|
|
87
|
+
|
|
88
|
+
// =============================================================================
|
|
89
|
+
// LINE HEIGHTS
|
|
90
|
+
// =============================================================================
|
|
91
|
+
|
|
92
|
+
export const lineHeight = {
|
|
93
|
+
tight: 1.2, // Headings
|
|
94
|
+
snug: 1.375, // Subheadings
|
|
95
|
+
normal: 1.5, // Body text
|
|
96
|
+
relaxed: 1.625, // Long-form reading
|
|
97
|
+
loose: 2, // Special cases
|
|
98
|
+
} as const;
|
|
99
|
+
|
|
100
|
+
// Computed line heights (fontSize * multiplier)
|
|
101
|
+
export const lineHeightValues = {
|
|
102
|
+
xs: Math.round(fontSize.xs * lineHeight.normal), // 17
|
|
103
|
+
sm: Math.round(fontSize.sm * lineHeight.normal), // 20
|
|
104
|
+
md: Math.round(fontSize.md * lineHeight.normal), // 23
|
|
105
|
+
lg: Math.round(fontSize.lg * lineHeight.normal), // 26
|
|
106
|
+
xl: Math.round(fontSize.xl * lineHeight.snug), // 28
|
|
107
|
+
'2xl': Math.round(fontSize['2xl'] * lineHeight.snug), // 33
|
|
108
|
+
'3xl': Math.round(fontSize['3xl'] * lineHeight.tight), // 36
|
|
109
|
+
'4xl': Math.round(fontSize['4xl'] * lineHeight.tight), // 43
|
|
110
|
+
'5xl': Math.round(fontSize['5xl'] * lineHeight.tight), // 58
|
|
111
|
+
} as const;
|
|
112
|
+
|
|
113
|
+
// =============================================================================
|
|
114
|
+
// LETTER SPACING
|
|
115
|
+
// =============================================================================
|
|
116
|
+
|
|
117
|
+
export const letterSpacing = {
|
|
118
|
+
tighter: -0.8,
|
|
119
|
+
tight: -0.4,
|
|
120
|
+
normal: 0,
|
|
121
|
+
wide: 0.4,
|
|
122
|
+
wider: 0.8,
|
|
123
|
+
widest: 1.6,
|
|
124
|
+
} as const;
|
|
125
|
+
|
|
126
|
+
// =============================================================================
|
|
127
|
+
// TYPOGRAPHY PRESETS
|
|
128
|
+
// =============================================================================
|
|
129
|
+
|
|
130
|
+
export const typographyPresets = {
|
|
131
|
+
// Display styles (heroes, splash screens)
|
|
132
|
+
displayLarge: {
|
|
133
|
+
fontSize: fontSize['5xl'],
|
|
134
|
+
lineHeight: lineHeightValues['5xl'],
|
|
135
|
+
fontWeight: fontWeight.bold,
|
|
136
|
+
letterSpacing: letterSpacing.tighter,
|
|
137
|
+
},
|
|
138
|
+
displayMedium: {
|
|
139
|
+
fontSize: fontSize['4xl'],
|
|
140
|
+
lineHeight: lineHeightValues['4xl'],
|
|
141
|
+
fontWeight: fontWeight.bold,
|
|
142
|
+
letterSpacing: letterSpacing.tighter,
|
|
143
|
+
},
|
|
144
|
+
displaySmall: {
|
|
145
|
+
fontSize: fontSize['3xl'],
|
|
146
|
+
lineHeight: lineHeightValues['3xl'],
|
|
147
|
+
fontWeight: fontWeight.bold,
|
|
148
|
+
letterSpacing: letterSpacing.tight,
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
// Heading styles
|
|
152
|
+
headingLarge: {
|
|
153
|
+
fontSize: fontSize['2xl'],
|
|
154
|
+
lineHeight: lineHeightValues['2xl'],
|
|
155
|
+
fontWeight: fontWeight.semibold,
|
|
156
|
+
letterSpacing: letterSpacing.tight,
|
|
157
|
+
},
|
|
158
|
+
headingMedium: {
|
|
159
|
+
fontSize: fontSize.xl,
|
|
160
|
+
lineHeight: lineHeightValues.xl,
|
|
161
|
+
fontWeight: fontWeight.semibold,
|
|
162
|
+
letterSpacing: letterSpacing.tight,
|
|
163
|
+
},
|
|
164
|
+
headingSmall: {
|
|
165
|
+
fontSize: fontSize.lg,
|
|
166
|
+
lineHeight: lineHeightValues.lg,
|
|
167
|
+
fontWeight: fontWeight.semibold,
|
|
168
|
+
letterSpacing: letterSpacing.normal,
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
// Body styles
|
|
172
|
+
bodyLarge: {
|
|
173
|
+
fontSize: fontSize.lg,
|
|
174
|
+
lineHeight: lineHeightValues.lg,
|
|
175
|
+
fontWeight: fontWeight.regular,
|
|
176
|
+
letterSpacing: letterSpacing.normal,
|
|
177
|
+
},
|
|
178
|
+
bodyMedium: {
|
|
179
|
+
fontSize: fontSize.md,
|
|
180
|
+
lineHeight: lineHeightValues.md,
|
|
181
|
+
fontWeight: fontWeight.regular,
|
|
182
|
+
letterSpacing: letterSpacing.normal,
|
|
183
|
+
},
|
|
184
|
+
bodySmall: {
|
|
185
|
+
fontSize: fontSize.sm,
|
|
186
|
+
lineHeight: lineHeightValues.sm,
|
|
187
|
+
fontWeight: fontWeight.regular,
|
|
188
|
+
letterSpacing: letterSpacing.normal,
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
// Label styles (buttons, form labels)
|
|
192
|
+
labelLarge: {
|
|
193
|
+
fontSize: fontSize.lg,
|
|
194
|
+
lineHeight: lineHeightValues.lg,
|
|
195
|
+
fontWeight: fontWeight.medium,
|
|
196
|
+
letterSpacing: letterSpacing.normal,
|
|
197
|
+
},
|
|
198
|
+
labelMedium: {
|
|
199
|
+
fontSize: fontSize.md,
|
|
200
|
+
lineHeight: lineHeightValues.md,
|
|
201
|
+
fontWeight: fontWeight.medium,
|
|
202
|
+
letterSpacing: letterSpacing.wide,
|
|
203
|
+
},
|
|
204
|
+
labelSmall: {
|
|
205
|
+
fontSize: fontSize.sm,
|
|
206
|
+
lineHeight: lineHeightValues.sm,
|
|
207
|
+
fontWeight: fontWeight.medium,
|
|
208
|
+
letterSpacing: letterSpacing.wide,
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
// Caption styles
|
|
212
|
+
caption: {
|
|
213
|
+
fontSize: fontSize.sm,
|
|
214
|
+
lineHeight: lineHeightValues.sm,
|
|
215
|
+
fontWeight: fontWeight.regular,
|
|
216
|
+
letterSpacing: letterSpacing.wide,
|
|
217
|
+
},
|
|
218
|
+
captionSmall: {
|
|
219
|
+
fontSize: fontSize.xs,
|
|
220
|
+
lineHeight: lineHeightValues.xs,
|
|
221
|
+
fontWeight: fontWeight.regular,
|
|
222
|
+
letterSpacing: letterSpacing.wide,
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
// Overline (small uppercase labels)
|
|
226
|
+
overline: {
|
|
227
|
+
fontSize: fontSize.xs,
|
|
228
|
+
lineHeight: lineHeightValues.xs,
|
|
229
|
+
fontWeight: fontWeight.semibold,
|
|
230
|
+
letterSpacing: letterSpacing.widest,
|
|
231
|
+
textTransform: 'uppercase' as TextStyle['textTransform'],
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
// Code/mono styles
|
|
235
|
+
code: {
|
|
236
|
+
fontSize: fontSize.sm,
|
|
237
|
+
lineHeight: lineHeightValues.sm,
|
|
238
|
+
fontWeight: fontWeight.regular,
|
|
239
|
+
letterSpacing: letterSpacing.normal,
|
|
240
|
+
},
|
|
241
|
+
} as const;
|
|
242
|
+
|
|
243
|
+
// =============================================================================
|
|
244
|
+
// TYPE EXPORTS
|
|
245
|
+
// =============================================================================
|
|
246
|
+
|
|
247
|
+
export type FontFamily = typeof fontFamily;
|
|
248
|
+
export type FontWeight = typeof fontWeight;
|
|
249
|
+
export type FontSize = typeof fontSize;
|
|
250
|
+
export type TypographyPresets = typeof typographyPresets;
|
|
251
|
+
export type TypographyVariant = keyof typeof typographyPresets;
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* El Sendero Design System - Shared Types
|
|
3
|
+
*
|
|
4
|
+
* Types shared across the entire design system that can be used
|
|
5
|
+
* throughout the application.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
|
|
9
|
+
import { RestyleTheme, AppThemeColors } from "./core/restyle";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Material Design icon name (strongly typed from @expo/vector-icons/MaterialIcons)
|
|
13
|
+
*
|
|
14
|
+
* This type represents all available Material Icons from the Material Icons library.
|
|
15
|
+
* It is used throughout the design system for icon-based components.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* import { MaterialIconName } from '@/src/design-system';
|
|
20
|
+
*
|
|
21
|
+
* const iconName: MaterialIconName = 'add';
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export type MaterialIconName = keyof typeof MaterialIcons.glyphMap;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Built-in theme color type — only the colors defined in the base Restyle theme.
|
|
28
|
+
* Used internally by components when passing color tokens to Restyle primitives
|
|
29
|
+
* (Box, Text, etc.) which are typed against the base theme.
|
|
30
|
+
*
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
export type BaseThemeColor = keyof RestyleTheme["colors"];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Restyle color type — represents all available colors in the design system theme,
|
|
37
|
+
* including any app-specific tokens registered via `AppThemeColors` augmentation.
|
|
38
|
+
*
|
|
39
|
+
* This unified type is used across all components that accept a color prop.
|
|
40
|
+
* Apps extend the palette by augmenting `AppThemeColors` in a `.d.ts` file
|
|
41
|
+
* and providing a matching theme to `DesignSystemProvider`.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* import { RestyleColor } from '@praxiis/ui';
|
|
46
|
+
*
|
|
47
|
+
* const color: RestyleColor = 'accentPrimary';
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export type RestyleColor = keyof RestyleTheme["colors"] | keyof AppThemeColors;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StayEasy Design System - Accessibility Utilities
|
|
3
|
+
*
|
|
4
|
+
* Helpers for building accessible components.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { AccessibilityRole, AccessibilityState } from "react-native";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Common accessibility roles mapped to their purposes
|
|
11
|
+
*/
|
|
12
|
+
export const a11yRoles = {
|
|
13
|
+
button: "button" as AccessibilityRole,
|
|
14
|
+
link: "link" as AccessibilityRole,
|
|
15
|
+
search: "search" as AccessibilityRole,
|
|
16
|
+
image: "image" as AccessibilityRole,
|
|
17
|
+
header: "header" as AccessibilityRole,
|
|
18
|
+
text: "text" as AccessibilityRole,
|
|
19
|
+
checkbox: "checkbox" as AccessibilityRole,
|
|
20
|
+
slider: "adjustable" as AccessibilityRole,
|
|
21
|
+
tab: "tab" as AccessibilityRole,
|
|
22
|
+
tablist: "tablist" as AccessibilityRole,
|
|
23
|
+
menu: "menu" as AccessibilityRole,
|
|
24
|
+
menuitem: "menuitem" as AccessibilityRole,
|
|
25
|
+
progressbar: "progressbar" as AccessibilityRole,
|
|
26
|
+
alert: "alert" as AccessibilityRole,
|
|
27
|
+
none: "none" as AccessibilityRole,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create accessibility state object
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* <Pressable accessibilityState={a11yState({ selected: isSelected, disabled })} />
|
|
35
|
+
*/
|
|
36
|
+
export function a11yState(state: {
|
|
37
|
+
disabled?: boolean;
|
|
38
|
+
selected?: boolean;
|
|
39
|
+
checked?: boolean | "mixed";
|
|
40
|
+
busy?: boolean;
|
|
41
|
+
expanded?: boolean;
|
|
42
|
+
}): AccessibilityState {
|
|
43
|
+
return state;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Generate accessibility props for a button
|
|
48
|
+
*/
|
|
49
|
+
export function buttonA11yProps(options: {
|
|
50
|
+
label: string;
|
|
51
|
+
hint?: string;
|
|
52
|
+
disabled?: boolean;
|
|
53
|
+
}) {
|
|
54
|
+
return {
|
|
55
|
+
accessible: true,
|
|
56
|
+
accessibilityRole: a11yRoles.button,
|
|
57
|
+
accessibilityLabel: options.label,
|
|
58
|
+
accessibilityHint: options.hint,
|
|
59
|
+
accessibilityState: a11yState({ disabled: options.disabled }),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Generate accessibility props for a checkbox
|
|
65
|
+
*/
|
|
66
|
+
export function checkboxA11yProps(options: {
|
|
67
|
+
label: string;
|
|
68
|
+
checked: boolean;
|
|
69
|
+
disabled?: boolean;
|
|
70
|
+
}) {
|
|
71
|
+
return {
|
|
72
|
+
accessible: true,
|
|
73
|
+
accessibilityRole: a11yRoles.checkbox,
|
|
74
|
+
accessibilityLabel: options.label,
|
|
75
|
+
accessibilityState: a11yState({
|
|
76
|
+
checked: options.checked,
|
|
77
|
+
disabled: options.disabled,
|
|
78
|
+
}),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Generate accessibility props for an image
|
|
84
|
+
*/
|
|
85
|
+
export function imageA11yProps(options: {
|
|
86
|
+
label: string;
|
|
87
|
+
isDecorative?: boolean;
|
|
88
|
+
}) {
|
|
89
|
+
if (options.isDecorative) {
|
|
90
|
+
return {
|
|
91
|
+
accessible: false,
|
|
92
|
+
accessibilityElementsHidden: true,
|
|
93
|
+
importantForAccessibility: "no-hide-descendants" as const,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
accessible: true,
|
|
99
|
+
accessibilityRole: a11yRoles.image,
|
|
100
|
+
accessibilityLabel: options.label,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Generate accessibility props for a heading
|
|
106
|
+
*/
|
|
107
|
+
export function headingA11yProps(
|
|
108
|
+
options: { level?: 1 | 2 | 3 | 4 | 5 | 6 } = {}
|
|
109
|
+
) {
|
|
110
|
+
return {
|
|
111
|
+
accessible: true,
|
|
112
|
+
accessibilityRole: a11yRoles.header,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Calculate if a color combination meets WCAG contrast requirements
|
|
118
|
+
* Returns approximate ratio (not perfect but useful for dev-time checks)
|
|
119
|
+
*
|
|
120
|
+
* @param foreground - Hex color string
|
|
121
|
+
* @param background - Hex color string
|
|
122
|
+
* @returns Approximate contrast ratio
|
|
123
|
+
*/
|
|
124
|
+
export function getContrastRatio(
|
|
125
|
+
foreground: string,
|
|
126
|
+
background: string
|
|
127
|
+
): number {
|
|
128
|
+
const getLuminance = (hex: string): number => {
|
|
129
|
+
const rgb = hex
|
|
130
|
+
.replace("#", "")
|
|
131
|
+
.match(/.{2}/g)
|
|
132
|
+
?.map((c) => {
|
|
133
|
+
const val = parseInt(c, 16) / 255;
|
|
134
|
+
return val <= 0.03928
|
|
135
|
+
? val / 12.92
|
|
136
|
+
: Math.pow((val + 0.055) / 1.055, 2.4);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
if (!rgb) return 0;
|
|
140
|
+
return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const l1 = getLuminance(foreground);
|
|
144
|
+
const l2 = getLuminance(background);
|
|
145
|
+
const lighter = Math.max(l1, l2);
|
|
146
|
+
const darker = Math.min(l1, l2);
|
|
147
|
+
|
|
148
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Check if contrast meets WCAG AA for normal text (4.5:1)
|
|
153
|
+
*/
|
|
154
|
+
export function meetsContrastAA(
|
|
155
|
+
foreground: string,
|
|
156
|
+
background: string
|
|
157
|
+
): boolean {
|
|
158
|
+
return getContrastRatio(foreground, background) >= 4.5;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Check if contrast meets WCAG AA for large text (3:1)
|
|
163
|
+
*/
|
|
164
|
+
export function meetsContrastAALarge(
|
|
165
|
+
foreground: string,
|
|
166
|
+
background: string
|
|
167
|
+
): boolean {
|
|
168
|
+
return getContrastRatio(foreground, background) >= 3;
|
|
169
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StayEasy Design System - Utils Exports
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
isIOS,
|
|
7
|
+
isAndroid,
|
|
8
|
+
platformSelect,
|
|
9
|
+
iosOnly,
|
|
10
|
+
androidOnly,
|
|
11
|
+
getStatusBarHeight,
|
|
12
|
+
MIN_TOUCH_TARGET,
|
|
13
|
+
} from './platform';
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
a11yRoles,
|
|
17
|
+
a11yState,
|
|
18
|
+
buttonA11yProps,
|
|
19
|
+
checkboxA11yProps,
|
|
20
|
+
imageA11yProps,
|
|
21
|
+
headingA11yProps,
|
|
22
|
+
getContrastRatio,
|
|
23
|
+
meetsContrastAA,
|
|
24
|
+
meetsContrastAALarge,
|
|
25
|
+
} from './accessibility';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StayEasy Design System - Platform Utilities
|
|
3
|
+
*
|
|
4
|
+
* Cross-platform helpers for consistent behavior across iOS and Android.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Platform } from 'react-native';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check if running on iOS
|
|
11
|
+
*/
|
|
12
|
+
export const isIOS = Platform.OS === 'ios';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Check if running on Android
|
|
16
|
+
*/
|
|
17
|
+
export const isAndroid = Platform.OS === 'android';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get platform-specific value
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const padding = platformSelect({ ios: 16, android: 12 });
|
|
24
|
+
*/
|
|
25
|
+
export function platformSelect<T>(specifics: { ios: T; android: T }): T {
|
|
26
|
+
return Platform.select(specifics) as T;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Apply iOS-only styles
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const styles = StyleSheet.create({
|
|
34
|
+
* container: {
|
|
35
|
+
* ...iosOnly({ shadowOpacity: 0.1 }),
|
|
36
|
+
* },
|
|
37
|
+
* });
|
|
38
|
+
*/
|
|
39
|
+
export function iosOnly<T extends object>(styles: T): T | object {
|
|
40
|
+
return isIOS ? styles : {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Apply Android-only styles
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const styles = StyleSheet.create({
|
|
48
|
+
* container: {
|
|
49
|
+
* ...androidOnly({ elevation: 4 }),
|
|
50
|
+
* },
|
|
51
|
+
* });
|
|
52
|
+
*/
|
|
53
|
+
export function androidOnly<T extends object>(styles: T): T | object {
|
|
54
|
+
return isAndroid ? styles : {};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get the status bar height for the platform
|
|
59
|
+
*/
|
|
60
|
+
export function getStatusBarHeight(): number {
|
|
61
|
+
return Platform.select({
|
|
62
|
+
ios: 44, // Approximate, use SafeAreaView for accuracy
|
|
63
|
+
android: 24,
|
|
64
|
+
default: 0,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get minimum touch target size per platform guidelines
|
|
70
|
+
* iOS: 44pt, Android: 48dp (we use 44 for consistency)
|
|
71
|
+
*/
|
|
72
|
+
export const MIN_TOUCH_TARGET = 44;
|