@praxiis/ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +52556 -0
- package/dist/index.d.ts +52556 -0
- package/dist/index.js +8753 -0
- package/dist/index.mjs +8777 -0
- package/package.json +70 -0
- package/src/__test-utils__/index.tsx +39 -0
- package/src/components/CalendarStrip/CalendarStrip.helpers.ts +106 -0
- package/src/components/CalendarStrip/CalendarStrip.tsx +83 -0
- package/src/components/CalendarStrip/CalendarStrip.types.ts +133 -0
- package/src/components/CalendarStrip/DayCard/DayCard.helpers.ts +44 -0
- package/src/components/CalendarStrip/DayCard/DayCard.tsx +71 -0
- package/src/components/CalendarStrip/DayCard/DayCard.types.ts +134 -0
- package/src/components/CalendarStrip/DayCard/index.ts +2 -0
- package/src/components/CalendarStrip/DayCard/useDayCardLogic.ts +45 -0
- package/src/components/CalendarStrip/index.ts +9 -0
- package/src/components/CalendarStrip/useCalendarStripLogic.ts +53 -0
- package/src/components/EmptyState/EmptyState.helpers.ts +104 -0
- package/src/components/EmptyState/EmptyState.tsx +205 -0
- package/src/components/EmptyState/EmptyState.types.ts +213 -0
- package/src/components/EmptyState/index.ts +44 -0
- package/src/components/EmptyState/useEmptyStateLogic.ts +131 -0
- package/src/components/Header/Header.helpers.ts +93 -0
- package/src/components/Header/Header.tsx +185 -0
- package/src/components/Header/Header.types.ts +153 -0
- package/src/components/Header/index.ts +44 -0
- package/src/components/Header/useHeaderLogic.ts +146 -0
- package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.helpers.ts +50 -0
- package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.tsx +78 -0
- package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.types.ts +99 -0
- package/src/components/ScheduleItem/ScheduleItem/index.ts +16 -0
- package/src/components/ScheduleItem/ScheduleItem/useScheduleItemLogic.ts +31 -0
- package/src/components/ScheduleItem/index.ts +15 -0
- package/src/components/index.ts +40 -0
- package/src/core/index.ts +34 -0
- package/src/core/restyle/RestyleThemeProviderWrapper.tsx +31 -0
- package/src/core/restyle/index.ts +38 -0
- package/src/core/restyle/restylePresetRegistry.ts +195 -0
- package/src/core/restyle/restyleTheme.ts +1352 -0
- package/src/core/restyle/restyleTypes.ts +8 -0
- package/src/core/restyle/useRestyleTheme.ts +10 -0
- package/src/hooks/animations/index.ts +3 -0
- package/src/hooks/animations/useAnimatedValue.ts +10 -0
- package/src/hooks/animations/useEntranceAnimation.ts +106 -0
- package/src/hooks/animations/usePulseAnimation.ts +63 -0
- package/src/hooks/index.ts +30 -0
- package/src/hooks/useReducedMotion.ts +60 -0
- package/src/i18n/index.ts +2 -0
- package/src/i18n/labels/en.ts +120 -0
- package/src/i18n/labels/es.ts +120 -0
- package/src/i18n/labels/index.ts +6 -0
- package/src/i18n/labels/types.ts +165 -0
- package/src/index.tsx +215 -0
- package/src/primitives/actions/Button/Button.helpers.ts +243 -0
- package/src/primitives/actions/Button/Button.tsx +198 -0
- package/src/primitives/actions/Button/Button.types.ts +207 -0
- package/src/primitives/actions/Button/index.ts +41 -0
- package/src/primitives/actions/Button/useButtonLogic.ts +160 -0
- package/src/primitives/actions/IconButton/IconButton.helpers.ts +235 -0
- package/src/primitives/actions/IconButton/IconButton.tsx +177 -0
- package/src/primitives/actions/IconButton/IconButton.types.ts +273 -0
- package/src/primitives/actions/IconButton/index.ts +30 -0
- package/src/primitives/actions/IconButton/useIconButtonLogic.ts +172 -0
- package/src/primitives/actions/index.ts +20 -0
- package/src/primitives/content/Avatar/Avatar.helpers.ts +177 -0
- package/src/primitives/content/Avatar/Avatar.tsx +199 -0
- package/src/primitives/content/Avatar/Avatar.types.ts +222 -0
- package/src/primitives/content/Avatar/index.ts +46 -0
- package/src/primitives/content/Avatar/useAvatarLogic.ts +149 -0
- package/src/primitives/content/Badge/Badge.helpers.ts +175 -0
- package/src/primitives/content/Badge/Badge.tsx +174 -0
- package/src/primitives/content/Badge/Badge.types.ts +223 -0
- package/src/primitives/content/Badge/index.ts +40 -0
- package/src/primitives/content/Badge/useBadgeLogic.ts +128 -0
- package/src/primitives/content/Card/Card.helpers.ts +27 -0
- package/src/primitives/content/Card/Card.tsx +123 -0
- package/src/primitives/content/Card/Card.types.ts +95 -0
- package/src/primitives/content/Card/index.ts +20 -0
- package/src/primitives/content/Card/useCardLogic.ts +48 -0
- package/src/primitives/content/Chip/Chip.helpers.ts +304 -0
- package/src/primitives/content/Chip/Chip.tsx +205 -0
- package/src/primitives/content/Chip/Chip.types.ts +234 -0
- package/src/primitives/content/Chip/index.ts +47 -0
- package/src/primitives/content/Chip/useChipLogic.ts +167 -0
- package/src/primitives/content/Icon/Icon.helpers.ts +54 -0
- package/src/primitives/content/Icon/Icon.tsx +110 -0
- package/src/primitives/content/Icon/Icon.types.ts +95 -0
- package/src/primitives/content/Icon/index.ts +20 -0
- package/src/primitives/content/Icon/useIconLogic.ts +73 -0
- package/src/primitives/content/index.ts +45 -0
- package/src/primitives/feedback/ProgressBar/ProgressBar.helpers.ts +122 -0
- package/src/primitives/feedback/ProgressBar/ProgressBar.tsx +154 -0
- package/src/primitives/feedback/ProgressBar/ProgressBar.types.ts +178 -0
- package/src/primitives/feedback/ProgressBar/index.ts +17 -0
- package/src/primitives/feedback/ProgressBar/useProgressBarLogic.ts +120 -0
- package/src/primitives/feedback/Skeleton/Skeleton.helpers.ts +145 -0
- package/src/primitives/feedback/Skeleton/Skeleton.tsx +155 -0
- package/src/primitives/feedback/Skeleton/Skeleton.types.ts +223 -0
- package/src/primitives/feedback/Skeleton/index.ts +44 -0
- package/src/primitives/feedback/Skeleton/useSkeletonLogic.ts +125 -0
- package/src/primitives/feedback/Spinner/Spinner.helpers.ts +40 -0
- package/src/primitives/feedback/Spinner/Spinner.tsx +105 -0
- package/src/primitives/feedback/Spinner/Spinner.types.ts +114 -0
- package/src/primitives/feedback/Spinner/index.ts +18 -0
- package/src/primitives/feedback/Spinner/useSpinnerLogic.ts +84 -0
- package/src/primitives/feedback/Toast/Toast.helpers.ts +163 -0
- package/src/primitives/feedback/Toast/Toast.tsx +190 -0
- package/src/primitives/feedback/Toast/Toast.types.ts +270 -0
- package/src/primitives/feedback/Toast/ToastContext.tsx +96 -0
- package/src/primitives/feedback/Toast/ToastProvider.tsx +241 -0
- package/src/primitives/feedback/Toast/index.ts +59 -0
- package/src/primitives/feedback/Toast/useToastLogic.ts +112 -0
- package/src/primitives/feedback/index.ts +45 -0
- package/src/primitives/index.ts +158 -0
- package/src/primitives/inputs/Checkbox/Checkbox.helpers.ts +132 -0
- package/src/primitives/inputs/Checkbox/Checkbox.tsx +150 -0
- package/src/primitives/inputs/Checkbox/Checkbox.types.ts +106 -0
- package/src/primitives/inputs/Checkbox/index.ts +30 -0
- package/src/primitives/inputs/Checkbox/useCheckboxLogic.ts +121 -0
- package/src/primitives/inputs/RadioButton/RadioButton.helpers.ts +123 -0
- package/src/primitives/inputs/RadioButton/RadioButton.tsx +159 -0
- package/src/primitives/inputs/RadioButton/RadioButton.types.ts +106 -0
- package/src/primitives/inputs/RadioButton/index.ts +25 -0
- package/src/primitives/inputs/RadioButton/useRadioButtonLogic.ts +117 -0
- package/src/primitives/inputs/SegmentedControl/SegmentedControl.helpers.ts +174 -0
- package/src/primitives/inputs/SegmentedControl/SegmentedControl.tsx +224 -0
- package/src/primitives/inputs/SegmentedControl/SegmentedControl.types.ts +187 -0
- package/src/primitives/inputs/SegmentedControl/index.ts +39 -0
- package/src/primitives/inputs/SegmentedControl/useSegmentedControlLogic.ts +151 -0
- package/src/primitives/inputs/SelectSheet/SelectSheet.helpers.ts +147 -0
- package/src/primitives/inputs/SelectSheet/SelectSheet.tsx +247 -0
- package/src/primitives/inputs/SelectSheet/SelectSheet.types.ts +196 -0
- package/src/primitives/inputs/SelectSheet/SelectSheetOption.tsx +177 -0
- package/src/primitives/inputs/SelectSheet/index.ts +48 -0
- package/src/primitives/inputs/SelectSheet/useSelectSheetLogic.ts +309 -0
- package/src/primitives/inputs/Switch/Switch.helpers.ts +109 -0
- package/src/primitives/inputs/Switch/Switch.tsx +191 -0
- package/src/primitives/inputs/Switch/Switch.types.ts +154 -0
- package/src/primitives/inputs/Switch/index.ts +40 -0
- package/src/primitives/inputs/Switch/useSwitchLogic.ts +192 -0
- package/src/primitives/inputs/TextInput/TextInput.helpers.ts +206 -0
- package/src/primitives/inputs/TextInput/TextInput.tsx +392 -0
- package/src/primitives/inputs/TextInput/TextInput.types.ts +216 -0
- package/src/primitives/inputs/TextInput/index.ts +37 -0
- package/src/primitives/inputs/TextInput/useTextInputLogic.ts +195 -0
- package/src/primitives/inputs/index.ts +52 -0
- package/src/primitives/layout/AnimatedBox.tsx +44 -0
- package/src/primitives/layout/Box.tsx +71 -0
- package/src/primitives/layout/Divider/Divider.helpers.ts +115 -0
- package/src/primitives/layout/Divider/Divider.tsx +139 -0
- package/src/primitives/layout/Divider/Divider.types.ts +178 -0
- package/src/primitives/layout/Divider/index.ts +24 -0
- package/src/primitives/layout/Divider/useDividerLogic.ts +109 -0
- package/src/primitives/layout/FlatList.tsx +66 -0
- package/src/primitives/layout/Pressable.tsx +74 -0
- package/src/primitives/layout/ScrollView.tsx +63 -0
- package/src/primitives/layout/Stack.tsx +69 -0
- package/src/primitives/layout/index.ts +40 -0
- package/src/primitives/navigation/index.ts +6 -0
- package/src/primitives/overlays/Modal/Modal.helpers.ts +31 -0
- package/src/primitives/overlays/Modal/Modal.tsx +264 -0
- package/src/primitives/overlays/Modal/Modal.types.ts +193 -0
- package/src/primitives/overlays/Modal/index.ts +43 -0
- package/src/primitives/overlays/Modal/useModalLogic.ts +103 -0
- package/src/primitives/overlays/index.ts +12 -0
- package/src/primitives/typography/Text.tsx +51 -0
- package/src/primitives/typography/index.ts +1 -0
- package/src/provider/DesignSystemContext.ts +22 -0
- package/src/provider/DesignSystemProvider.tsx +121 -0
- package/src/provider/index.ts +7 -0
- package/src/providers/ThemeProvider/createTheme.ts +304 -0
- package/src/providers/ThemeProvider/defaultTheme.ts +70 -0
- package/src/providers/ThemeProvider/index.ts +34 -0
- package/src/providers/ThemeProvider/types.ts +249 -0
- package/src/providers/index.ts +29 -0
- package/src/tokens/colors.ts +371 -0
- package/src/tokens/index.ts +145 -0
- package/src/tokens/motion.ts +176 -0
- package/src/tokens/radii.ts +82 -0
- package/src/tokens/scales.ts +588 -0
- package/src/tokens/shadows.ts +190 -0
- package/src/tokens/spacing.ts +140 -0
- package/src/tokens/tokens.json +207 -0
- package/src/tokens/typography.ts +251 -0
- package/src/types.ts +50 -0
- package/src/utils/accessibility.ts +169 -0
- package/src/utils/index.ts +25 -0
- package/src/utils/platform.ts +72 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Header Logic Hook
|
|
3
|
+
*
|
|
4
|
+
* Extracts all computational logic from the Header component.
|
|
5
|
+
* Returns memoized values for optimal render performance.
|
|
6
|
+
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* - Resolve responsive size prop to current breakpoint value
|
|
9
|
+
* - Calculate header dimensions with safe area insets
|
|
10
|
+
* - Determine back button visibility
|
|
11
|
+
* - Generate container and back button accessibility props
|
|
12
|
+
* - Create back button press handler
|
|
13
|
+
*
|
|
14
|
+
* External Dependencies:
|
|
15
|
+
* - react-native-safe-area-context: Safe area insets
|
|
16
|
+
* - i18n: Translated accessibility labels
|
|
17
|
+
*
|
|
18
|
+
* @see Header.tsx - Component consuming this hook
|
|
19
|
+
* @see Header.helpers.ts - Pure calculation functions
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { useDesignSystem } from "../../provider";
|
|
23
|
+
import { useResponsiveProp } from "@shopify/restyle";
|
|
24
|
+
import { useCallback, useMemo } from "react";
|
|
25
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
26
|
+
import { useRestyleTheme } from "../../core/restyle";
|
|
27
|
+
import { getHeaderA11y, getHeaderBackButtonA11y } from "./Header.a11y";
|
|
28
|
+
import {
|
|
29
|
+
resolveContainerStyle,
|
|
30
|
+
resolveHeaderDimensions,
|
|
31
|
+
SIZE_TO_TEXT_VARIANT,
|
|
32
|
+
} from "./Header.helpers";
|
|
33
|
+
import { HeaderSize, UseHeaderLogicParams, UseHeaderLogicReturn } from "./Header.types";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Orchestrates Header rendering logic and state management.
|
|
37
|
+
*
|
|
38
|
+
* Handles:
|
|
39
|
+
* - Responsive size resolution
|
|
40
|
+
* - Header dimension calculation with safe area insets
|
|
41
|
+
* - Back button visibility determination (shown when `onBackPress` is provided)
|
|
42
|
+
* - Back button press handling
|
|
43
|
+
* - Text variant selection based on size
|
|
44
|
+
* - Container style computation with top padding
|
|
45
|
+
* - Accessibility props for header and back button
|
|
46
|
+
* - Internationalization for back button labels
|
|
47
|
+
*
|
|
48
|
+
* @param params - Configuration object for header behavior
|
|
49
|
+
* @param params.accessibilityLabel - Custom a11y label for header
|
|
50
|
+
* @param params.accessibilityHint - Describes header purpose
|
|
51
|
+
* @param params.size - Size variant ('sm' | 'md' | 'lg')
|
|
52
|
+
* @param params.showBackButton - Whether to show back button
|
|
53
|
+
* @param params.safeAreaTop - Whether to add safe area top padding
|
|
54
|
+
* @param params.onBackPress - Optional custom back handler
|
|
55
|
+
*
|
|
56
|
+
* @returns Computed values for rendering Header
|
|
57
|
+
* @returns {function} handleBack - Back button press handler
|
|
58
|
+
* @returns {boolean} showBack - Whether to display back button
|
|
59
|
+
* @returns {object} dimensions - Height and padding dimensions
|
|
60
|
+
* @returns {ViewStyle} containerStyle - Dynamic container styles
|
|
61
|
+
* @returns {object} a11yContainerProps - Container accessibility props
|
|
62
|
+
* @returns {string} textVariant - Text variant for title
|
|
63
|
+
* @returns {object} backButtonA11yProps - Back button accessibility props
|
|
64
|
+
*
|
|
65
|
+
* @performance This hook uses useMemo() for expensive calculations
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* const {
|
|
69
|
+
* showBack,
|
|
70
|
+
* textVariant,
|
|
71
|
+
* dimensions,
|
|
72
|
+
* handleBack,
|
|
73
|
+
* a11yContainerProps
|
|
74
|
+
* } = useHeaderLogic({
|
|
75
|
+
* size: "md",
|
|
76
|
+
* showBackButton: true,
|
|
77
|
+
* safeAreaTop: true,
|
|
78
|
+
* accessibilityLabel: "Profile header",
|
|
79
|
+
* });
|
|
80
|
+
*/
|
|
81
|
+
export function useHeaderLogic(
|
|
82
|
+
params: UseHeaderLogicParams,
|
|
83
|
+
): UseHeaderLogicReturn {
|
|
84
|
+
const {
|
|
85
|
+
accessibilityLabel,
|
|
86
|
+
accessibilityHint,
|
|
87
|
+
size,
|
|
88
|
+
showBackButton,
|
|
89
|
+
safeAreaTop,
|
|
90
|
+
onBackPress,
|
|
91
|
+
} = params;
|
|
92
|
+
|
|
93
|
+
const insets = useSafeAreaInsets();
|
|
94
|
+
const theme = useRestyleTheme();
|
|
95
|
+
const { labels: t } = useDesignSystem();
|
|
96
|
+
|
|
97
|
+
const resolvedSize = (useResponsiveProp(size) ?? "md") as HeaderSize;
|
|
98
|
+
const showBack = !!showBackButton && onBackPress !== undefined;
|
|
99
|
+
|
|
100
|
+
const dimensions = useMemo(
|
|
101
|
+
() =>
|
|
102
|
+
resolveHeaderDimensions({
|
|
103
|
+
resolvedSize,
|
|
104
|
+
safeAreaTop,
|
|
105
|
+
topInset: insets.top,
|
|
106
|
+
theme,
|
|
107
|
+
}),
|
|
108
|
+
[resolvedSize, safeAreaTop, insets.top, theme],
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const containerStyle = resolveContainerStyle(dimensions.topPadding);
|
|
112
|
+
|
|
113
|
+
const handleBack = useCallback(() => {
|
|
114
|
+
onBackPress?.();
|
|
115
|
+
}, [onBackPress]);
|
|
116
|
+
|
|
117
|
+
const a11yContainerProps = useMemo(
|
|
118
|
+
() =>
|
|
119
|
+
getHeaderA11y({
|
|
120
|
+
accessibilityLabel,
|
|
121
|
+
accessibilityHint,
|
|
122
|
+
}),
|
|
123
|
+
[accessibilityLabel, accessibilityHint],
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const textVariant = SIZE_TO_TEXT_VARIANT[resolvedSize];
|
|
127
|
+
|
|
128
|
+
const backButtonA11yProps = useMemo(
|
|
129
|
+
() =>
|
|
130
|
+
getHeaderBackButtonA11y({
|
|
131
|
+
accessibilityLabel: t.header.backButton.label,
|
|
132
|
+
accessibilityHint: t.header.backButton.hint,
|
|
133
|
+
}),
|
|
134
|
+
[t],
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
handleBack,
|
|
139
|
+
showBack,
|
|
140
|
+
dimensions,
|
|
141
|
+
containerStyle,
|
|
142
|
+
a11yContainerProps,
|
|
143
|
+
textVariant,
|
|
144
|
+
backButtonA11yProps,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ScheduleItemSize,
|
|
3
|
+
ScheduleItemSizeConfig,
|
|
4
|
+
ScheduleItemSizeConfigMap,
|
|
5
|
+
} from "./ScheduleItem.types";
|
|
6
|
+
|
|
7
|
+
// ─── Time Formatting ─────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
export function formatTimeRange(startTime: Date, endTime: Date): string {
|
|
10
|
+
const startStr = startTime.toLocaleTimeString([], {
|
|
11
|
+
hour: "numeric",
|
|
12
|
+
minute: "2-digit",
|
|
13
|
+
hour12: true,
|
|
14
|
+
});
|
|
15
|
+
const endStr = endTime.toLocaleTimeString([], {
|
|
16
|
+
hour: "numeric",
|
|
17
|
+
minute: "2-digit",
|
|
18
|
+
hour12: true,
|
|
19
|
+
});
|
|
20
|
+
return `${startStr} – ${endStr}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ─── Size Config ─────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
const SCHEDULE_ITEM_SIZE_CONFIG: ScheduleItemSizeConfigMap = {
|
|
26
|
+
sm: {
|
|
27
|
+
indicatorHeight: 32,
|
|
28
|
+
contentGap: "2xs",
|
|
29
|
+
titleVariant: "labelSmall",
|
|
30
|
+
timeVariant: "captionSmall",
|
|
31
|
+
},
|
|
32
|
+
md: {
|
|
33
|
+
indicatorHeight: 48,
|
|
34
|
+
contentGap: "2xs",
|
|
35
|
+
titleVariant: "labelSmall",
|
|
36
|
+
timeVariant: "captionSmall",
|
|
37
|
+
},
|
|
38
|
+
lg: {
|
|
39
|
+
indicatorHeight: 64,
|
|
40
|
+
contentGap: "xs",
|
|
41
|
+
titleVariant: "labelMedium",
|
|
42
|
+
timeVariant: "bodySmall",
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export function getScheduleItemSizeConfig(
|
|
47
|
+
size: ScheduleItemSize,
|
|
48
|
+
): ScheduleItemSizeConfig {
|
|
49
|
+
return SCHEDULE_ITEM_SIZE_CONFIG[size];
|
|
50
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { RestyleTheme } from "../../../core/restyle";
|
|
2
|
+
import { Box, Text } from "../../../primitives";
|
|
3
|
+
import {
|
|
4
|
+
createRestyleComponent,
|
|
5
|
+
createVariant,
|
|
6
|
+
layout,
|
|
7
|
+
spacing,
|
|
8
|
+
spacingShorthand,
|
|
9
|
+
} from "@shopify/restyle";
|
|
10
|
+
import React, { memo } from "react";
|
|
11
|
+
import { Pressable as RNPressable } from "react-native";
|
|
12
|
+
import { BaseScheduleItemProps, ScheduleItemProps } from "./ScheduleItem.types";
|
|
13
|
+
import { useScheduleItemLogic } from "./useScheduleItemLogic";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Base ScheduleItem container with Restyle variant support.
|
|
17
|
+
*
|
|
18
|
+
* Built on RNPressable so press handling and variant styling live in one element.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
const BaseScheduleItemContainer = createRestyleComponent<
|
|
22
|
+
BaseScheduleItemProps,
|
|
23
|
+
RestyleTheme
|
|
24
|
+
>(
|
|
25
|
+
[
|
|
26
|
+
layout,
|
|
27
|
+
spacing,
|
|
28
|
+
spacingShorthand,
|
|
29
|
+
createVariant({ themeKey: "scheduleItemSizes", property: "size" }),
|
|
30
|
+
],
|
|
31
|
+
RNPressable,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
function ScheduleItemComponent({
|
|
35
|
+
task,
|
|
36
|
+
onPress,
|
|
37
|
+
size = "md",
|
|
38
|
+
testID,
|
|
39
|
+
...rest
|
|
40
|
+
}: ScheduleItemProps) {
|
|
41
|
+
const { timeRange, sizeConfig, a11yProps } = useScheduleItemLogic({
|
|
42
|
+
task,
|
|
43
|
+
size,
|
|
44
|
+
onPress,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<BaseScheduleItemContainer
|
|
49
|
+
size={size}
|
|
50
|
+
onPress={onPress}
|
|
51
|
+
disabled={!onPress}
|
|
52
|
+
testID={testID}
|
|
53
|
+
{...a11yProps}
|
|
54
|
+
{...rest}
|
|
55
|
+
>
|
|
56
|
+
{/* Left indicator bar */}
|
|
57
|
+
<Box
|
|
58
|
+
width={4}
|
|
59
|
+
height={sizeConfig.indicatorHeight}
|
|
60
|
+
borderRadius="full"
|
|
61
|
+
backgroundColor={task.indicatorColor}
|
|
62
|
+
/>
|
|
63
|
+
|
|
64
|
+
{/* Content */}
|
|
65
|
+
<Box flex={1} gap={sizeConfig.contentGap}>
|
|
66
|
+
<Text variant={sizeConfig.titleVariant} color="textPrimary">
|
|
67
|
+
{task.title}
|
|
68
|
+
</Text>
|
|
69
|
+
<Text variant={sizeConfig.timeVariant} color="textSecondary">
|
|
70
|
+
{timeRange}
|
|
71
|
+
</Text>
|
|
72
|
+
</Box>
|
|
73
|
+
</BaseScheduleItemContainer>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const ScheduleItem = memo(ScheduleItemComponent);
|
|
78
|
+
ScheduleItem.displayName = "ScheduleItem";
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { ResponsiveValue, SpacingShorthandProps, VariantProps } from "@shopify/restyle";
|
|
2
|
+
import { PressableProps as RNPressableProps } from "react-native";
|
|
3
|
+
import type { RestyleTheme } from "../../..";
|
|
4
|
+
import type { PressableRestyleProps } from "../../../primitives/layout/Pressable";
|
|
5
|
+
|
|
6
|
+
// ─── Size (derived from theme so it stays in sync) ───────────────────────────
|
|
7
|
+
|
|
8
|
+
export type ScheduleItemSize = Exclude<
|
|
9
|
+
keyof RestyleTheme["scheduleItemSizes"],
|
|
10
|
+
"defaults"
|
|
11
|
+
>;
|
|
12
|
+
|
|
13
|
+
// ─── Base component props (Restyle variant + Pressable) ──────────────────────
|
|
14
|
+
|
|
15
|
+
type ScheduleItemSizeVariantProps = VariantProps<
|
|
16
|
+
RestyleTheme,
|
|
17
|
+
"scheduleItemSizes",
|
|
18
|
+
"size"
|
|
19
|
+
>;
|
|
20
|
+
|
|
21
|
+
/** Base props for the Restyle container — used with createRestyleComponent. */
|
|
22
|
+
export type BaseScheduleItemProps = ScheduleItemSizeVariantProps &
|
|
23
|
+
PressableRestyleProps &
|
|
24
|
+
SpacingShorthandProps<RestyleTheme> &
|
|
25
|
+
RNPressableProps;
|
|
26
|
+
|
|
27
|
+
// ─── Size config (only values that cannot be expressed as theme tokens) ───────
|
|
28
|
+
|
|
29
|
+
export interface ScheduleItemSizeConfig {
|
|
30
|
+
indicatorHeight: number;
|
|
31
|
+
contentGap: keyof RestyleTheme["spacing"];
|
|
32
|
+
titleVariant: "labelSmall" | "labelMedium";
|
|
33
|
+
timeVariant: "captionSmall" | "bodySmall";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type ScheduleItemSizeConfigMap = Record<
|
|
37
|
+
ScheduleItemSize,
|
|
38
|
+
ScheduleItemSizeConfig
|
|
39
|
+
>;
|
|
40
|
+
|
|
41
|
+
// ─── Data ────────────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Data for a single scheduled task or event
|
|
45
|
+
*/
|
|
46
|
+
export interface ScheduleItemData {
|
|
47
|
+
/** Unique identifier */
|
|
48
|
+
id: string;
|
|
49
|
+
/** Task title (e.g., "Team Standup") */
|
|
50
|
+
title: string;
|
|
51
|
+
/** Task start time */
|
|
52
|
+
startTime: Date;
|
|
53
|
+
/** Task end time */
|
|
54
|
+
endTime: Date;
|
|
55
|
+
/** Theme color token for the left indicator bar */
|
|
56
|
+
indicatorColor: keyof RestyleTheme["colors"];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ─── Component Props ─────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
export interface ScheduleItemProps extends Omit<BaseScheduleItemProps, "style"> {
|
|
62
|
+
task: ScheduleItemData;
|
|
63
|
+
onPress?: () => void;
|
|
64
|
+
/**
|
|
65
|
+
* Size variant — drives container padding via the `scheduleItemSizes` theme
|
|
66
|
+
* variant and sub-element config (indicator height, text variants).
|
|
67
|
+
* `VariantProps` already types this as `ResponsiveValue<ScheduleItemSize, ...>`.
|
|
68
|
+
* @default "md"
|
|
69
|
+
*/
|
|
70
|
+
testID?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ─── Hook ────────────────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
export interface UseScheduleItemLogicParams {
|
|
76
|
+
task: ScheduleItemData;
|
|
77
|
+
size: ResponsiveValue<ScheduleItemSize, RestyleTheme["breakpoints"]>;
|
|
78
|
+
onPress?: () => void;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface UseScheduleItemLogicReturn {
|
|
82
|
+
timeRange: string;
|
|
83
|
+
sizeConfig: ScheduleItemSizeConfig;
|
|
84
|
+
a11yProps: ScheduleItemA11yProps;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ─── Accessibility ───────────────────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
export interface ScheduleItemA11yParams {
|
|
90
|
+
title: string;
|
|
91
|
+
timeRange: string;
|
|
92
|
+
onPress?: () => void;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface ScheduleItemA11yProps {
|
|
96
|
+
accessible: boolean;
|
|
97
|
+
accessibilityRole: "button" | "text";
|
|
98
|
+
accessibilityLabel: string;
|
|
99
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { ScheduleItem } from "./ScheduleItem";
|
|
2
|
+
export type {
|
|
3
|
+
BaseScheduleItemProps,
|
|
4
|
+
ScheduleItemA11yParams,
|
|
5
|
+
ScheduleItemA11yProps,
|
|
6
|
+
ScheduleItemData,
|
|
7
|
+
ScheduleItemProps,
|
|
8
|
+
ScheduleItemSize,
|
|
9
|
+
ScheduleItemSizeConfig,
|
|
10
|
+
ScheduleItemSizeConfigMap,
|
|
11
|
+
UseScheduleItemLogicParams,
|
|
12
|
+
UseScheduleItemLogicReturn,
|
|
13
|
+
} from "./ScheduleItem.types";
|
|
14
|
+
export { formatTimeRange, getScheduleItemSizeConfig } from "./ScheduleItem.helpers";
|
|
15
|
+
export { getScheduleItemA11y } from "./ScheduleItem.a11y";
|
|
16
|
+
export { useScheduleItemLogic } from "./useScheduleItemLogic";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useResponsiveProp } from "@shopify/restyle";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { getScheduleItemA11y } from "./ScheduleItem.a11y";
|
|
4
|
+
import {
|
|
5
|
+
formatTimeRange,
|
|
6
|
+
getScheduleItemSizeConfig,
|
|
7
|
+
} from "./ScheduleItem.helpers";
|
|
8
|
+
import type {
|
|
9
|
+
ScheduleItemSize,
|
|
10
|
+
UseScheduleItemLogicParams,
|
|
11
|
+
UseScheduleItemLogicReturn,
|
|
12
|
+
} from "./ScheduleItem.types";
|
|
13
|
+
|
|
14
|
+
export function useScheduleItemLogic({
|
|
15
|
+
task,
|
|
16
|
+
size,
|
|
17
|
+
onPress,
|
|
18
|
+
}: UseScheduleItemLogicParams): UseScheduleItemLogicReturn {
|
|
19
|
+
const resolvedSize = (useResponsiveProp(size) ?? "md") as ScheduleItemSize;
|
|
20
|
+
|
|
21
|
+
const timeRange = formatTimeRange(task.startTime, task.endTime);
|
|
22
|
+
|
|
23
|
+
const sizeConfig = getScheduleItemSizeConfig(resolvedSize);
|
|
24
|
+
|
|
25
|
+
const a11yProps = useMemo(
|
|
26
|
+
() => getScheduleItemA11y({ title: task.title, timeRange, onPress }),
|
|
27
|
+
[task.title, timeRange, onPress],
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return { timeRange, sizeConfig, a11yProps };
|
|
31
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// ScheduleItem sub-component
|
|
2
|
+
export { ScheduleItem } from "./ScheduleItem/ScheduleItem";
|
|
3
|
+
export { getScheduleItemA11y } from "./ScheduleItem/ScheduleItem.a11y";
|
|
4
|
+
export {
|
|
5
|
+
formatTimeRange,
|
|
6
|
+
getScheduleItemSizeConfig,
|
|
7
|
+
} from "./ScheduleItem/ScheduleItem.helpers";
|
|
8
|
+
export type {
|
|
9
|
+
ScheduleItemData,
|
|
10
|
+
ScheduleItemProps,
|
|
11
|
+
ScheduleItemSize,
|
|
12
|
+
ScheduleItemSizeConfig,
|
|
13
|
+
ScheduleItemSizeConfigMap,
|
|
14
|
+
} from "./ScheduleItem/ScheduleItem.types";
|
|
15
|
+
export { useScheduleItemLogic } from "./ScheduleItem/useScheduleItemLogic";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design System Components
|
|
3
|
+
*
|
|
4
|
+
* Composite components that are built from primitives but are not
|
|
5
|
+
* considered atomic/primitive themselves.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ─── CalendarStrip ───────────────────────────────────────────────────────────
|
|
9
|
+
export {
|
|
10
|
+
CalendarStrip,
|
|
11
|
+
DayCard,
|
|
12
|
+
type CalendarStripProps,
|
|
13
|
+
type CalendarStripSize,
|
|
14
|
+
type DayCardProps,
|
|
15
|
+
} from "./CalendarStrip";
|
|
16
|
+
|
|
17
|
+
// ─── EmptyState ─────────────────────────────────────────────────────────────
|
|
18
|
+
export {
|
|
19
|
+
EmptyState,
|
|
20
|
+
type EmptyStateProps,
|
|
21
|
+
type EmptyStateVariant,
|
|
22
|
+
} from "./EmptyState";
|
|
23
|
+
|
|
24
|
+
// ─── Header ──────────────────────────────────────────────────────────────────
|
|
25
|
+
export {
|
|
26
|
+
Header,
|
|
27
|
+
HeaderRightItems,
|
|
28
|
+
type HeaderProps,
|
|
29
|
+
type HeaderRightItemsProps,
|
|
30
|
+
type HeaderSize,
|
|
31
|
+
type HeaderVariant,
|
|
32
|
+
} from "./Header";
|
|
33
|
+
|
|
34
|
+
// ─── ScheduleItem ────────────────────────────────────────────────────────────
|
|
35
|
+
export {
|
|
36
|
+
ScheduleItem,
|
|
37
|
+
type ScheduleItemData,
|
|
38
|
+
type ScheduleItemProps,
|
|
39
|
+
type ScheduleItemSize,
|
|
40
|
+
} from "./ScheduleItem";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Primitives Module
|
|
3
|
+
*
|
|
4
|
+
* Fundamental, low-level primitives that serve as the foundation
|
|
5
|
+
* for all design system components.
|
|
6
|
+
*
|
|
7
|
+
* ## Restyle Integration
|
|
8
|
+
* - **RestyleTheme**: Type-safe theme definition
|
|
9
|
+
* - **useRestyleTheme**: Hook for accessing the current Restyle theme
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* import { Box, Text, AnimatedBox } from "@/design-system/core";
|
|
13
|
+
*
|
|
14
|
+
* <Box padding="lg" backgroundColor="surfacePrimary">
|
|
15
|
+
* <Text variant="headingLarge">Hello World</Text>
|
|
16
|
+
* </Box>
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// Restyle Integration
|
|
20
|
+
export {
|
|
21
|
+
restyleDarkTheme,
|
|
22
|
+
restyleLightTheme,
|
|
23
|
+
restyleTheme,
|
|
24
|
+
ThemeProvider,
|
|
25
|
+
useRestyleTheme,
|
|
26
|
+
buildPair,
|
|
27
|
+
buildRestyleTheme,
|
|
28
|
+
buildRestyleThemeFromThemeColors,
|
|
29
|
+
restylePresetThemes,
|
|
30
|
+
type RestyleTheme,
|
|
31
|
+
type AppThemeColors,
|
|
32
|
+
type RestyleThemePair,
|
|
33
|
+
type SemanticColorsInput,
|
|
34
|
+
} from "./restyle";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* El Sendero Design System - Restyle Theme Provider Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Provides the correct Restyle theme (light/dark) based on the
|
|
5
|
+
* current design system mode.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* <RestyleThemeProviderWrapper>
|
|
9
|
+
* <YourApp />
|
|
10
|
+
* </RestyleThemeProviderWrapper>
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { ThemeProvider } from "@shopify/restyle";
|
|
14
|
+
import React, { ReactNode } from "react";
|
|
15
|
+
import { useColorScheme } from "react-native";
|
|
16
|
+
import { restyleDarkTheme, restyleLightTheme } from "./restyleTheme";
|
|
17
|
+
|
|
18
|
+
export interface RestyleThemeProviderWrapperProps {
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function RestyleThemeProviderWrapper({
|
|
23
|
+
children,
|
|
24
|
+
}: RestyleThemeProviderWrapperProps) {
|
|
25
|
+
const isDark = useColorScheme() === "dark";
|
|
26
|
+
return (
|
|
27
|
+
<ThemeProvider theme={isDark ? restyleDarkTheme : restyleLightTheme}>
|
|
28
|
+
{children}
|
|
29
|
+
</ThemeProvider>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* El Sendero Design System - Restyle Exports
|
|
3
|
+
*
|
|
4
|
+
* Restyle provides type-safe, prop-based styling for React Native.
|
|
5
|
+
* This module exports Restyle components and utilities configured with our design system.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // Basic usage
|
|
9
|
+
* import { RestyleTheme, ThemeProvider, restyleTheme } from '@/design-system/core/restyle';
|
|
10
|
+
*
|
|
11
|
+
* <ThemeProvider theme={restyleTheme}>
|
|
12
|
+
* <Box padding="lg" backgroundColor="surfacePrimary" borderRadius="md">
|
|
13
|
+
* <Text variant="headingLarge" color="textPrimary">
|
|
14
|
+
* Hello World
|
|
15
|
+
* </Text>
|
|
16
|
+
* </Box>
|
|
17
|
+
* </ThemeProvider>
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export { ThemeProvider } from "@shopify/restyle";
|
|
21
|
+
export {
|
|
22
|
+
restyleDarkTheme,
|
|
23
|
+
restyleLightTheme,
|
|
24
|
+
restyleTheme,
|
|
25
|
+
buildRestyleTheme,
|
|
26
|
+
buildRestyleThemeFromThemeColors,
|
|
27
|
+
type RestyleTheme,
|
|
28
|
+
type AppThemeColors,
|
|
29
|
+
type SemanticColorsInput,
|
|
30
|
+
} from "./restyleTheme";
|
|
31
|
+
|
|
32
|
+
export { useRestyleTheme } from "./useRestyleTheme";
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
buildPair,
|
|
36
|
+
restylePresetThemes,
|
|
37
|
+
type RestyleThemePair,
|
|
38
|
+
} from "./restylePresetRegistry";
|