@coreui/react-pro 5.24.0 → 5.25.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 (180) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/components/calendar/CCalendar.js +4 -3
  3. package/dist/cjs/components/calendar/CCalendar.js.map +1 -1
  4. package/dist/cjs/components/date-picker/CDatePicker.d.ts +1 -1
  5. package/dist/cjs/components/date-picker/CDatePicker.js.map +1 -1
  6. package/dist/cjs/components/date-range-picker/CDateRangePicker.js +2 -0
  7. package/dist/cjs/components/date-range-picker/CDateRangePicker.js.map +1 -1
  8. package/dist/cjs/components/dropdown/CDropdown.js +1 -1
  9. package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
  10. package/dist/cjs/components/index.d.ts +1 -0
  11. package/dist/cjs/components/nav/CNavGroup.d.ts +3 -1
  12. package/dist/cjs/components/nav/CNavGroup.js +9 -5
  13. package/dist/cjs/components/nav/CNavGroup.js.map +1 -1
  14. package/dist/cjs/components/one-time-password-input/COneTimePassword.js +3 -3
  15. package/dist/cjs/components/one-time-password-input/COneTimePassword.js.map +1 -1
  16. package/dist/cjs/components/popover/CPopover.js +14 -17
  17. package/dist/cjs/components/popover/CPopover.js.map +1 -1
  18. package/dist/cjs/components/search-button/CSearchButton.d.ts +32 -0
  19. package/dist/cjs/components/search-button/CSearchButton.js +77 -0
  20. package/dist/cjs/components/search-button/CSearchButton.js.map +1 -0
  21. package/dist/cjs/components/search-button/index.d.ts +2 -0
  22. package/dist/cjs/components/search-button/types.d.ts +10 -0
  23. package/dist/cjs/components/search-button/utils.d.ts +11 -0
  24. package/dist/cjs/components/search-button/utils.js +115 -0
  25. package/dist/cjs/components/search-button/utils.js.map +1 -0
  26. package/dist/cjs/components/sidebar/CSidebarNav.d.ts +12 -0
  27. package/dist/cjs/components/sidebar/CSidebarNav.js +7 -2
  28. package/dist/cjs/components/sidebar/CSidebarNav.js.map +1 -1
  29. package/dist/cjs/components/smart-table/CSmartTable.js +2 -2
  30. package/dist/cjs/components/smart-table/CSmartTable.js.map +1 -1
  31. package/dist/cjs/components/smart-table/CSmartTableInterface.d.ts +2 -2
  32. package/dist/cjs/components/time-picker/CTimePicker.d.ts +1 -1
  33. package/dist/cjs/components/time-picker/CTimePicker.js +1 -1
  34. package/dist/cjs/components/time-picker/CTimePicker.js.map +1 -1
  35. package/dist/cjs/components/tooltip/CTooltip.js +14 -17
  36. package/dist/cjs/components/tooltip/CTooltip.js.map +1 -1
  37. package/dist/cjs/components/virtual-scroller/CVirtualScroller.js +11 -8
  38. package/dist/cjs/components/virtual-scroller/CVirtualScroller.js.map +1 -1
  39. package/dist/cjs/hooks/useDebouncedCallback.d.ts +1 -1
  40. package/dist/cjs/hooks/useDebouncedCallback.js +1 -1
  41. package/dist/cjs/hooks/useDebouncedCallback.js.map +1 -1
  42. package/dist/cjs/index.js +2 -0
  43. package/dist/cjs/index.js.map +1 -1
  44. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
  45. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
  46. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
  47. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
  48. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
  49. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
  50. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
  51. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
  52. package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js +2 -2
  53. package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
  54. package/dist/esm/components/calendar/CCalendar.js +4 -3
  55. package/dist/esm/components/calendar/CCalendar.js.map +1 -1
  56. package/dist/esm/components/date-picker/CDatePicker.d.ts +1 -1
  57. package/dist/esm/components/date-picker/CDatePicker.js.map +1 -1
  58. package/dist/esm/components/date-range-picker/CDateRangePicker.js +2 -0
  59. package/dist/esm/components/date-range-picker/CDateRangePicker.js.map +1 -1
  60. package/dist/esm/components/dropdown/CDropdown.js +1 -1
  61. package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
  62. package/dist/esm/components/index.d.ts +1 -0
  63. package/dist/esm/components/nav/CNavGroup.d.ts +3 -1
  64. package/dist/esm/components/nav/CNavGroup.js +9 -5
  65. package/dist/esm/components/nav/CNavGroup.js.map +1 -1
  66. package/dist/esm/components/one-time-password-input/COneTimePassword.js +3 -3
  67. package/dist/esm/components/one-time-password-input/COneTimePassword.js.map +1 -1
  68. package/dist/esm/components/popover/CPopover.js +14 -17
  69. package/dist/esm/components/popover/CPopover.js.map +1 -1
  70. package/dist/esm/components/search-button/CSearchButton.d.ts +32 -0
  71. package/dist/esm/components/search-button/CSearchButton.js +75 -0
  72. package/dist/esm/components/search-button/CSearchButton.js.map +1 -0
  73. package/dist/esm/components/search-button/index.d.ts +2 -0
  74. package/dist/esm/components/search-button/types.d.ts +10 -0
  75. package/dist/esm/components/search-button/utils.d.ts +11 -0
  76. package/dist/esm/components/search-button/utils.js +104 -0
  77. package/dist/esm/components/search-button/utils.js.map +1 -0
  78. package/dist/esm/components/sidebar/CSidebarNav.d.ts +12 -0
  79. package/dist/esm/components/sidebar/CSidebarNav.js +7 -2
  80. package/dist/esm/components/sidebar/CSidebarNav.js.map +1 -1
  81. package/dist/esm/components/smart-table/CSmartTable.js +2 -2
  82. package/dist/esm/components/smart-table/CSmartTable.js.map +1 -1
  83. package/dist/esm/components/smart-table/CSmartTableInterface.d.ts +2 -2
  84. package/dist/esm/components/time-picker/CTimePicker.d.ts +1 -1
  85. package/dist/esm/components/time-picker/CTimePicker.js +1 -1
  86. package/dist/esm/components/time-picker/CTimePicker.js.map +1 -1
  87. package/dist/esm/components/tooltip/CTooltip.js +14 -17
  88. package/dist/esm/components/tooltip/CTooltip.js.map +1 -1
  89. package/dist/esm/components/virtual-scroller/CVirtualScroller.js +11 -8
  90. package/dist/esm/components/virtual-scroller/CVirtualScroller.js.map +1 -1
  91. package/dist/esm/hooks/useDebouncedCallback.d.ts +1 -1
  92. package/dist/esm/hooks/useDebouncedCallback.js +1 -1
  93. package/dist/esm/hooks/useDebouncedCallback.js.map +1 -1
  94. package/dist/esm/index.js +1 -0
  95. package/dist/esm/index.js.map +1 -1
  96. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
  97. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
  98. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
  99. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
  100. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
  101. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
  102. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
  103. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
  104. package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js +2 -2
  105. package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
  106. package/package.json +7 -5
  107. package/src/components/autocomplete/__tests__/CAutocomplete.spec.tsx +18 -16
  108. package/src/components/autocomplete/__tests__/CAutocompleteOptions.spec.tsx +37 -28
  109. package/src/components/autocomplete/__tests__/__snapshots__/CAutocomplete.spec.tsx.snap +129 -0
  110. package/src/components/autocomplete/__tests__/__snapshots__/CAutocompleteOptions.spec.tsx.snap +36 -0
  111. package/src/components/calendar/CCalendar.tsx +5 -4
  112. package/src/components/calendar/__tests__/CCalendar.spec.tsx +40 -45
  113. package/src/components/calendar/__tests__/__snapshots__/CCalendar.spec.tsx.snap +99 -75
  114. package/src/components/calendar/__tests__/utils.spec.tsx +8 -18
  115. package/src/components/date-picker/CDatePicker.tsx +12 -13
  116. package/src/components/date-picker/__tests__/CDatePicker.spec.tsx +1 -1
  117. package/src/components/date-picker/__tests__/__snapshots__/CDatePicker.spec.tsx.snap +12 -640
  118. package/src/components/date-range-picker/CDateRangePicker.tsx +2 -0
  119. package/src/components/date-range-picker/__tests__/CDateRangePicker.spec.tsx +1 -1
  120. package/src/components/date-range-picker/__tests__/__snapshots__/CDateRangePicker.spec.tsx.snap +21 -1259
  121. package/src/components/dropdown/CDropdown.tsx +1 -1
  122. package/src/components/dropdown/__tests__/CDropdown.spec.tsx +1 -1
  123. package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +2 -2
  124. package/src/components/dropdown/__tests__/__snapshots__/CDropdownMenu.spec.tsx.snap +1 -1
  125. package/src/components/form/__tests__/CFormInput.spec.tsx +17 -20
  126. package/src/components/form/__tests__/__snapshots__/CFormInput.spec.tsx.snap +12 -3
  127. package/src/components/index.ts +1 -0
  128. package/src/components/loading-button/__tests__/CLoadingButton.spec.tsx +1 -1
  129. package/src/components/loading-button/__tests__/__snapshots__/CLoadingButton.spec.tsx.snap +4 -4
  130. package/src/components/multi-select/__tests__/CMultiSelect.spec.tsx +15 -61
  131. package/src/components/multi-select/__tests__/CMultiSelectNativeSelect.spec.tsx +4 -5
  132. package/src/components/multi-select/__tests__/CMultiSelectOptions.spec.tsx +4 -4
  133. package/src/components/multi-select/__tests__/CMultiSelectSelection.spec.tsx +7 -24
  134. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelect.spec.tsx.snap +50 -20
  135. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectNativeSelect.spec.tsx.snap +0 -2
  136. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectOptions.spec.tsx.snap +6 -0
  137. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelection.spec.tsx.snap +11 -8
  138. package/src/components/nav/CNavGroup.tsx +11 -6
  139. package/src/components/nav/__tests__/CNavGroup.spec.tsx +29 -1
  140. package/src/components/nav/__tests__/__snapshots__/CNavGroup.spec.tsx.snap +1 -1
  141. package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +1 -0
  142. package/src/components/one-time-password-input/COneTimePassword.tsx +10 -11
  143. package/src/components/picker/__tests__/CPicker.spec.tsx +1 -1
  144. package/src/components/picker/__tests__/__snapshots__/CPicker.spec.tsx.snap +2 -16
  145. package/src/components/popover/CPopover.tsx +15 -20
  146. package/src/components/popover/__tests__/CPopover.spec.tsx +10 -4
  147. package/src/components/search-button/CSearchButton.tsx +195 -0
  148. package/src/components/search-button/__tests__/CSearchButton.spec.tsx +95 -0
  149. package/src/components/search-button/__tests__/__snapshots__/CSearchButton.spec.tsx.snap +87 -0
  150. package/src/components/search-button/index.ts +3 -0
  151. package/src/components/search-button/types.ts +10 -0
  152. package/src/components/search-button/utils.ts +140 -0
  153. package/src/components/sidebar/CSidebarNav.tsx +27 -2
  154. package/src/components/smart-table/CSmartTable.tsx +5 -4
  155. package/src/components/smart-table/CSmartTableInterface.tsx +2 -2
  156. package/src/components/smart-table/__tests__/CSmartTable.spec.tsx +3 -2
  157. package/src/components/smart-table/__tests__/__snapshots__/CSmartTable.spec.tsx.snap +7 -15
  158. package/src/components/stepper/__tests__/CStepper.spec.tsx +24 -21
  159. package/src/components/stepper/__tests__/__snapshots__/CStepper.spec.tsx.snap +295 -0
  160. package/src/components/tabs/__tests__/CTabContent.spec.tsx +1 -0
  161. package/src/components/tabs/__tests__/CTabPane.spec.tsx +1 -0
  162. package/src/components/time-picker/CTimePicker.tsx +6 -7
  163. package/src/components/time-picker/__tests__/CTimePicker.spec.tsx +10 -1
  164. package/src/components/time-picker/__tests__/__snapshots__/CTimePicker.spec.tsx.snap +599 -315
  165. package/src/components/tooltip/CTooltip.tsx +15 -20
  166. package/src/components/tooltip/__tests__/CTooltip.spec.tsx +6 -0
  167. package/src/components/virtual-scroller/CVirtualScroller.tsx +13 -14
  168. package/src/hooks/useDebouncedCallback.ts +7 -4
  169. package/dist/cjs/components/accordion/CAccordionCollapse.d.ts +0 -3
  170. package/dist/esm/components/accordion/CAccordionCollapse.d.ts +0 -3
  171. package/src/components/accordion/CAccordionCollapse.tsx +0 -20
  172. package/src/components/accordion/__tests__/CAccordionCollapse.spec.tsx +0 -10
  173. package/src/components/accordion/__tests__/__snapshots__/CAccordionCollapse.spec.tsx.snap +0 -11
  174. package/src/components/button/__tests__/__snapshots__/CButtonClose.spec.tsx.snap +0 -26
  175. package/src/components/calendar/__tests__/CCalendar.accessibility.spec.tsx +0 -595
  176. package/src/components/calendar/__tests__/CCalendar.comprehensive.spec.tsx +0 -402
  177. package/src/components/calendar/__tests__/CCalendar.edge-cases.spec.tsx +0 -416
  178. package/src/components/calendar/__tests__/CCalendar.interactions.spec.tsx +0 -593
  179. package/src/components/header/CHeaderBrand.tsx~HEAD +0 -36
  180. /package/src/components/calendar/__tests__/{test-setup.ts → setup.ts} +0 -0
@@ -0,0 +1,87 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`CSearchButton customize 1`] = `
4
+ <div>
5
+ <button
6
+ class="search-button bazinga"
7
+ type="button"
8
+ >
9
+ <svg
10
+ aria-hidden="true"
11
+ class="search-button-icon"
12
+ viewBox="0 0 512 512"
13
+ xmlns="http://www.w3.org/2000/svg"
14
+ >
15
+ <path
16
+ d="m479.6 399.716-81.084-81.084-62.368-25.767A175 175 0 0 0 368 192c0-97.047-78.953-176-176-176S16 94.953 16 192s78.953 176 176 176a175.03 175.03 0 0 0 101.619-32.377l25.7 62.2 81.081 81.088a56 56 0 1 0 79.2-79.195M48 192c0-79.4 64.6-144 144-144s144 64.6 144 144-64.6 144-144 144S48 271.4 48 192m408.971 264.284a24.03 24.03 0 0 1-33.942 0l-76.572-76.572-23.894-57.835 57.837 23.894 76.573 76.572a24.03 24.03 0 0 1-.002 33.941"
17
+ fill="currentColor"
18
+ />
19
+ </svg>
20
+ <span
21
+ class="search-button-placeholder"
22
+ >
23
+ Command palette
24
+ </span>
25
+ <span
26
+ aria-hidden="true"
27
+ class="search-button-keys"
28
+ >
29
+ <span
30
+ class="search-button-key"
31
+ data-coreui-search-button-key="⌘"
32
+ >
33
+ ⌘
34
+ </span>
35
+ <span
36
+ class="search-button-key"
37
+ data-coreui-search-button-key="K"
38
+ >
39
+ K
40
+ </span>
41
+ </span>
42
+ </button>
43
+ </div>
44
+ `;
45
+
46
+ exports[`loads and displays CSearchButton component 1`] = `
47
+ <div>
48
+ <button
49
+ class="search-button"
50
+ type="button"
51
+ >
52
+ <svg
53
+ aria-hidden="true"
54
+ class="search-button-icon"
55
+ viewBox="0 0 512 512"
56
+ xmlns="http://www.w3.org/2000/svg"
57
+ >
58
+ <path
59
+ d="m479.6 399.716-81.084-81.084-62.368-25.767A175 175 0 0 0 368 192c0-97.047-78.953-176-176-176S16 94.953 16 192s78.953 176 176 176a175.03 175.03 0 0 0 101.619-32.377l25.7 62.2 81.081 81.088a56 56 0 1 0 79.2-79.195M48 192c0-79.4 64.6-144 144-144s144 64.6 144 144-64.6 144-144 144S48 271.4 48 192m408.971 264.284a24.03 24.03 0 0 1-33.942 0l-76.572-76.572-23.894-57.835 57.837 23.894 76.573 76.572a24.03 24.03 0 0 1-.002 33.941"
60
+ fill="currentColor"
61
+ />
62
+ </svg>
63
+ <span
64
+ class="search-button-placeholder"
65
+ >
66
+ Search
67
+ </span>
68
+ <span
69
+ aria-hidden="true"
70
+ class="search-button-keys"
71
+ >
72
+ <span
73
+ class="search-button-key"
74
+ data-coreui-search-button-key="⌘"
75
+ >
76
+ ⌘
77
+ </span>
78
+ <span
79
+ class="search-button-key"
80
+ data-coreui-search-button-key="/"
81
+ >
82
+ /
83
+ </span>
84
+ </span>
85
+ </button>
86
+ </div>
87
+ `;
@@ -0,0 +1,3 @@
1
+ import { CSearchButton } from './CSearchButton'
2
+
3
+ export { CSearchButton }
@@ -0,0 +1,10 @@
1
+ export type SearchButtonShortcut = {
2
+ key: string
3
+ modifiers: {
4
+ alt: boolean
5
+ ctrl: boolean
6
+ meta: boolean
7
+ shift: boolean
8
+ }
9
+ shortcut: string
10
+ }
@@ -0,0 +1,140 @@
1
+ import type { SearchButtonShortcut } from './types'
2
+
3
+ const MODIFIER_KEYS = new Set(['alt', 'ctrl', 'meta', 'shift'])
4
+ const KEY_ALIASES: Record<string, string> = {
5
+ ' ': 'space',
6
+ cmd: 'meta',
7
+ command: 'meta',
8
+ control: 'ctrl',
9
+ esc: 'escape',
10
+ option: 'alt',
11
+ return: 'enter',
12
+ spacebar: 'space',
13
+ }
14
+ const KEY_LABELS: Record<string, string> = {
15
+ alt: 'Alt',
16
+ ctrl: 'Ctrl',
17
+ meta: '⌘',
18
+ shift: 'Shift',
19
+ space: 'Space',
20
+ }
21
+ const EDITABLE_TARGET_SELECTOR =
22
+ 'input, textarea, select, [contenteditable=""], [contenteditable="true"], [contenteditable="plaintext-only"]'
23
+
24
+ export const normalizeKey = (key: string) => KEY_ALIASES[key.toLowerCase()] || key.toLowerCase()
25
+
26
+ export const parseShortcut = (shortcut: string): SearchButtonShortcut[] =>
27
+ shortcut
28
+ .split(',')
29
+ .map((value) => value.trim())
30
+ .filter(Boolean)
31
+ .map((value) => {
32
+ const keys = value.split('+').map((part) => normalizeKey(part.trim()))
33
+ const modifiers = {
34
+ alt: false,
35
+ ctrl: false,
36
+ meta: false,
37
+ shift: false,
38
+ }
39
+
40
+ let key = ''
41
+
42
+ for (const part of keys) {
43
+ if (MODIFIER_KEYS.has(part)) {
44
+ modifiers[part as keyof typeof modifiers] = true
45
+ continue
46
+ }
47
+
48
+ key = part
49
+ }
50
+
51
+ return {
52
+ key,
53
+ modifiers,
54
+ shortcut: value,
55
+ }
56
+ })
57
+
58
+ const getPlatform = () => {
59
+ if (typeof window === 'undefined') {
60
+ return ''
61
+ }
62
+
63
+ const navigator = window.navigator as Navigator & {
64
+ userAgentData?: {
65
+ platform?: string
66
+ }
67
+ }
68
+
69
+ return navigator.userAgentData?.platform || navigator.platform || navigator.userAgent || ''
70
+ }
71
+
72
+ export const isMacOS = () => /Mac|iPhone|iPad|iPod|macOS|Macintosh/.test(getPlatform())
73
+
74
+ export const getPreferredShortcut = (shortcuts: SearchButtonShortcut[]) =>
75
+ shortcuts.find((shortcut) => (isMacOS() ? shortcut.modifiers.meta : shortcut.modifiers.ctrl)) ||
76
+ shortcuts[0] ||
77
+ null
78
+
79
+ export const getKeyLabel = (key: string) =>
80
+ KEY_LABELS[key] ||
81
+ (key.length === 1 ? key.toUpperCase() : `${key.charAt(0).toUpperCase()}${key.slice(1)}`)
82
+
83
+ export const formatShortcutTokens = (shortcut: string) =>
84
+ shortcut
85
+ .split('+')
86
+ .map((part) => normalizeKey(part.trim()))
87
+ .map((part) => getKeyLabel(part))
88
+ .filter(Boolean)
89
+
90
+ export const getPressedKeys = (event: KeyboardEvent) => {
91
+ const pressedKeys = new Set<string>()
92
+
93
+ if (event.altKey) {
94
+ pressedKeys.add(KEY_LABELS.alt)
95
+ }
96
+
97
+ if (event.ctrlKey) {
98
+ pressedKeys.add(KEY_LABELS.ctrl)
99
+ }
100
+
101
+ if (event.metaKey) {
102
+ pressedKeys.add(KEY_LABELS.meta)
103
+ }
104
+
105
+ if (event.shiftKey) {
106
+ pressedKeys.add(KEY_LABELS.shift)
107
+ }
108
+
109
+ const normalizedKey = normalizeKey(event.key)
110
+
111
+ if (!MODIFIER_KEYS.has(normalizedKey) && event.type === 'keydown') {
112
+ pressedKeys.add(getKeyLabel(normalizedKey))
113
+ }
114
+
115
+ return pressedKeys
116
+ }
117
+
118
+ export const isEditableTarget = (target: EventTarget | null) => {
119
+ if (!(target instanceof Element)) {
120
+ return false
121
+ }
122
+
123
+ return target.matches(EDITABLE_TARGET_SELECTOR) || !!target.closest(EDITABLE_TARGET_SELECTOR)
124
+ }
125
+
126
+ export const shouldIgnoreShortcut = (event: KeyboardEvent) =>
127
+ isEditableTarget(event.target) && !event.ctrlKey && !event.metaKey
128
+
129
+ export const matchesShortcut = (shortcut: SearchButtonShortcut, event: KeyboardEvent) => {
130
+ if (!shortcut.key || normalizeKey(event.key) !== shortcut.key) {
131
+ return false
132
+ }
133
+
134
+ return (
135
+ shortcut.modifiers.alt === event.altKey &&
136
+ shortcut.modifiers.ctrl === event.ctrlKey &&
137
+ shortcut.modifiers.meta === event.metaKey &&
138
+ shortcut.modifiers.shift === event.shiftKey
139
+ )
140
+ }
@@ -28,6 +28,18 @@ export interface CSidebarNavProps extends HTMLAttributes<HTMLUListElement> {
28
28
  * A string of all className you want applied to the component.
29
29
  */
30
30
  className?: string
31
+ /**
32
+ * Make navigation more compact by cutting link padding in half.
33
+ *
34
+ * @since 5.11.0
35
+ */
36
+ compact?: boolean
37
+ /**
38
+ * Sets the navigation variant.
39
+ *
40
+ * @since 5.11.0
41
+ */
42
+ variant?: 'tree'
31
43
  }
32
44
 
33
45
  const isNavElement = (
@@ -69,7 +81,7 @@ const recursiveClone = (children: ReactNode, id?: string, updateId?: boolean): R
69
81
  export const CSidebarNav: PolymorphicRefForwardingComponent<'ul', CSidebarNavProps> = forwardRef<
70
82
  HTMLUListElement,
71
83
  CSidebarNavProps
72
- >(({ children, as: Component = 'ul', className, ...rest }, ref) => {
84
+ >(({ children, as: Component = 'ul', className, compact, variant, ...rest }, ref) => {
73
85
  const [visibleGroup, setVisibleGroup] = useState('')
74
86
  const CNavContextValues = {
75
87
  visibleGroup,
@@ -78,7 +90,18 @@ export const CSidebarNav: PolymorphicRefForwardingComponent<'ul', CSidebarNavPro
78
90
 
79
91
  return (
80
92
  <CSidebarNavContext.Provider value={CNavContextValues}>
81
- <Component className={classNames('sidebar-nav', className)} ref={ref} {...rest}>
93
+ <Component
94
+ className={classNames(
95
+ 'sidebar-nav',
96
+ {
97
+ compact,
98
+ 'sidebar-nav-tree': variant === 'tree',
99
+ },
100
+ className
101
+ )}
102
+ ref={ref}
103
+ {...rest}
104
+ >
82
105
  {recursiveClone(children)}
83
106
  </Component>
84
107
  </CSidebarNavContext.Provider>
@@ -89,6 +112,8 @@ CSidebarNav.propTypes = {
89
112
  as: PropTypes.elementType,
90
113
  children: PropTypes.node,
91
114
  className: PropTypes.string,
115
+ compact: PropTypes.bool,
116
+ variant: PropTypes.oneOf(['tree']),
92
117
  }
93
118
 
94
119
  CSidebarNav.displayName = 'CSidebarNav'
@@ -207,9 +207,10 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
207
207
 
208
208
  const firstItemOnActivePageIndex: number = _activePage ? (_activePage - 1) * _itemsPerPage : 0
209
209
 
210
- const currentItems: Item[] = _activePage
211
- ? sortedItems.slice(firstItemOnActivePageIndex, firstItemOnActivePageIndex + _itemsPerPage)
212
- : sortedItems
210
+ const currentItems: Item[] =
211
+ _activePage && pagination
212
+ ? sortedItems.slice(firstItemOnActivePageIndex, firstItemOnActivePageIndex + _itemsPerPage)
213
+ : sortedItems
213
214
 
214
215
  useEffect(() => {
215
216
  mountedRef.current && onFilteredItemsChange && onFilteredItemsChange(sortedItems)
@@ -496,7 +497,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
496
497
  )}
497
498
  </div>
498
499
 
499
- {(pagination || itemsPerPageSelect) && (
500
+ {pagination && (
500
501
  <div className="row">
501
502
  <div className="col">
502
503
  {((pagination && numberOfPages > 1) ||
@@ -103,7 +103,7 @@ export interface CSmartTableProps extends HTMLAttributes<HTMLDivElement> {
103
103
  */
104
104
  itemsNumber?: number
105
105
  /**
106
- * Number of items per site, when pagination is enabled.
106
+ * Number of items per page. Only applicable when `pagination` is enabled.
107
107
  */
108
108
  itemsPerPage?: number
109
109
  /**
@@ -115,7 +115,7 @@ export interface CSmartTableProps extends HTMLAttributes<HTMLDivElement> {
115
115
  */
116
116
  itemsPerPageOptions?: number[]
117
117
  /**
118
- * 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
+ * Adds select element over table, which is used for control items per page in pagination. Only applicable when `pagination` is enabled. If you want to customize this element, pass object with optional values:
119
119
  * - external (Boolean) - disables automatic 'itemsPerPage' change.
120
120
  */
121
121
  itemsPerPageSelect?: boolean | ItemsPerPageSelect
@@ -1,7 +1,8 @@
1
1
  import * as React from 'react'
2
2
  import { render } from '@testing-library/react'
3
- import '@testing-library/jest-dom/extend-expect'
4
- import { CBadge, CSmartTable } from '../index'
3
+ import '@testing-library/jest-dom'
4
+ import { CBadge } from '../../badge'
5
+ import { CSmartTable } from '../index'
5
6
  import { Item } from '../types'
6
7
 
7
8
  test('loads and displays CSpinner component', async () => {
@@ -37,6 +37,7 @@ exports[`loads and displays CSpinner component 1`] = `
37
37
  type="button"
38
38
  >
39
39
  <svg
40
+ aria-hidden="true"
40
41
  class="icon icon-custom-size"
41
42
  role="img"
42
43
  viewBox="0 0 512 512"
@@ -80,6 +81,7 @@ exports[`loads and displays CSpinner component 1`] = `
80
81
  <th
81
82
  class="table-primary fw-semibold"
82
83
  style="cursor: pointer; width: 20%; color: blue;"
84
+ tabindex="0"
83
85
  >
84
86
  <div
85
87
  class="d-inline"
@@ -90,6 +92,7 @@ exports[`loads and displays CSpinner component 1`] = `
90
92
  class="opacity-25 float-end me-1"
91
93
  >
92
94
  <svg
95
+ aria-hidden="true"
93
96
  class="icon icon-custom-size"
94
97
  role="img"
95
98
  viewBox="0 0 512 512"
@@ -111,6 +114,7 @@ exports[`loads and displays CSpinner component 1`] = `
111
114
  </th>
112
115
  <th
113
116
  style="cursor: pointer;"
117
+ tabindex="0"
114
118
  >
115
119
  <div
116
120
  class="d-inline"
@@ -121,6 +125,7 @@ exports[`loads and displays CSpinner component 1`] = `
121
125
  class="opacity-25 float-end me-1"
122
126
  >
123
127
  <svg
128
+ aria-hidden="true"
124
129
  class="icon icon-custom-size"
125
130
  role="img"
126
131
  viewBox="0 0 512 512"
@@ -151,6 +156,7 @@ exports[`loads and displays CSpinner component 1`] = `
151
156
  </th>
152
157
  <th
153
158
  style="cursor: pointer; width: 20%;"
159
+ tabindex="0"
154
160
  >
155
161
  <div
156
162
  class="d-inline"
@@ -161,6 +167,7 @@ exports[`loads and displays CSpinner component 1`] = `
161
167
  class="float-end me-1"
162
168
  >
163
169
  <svg
170
+ aria-hidden="true"
164
171
  class="icon icon-custom-size"
165
172
  role="img"
166
173
  viewBox="0 0 512 512"
@@ -247,9 +254,6 @@ exports[`loads and displays CSpinner component 1`] = `
247
254
  Banned
248
255
  </span>
249
256
  </td>
250
- <td>
251
- undefined
252
- </td>
253
257
  </tr>
254
258
  <tr
255
259
  tabindex="0"
@@ -276,9 +280,6 @@ exports[`loads and displays CSpinner component 1`] = `
276
280
  Banned
277
281
  </span>
278
282
  </td>
279
- <td>
280
- undefined
281
- </td>
282
283
  </tr>
283
284
  <tr
284
285
  tabindex="0"
@@ -305,9 +306,6 @@ exports[`loads and displays CSpinner component 1`] = `
305
306
  Banned
306
307
  </span>
307
308
  </td>
308
- <td>
309
- undefined
310
- </td>
311
309
  </tr>
312
310
  <tr
313
311
  tabindex="0"
@@ -334,9 +332,6 @@ exports[`loads and displays CSpinner component 1`] = `
334
332
  Banned
335
333
  </span>
336
334
  </td>
337
- <td>
338
- undefined
339
- </td>
340
335
  </tr>
341
336
  <tr
342
337
  tabindex="0"
@@ -363,9 +358,6 @@ exports[`loads and displays CSpinner component 1`] = `
363
358
  Don't panic!
364
359
  </span>
365
360
  </td>
366
- <td>
367
- undefined
368
- </td>
369
361
  </tr>
370
362
  </tbody>
371
363
  <tfoot>
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react'
2
- import { render, screen, fireEvent, waitFor } from '@testing-library/react'
2
+ import { render, screen, fireEvent } from '@testing-library/react'
3
3
  import '@testing-library/jest-dom'
4
4
  import { CStepper } from '../index'
5
5
 
@@ -24,8 +24,8 @@ test('CStepper disables future steps in linear mode', async () => {
24
24
 
25
25
  const buttons = screen.getAllByRole('tab')
26
26
  expect(buttons[0]).toBeEnabled()
27
- expect(buttons[1]).toBeDisabled()
28
- expect(buttons[2]).toBeDisabled()
27
+ expect(buttons[1]).toBeEnabled() // next step is enabled
28
+ expect(buttons[2]).toBeDisabled() // steps beyond next are disabled
29
29
  })
30
30
 
31
31
  test('CStepper allows all steps in non-linear mode', async () => {
@@ -47,26 +47,27 @@ test('CStepper calls onStepChange when step is clicked', async () => {
47
47
  expect(handleStepChange).toHaveBeenCalledWith(3) // stepNumber = index + 1
48
48
  })
49
49
 
50
- test('CStepper renders only active step content in horizontal layout', async () => {
51
- render(<CStepper steps={stepsMock} layout="horizontal" />)
50
+ test('CStepper renders active step content in horizontal layout', async () => {
51
+ const { container } = render(<CStepper steps={stepsMock} layout="horizontal" />)
52
52
 
53
53
  expect(screen.getByText('Content 1')).toBeVisible()
54
- expect(screen.queryByText('Content 2')).not.toBeInTheDocument()
55
- expect(screen.queryByText('Content 3')).not.toBeInTheDocument()
54
+ const panels = container.querySelectorAll('[role="tabpanel"]')
55
+ expect(panels[0]).toHaveClass('active')
56
+ expect(panels[1]).not.toHaveClass('active')
57
+ expect(panels[2]).not.toHaveClass('active')
56
58
  })
57
59
 
58
- test('CStepper finish calls onFinish only after last step and valid', async () => {
59
- const handleFinish = jest.fn()
60
- render(<CStepper steps={stepsMock} onFinish={handleFinish} linear={false} />)
60
+ test('CStepper calls onStepChange when navigating to last step', async () => {
61
+ const handleStepChange = jest.fn()
62
+ render(<CStepper steps={stepsMock} onStepChange={handleStepChange} linear={false} />)
61
63
 
62
64
  const buttons = screen.getAllByRole('tab')
63
65
  fireEvent.click(buttons[2])
64
66
 
65
- fireEvent.click(screen.getByText('Step 3'))
66
- expect(handleFinish).toHaveBeenCalledTimes(1)
67
+ expect(handleStepChange).toHaveBeenCalledWith(3)
67
68
  })
68
69
 
69
- test('CStepper resets correctly and focuses first step', async () => {
70
+ test('CStepper resets correctly', async () => {
70
71
  const handleReset = jest.fn()
71
72
  const stepperRef = React.createRef<any>()
72
73
 
@@ -76,23 +77,25 @@ test('CStepper resets correctly and focuses first step', async () => {
76
77
  stepperRef.current?.reset()
77
78
 
78
79
  expect(handleReset).toHaveBeenCalled()
79
- expect(screen.getAllByRole('tab')[0]).toHaveFocus()
80
80
  })
81
81
 
82
82
  test('CStepper works in uncontrolled mode with defaultActiveStepIndex', async () => {
83
- render(<CStepper steps={stepsMock} defaultActiveStepIndex={1} />)
83
+ const { container } = render(<CStepper steps={stepsMock} defaultActiveStepIndex={1} />)
84
84
 
85
- expect(screen.getByText('Content 2')).toBeVisible()
86
- expect(screen.queryByText('Content 1')).not.toBeInTheDocument()
85
+ const panels = container.querySelectorAll('[role="tabpanel"]')
86
+ expect(panels[1]).toHaveClass('active')
87
+ expect(panels[0]).not.toHaveClass('active')
87
88
  })
88
89
 
89
90
  test('CStepper works in controlled mode with activeStepIndex', async () => {
90
- const { rerender } = render(<CStepper steps={stepsMock} activeStepIndex={0} />)
91
+ const { container, rerender } = render(<CStepper steps={stepsMock} activeStepIndex={0} />)
91
92
 
92
- expect(screen.getByText('Content 1')).toBeVisible()
93
+ let panels = container.querySelectorAll('[role="tabpanel"]')
94
+ expect(panels[0]).toHaveClass('active')
93
95
 
94
96
  rerender(<CStepper steps={stepsMock} activeStepIndex={2} />)
95
97
 
96
- expect(screen.getByText('Content 3')).toBeVisible()
97
- expect(screen.queryByText('Content 1')).not.toBeInTheDocument()
98
+ panels = container.querySelectorAll('[role="tabpanel"]')
99
+ expect(panels[2]).toHaveClass('active')
100
+ expect(panels[0]).not.toHaveClass('active')
98
101
  })