@utilitywarehouse/hearth-react-native 0.9.0 → 0.10.0

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 (75) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/CHANGELOG.md +8 -0
  4. package/build/components/PillGroup/Pill.d.ts +16 -0
  5. package/build/components/PillGroup/Pill.js +94 -0
  6. package/build/components/PillGroup/Pill.props.d.ts +10 -0
  7. package/build/components/PillGroup/Pill.props.js +1 -0
  8. package/build/components/PillGroup/PillGroup.context.d.ts +6 -0
  9. package/build/components/PillGroup/PillGroup.context.js +5 -0
  10. package/build/components/PillGroup/PillGroup.d.ts +5 -0
  11. package/build/components/PillGroup/PillGroup.js +34 -0
  12. package/build/components/PillGroup/PillGroup.props.d.ts +15 -0
  13. package/build/components/PillGroup/PillGroup.props.js +1 -0
  14. package/build/components/PillGroup/index.d.ts +4 -0
  15. package/build/components/PillGroup/index.js +2 -0
  16. package/build/components/Select/Select.js +2 -1
  17. package/build/components/Toast/Toast.context.d.ts +9 -0
  18. package/build/components/Toast/Toast.context.js +90 -0
  19. package/build/components/Toast/Toast.props.d.ts +29 -0
  20. package/build/components/Toast/Toast.props.js +1 -0
  21. package/build/components/Toast/ToastItem.d.ts +10 -0
  22. package/build/components/Toast/ToastItem.js +129 -0
  23. package/build/components/Toast/index.d.ts +3 -0
  24. package/build/components/Toast/index.js +2 -0
  25. package/build/components/index.d.ts +2 -0
  26. package/build/components/index.js +2 -0
  27. package/build/tokens/components/dark/checkbox.d.ts +3 -0
  28. package/build/tokens/components/dark/checkbox.js +3 -0
  29. package/build/tokens/components/dark/input.d.ts +6 -0
  30. package/build/tokens/components/dark/input.js +6 -0
  31. package/build/tokens/components/dark/radio.d.ts +3 -0
  32. package/build/tokens/components/dark/radio.js +3 -0
  33. package/build/tokens/components/dark/table.d.ts +2 -0
  34. package/build/tokens/components/dark/table.js +2 -0
  35. package/build/tokens/components/dark/toast.d.ts +6 -2
  36. package/build/tokens/components/dark/toast.js +6 -2
  37. package/build/tokens/components/light/checkbox.d.ts +3 -0
  38. package/build/tokens/components/light/checkbox.js +3 -0
  39. package/build/tokens/components/light/input.d.ts +6 -0
  40. package/build/tokens/components/light/input.js +6 -0
  41. package/build/tokens/components/light/radio.d.ts +3 -0
  42. package/build/tokens/components/light/radio.js +3 -0
  43. package/build/tokens/components/light/table.d.ts +2 -0
  44. package/build/tokens/components/light/table.js +2 -0
  45. package/build/tokens/components/light/toast.d.ts +6 -2
  46. package/build/tokens/components/light/toast.js +6 -2
  47. package/docs/assets/toast-ios.MP4 +0 -0
  48. package/docs/components/AllComponents.web.tsx +26 -0
  49. package/package.json +3 -3
  50. package/src/components/PillGroup/Pill.props.ts +13 -0
  51. package/src/components/PillGroup/Pill.tsx +120 -0
  52. package/src/components/PillGroup/PillGroup.context.tsx +12 -0
  53. package/src/components/PillGroup/PillGroup.docs.mdx +96 -0
  54. package/src/components/PillGroup/PillGroup.props.ts +22 -0
  55. package/src/components/PillGroup/PillGroup.stories.tsx +159 -0
  56. package/src/components/PillGroup/PillGroup.tsx +66 -0
  57. package/src/components/PillGroup/index.ts +4 -0
  58. package/src/components/Select/Select.tsx +2 -0
  59. package/src/components/Toast/Toast.context.tsx +118 -0
  60. package/src/components/Toast/Toast.docs.mdx +164 -0
  61. package/src/components/Toast/Toast.props.ts +33 -0
  62. package/src/components/Toast/Toast.stories.tsx +356 -0
  63. package/src/components/Toast/ToastItem.tsx +200 -0
  64. package/src/components/Toast/index.ts +3 -0
  65. package/src/components/index.ts +2 -0
  66. package/src/tokens/components/dark/checkbox.ts +3 -0
  67. package/src/tokens/components/dark/input.ts +6 -0
  68. package/src/tokens/components/dark/radio.ts +3 -0
  69. package/src/tokens/components/dark/table.ts +2 -0
  70. package/src/tokens/components/dark/toast.ts +6 -2
  71. package/src/tokens/components/light/checkbox.ts +3 -0
  72. package/src/tokens/components/light/input.ts +6 -0
  73. package/src/tokens/components/light/radio.ts +3 -0
  74. package/src/tokens/components/light/table.ts +2 -0
  75. package/src/tokens/components/light/toast.ts +6 -2
@@ -0,0 +1,356 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-native';
2
+ import {
3
+ InfoSmallIcon,
4
+ TickSmallIcon,
5
+ TrashSmallIcon,
6
+ WarningSmallIcon,
7
+ } from '@utilitywarehouse/hearth-react-native-icons';
8
+ import React from 'react';
9
+ import { Platform, View } from 'react-native';
10
+ import { Button } from '../Button';
11
+ import { ToastProvider, useToast } from './';
12
+
13
+ const meta: Meta = {
14
+ title: 'Stories / Toast',
15
+ argTypes: {},
16
+ };
17
+ export default meta;
18
+ type Story = StoryObj<typeof meta>;
19
+
20
+ const ViewWrap = ({ children }: { children: React.ReactNode }) => (
21
+ <View
22
+ style={
23
+ Platform.OS === 'web'
24
+ ? { width: 400, height: 400, position: 'relative', overflow: 'visible' }
25
+ : { flex: 1 }
26
+ }
27
+ >
28
+ <ToastProvider>{children}</ToastProvider>
29
+ </View>
30
+ );
31
+
32
+ export const Playground: Story = {
33
+ render: () => {
34
+ return (
35
+ <ViewWrap>
36
+ <PlaygroundDemo />
37
+ </ViewWrap>
38
+ );
39
+ },
40
+ };
41
+
42
+ const PlaygroundDemo = () => {
43
+ const { addToast } = useToast();
44
+
45
+ const showBasic = () => {
46
+ addToast({ text: 'This is a simple toast message' });
47
+ };
48
+
49
+ return (
50
+ <View style={{ gap: 12, padding: 16 }}>
51
+ <Button onPress={showBasic}>Show Toast</Button>
52
+ </View>
53
+ );
54
+ };
55
+
56
+ const BasicToastDemo = () => {
57
+ const { addToast } = useToast();
58
+
59
+ return (
60
+ <View style={{ gap: 12, padding: 16 }}>
61
+ <Button onPress={() => addToast({ text: 'Settings saved successfully' })}>
62
+ Show Basic Toast
63
+ </Button>
64
+ </View>
65
+ );
66
+ };
67
+
68
+ export const BasicToast: Story = {
69
+ render: () => (
70
+ <ViewWrap>
71
+ <BasicToastDemo />
72
+ </ViewWrap>
73
+ ),
74
+ };
75
+
76
+ const WithIconDemo = () => {
77
+ const { addToast } = useToast();
78
+
79
+ return (
80
+ <View style={{ gap: 12, padding: 16 }}>
81
+ <Button
82
+ onPress={() =>
83
+ addToast({
84
+ text: 'Changes saved',
85
+ icon: TickSmallIcon,
86
+ })
87
+ }
88
+ >
89
+ Show Success Toast
90
+ </Button>
91
+ <Button
92
+ onPress={() =>
93
+ addToast({
94
+ text: 'Important information',
95
+ icon: InfoSmallIcon,
96
+ })
97
+ }
98
+ >
99
+ Show Info Toast
100
+ </Button>
101
+ <Button
102
+ onPress={() =>
103
+ addToast({
104
+ text: 'Please review your input',
105
+ icon: WarningSmallIcon,
106
+ })
107
+ }
108
+ >
109
+ Show Warning Toast
110
+ </Button>
111
+ <Button
112
+ onPress={() =>
113
+ addToast({
114
+ text: 'Item deleted',
115
+ icon: TrashSmallIcon,
116
+ })
117
+ }
118
+ >
119
+ Show Destructive Toast
120
+ </Button>
121
+ </View>
122
+ );
123
+ };
124
+
125
+ export const WithIcon: Story = {
126
+ render: () => (
127
+ <ViewWrap>
128
+ <WithIconDemo />
129
+ </ViewWrap>
130
+ ),
131
+ };
132
+
133
+ const WithActionDemo = () => {
134
+ const { addToast } = useToast();
135
+
136
+ return (
137
+ <View style={{ gap: 12, padding: 16, flex: 1 }}>
138
+ <Button
139
+ onPress={() =>
140
+ addToast({
141
+ text: 'File uploaded successfully',
142
+ actionText: 'View file',
143
+ onPress: () => console.log('View clicked'),
144
+ })
145
+ }
146
+ >
147
+ Show Toast With Action
148
+ </Button>
149
+ <Button
150
+ onPress={() =>
151
+ addToast({
152
+ text: 'Changes saved',
153
+ icon: TickSmallIcon,
154
+ actionText: 'Undo',
155
+ onPress: () => console.log('Undo clicked'),
156
+ })
157
+ }
158
+ >
159
+ Show With Icon & Action
160
+ </Button>
161
+ </View>
162
+ );
163
+ };
164
+
165
+ export const WithAction: Story = {
166
+ render: () => (
167
+ <ViewWrap>
168
+ <WithActionDemo />
169
+ </ViewWrap>
170
+ ),
171
+ };
172
+
173
+ const CustomDurationDemo = () => {
174
+ const { addToast } = useToast();
175
+
176
+ return (
177
+ <View style={{ gap: 12, padding: 16 }}>
178
+ <Button
179
+ onPress={() =>
180
+ addToast({
181
+ text: 'Quick message (2 seconds)',
182
+ duration: 2000,
183
+ })
184
+ }
185
+ >
186
+ 2 Second Toast
187
+ </Button>
188
+ <Button
189
+ onPress={() =>
190
+ addToast({
191
+ text: 'Default duration (6 seconds)',
192
+ })
193
+ }
194
+ >
195
+ Default Duration
196
+ </Button>
197
+ <Button
198
+ onPress={() =>
199
+ addToast({
200
+ text: 'Long message (10 seconds)',
201
+ duration: 10000,
202
+ })
203
+ }
204
+ >
205
+ 10 Second Toast
206
+ </Button>
207
+ <Button
208
+ onPress={() =>
209
+ addToast({
210
+ text: 'Persistent (no auto-dismiss)',
211
+ duration: 0,
212
+ })
213
+ }
214
+ >
215
+ No Auto-Dismiss
216
+ </Button>
217
+ </View>
218
+ );
219
+ };
220
+
221
+ export const CustomDuration: Story = {
222
+ render: () => (
223
+ <ViewWrap>
224
+ <CustomDurationDemo />
225
+ </ViewWrap>
226
+ ),
227
+ };
228
+
229
+ const StackedToastsDemo = () => {
230
+ const { addToast } = useToast();
231
+
232
+ const showMultiple = () => {
233
+ addToast({ text: 'First toast', icon: TickSmallIcon });
234
+ setTimeout(() => {
235
+ addToast({ text: 'Second toast', icon: InfoSmallIcon });
236
+ }, 500);
237
+ setTimeout(() => {
238
+ addToast({ text: 'Third toast', icon: TickSmallIcon });
239
+ }, 1000);
240
+ };
241
+
242
+ return (
243
+ <View style={{ gap: 12, padding: 16 }}>
244
+ <Button onPress={showMultiple}>Show Multiple Toasts</Button>
245
+ <Button
246
+ onPress={() =>
247
+ addToast({
248
+ text: 'Another toast message',
249
+ })
250
+ }
251
+ >
252
+ Add Another
253
+ </Button>
254
+ </View>
255
+ );
256
+ };
257
+
258
+ export const StackedToasts: Story = {
259
+ render: () => (
260
+ <ViewWrap>
261
+ <StackedToastsDemo />
262
+ </ViewWrap>
263
+ ),
264
+ };
265
+
266
+ const ProgrammaticDismissDemo = () => {
267
+ const { addToast, removeToast } = useToast();
268
+ const [lastId, setLastId] = React.useState<string | null>(null);
269
+
270
+ const showToast = () => {
271
+ const id = addToast({
272
+ text: 'This toast can be dismissed programmatically',
273
+ duration: 0, // Don't auto-dismiss
274
+ });
275
+ setLastId(id);
276
+ };
277
+
278
+ const dismissLast = () => {
279
+ if (lastId) {
280
+ removeToast(lastId);
281
+ setLastId(null);
282
+ }
283
+ };
284
+
285
+ return (
286
+ <View style={{ gap: 12, padding: 16 }}>
287
+ <Button onPress={showToast}>Show Persistent Toast</Button>
288
+ <Button onPress={dismissLast} disabled={!lastId}>
289
+ Dismiss Last Toast
290
+ </Button>
291
+ </View>
292
+ );
293
+ };
294
+
295
+ export const ProgrammaticDismiss: Story = {
296
+ render: () => (
297
+ <ViewWrap>
298
+ <ProgrammaticDismissDemo />
299
+ </ViewWrap>
300
+ ),
301
+ };
302
+
303
+ const DismissOptionsDemo = () => {
304
+ const { addToast } = useToast();
305
+
306
+ return (
307
+ <View style={{ gap: 12, padding: 16 }}>
308
+ <Button
309
+ onPress={() =>
310
+ addToast({
311
+ text: 'Toast without dismiss button',
312
+ showDismissIcon: false,
313
+ duration: 3000,
314
+ })
315
+ }
316
+ >
317
+ Hide Dismiss Icon
318
+ </Button>
319
+ <Button
320
+ onPress={() =>
321
+ addToast({
322
+ text: 'Tap anywhere to dismiss',
323
+ dismissOnPress: true,
324
+ onPress: () => console.log('Toast pressed'),
325
+ actionText: 'Action',
326
+ duration: 0,
327
+ })
328
+ }
329
+ >
330
+ Dismiss On Press
331
+ </Button>
332
+ <Button
333
+ onPress={() =>
334
+ addToast({
335
+ text: 'No dismiss button, press to dismiss',
336
+ showDismissIcon: false,
337
+ dismissOnPress: true,
338
+ onPress: () => console.log('Toast pressed'),
339
+ actionText: 'Action',
340
+ duration: 0,
341
+ })
342
+ }
343
+ >
344
+ Both Options
345
+ </Button>
346
+ </View>
347
+ );
348
+ };
349
+
350
+ export const DismissOptions: Story = {
351
+ render: () => (
352
+ <ViewWrap>
353
+ <DismissOptionsDemo />
354
+ </ViewWrap>
355
+ ),
356
+ };
@@ -0,0 +1,200 @@
1
+ import { CloseSmallIcon } from '@utilitywarehouse/hearth-react-native-icons';
2
+ import { forwardRef, useEffect, useImperativeHandle } from 'react';
3
+ import { AccessibilityInfo, Platform, Pressable, View } from 'react-native';
4
+ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
5
+ import Animated, {
6
+ useAnimatedStyle,
7
+ useSharedValue,
8
+ withSpring,
9
+ withTiming,
10
+ } from 'react-native-reanimated';
11
+ import { StyleSheet, withUnistyles } from 'react-native-unistyles';
12
+ import { scheduleOnRN } from 'react-native-worklets';
13
+ import { BodyText } from '../BodyText';
14
+ import { Icon } from '../Icon';
15
+ import { Link } from '../Link';
16
+ import { UnstyledIconButton } from '../UnstyledIconButton';
17
+ import type { ToastInstance } from './Toast.props';
18
+
19
+ const AnimatedView = Platform.OS === 'web' ? withUnistyles(Animated.View) : Animated.View;
20
+
21
+ export interface ToastItemHandle {
22
+ dismiss: () => void;
23
+ }
24
+
25
+ interface Props {
26
+ toast: ToastInstance;
27
+ onClose: (id: string) => void;
28
+ }
29
+
30
+ const ToastItem = forwardRef<ToastItemHandle, Props>(({ toast, onClose }, ref) => {
31
+ const translateY = useSharedValue(30);
32
+ const opacity = useSharedValue(0);
33
+ const gestureTranslateY = useSharedValue(0);
34
+
35
+ useEffect(() => {
36
+ translateY.value = withTiming(0, { duration: 300 });
37
+ opacity.value = withTiming(1, { duration: 300 });
38
+
39
+ // Announce toast content to screen readers
40
+ // Use a slight delay to ensure iOS VoiceOver picks it up
41
+ const timer = setTimeout(() => {
42
+ const message = typeof toast.text === 'string' ? toast.text : 'Toast notification';
43
+ const announcement = toast.actionText ? `${message}, ${toast.actionText}` : message;
44
+ AccessibilityInfo.announceForAccessibility(announcement);
45
+ }, 100);
46
+
47
+ return () => clearTimeout(timer);
48
+ }, [toast.text, toast.actionText]);
49
+
50
+ const animatedStyle = useAnimatedStyle(() => ({
51
+ transform: [{ translateY: translateY.value + gestureTranslateY.value }],
52
+ opacity: opacity.value,
53
+ }));
54
+
55
+ const handleDismiss = (fromGesture = false) => {
56
+ 'worklet';
57
+ // Call onDismiss callback if provided
58
+ if (toast.onDismiss) {
59
+ scheduleOnRN(toast.onDismiss);
60
+ }
61
+ // animate out then call onClose
62
+ if (!fromGesture) {
63
+ gestureTranslateY.value = 0;
64
+ }
65
+ // Continue from current position and animate further down
66
+ translateY.value = withTiming(100, { duration: 250 });
67
+ opacity.value = withTiming(0, { duration: 250 }, finished => {
68
+ if (finished) scheduleOnRN(onClose, toast.id);
69
+ });
70
+ };
71
+
72
+ useImperativeHandle(ref, () => ({
73
+ dismiss: handleDismiss,
74
+ }));
75
+
76
+ const panGesture = Gesture.Pan()
77
+ .onUpdate(event => {
78
+ // only allow downward drag
79
+ if (event.translationY > 0) {
80
+ gestureTranslateY.value = event.translationY;
81
+ }
82
+ })
83
+ .onEnd(event => {
84
+ if (event.translationY > 30 || event.velocityY > 800) {
85
+ handleDismiss(true);
86
+ } else {
87
+ // spring back to original position
88
+ gestureTranslateY.value = withSpring(0, {
89
+ damping: 20,
90
+ stiffness: 300,
91
+ });
92
+ }
93
+ });
94
+
95
+ const IconComp = toast.icon;
96
+ const showDismissIcon = toast.showDismissIcon !== false; // default true
97
+ const dismissOnPress = toast.dismissOnPress === true; // default false
98
+
99
+ const handlePress = () => {
100
+ if (toast.onPress) {
101
+ toast.onPress();
102
+ if (dismissOnPress) {
103
+ handleDismiss(false);
104
+ }
105
+ }
106
+ };
107
+
108
+ const toastContent = (
109
+ <View style={styles.inner}>
110
+ <View style={styles.content}>
111
+ {IconComp ? (
112
+ <View style={styles.iconWrap}>
113
+ <Icon as={IconComp} style={styles.icon} />
114
+ </View>
115
+ ) : null}
116
+ <BodyText inverted>{toast.text}</BodyText>
117
+ </View>
118
+ {toast.actionText ? (
119
+ <Link onPress={handlePress} showIcon={false} inverted>
120
+ {toast.actionText}
121
+ </Link>
122
+ ) : null}
123
+
124
+ {showDismissIcon ? (
125
+ <View style={styles.actions}>
126
+ <UnstyledIconButton
127
+ icon={CloseSmallIcon}
128
+ accessibilityLabel="Dismiss"
129
+ inverted
130
+ onPress={() => handleDismiss(false)}
131
+ />
132
+ </View>
133
+ ) : null}
134
+ </View>
135
+ );
136
+
137
+ return (
138
+ <GestureDetector gesture={panGesture}>
139
+ <AnimatedView
140
+ style={[styles.toast, animatedStyle]}
141
+ {...(Platform.OS === 'ios' && {
142
+ accessible: true,
143
+ accessibilityRole: 'alert',
144
+ accessibilityLiveRegion: 'polite',
145
+ })}
146
+ importantForAccessibility={Platform.OS === 'android' ? 'no-hide-descendants' : undefined}
147
+ >
148
+ {toast.onPress ? (
149
+ <Pressable onPress={handlePress} style={styles.pressable}>
150
+ {toastContent}
151
+ </Pressable>
152
+ ) : (
153
+ toastContent
154
+ )}
155
+ </AnimatedView>
156
+ </GestureDetector>
157
+ );
158
+ });
159
+
160
+ ToastItem.displayName = 'ToastItem';
161
+
162
+ const styles = StyleSheet.create(theme => ({
163
+ toast: {
164
+ backgroundColor: theme.components.toast.backgroundColor,
165
+ borderRadius: theme.components.toast.borderRadius,
166
+ padding: theme.components.toast.padding,
167
+ width: '95%',
168
+ },
169
+ pressable: {
170
+ width: '100%',
171
+ },
172
+ inner: {
173
+ flexDirection: 'row',
174
+ alignItems: 'center',
175
+ width: '100%',
176
+ gap: theme.components.toast.gap,
177
+ },
178
+ iconWrap: {
179
+ width: 24,
180
+ height: 24,
181
+ justifyContent: 'center',
182
+ alignItems: 'center',
183
+ flexShrink: 0,
184
+ },
185
+ icon: {
186
+ color: theme.color.icon.inverted,
187
+ },
188
+ content: {
189
+ flex: 1,
190
+ gap: theme.components.toast.text.gap,
191
+ flexDirection: 'row',
192
+ alignItems: 'center',
193
+ minWidth: 0,
194
+ },
195
+ actions: {
196
+ flexShrink: 0,
197
+ },
198
+ }));
199
+
200
+ export default ToastItem;
@@ -0,0 +1,3 @@
1
+ export { ToastProvider, useToast, useToastContext } from './Toast.context';
2
+ export type { ToastInstance, ToastOptions } from './Toast.props';
3
+ export { default as ToastItem } from './ToastItem';
@@ -38,6 +38,7 @@ export * from './Link';
38
38
  export * from './List';
39
39
  export * from './Menu';
40
40
  export * from './Modal';
41
+ export * from './PillGroup';
41
42
  export * from './ProgressStepper';
42
43
  export * from './Radio';
43
44
  export * from './RadioCard';
@@ -49,6 +50,7 @@ export * from './Switch';
49
50
  export * from './Tabs';
50
51
  export * from './Textarea';
51
52
  export * from './ThemedImage';
53
+ export * from './Toast';
52
54
  export * from './ToggleButtonCard';
53
55
 
54
56
  export { FlatList, Image, KeyboardAvoidingView, ScrollView, SectionList, View } from 'react-native';
@@ -28,6 +28,9 @@ export default {
28
28
  gap: 8,
29
29
  group: {
30
30
  gap: 12,
31
+ heading: {
32
+ gap: 2,
33
+ },
31
34
  stack: {
32
35
  gap: 12,
33
36
  },
@@ -14,6 +14,12 @@ export default {
14
14
  gap: 8,
15
15
  },
16
16
  gap: 6,
17
+ heading: {
18
+ gap: 12,
19
+ text: {
20
+ gap: 0,
21
+ },
22
+ },
17
23
  height: 48,
18
24
  label: {
19
25
  gap: 6,
@@ -25,6 +25,9 @@ export default {
25
25
  gap: 8,
26
26
  group: {
27
27
  gap: 8,
28
+ heading: {
29
+ gap: 2,
30
+ },
28
31
  stack: {
29
32
  gap: 12,
30
33
  },
@@ -6,6 +6,7 @@ export default {
6
6
  borderRadius: 16,
7
7
  cell: {
8
8
  borderWidth: 1,
9
+ minHeight: 48,
9
10
  padding: 12,
10
11
  },
11
12
  emphasis: {
@@ -14,6 +15,7 @@ export default {
14
15
  headerCell: {
15
16
  borderWidth: 2,
16
17
  gap: 8,
18
+ height: 56,
17
19
  paddingHorizontal: 12,
18
20
  paddingVertical: 16,
19
21
  },
@@ -5,9 +5,13 @@
5
5
  export default {
6
6
  backgroundColor: '#3f3f3f',
7
7
  borderRadius: 8,
8
- gapHorizontal: 16,
8
+ bottomPosition: 32,
9
+ gap: 16,
9
10
  padding: 14,
10
11
  stack: {
11
- gapHorizontal: 8,
12
+ gap: 12,
13
+ },
14
+ text: {
15
+ gap: 8,
12
16
  },
13
17
  } as const;
@@ -28,6 +28,9 @@ export default {
28
28
  gap: 12,
29
29
  group: {
30
30
  gap: 6,
31
+ heading: {
32
+ gap: 2,
33
+ },
31
34
  stack: {
32
35
  gap: 12,
33
36
  },
@@ -14,6 +14,12 @@ export default {
14
14
  gap: 8,
15
15
  },
16
16
  gap: 6,
17
+ heading: {
18
+ gap: 12,
19
+ text: {
20
+ gap: 2,
21
+ },
22
+ },
17
23
  height: 48,
18
24
  label: {
19
25
  gap: 2,
@@ -25,6 +25,9 @@ export default {
25
25
  gap: 8,
26
26
  group: {
27
27
  gap: 12,
28
+ heading: {
29
+ gap: 2,
30
+ },
28
31
  stack: {
29
32
  gap: 12,
30
33
  },
@@ -6,6 +6,7 @@ export default {
6
6
  borderRadius: 16,
7
7
  cell: {
8
8
  borderWidth: 1,
9
+ minHeight: 48,
9
10
  padding: 12,
10
11
  },
11
12
  emphasis: {
@@ -14,6 +15,7 @@ export default {
14
15
  headerCell: {
15
16
  borderWidth: 2,
16
17
  gap: 8,
18
+ height: 56,
17
19
  paddingHorizontal: 12,
18
20
  paddingVertical: 16,
19
21
  },
@@ -5,9 +5,13 @@
5
5
  export default {
6
6
  backgroundColor: '#101010',
7
7
  borderRadius: 8,
8
- gapHorizontal: 16,
8
+ bottomPosition: 32,
9
+ gap: 16,
9
10
  padding: 14,
10
11
  stack: {
11
- gapHorizontal: 8,
12
+ gap: 12,
13
+ },
14
+ text: {
15
+ gap: 8,
12
16
  },
13
17
  } as const;