@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,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
|
+
}
|