@utilitywarehouse/hearth-react-native 0.23.0 → 0.25.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 (107) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-lint.log +13 -13
  3. package/CHANGELOG.md +77 -0
  4. package/build/components/DatePicker/DatePickerCalendar.js +4 -9
  5. package/build/components/Modal/Modal.js +5 -4
  6. package/build/components/Modal/Modal.props.d.ts +10 -4
  7. package/build/components/ProgressBar/ProgressBar.d.ts +6 -0
  8. package/build/components/ProgressBar/ProgressBar.js +35 -0
  9. package/build/components/ProgressBar/ProgressBar.props.d.ts +60 -0
  10. package/build/components/ProgressBar/ProgressBar.props.js +1 -0
  11. package/build/components/ProgressBar/ProgressBarCircular.d.ts +6 -0
  12. package/build/components/ProgressBar/ProgressBarCircular.js +115 -0
  13. package/build/components/ProgressBar/ProgressBarLinear.d.ts +6 -0
  14. package/build/components/ProgressBar/ProgressBarLinear.js +79 -0
  15. package/build/components/ProgressBar/index.d.ts +2 -0
  16. package/build/components/ProgressBar/index.js +1 -0
  17. package/build/components/TimePicker/TimePicker.d.ts +6 -0
  18. package/build/components/TimePicker/TimePicker.js +78 -0
  19. package/build/components/TimePicker/TimePicker.props.d.ts +45 -0
  20. package/build/components/TimePicker/TimePicker.props.js +1 -0
  21. package/build/components/TimePicker/TimePickerView.d.ts +12 -0
  22. package/build/components/TimePicker/TimePickerView.js +130 -0
  23. package/build/components/TimePicker/TimePickerWheel.d.ts +8 -0
  24. package/build/components/TimePicker/TimePickerWheel.js +78 -0
  25. package/build/components/{DatePicker/time-picker/wheel-web.d.ts → TimePicker/TimePickerWheel.web.d.ts} +4 -4
  26. package/build/components/TimePicker/TimePickerWheel.web.js +122 -0
  27. package/build/components/TimePicker/index.d.ts +6 -0
  28. package/build/components/TimePicker/index.js +3 -0
  29. package/build/components/TimePickerInput/TimePickerInput.d.ts +6 -0
  30. package/build/components/TimePickerInput/TimePickerInput.js +127 -0
  31. package/build/components/TimePickerInput/TimePickerInput.props.d.ts +52 -0
  32. package/build/components/TimePickerInput/TimePickerInput.props.js +1 -0
  33. package/build/components/TimePickerInput/TimePickerInputDoneButton.d.ts +8 -0
  34. package/build/components/TimePickerInput/TimePickerInputDoneButton.js +19 -0
  35. package/build/components/TimePickerInput/TimePickerInputDoneButton.web.d.ts +5 -0
  36. package/build/components/TimePickerInput/TimePickerInputDoneButton.web.js +5 -0
  37. package/build/components/TimePickerInput/index.d.ts +2 -0
  38. package/build/components/TimePickerInput/index.js +1 -0
  39. package/build/components/index.d.ts +3 -0
  40. package/build/components/index.js +3 -0
  41. package/docs/components/AllComponents.web.tsx +36 -0
  42. package/package.json +2 -1
  43. package/src/components/DatePicker/DatePickerCalendar.tsx +30 -13
  44. package/src/components/Modal/Modal.props.ts +13 -4
  45. package/src/components/Modal/Modal.stories.tsx +1 -1
  46. package/src/components/Modal/Modal.tsx +28 -11
  47. package/src/components/ProgressBar/ProgressBar.docs.mdx +90 -0
  48. package/src/components/ProgressBar/ProgressBar.figma.tsx +79 -0
  49. package/src/components/ProgressBar/ProgressBar.props.ts +60 -0
  50. package/src/components/ProgressBar/ProgressBar.stories.tsx +117 -0
  51. package/src/components/ProgressBar/ProgressBar.tsx +74 -0
  52. package/src/components/ProgressBar/ProgressBarCircular.tsx +181 -0
  53. package/src/components/ProgressBar/ProgressBarLinear.tsx +127 -0
  54. package/src/components/ProgressBar/index.ts +7 -0
  55. package/src/components/TimePicker/TimePicker.docs.mdx +84 -0
  56. package/src/components/TimePicker/TimePicker.figma.tsx +29 -0
  57. package/src/components/TimePicker/TimePicker.props.ts +45 -0
  58. package/src/components/TimePicker/TimePicker.stories.tsx +85 -0
  59. package/src/components/TimePicker/TimePicker.tsx +150 -0
  60. package/src/components/TimePicker/TimePickerView.tsx +216 -0
  61. package/src/components/TimePicker/TimePickerWheel.tsx +154 -0
  62. package/src/components/TimePicker/TimePickerWheel.web.tsx +217 -0
  63. package/src/components/TimePicker/index.ts +8 -0
  64. package/src/components/TimePickerInput/TimePickerInput.docs.mdx +135 -0
  65. package/src/components/TimePickerInput/TimePickerInput.figma.tsx +34 -0
  66. package/src/components/TimePickerInput/TimePickerInput.props.ts +55 -0
  67. package/src/components/TimePickerInput/TimePickerInput.stories.tsx +175 -0
  68. package/src/components/TimePickerInput/TimePickerInput.tsx +283 -0
  69. package/src/components/TimePickerInput/TimePickerInputDoneButton.tsx +42 -0
  70. package/src/components/TimePickerInput/TimePickerInputDoneButton.web.tsx +7 -0
  71. package/src/components/TimePickerInput/index.ts +2 -0
  72. package/src/components/index.ts +3 -0
  73. package/build/components/DatePicker/TimePicker.d.ts +0 -3
  74. package/build/components/DatePicker/TimePicker.js +0 -84
  75. package/build/components/DatePicker/time-picker/animated-math.d.ts +0 -4
  76. package/build/components/DatePicker/time-picker/animated-math.js +0 -19
  77. package/build/components/DatePicker/time-picker/period-native.d.ts +0 -6
  78. package/build/components/DatePicker/time-picker/period-native.js +0 -17
  79. package/build/components/DatePicker/time-picker/period-picker.d.ts +0 -6
  80. package/build/components/DatePicker/time-picker/period-picker.js +0 -10
  81. package/build/components/DatePicker/time-picker/period-web.d.ts +0 -6
  82. package/build/components/DatePicker/time-picker/period-web.js +0 -21
  83. package/build/components/DatePicker/time-picker/wheel-native.d.ts +0 -8
  84. package/build/components/DatePicker/time-picker/wheel-native.js +0 -19
  85. package/build/components/DatePicker/time-picker/wheel-picker/index.d.ts +0 -2
  86. package/build/components/DatePicker/time-picker/wheel-picker/index.js +0 -2
  87. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.d.ts +0 -16
  88. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.js +0 -97
  89. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.d.ts +0 -21
  90. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.js +0 -88
  91. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.d.ts +0 -23
  92. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.js +0 -21
  93. package/build/components/DatePicker/time-picker/wheel-web.js +0 -146
  94. package/build/components/DatePicker/time-picker/wheel.d.ts +0 -8
  95. package/build/components/DatePicker/time-picker/wheel.js +0 -10
  96. package/src/components/DatePicker/TimePicker.tsx +0 -141
  97. package/src/components/DatePicker/time-picker/animated-math.ts +0 -33
  98. package/src/components/DatePicker/time-picker/period-native.tsx +0 -34
  99. package/src/components/DatePicker/time-picker/period-picker.tsx +0 -16
  100. package/src/components/DatePicker/time-picker/period-web.tsx +0 -36
  101. package/src/components/DatePicker/time-picker/wheel-native.tsx +0 -37
  102. package/src/components/DatePicker/time-picker/wheel-picker/index.ts +0 -3
  103. package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.tsx +0 -132
  104. package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.ts +0 -22
  105. package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker.tsx +0 -200
  106. package/src/components/DatePicker/time-picker/wheel-web.tsx +0 -180
  107. package/src/components/DatePicker/time-picker/wheel.tsx +0 -18
@@ -0,0 +1,5 @@
1
+ const TimePickerInputDoneButton = () => {
2
+ return null;
3
+ };
4
+ TimePickerInputDoneButton.DisplayName = 'TimePickerInputDoneButton';
5
+ export default TimePickerInputDoneButton;
@@ -0,0 +1,2 @@
1
+ export { default as TimePickerInput } from './TimePickerInput';
2
+ export type { default as TimePickerInputProps } from './TimePickerInput.props';
@@ -0,0 +1 @@
1
+ export { default as TimePickerInput } from './TimePickerInput';
@@ -40,6 +40,7 @@ export * from './List';
40
40
  export * from './Menu';
41
41
  export * from './Modal';
42
42
  export * from './PillGroup';
43
+ export * from './ProgressBar';
43
44
  export * from './ProgressStepper';
44
45
  export * from './Radio';
45
46
  export * from './RadioCard';
@@ -51,6 +52,8 @@ export * from './Switch';
51
52
  export * from './Tabs';
52
53
  export * from './Textarea';
53
54
  export * from './ThemedImage';
55
+ export * from './TimePicker';
56
+ export * from './TimePickerInput';
54
57
  export * from './Toast';
55
58
  export * from './ToggleButtonCard';
56
59
  export * from './VerificationInput';
@@ -41,6 +41,7 @@ export * from './List';
41
41
  export * from './Menu';
42
42
  export * from './Modal';
43
43
  export * from './PillGroup';
44
+ export * from './ProgressBar';
44
45
  export * from './ProgressStepper';
45
46
  export * from './Radio';
46
47
  export * from './RadioCard';
@@ -52,6 +53,8 @@ export * from './Switch';
52
53
  export * from './Tabs';
53
54
  export * from './Textarea';
54
55
  export * from './ThemedImage';
56
+ export * from './TimePicker';
57
+ export * from './TimePickerInput';
55
58
  export * from './Toast';
56
59
  export * from './ToggleButtonCard';
57
60
  export * from './VerificationInput';
@@ -74,6 +74,7 @@ import {
74
74
  OL,
75
75
  Pill,
76
76
  PillGroup,
77
+ ProgressBar,
77
78
  ProgressStep,
78
79
  ProgressStepper,
79
80
  Radio,
@@ -91,6 +92,8 @@ import {
91
92
  TabsList,
92
93
  Textarea,
93
94
  ThemedImage,
95
+ TimePicker,
96
+ TimePickerInput,
94
97
  ToastItem,
95
98
  ToggleButtonCard,
96
99
  ToggleButtonCardGroup,
@@ -150,6 +153,11 @@ const AllComponents: React.FC = () => {
150
153
  const handleDatePickerOpenPress = useCallback(() => {
151
154
  datePickerRef.current?.present();
152
155
  }, []);
156
+ const [selectedTime, setSelectedTime] = useState<DateType>();
157
+ const timePickerRef = useRef<BottomSheetModal>(null);
158
+ const handleTimePickerOpenPress = useCallback(() => {
159
+ timePickerRef.current?.present();
160
+ }, []);
153
161
  useEffect(() => {
154
162
  if (bottomSheetRef.current) {
155
163
  setTimeout(() => {
@@ -380,6 +388,29 @@ const AllComponents: React.FC = () => {
380
388
  </BottomSheetModalProvider>
381
389
  </Center>
382
390
  </ComponentWrapper>
391
+ <ComponentWrapper name="Time Picker" link="/?path=/docs/components-time-picker--docs">
392
+ <Center flex={1}>
393
+ <Button onPress={handleTimePickerOpenPress}>Open Time Picker</Button>
394
+ <BottomSheetModalProvider>
395
+ <TimePicker
396
+ ref={timePickerRef}
397
+ date={selectedTime}
398
+ onChange={({ date }) => setSelectedTime(date)}
399
+ onCancel={() => setSelectedTime(undefined)}
400
+ />
401
+ </BottomSheetModalProvider>
402
+ </Center>
403
+ </ComponentWrapper>
404
+ <ComponentWrapper
405
+ name="Time Picker Input"
406
+ link="/?path=/docs/forms-time-picker-input--docs"
407
+ >
408
+ <Center flex={1} padding="200">
409
+ <BottomSheetModalProvider>
410
+ <TimePickerInput placeholder="HH:mm" />
411
+ </BottomSheetModalProvider>
412
+ </Center>
413
+ </ComponentWrapper>
383
414
  <ComponentWrapper
384
415
  name="Description List"
385
416
  link="/?path=/docs/components-description-list--docs"
@@ -663,6 +694,11 @@ const AllComponents: React.FC = () => {
663
694
  </PillGroup>
664
695
  </Center>
665
696
  </ComponentWrapper>
697
+ <ComponentWrapper name="Progress Bar" link="/?path=/docs/components-progress-bar--docs">
698
+ <Center flex={1} px="300">
699
+ <ProgressBar value={58} label="Order progress" />
700
+ </Center>
701
+ </ComponentWrapper>
666
702
  <ComponentWrapper
667
703
  name="Progress Stepper"
668
704
  link="/?path=/docs/components-progress-stepper--docs"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilitywarehouse/hearth-react-native",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "description": "Utility Warehouse React Native UI library",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -20,6 +20,7 @@
20
20
  "@gluestack-ui/spinner": "0.1.14",
21
21
  "@gluestack-ui/switch": "0.1.22",
22
22
  "@gluestack-ui/textarea": "0.1.23",
23
+ "@quidone/react-native-wheel-picker": "^1.6.1",
23
24
  "dayjs": "^1.11.13"
24
25
  },
25
26
  "devDependencies": {
@@ -1,30 +1,47 @@
1
- import { ReactNode } from 'react';
2
1
  import { View } from 'react-native';
3
2
  import { StyleSheet } from 'react-native-unistyles';
3
+ import TimePickerView from '../TimePicker/TimePickerView';
4
4
  import { useDatePickerContext } from './DatePicker.context';
5
5
  import Days from './DatePickerDays';
6
6
  import Footer from './DatePickerFooter';
7
7
  import Header from './DatePickerHeader';
8
8
  import Months from './DatePickerMonths';
9
9
  import Years from './DatePickerYears';
10
- import type { CalendarViews } from './enums';
11
- import TimePicker from './TimePicker';
12
-
13
- const CalendarView: Record<CalendarViews, ReactNode> = {
14
- year: <Years />,
15
- month: <Months />,
16
- day: <Days />,
17
- time: <TimePicker />,
18
- };
19
10
 
20
11
  const Calendar = () => {
21
- const { hideHeader, hideFooter, calendarView, containerHeight, navigationPosition } =
22
- useDatePickerContext();
12
+ const {
13
+ hideHeader,
14
+ hideFooter,
15
+ calendarView,
16
+ containerHeight,
17
+ navigationPosition,
18
+ currentDate,
19
+ onSelectDate,
20
+ timeZone,
21
+ use12Hours,
22
+ } = useDatePickerContext();
23
+
24
+ const calendarContent =
25
+ calendarView === 'year' ? (
26
+ <Years />
27
+ ) : calendarView === 'month' ? (
28
+ <Months />
29
+ ) : calendarView === 'time' ? (
30
+ <TimePickerView
31
+ currentDate={currentDate}
32
+ onSelectDate={onSelectDate}
33
+ timeZone={timeZone}
34
+ use12Hours={use12Hours}
35
+ containerHeight={containerHeight}
36
+ />
37
+ ) : (
38
+ <Days />
39
+ );
23
40
 
24
41
  return (
25
42
  <View style={[styles.container]} testID="calendar">
26
43
  {!hideHeader ? <Header navigationPosition={navigationPosition} /> : null}
27
- <View style={styles.containerInner(containerHeight)}>{CalendarView[calendarView]}</View>
44
+ <View style={styles.containerInner(containerHeight)}>{calendarContent}</View>
28
45
  {!hideFooter ? <Footer /> : null}
29
46
  </View>
30
47
  );
@@ -4,16 +4,14 @@ import { BottomSheetProps } from '../BottomSheet';
4
4
  import { ButtonWithoutChildrenProps } from '../Button/Button.props';
5
5
  import { UnstyledIconButtonProps } from '../UnstyledIconButton';
6
6
 
7
- interface ModalProps extends Omit<BottomSheetProps, 'children'> {
7
+ interface ModalPropsBase extends Omit<BottomSheetProps, 'children'> {
8
8
  loading?: boolean;
9
9
  image?: ReactNode;
10
10
  showCloseButton?: boolean;
11
11
  heading?: string;
12
12
  loadingHeading?: string;
13
13
  description?: string;
14
- inNavModal?: boolean;
15
14
  fullscreen?: boolean;
16
- stickyFooter?: boolean;
17
15
  children?: ViewProps['children'];
18
16
  onPressPrimaryButton?: () => void;
19
17
  primaryButtonText?: string;
@@ -25,7 +23,18 @@ interface ModalProps extends Omit<BottomSheetProps, 'children'> {
25
23
  primaryButtonProps?: Omit<ButtonWithoutChildrenProps, 'children'>;
26
24
  secondaryButtonProps?: Omit<ButtonWithoutChildrenProps, 'children'>;
27
25
  closeButtonProps?: Omit<UnstyledIconButtonProps, 'children'>;
28
- background?: 'default' | 'brand';
29
26
  }
30
27
 
28
+ type ModalProps =
29
+ | (ModalPropsBase & {
30
+ inNavModal?: false | undefined;
31
+ stickyFooter?: boolean;
32
+ background?: never;
33
+ })
34
+ | (ModalPropsBase & {
35
+ inNavModal: true;
36
+ stickyFooter?: never;
37
+ background?: 'default' | 'brand';
38
+ });
39
+
31
40
  export default ModalProps;
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react-vite';
1
+ import { Meta, StoryObj } from '@storybook/react-native';
2
2
  import { useRef } from 'react';
3
3
  import { ImageSourcePropType, Platform, View } from 'react-native';
4
4
  import { Modal, ModalImage } from '.';
@@ -59,6 +59,7 @@ const Modal = ({
59
59
  const theme = useTheme();
60
60
  const backgroundOpacity = useSharedValue(0);
61
61
  const pretendContentTranslateY = useSharedValue(20);
62
+ const isBrandBackground = background === 'brand';
62
63
 
63
64
  const triggerCloseAnimation = useCallback(() => {
64
65
  if (Platform.OS === 'android' && inNavModal) {
@@ -171,7 +172,7 @@ const Modal = ({
171
172
  noButtons,
172
173
  stickyFooter,
173
174
  showHandle: props.showHandle,
174
- background: background === 'brand' ? 'brand' : 'primary',
175
+ background: isBrandBackground ? 'brand' : 'primary',
175
176
  });
176
177
 
177
178
  const footer = (
@@ -180,7 +181,7 @@ const Modal = ({
180
181
  <Button
181
182
  onPress={handlePrimaryButtonPress}
182
183
  text={primaryButtonText}
183
- inverted={background === 'brand' && inNavModal}
184
+ inverted={isBrandBackground && inNavModal}
184
185
  {...primaryButtonProps}
185
186
  variant={(primaryButtonProps?.variant as 'solid') ?? 'solid'}
186
187
  colorScheme={(primaryButtonProps?.colorScheme as 'highlight') ?? 'highlight'}
@@ -190,7 +191,7 @@ const Modal = ({
190
191
  <Button
191
192
  onPress={handleSecondaryButtonPress}
192
193
  text={secondaryButtonText}
193
- inverted={background === 'brand' && inNavModal}
194
+ inverted={isBrandBackground && inNavModal}
194
195
  {...secondaryButtonProps}
195
196
  variant={(secondaryButtonProps?.variant as 'outline') ?? 'outline'}
196
197
  colorScheme={(secondaryButtonProps?.colorScheme as 'functional') ?? 'functional'}
@@ -209,8 +210,11 @@ const Modal = ({
209
210
  screenReaderFocusable
210
211
  ref={viewRef}
211
212
  >
212
- <Spinner size="lg" />
213
- <Heading size="lg" textAlign="center">
213
+ <Spinner
214
+ size="lg"
215
+ color={isBrandBackground && inNavModal ? theme.color.icon.inverted : undefined}
216
+ />
217
+ <Heading size="lg" textAlign="center" inverted={isBrandBackground && inNavModal}>
214
218
  {loadingHeading}
215
219
  </Heading>
216
220
  </View>
@@ -225,18 +229,22 @@ const Modal = ({
225
229
  <View style={styles.header}>
226
230
  <View style={styles.headerTextContent}>
227
231
  {heading && !image ? (
228
- <Heading size="lg" accessible>
232
+ <Heading size="lg" accessible inverted={isBrandBackground && inNavModal}>
229
233
  {heading}
230
234
  </Heading>
231
235
  ) : null}
232
- {description && !image ? <BodyText accessible>{description}</BodyText> : null}
236
+ {description && !image ? (
237
+ <BodyText accessible inverted={isBrandBackground && inNavModal}>
238
+ {description}
239
+ </BodyText>
240
+ ) : null}
233
241
  </View>
234
242
  {showCloseButton ? (
235
243
  <UnstyledIconButton
236
244
  icon={CloseMediumIcon}
237
245
  onPress={handleCloseButtonPress}
238
246
  accessibilityLabel="Close modal"
239
- inverted={background === 'brand' && inNavModal}
247
+ inverted={isBrandBackground && inNavModal}
240
248
  {...closeButtonProps}
241
249
  />
242
250
  ) : null}
@@ -246,12 +254,21 @@ const Modal = ({
246
254
  {image}
247
255
  <View style={styles.textContent}>
248
256
  {heading ? (
249
- <Heading size="lg" textAlign="center" accessible>
257
+ <Heading
258
+ size="lg"
259
+ textAlign="center"
260
+ accessible
261
+ inverted={isBrandBackground && inNavModal}
262
+ >
250
263
  {heading}
251
264
  </Heading>
252
265
  ) : null}
253
266
  {description ? (
254
- <BodyText textAlign="center" accessible>
267
+ <BodyText
268
+ textAlign="center"
269
+ accessible
270
+ inverted={isBrandBackground && inNavModal}
271
+ >
255
272
  {description}
256
273
  </BodyText>
257
274
  ) : null}
@@ -285,7 +302,7 @@ const Modal = ({
285
302
  <View
286
303
  style={{
287
304
  flex: 1,
288
- backgroundColor: theme.color.background[background === 'brand' ? 'brand' : 'primary'],
305
+ backgroundColor: theme.color.background[isBrandBackground ? 'brand' : 'primary'],
289
306
  }}
290
307
  >
291
308
  {Platform.OS === 'android' ? (
@@ -0,0 +1,90 @@
1
+ import { Canvas, Controls, Meta } from '@storybook/addon-docs/blocks';
2
+ import { Box, Center, ProgressBar } from '../..';
3
+ import { BackToTopButton, UsageWrap, ViewFigmaButton } from '../../../docs/components';
4
+ import * as Stories from './ProgressBar.stories';
5
+
6
+ <Meta title="Components / Progress Bar" />
7
+
8
+ <BackToTopButton />
9
+
10
+ <ViewFigmaButton url="https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=7849-5704&t=Jg2fPJPQNzOyspmQ-4" />
11
+ <ViewFigmaButton url="https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=7863-3977&t=Jg2fPJPQNzOyspmQ-4" />
12
+
13
+ # Progress Bar
14
+
15
+ Progress bars communicate task completion for linear flows and bounded operations. Use the linear variant for
16
+ inline layouts and the circular variant when space is tighter or when progress needs more emphasis.
17
+
18
+ - [Playground](#playground)
19
+ - [Usage](#usage)
20
+ - [Props](#props)
21
+ - [Variants](#variants)
22
+ - [Circular Sizes](#circular-sizes)
23
+ - [Examples](#examples)
24
+ - [Custom Value Labels](#custom-value-labels)
25
+
26
+ ## Playground
27
+
28
+ <Canvas of={Stories.Playground} />
29
+
30
+ <Controls of={Stories.Playground} />
31
+
32
+ ## Usage
33
+
34
+ <UsageWrap>
35
+ <Center>
36
+ <Box style={{ width: 260 }}>
37
+ <ProgressBar value={42} label="Uploading documents" />
38
+ </Box>
39
+ </Center>
40
+ </UsageWrap>
41
+
42
+ ```tsx
43
+ import { ProgressBar } from '@utilitywarehouse/hearth-react-native';
44
+
45
+ const MyComponent = () => <ProgressBar value={42} label="Uploading documents" />;
46
+ ```
47
+
48
+ ## Props
49
+
50
+ | Property | Type | Description | Default |
51
+ | ----------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------- |
52
+ | `variant` | `'linear' \| 'circular'` | The progress bar variant. | `linear` |
53
+ | `colorScheme` | `'default' \| 'success' \| 'danger'` | The color scheme for the progress indicator. | `default` |
54
+ | `size` | `'sm' \| 'md'` | Circular size. Only applies to the circular variant. | `md` |
55
+ | `value` | `number` | Current progress value. | |
56
+ | `min` | `number` | Minimum value. | `0` |
57
+ | `max` | `number` | Maximum value. | `100` |
58
+ | `label` | `string` | Accessible label for the progress bar. | |
59
+ | `hideLabel` | `boolean` | Visually hide the label and value text. | `false` |
60
+ | `formatValueText` | `(value: number, meta: { min: number; `<br />` max: number; percent: number }) => string` | Override the default percentage label. | |
61
+ | `aria-valuetext` | `string` | A human-readable text alternative for the current value. | |
62
+
63
+ ## Variants
64
+
65
+ <Canvas of={Stories.Variants} />
66
+
67
+ ## Circular Sizes
68
+
69
+ <Canvas of={Stories.CircularSizes} />
70
+
71
+ ## Examples
72
+
73
+ ### Custom Value Labels
74
+
75
+ Use `formatValueText` to show values that are not percentages, such as remaining data allowance.
76
+
77
+ <Canvas of={Stories.CustomValueLabels} />
78
+
79
+ ```tsx
80
+ import { ProgressBar } from '@utilitywarehouse/hearth-react-native';
81
+
82
+ const MyComponent = () => (
83
+ <ProgressBar
84
+ value={68}
85
+ max={100}
86
+ label="Data allowance"
87
+ formatValueText={(value, { max }) => `${max - value}GB remaining`}
88
+ />
89
+ );
90
+ ```
@@ -0,0 +1,79 @@
1
+ import figma from '@figma/code-connect';
2
+ import { ProgressBar } from '../';
3
+
4
+ figma.connect(
5
+ ProgressBar,
6
+ 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=7849-5704',
7
+ {
8
+ props: {
9
+ value: figma.enum('Progress', {
10
+ '0%': 0,
11
+ '10%': 10,
12
+ '20%': 20,
13
+ '30%': 30,
14
+ '40%': 40,
15
+ '50%': 50,
16
+ '60%': 60,
17
+ '70%': 70,
18
+ '80%': 80,
19
+ '90%': 90,
20
+ '100%': 100,
21
+ }),
22
+ colorScheme: figma.enum('Color Scheme', {
23
+ Default: 'default',
24
+ Success: 'success',
25
+ Danger: 'danger',
26
+ }),
27
+ label: figma.boolean('Label?', { true: figma.string('Label') }),
28
+ },
29
+ example: props => (
30
+ <ProgressBar
31
+ variant="linear"
32
+ value={props.value}
33
+ colorScheme={props.colorScheme}
34
+ label={props.label}
35
+ />
36
+ ),
37
+ }
38
+ );
39
+
40
+ figma.connect(
41
+ ProgressBar,
42
+ 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=7863-3977',
43
+ {
44
+ props: {
45
+ value: figma.enum('Progress', {
46
+ '0%': 0,
47
+ '10%': 10,
48
+ '20%': 20,
49
+ '30%': 30,
50
+ '40%': 40,
51
+ '50%': 50,
52
+ '60%': 60,
53
+ '70%': 70,
54
+ '80%': 80,
55
+ '90%': 90,
56
+ '100%': 100,
57
+ }),
58
+ colorScheme: figma.enum('Color Scheme', {
59
+ Default: 'default',
60
+ Success: 'success',
61
+ Danger: 'danger',
62
+ }),
63
+ size: figma.enum('Size', {
64
+ 'SM-80': 'sm',
65
+ 'MD-140': 'md',
66
+ }),
67
+ label: figma.boolean('Label?', { true: figma.string('Label') }),
68
+ },
69
+ example: props => (
70
+ <ProgressBar
71
+ variant="circular"
72
+ value={props.value}
73
+ colorScheme={props.colorScheme}
74
+ size={props.size}
75
+ label={props.label}
76
+ />
77
+ ),
78
+ }
79
+ );
@@ -0,0 +1,60 @@
1
+ import { ViewProps } from 'react-native';
2
+
3
+ export type ProgressBarVariant = 'linear' | 'circular';
4
+ export type ProgressBarColorScheme = 'default' | 'success' | 'danger';
5
+ export type ProgressBarSize = 'sm' | 'md';
6
+
7
+ export interface ProgressBarProps extends ViewProps {
8
+ variant?: ProgressBarVariant;
9
+ /**
10
+ * Set the visual appearance.
11
+ * @default 'default'
12
+ */
13
+ colorScheme?: ProgressBarColorScheme;
14
+ /**
15
+ * Sets the circular variant size. Does not affect the appearance of the linear variant.
16
+ * @default 'md'
17
+ */
18
+ size?: ProgressBarSize;
19
+ /**
20
+ * The current progress value.
21
+ */
22
+ value: number;
23
+ /**
24
+ * The minimum value.
25
+ * @default 0
26
+ */
27
+ min?: number;
28
+ /**
29
+ * The maximum value.
30
+ * @default 100
31
+ */
32
+ max?: number;
33
+ /**
34
+ * Required text label for the progress bar.
35
+ */
36
+ label: string;
37
+ /**
38
+ * Visually hide the label and value text.
39
+ */
40
+ hideLabel?: boolean;
41
+ /**
42
+ * Override the default percentage value label formatting.
43
+ */
44
+ formatValueText?: (value: number, meta: { min: number; max: number; percent: number }) => string;
45
+ /**
46
+ * A human-readable text alternative for the current value.
47
+ */
48
+ 'aria-valuetext'?: string;
49
+ }
50
+
51
+ export interface ProgressBarInternalProps {
52
+ percent: number;
53
+ label: string;
54
+ valueText: string;
55
+ hideLabel?: boolean;
56
+ colorScheme: ProgressBarColorScheme;
57
+ size: ProgressBarSize;
58
+ }
59
+
60
+ export default ProgressBarProps;