@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.
Files changed (187) hide show
  1. package/dist/index.d.mts +52556 -0
  2. package/dist/index.d.ts +52556 -0
  3. package/dist/index.js +8753 -0
  4. package/dist/index.mjs +8777 -0
  5. package/package.json +70 -0
  6. package/src/__test-utils__/index.tsx +39 -0
  7. package/src/components/CalendarStrip/CalendarStrip.helpers.ts +106 -0
  8. package/src/components/CalendarStrip/CalendarStrip.tsx +83 -0
  9. package/src/components/CalendarStrip/CalendarStrip.types.ts +133 -0
  10. package/src/components/CalendarStrip/DayCard/DayCard.helpers.ts +44 -0
  11. package/src/components/CalendarStrip/DayCard/DayCard.tsx +71 -0
  12. package/src/components/CalendarStrip/DayCard/DayCard.types.ts +134 -0
  13. package/src/components/CalendarStrip/DayCard/index.ts +2 -0
  14. package/src/components/CalendarStrip/DayCard/useDayCardLogic.ts +45 -0
  15. package/src/components/CalendarStrip/index.ts +9 -0
  16. package/src/components/CalendarStrip/useCalendarStripLogic.ts +53 -0
  17. package/src/components/EmptyState/EmptyState.helpers.ts +104 -0
  18. package/src/components/EmptyState/EmptyState.tsx +205 -0
  19. package/src/components/EmptyState/EmptyState.types.ts +213 -0
  20. package/src/components/EmptyState/index.ts +44 -0
  21. package/src/components/EmptyState/useEmptyStateLogic.ts +131 -0
  22. package/src/components/Header/Header.helpers.ts +93 -0
  23. package/src/components/Header/Header.tsx +185 -0
  24. package/src/components/Header/Header.types.ts +153 -0
  25. package/src/components/Header/index.ts +44 -0
  26. package/src/components/Header/useHeaderLogic.ts +146 -0
  27. package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.helpers.ts +50 -0
  28. package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.tsx +78 -0
  29. package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.types.ts +99 -0
  30. package/src/components/ScheduleItem/ScheduleItem/index.ts +16 -0
  31. package/src/components/ScheduleItem/ScheduleItem/useScheduleItemLogic.ts +31 -0
  32. package/src/components/ScheduleItem/index.ts +15 -0
  33. package/src/components/index.ts +40 -0
  34. package/src/core/index.ts +34 -0
  35. package/src/core/restyle/RestyleThemeProviderWrapper.tsx +31 -0
  36. package/src/core/restyle/index.ts +38 -0
  37. package/src/core/restyle/restylePresetRegistry.ts +195 -0
  38. package/src/core/restyle/restyleTheme.ts +1352 -0
  39. package/src/core/restyle/restyleTypes.ts +8 -0
  40. package/src/core/restyle/useRestyleTheme.ts +10 -0
  41. package/src/hooks/animations/index.ts +3 -0
  42. package/src/hooks/animations/useAnimatedValue.ts +10 -0
  43. package/src/hooks/animations/useEntranceAnimation.ts +106 -0
  44. package/src/hooks/animations/usePulseAnimation.ts +63 -0
  45. package/src/hooks/index.ts +30 -0
  46. package/src/hooks/useReducedMotion.ts +60 -0
  47. package/src/i18n/index.ts +2 -0
  48. package/src/i18n/labels/en.ts +120 -0
  49. package/src/i18n/labels/es.ts +120 -0
  50. package/src/i18n/labels/index.ts +6 -0
  51. package/src/i18n/labels/types.ts +165 -0
  52. package/src/index.tsx +215 -0
  53. package/src/primitives/actions/Button/Button.helpers.ts +243 -0
  54. package/src/primitives/actions/Button/Button.tsx +198 -0
  55. package/src/primitives/actions/Button/Button.types.ts +207 -0
  56. package/src/primitives/actions/Button/index.ts +41 -0
  57. package/src/primitives/actions/Button/useButtonLogic.ts +160 -0
  58. package/src/primitives/actions/IconButton/IconButton.helpers.ts +235 -0
  59. package/src/primitives/actions/IconButton/IconButton.tsx +177 -0
  60. package/src/primitives/actions/IconButton/IconButton.types.ts +273 -0
  61. package/src/primitives/actions/IconButton/index.ts +30 -0
  62. package/src/primitives/actions/IconButton/useIconButtonLogic.ts +172 -0
  63. package/src/primitives/actions/index.ts +20 -0
  64. package/src/primitives/content/Avatar/Avatar.helpers.ts +177 -0
  65. package/src/primitives/content/Avatar/Avatar.tsx +199 -0
  66. package/src/primitives/content/Avatar/Avatar.types.ts +222 -0
  67. package/src/primitives/content/Avatar/index.ts +46 -0
  68. package/src/primitives/content/Avatar/useAvatarLogic.ts +149 -0
  69. package/src/primitives/content/Badge/Badge.helpers.ts +175 -0
  70. package/src/primitives/content/Badge/Badge.tsx +174 -0
  71. package/src/primitives/content/Badge/Badge.types.ts +223 -0
  72. package/src/primitives/content/Badge/index.ts +40 -0
  73. package/src/primitives/content/Badge/useBadgeLogic.ts +128 -0
  74. package/src/primitives/content/Card/Card.helpers.ts +27 -0
  75. package/src/primitives/content/Card/Card.tsx +123 -0
  76. package/src/primitives/content/Card/Card.types.ts +95 -0
  77. package/src/primitives/content/Card/index.ts +20 -0
  78. package/src/primitives/content/Card/useCardLogic.ts +48 -0
  79. package/src/primitives/content/Chip/Chip.helpers.ts +304 -0
  80. package/src/primitives/content/Chip/Chip.tsx +205 -0
  81. package/src/primitives/content/Chip/Chip.types.ts +234 -0
  82. package/src/primitives/content/Chip/index.ts +47 -0
  83. package/src/primitives/content/Chip/useChipLogic.ts +167 -0
  84. package/src/primitives/content/Icon/Icon.helpers.ts +54 -0
  85. package/src/primitives/content/Icon/Icon.tsx +110 -0
  86. package/src/primitives/content/Icon/Icon.types.ts +95 -0
  87. package/src/primitives/content/Icon/index.ts +20 -0
  88. package/src/primitives/content/Icon/useIconLogic.ts +73 -0
  89. package/src/primitives/content/index.ts +45 -0
  90. package/src/primitives/feedback/ProgressBar/ProgressBar.helpers.ts +122 -0
  91. package/src/primitives/feedback/ProgressBar/ProgressBar.tsx +154 -0
  92. package/src/primitives/feedback/ProgressBar/ProgressBar.types.ts +178 -0
  93. package/src/primitives/feedback/ProgressBar/index.ts +17 -0
  94. package/src/primitives/feedback/ProgressBar/useProgressBarLogic.ts +120 -0
  95. package/src/primitives/feedback/Skeleton/Skeleton.helpers.ts +145 -0
  96. package/src/primitives/feedback/Skeleton/Skeleton.tsx +155 -0
  97. package/src/primitives/feedback/Skeleton/Skeleton.types.ts +223 -0
  98. package/src/primitives/feedback/Skeleton/index.ts +44 -0
  99. package/src/primitives/feedback/Skeleton/useSkeletonLogic.ts +125 -0
  100. package/src/primitives/feedback/Spinner/Spinner.helpers.ts +40 -0
  101. package/src/primitives/feedback/Spinner/Spinner.tsx +105 -0
  102. package/src/primitives/feedback/Spinner/Spinner.types.ts +114 -0
  103. package/src/primitives/feedback/Spinner/index.ts +18 -0
  104. package/src/primitives/feedback/Spinner/useSpinnerLogic.ts +84 -0
  105. package/src/primitives/feedback/Toast/Toast.helpers.ts +163 -0
  106. package/src/primitives/feedback/Toast/Toast.tsx +190 -0
  107. package/src/primitives/feedback/Toast/Toast.types.ts +270 -0
  108. package/src/primitives/feedback/Toast/ToastContext.tsx +96 -0
  109. package/src/primitives/feedback/Toast/ToastProvider.tsx +241 -0
  110. package/src/primitives/feedback/Toast/index.ts +59 -0
  111. package/src/primitives/feedback/Toast/useToastLogic.ts +112 -0
  112. package/src/primitives/feedback/index.ts +45 -0
  113. package/src/primitives/index.ts +158 -0
  114. package/src/primitives/inputs/Checkbox/Checkbox.helpers.ts +132 -0
  115. package/src/primitives/inputs/Checkbox/Checkbox.tsx +150 -0
  116. package/src/primitives/inputs/Checkbox/Checkbox.types.ts +106 -0
  117. package/src/primitives/inputs/Checkbox/index.ts +30 -0
  118. package/src/primitives/inputs/Checkbox/useCheckboxLogic.ts +121 -0
  119. package/src/primitives/inputs/RadioButton/RadioButton.helpers.ts +123 -0
  120. package/src/primitives/inputs/RadioButton/RadioButton.tsx +159 -0
  121. package/src/primitives/inputs/RadioButton/RadioButton.types.ts +106 -0
  122. package/src/primitives/inputs/RadioButton/index.ts +25 -0
  123. package/src/primitives/inputs/RadioButton/useRadioButtonLogic.ts +117 -0
  124. package/src/primitives/inputs/SegmentedControl/SegmentedControl.helpers.ts +174 -0
  125. package/src/primitives/inputs/SegmentedControl/SegmentedControl.tsx +224 -0
  126. package/src/primitives/inputs/SegmentedControl/SegmentedControl.types.ts +187 -0
  127. package/src/primitives/inputs/SegmentedControl/index.ts +39 -0
  128. package/src/primitives/inputs/SegmentedControl/useSegmentedControlLogic.ts +151 -0
  129. package/src/primitives/inputs/SelectSheet/SelectSheet.helpers.ts +147 -0
  130. package/src/primitives/inputs/SelectSheet/SelectSheet.tsx +247 -0
  131. package/src/primitives/inputs/SelectSheet/SelectSheet.types.ts +196 -0
  132. package/src/primitives/inputs/SelectSheet/SelectSheetOption.tsx +177 -0
  133. package/src/primitives/inputs/SelectSheet/index.ts +48 -0
  134. package/src/primitives/inputs/SelectSheet/useSelectSheetLogic.ts +309 -0
  135. package/src/primitives/inputs/Switch/Switch.helpers.ts +109 -0
  136. package/src/primitives/inputs/Switch/Switch.tsx +191 -0
  137. package/src/primitives/inputs/Switch/Switch.types.ts +154 -0
  138. package/src/primitives/inputs/Switch/index.ts +40 -0
  139. package/src/primitives/inputs/Switch/useSwitchLogic.ts +192 -0
  140. package/src/primitives/inputs/TextInput/TextInput.helpers.ts +206 -0
  141. package/src/primitives/inputs/TextInput/TextInput.tsx +392 -0
  142. package/src/primitives/inputs/TextInput/TextInput.types.ts +216 -0
  143. package/src/primitives/inputs/TextInput/index.ts +37 -0
  144. package/src/primitives/inputs/TextInput/useTextInputLogic.ts +195 -0
  145. package/src/primitives/inputs/index.ts +52 -0
  146. package/src/primitives/layout/AnimatedBox.tsx +44 -0
  147. package/src/primitives/layout/Box.tsx +71 -0
  148. package/src/primitives/layout/Divider/Divider.helpers.ts +115 -0
  149. package/src/primitives/layout/Divider/Divider.tsx +139 -0
  150. package/src/primitives/layout/Divider/Divider.types.ts +178 -0
  151. package/src/primitives/layout/Divider/index.ts +24 -0
  152. package/src/primitives/layout/Divider/useDividerLogic.ts +109 -0
  153. package/src/primitives/layout/FlatList.tsx +66 -0
  154. package/src/primitives/layout/Pressable.tsx +74 -0
  155. package/src/primitives/layout/ScrollView.tsx +63 -0
  156. package/src/primitives/layout/Stack.tsx +69 -0
  157. package/src/primitives/layout/index.ts +40 -0
  158. package/src/primitives/navigation/index.ts +6 -0
  159. package/src/primitives/overlays/Modal/Modal.helpers.ts +31 -0
  160. package/src/primitives/overlays/Modal/Modal.tsx +264 -0
  161. package/src/primitives/overlays/Modal/Modal.types.ts +193 -0
  162. package/src/primitives/overlays/Modal/index.ts +43 -0
  163. package/src/primitives/overlays/Modal/useModalLogic.ts +103 -0
  164. package/src/primitives/overlays/index.ts +12 -0
  165. package/src/primitives/typography/Text.tsx +51 -0
  166. package/src/primitives/typography/index.ts +1 -0
  167. package/src/provider/DesignSystemContext.ts +22 -0
  168. package/src/provider/DesignSystemProvider.tsx +121 -0
  169. package/src/provider/index.ts +7 -0
  170. package/src/providers/ThemeProvider/createTheme.ts +304 -0
  171. package/src/providers/ThemeProvider/defaultTheme.ts +70 -0
  172. package/src/providers/ThemeProvider/index.ts +34 -0
  173. package/src/providers/ThemeProvider/types.ts +249 -0
  174. package/src/providers/index.ts +29 -0
  175. package/src/tokens/colors.ts +371 -0
  176. package/src/tokens/index.ts +145 -0
  177. package/src/tokens/motion.ts +176 -0
  178. package/src/tokens/radii.ts +82 -0
  179. package/src/tokens/scales.ts +588 -0
  180. package/src/tokens/shadows.ts +190 -0
  181. package/src/tokens/spacing.ts +140 -0
  182. package/src/tokens/tokens.json +207 -0
  183. package/src/tokens/typography.ts +251 -0
  184. package/src/types.ts +50 -0
  185. package/src/utils/accessibility.ts +169 -0
  186. package/src/utils/index.ts +25 -0
  187. package/src/utils/platform.ts +72 -0
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Design System Labels — Type Definitions
3
+ *
4
+ * Defines the shape of all accessibility labels used by the design system.
5
+ * Each component group has its own section. The consuming app can override
6
+ * any or all labels by passing a partial object to DesignSystemProvider.
7
+ */
8
+
9
+ export interface ButtonLabels {
10
+ loadingLabel: string;
11
+ }
12
+
13
+ export interface IconButtonLabels {
14
+ loadingLabel: string;
15
+ }
16
+
17
+ export interface RadioButtonLabels {
18
+ fallbackLabel: string;
19
+ }
20
+
21
+ export interface AvatarLabels {
22
+ fallbackLabel: string;
23
+ statusOnline: string;
24
+ statusOffline: string;
25
+ statusBusy: string;
26
+ statusAway: string;
27
+ }
28
+
29
+ export interface BadgeLabels {
30
+ fallbackLabel: string;
31
+ statusIndicator: string;
32
+ colorPrimary: string;
33
+ colorSuccess: string;
34
+ colorWarning: string;
35
+ colorError: string;
36
+ colorInfo: string;
37
+ }
38
+
39
+ export interface ChipLabels {
40
+ toggleHint: string;
41
+ removeHint: string;
42
+ }
43
+
44
+ export interface SpinnerLabels {
45
+ fallbackLabel: string;
46
+ }
47
+
48
+ export interface ProgressBarLabels {
49
+ fallbackLabel: string;
50
+ }
51
+
52
+ export interface ToastLabels {
53
+ prefixSuccess: string;
54
+ prefixError: string;
55
+ prefixWarning: string;
56
+ prefixInfo: string;
57
+ }
58
+
59
+ export interface TextInputLabels {
60
+ fallbackLabel: string;
61
+ required: string;
62
+ errorPrefix: string;
63
+ }
64
+
65
+ export interface ModalLabels {
66
+ fallbackTitle: string;
67
+ positionBottom: string;
68
+ positionTop: string;
69
+ positionCenter: string;
70
+ closeLabel: string;
71
+ closeHint: string;
72
+ }
73
+
74
+ export interface SegmentedControlLabels {
75
+ containerLabel: string;
76
+ options: string;
77
+ selected: string;
78
+ currentlySelected: string;
79
+ doubleTapToSelect: string;
80
+ of: string;
81
+ }
82
+
83
+ export interface SelectSheetLabels {
84
+ positionBottom: string;
85
+ positionTop: string;
86
+ positionCenter: string;
87
+ fallbackTitle: string;
88
+ selected: string;
89
+ disabled: string;
90
+ of: string;
91
+ doneLabel: string;
92
+ itemsSelected: string;
93
+ doneHint: string;
94
+ closeLabel: string;
95
+ closeHint: string;
96
+ deselected: string;
97
+ }
98
+
99
+ export interface CalendarLabels {
100
+ datePicker: {
101
+ label: string;
102
+ selected: string;
103
+ today: string;
104
+ daysShown: string;
105
+ };
106
+ days: {
107
+ sun: string;
108
+ mon: string;
109
+ tue: string;
110
+ wed: string;
111
+ thu: string;
112
+ fri: string;
113
+ sat: string;
114
+ };
115
+ months: {
116
+ jan: string;
117
+ feb: string;
118
+ mar: string;
119
+ apr: string;
120
+ may: string;
121
+ jun: string;
122
+ jul: string;
123
+ aug: string;
124
+ sep: string;
125
+ oct: string;
126
+ nov: string;
127
+ dec: string;
128
+ };
129
+ }
130
+
131
+ export interface HeaderLabels {
132
+ backButton: {
133
+ label: string;
134
+ hint: string;
135
+ };
136
+ }
137
+
138
+ export interface DesignSystemLabels {
139
+ designSystem: {
140
+ button: ButtonLabels;
141
+ iconButton: IconButtonLabels;
142
+ radioButton: RadioButtonLabels;
143
+ avatar: AvatarLabels;
144
+ badge: BadgeLabels;
145
+ chip: ChipLabels;
146
+ spinner: SpinnerLabels;
147
+ progressBar: ProgressBarLabels;
148
+ toast: ToastLabels;
149
+ textInput: TextInputLabels;
150
+ modal: ModalLabels;
151
+ segmentedControl: SegmentedControlLabels;
152
+ selectSheet: SelectSheetLabels;
153
+ };
154
+ calendar: CalendarLabels;
155
+ header: HeaderLabels;
156
+ }
157
+
158
+ /** Deep partial — allows overriding any subset of labels */
159
+ export type DesignSystemLabelsOverride = {
160
+ [K in keyof DesignSystemLabels]?: {
161
+ [J in keyof DesignSystemLabels[K]]?: DesignSystemLabels[K][J] extends object
162
+ ? Partial<DesignSystemLabels[K][J]>
163
+ : DesignSystemLabels[K][J];
164
+ };
165
+ };
package/src/index.tsx ADDED
@@ -0,0 +1,215 @@
1
+ /**
2
+ * El Sendero Design System
3
+ *
4
+ * A complete, production-ready design system for React Native (Expo).
5
+ * Warm, calming aesthetic for anxiety companion app.
6
+ *
7
+ * ## Architecture
8
+ *
9
+ * ```
10
+ * design-system/
11
+ * ├── tokens/ - Design tokens (colors, spacing, typography, motion)
12
+ * ├── core/ - Low-level primitives (Box, Text, AnimatedBox, restyle)
13
+ * ├── primitives/ - Atomic, themed components (Button, Card, Input, etc.)
14
+ * ├── providers/ - Theme providers and contexts
15
+ * ├── hooks/ - Custom hooks (motion, accessibility)
16
+ * └── utils/ - Utility functions
17
+ * ```
18
+ *
19
+ * @example
20
+ * import {
21
+ * Button,
22
+ * Box,
23
+ * Text,
24
+ * Card,
25
+ * } from '@/design-system';
26
+ *
27
+ * function App() {
28
+ * return <MyApp />;
29
+ * }
30
+ */
31
+
32
+ // =============================================================================
33
+ // TOKENS
34
+ // =============================================================================
35
+
36
+ export {
37
+ // Colors
38
+ baseColors,
39
+ darkSemanticColors,
40
+ // Motion
41
+ duration,
42
+ easing,
43
+ // Shadows
44
+ elevation,
45
+ // Typography
46
+ fontFamily,
47
+ fontSize,
48
+ fontWeight,
49
+ hitSlop,
50
+ // Icons
51
+ iconSize,
52
+ letterSpacing,
53
+ lightSemanticColors,
54
+ lineHeight,
55
+ lineHeightValues,
56
+ opacity,
57
+ // Radii
58
+ radii,
59
+ semanticElevation,
60
+ semanticMotion,
61
+ semanticRadii,
62
+ semanticSpacing,
63
+ // Spacing
64
+ spacing,
65
+ springConfig,
66
+ touchTarget,
67
+ typographyPresets,
68
+ zIndex,
69
+ // Types
70
+ type BaseColors,
71
+ type Duration,
72
+ type DurationKey,
73
+ type Easing,
74
+ type EasingKey,
75
+ type Elevation,
76
+ type ElevationKey,
77
+ type FontFamily,
78
+ type FontSize,
79
+ type FontWeight,
80
+ type IconSize,
81
+ type IconSizeKey,
82
+ type Opacity,
83
+ type Radii,
84
+ type RadiiKey,
85
+ type SemanticColors,
86
+ type SemanticSpacing,
87
+ type Spacing,
88
+ type SpacingKey,
89
+ type SpringConfig,
90
+ type TypographyPresets,
91
+ type TypographyVariant,
92
+ type ZIndex,
93
+ } from "./tokens";
94
+
95
+ // =============================================================================
96
+ // SHARED TYPES
97
+ // =============================================================================
98
+
99
+ export type { MaterialIconName, RestyleColor, BaseThemeColor } from "./types";
100
+
101
+ // =============================================================================
102
+ // CORE PRIMITIVES
103
+ // =============================================================================
104
+
105
+ export {
106
+ restyleDarkTheme,
107
+ restyleLightTheme,
108
+ restyleTheme,
109
+ // Restyle
110
+ ThemeProvider,
111
+ useRestyleTheme,
112
+ // Theme building utilities
113
+ buildPair,
114
+ buildRestyleTheme,
115
+ buildRestyleThemeFromThemeColors,
116
+ restylePresetThemes,
117
+ type RestyleTheme,
118
+ type AppThemeColors,
119
+ type RestyleThemePair,
120
+ type SemanticColorsInput,
121
+ } from "./core";
122
+
123
+ // =============================================================================
124
+ // DESIGN SYSTEM PROVIDER
125
+ // =============================================================================
126
+
127
+ export {
128
+ DesignSystemProvider,
129
+ useDesignSystem,
130
+ } from "./provider";
131
+ export type { DesignSystemLanguage, DesignSystemProviderProps } from "./provider";
132
+ export type {
133
+ DesignSystemLabels,
134
+ DesignSystemLabelsOverride,
135
+ } from "./i18n/labels";
136
+ export { en, es } from "./i18n";
137
+
138
+ // =============================================================================
139
+ // PROVIDERS
140
+ // =============================================================================
141
+
142
+ export {
143
+ // Theme Factory
144
+ createTheme,
145
+ createThemePair,
146
+ // Built-in theme presets
147
+ darkTheme,
148
+ defaultTheme,
149
+ horizonTheme,
150
+ lavenderTheme,
151
+ lightTheme,
152
+ oceanTheme,
153
+ roseTheme,
154
+ sageTheme,
155
+ sunsetTheme,
156
+ type DeepPartial,
157
+ type ShadowStyle,
158
+ // Types
159
+ type Theme,
160
+ type ThemeColors,
161
+ type ThemeElevation,
162
+ type ThemeMode,
163
+ type ThemeMotion,
164
+ type ThemeOverrides,
165
+ type ThemeTypography,
166
+ type TypographyStyle,
167
+ } from "./providers";
168
+
169
+ // =============================================================================
170
+ // HOOKS
171
+ // =============================================================================
172
+
173
+ export {
174
+ useMotionSafeDuration,
175
+ useReducedMotion,
176
+ useAnimatedValue,
177
+ usePulseAnimation,
178
+ useEntranceAnimation,
179
+ type PulseAnimationConfig,
180
+ type EntranceAnimationConfig,
181
+ type EntranceAnimationResult,
182
+ } from "./hooks";
183
+
184
+ // =============================================================================
185
+ // UTILS
186
+ // =============================================================================
187
+
188
+ export {
189
+ // Accessibility
190
+ a11yRoles,
191
+ a11yState,
192
+ androidOnly,
193
+ buttonA11yProps,
194
+ checkboxA11yProps,
195
+ getContrastRatio,
196
+ getStatusBarHeight,
197
+ headingA11yProps,
198
+ imageA11yProps,
199
+ iosOnly,
200
+ isAndroid,
201
+ // Platform
202
+ isIOS,
203
+ meetsContrastAA,
204
+ meetsContrastAALarge,
205
+ MIN_TOUCH_TARGET,
206
+ platformSelect,
207
+ } from "./utils";
208
+
209
+ // =============================================================================
210
+ // COMPONENTS
211
+ // =============================================================================
212
+
213
+ export * from "./primitives";
214
+
215
+ export * from "./components";
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Button Component Helpers
3
+ *
4
+ * Pure functions for computing Button styles, sizes, and colors.
5
+ * All calculations are derived from the centralized scales.ts token file.
6
+ */
7
+
8
+ import { Insets } from "react-native";
9
+ import {
10
+ BUTTON_HEIGHTS,
11
+ BUTTON_ICON_SIZE,
12
+ BUTTON_TEXT_VARIANT,
13
+ calculateHitSlop,
14
+ SPINNER_SIZE,
15
+ } from "../../../tokens/scales";
16
+ import { BaseThemeColor, RestyleColor } from "../../../types";
17
+ import { IconSize } from "../../content/Icon";
18
+ import {
19
+ ButtonSize,
20
+ ButtonStyleResult,
21
+ ButtonTextVariant,
22
+ ButtonVariant,
23
+ ResolveButtonStyleParams,
24
+ } from "./Button.types";
25
+
26
+ // =============================================================================
27
+ // TEXT VARIANT RESOLUTION
28
+ // =============================================================================
29
+
30
+ /**
31
+ * Get text variant based on button size.
32
+ *
33
+ * Uses BUTTON_TEXT_VARIANT from scales.ts for consistency.
34
+ *
35
+ * | Button Size | Text Variant |
36
+ * |-------------|--------------|
37
+ * | sm | labelSmall |
38
+ * | md | labelMedium |
39
+ * | lg | labelLarge |
40
+ *
41
+ * @param size - The button size
42
+ * @returns The text variant for Text
43
+ */
44
+ export function getTextVariant(size: ButtonSize): ButtonTextVariant {
45
+ return BUTTON_TEXT_VARIANT[size];
46
+ }
47
+
48
+ // =============================================================================
49
+ // ICON SIZE RESOLUTION
50
+ // =============================================================================
51
+
52
+ /**
53
+ * Get icon size based on button size.
54
+ *
55
+ * Uses BUTTON_ICON_SIZE from scales.ts for consistency.
56
+ * Icons match label visual weight for optical balance.
57
+ *
58
+ * | Button Size | Icon Size |
59
+ * |-------------|-----------|
60
+ * | sm | sm (16px) |
61
+ * | md | md (20px) |
62
+ * | lg | lg (24px) |
63
+ *
64
+ * @param size - The button size
65
+ * @returns The icon size
66
+ */
67
+ export function getButtonIconSize(size: ButtonSize): IconSize {
68
+ return BUTTON_ICON_SIZE[size];
69
+ }
70
+
71
+ // =============================================================================
72
+ // TOUCH TARGET (hitSlop)
73
+ // =============================================================================
74
+
75
+ /**
76
+ * Get hitSlop based on button size.
77
+ *
78
+ * Uses calculateHitSlop from scales.ts to ensure
79
+ * all buttons meet the 44px minimum touch target.
80
+ *
81
+ * | Size | Height | hitSlop | Total Touch Target |
82
+ * |------|--------|---------|-------------------|
83
+ * | sm | 36px | 4px | 44px |
84
+ * | md | 44px | 0px | 44px |
85
+ * | lg | 52px | 0px | 52px |
86
+ *
87
+ * @param size - The button size variant
88
+ * @returns Insets for touch target expansion
89
+ */
90
+ export function getButtonHitSlop(size: ButtonSize): Insets {
91
+ return calculateHitSlop(BUTTON_HEIGHTS[size]);
92
+ }
93
+
94
+ // =============================================================================
95
+ // SPINNER SIZE RESOLUTION
96
+ // =============================================================================
97
+
98
+ /**
99
+ * Get spinner size based on button size.
100
+ *
101
+ * Uses SPINNER_SIZE from scales.ts for consistency across all components.
102
+ *
103
+ * | Button Size | Spinner Size |
104
+ * |-------------|--------------|
105
+ * | sm | sm |
106
+ * | md | sm |
107
+ * | lg | lg |
108
+ *
109
+ * @param size - The button size
110
+ * @returns The spinner size
111
+ */
112
+ export function getButtonSpinnerSize(size: ButtonSize): "sm" | "lg" {
113
+ return SPINNER_SIZE[size];
114
+ }
115
+
116
+ // =============================================================================
117
+ // COLOR RESOLUTION
118
+ // =============================================================================
119
+
120
+ /**
121
+ * Get text color based on variant and disabled state.
122
+ *
123
+ * | Variant | Normal | Disabled |
124
+ * |----------|--------------|--------------|
125
+ * | solid | textInverse | textDisabled |
126
+ * | outline | color prop | textDisabled |
127
+ * | ghost | color prop | textDisabled |
128
+ *
129
+ * Note: Disabled state uses textDisabled for accessibility.
130
+ * Opacity is also applied on the container for additional visual cue.
131
+ *
132
+ * @param variant - The visual variant
133
+ * @param color - The primary color prop
134
+ * @param disabled - Whether the button is disabled
135
+ * @returns The computed text color
136
+ */
137
+ export function getTextColor(
138
+ variant: ButtonVariant,
139
+ color: RestyleColor,
140
+ disabled: boolean = false,
141
+ ): RestyleColor {
142
+ if (disabled) {
143
+ return "textDisabled";
144
+ }
145
+
146
+ if (variant === "solid") {
147
+ return "textInverse";
148
+ }
149
+ return color;
150
+ }
151
+
152
+ /**
153
+ * Get icon color based on variant and disabled state.
154
+ *
155
+ * Follows the same logic as text color for visual consistency.
156
+ *
157
+ * @param variant - The visual variant
158
+ * @param color - The primary color prop
159
+ * @param disabled - Whether the button is disabled
160
+ * @returns The computed icon color
161
+ */
162
+ export function getButtonIconColor(
163
+ variant: ButtonVariant,
164
+ color: RestyleColor,
165
+ disabled: boolean = false,
166
+ ): RestyleColor {
167
+ // Icon uses same color logic as text
168
+ return getTextColor(variant, color, disabled);
169
+ }
170
+
171
+ /**
172
+ * Get spinner color based on variant and disabled state.
173
+ *
174
+ * Follows the same logic as text color for visual consistency.
175
+ *
176
+ * @param variant - The visual variant
177
+ * @param color - The primary color prop
178
+ * @param disabled - Whether the button is disabled
179
+ * @returns The computed spinner color
180
+ */
181
+ export function getButtonSpinnerColor(
182
+ variant: ButtonVariant,
183
+ color: RestyleColor,
184
+ disabled: boolean = false,
185
+ ): RestyleColor {
186
+ // Spinner uses same color logic as text
187
+ return getTextColor(variant, color, disabled);
188
+ }
189
+
190
+ // =============================================================================
191
+ // STYLE RESOLUTION
192
+ // =============================================================================
193
+
194
+ /**
195
+ * Resolve dynamic style properties for the Button container.
196
+ *
197
+ * Static styles (borderRadius, padding) come from theme variants.
198
+ * This function handles dynamic state-based values:
199
+ * - backgroundColor based on variant and disabled state
200
+ * - borderColor based on variant and disabled state
201
+ * - opacity based on disabled/loading state
202
+ *
203
+ * @param params - Resolution parameters
204
+ * @returns Computed style object
205
+ */
206
+ export function resolveButtonStyle(
207
+ params: ResolveButtonStyleParams,
208
+ ): ButtonStyleResult {
209
+ const { variant, disabled, isLoading, color, theme } = params;
210
+
211
+ const isDisabledOrLoading = disabled || isLoading;
212
+
213
+ let backgroundColor: string;
214
+ let borderColor: string;
215
+ let borderWidth: number;
216
+
217
+ switch (variant) {
218
+ case "solid":
219
+ backgroundColor = isDisabledOrLoading
220
+ ? theme.colors.interactiveDisabled
221
+ : theme.colors[color as BaseThemeColor];
222
+ borderColor = "transparent";
223
+ borderWidth = 0;
224
+ break;
225
+
226
+ case "outline":
227
+ backgroundColor = "transparent";
228
+ borderColor = isDisabledOrLoading
229
+ ? theme.colors.borderDefault
230
+ : theme.colors[color as BaseThemeColor];
231
+ borderWidth = 2;
232
+ break;
233
+
234
+ case "ghost":
235
+ default:
236
+ backgroundColor = "transparent";
237
+ borderColor = "transparent";
238
+ borderWidth = 0;
239
+ break;
240
+ }
241
+
242
+ return { backgroundColor, borderColor, borderWidth, opacity: 1 };
243
+ }