jfs-components 0.0.73 → 0.0.77

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 (134) hide show
  1. package/CHANGELOG.md +115 -6
  2. package/lib/commonjs/components/AccountCard/AccountCard.js +247 -0
  3. package/lib/commonjs/components/ActionFooter/ActionFooter.js +147 -82
  4. package/lib/commonjs/components/AppBar/AppBar.js +17 -11
  5. package/lib/commonjs/components/Avatar/Avatar.js +20 -0
  6. package/lib/commonjs/components/Badge/Badge.js +23 -0
  7. package/lib/commonjs/components/Button/Button.js +37 -0
  8. package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +18 -2
  9. package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +40 -25
  10. package/lib/commonjs/components/Dropdown/Dropdown.js +214 -0
  11. package/lib/commonjs/components/DropdownInput/DropdownInput.js +542 -0
  12. package/lib/commonjs/components/FormField/FormField.js +328 -178
  13. package/lib/commonjs/components/IconButton/IconButton.js +20 -0
  14. package/lib/commonjs/components/Image/Image.js +26 -1
  15. package/lib/commonjs/components/LottieIntroBlock/LottieIntroBlock.js +150 -0
  16. package/lib/commonjs/components/LottiePlayer/LottiePlayer.js +116 -0
  17. package/lib/commonjs/components/LottiePlayer/LottiePlayer.web.js +82 -0
  18. package/lib/commonjs/components/LottiePlayer/loadNativeLottieView.js +74 -0
  19. package/lib/commonjs/components/LottiePlayer/loadWebLottieView.js +50 -0
  20. package/lib/commonjs/components/PageHero/PageHero.js +189 -0
  21. package/lib/commonjs/components/PoweredByLabel/PoweredByLabel.js +135 -0
  22. package/lib/commonjs/components/PoweredByLabel/finvu.png +0 -0
  23. package/lib/commonjs/components/RechargeCard/RechargeCard.js +32 -17
  24. package/lib/commonjs/components/Text/Text.js +40 -3
  25. package/lib/commonjs/components/Tooltip/Tooltip.js +34 -27
  26. package/lib/commonjs/components/index.js +67 -0
  27. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  28. package/lib/commonjs/icons/Icon.js +16 -0
  29. package/lib/commonjs/icons/registry.js +1 -1
  30. package/lib/commonjs/index.js +12 -0
  31. package/lib/commonjs/skeleton/Skeleton.js +234 -0
  32. package/lib/commonjs/skeleton/SkeletonGroup.js +140 -0
  33. package/lib/commonjs/skeleton/index.js +58 -0
  34. package/lib/commonjs/skeleton/shimmer-tokens.js +189 -0
  35. package/lib/commonjs/skeleton/useReducedMotion.js +64 -0
  36. package/lib/module/components/AccountCard/AccountCard.js +241 -0
  37. package/lib/module/components/ActionFooter/ActionFooter.js +146 -82
  38. package/lib/module/components/AppBar/AppBar.js +17 -11
  39. package/lib/module/components/Avatar/Avatar.js +19 -0
  40. package/lib/module/components/Badge/Badge.js +23 -0
  41. package/lib/module/components/Button/Button.js +37 -0
  42. package/lib/module/components/CardBankAccount/CardBankAccount.js +17 -2
  43. package/lib/module/components/CheckboxItem/CheckboxItem.js +41 -26
  44. package/lib/module/components/Dropdown/Dropdown.js +206 -0
  45. package/lib/module/components/DropdownInput/DropdownInput.js +536 -0
  46. package/lib/module/components/FormField/FormField.js +330 -180
  47. package/lib/module/components/IconButton/IconButton.js +20 -0
  48. package/lib/module/components/Image/Image.js +25 -1
  49. package/lib/module/components/LottieIntroBlock/LottieIntroBlock.js +144 -0
  50. package/lib/module/components/LottiePlayer/LottiePlayer.js +111 -0
  51. package/lib/module/components/LottiePlayer/LottiePlayer.web.js +77 -0
  52. package/lib/module/components/LottiePlayer/loadNativeLottieView.js +69 -0
  53. package/lib/module/components/LottiePlayer/loadWebLottieView.js +45 -0
  54. package/lib/module/components/PageHero/PageHero.js +183 -0
  55. package/lib/module/components/PoweredByLabel/PoweredByLabel.js +130 -0
  56. package/lib/module/components/PoweredByLabel/finvu.png +0 -0
  57. package/lib/module/components/RechargeCard/RechargeCard.js +33 -17
  58. package/lib/module/components/Text/Text.js +40 -3
  59. package/lib/module/components/Tooltip/Tooltip.js +34 -27
  60. package/lib/module/components/index.js +8 -1
  61. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  62. package/lib/module/icons/Icon.js +16 -0
  63. package/lib/module/icons/registry.js +1 -1
  64. package/lib/module/index.js +2 -1
  65. package/lib/module/skeleton/Skeleton.js +229 -0
  66. package/lib/module/skeleton/SkeletonGroup.js +133 -0
  67. package/lib/module/skeleton/index.js +6 -0
  68. package/lib/module/skeleton/shimmer-tokens.js +181 -0
  69. package/lib/module/skeleton/useReducedMotion.js +61 -0
  70. package/lib/typescript/src/components/AccountCard/AccountCard.d.ts +81 -0
  71. package/lib/typescript/src/components/ActionFooter/ActionFooter.d.ts +26 -21
  72. package/lib/typescript/src/components/Avatar/Avatar.d.ts +7 -1
  73. package/lib/typescript/src/components/Badge/Badge.d.ts +7 -1
  74. package/lib/typescript/src/components/Button/Button.d.ts +8 -1
  75. package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +9 -2
  76. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +18 -2
  77. package/lib/typescript/src/components/Dropdown/Dropdown.d.ts +62 -0
  78. package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +107 -0
  79. package/lib/typescript/src/components/FormField/FormField.d.ts +76 -19
  80. package/lib/typescript/src/components/IconButton/IconButton.d.ts +7 -1
  81. package/lib/typescript/src/components/Image/Image.d.ts +8 -1
  82. package/lib/typescript/src/components/LottieIntroBlock/LottieIntroBlock.d.ts +58 -0
  83. package/lib/typescript/src/components/LottiePlayer/LottiePlayer.d.ts +85 -0
  84. package/lib/typescript/src/components/LottiePlayer/LottiePlayer.web.d.ts +28 -0
  85. package/lib/typescript/src/components/LottiePlayer/loadNativeLottieView.d.ts +11 -0
  86. package/lib/typescript/src/components/LottiePlayer/loadWebLottieView.d.ts +11 -0
  87. package/lib/typescript/src/components/PageHero/PageHero.d.ts +79 -0
  88. package/lib/typescript/src/components/PoweredByLabel/PoweredByLabel.d.ts +70 -0
  89. package/lib/typescript/src/components/Text/Text.d.ts +31 -2
  90. package/lib/typescript/src/components/Tooltip/Tooltip.d.ts +13 -2
  91. package/lib/typescript/src/components/index.d.ts +8 -1
  92. package/lib/typescript/src/icons/Icon.d.ts +7 -1
  93. package/lib/typescript/src/icons/registry.d.ts +1 -1
  94. package/lib/typescript/src/index.d.ts +1 -0
  95. package/lib/typescript/src/skeleton/Skeleton.d.ts +60 -0
  96. package/lib/typescript/src/skeleton/SkeletonGroup.d.ts +78 -0
  97. package/lib/typescript/src/skeleton/index.d.ts +5 -0
  98. package/lib/typescript/src/skeleton/shimmer-tokens.d.ts +160 -0
  99. package/lib/typescript/src/skeleton/useReducedMotion.d.ts +15 -0
  100. package/package.json +11 -3
  101. package/src/components/AccountCard/AccountCard.tsx +376 -0
  102. package/src/components/ActionFooter/ActionFooter.tsx +152 -86
  103. package/src/components/AppBar/AppBar.tsx +25 -14
  104. package/src/components/Avatar/Avatar.tsx +26 -0
  105. package/src/components/Badge/Badge.tsx +27 -0
  106. package/src/components/Button/Button.tsx +40 -0
  107. package/src/components/CardBankAccount/CardBankAccount.tsx +29 -3
  108. package/src/components/CheckboxItem/CheckboxItem.tsx +65 -30
  109. package/src/components/Dropdown/Dropdown.tsx +331 -0
  110. package/src/components/DropdownInput/DropdownInput.tsx +819 -0
  111. package/src/components/FormField/FormField.tsx +542 -215
  112. package/src/components/IconButton/IconButton.tsx +27 -0
  113. package/src/components/Image/Image.tsx +25 -0
  114. package/src/components/LottieIntroBlock/LottieIntroBlock.tsx +202 -0
  115. package/src/components/LottiePlayer/LottiePlayer.tsx +145 -0
  116. package/src/components/LottiePlayer/LottiePlayer.web.tsx +94 -0
  117. package/src/components/LottiePlayer/loadNativeLottieView.tsx +87 -0
  118. package/src/components/LottiePlayer/loadWebLottieView.tsx +64 -0
  119. package/src/components/PageHero/PageHero.tsx +257 -0
  120. package/src/components/PoweredByLabel/PoweredByLabel.tsx +221 -0
  121. package/src/components/PoweredByLabel/finvu.png +0 -0
  122. package/src/components/RechargeCard/RechargeCard.tsx +32 -24
  123. package/src/components/Text/Text.tsx +78 -3
  124. package/src/components/Tooltip/Tooltip.tsx +50 -25
  125. package/src/components/index.ts +16 -1
  126. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  127. package/src/icons/Icon.tsx +17 -0
  128. package/src/icons/registry.ts +1 -1
  129. package/src/index.ts +1 -0
  130. package/src/skeleton/Skeleton.tsx +298 -0
  131. package/src/skeleton/SkeletonGroup.tsx +193 -0
  132. package/src/skeleton/index.ts +10 -0
  133. package/src/skeleton/shimmer-tokens.ts +221 -0
  134. package/src/skeleton/useReducedMotion.ts +72 -0
@@ -2,10 +2,21 @@ import React from 'react'
2
2
  import { Text as RNText, type TextStyle, type StyleProp } from 'react-native'
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
4
  import { EMPTY_MODES } from '../../utils/react-utils'
5
+ import Skeleton from '../../skeleton/Skeleton'
6
+ import { useSkeleton } from '../../skeleton/SkeletonGroup'
5
7
 
6
8
  export type TextProps = {
7
- /** The text content to display. */
9
+ /**
10
+ * The text content to display. You may also pass content as JSX children
11
+ * (e.g. `<Text>Hello</Text>`) — when both are provided, `children` wins.
12
+ */
8
13
  text?: string
14
+ /**
15
+ * Child nodes (string, number, or nested <Text>/<RNText> elements). This
16
+ * mirrors the standard React Native `<Text>` API so the component is a
17
+ * near-drop-in replacement.
18
+ */
19
+ children?: React.ReactNode
9
20
  /** Horizontal alignment of the text. */
10
21
  textAlign?: 'Left' | 'Center'
11
22
  /** Modes configuration for design token resolution. */
@@ -14,6 +25,25 @@ export type TextProps = {
14
25
  style?: StyleProp<TextStyle>
15
26
  /** Number of lines to limit the text to. */
16
27
  numberOfLines?: number
28
+ /**
29
+ * Explicit per-instance loading override. When `true`, this `Text` renders
30
+ * a skeleton placeholder regardless of any surrounding `<SkeletonGroup>`.
31
+ * When `false`, the surrounding group is ignored for this instance. When
32
+ * omitted, the surrounding group's `loading` flag wins.
33
+ */
34
+ loading?: boolean
35
+ /**
36
+ * Optional width used while the skeleton is showing. Numbers are dp;
37
+ * `'100%'` (etc.) is a valid RN dimension. Defaults to a character-count
38
+ * heuristic based on the resolved font size and the supplied content.
39
+ */
40
+ skeletonWidth?: number | `${number}%`
41
+ /**
42
+ * Optional explicit line count for the skeleton placeholder. Defaults to
43
+ * `numberOfLines ?? 1`. Useful when `numberOfLines` is intentionally
44
+ * unbounded but you want a sensible multi-line placeholder.
45
+ */
46
+ skeletonLines?: number
17
47
  }
18
48
 
19
49
  const TEXT_ALIGN_MAP: Record<NonNullable<TextProps['textAlign']>, TextStyle['textAlign']> = {
@@ -22,11 +52,15 @@ const TEXT_ALIGN_MAP: Record<NonNullable<TextProps['textAlign']>, TextStyle['tex
22
52
  }
23
53
 
24
54
  function Text({
25
- text = 'Korem ipsum ',
55
+ text,
56
+ children,
26
57
  textAlign = 'Left',
27
58
  modes = EMPTY_MODES,
28
59
  style,
29
60
  numberOfLines,
61
+ loading,
62
+ skeletonWidth,
63
+ skeletonLines,
30
64
  }: TextProps) {
31
65
  const foreground = getVariableByName('text/foreground', modes) ?? '#000000'
32
66
  const fontFamily = getVariableByName('text/fontFamily', modes) ?? 'JioType'
@@ -35,6 +69,36 @@ function Text({
35
69
  const lineHeight = getVariableByName('text/lineHeight', modes) ?? 20
36
70
  const letterSpacing = getVariableByName('text/letterSpacing', modes) ?? -0.5
37
71
 
72
+ // Skeleton short-circuit. The hook is always called (stable order); the
73
+ // surrounding group's `active` flag is the default, but an explicit
74
+ // `loading` prop overrides both directions.
75
+ const { active: groupActive } = useSkeleton()
76
+ const isLoading = loading ?? groupActive
77
+ if (isLoading) {
78
+ const resolvedFontSize = fontSize as number
79
+ const resolvedLineHeight = lineHeight as number
80
+ const lines = Math.max(1, skeletonLines ?? numberOfLines ?? 1)
81
+ // Heuristic width based on the actual content length so the placeholder
82
+ // visually matches what's about to load. Capped to a reasonable lower
83
+ // bound so very short labels still produce a visible block.
84
+ const contentLength =
85
+ typeof children === 'string'
86
+ ? children.length
87
+ : typeof text === 'string'
88
+ ? text.length
89
+ : 12
90
+ const charWidth = resolvedFontSize * 0.55
91
+ const computedWidth = Math.max(charWidth * 4, contentLength * charWidth)
92
+ return (
93
+ <Skeleton
94
+ kind="text"
95
+ width={skeletonWidth ?? computedWidth}
96
+ height={resolvedLineHeight * lines}
97
+ modes={modes}
98
+ />
99
+ )
100
+ }
101
+
38
102
  const textStyle: TextStyle = {
39
103
  color: foreground as string,
40
104
  fontFamily: fontFamily as string,
@@ -45,12 +109,23 @@ function Text({
45
109
  textAlign: TEXT_ALIGN_MAP[textAlign],
46
110
  }
47
111
 
112
+ // Prefer JSX children when present, otherwise fall back to the `text` prop.
113
+ // Keep the storybook placeholder as a last resort so the Default story
114
+ // still renders something visible when no content is supplied via either
115
+ // route.
116
+ const content =
117
+ children !== undefined && children !== null && children !== false
118
+ ? children
119
+ : text !== undefined
120
+ ? text
121
+ : 'Korem ipsum '
122
+
48
123
  return (
49
124
  <RNText
50
125
  style={[textStyle, style]}
51
126
  numberOfLines={numberOfLines}
52
127
  >
53
- {text}
128
+ {content}
54
129
  </RNText>
55
130
  )
56
131
  }
@@ -238,9 +238,25 @@ export function TooltipTrigger({ children, asChild, ...props }: TooltipTriggerPr
238
238
  export type TooltipContentProps = {
239
239
  children: ReactNode
240
240
  sideOffset?: number
241
+ /**
242
+ * Vertical spacing between slot children, in pixels.
243
+ * The content area acts as a vertical slot: any children passed in
244
+ * (text, icons, custom views, etc.) are stacked top-to-bottom with this gap.
245
+ */
246
+ gap?: number
247
+ /**
248
+ * Cross-axis alignment of slot children.
249
+ * Defaults to `flex-start` so multi-line/multi-element content lines up on the left.
250
+ */
251
+ alignItems?: ViewStyle['alignItems']
241
252
  }
242
253
 
243
- export function TooltipContent({ children, sideOffset = 4 }: TooltipContentProps) {
254
+ export function TooltipContent({
255
+ children,
256
+ sideOffset = 4,
257
+ gap = 4,
258
+ alignItems = 'flex-start',
259
+ }: TooltipContentProps) {
244
260
  const { isVisible, hide, triggerRect, setContentSize, contentSize, modes, placement: preferredPlacement } = useTooltipContext()
245
261
  const insets = useSafeAreaInsets()
246
262
  const { width: windowWidth, height: windowHeight } = Dimensions.get('window')
@@ -467,6 +483,37 @@ export function TooltipContent({ children, sideOffset = 4 }: TooltipContentProps
467
483
  paddingVertical: paddingV,
468
484
  }
469
485
 
486
+ // Vertical slot wrapper: stack arbitrary children top-to-bottom with a gap.
487
+ // Raw <Text> children still get auto-styled with the tooltip label tokens
488
+ // so the simple <TooltipContent><Text>label</Text></TooltipContent> usage
489
+ // keeps working without any changes.
490
+ const slotStyle: ViewStyle = {
491
+ flexDirection: 'column',
492
+ alignItems,
493
+ gap,
494
+ }
495
+
496
+ const renderSlotChildren = () => {
497
+ if (typeof children === 'string') {
498
+ return <Text style={textStyle}>{children}</Text>
499
+ }
500
+ return (
501
+ <View style={slotStyle}>
502
+ {React.Children.map(children, (child) => {
503
+ if (
504
+ React.isValidElement(child) &&
505
+ (child.type === Text || (child.type as any).displayName === 'Text')
506
+ ) {
507
+ return React.cloneElement(child, {
508
+ style: [textStyle, (child.props as any).style],
509
+ } as any)
510
+ }
511
+ return child
512
+ })}
513
+ </View>
514
+ )
515
+ }
516
+
470
517
  if (!hasMeasured) {
471
518
  return (
472
519
  <Modal transparent visible={isVisible} animationType="fade">
@@ -475,18 +522,7 @@ export function TooltipContent({ children, sideOffset = 4 }: TooltipContentProps
475
522
  style={measureStyle}
476
523
  onLayout={(e) => setContentSize(e.nativeEvent.layout)}
477
524
  >
478
- {typeof children === 'string' ? (
479
- <Text style={textStyle}>{children}</Text>
480
- ) : (
481
- <View>
482
- {React.Children.map(children, child => {
483
- if (React.isValidElement(child) && (child.type === Text || (child.type as any).displayName === 'Text')) {
484
- return React.cloneElement(child, { style: [textStyle, (child.props as any).style] } as any)
485
- }
486
- return child
487
- })}
488
- </View>
489
- )}
525
+ {renderSlotChildren()}
490
526
  </View>
491
527
  </View>
492
528
  </Modal>
@@ -519,18 +555,7 @@ export function TooltipContent({ children, sideOffset = 4 }: TooltipContentProps
519
555
  }
520
556
  ]}
521
557
  >
522
- {typeof children === 'string' ? (
523
- <Text style={textStyle}>{children}</Text>
524
- ) : (
525
- <View>
526
- {React.Children.map(children, child => {
527
- if (React.isValidElement(child) && (child.type === Text || (child.type as any).displayName === 'Text')) {
528
- return React.cloneElement(child, { style: [textStyle, (child.props as any).style] } as any)
529
- }
530
- return child
531
- })}
532
- </View>
533
- )}
558
+ {renderSlotChildren()}
534
559
 
535
560
  {/* Arrow */}
536
561
  {/* Render different arrow based on axis to avoid rotation gap issues */}
@@ -1,3 +1,4 @@
1
+ export { default as AccountCard, type AccountCardProps, type AccountCardState } from './AccountCard/AccountCard';
1
2
  export { default as ActionFooter, type ActionFooterProps } from './ActionFooter/ActionFooter';
2
3
  export { default as AppBar } from './AppBar/AppBar';
3
4
  export { default as Avatar, type AvatarProps } from './Avatar/Avatar';
@@ -21,6 +22,8 @@ export { default as CardInsight, type CardInsightProps } from './CardInsight/Car
21
22
  export { default as Disclaimer } from './Disclaimer/Disclaimer';
22
23
  export { default as Divider, type DividerProps, type DividerDirection } from './Divider/Divider';
23
24
  export { default as Drawer } from './Drawer/Drawer';
25
+ export { default as Dropdown, DropdownItem, type DropdownProps, type DropdownItemProps } from './Dropdown/Dropdown';
26
+ export { default as DropdownInput, type DropdownInputProps, type DropdownInputOption, type DropdownInputOptionValue } from './DropdownInput/DropdownInput';
24
27
  export { default as CardCTA, type CardCTAProps, type CardCTAType } from './CardCTA/CardCTA'
25
28
  export { default as DebitCard, type DebitCardProps } from './DebitCard/DebitCard';
26
29
  export { default as FilterBar } from './FilterBar/FilterBar';
@@ -43,6 +46,8 @@ export { default as LazyList } from './LazyList/LazyList';
43
46
  export { default as LinearMeter, type LinearMeterProps } from './LinearMeter/LinearMeter';
44
47
  export { default as LinearProgress, type LinearProgressProps } from './LinearProgress/LinearProgress';
45
48
  export { default as ListGroup } from './ListGroup/ListGroup';
49
+ export { default as LottieIntroBlock, type LottieIntroBlockProps } from './LottieIntroBlock/LottieIntroBlock';
50
+ export { default as LottiePlayer, type LottiePlayerProps, type LottieAnimationSource } from './LottiePlayer/LottiePlayer';
46
51
  export { default as ListItem } from './ListItem/ListItem';
47
52
  export { default as MediaCard, type MediaCardProps } from './MediaCard/MediaCard';
48
53
  export { default as MerchantProfile, type MerchantProfileProps } from './MerchantProfile/MerchantProfile';
@@ -61,7 +66,15 @@ export { StepLabel } from './Stepper/StepLabel';
61
66
  export { default as TextInput } from './TextInput/TextInput';
62
67
  export { default as StatusHero, type StatusHeroProps } from './StatusHero/StatusHero';
63
68
  export { default as ThreadHero, type ThreadHeroProps } from './ThreadHero/ThreadHero';
64
- export { Tooltip } from './Tooltip/Tooltip';
69
+ export {
70
+ Tooltip,
71
+ TooltipTrigger,
72
+ TooltipContent,
73
+ type TooltipProps,
74
+ type TooltipTriggerProps,
75
+ type TooltipContentProps,
76
+ type Placement as TooltipPlacement,
77
+ } from './Tooltip/Tooltip';
65
78
 
66
79
  export { default as TransactionDetails } from './TransactionDetails/TransactionDetails';
67
80
  export { default as TransactionStatus } from './TransactionStatus/TransactionStatus';
@@ -99,8 +112,10 @@ export { default as Toast, type ToastProps } from './Toast/Toast';
99
112
  export { default as ToastProvider, type ToastProviderProps } from './Toast/ToastProvider';
100
113
  export { useToast, addToast, closeToast, closeAll, type ToastOptions, type ToastEntry, type ToastPlacement } from './Toast/useToast';
101
114
  export { default as AmountInput, type AmountInputProps } from './AmountInput/AmountInput';
115
+ export { default as PageHero, type PageHeroProps } from './PageHero/PageHero';
102
116
  export { default as Popup, type PopupProps, type PopupRef } from './Popup/Popup';
103
117
  export { default as PortfolioHero, type PortfolioHeroProps } from './PortfolioHero/PortfolioHero';
118
+ export { default as PoweredByLabel, type PoweredByLabelProps } from './PoweredByLabel/PoweredByLabel';
104
119
  export { default as ProductLabel, type ProductLabelProps } from './ProductLabel/ProductLabel';
105
120
  export { default as ProductOverview, type ProductOverviewProps, type ProductOverviewStat } from './ProductOverview/ProductOverview';
106
121
  export { default as ProgressBadge, type ProgressBadgeProps } from './ProgressBadge/ProgressBadge';