@coreui/react-pro 5.0.0-alpha.0 → 5.0.0-alpha.1
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.
- package/README.md +1 -1
- package/dist/components/calendar/CCalendar.d.ts +25 -7
- package/dist/components/calendar/utils.d.ts +12 -3
- package/dist/components/close-button/CCloseButton.d.ts +6 -0
- package/dist/components/modal/CModal.d.ts +6 -0
- package/dist/components/multi-select/types.d.ts +2 -2
- package/dist/components/multi-select/utils.d.ts +2 -2
- package/dist/components/nav/CNav.d.ts +1 -1
- package/dist/components/navbar/CNavbar.d.ts +1 -1
- package/dist/components/offcanvas/COffcanvas.d.ts +4 -0
- package/dist/components/smart-table/CSmartTableBody.d.ts +2 -1
- package/dist/components/smart-table/CSmartTableInterface.d.ts +1 -3
- package/dist/components/smart-table/types.d.ts +2 -2
- package/dist/components/smart-table/utils.d.ts +3 -1
- package/dist/index.es.js +1388 -1097
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1388 -1097
- package/dist/index.js.map +1 -1
- package/dist/utils/executeAfterTransition.d.ts +2 -0
- package/dist/utils/getTransitionDurationFromElement.d.ts +2 -0
- package/dist/utils/index.d.ts +3 -1
- package/package.json +2 -2
- package/src/components/calendar/CCalendar.tsx +396 -193
- package/src/components/calendar/utils.ts +91 -4
- package/src/components/carousel/CCarousel.tsx +9 -5
- package/src/components/close-button/CCloseButton.tsx +9 -1
- package/src/components/date-range-picker/CDateRangePicker.tsx +49 -45
- package/src/components/dropdown/CDropdownMenu.tsx +1 -1
- package/src/components/modal/CModal.tsx +25 -9
- package/src/components/multi-select/CMultiSelect.tsx +3 -3
- package/src/components/multi-select/CMultiSelectNativeSelect.tsx +1 -1
- package/src/components/multi-select/CMultiSelectOptions.tsx +1 -1
- package/src/components/multi-select/CMultiSelectSelection.tsx +3 -3
- package/src/components/multi-select/types.ts +2 -2
- package/src/components/multi-select/utils.ts +5 -5
- package/src/components/nav/CNav.tsx +2 -2
- package/src/components/nav/CNavGroup.tsx +9 -2
- package/src/components/navbar/CNavbar.tsx +2 -2
- package/src/components/offcanvas/COffcanvas.tsx +8 -1
- package/src/components/popover/CPopover.tsx +2 -2
- package/src/components/sidebar/CSidebar.tsx +1 -1
- package/src/components/smart-table/CSmartTable.tsx +2 -1
- package/src/components/smart-table/CSmartTableBody.tsx +11 -5
- package/src/components/smart-table/CSmartTableInterface.tsx +1 -3
- package/src/components/smart-table/types.ts +2 -2
- package/src/components/smart-table/utils.ts +40 -5
- package/src/components/time-picker/CTimePicker.tsx +2 -2
- package/src/components/time-picker/utils.ts +5 -1
- package/src/components/tooltip/CTooltip.tsx +2 -2
- package/src/hooks/usePopper.ts +10 -2
- package/src/utils/executeAfterTransition.ts +46 -0
- package/src/utils/getTransitionDurationFromElement.ts +24 -0
- package/src/utils/index.ts +10 -1
|
@@ -19,7 +19,7 @@ export interface CNavProps
|
|
|
19
19
|
/**
|
|
20
20
|
* Set the nav variant to tabs or pills.
|
|
21
21
|
*/
|
|
22
|
-
variant?: '
|
|
22
|
+
variant?: 'pills' | 'tabs' | 'underline'
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export const CNav = forwardRef<HTMLDivElement | HTMLUListElement | HTMLOListElement, CNavProps>(
|
|
@@ -49,7 +49,7 @@ CNav.propTypes = {
|
|
|
49
49
|
className: PropTypes.string,
|
|
50
50
|
component: PropTypes.elementType,
|
|
51
51
|
layout: PropTypes.oneOf(['fill', 'justified']),
|
|
52
|
-
variant: PropTypes.oneOf(['
|
|
52
|
+
variant: PropTypes.oneOf(['pills', 'tabs', 'underline']),
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
CNav.displayName = 'CNav'
|
|
@@ -36,6 +36,13 @@ export interface CNavGroupProps {
|
|
|
36
36
|
idx?: string
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
const isInVisibleGroup = (el1: string, el2: string) => {
|
|
40
|
+
const array1 = el1.toString().split('.')
|
|
41
|
+
const array2 = el2.toString().split('.')
|
|
42
|
+
|
|
43
|
+
return array2.every((item, index) => item === array1[index])
|
|
44
|
+
}
|
|
45
|
+
|
|
39
46
|
export const CNavGroup = forwardRef<HTMLLIElement, CNavGroupProps>(
|
|
40
47
|
({ children, className, compact, idx, toggler, visible, ...rest }, ref) => {
|
|
41
48
|
const [height, setHeight] = useState<number | string>()
|
|
@@ -45,12 +52,12 @@ export const CNavGroup = forwardRef<HTMLLIElement, CNavGroupProps>(
|
|
|
45
52
|
|
|
46
53
|
const [_visible, setVisible] = useState(
|
|
47
54
|
Boolean(
|
|
48
|
-
visible || (idx && visibleGroup && visibleGroup
|
|
55
|
+
visible || (idx && visibleGroup && isInVisibleGroup(visibleGroup, idx)),
|
|
49
56
|
),
|
|
50
57
|
)
|
|
51
58
|
|
|
52
59
|
useEffect(() => {
|
|
53
|
-
setVisible(Boolean(idx && visibleGroup && visibleGroup
|
|
60
|
+
setVisible(Boolean(idx && visibleGroup && isInVisibleGroup(visibleGroup, idx)))
|
|
54
61
|
}, [visibleGroup])
|
|
55
62
|
|
|
56
63
|
const handleTogglerOnCLick = (event: React.MouseEvent<HTMLElement>) => {
|
|
@@ -17,7 +17,7 @@ export interface CNavbarProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
17
17
|
*/
|
|
18
18
|
color?: Colors
|
|
19
19
|
/**
|
|
20
|
-
* Sets if the color of text should be colored for a light or dark
|
|
20
|
+
* Sets if the color of text should be colored for a light or dark background.
|
|
21
21
|
*/
|
|
22
22
|
colorScheme?: 'dark' | 'light'
|
|
23
23
|
/**
|
|
@@ -59,12 +59,12 @@ export const CNavbar = forwardRef<HTMLDivElement, CNavbarProps>(
|
|
|
59
59
|
'navbar',
|
|
60
60
|
{
|
|
61
61
|
[`bg-${color}`]: color,
|
|
62
|
-
[`navbar-${colorScheme}`]: colorScheme,
|
|
63
62
|
[typeof expand === 'boolean' ? 'navbar-expand' : `navbar-expand-${expand}`]: expand,
|
|
64
63
|
},
|
|
65
64
|
placement,
|
|
66
65
|
className,
|
|
67
66
|
)}
|
|
67
|
+
{...(colorScheme && { 'data-coreui-theme': colorScheme })}
|
|
68
68
|
{...rest}
|
|
69
69
|
ref={ref}
|
|
70
70
|
>
|
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import { Transition } from 'react-transition-group'
|
|
5
5
|
|
|
6
|
-
import { CBackdrop } from '../backdrop
|
|
6
|
+
import { CBackdrop } from '../backdrop'
|
|
7
7
|
import { CConditionalPortal } from '../conditional-portal'
|
|
8
8
|
|
|
9
9
|
import { useForkedRef } from '../../hooks'
|
|
@@ -17,6 +17,10 @@ export interface COffcanvasProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
17
17
|
* A string of all className you want applied to the base component.
|
|
18
18
|
*/
|
|
19
19
|
className?: string
|
|
20
|
+
/**
|
|
21
|
+
* Sets a darker color scheme.
|
|
22
|
+
*/
|
|
23
|
+
dark?: boolean
|
|
20
24
|
/**
|
|
21
25
|
* Closes the offcanvas when escape key is pressed.
|
|
22
26
|
*/
|
|
@@ -59,6 +63,7 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
|
|
|
59
63
|
children,
|
|
60
64
|
backdrop = true,
|
|
61
65
|
className,
|
|
66
|
+
dark,
|
|
62
67
|
keyboard = true,
|
|
63
68
|
onHide,
|
|
64
69
|
onShow,
|
|
@@ -135,6 +140,7 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
|
|
|
135
140
|
role="dialog"
|
|
136
141
|
tabIndex={-1}
|
|
137
142
|
onKeyDown={handleKeyDown}
|
|
143
|
+
{...(dark && { 'data-coreui-theme': 'dark' })}
|
|
138
144
|
{...rest}
|
|
139
145
|
ref={forkedRef}
|
|
140
146
|
>
|
|
@@ -161,6 +167,7 @@ COffcanvas.propTypes = {
|
|
|
161
167
|
backdrop: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf<'static'>(['static'])]),
|
|
162
168
|
children: PropTypes.node,
|
|
163
169
|
className: PropTypes.string,
|
|
170
|
+
dark: PropTypes.bool,
|
|
164
171
|
keyboard: PropTypes.bool,
|
|
165
172
|
onHide: PropTypes.func,
|
|
166
173
|
onShow: PropTypes.func,
|
|
@@ -7,7 +7,7 @@ import { Transition } from 'react-transition-group'
|
|
|
7
7
|
import { usePopper } from '../../hooks'
|
|
8
8
|
import { fallbackPlacementsPropType, triggerPropType } from '../../props'
|
|
9
9
|
import type { Placements, Triggers } from '../../types'
|
|
10
|
-
import { getRTLPlacement } from '../../utils'
|
|
10
|
+
import { getRTLPlacement, getTransitionDurationFromElement } from '../../utils'
|
|
11
11
|
|
|
12
12
|
export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'content'> {
|
|
13
13
|
/**
|
|
@@ -164,7 +164,7 @@ export const CPopover: FC<CPopoverProps> = ({
|
|
|
164
164
|
onExit={onHide}
|
|
165
165
|
timeout={{
|
|
166
166
|
enter: 0,
|
|
167
|
-
exit: 200,
|
|
167
|
+
exit: popoverRef.current ? getTransitionDurationFromElement(popoverRef.current) + 50 : 200,
|
|
168
168
|
}}
|
|
169
169
|
unmountOnExit
|
|
170
170
|
>
|
|
@@ -3,7 +3,7 @@ import { createPortal } from 'react-dom'
|
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
4
|
import classNames from 'classnames'
|
|
5
5
|
|
|
6
|
-
import { CBackdrop } from '../backdrop
|
|
6
|
+
import { CBackdrop } from '../backdrop'
|
|
7
7
|
|
|
8
8
|
import { isInViewport } from '../../utils'
|
|
9
9
|
import { useForkedRef } from '../../hooks'
|
|
@@ -409,6 +409,8 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
409
409
|
)}
|
|
410
410
|
<CSmartTableBody
|
|
411
411
|
clickableRows={clickableRows}
|
|
412
|
+
columnNames={columnNames}
|
|
413
|
+
columns={columns ?? columnNames}
|
|
412
414
|
currentItems={currentItems}
|
|
413
415
|
firstItemOnActivePageIndex={firstItemOnActivePageIndex}
|
|
414
416
|
noItemsLabel={noItemsLabel}
|
|
@@ -416,7 +418,6 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
416
418
|
clickableRows && onRowClick && onRowClick(item, index, columnName, event)
|
|
417
419
|
}
|
|
418
420
|
onRowChecked={(item, value) => handleRowChecked(item, value)}
|
|
419
|
-
columnNames={columnNames}
|
|
420
421
|
scopedColumns={scopedColumns}
|
|
421
422
|
selectable={selectable}
|
|
422
423
|
selected={_selected}
|
|
@@ -7,12 +7,13 @@ import { CTableDataCell, CTableRow } from '../table'
|
|
|
7
7
|
|
|
8
8
|
import { isObjectInArray } from '../../utils'
|
|
9
9
|
|
|
10
|
-
import type { Item, ScopedColumns } from './types'
|
|
11
|
-
import { getClickedColumnName, getTableDataCellProps } from './utils'
|
|
10
|
+
import type { Column, Item, ScopedColumns } from './types'
|
|
11
|
+
import { getClickedColumnName, getColumnName, getTableDataCellProps, getTableDataCellStyles } from './utils'
|
|
12
12
|
|
|
13
13
|
export interface CSmartTableBodyProps extends CTableBodyProps {
|
|
14
14
|
clickableRows?: boolean
|
|
15
15
|
columnNames: string[]
|
|
16
|
+
columns: (Column | string)[]
|
|
16
17
|
currentItems: Item[]
|
|
17
18
|
firstItemOnActivePageIndex: number
|
|
18
19
|
noItemsLabel?: string | ReactNode
|
|
@@ -28,6 +29,7 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
|
|
|
28
29
|
{
|
|
29
30
|
clickableRows,
|
|
30
31
|
columnNames,
|
|
32
|
+
columns,
|
|
31
33
|
currentItems,
|
|
32
34
|
firstItemOnActivePageIndex,
|
|
33
35
|
noItemsLabel,
|
|
@@ -40,7 +42,7 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
|
|
|
40
42
|
},
|
|
41
43
|
ref,
|
|
42
44
|
) => {
|
|
43
|
-
const colspan: number = selectable ?
|
|
45
|
+
const colspan: number = selectable ? columns.length + 1 : columns.length
|
|
44
46
|
|
|
45
47
|
return (
|
|
46
48
|
<CTableBody
|
|
@@ -84,7 +86,8 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
|
|
|
84
86
|
/>
|
|
85
87
|
</CTableDataCell>
|
|
86
88
|
)}
|
|
87
|
-
{
|
|
89
|
+
{columns.map((column, index) => {
|
|
90
|
+
const colName = getColumnName(column)
|
|
88
91
|
return (
|
|
89
92
|
(scopedColumns &&
|
|
90
93
|
scopedColumns[colName] &&
|
|
@@ -95,7 +98,10 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
|
|
|
95
98
|
},
|
|
96
99
|
)) ||
|
|
97
100
|
(item[colName] !== undefined && (
|
|
98
|
-
<CTableDataCell
|
|
101
|
+
<CTableDataCell
|
|
102
|
+
{...getTableDataCellProps(column, item, colName)}
|
|
103
|
+
style={getTableDataCellStyles(column, item, colName)}
|
|
104
|
+
key={index}>
|
|
99
105
|
{item[colName]}
|
|
100
106
|
</CTableDataCell>
|
|
101
107
|
))
|
|
@@ -115,9 +115,7 @@ export interface CSmartTableProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
115
115
|
itemsPerPageOptions?: number[]
|
|
116
116
|
/**
|
|
117
117
|
* Adds select element over table, which is used for control items per page in pagination. If you want to customize this element, pass object with optional values:
|
|
118
|
-
* -
|
|
119
|
-
* - values (Array) - custom array of pagination values
|
|
120
|
-
* - external (Boolean) - disables automatic 'itemsPerPage' change (use to change pages externaly by 'pagination-change' event).
|
|
118
|
+
* - external (Boolean) - disables automatic 'itemsPerPage' change.
|
|
121
119
|
*/
|
|
122
120
|
itemsPerPageSelect?: boolean | ItemsPerPageSelect
|
|
123
121
|
/**
|
|
@@ -13,6 +13,8 @@ export type Column = {
|
|
|
13
13
|
sorter?: boolean
|
|
14
14
|
_style?: any
|
|
15
15
|
_props?: CTableHeaderCellProps
|
|
16
|
+
_colStyle?: any
|
|
17
|
+
_colProps?: CTableDataCellProps
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export type ColumnFilter = {
|
|
@@ -49,8 +51,6 @@ export type Item = {
|
|
|
49
51
|
|
|
50
52
|
export type ItemsPerPageSelect = {
|
|
51
53
|
external?: boolean
|
|
52
|
-
label?: string
|
|
53
|
-
values?: Array<number>
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
export type Pagination = {
|
|
@@ -65,7 +65,7 @@ export const getClickedColumnName = (
|
|
|
65
65
|
const closest = target.closest('tr')
|
|
66
66
|
const children = closest ? Array.from(closest.children) : []
|
|
67
67
|
const clickedCell = children.filter((child) => child.contains(target))[0]
|
|
68
|
-
return columnNames[children.indexOf(clickedCell)]
|
|
68
|
+
return columnNames[children.indexOf(clickedCell) - 1]
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
export const getColumnKey = (column: Column | string) =>
|
|
@@ -78,6 +78,14 @@ export const getColumnLabel = (column: Column | string) =>
|
|
|
78
78
|
: pretifyName(column.key)
|
|
79
79
|
: pretifyName(column)
|
|
80
80
|
|
|
81
|
+
export const getColumnName = (column: string | Column) => {
|
|
82
|
+
if (typeof column === 'object') {
|
|
83
|
+
return column.key
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return column
|
|
87
|
+
}
|
|
88
|
+
|
|
81
89
|
export const getColumnNames = (
|
|
82
90
|
columns: (string | Column)[] | undefined,
|
|
83
91
|
items: Item[],
|
|
@@ -217,15 +225,42 @@ export const getColumnValues = (items: Item[], key: string) => {
|
|
|
217
225
|
return items.map((item) => item[key])
|
|
218
226
|
}
|
|
219
227
|
|
|
220
|
-
export const getTableDataCellProps = (item: Item, colName: string) => {
|
|
221
|
-
const props =
|
|
222
|
-
|
|
223
|
-
|
|
228
|
+
export const getTableDataCellProps = (column: Column | string, item: Item, colName: string) => {
|
|
229
|
+
const props = {}
|
|
230
|
+
|
|
231
|
+
if (typeof column === 'object' && column._colProps) {
|
|
232
|
+
Object.assign(props, column._colProps)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (item._cellProps && item._cellProps['all']) {
|
|
236
|
+
Object.assign(props, item._cellProps['all'])
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (item._cellProps && item._cellProps[colName]) {
|
|
240
|
+
Object.assign(props, item._cellProps[colName])
|
|
224
241
|
}
|
|
225
242
|
|
|
226
243
|
return props
|
|
227
244
|
}
|
|
228
245
|
|
|
246
|
+
export const getTableDataCellStyles = (column: Column | string, item: Item, colName: string) => {
|
|
247
|
+
const styles = {}
|
|
248
|
+
|
|
249
|
+
if (typeof column === 'object' && column._colStyle) {
|
|
250
|
+
Object.assign(styles, column._colStyle)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (item._cellStyle && item._cellStyle['all']) {
|
|
254
|
+
Object.assign(styles, item._cellStyle['all'])
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (item._cellStyle && item._cellStyle[colName]) {
|
|
258
|
+
Object.assign(styles, item._cellStyle[colName])
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return styles
|
|
262
|
+
}
|
|
263
|
+
|
|
229
264
|
export const getTableHeaderCellProps = (column: Column | string) => {
|
|
230
265
|
if (typeof column === 'object' && column._props) {
|
|
231
266
|
return column._props
|
|
@@ -171,7 +171,7 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
|
|
|
171
171
|
|
|
172
172
|
const [date, setDate] = useState<Date | null>(convertTimeToDate(time))
|
|
173
173
|
const [initialDate, setInitialDate] = useState<Date | null>(null)
|
|
174
|
-
const [isValid, setIsValid] = useState(valid
|
|
174
|
+
const [isValid, setIsValid] = useState(valid ?? (invalid === true ? false : undefined))
|
|
175
175
|
const [_ampm, setAmPm] = useState<'am' | 'pm'>(date ? getAmPm(new Date(date), locale) : 'am')
|
|
176
176
|
const [_visible, setVisible] = useState(visible)
|
|
177
177
|
|
|
@@ -187,7 +187,7 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
|
|
|
187
187
|
}, [time])
|
|
188
188
|
|
|
189
189
|
useEffect(() => {
|
|
190
|
-
setIsValid(valid
|
|
190
|
+
setIsValid(valid ?? (invalid === true ? false : undefined))
|
|
191
191
|
}, [valid, invalid])
|
|
192
192
|
|
|
193
193
|
useEffect(() => {
|
|
@@ -16,7 +16,11 @@ export const convert12hTo24h = (abbr: 'am' | 'pm', hour: number) => {
|
|
|
16
16
|
export const convert24hTo12h = (hour: number) => hour % 12 || 12
|
|
17
17
|
|
|
18
18
|
export const convertTimeToDate = (time: Date | string | null | undefined) =>
|
|
19
|
-
time
|
|
19
|
+
time
|
|
20
|
+
? time instanceof Date
|
|
21
|
+
? time
|
|
22
|
+
: new Date(`1970-01-01 ${time}`)
|
|
23
|
+
: null
|
|
20
24
|
|
|
21
25
|
export const getAmPm = (date: Date, locale: string) => {
|
|
22
26
|
if (date.toLocaleTimeString(locale).includes('AM')) {
|
|
@@ -7,7 +7,7 @@ import { Transition } from 'react-transition-group'
|
|
|
7
7
|
import { usePopper } from '../../hooks'
|
|
8
8
|
import { fallbackPlacementsPropType, triggerPropType } from '../../props'
|
|
9
9
|
import type { Placements, Triggers } from '../../types'
|
|
10
|
-
import { getRTLPlacement } from '../../utils'
|
|
10
|
+
import { getRTLPlacement, getTransitionDurationFromElement } from '../../utils'
|
|
11
11
|
|
|
12
12
|
export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {
|
|
13
13
|
/**
|
|
@@ -158,7 +158,7 @@ export const CTooltip: FC<CTooltipProps> = ({
|
|
|
158
158
|
onExit={onHide}
|
|
159
159
|
timeout={{
|
|
160
160
|
enter: 0,
|
|
161
|
-
exit: 200,
|
|
161
|
+
exit: tooltipRef.current ? getTransitionDurationFromElement(tooltipRef.current) + 50 : 200,
|
|
162
162
|
}}
|
|
163
163
|
unmountOnExit
|
|
164
164
|
>
|
package/src/hooks/usePopper.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { useRef } from 'react'
|
|
|
2
2
|
import { createPopper } from '@popperjs/core'
|
|
3
3
|
import type { Instance, Options } from '@popperjs/core'
|
|
4
4
|
|
|
5
|
+
import { executeAfterTransition } from '../utils'
|
|
6
|
+
|
|
5
7
|
interface UsePopperOutput {
|
|
6
8
|
popper: Instance | undefined
|
|
7
9
|
initPopper: (reference: HTMLElement, popper: HTMLElement, options: Partial<Options>) => void
|
|
@@ -10,14 +12,20 @@ interface UsePopperOutput {
|
|
|
10
12
|
|
|
11
13
|
export const usePopper = (): UsePopperOutput => {
|
|
12
14
|
const _popper = useRef<Instance>()
|
|
15
|
+
const el = useRef<HTMLElement>()
|
|
13
16
|
|
|
14
17
|
const initPopper = (reference: HTMLElement, popper: HTMLElement, options: Partial<Options>) => {
|
|
15
18
|
_popper.current = createPopper(reference, popper, options)
|
|
19
|
+
el.current = popper
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
const destroyPopper = () => {
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
const popperInstance = _popper.current
|
|
24
|
+
|
|
25
|
+
if (popperInstance && el.current) {
|
|
26
|
+
executeAfterTransition(() => {
|
|
27
|
+
popperInstance.destroy()
|
|
28
|
+
}, el.current)
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
_popper.current = undefined
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import getTransitionDurationFromElement from './getTransitionDurationFromElement'
|
|
2
|
+
|
|
3
|
+
const execute = (callback: () => void) => {
|
|
4
|
+
if (typeof callback === 'function') {
|
|
5
|
+
callback()
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const triggerTransitionEnd = (element: HTMLElement) => {
|
|
10
|
+
element.dispatchEvent(new Event('transitionend'))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const executeAfterTransition = (
|
|
14
|
+
callback: () => void,
|
|
15
|
+
transitionElement: HTMLElement,
|
|
16
|
+
waitForTransition = true,
|
|
17
|
+
) => {
|
|
18
|
+
if (!waitForTransition) {
|
|
19
|
+
execute(callback)
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const durationPadding = 5
|
|
24
|
+
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding
|
|
25
|
+
|
|
26
|
+
let called = false
|
|
27
|
+
|
|
28
|
+
const handler = ({ target }: { target: any }) => {
|
|
29
|
+
if (target !== transitionElement) {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
called = true
|
|
34
|
+
transitionElement.removeEventListener('transitionend', handler)
|
|
35
|
+
execute(callback)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
transitionElement.addEventListener('transitionend', handler)
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
if (!called) {
|
|
41
|
+
triggerTransitionEnd(transitionElement)
|
|
42
|
+
}
|
|
43
|
+
}, emulatedDuration)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default executeAfterTransition
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const getTransitionDurationFromElement = (element: HTMLElement) => {
|
|
2
|
+
if (!element) {
|
|
3
|
+
return 0
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// Get transition-duration of the element
|
|
7
|
+
let { transitionDuration, transitionDelay } = window.getComputedStyle(element)
|
|
8
|
+
|
|
9
|
+
const floatTransitionDuration = Number.parseFloat(transitionDuration)
|
|
10
|
+
const floatTransitionDelay = Number.parseFloat(transitionDelay)
|
|
11
|
+
|
|
12
|
+
// Return 0 if element or transition duration is not found
|
|
13
|
+
if (!floatTransitionDuration && !floatTransitionDelay) {
|
|
14
|
+
return 0
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// If multiple durations are defined, take the first
|
|
18
|
+
transitionDuration = transitionDuration.split(',')[0]
|
|
19
|
+
transitionDelay = transitionDelay.split(',')[0]
|
|
20
|
+
|
|
21
|
+
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * 1000
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default getTransitionDurationFromElement
|
package/src/utils/index.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import executeAfterTransition from './executeAfterTransition'
|
|
1
2
|
import getRTLPlacement from './getRTLPlacement'
|
|
3
|
+
import getTransitionDurationFromElement from './getTransitionDurationFromElement'
|
|
2
4
|
import isInViewport from './isInViewport'
|
|
3
5
|
import isObjectInArray from './isObjectInArray'
|
|
4
6
|
import isRTL from './isRTL'
|
|
5
7
|
|
|
6
|
-
export {
|
|
8
|
+
export {
|
|
9
|
+
executeAfterTransition,
|
|
10
|
+
getRTLPlacement,
|
|
11
|
+
getTransitionDurationFromElement,
|
|
12
|
+
isInViewport,
|
|
13
|
+
isObjectInArray,
|
|
14
|
+
isRTL,
|
|
15
|
+
}
|