@coreui/react-pro 5.1.0 → 5.2.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 (93) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/components/calendar/CCalendar.js +2 -2
  3. package/dist/cjs/components/calendar/CCalendar.js.map +1 -1
  4. package/dist/cjs/components/calendar/utils.d.ts +1 -0
  5. package/dist/cjs/components/calendar/utils.js +14 -5
  6. package/dist/cjs/components/calendar/utils.js.map +1 -1
  7. package/dist/cjs/components/date-range-picker/CDateRangePicker.js +1 -1
  8. package/dist/cjs/components/date-range-picker/CDateRangePicker.js.map +1 -1
  9. package/dist/cjs/components/dropdown/CDropdown.js +2 -1
  10. package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
  11. package/dist/cjs/components/dropdown/utils.d.ts +0 -1
  12. package/dist/cjs/components/dropdown/utils.js +0 -13
  13. package/dist/cjs/components/dropdown/utils.js.map +1 -1
  14. package/dist/cjs/components/multi-select/CMultiSelect.js +4 -0
  15. package/dist/cjs/components/multi-select/CMultiSelect.js.map +1 -1
  16. package/dist/cjs/components/multi-select/CMultiSelectSelection.js +1 -1
  17. package/dist/cjs/components/multi-select/CMultiSelectSelection.js.map +1 -1
  18. package/dist/cjs/components/tabs/CTab.d.ts +12 -0
  19. package/dist/cjs/components/tabs/CTab.js +25 -0
  20. package/dist/cjs/components/tabs/CTab.js.map +1 -0
  21. package/dist/cjs/components/tabs/CTabList.d.ts +16 -0
  22. package/dist/cjs/components/tabs/CTabList.js +54 -0
  23. package/dist/cjs/components/tabs/CTabList.js.map +1 -0
  24. package/dist/cjs/components/tabs/CTabPane.d.ts +6 -0
  25. package/dist/cjs/components/tabs/CTabPane.js +4 -2
  26. package/dist/cjs/components/tabs/CTabPane.js.map +1 -1
  27. package/dist/cjs/components/tabs/CTabPanel.d.ts +28 -0
  28. package/dist/cjs/components/tabs/CTabPanel.js +43 -0
  29. package/dist/cjs/components/tabs/CTabPanel.js.map +1 -0
  30. package/dist/cjs/components/tabs/CTabs.d.ts +22 -0
  31. package/dist/cjs/components/tabs/CTabs.js +28 -0
  32. package/dist/cjs/components/tabs/CTabs.js.map +1 -0
  33. package/dist/cjs/components/tabs/index.d.ts +5 -1
  34. package/dist/cjs/index.js +8 -0
  35. package/dist/cjs/index.js.map +1 -1
  36. package/dist/cjs/utils/getNextActiveElement.d.ts +2 -0
  37. package/dist/cjs/utils/getNextActiveElement.js +19 -0
  38. package/dist/cjs/utils/getNextActiveElement.js.map +1 -0
  39. package/dist/cjs/utils/index.d.ts +2 -1
  40. package/dist/esm/components/calendar/CCalendar.js +2 -2
  41. package/dist/esm/components/calendar/CCalendar.js.map +1 -1
  42. package/dist/esm/components/calendar/utils.d.ts +1 -0
  43. package/dist/esm/components/calendar/utils.js +14 -6
  44. package/dist/esm/components/calendar/utils.js.map +1 -1
  45. package/dist/esm/components/date-range-picker/CDateRangePicker.js +1 -1
  46. package/dist/esm/components/date-range-picker/CDateRangePicker.js.map +1 -1
  47. package/dist/esm/components/dropdown/CDropdown.js +2 -1
  48. package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
  49. package/dist/esm/components/dropdown/utils.d.ts +0 -1
  50. package/dist/esm/components/dropdown/utils.js +1 -13
  51. package/dist/esm/components/dropdown/utils.js.map +1 -1
  52. package/dist/esm/components/multi-select/CMultiSelect.js +4 -0
  53. package/dist/esm/components/multi-select/CMultiSelect.js.map +1 -1
  54. package/dist/esm/components/multi-select/CMultiSelectSelection.js +1 -1
  55. package/dist/esm/components/multi-select/CMultiSelectSelection.js.map +1 -1
  56. package/dist/esm/components/tabs/CTab.d.ts +12 -0
  57. package/dist/esm/components/tabs/CTab.js +23 -0
  58. package/dist/esm/components/tabs/CTab.js.map +1 -0
  59. package/dist/esm/components/tabs/CTabList.d.ts +16 -0
  60. package/dist/esm/components/tabs/CTabList.js +52 -0
  61. package/dist/esm/components/tabs/CTabList.js.map +1 -0
  62. package/dist/esm/components/tabs/CTabPane.d.ts +6 -0
  63. package/dist/esm/components/tabs/CTabPane.js +4 -2
  64. package/dist/esm/components/tabs/CTabPane.js.map +1 -1
  65. package/dist/esm/components/tabs/CTabPanel.d.ts +28 -0
  66. package/dist/esm/components/tabs/CTabPanel.js +41 -0
  67. package/dist/esm/components/tabs/CTabPanel.js.map +1 -0
  68. package/dist/esm/components/tabs/CTabs.d.ts +22 -0
  69. package/dist/esm/components/tabs/CTabs.js +25 -0
  70. package/dist/esm/components/tabs/CTabs.js.map +1 -0
  71. package/dist/esm/components/tabs/index.d.ts +5 -1
  72. package/dist/esm/index.js +4 -0
  73. package/dist/esm/index.js.map +1 -1
  74. package/dist/esm/utils/getNextActiveElement.d.ts +2 -0
  75. package/dist/esm/utils/getNextActiveElement.js +15 -0
  76. package/dist/esm/utils/getNextActiveElement.js.map +1 -0
  77. package/dist/esm/utils/index.d.ts +2 -1
  78. package/package.json +6 -6
  79. package/src/components/calendar/CCalendar.tsx +2 -2
  80. package/src/components/calendar/utils.ts +23 -7
  81. package/src/components/date-range-picker/CDateRangePicker.tsx +1 -1
  82. package/src/components/dropdown/CDropdown.tsx +2 -2
  83. package/src/components/dropdown/utils.ts +0 -22
  84. package/src/components/multi-select/CMultiSelect.tsx +5 -0
  85. package/src/components/multi-select/CMultiSelectSelection.tsx +1 -0
  86. package/src/components/tabs/CTab.tsx +56 -0
  87. package/src/components/tabs/CTabList.tsx +92 -0
  88. package/src/components/tabs/CTabPane.tsx +9 -2
  89. package/src/components/tabs/CTabPanel.tsx +98 -0
  90. package/src/components/tabs/CTabs.tsx +54 -0
  91. package/src/components/tabs/index.ts +5 -1
  92. package/src/utils/getNextActiveElement.ts +23 -0
  93. package/src/utils/index.ts +2 -0
@@ -0,0 +1,22 @@
1
+ import React, { HTMLAttributes } from 'react';
2
+ export interface CTabsProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
3
+ /**
4
+ * The active item key.
5
+ */
6
+ activeItemKey: number | string;
7
+ /**
8
+ * A string of all className you want applied to the base component.
9
+ */
10
+ className?: string;
11
+ /**
12
+ * The callback is fired when the active tab changes.
13
+ */
14
+ onChange?: (value: number | string) => void;
15
+ }
16
+ export interface TabsContextProps {
17
+ _activeItemKey?: number | string;
18
+ setActiveItemKey: React.Dispatch<React.SetStateAction<number | string | undefined>>;
19
+ id?: string;
20
+ }
21
+ export declare const TabsContext: React.Context<TabsContextProps>;
22
+ export declare const CTabs: React.ForwardRefExoticComponent<CTabsProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,25 @@
1
+ import React, { createContext, forwardRef, useId, useState, useEffect } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import classNames from '../../node_modules/classnames/index.js';
4
+
5
+ var TabsContext = createContext({});
6
+ var CTabs = forwardRef(function (_a, ref) {
7
+ var children = _a.children, activeItemKey = _a.activeItemKey, className = _a.className, onChange = _a.onChange;
8
+ var id = useId();
9
+ var _b = useState(activeItemKey), _activeItemKey = _b[0], setActiveItemKey = _b[1];
10
+ useEffect(function () {
11
+ _activeItemKey && onChange && onChange(_activeItemKey);
12
+ }, [_activeItemKey]);
13
+ return (React.createElement(TabsContext.Provider, { value: { _activeItemKey: _activeItemKey, setActiveItemKey: setActiveItemKey, id: id } },
14
+ React.createElement("div", { className: classNames('tabs', className), ref: ref }, children)));
15
+ });
16
+ CTabs.propTypes = {
17
+ activeItemKey: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
18
+ children: PropTypes.node,
19
+ className: PropTypes.string,
20
+ onChange: PropTypes.func,
21
+ };
22
+ CTabs.displayName = 'CTabs';
23
+
24
+ export { CTabs, TabsContext };
25
+ //# sourceMappingURL=CTabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CTabs.js","sources":["../../../../src/components/tabs/CTabs.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;IAyBa,WAAW,GAAG,aAAa,CAAC,EAAsB,EAAC;IAEnD,KAAK,GAAG,UAAU,CAC7B,UAAC,EAAgD,EAAE,GAAG,EAAA;QAAnD,QAAQ,GAAA,EAAA,CAAA,QAAA,EAAE,aAAa,GAAA,EAAA,CAAA,aAAA,EAAE,SAAS,GAAA,EAAA,CAAA,SAAA,EAAE,QAAQ,GAAA,EAAA,CAAA,QAAA,CAAA;AAC7C,IAAA,IAAM,EAAE,GAAG,KAAK,EAAE,CAAA;IACZ,IAAA,EAAA,GAAqC,QAAQ,CAAC,aAAa,CAAC,EAA3D,cAAc,GAAA,EAAA,CAAA,CAAA,CAAA,EAAE,gBAAgB,GAAA,EAAA,CAAA,CAAA,CAA2B,CAAA;AAElE,IAAA,SAAS,CAAC,YAAA;AACR,QAAA,cAAc,IAAI,QAAQ,IAAI,QAAQ,CAAC,cAAc,CAAC,CAAA;AACxD,KAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAA;AAEpB,IAAA,QACE,KAAC,CAAA,aAAA,CAAA,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,cAAc,gBAAA,EAAE,gBAAgB,kBAAA,EAAE,EAAE,IAAA,EAAE,EAAA;AACnE,QAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAA,EACpD,QAAQ,CACL,CACe,EACxB;AACH,CAAC,EACF;AAED,KAAK,CAAC,SAAS,GAAG;AAChB,IAAA,aAAa,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU;IACnF,QAAQ,EAAE,SAAS,CAAC,IAAI;IACxB,SAAS,EAAE,SAAS,CAAC,MAAM;IAC3B,QAAQ,EAAE,SAAS,CAAC,IAAI;CACzB,CAAA;AAED,KAAK,CAAC,WAAW,GAAG,OAAO;;;;"}
@@ -1,3 +1,7 @@
1
+ import { CTab } from './CTab';
1
2
  import { CTabContent } from './CTabContent';
2
3
  import { CTabPane } from './CTabPane';
3
- export { CTabContent, CTabPane };
4
+ import { CTabPanel } from './CTabPanel';
5
+ import { CTabList } from './CTabList';
6
+ import { CTabs } from './CTabs';
7
+ export { CTab, CTabContent, CTabList, CTabPane, CTabPanel, CTabs };
package/dist/esm/index.js CHANGED
@@ -120,8 +120,12 @@ export { CTableFoot } from './components/table/CTableFoot.js';
120
120
  export { CTableHead } from './components/table/CTableHead.js';
121
121
  export { CTableHeaderCell } from './components/table/CTableHeaderCell.js';
122
122
  export { CTableRow } from './components/table/CTableRow.js';
123
+ export { CTab } from './components/tabs/CTab.js';
123
124
  export { CTabContent } from './components/tabs/CTabContent.js';
124
125
  export { CTabPane } from './components/tabs/CTabPane.js';
126
+ export { CTabPanel } from './components/tabs/CTabPanel.js';
127
+ export { CTabList } from './components/tabs/CTabList.js';
128
+ export { CTabs } from './components/tabs/CTabs.js';
125
129
  export { CTimePicker } from './components/time-picker/CTimePicker.js';
126
130
  export { CToast } from './components/toast/CToast.js';
127
131
  export { CToastBody } from './components/toast/CToastBody.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,2 @@
1
+ declare const getNextActiveElement: (list: HTMLElement[], activeElement: HTMLElement, shouldGetNext: boolean, isCycleAllowed: boolean) => HTMLElement;
2
+ export default getNextActiveElement;
@@ -0,0 +1,15 @@
1
+ var getNextActiveElement = function (list, activeElement, shouldGetNext, isCycleAllowed) {
2
+ var listLength = list.length;
3
+ var index = list.indexOf(activeElement);
4
+ if (index === -1) {
5
+ return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
6
+ }
7
+ index += shouldGetNext ? 1 : -1;
8
+ {
9
+ index = (index + listLength) % listLength;
10
+ }
11
+ return list[Math.max(0, Math.min(index, listLength - 1))];
12
+ };
13
+
14
+ export { getNextActiveElement as default };
15
+ //# sourceMappingURL=getNextActiveElement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getNextActiveElement.js","sources":["../../../src/utils/getNextActiveElement.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAM,IAAA,oBAAoB,GAAG,UAC3B,IAAmB,EACnB,aAA0B,EAC1B,aAAsB,EACtB,cAAuB,EAAA;AAEvB,IAAA,IAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAA;IAC9B,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;AAEvC,IAAA,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;QAChB,OAAO,CAAC,aAAa,IAAI,cAAc,GAAG,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;KACzE;IAED,KAAK,IAAI,aAAa,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAEX;QAClB,KAAK,GAAG,CAAC,KAAK,GAAG,UAAU,IAAI,UAAU,CAAA;KAC1C;IAED,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AAC3D;;;;"}
@@ -1,7 +1,8 @@
1
1
  import executeAfterTransition from './executeAfterTransition';
2
+ import getNextActiveElement from './getNextActiveElement';
2
3
  import getRTLPlacement from './getRTLPlacement';
3
4
  import getTransitionDurationFromElement from './getTransitionDurationFromElement';
4
5
  import isInViewport from './isInViewport';
5
6
  import isObjectInArray from './isObjectInArray';
6
7
  import isRTL from './isRTL';
7
- export { executeAfterTransition, getRTLPlacement, getTransitionDurationFromElement, isInViewport, isObjectInArray, isRTL, };
8
+ export { executeAfterTransition, getNextActiveElement, getRTLPlacement, getTransitionDurationFromElement, isInViewport, isObjectInArray, isRTL, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreui/react-pro",
3
- "version": "5.1.0",
3
+ "version": "5.2.0",
4
4
  "description": "UI Components Library for React.js",
5
5
  "keywords": [
6
6
  "react",
@@ -41,18 +41,18 @@
41
41
  "test:update": "jest --coverage --updateSnapshot"
42
42
  },
43
43
  "dependencies": {
44
- "@coreui/coreui-pro": "^5.1.0",
44
+ "@coreui/coreui-pro": "^5.2.0",
45
45
  "@popperjs/core": "^2.11.8",
46
46
  "prop-types": "^15.8.1"
47
47
  },
48
48
  "devDependencies": {
49
- "@rollup/plugin-commonjs": "^25.0.7",
49
+ "@rollup/plugin-commonjs": "^25.0.8",
50
50
  "@rollup/plugin-node-resolve": "^15.2.3",
51
51
  "@rollup/plugin-typescript": "^11.1.6",
52
52
  "@testing-library/jest-dom": "^6.4.5",
53
53
  "@testing-library/react": "^14.3.1",
54
54
  "@types/jest": "^29.5.12",
55
- "@types/react": "18.3.1",
55
+ "@types/react": "18.3.3",
56
56
  "@types/react-dom": "^18.3.0",
57
57
  "@types/react-transition-group": "^4.4.10",
58
58
  "classnames": "^2.5.1",
@@ -63,8 +63,8 @@
63
63
  "react-device-detect": "^2.2.3",
64
64
  "react-dom": "^18.3.1",
65
65
  "react-transition-group": "^4.4.5",
66
- "rollup": "^4.17.2",
67
- "ts-jest": "^29.1.2",
66
+ "rollup": "^4.18.0",
67
+ "ts-jest": "^29.1.3",
68
68
  "tslib": "^2.6.2",
69
69
  "typescript": "^5.4.5"
70
70
  },
@@ -366,7 +366,7 @@ const Calendar = (props: {
366
366
  <tr key={index}>
367
367
  {row.map((month, idx) => {
368
368
  const monthNumber = index * 3 + idx
369
- const date = new Date(Date.UTC(calendarDate.getFullYear(), monthNumber, 1))
369
+ const date = new Date(calendarDate.getFullYear(), monthNumber, 1)
370
370
  const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
371
371
  return (
372
372
  <td
@@ -403,7 +403,7 @@ const Calendar = (props: {
403
403
  return (
404
404
  <tr key={index}>
405
405
  {row.map((year, idx) => {
406
- const date = new Date(Date.UTC(year, 0, 1))
406
+ const date = new Date(year, 0, 1)
407
407
  const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
408
408
  return (
409
409
  <td
@@ -19,7 +19,10 @@ export const convertToDateObject = (
19
19
  return convertIsoWeekToDate(date as string)
20
20
  }
21
21
 
22
- return new Date(Date.parse(date))
22
+ const _date = new Date(Date.parse(date))
23
+ const userTimezoneOffset = _date.getTimezoneOffset() * 60_000
24
+
25
+ return new Date(_date.getTime() + userTimezoneOffset)
23
26
  }
24
27
 
25
28
  export const convertToLocalDate = (d: Date, locale: string, options = {}) =>
@@ -35,17 +38,21 @@ export const createGroupsInArray = <T>(arr: T[], numberOfGroups: number): T[][]
35
38
  .map((_, i) => arr.slice(i * perGroup, (i + 1) * perGroup))
36
39
  }
37
40
 
38
- export const getCalendarDate = (calendarDate: Date, order: number, view: 'days' | 'months' | 'years') => {
41
+ export const getCalendarDate = (
42
+ calendarDate: Date,
43
+ order: number,
44
+ view: 'days' | 'months' | 'years',
45
+ ) => {
39
46
  if (order !== 0 && view === 'days') {
40
- return new Date(Date.UTC(calendarDate.getFullYear(), calendarDate.getMonth() + order, 1))
47
+ return new Date(calendarDate.getFullYear(), calendarDate.getMonth() + order, 1)
41
48
  }
42
49
 
43
50
  if (order !== 0 && view === 'months') {
44
- return new Date(Date.UTC(calendarDate.getFullYear() + order, calendarDate.getMonth(), 1))
51
+ return new Date(calendarDate.getFullYear() + order, calendarDate.getMonth(), 1)
45
52
  }
46
53
 
47
54
  if (order !== 0 && view === 'years') {
48
- return new Date(Date.UTC(calendarDate.getFullYear() + (12 * order), calendarDate.getMonth(), 1))
55
+ return new Date(calendarDate.getFullYear() + 12 * order, calendarDate.getMonth(), 1)
49
56
  }
50
57
 
51
58
  return calendarDate
@@ -167,7 +174,9 @@ export const getWeekNumber = (date: Date) => {
167
174
  const week1 = new Date(date.getFullYear(), 0, 4)
168
175
  return (
169
176
  1 +
170
- Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + ((week1.getDay() + 6) % 7)) / 7)
177
+ Math.round(
178
+ ((date.getTime() - week1.getTime()) / 86_400_000 - 3 + ((week1.getDay() + 6) % 7)) / 7,
179
+ )
171
180
  )
172
181
  }
173
182
 
@@ -249,7 +258,11 @@ export const isDateDisabled = (
249
258
  }
250
259
 
251
260
  export const isDateInRange = (date: Date, start: Date | null, end: Date | null) => {
252
- return start && end && start <= date && date <= end
261
+ const _date = removeTimeFromDate(date)
262
+ const _start = start ? removeTimeFromDate(start) : null
263
+ const _end = end ? removeTimeFromDate(end) : null
264
+
265
+ return _start && _end && _start <= _date && _date <= _end
253
266
  }
254
267
 
255
268
  export const isDateSelected = (date: Date, start: Date | null, end: Date | null) => {
@@ -301,3 +314,6 @@ export const isValidDate = (date: string) => {
301
314
  const d = new Date(date)
302
315
  return d instanceof Date && d.getTime()
303
316
  }
317
+
318
+ export const removeTimeFromDate = (date: Date) =>
319
+ new Date(date.getFullYear(), date.getMonth(), date.getDate())
@@ -612,7 +612,7 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
612
612
  />
613
613
  {timepicker && (
614
614
  <div className="date-picker-timepickers">
615
- {isMobile || (range && calendars === 1) ? (
615
+ {(isMobile && range) || (range && calendars === 1) ? (
616
616
  <>
617
617
  <CTimePicker
618
618
  container="inline"
@@ -15,10 +15,10 @@ import { PolymorphicRefForwardingComponent } from '../../helpers'
15
15
  import { useForkedRef, usePopper } from '../../hooks'
16
16
  import { placementPropType } from '../../props'
17
17
  import type { Placements } from '../../types'
18
- import { isRTL } from '../../utils'
18
+ import { getNextActiveElement, isRTL } from '../../utils'
19
19
 
20
20
  import type { Alignments, Directions } from './types'
21
- import { getNextActiveElement, getPlacement } from './utils'
21
+ import { getPlacement } from './utils'
22
22
 
23
23
  export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIElement> {
24
24
  /**
@@ -19,28 +19,6 @@ export const getAlignmentClassNames = (alignment: Alignments) => {
19
19
  return classNames
20
20
  }
21
21
 
22
- export const getNextActiveElement = (
23
- list: HTMLElement[],
24
- activeElement: HTMLElement,
25
- shouldGetNext: boolean,
26
- isCycleAllowed: boolean,
27
- ) => {
28
- const listLength = list.length
29
- let index = list.indexOf(activeElement)
30
-
31
- if (index === -1) {
32
- return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]
33
- }
34
-
35
- index += shouldGetNext ? 1 : -1
36
-
37
- if (isCycleAllowed) {
38
- index = (index + listLength) % listLength
39
- }
40
-
41
- return list[Math.max(0, Math.min(index, listLength - 1))]
42
- }
43
-
44
22
  export const getPlacement = (
45
23
  placement: Placement,
46
24
  direction: string | undefined,
@@ -311,6 +311,11 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
311
311
  return () => {
312
312
  onHide && onHide()
313
313
 
314
+ setSearchValue('')
315
+ if (searchRef.current) {
316
+ searchRef.current.value = ''
317
+ }
318
+
314
319
  window.removeEventListener('mouseup', handleMouseUp)
315
320
  window.removeEventListener('keyup', handleKeyUp)
316
321
 
@@ -52,6 +52,7 @@ export const CMultiSelectSelection = forwardRef<HTMLSpanElement, CMultiSelectSel
52
52
  {!option.disabled && (
53
53
  <button
54
54
  className="form-multi-select-tag-delete"
55
+ type="button"
55
56
  aria-label="Close"
56
57
  onClick={() => onRemove && onRemove(option)}
57
58
  />
@@ -0,0 +1,56 @@
1
+ import React, { forwardRef, HTMLAttributes, useContext } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import classNames from 'classnames'
4
+
5
+ import { TabsContext } from './CTabs'
6
+
7
+ export interface CTabProps extends HTMLAttributes<HTMLButtonElement> {
8
+ /**
9
+ * A string of all className you want applied to the base component.
10
+ */
11
+ className?: string
12
+ /**
13
+ * Item key.
14
+ */
15
+ itemKey: number | string
16
+ }
17
+
18
+ export const CTab = forwardRef<HTMLButtonElement, CTabProps>(
19
+ ({ children, className, itemKey, ...rest }, ref) => {
20
+ const { _activeItemKey, setActiveItemKey, id } = useContext(TabsContext)
21
+
22
+ const isActive = () => itemKey === _activeItemKey
23
+
24
+ return (
25
+ <button
26
+ className={classNames(
27
+ 'nav-link',
28
+ {
29
+ active: isActive(),
30
+ },
31
+ className,
32
+ )}
33
+ id={`${id}${itemKey}-tab`}
34
+ onClick={() => setActiveItemKey(itemKey)}
35
+ onFocus={() => setActiveItemKey(itemKey)}
36
+ role="tab"
37
+ tabIndex={isActive() ? 0 : -1}
38
+ type="button"
39
+ aria-controls={`${id}${itemKey}-tab-pane`}
40
+ aria-selected={isActive()}
41
+ ref={ref}
42
+ {...rest}
43
+ >
44
+ {children}
45
+ </button>
46
+ )
47
+ },
48
+ )
49
+
50
+ CTab.propTypes = {
51
+ children: PropTypes.node,
52
+ className: PropTypes.string,
53
+ itemKey: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
54
+ }
55
+
56
+ CTab.displayName = 'CTab'
@@ -0,0 +1,92 @@
1
+ import React, { forwardRef, HTMLAttributes, KeyboardEvent, useRef } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import classNames from 'classnames'
4
+
5
+ import { useForkedRef } from '../../hooks'
6
+ import { getNextActiveElement } from '../../utils'
7
+
8
+ export interface CTabListProps extends HTMLAttributes<HTMLDivElement> {
9
+ /**
10
+ * A string of all className you want applied to the base component.
11
+ */
12
+ className?: string
13
+ /**
14
+ * Specify a layout type for component.
15
+ */
16
+ layout?: 'fill' | 'justified'
17
+ /**
18
+ * Set the nav variant to tabs or pills.
19
+ */
20
+ variant?: 'pills' | 'tabs' | 'underline' | 'underline-border'
21
+ }
22
+
23
+ export const CTabList = forwardRef<HTMLDivElement, CTabListProps>(
24
+ ({ children, className, layout, variant, ...rest }, ref) => {
25
+ const tabListRef = useRef<HTMLDivElement>(null)
26
+ const forkedRef = useForkedRef(ref, tabListRef)
27
+
28
+ const handleKeydown = (event: KeyboardEvent<HTMLDivElement>) => {
29
+ if (
30
+ tabListRef.current !== null &&
31
+ (event.key === 'ArrowDown' ||
32
+ event.key === 'ArrowUp' ||
33
+ event.key === 'ArrowLeft' ||
34
+ event.key === 'ArrowRight' ||
35
+ event.key === 'Home' ||
36
+ event.key === 'End')
37
+ ) {
38
+ event.preventDefault()
39
+ const target = event.target as HTMLElement
40
+ // eslint-disable-next-line unicorn/prefer-spread
41
+ const items: HTMLElement[] = Array.from(
42
+ tabListRef.current.querySelectorAll('.nav-link:not(.disabled):not(:disabled)'),
43
+ )
44
+
45
+ let nextActiveElement
46
+
47
+ if (event.key === 'Home' || event.key === 'End') {
48
+ nextActiveElement = event.key === 'End' ? items.at(-1) : items[0]
49
+ } else {
50
+ nextActiveElement = getNextActiveElement(
51
+ items,
52
+ target,
53
+ event.key === 'ArrowDown' || event.key === 'ArrowRight',
54
+ true,
55
+ )
56
+ }
57
+
58
+ if (nextActiveElement) {
59
+ nextActiveElement.focus({ preventScroll: true })
60
+ }
61
+ }
62
+ }
63
+
64
+ return (
65
+ <div
66
+ className={classNames(
67
+ 'nav',
68
+ {
69
+ [`nav-${layout}`]: layout,
70
+ [`nav-${variant}`]: variant,
71
+ },
72
+ className,
73
+ )}
74
+ role="tablist"
75
+ onKeyDown={handleKeydown}
76
+ ref={forkedRef}
77
+ {...rest}
78
+ >
79
+ {children}
80
+ </div>
81
+ )
82
+ },
83
+ )
84
+
85
+ CTabList.propTypes = {
86
+ children: PropTypes.node,
87
+ className: PropTypes.string,
88
+ layout: PropTypes.oneOf(['fill', 'justified']),
89
+ variant: PropTypes.oneOf(['pills', 'tabs', 'underline', 'underline-border']),
90
+ }
91
+
92
+ CTabList.displayName = 'CTabList'
@@ -18,6 +18,12 @@ export interface CTabPaneProps extends HTMLAttributes<HTMLDivElement> {
18
18
  * Callback fired when the component requests to be shown.
19
19
  */
20
20
  onShow?: () => void
21
+ /**
22
+ * Enable fade in and fade out transition.
23
+ *
24
+ * @since 5.1.0
25
+ */
26
+ transition?: boolean
21
27
  /**
22
28
  * Toggle the visibility of component.
23
29
  */
@@ -25,7 +31,7 @@ export interface CTabPaneProps extends HTMLAttributes<HTMLDivElement> {
25
31
  }
26
32
 
27
33
  export const CTabPane = forwardRef<HTMLDivElement, CTabPaneProps>(
28
- ({ children, className, onHide, onShow, visible, ...rest }, ref) => {
34
+ ({ children, className, onHide, onShow, transition = true, visible, ...rest }, ref) => {
29
35
  const tabPaneRef = useRef()
30
36
  const forkedRef = useForkedRef(ref, tabPaneRef)
31
37
 
@@ -35,9 +41,9 @@ export const CTabPane = forwardRef<HTMLDivElement, CTabPaneProps>(
35
41
  <div
36
42
  className={classNames(
37
43
  'tab-pane',
38
- 'fade',
39
44
  {
40
45
  active: visible,
46
+ fade: transition,
41
47
  show: state === 'entered',
42
48
  },
43
49
  className,
@@ -58,6 +64,7 @@ CTabPane.propTypes = {
58
64
  className: PropTypes.string,
59
65
  onHide: PropTypes.func,
60
66
  onShow: PropTypes.func,
67
+ transition: PropTypes.bool,
61
68
  visible: PropTypes.bool,
62
69
  }
63
70
 
@@ -0,0 +1,98 @@
1
+ import React, { HTMLAttributes, forwardRef, useContext, useEffect, useRef, useState } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import classNames from 'classnames'
4
+ import { Transition } from 'react-transition-group'
5
+
6
+ import { TabsContext } from './CTabs'
7
+ import { useForkedRef } from '../../hooks'
8
+ import { getTransitionDurationFromElement } from '../../utils'
9
+
10
+ export interface CTabPanelProps extends HTMLAttributes<HTMLDivElement> {
11
+ /**
12
+ * A string of all className you want applied to the base component.
13
+ */
14
+ className?: string
15
+ /**
16
+ * Item key.
17
+ */
18
+ itemKey: number | string
19
+ /**
20
+ * Callback fired when the component requests to be hidden.
21
+ */
22
+ onHide?: () => void
23
+ /**
24
+ * Callback fired when the component requests to be shown.
25
+ */
26
+ onShow?: () => void
27
+ /**
28
+ * Enable fade in and fade out transition.
29
+ */
30
+ transition?: boolean
31
+ /**
32
+ * Toggle the visibility of component.
33
+ */
34
+ visible?: boolean
35
+ }
36
+
37
+ export const CTabPanel = forwardRef<HTMLDivElement, CTabPanelProps>(
38
+ ({ children, className, itemKey, onHide, onShow, transition = true, visible, ...rest }, ref) => {
39
+ const { _activeItemKey, id } = useContext(TabsContext)
40
+
41
+ const tabPaneRef = useRef()
42
+ const forkedRef = useForkedRef(ref, tabPaneRef)
43
+
44
+ const [_visible, setVisible] = useState(visible || _activeItemKey === itemKey)
45
+
46
+ useEffect(() => {
47
+ visible !== undefined && setVisible(visible)
48
+ }, [visible])
49
+
50
+ useEffect(() => {
51
+ setVisible(_activeItemKey === itemKey)
52
+ }, [_activeItemKey])
53
+
54
+ return (
55
+ <Transition
56
+ in={_visible}
57
+ nodeRef={tabPaneRef}
58
+ onEnter={onShow}
59
+ onExit={onHide}
60
+ timeout={tabPaneRef.current ? getTransitionDurationFromElement(tabPaneRef.current) : 0}
61
+ >
62
+ {(state) => (
63
+ <div
64
+ className={classNames(
65
+ 'tab-pane',
66
+ {
67
+ active: _visible,
68
+ fade: transition,
69
+ show: state === 'entered',
70
+ },
71
+ className,
72
+ )}
73
+ id={`${id}${itemKey}-tab-pane`}
74
+ role="tabpanel"
75
+ aria-labelledby={`${id}${itemKey}-tab`}
76
+ tabIndex={0}
77
+ ref={forkedRef}
78
+ {...rest}
79
+ >
80
+ {children}
81
+ </div>
82
+ )}
83
+ </Transition>
84
+ )
85
+ },
86
+ )
87
+
88
+ CTabPanel.propTypes = {
89
+ children: PropTypes.node,
90
+ className: PropTypes.string,
91
+ itemKey: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
92
+ onHide: PropTypes.func,
93
+ onShow: PropTypes.func,
94
+ transition: PropTypes.bool,
95
+ visible: PropTypes.bool,
96
+ }
97
+
98
+ CTabPanel.displayName = 'CTabPanel'
@@ -0,0 +1,54 @@
1
+ import React, { createContext, forwardRef, HTMLAttributes, useEffect, useId, useState } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import classNames from 'classnames'
4
+
5
+ export interface CTabsProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
6
+ /**
7
+ * The active item key.
8
+ */
9
+ activeItemKey: number | string
10
+ /**
11
+ * A string of all className you want applied to the base component.
12
+ */
13
+ className?: string
14
+ /**
15
+ * The callback is fired when the active tab changes.
16
+ */
17
+ onChange?: (value: number | string) => void
18
+ }
19
+
20
+ export interface TabsContextProps {
21
+ _activeItemKey?: number | string
22
+ setActiveItemKey: React.Dispatch<React.SetStateAction<number | string | undefined>>
23
+ id?: string
24
+ }
25
+
26
+ export const TabsContext = createContext({} as TabsContextProps)
27
+
28
+ export const CTabs = forwardRef<HTMLDivElement, CTabsProps>(
29
+ ({ children, activeItemKey, className, onChange }, ref) => {
30
+ const id = useId()
31
+ const [_activeItemKey, setActiveItemKey] = useState(activeItemKey)
32
+
33
+ useEffect(() => {
34
+ _activeItemKey && onChange && onChange(_activeItemKey)
35
+ }, [_activeItemKey])
36
+
37
+ return (
38
+ <TabsContext.Provider value={{ _activeItemKey, setActiveItemKey, id }}>
39
+ <div className={classNames('tabs', className)} ref={ref}>
40
+ {children}
41
+ </div>
42
+ </TabsContext.Provider>
43
+ )
44
+ },
45
+ )
46
+
47
+ CTabs.propTypes = {
48
+ activeItemKey: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
49
+ children: PropTypes.node,
50
+ className: PropTypes.string,
51
+ onChange: PropTypes.func,
52
+ }
53
+
54
+ CTabs.displayName = 'CTabs'