@coreui/react-pro 4.11.3 → 4.12.0-beta.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 (95) hide show
  1. package/README.md +1 -1
  2. package/dist/components/accordion/index.d.ts +1 -1
  3. package/dist/components/calendar/CCalendar.d.ts +4 -4
  4. package/dist/components/date-range-picker/CDateRangePicker copy.d.ts +114 -0
  5. package/dist/components/date-range-picker/CDateRangePicker.d.ts +49 -1
  6. package/dist/components/multi-select/CMultiSelect.d.ts +34 -3
  7. package/dist/components/multi-select/CMultiSelectNativeSelect.d.ts +4 -5
  8. package/dist/components/multi-select/CMultiSelectOptions.d.ts +4 -2
  9. package/dist/components/multi-select/CMultiSelectSelection.d.ts +1 -0
  10. package/dist/components/multi-select/types.d.ts +7 -3
  11. package/dist/components/multi-select/utils.d.ts +5 -5
  12. package/dist/components/multi-select-new/CMultiSelect.d.ts +133 -0
  13. package/dist/components/multi-select-new/CMultiSelectNativeSelect.d.ts +7 -0
  14. package/dist/components/multi-select-new/CMultiSelectNew.d.ts +121 -0
  15. package/dist/components/multi-select-new/CMultiSelectOptions.d.ts +16 -0
  16. package/dist/components/multi-select-new/CMultiSelectSelection.d.ts +11 -0
  17. package/dist/components/multi-select-new/index.d.ts +2 -0
  18. package/dist/components/multi-select-new/types.d.ts +15 -0
  19. package/dist/components/multi-select-new/utils.d.ts +11 -0
  20. package/dist/components/picker/CPicker copy.d.ts +82 -0
  21. package/dist/components/picker/CPicker.d.ts +14 -56
  22. package/dist/components/picker copy/CPicker.d.ts +82 -0
  23. package/dist/components/popover/CPopover.d.ts +1 -1
  24. package/dist/components/time-picker/CTimePicker.d.ts +41 -1
  25. package/dist/components/tooltip/CTooltip.d.ts +3 -3
  26. package/dist/hooks/index.d.ts +2 -1
  27. package/dist/hooks/useColorModes.d.ts +6 -0
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.es.js +2385 -2403
  30. package/dist/index.es.js.map +1 -1
  31. package/dist/index.js +2386 -2401
  32. package/dist/index.js.map +1 -1
  33. package/dist/props.d.ts +1 -1
  34. package/dist/utils/index.d.ts +2 -1
  35. package/dist/utils/isRTL.d.ts +2 -0
  36. package/package.json +15 -15
  37. package/src/components/accordion/index.ts +1 -7
  38. package/src/components/calendar/CCalendar.tsx +49 -64
  39. package/src/components/calendar/__tests__/__snapshots__/CCalendar.spec.tsx.snap +601 -555
  40. package/src/components/calendar/utils.ts +1 -1
  41. package/src/components/date-picker/__tests__/__snapshots__/CDatePicker.spec.tsx.snap +599 -561
  42. package/src/components/date-range-picker/CDateRangePicker.tsx +208 -107
  43. package/src/components/date-range-picker/__tests__/__snapshots__/CDateRangePicker.spec.tsx.snap +1197 -1121
  44. package/src/components/date-range-picker/utils.ts +2 -2
  45. package/src/components/dropdown/CDropdownMenu.tsx +5 -4
  46. package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +1 -1
  47. package/src/components/element-cover/CElementCover.tsx +1 -0
  48. package/src/components/form/CFormSelect.tsx +3 -1
  49. package/src/components/modal/CModal.tsx +2 -0
  50. package/src/components/multi-select/CMultiSelect.tsx +200 -79
  51. package/src/components/multi-select/CMultiSelectNativeSelect.tsx +34 -24
  52. package/src/components/multi-select/CMultiSelectOptions.tsx +25 -23
  53. package/src/components/multi-select/CMultiSelectSelection.tsx +36 -7
  54. package/src/components/multi-select/__tests__/CMultiSelect.spec.tsx +25 -14
  55. package/src/components/multi-select/__tests__/CMultiSelectNativeSelect.spec.tsx +1 -1
  56. package/src/components/multi-select/__tests__/CMultiSelectOptions.spec.tsx +4 -4
  57. package/src/components/multi-select/__tests__/CMultiSelectSelection.spec.tsx +0 -1
  58. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelect.spec.tsx.snap +136 -30
  59. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectNativeSelect.spec.tsx.snap +2 -0
  60. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectOptions.spec.tsx.snap +3 -1
  61. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelection.spec.tsx.snap +2 -2
  62. package/src/components/multi-select/types.ts +9 -4
  63. package/src/components/multi-select/utils.ts +56 -39
  64. package/src/components/picker/CPicker.tsx +113 -138
  65. package/src/components/popover/CPopover.tsx +61 -26
  66. package/src/components/popover/__tests__/__snapshots__/CPopover.spec.tsx.snap +2 -1
  67. package/src/components/progress/CProgress.tsx +1 -0
  68. package/src/components/sidebar/CSidebar.tsx +2 -2
  69. package/src/components/smart-table/CSmartTable.tsx +22 -10
  70. package/src/components/smart-table/CSmartTableBody.tsx +3 -5
  71. package/src/components/smart-table/CSmartTableHead.tsx +5 -6
  72. package/src/components/smart-table/__tests__/CSmartTable.spec.tsx +1 -1
  73. package/src/components/smart-table/__tests__/__snapshots__/CSmartTable.spec.tsx.snap +580 -0
  74. package/src/components/spinner/CSpinner.tsx +4 -2
  75. package/src/components/spinner/__tests__/__snapshots__/CSpinner.spec.tsx.snap +2 -2
  76. package/src/components/table/CTable.tsx +2 -1
  77. package/src/components/time-picker/CTimePicker.tsx +182 -82
  78. package/src/components/time-picker/__tests__/__snapshots__/CTimePicker.spec.tsx.snap +1078 -0
  79. package/src/components/tooltip/CTooltip.tsx +65 -31
  80. package/src/components/tooltip/__tests__/CTooltip.spec.tsx +1 -1
  81. package/src/components/virtual-scroller/CVirtualScroller.tsx +0 -1
  82. package/src/hooks/index.ts +2 -1
  83. package/src/hooks/useColorModes.ts +55 -0
  84. package/src/hooks/useForkedRef.ts +1 -1
  85. package/src/index.ts +1 -0
  86. package/src/props.ts +4 -1
  87. package/src/utils/index.ts +2 -1
  88. package/src/utils/isRTL.ts +13 -0
  89. package/src/components/multi-select/__tests__/CMultiSelectCleaner.spec.tsx +0 -15
  90. package/src/components/multi-select/__tests__/CMultiSelectSearchInput.spec.tsx +0 -17
  91. package/src/components/multi-select/__tests__/CMultiSelectSelectAllButton.spec.tsx +0 -21
  92. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectCleaner.spec.tsx.snap +0 -19
  93. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSearchInput.spec.tsx.snap +0 -20
  94. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelectAllButton.spec.tsx.snap +0 -24
  95. package/src/components/smart-table/CSmartTableCleaner.tsx +0 -37
@@ -1,14 +1,15 @@
1
- import React, { FC, HTMLAttributes, ReactNode, useEffect, useRef, useState } from 'react'
1
+ import React, { FC, HTMLAttributes, ReactNode, useRef, useEffect, useState } from 'react'
2
2
  import { createPortal } from 'react-dom'
3
- import PropTypes from 'prop-types'
4
3
  import classNames from 'classnames'
5
- import { usePopper } from 'react-popper'
4
+ import PropTypes from 'prop-types'
6
5
  import { Transition } from 'react-transition-group'
6
+ import { createPopper, Instance, Placement } from '@popperjs/core'
7
7
 
8
8
  import { triggerPropType } from '../../props'
9
9
  import type { Triggers } from '../../types'
10
+ import { isRTL } from '../../utils'
10
11
 
11
- export interface CTooltipProps extends HTMLAttributes<HTMLDivElement> {
12
+ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {
12
13
  /**
13
14
  * A string of all className you want applied to the component.
14
15
  */
@@ -18,7 +19,7 @@ export interface CTooltipProps extends HTMLAttributes<HTMLDivElement> {
18
19
  */
19
20
  content: ReactNode | string
20
21
  /**
21
- * Offset of the popover relative to its target.
22
+ * Offset of the tooltip relative to its target.
22
23
  */
23
24
  offset?: [number, number]
24
25
  /**
@@ -40,16 +41,30 @@ export interface CTooltipProps extends HTMLAttributes<HTMLDivElement> {
40
41
  */
41
42
  placement?: 'auto' | 'top' | 'right' | 'bottom' | 'left'
42
43
  /**
43
- * Toggle the visibility of popover component.
44
+ * Toggle the visibility of tooltip component.
44
45
  */
45
46
  visible?: boolean
46
47
  }
47
48
 
49
+ const getPlacement = (placement: string, element: HTMLDivElement | null): Placement => {
50
+ switch (placement) {
51
+ case 'right': {
52
+ return isRTL(element) ? 'left' : 'right'
53
+ }
54
+ case 'left': {
55
+ return isRTL(element) ? 'right' : 'left'
56
+ }
57
+ default: {
58
+ return placement as Placement
59
+ }
60
+ }
61
+ }
62
+
48
63
  export const CTooltip: FC<CTooltipProps> = ({
49
64
  children,
50
65
  className,
51
66
  content,
52
- offset = [0, 0],
67
+ offset = [0, 6],
53
68
  onHide,
54
69
  onShow,
55
70
  placement = 'top',
@@ -57,33 +72,53 @@ export const CTooltip: FC<CTooltipProps> = ({
57
72
  visible,
58
73
  ...rest
59
74
  }) => {
60
- const tooltipRef = useRef()
75
+ const tooltipRef = useRef(null)
76
+ const togglerRef = useRef(null)
77
+ const popper = useRef<Instance>()
61
78
  const [_visible, setVisible] = useState(visible)
62
79
 
63
- const [referenceElement, setReferenceElement] = useState(null)
64
- const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null)
65
- const [arrowElement, setArrowElement] = useState<HTMLDivElement | null>(null)
66
- const { styles, attributes } = usePopper(referenceElement, popperElement, {
67
- modifiers: [
68
- { name: 'arrow', options: { element: arrowElement } },
69
- {
70
- name: 'offset',
71
- options: {
72
- offset: offset,
73
- },
74
- },
75
- ],
76
- placement: placement,
77
- })
78
-
79
80
  useEffect(() => {
80
81
  setVisible(visible)
81
82
  }, [visible])
82
83
 
84
+ useEffect(() => {
85
+ if (_visible) {
86
+ initPopper()
87
+ }
88
+
89
+ return () => {
90
+ destroyPopper()
91
+ }
92
+ }, [_visible])
93
+
94
+ const initPopper = () => {
95
+ if (togglerRef.current && tooltipRef.current) {
96
+ popper.current = createPopper(togglerRef.current, tooltipRef.current, {
97
+ modifiers: [
98
+ {
99
+ name: 'offset',
100
+ options: {
101
+ offset: offset,
102
+ },
103
+ },
104
+ ],
105
+ placement: getPlacement(placement, togglerRef.current),
106
+ })
107
+ }
108
+ }
109
+
110
+ const destroyPopper = () => {
111
+ if (popper.current) {
112
+ popper.current.destroy()
113
+ }
114
+
115
+ popper.current = undefined
116
+ }
117
+
83
118
  return (
84
119
  <>
85
120
  {React.cloneElement(children as React.ReactElement<any>, {
86
- ref: setReferenceElement,
121
+ ref: togglerRef,
87
122
  ...((trigger === 'click' || trigger.includes('click')) && {
88
123
  onClick: () => setVisible(!_visible),
89
124
  }),
@@ -101,7 +136,6 @@ export const CTooltip: FC<CTooltipProps> = ({
101
136
  <Transition
102
137
  in={_visible}
103
138
  mountOnEnter
104
- nodeRef={tooltipRef}
105
139
  onEnter={onShow}
106
140
  onExit={onHide}
107
141
  timeout={{
@@ -114,20 +148,20 @@ export const CTooltip: FC<CTooltipProps> = ({
114
148
  <div
115
149
  className={classNames(
116
150
  'tooltip',
117
- `bs-popover-${placement.replace('left', 'start').replace('right', 'end')}`,
151
+ `bs-tooltip-${getPlacement(placement, togglerRef.current)
152
+ .replace('left', 'start')
153
+ .replace('right', 'end')}`,
118
154
  'fade',
119
155
  {
120
156
  show: state === 'entered',
121
157
  },
122
158
  className,
123
159
  )}
124
- ref={setPopperElement}
160
+ ref={tooltipRef}
125
161
  role="tooltip"
126
- style={styles.popper}
127
- {...attributes.popper}
128
162
  {...rest}
129
163
  >
130
- <div className="tooltip-arrow" style={styles.arrow} ref={setArrowElement}></div>
164
+ <div data-popper-arrow className="tooltip-arrow"></div>
131
165
  <div className="tooltip-inner">{content}</div>
132
166
  </div>
133
167
  )}
@@ -13,7 +13,7 @@ beforeEach(() => {
13
13
  })
14
14
 
15
15
  afterEach(() => {
16
- container && document.body.removeChild(container)
16
+ container && container.remove()
17
17
  container = null
18
18
  })
19
19
 
@@ -73,7 +73,6 @@ export const CVirtualScroller = forwardRef<HTMLDivElement, CVirtualScrollerProps
73
73
  }
74
74
  ref={forkedRef}
75
75
  style={{
76
- // height: maxHeight > viewportHeight ? viewportHeight : maxHeight,
77
76
  height: viewportHeight,
78
77
  overflowY: 'auto',
79
78
  }}
@@ -1,4 +1,5 @@
1
+ import { useColorModes } from './useColorModes'
1
2
  import { useForkedRef } from './useForkedRef'
2
3
  import { useStateWithCallback } from './useStateWithCallback'
3
4
 
4
- export { useForkedRef, useStateWithCallback }
5
+ export { useColorModes, useForkedRef, useStateWithCallback }
@@ -0,0 +1,55 @@
1
+ import { useEffect, useState } from 'react'
2
+
3
+ interface UseColorModesOutput {
4
+ getColorMode: () => string
5
+ setColorMode: (mode: string) => void
6
+ }
7
+
8
+ const getStoredTheme = (localStorageItemName: string) => localStorage.getItem(localStorageItemName)
9
+ const setStoredTheme = (localStorageItemName: string, colorMode: string) =>
10
+ localStorage.setItem(localStorageItemName, colorMode)
11
+
12
+ const getPreferredColorScheme = (localStorageItemName: string) => {
13
+ const storedTheme = getStoredTheme(localStorageItemName)
14
+
15
+ if (storedTheme) {
16
+ return storedTheme
17
+ }
18
+
19
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
20
+ }
21
+
22
+ const setTheme = (colorMode: string) => {
23
+ document.documentElement.dataset.coreuiTheme =
24
+ colorMode === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches
25
+ ? 'dark'
26
+ : colorMode
27
+
28
+ const event = new Event('ColorSchemeChange')
29
+ document.documentElement.dispatchEvent(event)
30
+ }
31
+
32
+ export const useColorModes = (
33
+ localStorageItemName = 'coreui-react-color-scheme',
34
+ ): UseColorModesOutput => {
35
+ const [colorMode, setColorMode] = useState<string>(getPreferredColorScheme(localStorageItemName))
36
+
37
+ useEffect(() => {
38
+ setStoredTheme(localStorageItemName, colorMode)
39
+ setTheme(colorMode)
40
+ }, [colorMode])
41
+
42
+ useEffect(() => {
43
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
44
+ const storedTheme = getStoredTheme(localStorageItemName)
45
+ if (storedTheme !== 'light' && storedTheme !== 'dark') {
46
+ setTheme(colorMode)
47
+ }
48
+ })
49
+ }, [])
50
+
51
+ return {
52
+ getColorMode: () => colorMode,
53
+ setColorMode: (mode: string) => setColorMode(mode),
54
+ }
55
+ }
@@ -38,7 +38,7 @@ export function assignRef<RefValueType = any>(
38
38
  } else {
39
39
  try {
40
40
  ref.current = value
41
- } catch (error) {
41
+ } catch {
42
42
  throw new Error(`Cannot assign value "${value}" to ref "${ref}"`)
43
43
  }
44
44
  }
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './components/'
2
+ export * from './hooks/'
package/src/props.ts CHANGED
@@ -68,4 +68,7 @@ export const textColorsPropType = PropTypes.oneOfType([
68
68
  PropTypes.string,
69
69
  ])
70
70
 
71
- export const triggerPropType = PropTypes.oneOf<Triggers>(['hover', 'focus', 'click'])
71
+ export const triggerPropType = PropTypes.oneOfType([
72
+ PropTypes.arrayOf(PropTypes.oneOf<Triggers>(['hover', 'focus', 'click']).isRequired),
73
+ PropTypes.oneOf<Triggers>(['hover', 'focus', 'click']),
74
+ ])
@@ -1,4 +1,5 @@
1
1
  import isInViewport from './isInViewport'
2
2
  import isObjectInArray from './isObjectInArray'
3
+ import isRTL from './isRTL'
3
4
 
4
- export { isInViewport, isObjectInArray }
5
+ export { isInViewport, isObjectInArray, isRTL }
@@ -0,0 +1,13 @@
1
+ const isRTL = (element?: HTMLElement | HTMLDivElement | null) => {
2
+ if (typeof document !== 'undefined' && document.documentElement.dir === 'rtl') {
3
+ return true
4
+ }
5
+
6
+ if (element) {
7
+ return element.closest('[dir="rtl"]') !== null
8
+ }
9
+
10
+ return false
11
+ }
12
+
13
+ export default isRTL
@@ -1,15 +0,0 @@
1
- import * as React from 'react'
2
- import { render } from '@testing-library/react'
3
- import '@testing-library/jest-dom/extend-expect'
4
- import { CMultiSelectCleaner } from '../CMultiSelectCleaner'
5
-
6
- test('loads and displays CMultiSelectCleaner component', async () => {
7
- const { container } = render(<CMultiSelectCleaner />)
8
- expect(container).toMatchSnapshot()
9
- })
10
-
11
- test('CMultiSelectCleaner customize', async () => {
12
- const { container } = render(<CMultiSelectCleaner />)
13
- expect(container).toMatchSnapshot()
14
- expect(container.firstChild).toHaveClass('form-multi-select-selection-cleaner')
15
- })
@@ -1,17 +0,0 @@
1
- import * as React from 'react'
2
- import { render } from '@testing-library/react'
3
- import '@testing-library/jest-dom/extend-expect'
4
- import { CMultiSelectSearchInput } from '../CMultiSelectSearchInput'
5
-
6
- test('loads and displays CMultiSelectSearchInput component', async () => {
7
- const { container } = render(<CMultiSelectSearchInput />)
8
- expect(container).toMatchSnapshot()
9
- })
10
-
11
- test('CMultiSelectSearchInput customize', async () => {
12
- const { container } = render(<CMultiSelectSearchInput placeholder="some placeholder" />)
13
- expect(container).toMatchSnapshot()
14
- expect(container.firstChild).toHaveClass('form-multi-select-search')
15
- expect(container.firstChild).toHaveAttribute('type', 'text')
16
- expect(container.firstChild).toHaveAttribute('placeholder', 'some placeholder')
17
- })
@@ -1,21 +0,0 @@
1
- import * as React from 'react'
2
- import { render } from '@testing-library/react'
3
- import '@testing-library/jest-dom/extend-expect'
4
- import { CMultiSelectSelectAllButton } from '../CMultiSelectSelectAllButton'
5
-
6
- test('loads and displays CMultiSelectSelectAllButton component', async () => {
7
- const { container } = render(<CMultiSelectSelectAllButton>text</CMultiSelectSelectAllButton>)
8
- expect(container).toMatchSnapshot()
9
- })
10
-
11
- test('CMultiSelectSelectAllButton customize', async () => {
12
- const { container } = render(
13
- <CMultiSelectSelectAllButton placeholder="some placeholder">
14
- bazinga
15
- </CMultiSelectSelectAllButton>,
16
- )
17
- expect(container).toMatchSnapshot()
18
- expect(container.firstChild).toHaveClass('form-multi-select-all')
19
- expect(container.firstChild).toHaveAttribute('type', 'button')
20
- expect(container.firstChild).toHaveTextContent('bazinga')
21
- })
@@ -1,19 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`CMultiSelectCleaner customize 1`] = `
4
- <div>
5
- <button
6
- class="form-multi-select-selection-cleaner"
7
- type="button"
8
- />
9
- </div>
10
- `;
11
-
12
- exports[`loads and displays CMultiSelectCleaner component 1`] = `
13
- <div>
14
- <button
15
- class="form-multi-select-selection-cleaner"
16
- type="button"
17
- />
18
- </div>
19
- `;
@@ -1,20 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`CMultiSelectSearchInput customize 1`] = `
4
- <div>
5
- <input
6
- class="form-multi-select-search"
7
- placeholder="some placeholder"
8
- type="text"
9
- />
10
- </div>
11
- `;
12
-
13
- exports[`loads and displays CMultiSelectSearchInput component 1`] = `
14
- <div>
15
- <input
16
- class="form-multi-select-search"
17
- type="text"
18
- />
19
- </div>
20
- `;
@@ -1,24 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`CMultiSelectSelectAllButton customize 1`] = `
4
- <div>
5
- <button
6
- class="form-multi-select-all"
7
- placeholder="some placeholder"
8
- type="button"
9
- >
10
- bazinga
11
- </button>
12
- </div>
13
- `;
14
-
15
- exports[`loads and displays CMultiSelectSelectAllButton component 1`] = `
16
- <div>
17
- <button
18
- class="form-multi-select-all"
19
- type="button"
20
- >
21
- text
22
- </button>
23
- </div>
24
- `;
@@ -1,37 +0,0 @@
1
- import PropTypes from 'prop-types'
2
- import React, { forwardRef, HTMLAttributes, ReactNode } from 'react'
3
-
4
- import { cilFilterX } from '@coreui/icons'
5
-
6
- import CIcon from '@coreui/icons-react'
7
-
8
- interface CSmartTableCleanerProps extends HTMLAttributes<HTMLButtonElement> {
9
- content?: string | ReactNode
10
- isFiltered?: string
11
- }
12
-
13
- export const CSmartTableCleaner = forwardRef<HTMLButtonElement, CSmartTableCleanerProps>(
14
- ({ content = <CIcon width={18} icon={cilFilterX} />, isFiltered, ...rest }, ref) => {
15
- return (
16
- <button
17
- type="button"
18
- className="btn btn-transparent"
19
- {...(!isFiltered && {
20
- disabled: true,
21
- tabIndex: -1,
22
- })}
23
- {...rest}
24
- ref={ref}
25
- >
26
- {content}
27
- </button>
28
- )
29
- },
30
- )
31
-
32
- CSmartTableCleaner.propTypes = {
33
- content: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
34
- isFiltered: PropTypes.string,
35
- }
36
-
37
- CSmartTableCleaner.displayName = 'CSmartTableCleaner'