@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,234 @@
1
+ /**
2
+ * Chip Component Types
3
+ *
4
+ * Type definitions for the Chip component and its related hooks/helpers.
5
+ * All types are explicitly exported for external consumption.
6
+ */
7
+
8
+ import { BoxProps, ResponsiveValue, VariantProps } from "@shopify/restyle";
9
+ import { PressableProps, StyleProp, ViewStyle } from "react-native";
10
+ import { RestyleTheme } from "../../../core/restyle";
11
+ import { RestyleColor } from "../../../types";
12
+ import { IconName, IconSize } from "../Icon";
13
+
14
+ // =============================================================================
15
+ // VARIANT TYPES (Explicitly exported for external use)
16
+ // =============================================================================
17
+
18
+ /**
19
+ * Visual variant for the Chip component.
20
+ *
21
+ * - `filled`: Solid background with the specified color
22
+ * - `outlined`: Transparent background with a colored border
23
+ */
24
+ export type ChipVariant = Exclude<
25
+ keyof RestyleTheme["chipVariants"],
26
+ "defaults"
27
+ >;
28
+
29
+ /**
30
+ * Size preset for the Chip component.
31
+ *
32
+ * - `sm`: Small - compact lists, dense UIs
33
+ * - `md`: Medium - default size (32px height)
34
+ * - `lg`: Large - prominent tags, filter chips
35
+ */
36
+ export type ChipSize = Exclude<keyof RestyleTheme["chipSizes"], "defaults">;
37
+
38
+ /**
39
+ * Text variant type for chip labels.
40
+ */
41
+ export type ChipTextVariant = Exclude<keyof RestyleTheme["textVariants"], "defaults">;
42
+
43
+ // =============================================================================
44
+ // RESTYLE PROP TYPES
45
+ // =============================================================================
46
+
47
+ type ChipVariantProps = VariantProps<RestyleTheme, "chipVariants">;
48
+ type ChipSizeProps = VariantProps<RestyleTheme, "chipSizes", "size">;
49
+ type ChipRestyleProps = ChipVariantProps & ChipSizeProps & BoxProps<RestyleTheme>;
50
+
51
+ export type BaseChipProps = ChipRestyleProps & PressableProps;
52
+
53
+ // =============================================================================
54
+ // COMPONENT PROPS
55
+ // =============================================================================
56
+
57
+ /**
58
+ * Props for the Chip component.
59
+ *
60
+ * @example
61
+ * // Basic usage
62
+ * <Chip label="Tag" />
63
+ *
64
+ * @example
65
+ * // Selectable chip
66
+ * <Chip
67
+ * label="Option A"
68
+ * onPress={handleSelect}
69
+ * selected={isSelected}
70
+ * />
71
+ *
72
+ * @example
73
+ * // Dismissible chip with icon
74
+ * <Chip
75
+ * label="Filter"
76
+ * iconName="filter-list"
77
+ * onDelete={handleRemove}
78
+ * color="primary"
79
+ * />
80
+ */
81
+ export interface ChipProps extends Omit<BaseChipProps, "variant" | "style"> {
82
+ /** Chip label text */
83
+ label: string;
84
+ /** Visual variant of the chip (supports responsive values) */
85
+ variant?: ResponsiveValue<ChipVariant, RestyleTheme["breakpoints"]>;
86
+ /** Size of the chip (supports responsive values) */
87
+ size?: ResponsiveValue<ChipSize, RestyleTheme["breakpoints"]>;
88
+ /**
89
+ * Color for the chip. Accepts any theme color token.
90
+ * @default "accentPrimary"
91
+ */
92
+ color?: RestyleColor;
93
+ /** Whether the chip is selected */
94
+ selected?: boolean;
95
+ /** Whether the chip is disabled */
96
+ disabled?: boolean;
97
+ /** Press handler for selectable chips */
98
+ onPress?: () => void;
99
+ /** Delete handler for dismissible chips (shows close icon) */
100
+ onDelete?: () => void;
101
+ /** Optional leading icon name */
102
+ iconName?: IconName;
103
+ /** Test ID for testing */
104
+ testID?: string;
105
+ /** Accessibility label (required for screen readers) */
106
+ accessibilityLabel?: string;
107
+ /** Accessibility hint for additional context */
108
+ accessibilityHint?: string;
109
+ /** Custom style overrides */
110
+ style?: StyleProp<ViewStyle>;
111
+ }
112
+
113
+ // =============================================================================
114
+ // HOOK TYPES
115
+ // =============================================================================
116
+
117
+ /**
118
+ * Parameters for the useChipLogic hook.
119
+ */
120
+ export interface UseChipLogicParams {
121
+ label: string;
122
+ variant: ResponsiveValue<ChipVariant, RestyleTheme["breakpoints"]>;
123
+ size: ResponsiveValue<ChipSize, RestyleTheme["breakpoints"]>;
124
+ color: RestyleColor;
125
+ selected: boolean;
126
+ disabled: boolean;
127
+ onPress?: () => void;
128
+ onDelete?: () => void;
129
+ accessibilityLabel?: string;
130
+ accessibilityHint?: string;
131
+ }
132
+
133
+ /**
134
+ * Return value from the useChipLogic hook.
135
+ */
136
+ export interface UseChipLogicReturn {
137
+ /** Theme variant key for the base component */
138
+ themeVariantKey: "filled" | "outlined";
139
+ /** Text variant based on chip size */
140
+ textVariant: ChipTextVariant;
141
+ /** Text color based on variant and state */
142
+ textColor: RestyleColor;
143
+ /** Icon size based on chip size */
144
+ iconSize: IconSize;
145
+ /** Icon color based on variant and state */
146
+ iconColor: RestyleColor;
147
+ /** Container style with token keys for Restyle */
148
+ containerStyle: ChipStyleResult;
149
+ /** Accessibility props */
150
+ a11yProps: ChipA11yProps;
151
+ /** Whether the chip is interactive */
152
+ isInteractive: boolean;
153
+ /** Whether to show delete icon */
154
+ showDeleteIcon: boolean;
155
+ /** Delete icon size */
156
+ deleteIconSize: IconSize;
157
+ /** Delete icon color */
158
+ deleteIconColor: RestyleColor;
159
+ /** Accessibility hint for the delete/remove button */
160
+ deleteHint: string;
161
+ }
162
+
163
+ // =============================================================================
164
+ // ACCESSIBILITY TYPES
165
+ // =============================================================================
166
+
167
+ /**
168
+ * Parameters for the getChipA11y function.
169
+ */
170
+ export interface ChipA11yParams {
171
+ label: string;
172
+ accessibilityLabel?: string;
173
+ accessibilityHint?: string;
174
+ disabled: boolean;
175
+ selected: boolean;
176
+ isSelectable: boolean;
177
+ isDismissible: boolean;
178
+ toggleHint: string;
179
+ removeHint: string;
180
+ }
181
+
182
+ /**
183
+ * Accessibility props returned by getChipA11y.
184
+ */
185
+ export interface ChipA11yProps {
186
+ accessibilityRole: "button" | "checkbox";
187
+ accessibilityLabel: string;
188
+ accessibilityHint?: string;
189
+ accessibilityState: {
190
+ disabled: boolean;
191
+ selected?: boolean;
192
+ checked?: boolean;
193
+ };
194
+ }
195
+
196
+ // =============================================================================
197
+ // HELPER TYPES
198
+ // =============================================================================
199
+
200
+ /**
201
+ * Parameters for resolveChipStyle function.
202
+ * Note: theme is no longer needed as we return token keys instead of resolved values.
203
+ */
204
+ export interface ResolveChipStyleParams {
205
+ variant: ChipVariant;
206
+ color: RestyleColor;
207
+ selected: boolean;
208
+ disabled: boolean;
209
+ }
210
+
211
+ /**
212
+ * Result from resolveChipStyle function.
213
+ * Returns token keys instead of resolved hex values to let Restyle handle resolution.
214
+ */
215
+ export interface ChipStyleResult {
216
+ backgroundColor: RestyleColor | "transparent";
217
+ borderColor: RestyleColor | "transparent";
218
+ borderWidth: number;
219
+ opacity: number;
220
+ }
221
+
222
+ /**
223
+ * Color token mapping for chip colors.
224
+ */
225
+ export interface ChipColorTokens {
226
+ /** Background color for filled variant */
227
+ filled: RestyleColor;
228
+ /** Border/text color for outlined variant */
229
+ accent: RestyleColor;
230
+ /** Text color for filled variant */
231
+ filledText: RestyleColor;
232
+ /** Text color for outlined variant */
233
+ accentText: RestyleColor;
234
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Chip Component Module
3
+ *
4
+ * A compact element for tags, filters, and selections.
5
+ *
6
+ * Features:
7
+ * - Two variants: filled, outlined
8
+ * - Three sizes: sm, md, lg (supports responsive values)
9
+ * - Five color options: primary, secondary, success, warning, error
10
+ * - Optional leading icon
11
+ * - Selectable with visual feedback
12
+ * - Dismissible with close button
13
+ * - Full accessibility support
14
+ *
15
+ * @example
16
+ * import { Chip } from '@/src/design-system/primitives/content/Chip';
17
+ *
18
+ * // Basic tag
19
+ * <Chip label="JavaScript" />
20
+ *
21
+ * // Selectable chip
22
+ * <Chip
23
+ * label="Option A"
24
+ * onPress={() => setSelected(!selected)}
25
+ * selected={selected}
26
+ * variant="outlined"
27
+ * />
28
+ *
29
+ * // Dismissible chip
30
+ * <Chip
31
+ * label="Filter"
32
+ * onDelete={() => removeFilter()}
33
+ * iconName="filter-list"
34
+ * />
35
+ */
36
+
37
+ export { Chip } from "./Chip";
38
+
39
+ export type {
40
+ ChipProps,
41
+ ChipVariant,
42
+ ChipSize,
43
+ ChipA11yParams,
44
+ ChipA11yProps,
45
+ } from "./Chip.types";
46
+
47
+ export { getChipA11y } from "./Chip.a11y";
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Chip Logic Hook
3
+ *
4
+ * Extracts all computational logic from the Chip component.
5
+ * Returns memoized values for optimal render performance.
6
+ *
7
+ * Responsibilities:
8
+ * - Resolve responsive size prop
9
+ * - Calculate colors based on variant, color, and state
10
+ * - Compute icon sizes
11
+ * - Generate container styles (token keys for Restyle)
12
+ * - Provide accessibility props
13
+ *
14
+ * @see Chip.tsx - Component consuming this hook
15
+ * @see Chip.helpers.ts - Pure calculation functions
16
+ */
17
+
18
+ import { useDesignSystem } from "../../../provider";
19
+ import { useResponsiveProp } from "@shopify/restyle";
20
+ import { useMemo } from "react";
21
+ import { getChipA11y } from "./Chip.a11y";
22
+ import {
23
+ getChipIconColor,
24
+ getChipIconSize,
25
+ getChipTextColor,
26
+ getChipTextVariant,
27
+ getThemeVariantKey,
28
+ resolveChipStyle,
29
+ } from "./Chip.helpers";
30
+ import { ChipSize, ChipStyleResult, ChipVariant, UseChipLogicParams, UseChipLogicReturn } from "./Chip.types";
31
+
32
+ /**
33
+ * Orchestrates Chip rendering logic and state management.
34
+ *
35
+ * Handles:
36
+ * - Responsive size and variant resolution
37
+ * - Theme variant key mapping for Restyle
38
+ * - Text variant and color calculation
39
+ * - Icon size and color determination
40
+ * - Container style computation (background, border, opacity)
41
+ * - Interactive state detection (press/delete handlers)
42
+ * - Delete icon visibility and styling
43
+ * - Accessibility props with selection/dismissible states
44
+ *
45
+ * @param params - Configuration object for chip behavior
46
+ * @param params.label - Chip label text
47
+ * @param params.variant - Visual variant ('filled' | 'outlined')
48
+ * @param params.size - Size variant ('sm' | 'md' | 'lg')
49
+ * @param params.color - Theme color token
50
+ * @param params.selected - Whether chip is selected
51
+ * @param params.disabled - Whether chip is disabled
52
+ * @param params.onPress - Optional press handler (makes chip selectable)
53
+ * @param params.onDelete - Optional delete handler (shows X icon)
54
+ * @param params.accessibilityLabel - Custom a11y label
55
+ * @param params.accessibilityHint - Describes action result
56
+ *
57
+ * @returns Computed values for rendering Chip
58
+ * @returns {string} themeVariantKey - Restyle theme variant identifier
59
+ * @returns {string} textVariant - Text component variant
60
+ * @returns {string} textColor - Text color token
61
+ * @returns {number} iconSize - Icon size in pixels
62
+ * @returns {string} iconColor - Icon color token
63
+ * @returns {ChipStyleResult} containerStyle - Container style tokens
64
+ * @returns {object} a11yProps - Accessibility props
65
+ * @returns {boolean} isInteractive - Whether chip responds to press
66
+ * @returns {boolean} showDeleteIcon - Whether to show delete icon
67
+ * @returns {number} deleteIconSize - Delete icon size in pixels
68
+ * @returns {string} deleteIconColor - Delete icon color token
69
+ *
70
+ * @performance This hook uses useMemo() for expensive calculations
71
+ *
72
+ * @example
73
+ * const {
74
+ * themeVariantKey,
75
+ * textColor,
76
+ * iconSize,
77
+ * containerStyle,
78
+ * showDeleteIcon,
79
+ * a11yProps
80
+ * } = useChipLogic({
81
+ * label: "React",
82
+ * variant: "filled",
83
+ * size: "md",
84
+ * color: "primary",
85
+ * selected: true,
86
+ * onDelete: () => removeTag("react"),
87
+ * });
88
+ */
89
+ export function useChipLogic(params: UseChipLogicParams): UseChipLogicReturn {
90
+ const {
91
+ label,
92
+ variant,
93
+ size,
94
+ color,
95
+ selected,
96
+ disabled,
97
+ onPress,
98
+ onDelete,
99
+ accessibilityLabel,
100
+ accessibilityHint,
101
+ } = params;
102
+
103
+ const { labels: t } = useDesignSystem();
104
+
105
+ const resolvedSize = (useResponsiveProp(size) ?? "md") as ChipSize;
106
+ const resolvedVariant = (useResponsiveProp(variant) ?? "filled") as ChipVariant;
107
+
108
+ // Theme variant key for the base component
109
+ const themeVariantKey = getThemeVariantKey(resolvedVariant);
110
+
111
+ // Text styling
112
+ const textVariant = getChipTextVariant(resolvedSize);
113
+ const textColor = getChipTextColor(resolvedVariant, color, selected, disabled);
114
+
115
+ // Icon styling
116
+ const iconSize = getChipIconSize(resolvedSize);
117
+ const iconColor = getChipIconColor(resolvedVariant, color, selected, disabled);
118
+
119
+ // Interaction states
120
+ const isInteractive = !!onPress || !!onDelete;
121
+ const showDeleteIcon = !!onDelete;
122
+
123
+ // Delete icon uses same size and color as leading icon
124
+ const deleteIconSize = iconSize;
125
+ const deleteIconColor = iconColor;
126
+ const deleteHint = t.designSystem.chip.removeHint;
127
+
128
+ // Container style - returns token keys for Restyle to handle
129
+ const containerStyle: ChipStyleResult = resolveChipStyle({
130
+ variant: resolvedVariant,
131
+ color,
132
+ selected,
133
+ disabled,
134
+ });
135
+
136
+ // Accessibility props
137
+ const a11yProps = useMemo(
138
+ () =>
139
+ getChipA11y({
140
+ label,
141
+ accessibilityLabel,
142
+ accessibilityHint,
143
+ disabled,
144
+ selected,
145
+ isSelectable: !!onPress && !onDelete,
146
+ isDismissible: !!onDelete,
147
+ toggleHint: t.designSystem.chip.toggleHint,
148
+ removeHint: t.designSystem.chip.removeHint,
149
+ }),
150
+ [label, accessibilityLabel, accessibilityHint, disabled, selected, onPress, onDelete, t]
151
+ );
152
+
153
+ return {
154
+ themeVariantKey,
155
+ textVariant,
156
+ textColor,
157
+ iconSize,
158
+ iconColor,
159
+ containerStyle,
160
+ a11yProps,
161
+ isInteractive,
162
+ showDeleteIcon,
163
+ deleteIconSize,
164
+ deleteIconColor,
165
+ deleteHint,
166
+ };
167
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Icon Component Helpers
3
+ *
4
+ * Pure functions for resolving icon sizes and colors from the theme.
5
+ *
6
+ * ## Size Scale Reference
7
+ * | Size | Pixels | Use Case |
8
+ * |------|--------|----------|
9
+ * | xs | 12px | Badges, status dots |
10
+ * | sm | 16px | Compact buttons, dense lists |
11
+ * | md | 20px | Default, standard buttons |
12
+ * | lg | 24px | Primary actions, headers |
13
+ * | xl | 32px | Tablet headers, emphasized |
14
+ * | 2xl | 40px | Empty states, onboarding |
15
+ * | 3xl | 48px | Hero sections |
16
+ *
17
+ * @see tokens/index.ts - iconSize token definitions
18
+ */
19
+
20
+ import { RestyleTheme } from "../../../core/restyle";
21
+ import { BaseThemeColor, RestyleColor } from "../../../types";
22
+ import { ResolveIconSizeParams } from "./Icon.types";
23
+
24
+ /**
25
+ * Resolve icon size to pixel value from theme.
26
+ *
27
+ * @param params - Contains resolvedSize and theme
28
+ * @returns The icon size in pixels
29
+ *
30
+ * @example
31
+ * resolveIconSizeValue({ resolvedSize: "lg", theme }) // 24
32
+ */
33
+ export function resolveIconSizeValue(params: ResolveIconSizeParams): number {
34
+ const { resolvedSize, theme } = params;
35
+ const sizeConfig = theme.iconSizes[resolvedSize];
36
+ return sizeConfig.width || sizeConfig.height;
37
+ }
38
+
39
+ /**
40
+ * Resolve icon color token to hex value from theme.
41
+ *
42
+ * @param color - Theme color token (e.g., "textPrimary", "accentPrimary")
43
+ * @param theme - Current Restyle theme
44
+ * @returns The resolved hex color string
45
+ *
46
+ * @example
47
+ * resolveIconColor("accentPrimary", theme) // "#A68B6A"
48
+ */
49
+ export function resolveIconColor(
50
+ color: RestyleColor,
51
+ theme: RestyleTheme,
52
+ ): string {
53
+ return theme.colors[color as BaseThemeColor];
54
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Icon Component
3
+ *
4
+ * @description Renders Material Icons with theme integration - Atom
5
+ *
6
+ * Icons are the most fundamental visual element in the design system.
7
+ * This component wraps @expo/vector-icons/MaterialIcons with Restyle
8
+ * theming for consistent sizing and coloring across the app.
9
+ *
10
+ * ## Size Scale
11
+ * | Size | Pixels | Use Case |
12
+ * |------|--------|----------|
13
+ * | xs | 12px | Badges, status dots |
14
+ * | sm | 16px | Compact buttons, dense lists |
15
+ * | md | 20px | Default, standard buttons |
16
+ * | lg | 24px | Primary actions, headers |
17
+ * | xl | 32px | Tablet headers, emphasized |
18
+ * | 2xl | 40px | Empty states, onboarding |
19
+ * | 3xl | 48px | Hero sections |
20
+ *
21
+ * ## Features
22
+ * - Responsive size prop (phone/tablet breakpoints)
23
+ * - Theme-aware color tokens
24
+ * - Full accessibility support
25
+ * - Memoized for performance
26
+ *
27
+ * @see Icon.types.ts - Type definitions
28
+ * @see Icon.helpers.ts - Size/color resolution functions
29
+ * @see Icon.a11y.ts - Accessibility prop generation
30
+ *
31
+ * @example
32
+ * // Basic usage
33
+ * <Icon name="home" />
34
+ *
35
+ * @example
36
+ * // With size and color
37
+ * <Icon name="settings" size="lg" color="accentPrimary" />
38
+ *
39
+ * @example
40
+ * // Responsive with accessibility
41
+ * <Icon
42
+ * name="check"
43
+ * size={{ phone: "md", tablet: "lg" }}
44
+ * accessibilityLabel="Checkmark"
45
+ * />
46
+ */
47
+
48
+ import MaterialIcons from "@expo/vector-icons/MaterialIcons";
49
+ import {
50
+ createRestyleComponent,
51
+ createVariant,
52
+ layout,
53
+ spacing,
54
+ spacingShorthand,
55
+ } from "@shopify/restyle";
56
+ import React, { memo } from "react";
57
+ import { RestyleTheme } from "../../../core/restyle";
58
+ import { Box } from "../../layout";
59
+ import { BaseIconContainerProps, IconProps } from "./Icon.types";
60
+ import { useIconLogic } from "./useIconLogic";
61
+
62
+ /**
63
+ * Base container with Restyle variant support for icon sizing.
64
+ * @internal
65
+ */
66
+ const BaseIconContainer = createRestyleComponent<
67
+ BaseIconContainerProps,
68
+ RestyleTheme
69
+ >(
70
+ [
71
+ createVariant({ themeKey: "iconSizes", property: "size" }),
72
+ layout,
73
+ spacing,
74
+ spacingShorthand,
75
+ ],
76
+ Box,
77
+ );
78
+
79
+ function IconComponent({
80
+ name,
81
+ color = "textPrimary",
82
+ size = "md",
83
+ iconStyle,
84
+ testID,
85
+ accessibilityLabel,
86
+ accessibilityHint,
87
+ ...rest
88
+ }: IconProps) {
89
+ const { iconSizeValue, iconColor, a11yProps } = useIconLogic({
90
+ color,
91
+ size,
92
+ accessibilityLabel,
93
+ accessibilityHint,
94
+ });
95
+
96
+ return (
97
+ <BaseIconContainer {...a11yProps} {...rest}>
98
+ <MaterialIcons
99
+ name={name}
100
+ size={iconSizeValue}
101
+ color={iconColor}
102
+ style={iconStyle}
103
+ testID={testID}
104
+ />
105
+ </BaseIconContainer>
106
+ );
107
+ }
108
+
109
+ export const Icon = memo(IconComponent);
110
+ Icon.displayName = "Icon";
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Icon Component Types
3
+ *
4
+ * Type definitions for the Icon component and its related hooks/helpers.
5
+ *
6
+ * @see Icon.tsx - Component implementation
7
+ */
8
+
9
+ import MaterialIcons from "@expo/vector-icons/MaterialIcons";
10
+ import { BoxProps, ResponsiveValue, VariantProps } from "@shopify/restyle";
11
+ import { AccessibilityRole, ViewProps } from "react-native";
12
+ import { RestyleTheme } from "../../../core/restyle";
13
+ import { RestyleColor } from "../../../types";
14
+
15
+ type IconSizeVariantProps = VariantProps<RestyleTheme, "iconSizes", "size">;
16
+ type IconRestyleProps = IconSizeVariantProps & BoxProps<RestyleTheme>;
17
+
18
+ /** All available Material Icon names from @expo/vector-icons */
19
+ export type IconName = keyof typeof MaterialIcons.glyphMap;
20
+
21
+ /** Size variants: xs | sm | md | lg | xl | 2xl | 3xl */
22
+ export type IconSize = Exclude<keyof RestyleTheme["iconSizes"], "defaults">;
23
+
24
+
25
+ /** @internal Base container props for Restyle integration */
26
+ export type BaseIconContainerProps = IconRestyleProps & ViewProps;
27
+
28
+ /**
29
+ * Props for the Icon component.
30
+ *
31
+ * @example
32
+ * <Icon name="home" size="lg" color="accentPrimary" />
33
+ */
34
+ export interface IconProps extends Omit<IconRestyleProps, "size"> {
35
+ /** Material Icon name (e.g., "home", "settings", "check") */
36
+ name: IconName;
37
+
38
+ /**
39
+ * Size of the icon (supports responsive values).
40
+ * @default "md"
41
+ */
42
+ size?: ResponsiveValue<IconSize, RestyleTheme["breakpoints"]>;
43
+
44
+ /**
45
+ * Icon color from theme palette.
46
+ * @default "textPrimary"
47
+ */
48
+ color?: RestyleColor;
49
+
50
+ /** Custom styles applied directly to the MaterialIcons component */
51
+ iconStyle?: React.ComponentProps<typeof MaterialIcons>["style"];
52
+
53
+ /** Test ID for testing frameworks */
54
+ testID?: string;
55
+
56
+ /**
57
+ * Accessibility label for screen readers.
58
+ * @warning Logs console warning in dev if missing
59
+ */
60
+ accessibilityLabel?: string;
61
+
62
+ /** Additional context for screen readers */
63
+ accessibilityHint?: string;
64
+ }
65
+
66
+ export interface UseIconLogicParams {
67
+ color: RestyleColor;
68
+ size: ResponsiveValue<IconSize, RestyleTheme["breakpoints"]>;
69
+ accessibilityLabel?: string;
70
+ accessibilityHint?: string;
71
+ }
72
+
73
+ export interface UseIconLogicReturn {
74
+ iconSizeValue: number;
75
+ iconColor: string;
76
+ a11yProps: IconA11yProps;
77
+ }
78
+
79
+ export interface IconA11yParams {
80
+ /** Text alternative for screen readers */
81
+ accessibilityLabel?: string;
82
+ /** Additional context about the icon's purpose */
83
+ accessibilityHint?: string;
84
+ }
85
+
86
+ export interface IconA11yProps {
87
+ accessibilityRole: AccessibilityRole;
88
+ accessibilityLabel?: string;
89
+ accessibilityHint?: string;
90
+ }
91
+
92
+ export interface ResolveIconSizeParams {
93
+ resolvedSize: IconSize;
94
+ theme: RestyleTheme;
95
+ }