@coreui/react-pro 4.12.0-beta.1 → 4.12.0-beta.3

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 (40) hide show
  1. package/README.md +1 -1
  2. package/dist/components/dropdown/CDropdown.d.ts +8 -1
  3. package/dist/components/dropdown/CDropdownMenu.d.ts +3 -4
  4. package/dist/components/multi-select/CMultiSelect.d.ts +2 -2
  5. package/dist/components/popover/CPopover.d.ts +22 -1
  6. package/dist/components/progress/CProgress.d.ts +6 -0
  7. package/dist/components/progress/CProgressStacked.d.ts +12 -0
  8. package/dist/components/progress/index.d.ts +2 -1
  9. package/dist/components/tooltip/CTooltip.d.ts +22 -1
  10. package/dist/hooks/index.d.ts +2 -1
  11. package/dist/hooks/useColorModes.d.ts +3 -2
  12. package/dist/hooks/usePopper.d.ts +8 -0
  13. package/dist/index.es.js +6682 -7089
  14. package/dist/index.es.js.map +1 -1
  15. package/dist/index.js +6300 -6723
  16. package/dist/index.js.map +1 -1
  17. package/dist/props.d.ts +1 -0
  18. package/dist/utils/getRTLPlacement.d.ts +3 -0
  19. package/dist/utils/index.d.ts +2 -1
  20. package/package.json +5 -5
  21. package/src/components/date-range-picker/CDateRangePicker.tsx +10 -7
  22. package/src/components/dropdown/CDropdown.tsx +130 -45
  23. package/src/components/dropdown/CDropdownMenu.tsx +41 -138
  24. package/src/components/dropdown/CDropdownToggle.tsx +6 -15
  25. package/src/components/dropdown/__tests__/__snapshots__/CDropdownMenu.spec.tsx.snap +0 -1
  26. package/src/components/multi-select/CMultiSelect.tsx +30 -39
  27. package/src/components/picker/CPicker.tsx +24 -34
  28. package/src/components/popover/CPopover.tsx +76 -51
  29. package/src/components/popover/__tests__/__snapshots__/CPopover.spec.tsx.snap +0 -21
  30. package/src/components/progress/CProgress.tsx +43 -8
  31. package/src/components/progress/CProgressBar.tsx +5 -6
  32. package/src/components/progress/CProgressStacked.tsx +39 -0
  33. package/src/components/progress/index.ts +2 -1
  34. package/src/components/tooltip/CTooltip.tsx +77 -52
  35. package/src/hooks/index.ts +2 -1
  36. package/src/hooks/useColorModes.ts +21 -11
  37. package/src/hooks/usePopper.ts +31 -0
  38. package/src/props.ts +5 -0
  39. package/src/utils/getRTLPlacement.ts +18 -0
  40. package/src/utils/index.ts +2 -1
@@ -11,7 +11,8 @@ import React, {
11
11
 
12
12
  import classNames from 'classnames'
13
13
  import PropTypes from 'prop-types'
14
- import { createPopper, Instance } from '@popperjs/core'
14
+
15
+ import type { Placement } from '@popperjs/core'
15
16
 
16
17
  import { CFormControlWrapper, CFormControlWrapperProps } from '../form/CFormControlWrapper'
17
18
 
@@ -19,7 +20,7 @@ import { CMultiSelectNativeSelect } from './CMultiSelectNativeSelect'
19
20
  import { CMultiSelectOptions } from './CMultiSelectOptions'
20
21
  import { CMultiSelectSelection } from './CMultiSelectSelection'
21
22
 
22
- import { useForkedRef } from '../../hooks'
23
+ import { useForkedRef, usePopper } from '../../hooks'
23
24
  import { isRTL } from '../../utils'
24
25
  import { createOption, filterOptionsList, flattenOptionsArray, selectOptions } from './utils'
25
26
  import type { Option, OptionsGroup, SelectedOption } from './types'
@@ -101,13 +102,13 @@ export interface CMultiSelectProps
101
102
  /**
102
103
  * Custom template for options.
103
104
  *
104
- * @since 4.12.0-beta.1
105
+ * @since 4.12.0-beta.3
105
106
  */
106
107
  optionsTemplate?: (option: Option) => ReactNode
107
108
  /**
108
109
  * Custom template for options groups.
109
110
  *
110
- * @since 4.12.0-beta.1
111
+ * @since 4.12.0-beta.3
111
112
  */
112
113
  optionsGroupsTemplate?: (option: OptionsGroup) => ReactNode
113
114
  /**
@@ -215,9 +216,9 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
215
216
  const nativeSelectRef = useRef<HTMLSelectElement>(null)
216
217
  const togglerRef = useRef<HTMLDivElement>(null)
217
218
  const searchRef = useRef<HTMLInputElement>(null)
218
-
219
219
  const isInitialMount = useRef(true)
220
- const popper = useRef<Instance>()
220
+
221
+ const { popper, initPopper, destroyPopper } = usePopper()
221
222
 
222
223
  const [_options, setOptions] = useState<(Option | OptionsGroup)[]>(options)
223
224
  const [_visible, setVisible] = useState(visible)
@@ -251,6 +252,24 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
251
252
  return searchRef.current && createOption(String(searchValue), flattenedOptions)
252
253
  }, [filteredOptions, searchValue])
253
254
 
255
+ const popperConfig = {
256
+ placement: (isRTL(multiSelectRef.current) ? 'bottom-end' : 'bottom-start') as Placement,
257
+ modifiers: [
258
+ {
259
+ name: 'preventOverflow',
260
+ options: {
261
+ boundary: 'clippingParents',
262
+ },
263
+ },
264
+ {
265
+ name: 'offset',
266
+ options: {
267
+ offset: [0, 2],
268
+ },
269
+ },
270
+ ],
271
+ }
272
+
254
273
  useEffect(() => {
255
274
  setOptions(options)
256
275
 
@@ -271,8 +290,8 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
271
290
  nativeSelectRef.current.dispatchEvent(new Event('change', { bubbles: true }))
272
291
  }
273
292
 
274
- if (popper.current) {
275
- popper.current.update()
293
+ if (popper) {
294
+ popper.update()
276
295
  }
277
296
  }, [JSON.stringify(selected)])
278
297
 
@@ -283,7 +302,9 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
283
302
  window.addEventListener('mouseup', handleMouseUp)
284
303
  window.addEventListener('keyup', handleKeyUp)
285
304
 
286
- initPopper()
305
+ togglerRef.current &&
306
+ dropdownRef.current &&
307
+ initPopper(togglerRef.current, dropdownRef.current, popperConfig)
287
308
  searchRef.current && searchRef.current.focus()
288
309
  }
289
310
 
@@ -301,36 +322,6 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
301
322
  isInitialMount.current = false
302
323
  }, [])
303
324
 
304
- const initPopper = () => {
305
- if (togglerRef.current && dropdownRef.current) {
306
- popper.current = createPopper(togglerRef.current, dropdownRef.current, {
307
- placement: isRTL(multiSelectRef.current) ? 'bottom-end' : 'bottom-start',
308
- modifiers: [
309
- {
310
- name: 'preventOverflow',
311
- options: {
312
- boundary: 'clippingParents',
313
- },
314
- },
315
- {
316
- name: 'offset',
317
- options: {
318
- offset: [0, 2],
319
- },
320
- },
321
- ],
322
- })
323
- }
324
- }
325
-
326
- const destroyPopper = () => {
327
- if (popper.current) {
328
- popper.current.destroy()
329
- }
330
-
331
- popper.current = undefined
332
- }
333
-
334
325
  const handleKeyUp = (event: KeyboardEvent) => {
335
326
  if (event.key === 'Escape') {
336
327
  setVisible(false)
@@ -2,9 +2,9 @@ import React, { forwardRef, HTMLAttributes, ReactNode, useEffect, useRef, useSta
2
2
 
3
3
  import PropTypes from 'prop-types'
4
4
  import classNames from 'classnames'
5
- import { createPopper, Instance } from '@popperjs/core'
5
+ import { Placement } from '@popperjs/core'
6
6
 
7
- import { useForkedRef } from '../../hooks'
7
+ import { useForkedRef, usePopper } from '../../hooks'
8
8
  import { isRTL } from '../../utils'
9
9
 
10
10
  export interface CPickerProps extends HTMLAttributes<HTMLDivElement> {
@@ -68,10 +68,28 @@ export const CPicker = forwardRef<HTMLDivElement | HTMLLIElement, CPickerProps>(
68
68
  const dropdownRef = useRef<HTMLDivElement>(null)
69
69
  const togglerRef = useRef<HTMLDivElement>(null)
70
70
 
71
- const popper = useRef<Instance>()
71
+ const { initPopper, destroyPopper } = usePopper()
72
72
 
73
73
  const [_visible, setVisible] = useState(visible)
74
74
 
75
+ const popperConfig = {
76
+ placement: (isRTL(pickerRef.current) ? 'bottom-end' : 'bottom-start') as Placement,
77
+ modifiers: [
78
+ {
79
+ name: 'preventOverflow',
80
+ options: {
81
+ boundary: 'clippingParents',
82
+ },
83
+ },
84
+ {
85
+ name: 'offset',
86
+ options: {
87
+ offset: [0, 2],
88
+ },
89
+ },
90
+ ],
91
+ }
92
+
75
93
  useEffect(() => {
76
94
  setVisible(visible)
77
95
  }, [visible])
@@ -83,7 +101,9 @@ export const CPicker = forwardRef<HTMLDivElement | HTMLLIElement, CPickerProps>(
83
101
  window.addEventListener('mouseup', handleMouseUp)
84
102
  window.addEventListener('keyup', handleKeyUp)
85
103
 
86
- initPopper()
104
+ togglerRef.current &&
105
+ dropdownRef.current &&
106
+ initPopper(togglerRef.current, dropdownRef.current, popperConfig)
87
107
  }
88
108
 
89
109
  return () => {
@@ -96,36 +116,6 @@ export const CPicker = forwardRef<HTMLDivElement | HTMLLIElement, CPickerProps>(
96
116
  }
97
117
  }, [_visible])
98
118
 
99
- const initPopper = () => {
100
- if (togglerRef.current && dropdownRef.current) {
101
- popper.current = createPopper(togglerRef.current, dropdownRef.current, {
102
- placement: isRTL(pickerRef.current) ? 'bottom-end' : 'bottom-start',
103
- modifiers: [
104
- {
105
- name: 'preventOverflow',
106
- options: {
107
- boundary: 'clippingParents',
108
- },
109
- },
110
- {
111
- name: 'offset',
112
- options: {
113
- offset: [0, 2],
114
- },
115
- },
116
- ],
117
- })
118
- }
119
- }
120
-
121
- const destroyPopper = () => {
122
- if (popper.current) {
123
- popper.current.destroy()
124
- }
125
-
126
- popper.current = undefined
127
- }
128
-
129
119
  const handleKeyUp = (event: KeyboardEvent) => {
130
120
  if (event.key === 'Escape') {
131
121
  setVisible(false)
@@ -3,13 +3,19 @@ import { createPortal } from 'react-dom'
3
3
  import classNames from 'classnames'
4
4
  import PropTypes from 'prop-types'
5
5
  import { Transition } from 'react-transition-group'
6
- import { createPopper, Instance, Placement } from '@popperjs/core'
7
6
 
8
- import { triggerPropType } from '../../props'
9
- import type { Triggers } from '../../types'
10
- import { isRTL } from '../../utils'
7
+ import { usePopper } from '../../hooks'
8
+ import { fallbackPlacementsPropType, triggerPropType } from '../../props'
9
+ import type { Placements, Triggers } from '../../types'
10
+ import { getRTLPlacement } from '../../utils'
11
11
 
12
12
  export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'content'> {
13
+ /**
14
+ * Apply a CSS fade transition to the popover.
15
+ *
16
+ * @since 4.9.0-beta.1
17
+ */
18
+ animation?: boolean
13
19
  /**
14
20
  * A string of all className you want applied to the component.
15
21
  */
@@ -22,6 +28,18 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
22
28
  * Offset of the popover relative to its target.
23
29
  */
24
30
  offset?: [number, number]
31
+ /**
32
+ * The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
33
+ *
34
+ * @since 4.9.0-beta.1
35
+ */
36
+ delay?: number | { show: number; hide: number }
37
+ /**
38
+ * Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference.
39
+ *
40
+ * @since 4.9.0-beta.1
41
+ */
42
+ fallbackPlacements?: Placements | Placements[]
25
43
  /**
26
44
  * Callback fired when the component requests to be hidden.
27
45
  */
@@ -50,24 +68,13 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
50
68
  visible?: boolean
51
69
  }
52
70
 
53
- const getPlacement = (placement: string, element: HTMLDivElement | null): Placement => {
54
- switch (placement) {
55
- case 'right': {
56
- return isRTL(element) ? 'left' : 'right'
57
- }
58
- case 'left': {
59
- return isRTL(element) ? 'right' : 'left'
60
- }
61
- default: {
62
- return placement as Placement
63
- }
64
- }
65
- }
66
-
67
71
  export const CPopover: FC<CPopoverProps> = ({
68
72
  children,
73
+ animation = true,
69
74
  className,
70
75
  content,
76
+ delay = 0,
77
+ fallbackPlacements = ['top', 'right', 'bottom', 'left'],
71
78
  offset = [0, 8],
72
79
  onHide,
73
80
  onShow,
@@ -79,16 +86,42 @@ export const CPopover: FC<CPopoverProps> = ({
79
86
  }) => {
80
87
  const popoverRef = useRef(null)
81
88
  const togglerRef = useRef(null)
82
- const popper = useRef<Instance>()
89
+ const { initPopper, destroyPopper } = usePopper()
83
90
  const [_visible, setVisible] = useState(visible)
84
91
 
92
+ const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
93
+
94
+ const popperConfig = {
95
+ modifiers: [
96
+ {
97
+ name: 'arrow',
98
+ options: {
99
+ element: '.popover-arrow',
100
+ },
101
+ },
102
+ {
103
+ name: 'flip',
104
+ options: {
105
+ fallbackPlacements: fallbackPlacements,
106
+ },
107
+ },
108
+ {
109
+ name: 'offset',
110
+ options: {
111
+ offset: offset,
112
+ },
113
+ },
114
+ ],
115
+ placement: getRTLPlacement(placement, togglerRef.current),
116
+ }
117
+
85
118
  useEffect(() => {
86
119
  setVisible(visible)
87
120
  }, [visible])
88
121
 
89
122
  useEffect(() => {
90
- if (_visible) {
91
- initPopper()
123
+ if (_visible && togglerRef.current && popoverRef.current) {
124
+ initPopper(togglerRef.current, popoverRef.current, popperConfig)
92
125
  }
93
126
 
94
127
  return () => {
@@ -96,28 +129,13 @@ export const CPopover: FC<CPopoverProps> = ({
96
129
  }
97
130
  }, [_visible])
98
131
 
99
- const initPopper = () => {
100
- if (togglerRef.current && popoverRef.current) {
101
- popper.current = createPopper(togglerRef.current, popoverRef.current, {
102
- modifiers: [
103
- {
104
- name: 'offset',
105
- options: {
106
- offset: offset,
107
- },
108
- },
109
- ],
110
- placement: getPlacement(placement, togglerRef.current),
111
- })
112
- }
113
- }
114
-
115
- const destroyPopper = () => {
116
- if (popper.current) {
117
- popper.current.destroy()
132
+ const toggleVisible = (visible: boolean) => {
133
+ if (visible) {
134
+ setTimeout(() => setVisible(true), _delay.show)
135
+ return
118
136
  }
119
137
 
120
- popper.current = undefined
138
+ setTimeout(() => setVisible(false), _delay.hide)
121
139
  }
122
140
 
123
141
  return (
@@ -125,15 +143,15 @@ export const CPopover: FC<CPopoverProps> = ({
125
143
  {React.cloneElement(children as React.ReactElement<any>, {
126
144
  ref: togglerRef,
127
145
  ...((trigger === 'click' || trigger.includes('click')) && {
128
- onClick: () => setVisible(!_visible),
146
+ onClick: () => toggleVisible(!_visible),
129
147
  }),
130
148
  ...((trigger === 'focus' || trigger.includes('focus')) && {
131
- onFocus: () => setVisible(true),
132
- onBlur: () => setVisible(false),
149
+ onFocus: () => toggleVisible(true),
150
+ onBlur: () => toggleVisible(false),
133
151
  }),
134
152
  ...((trigger === 'hover' || trigger.includes('hover')) && {
135
- onMouseEnter: () => setVisible(true),
136
- onMouseLeave: () => setVisible(false),
153
+ onMouseEnter: () => toggleVisible(true),
154
+ onMouseLeave: () => toggleVisible(false),
137
155
  }),
138
156
  })}
139
157
  {typeof window !== 'undefined' &&
@@ -154,11 +172,9 @@ export const CPopover: FC<CPopoverProps> = ({
154
172
  <div
155
173
  className={classNames(
156
174
  'popover',
157
- `bs-popover-${getPlacement(placement, togglerRef.current)
158
- .replace('left', 'start')
159
- .replace('right', 'end')}`,
160
- 'fade',
175
+ 'bs-popover-auto',
161
176
  {
177
+ fade: animation,
162
178
  show: state === 'entered',
163
179
  },
164
180
  className,
@@ -167,7 +183,7 @@ export const CPopover: FC<CPopoverProps> = ({
167
183
  role="tooltip"
168
184
  {...rest}
169
185
  >
170
- <div data-popper-arrow className="popover-arrow"></div>
186
+ <div className="popover-arrow"></div>
171
187
  <div className="popover-header">{title}</div>
172
188
  <div className="popover-body">{content}</div>
173
189
  </div>
@@ -180,9 +196,18 @@ export const CPopover: FC<CPopoverProps> = ({
180
196
  }
181
197
 
182
198
  CPopover.propTypes = {
199
+ animation: PropTypes.bool,
183
200
  children: PropTypes.node,
184
201
  className: PropTypes.string,
185
202
  content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
203
+ delay: PropTypes.oneOfType([
204
+ PropTypes.number,
205
+ PropTypes.shape({
206
+ show: PropTypes.number.isRequired,
207
+ hide: PropTypes.number.isRequired,
208
+ }),
209
+ ]),
210
+ fallbackPlacements: fallbackPlacementsPropType,
186
211
  offset: PropTypes.any, // TODO: find good proptype
187
212
  onHide: PropTypes.func,
188
213
  onShow: PropTypes.func,
@@ -8,27 +8,6 @@ exports[`CPopover customize 1`] = `
8
8
  >
9
9
  Test
10
10
  </button>
11
- <div
12
- class="popover bs-popover-end fade"
13
- role="tooltip"
14
- style="position: absolute; left: 0px; top: 0px; margin: 0px;"
15
- >
16
- <div
17
- class="popover-arrow"
18
- data-popper-arrow="true"
19
- style="position: absolute;"
20
- />
21
- <div
22
- class="popover-header"
23
- >
24
- title
25
- </div>
26
- <div
27
- class="popover-body"
28
- >
29
- content
30
- </div>
31
- </div>
32
11
  </body>
33
12
  `;
34
13
 
@@ -1,7 +1,8 @@
1
- import React, { forwardRef, HTMLAttributes } from 'react'
1
+ import React, { forwardRef, HTMLAttributes, useContext } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
 
5
+ import { CProgressStackedContext } from './CProgressStacked'
5
6
  import { CProgressBar, CProgressBarProps } from './CProgressBar'
6
7
 
7
8
  export interface CProgressProps
@@ -15,6 +16,12 @@ export interface CProgressProps
15
16
  * Sets the height of the component. If you set that value the inner `<CProgressBar>` will automatically resize accordingly.
16
17
  */
17
18
  height?: number
19
+ /**
20
+ * A string of all className you want applied to the <CProgressBar/> component.
21
+ *
22
+ * @since 4.9.0
23
+ */
24
+ progressBarClassName?: string
18
25
  /**
19
26
  * Makes progress bar thinner.
20
27
  */
@@ -29,9 +36,10 @@ export interface CProgressProps
29
36
  white?: boolean
30
37
  }
31
38
 
32
- // TODO: update markup and add '.progress-stacked' in v5
33
39
  export const CProgress = forwardRef<HTMLDivElement, CProgressProps>(
34
- ({ children, className, height, thin, value = 0, white, ...rest }, ref) => {
40
+ ({ children, className, height, progressBarClassName, thin, value, white, ...rest }, ref) => {
41
+ const { stacked } = useContext(CProgressStackedContext)
42
+
35
43
  return (
36
44
  <div
37
45
  className={classNames(
@@ -42,15 +50,41 @@ export const CProgress = forwardRef<HTMLDivElement, CProgressProps>(
42
50
  },
43
51
  className,
44
52
  )}
45
- style={height ? { height: `${height}px` } : {}}
53
+ {...(value !== undefined && {
54
+ role: 'progressbar',
55
+ 'aria-valuenow': value,
56
+ 'aria-valuemin': 0,
57
+ 'aria-valuemax': 100,
58
+ })}
59
+ style={{
60
+ ...(height ? { height: `${height}px` } : {}),
61
+ ...(stacked ? { width: `${value}%` } : {}),
62
+ }}
46
63
  ref={ref}
47
64
  >
48
- {value ? (
49
- <CProgressBar value={value} {...rest}>
65
+ {React.Children.toArray(children).some(
66
+ // @ts-expect-error displayName is set in the CProgressBar component
67
+ (child) => child.type && child.type.displayName === 'CProgressBar',
68
+ ) ? (
69
+ React.Children.map(children, (child) => {
70
+ // @ts-expect-error displayName is set in the CProgressBar component
71
+ if (React.isValidElement(child) && child.type.displayName === 'CProgressBar') {
72
+ return React.cloneElement(child, {
73
+ ...(value && { value: value }),
74
+ ...rest,
75
+ })
76
+ }
77
+
78
+ return
79
+ })
80
+ ) : (
81
+ <CProgressBar
82
+ {...(progressBarClassName && { className: progressBarClassName })}
83
+ value={value}
84
+ {...rest}
85
+ >
50
86
  {children}
51
87
  </CProgressBar>
52
- ) : (
53
- children
54
88
  )}
55
89
  </div>
56
90
  )
@@ -61,6 +95,7 @@ CProgress.propTypes = {
61
95
  children: PropTypes.node,
62
96
  className: PropTypes.string,
63
97
  height: PropTypes.number,
98
+ progressBarClassName: PropTypes.string,
64
99
  thin: PropTypes.bool,
65
100
  value: PropTypes.number,
66
101
  white: PropTypes.bool,
@@ -1,7 +1,8 @@
1
- import React, { forwardRef, HTMLAttributes } from 'react'
1
+ import React, { forwardRef, HTMLAttributes, useContext } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
 
5
+ import { CProgressStackedContext } from './CProgressStacked'
5
6
  import { colorPropType, gradientsPropType } from '../../props'
6
7
  import type { Colors, Gradients } from '../../types'
7
8
 
@@ -32,6 +33,8 @@ export interface CProgressBarProps extends HTMLAttributes<HTMLDivElement> {
32
33
 
33
34
  export const CProgressBar = forwardRef<HTMLDivElement, CProgressBarProps>(
34
35
  ({ children, animated, className, color, value = 0, variant, ...rest }, ref) => {
36
+ const { stacked } = useContext(CProgressStackedContext)
37
+
35
38
  return (
36
39
  <div
37
40
  className={classNames(
@@ -43,11 +46,7 @@ export const CProgressBar = forwardRef<HTMLDivElement, CProgressBarProps>(
43
46
  },
44
47
  className,
45
48
  )}
46
- role="progressbar"
47
- style={{ width: `${value}%` }}
48
- aria-valuenow={value}
49
- aria-valuemin={0}
50
- aria-valuemax={100}
49
+ {...(!stacked && { style: { width: `${value}%` } })}
51
50
  {...rest}
52
51
  ref={ref}
53
52
  >
@@ -0,0 +1,39 @@
1
+ import React, { createContext, forwardRef, HTMLAttributes } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import classNames from 'classnames'
4
+
5
+ export interface CProgressStackedProps extends HTMLAttributes<HTMLDivElement> {
6
+ /**
7
+ * A string of all className you want applied to the component.
8
+ */
9
+ className?: string
10
+ }
11
+
12
+ export interface CProgressStackedContextProps {
13
+ stacked?: boolean
14
+ }
15
+
16
+ export const CProgressStackedContext = createContext({} as CProgressStackedContextProps)
17
+
18
+ export const CProgressStacked = forwardRef<HTMLDivElement, CProgressStackedProps>(
19
+ ({ children, className, ...rest }, ref) => {
20
+ return (
21
+ <div className={classNames('progress-stacked', className)} ref={ref} {...rest}>
22
+ <CProgressStackedContext.Provider
23
+ value={{
24
+ stacked: true,
25
+ }}
26
+ >
27
+ {children}
28
+ </CProgressStackedContext.Provider>
29
+ </div>
30
+ )
31
+ },
32
+ )
33
+
34
+ CProgressStacked.propTypes = {
35
+ children: PropTypes.node,
36
+ className: PropTypes.string,
37
+ }
38
+
39
+ CProgressStacked.displayName = 'CProgressStacked'
@@ -1,4 +1,5 @@
1
1
  import { CProgress } from './CProgress'
2
2
  import { CProgressBar } from './CProgressBar'
3
+ import { CProgressStacked } from './CProgressStacked'
3
4
 
4
- export { CProgress, CProgressBar }
5
+ export { CProgress, CProgressBar, CProgressStacked }