@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,131 @@
1
+ /**
2
+ * EmptyState Logic Hook
3
+ *
4
+ * Extracts all computational logic from the EmptyState component.
5
+ * Returns memoized values for optimal render performance.
6
+ *
7
+ * Responsibilities:
8
+ * - Resolve responsive variant prop
9
+ * - Calculate styling configuration based on variant
10
+ * - Determine visibility of optional elements
11
+ * - Provide accessibility props
12
+ *
13
+ * @see EmptyState.tsx - Component consuming this hook
14
+ * @see EmptyState.helpers.ts - Pure calculation functions
15
+ */
16
+
17
+ import { useResponsiveProp } from "@shopify/restyle";
18
+ import { useMemo } from "react";
19
+ import { getEmptyStateA11y } from "./EmptyState.a11y";
20
+ import { getEmptyStateConfig } from "./EmptyState.helpers";
21
+ import { EmptyStateVariant, UseEmptyStateLogicParams, UseEmptyStateLogicReturn } from "./EmptyState.types";
22
+
23
+ /**
24
+ * Orchestrates EmptyState rendering logic and state management.
25
+ *
26
+ * Handles:
27
+ * - Responsive variant resolution
28
+ * - Configuration lookup (icon size, text variants, spacing)
29
+ * - Icon resolution (custom or type-based defaults)
30
+ * - Color determination based on type (error vs default)
31
+ * - Element visibility flags (icon, actions)
32
+ * - Accessibility props generation
33
+ *
34
+ * @param params - Configuration object for empty state behavior
35
+ * @param params.type - Semantic type ('default' | 'error')
36
+ * @param params.variant - Size variant ('default' | 'compact')
37
+ * @param params.iconName - Optional custom icon
38
+ * @param params.title - Title text
39
+ * @param params.description - Description text
40
+ * @param params.actionLabel - Primary action button label
41
+ * @param params.secondaryActionLabel - Secondary action button label
42
+ * @param params.accessibilityLabel - Custom a11y label
43
+ *
44
+ * @returns Computed values for rendering EmptyState
45
+ * @returns {number} iconSize - Icon size in pixels
46
+ * @returns {string} iconColor - Icon color token
47
+ * @returns {string} titleColor - Title color token
48
+ * @returns {string} titleVariant - Title text variant
49
+ * @returns {string} descriptionVariant - Description text variant
50
+ * @returns {number} containerPadding - Container padding in pixels
51
+ * @returns {number} contentGap - Gap between elements in pixels
52
+ * @returns {object} a11yProps - Accessibility props
53
+ * @returns {boolean} showIcon - Whether to show icon
54
+ * @returns {boolean} showAction - Whether to show primary action
55
+ * @returns {boolean} showSecondaryAction - Whether to show secondary action
56
+ * @returns {string} resolvedIconName - Resolved icon name
57
+ *
58
+ * @performance This hook uses useMemo() for configuration lookups
59
+ *
60
+ * @example
61
+ * const {
62
+ * iconSize,
63
+ * iconColor,
64
+ * titleVariant,
65
+ * showIcon,
66
+ * showAction,
67
+ * resolvedIconName,
68
+ * } = useEmptyStateLogic({
69
+ * variant: "default",
70
+ * iconName: "inbox",
71
+ * title: "No messages",
72
+ * description: "Your inbox is empty",
73
+ * actionLabel: "Compose",
74
+ * secondaryActionLabel: "Learn more",
75
+ * });
76
+ */
77
+ export function useEmptyStateLogic({
78
+ type,
79
+ variant,
80
+ iconName,
81
+ title,
82
+ description,
83
+ actionLabel,
84
+ secondaryActionLabel,
85
+ accessibilityLabel,
86
+ }: UseEmptyStateLogicParams): UseEmptyStateLogicReturn {
87
+ // Resolve responsive variant
88
+ const resolvedVariant = (useResponsiveProp(variant) ?? "default") as EmptyStateVariant;
89
+
90
+ // Get variant configuration
91
+ const config = getEmptyStateConfig(resolvedVariant);
92
+
93
+ // Determine icon based on type if not provided
94
+ const resolvedIconName = iconName || (type === "error" ? "error" : "inbox");
95
+
96
+ // Determine colors based on type
97
+ const iconColor = type === "error" ? "feedbackError" : "textSecondary";
98
+
99
+ const titleColor = type === "error" ? "feedbackError" : "textPrimary";
100
+
101
+ // Determine element visibility
102
+ const showIcon = resolvedIconName !== undefined;
103
+ const showAction = actionLabel !== undefined;
104
+ const showSecondaryAction = secondaryActionLabel !== undefined;
105
+
106
+ // Accessibility props
107
+ const a11yProps = useMemo(
108
+ () =>
109
+ getEmptyStateA11y({
110
+ title,
111
+ description,
112
+ accessibilityLabel,
113
+ }),
114
+ [title, description, accessibilityLabel]
115
+ );
116
+
117
+ return {
118
+ iconSize: config.iconSize,
119
+ iconColor,
120
+ titleColor,
121
+ titleVariant: config.titleVariant,
122
+ descriptionVariant: config.descriptionVariant,
123
+ containerPadding: config.containerPadding,
124
+ contentGap: config.contentGap,
125
+ a11yProps,
126
+ showIcon,
127
+ showAction,
128
+ showSecondaryAction,
129
+ resolvedIconName,
130
+ };
131
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Header Component Helpers
3
+ *
4
+ * Pure functions for computing Header dimensions, sizes, and mappings.
5
+ *
6
+ * ## Size Configuration
7
+ * | Header Size | Height | Text Variant | IconButton |
8
+ * |-------------|--------|---------------|------------|
9
+ * | sm | 44px | headingSmall | sm (36px) |
10
+ * | md | 56px | headingMedium | md (44px) |
11
+ * | lg | 64px | headingLarge | lg (56px) |
12
+ *
13
+ * ## Safe Area Calculation
14
+ * Total height = base height + safe area top inset (when enabled)
15
+ */
16
+
17
+ import { ResponsiveValue } from "@shopify/restyle";
18
+ import { ViewStyle } from "react-native";
19
+ import { RestyleTheme } from "../../core/restyle";
20
+ import { IconButtonSize } from "../../primitives/actions/IconButton";
21
+ import {
22
+ HeaderDimensionsResult,
23
+ HeaderSize,
24
+ HeaderTextVariant,
25
+ ResolveHeaderDimensionsParams,
26
+ } from "./Header.types";
27
+
28
+ /**
29
+ * Maps header size to text variant.
30
+ */
31
+ export const SIZE_TO_TEXT_VARIANT: Record<HeaderSize, HeaderTextVariant> = {
32
+ sm: "headingSmall",
33
+ md: "headingMedium",
34
+ lg: "headingLarge",
35
+ } as const;
36
+
37
+ /**
38
+ * Maps Header size to IconButton size for proper visual alignment.
39
+ *
40
+ * | Header | IconButton | Ratio |
41
+ * |--------|------------|-------|
42
+ * | sm 44px| sm 36px | 82% |
43
+ * | md 56px| md 44px | 79% |
44
+ * | lg 64px| lg 56px | 87% |
45
+ *
46
+ * @param headerSize - Header size (supports responsive values)
47
+ * @returns Corresponding IconButton size
48
+ */
49
+ export function getHeaderIconButtonSize(
50
+ headerSize: ResponsiveValue<HeaderSize, RestyleTheme["breakpoints"]>,
51
+ ): ResponsiveValue<IconButtonSize, RestyleTheme["breakpoints"]> {
52
+ // If responsive, map each breakpoint
53
+ if (typeof headerSize === "object") {
54
+ return {
55
+ phone:
56
+ headerSize.phone === "sm"
57
+ ? "sm"
58
+ : headerSize.phone === "lg"
59
+ ? "lg"
60
+ : "md",
61
+ tablet:
62
+ headerSize.tablet === "sm"
63
+ ? "sm"
64
+ : headerSize.tablet === "lg"
65
+ ? "lg"
66
+ : "md",
67
+ };
68
+ }
69
+ // If single value, map directly
70
+ return headerSize === "sm" ? "sm" : headerSize === "lg" ? "lg" : "md";
71
+ }
72
+
73
+ export const BACK_BUTTON_HIT_SLOP = {
74
+ top: 8,
75
+ bottom: 8,
76
+ left: 8,
77
+ right: 8,
78
+ } as const;
79
+
80
+ export function resolveHeaderDimensions(
81
+ params: ResolveHeaderDimensionsParams,
82
+ ): HeaderDimensionsResult {
83
+ const { resolvedSize, safeAreaTop, topInset, theme } = params;
84
+ const { height } = theme.headerSizes[resolvedSize];
85
+ const topPadding = safeAreaTop ? topInset : 0;
86
+ const totalHeight = height + topPadding;
87
+
88
+ return { topPadding, totalHeight };
89
+ }
90
+
91
+ export function resolveContainerStyle(topPadding: number): ViewStyle {
92
+ return { paddingTop: topPadding };
93
+ }
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Header Component
3
+ *
4
+ * @description Navigation header with title and actions - Organism
5
+ *
6
+ * Header is a complex component combining multiple atoms and molecules
7
+ * into a complete navigation bar with back button, title, and actions.
8
+ *
9
+ * ## Size Scale
10
+ * | Size | Height | Text Variant | IconButton |
11
+ * |------|--------|--------------|------------|
12
+ * | sm | 44px | headingSmall | sm (36px) |
13
+ * | md | 56px | headingMedium| md (44px) |
14
+ * | lg | 64px | headingLarge | lg (56px) |
15
+ *
16
+ * ## Safe Area Handling
17
+ * When `safeAreaTop={true}` (default), the header adds top padding
18
+ * for the device safe area (notch/status bar). Total height = size + insets.top.
19
+ *
20
+ * ## Back Button Behavior
21
+ * - Shows when `showBackButton={true}` AND `onBackPress` is provided
22
+ * - Calls `onBackPress` when pressed
23
+ * - Accessibility labels from i18n translations
24
+ *
25
+ * ## Features
26
+ * - Responsive size prop (phone/tablet breakpoints)
27
+ * - Optional back button with smart visibility
28
+ * - Custom left/right items for actions
29
+ * - Safe area aware (status bar + notch)
30
+ * - Full accessibility support (header role)
31
+ *
32
+ * @performance
33
+ * - Wrapped with React.memo() to prevent unnecessary re-renders
34
+ * - Uses useMemo() for dimension calculations with safe area insets
35
+ * - Back button visibility computed once per canGoBack() change
36
+ * - Container styles cached to avoid style object recreation
37
+ * - Integrates with expo-router for efficient navigation state
38
+ *
39
+ * @see Header.types.ts - Type definitions
40
+ * @see Header.helpers.ts - Size and dimension functions
41
+ * @see Header.a11y.ts - Accessibility prop generation
42
+ *
43
+ * @example
44
+ * // Basic usage
45
+ * <Header title="Settings" />
46
+ *
47
+ * @example
48
+ * // With actions
49
+ * <Header
50
+ * title="Profile"
51
+ * size={{ phone: "md", tablet: "lg" }}
52
+ * rightItems={
53
+ * <HeaderRightItems>
54
+ * <IconButton iconName="edit" onPress={handleEdit} accessibilityLabel="Edit" />
55
+ * </HeaderRightItems>
56
+ * }
57
+ * />
58
+ *
59
+ * @example
60
+ * // Custom back handler
61
+ * <Header
62
+ * title="Checkout"
63
+ * onBackPress={handleConfirmCancel}
64
+ * accessibilityLabel="Checkout header"
65
+ * />
66
+ */
67
+
68
+ import { RestyleTheme } from "../../core/restyle";
69
+ import { Box, IconButton, Text } from "../../primitives";
70
+ import {
71
+ backgroundColor,
72
+ border,
73
+ createRestyleComponent,
74
+ createVariant,
75
+ layout,
76
+ opacity,
77
+ spacing,
78
+ spacingShorthand,
79
+ } from "@shopify/restyle";
80
+ import React, { memo } from "react";
81
+ import { getHeaderIconButtonSize } from "./Header.helpers";
82
+ import {
83
+ BaseHeaderContainerProps,
84
+ HeaderProps,
85
+ HeaderRightItemsProps,
86
+ } from "./Header.types";
87
+ import { useHeaderLogic } from "./useHeaderLogic";
88
+
89
+ /**
90
+ * Base container with Restyle variant support.
91
+ * @internal
92
+ */
93
+ const BaseHeaderContainer = createRestyleComponent<
94
+ BaseHeaderContainerProps,
95
+ RestyleTheme
96
+ >(
97
+ [
98
+ createVariant({ themeKey: "headerVariants" }),
99
+ createVariant({ themeKey: "headerSizes", property: "size" }),
100
+ backgroundColor,
101
+ border,
102
+ layout,
103
+ opacity,
104
+ spacing,
105
+ spacingShorthand,
106
+ ],
107
+ Box,
108
+ );
109
+
110
+ function HeaderComponent({
111
+ title,
112
+ accessibilityLabel,
113
+ accessibilityHint,
114
+ size = "md",
115
+ variant,
116
+ showBackButton = true,
117
+ rightItems,
118
+ leftItems,
119
+ safeAreaTop = true,
120
+ onBackPress,
121
+ testID,
122
+ ...rest
123
+ }: HeaderProps) {
124
+ const {
125
+ showBack,
126
+ textVariant,
127
+ dimensions,
128
+ containerStyle,
129
+ backButtonA11yProps,
130
+ a11yContainerProps,
131
+ handleBack,
132
+ } = useHeaderLogic({
133
+ accessibilityLabel,
134
+ accessibilityHint,
135
+ size,
136
+ showBackButton,
137
+ safeAreaTop,
138
+ onBackPress,
139
+ });
140
+
141
+ return (
142
+ <BaseHeaderContainer
143
+ height={dimensions.totalHeight}
144
+ variant={variant}
145
+ style={containerStyle}
146
+ testID={testID}
147
+ {...a11yContainerProps}
148
+ {...rest}
149
+ >
150
+ {showBack && (
151
+ <IconButton
152
+ iconName="arrow-back"
153
+ onPress={handleBack}
154
+ variant="ghost"
155
+ size={getHeaderIconButtonSize(size)}
156
+ accessibilityLabel={
157
+ backButtonA11yProps.accessibilityLabel ?? "Go back"
158
+ }
159
+ accessibilityHint={backButtonA11yProps.accessibilityHint}
160
+ />
161
+ )}
162
+ {leftItems}
163
+ {title && (
164
+ <Text flex={1} numberOfLines={1} variant={textVariant}>
165
+ {title}
166
+ </Text>
167
+ )}
168
+ {rightItems}
169
+ </BaseHeaderContainer>
170
+ );
171
+ }
172
+
173
+ function HeaderRightItemsComponent({ children }: HeaderRightItemsProps) {
174
+ return (
175
+ <Box flexDirection="row" alignItems="center" gap="xs">
176
+ {children}
177
+ </Box>
178
+ );
179
+ }
180
+
181
+ export const Header = memo(HeaderComponent);
182
+ Header.displayName = "Header";
183
+
184
+ export const HeaderRightItems = memo(HeaderRightItemsComponent);
185
+ HeaderRightItems.displayName = "HeaderRightItems";
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Header Component Types
3
+ *
4
+ * Type definitions for the Header component and its related hooks/helpers.
5
+ *
6
+ * @see Header.tsx - Component implementation
7
+ */
8
+
9
+ import { BoxProps, ResponsiveValue, VariantProps } from "@shopify/restyle";
10
+ import { ReactNode } from "react";
11
+ import { AccessibilityRole, ViewProps, ViewStyle } from "react-native";
12
+ import { RestyleTheme } from "../../core/restyle";
13
+
14
+ type HeaderVariantProps = VariantProps<
15
+ RestyleTheme,
16
+ "headerVariants",
17
+ "variant"
18
+ >;
19
+ type HeaderSizeProps = VariantProps<RestyleTheme, "headerSizes", "size">;
20
+ type HeaderRestyleProps = HeaderVariantProps &
21
+ HeaderSizeProps &
22
+ BoxProps<RestyleTheme>;
23
+
24
+ /**
25
+ * Size variants for the Header.
26
+ *
27
+ * | Size | Height | Text Variant | Use Case |
28
+ * |------|--------|---------------|----------|
29
+ * | sm | 44px | headingSmall | Compact screens |
30
+ * | md | 56px | headingMedium | Default mobile |
31
+ * | lg | 64px | headingLarge | Tablets, emphasis |
32
+ */
33
+ export type HeaderSize = Exclude<
34
+ keyof RestyleTheme["headerSizes"],
35
+ "defaults"
36
+ >;
37
+
38
+ /** Visual variants derived from theme headerVariants */
39
+ export type HeaderVariant = Exclude<
40
+ keyof RestyleTheme["headerVariants"],
41
+ "defaults"
42
+ >;
43
+
44
+ /** @internal Base container props for Restyle integration */
45
+ export type BaseHeaderContainerProps = HeaderRestyleProps & ViewProps;
46
+
47
+ /**
48
+ * Props for the Header component.
49
+ *
50
+ * @example
51
+ * <Header
52
+ * title="Settings"
53
+ * size="md"
54
+ * showBackButton
55
+ * rightItems={<IconButton iconName="more-vert" onPress={handleMore} accessibilityLabel="More" />}
56
+ * />
57
+ */
58
+ export interface HeaderProps extends Omit<HeaderRestyleProps, "size"> {
59
+ /** Title text displayed in header */
60
+ title?: string;
61
+
62
+ /**
63
+ * Size of the header (supports responsive values).
64
+ * @default "md"
65
+ */
66
+ size?: ResponsiveValue<HeaderSize, RestyleTheme["breakpoints"]>;
67
+
68
+ /** Accessibility label for the header container */
69
+ accessibilityLabel?: string;
70
+
71
+ /** Accessibility hint for additional context */
72
+ accessibilityHint?: string;
73
+
74
+ /**
75
+ * Whether to show back button (only shows when `onBackPress` is also provided).
76
+ * @default true
77
+ */
78
+ showBackButton?: boolean;
79
+
80
+ /** Content rendered on the right side of the header */
81
+ rightItems?: ReactNode;
82
+
83
+ /** Content rendered on the left side (after back button) */
84
+ leftItems?: ReactNode;
85
+
86
+ /**
87
+ * Whether to add safe area top padding.
88
+ * @default true
89
+ */
90
+ safeAreaTop?: boolean;
91
+
92
+ /** Back button press handler — back button only renders when this is provided */
93
+ onBackPress?: () => void;
94
+
95
+ /** Test ID for testing frameworks */
96
+ testID?: string;
97
+ }
98
+
99
+ export interface HeaderRightItemsProps {
100
+ children: ReactNode;
101
+ }
102
+
103
+ export type HeaderTextVariant =
104
+ | "headingSmall"
105
+ | "headingMedium"
106
+ | "headingLarge";
107
+
108
+ export interface UseHeaderLogicParams {
109
+ accessibilityLabel: string | undefined;
110
+ accessibilityHint: string | undefined;
111
+ size: ResponsiveValue<HeaderSize, RestyleTheme["breakpoints"]>;
112
+ showBackButton: boolean;
113
+ safeAreaTop: boolean;
114
+ onBackPress: (() => void) | undefined;
115
+ }
116
+
117
+ export interface UseHeaderLogicReturn {
118
+ handleBack: () => void;
119
+ showBack: boolean;
120
+ dimensions: HeaderDimensionsResult;
121
+ containerStyle: ViewStyle;
122
+ a11yContainerProps: HeaderA11yProps;
123
+ textVariant: HeaderTextVariant;
124
+ backButtonA11yProps: HeaderA11yProps;
125
+ }
126
+
127
+ export interface ResolveHeaderDimensionsParams {
128
+ resolvedSize: HeaderSize;
129
+ safeAreaTop: boolean;
130
+ topInset: number;
131
+ theme: RestyleTheme;
132
+ }
133
+
134
+ export interface HeaderDimensionsResult {
135
+ topPadding: number;
136
+ totalHeight: number;
137
+ }
138
+
139
+ export interface HeaderA11yParams {
140
+ accessibilityLabel?: string;
141
+ accessibilityHint?: string;
142
+ }
143
+
144
+ export interface HeaderBackButtonA11yParams {
145
+ accessibilityLabel?: string;
146
+ accessibilityHint?: string;
147
+ }
148
+
149
+ export interface HeaderA11yProps {
150
+ accessibilityRole: AccessibilityRole;
151
+ accessibilityLabel?: string;
152
+ accessibilityHint?: string;
153
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Header Module
3
+ *
4
+ * Organism component for navigation headers with title and actions.
5
+ *
6
+ * Combines IconButton, Text, and Box atoms into a complete
7
+ * navigation bar with safe area awareness.
8
+ *
9
+ * ## Components
10
+ * - **Header**: Main navigation header
11
+ * - **HeaderRightItems**: Container for right-side action buttons
12
+ *
13
+ * ## Size Scale
14
+ * | Size | Height | Use Case |
15
+ * |------|--------|----------|
16
+ * | sm | 44px | Compact screens |
17
+ * | md | 56px | Default mobile |
18
+ * | lg | 64px | Tablets |
19
+ *
20
+ * @example
21
+ * import { Header, HeaderRightItems } from "@/design-system/primitives/navigation/Header";
22
+ *
23
+ * <Header
24
+ * title="Profile"
25
+ * rightItems={
26
+ * <HeaderRightItems>
27
+ * <IconButton iconName="edit" onPress={handleEdit} accessibilityLabel="Edit" />
28
+ * </HeaderRightItems>
29
+ * }
30
+ * />
31
+ */
32
+
33
+ export { Header, HeaderRightItems } from "./Header";
34
+
35
+ export type {
36
+ HeaderProps,
37
+ HeaderSize,
38
+ HeaderVariant,
39
+ HeaderRightItemsProps,
40
+ HeaderA11yParams,
41
+ HeaderA11yProps,
42
+ } from "./Header.types";
43
+
44
+ export { getHeaderA11y, getHeaderBackButtonA11y } from "./Header.a11y";