@coreui/react 5.8.0 → 5.9.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.
Files changed (49) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/components/dropdown/CDropdown.d.ts +21 -1
  3. package/dist/cjs/components/dropdown/CDropdown.js +67 -33
  4. package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
  5. package/dist/cjs/components/dropdown/CDropdownHeader.js.map +1 -1
  6. package/dist/cjs/components/dropdown/CDropdownItemPlain.js.map +1 -1
  7. package/dist/cjs/components/dropdown/CDropdownMenu.js.map +1 -1
  8. package/dist/cjs/components/dropdown/CDropdownToggle.d.ts +7 -0
  9. package/dist/cjs/components/dropdown/CDropdownToggle.js +3 -2
  10. package/dist/cjs/components/dropdown/CDropdownToggle.js.map +1 -1
  11. package/dist/cjs/components/dropdown/utils.d.ts +2 -0
  12. package/dist/cjs/components/dropdown/utils.js +13 -0
  13. package/dist/cjs/components/dropdown/utils.js.map +1 -1
  14. package/dist/cjs/components/focus-trap/CFocusTrap.js +23 -6
  15. package/dist/cjs/components/focus-trap/CFocusTrap.js.map +1 -1
  16. package/dist/cjs/components/focus-trap/utils.d.ts +10 -0
  17. package/dist/cjs/components/focus-trap/utils.js +25 -5
  18. package/dist/cjs/components/focus-trap/utils.js.map +1 -1
  19. package/dist/cjs/components/modal/CModal.js +10 -11
  20. package/dist/cjs/components/modal/CModal.js.map +1 -1
  21. package/dist/esm/components/dropdown/CDropdown.d.ts +21 -1
  22. package/dist/esm/components/dropdown/CDropdown.js +68 -34
  23. package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
  24. package/dist/esm/components/dropdown/CDropdownHeader.js.map +1 -1
  25. package/dist/esm/components/dropdown/CDropdownItemPlain.js.map +1 -1
  26. package/dist/esm/components/dropdown/CDropdownMenu.js.map +1 -1
  27. package/dist/esm/components/dropdown/CDropdownToggle.d.ts +7 -0
  28. package/dist/esm/components/dropdown/CDropdownToggle.js +3 -2
  29. package/dist/esm/components/dropdown/CDropdownToggle.js.map +1 -1
  30. package/dist/esm/components/dropdown/utils.d.ts +2 -0
  31. package/dist/esm/components/dropdown/utils.js +13 -1
  32. package/dist/esm/components/dropdown/utils.js.map +1 -1
  33. package/dist/esm/components/focus-trap/CFocusTrap.js +24 -7
  34. package/dist/esm/components/focus-trap/CFocusTrap.js.map +1 -1
  35. package/dist/esm/components/focus-trap/utils.d.ts +10 -0
  36. package/dist/esm/components/focus-trap/utils.js +25 -6
  37. package/dist/esm/components/focus-trap/utils.js.map +1 -1
  38. package/dist/esm/components/modal/CModal.js +10 -11
  39. package/dist/esm/components/modal/CModal.js.map +1 -1
  40. package/package.json +10 -10
  41. package/src/components/dropdown/CDropdown.tsx +126 -60
  42. package/src/components/dropdown/CDropdownHeader.tsx +1 -0
  43. package/src/components/dropdown/CDropdownItemPlain.tsx +1 -0
  44. package/src/components/dropdown/CDropdownMenu.tsx +1 -0
  45. package/src/components/dropdown/CDropdownToggle.tsx +15 -1
  46. package/src/components/dropdown/utils.ts +21 -0
  47. package/src/components/focus-trap/CFocusTrap.tsx +33 -8
  48. package/src/components/focus-trap/utils.ts +24 -6
  49. package/src/components/modal/CModal.tsx +30 -31
@@ -15,7 +15,6 @@ import Transition from '../../node_modules/react-transition-group/esm/Transition
15
15
  const CModal = forwardRef((_a, ref) => {
16
16
  var { children, alignment, backdrop = true, className, container, duration = 150, focus = true, fullscreen, keyboard = true, onClose, onClosePrevented, onShow, portal = true, scrollable, size, transition = true, unmountOnClose = true, visible } = _a, rest = __rest(_a, ["children", "alignment", "backdrop", "className", "container", "duration", "focus", "fullscreen", "keyboard", "onClose", "onClosePrevented", "onShow", "portal", "scrollable", "size", "transition", "unmountOnClose", "visible"]);
17
17
  const modalRef = useRef(null);
18
- const modalContentRef = useRef(null);
19
18
  const forkedRef = useForkedRef(ref, modalRef);
20
19
  const [_visible, setVisible] = useState(visible);
21
20
  const [staticBackdrop, setStaticBackdrop] = useState(false);
@@ -83,16 +82,16 @@ const CModal = forwardRef((_a, ref) => {
83
82
  return (React.createElement(React.Fragment, null,
84
83
  React.createElement(Transition, { in: _visible, mountOnEnter: true, nodeRef: modalRef, onEnter: onShow, onExit: onClose, unmountOnExit: unmountOnClose, timeout: transition ? duration : 0 }, (state) => (React.createElement(CConditionalPortal, { container: container, portal: portal },
85
84
  React.createElement(CModalContext.Provider, { value: contextValues },
86
- React.createElement("div", Object.assign({ className: classNames('modal', {
87
- 'modal-static': staticBackdrop,
88
- fade: transition,
89
- show: state === 'entered',
90
- }, className), tabIndex: -1 }, (_visible
91
- ? { 'aria-modal': true, role: 'dialog' }
92
- : { 'aria-hidden': 'true' }), { style: Object.assign({}, (state !== 'exited' && { display: 'block' })) }, rest, { ref: forkedRef }),
93
- React.createElement(CModalDialog, { alignment: alignment, fullscreen: fullscreen, scrollable: scrollable, size: size },
94
- React.createElement(CFocusTrap, { active: focus && state === 'entered', restoreFocus: true },
95
- React.createElement(CModalContent, { ref: modalContentRef }, children)))))))),
85
+ React.createElement(CFocusTrap, { active: focus && state === 'entered' },
86
+ React.createElement("div", Object.assign({ className: classNames('modal', {
87
+ 'modal-static': staticBackdrop,
88
+ fade: transition,
89
+ show: state === 'entered',
90
+ }, className), tabIndex: -1 }, (_visible
91
+ ? { 'aria-modal': true, role: 'dialog' }
92
+ : { 'aria-hidden': 'true' }), { style: Object.assign({}, (state !== 'exited' && { display: 'block' })) }, rest, { ref: forkedRef }),
93
+ React.createElement(CModalDialog, { alignment: alignment, fullscreen: fullscreen, scrollable: scrollable, size: size },
94
+ React.createElement(CModalContent, null, children)))))))),
96
95
  backdrop && (React.createElement(CConditionalPortal, { container: container, portal: portal },
97
96
  React.createElement(CBackdrop, { visible: _visible })))));
98
97
  });
@@ -1 +1 @@
1
- {"version":3,"file":"CModal.js","sources":["../../../../src/components/modal/CModal.tsx"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CModal.js","sources":["../../../../src/components/modal/CModal.tsx"],"sourcesContent":[null],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreui/react",
3
- "version": "5.8.0",
3
+ "version": "5.9.1",
4
4
  "description": "UI Components Library for React.js",
5
5
  "keywords": [
6
6
  "react",
@@ -47,27 +47,27 @@
47
47
  },
48
48
  "devDependencies": {
49
49
  "@rollup/plugin-commonjs": "^28.0.6",
50
- "@rollup/plugin-node-resolve": "^16.0.1",
50
+ "@rollup/plugin-node-resolve": "^16.0.2",
51
51
  "@rollup/plugin-typescript": "^12.1.4",
52
52
  "@testing-library/dom": "^10.4.1",
53
- "@testing-library/jest-dom": "^6.8.0",
53
+ "@testing-library/jest-dom": "^6.9.1",
54
54
  "@testing-library/react": "^16.3.0",
55
55
  "@types/jest": "^29.5.14",
56
- "@types/prop-types": "15.8.05",
57
- "@types/react": "^19.1.12",
58
- "@types/react-dom": "^19.1.9",
56
+ "@types/prop-types": "15.7.15",
57
+ "@types/react": "^19.2.0",
58
+ "@types/react-dom": "^19.2.0",
59
59
  "@types/react-transition-group": "^4.4.12",
60
60
  "classnames": "^2.5.1",
61
- "cross-env": "^10.0.0",
61
+ "cross-env": "^10.1.0",
62
62
  "jest": "^29.7.0",
63
63
  "jest-environment-jsdom": "^29.7.0",
64
64
  "react": "^18.3.1",
65
65
  "react-dom": "^18.3.1",
66
66
  "react-transition-group": "^4.4.5",
67
- "rollup": "^4.50.0",
68
- "ts-jest": "^29.4.1",
67
+ "rollup": "^4.52.4",
68
+ "ts-jest": "^29.4.4",
69
69
  "tslib": "^2.8.1",
70
- "typescript": "^5.9.2"
70
+ "typescript": "^5.9.3"
71
71
  },
72
72
  "peerDependencies": {
73
73
  "react": ">=17",
@@ -21,7 +21,8 @@ import type { Placements } from '../../types'
21
21
  import { getNextActiveElement, isRTL } from '../../utils'
22
22
 
23
23
  import type { Alignments, Directions } from './types'
24
- import { getPlacement } from './utils'
24
+ import { getPlacement, getReferenceElement } from './utils'
25
+ import { CFocusTrap } from '../focus-trap'
25
26
 
26
27
  export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIElement> {
27
28
  /**
@@ -160,6 +161,27 @@ export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIEl
160
161
  */
161
162
  portal?: boolean
162
163
 
164
+ /**
165
+ * Sets the reference element for positioning the React Dropdown Menu.
166
+ * - `toggle` - The React Dropdown Toggle button (default).
167
+ * - `parent` - The React Dropdown wrapper element.
168
+ * - `HTMLElement` - A custom HTML element.
169
+ * - `React.RefObject` - A custom reference element.
170
+ *
171
+ * @example
172
+ * // Use the parent element as reference for positioning
173
+ * <CDropdown reference="parent">
174
+ * <CDropdownToggle>Toggle dropdown</CDropdownToggle>
175
+ * <CDropdownMenu>
176
+ * <CDropdownItem>Action</CDropdownItem>
177
+ * <CDropdownItem>Another Action</CDropdownItem>
178
+ * </CDropdownMenu>
179
+ * </CDropdown>
180
+ *
181
+ * @since 5.9.0
182
+ */
183
+ reference?: 'parent' | 'toggle' | HTMLElement | React.RefObject<HTMLElement | null>
184
+
163
185
  /**
164
186
  * Defines the visual variant of the React Dropdown
165
187
  */
@@ -203,6 +225,7 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
203
225
  popper = true,
204
226
  popperConfig,
205
227
  portal = false,
228
+ reference = 'toggle',
206
229
  variant = 'btn-group',
207
230
  visible = false,
208
231
  ...rest
@@ -254,12 +277,20 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
254
277
  }, [visible])
255
278
 
256
279
  useEffect(() => {
257
- const toggleElement = dropdownToggleElement
280
+ return () => {
281
+ if (_visible) {
282
+ handleHide()
283
+ }
284
+ }
285
+ }, [])
286
+
287
+ useEffect(() => {
288
+ const referenceElement = getReferenceElement(reference, dropdownToggleElement, dropdownRef)
258
289
  const menuElement = dropdownMenuRef.current
259
- if (allowPopperUse && menuElement && toggleElement && _visible) {
260
- initPopper(toggleElement, menuElement, computedPopperConfig)
290
+ if (allowPopperUse && menuElement && referenceElement && _visible) {
291
+ initPopper(referenceElement, menuElement, computedPopperConfig)
261
292
  }
262
- }, [dropdownToggleElement])
293
+ }, [dropdownToggleElement, reference])
263
294
 
264
295
  useEffect(() => {
265
296
  if (pendingKeyDownEvent !== null) {
@@ -271,24 +302,28 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
271
302
  const handleHide = useCallback(() => {
272
303
  setVisible(false)
273
304
 
274
- const toggleElement = dropdownToggleElement
275
305
  const menuElement = dropdownMenuRef.current
306
+ const toggleElement = dropdownToggleElement
276
307
 
277
308
  if (allowPopperUse) {
278
309
  destroyPopper()
279
310
  }
280
311
 
281
- toggleElement?.removeEventListener('keydown', handleKeydown)
282
312
  menuElement?.removeEventListener('keydown', handleKeydown)
313
+ toggleElement?.removeEventListener('keydown', handleKeydown)
283
314
 
284
- window.removeEventListener('mouseup', handleMouseUp)
315
+ window.removeEventListener('click', handleClick)
285
316
  window.removeEventListener('keyup', handleKeyup)
286
317
 
287
318
  onHide?.()
288
- }, [dropdownToggleElement, allowPopperUse, destroyPopper, onHide])
319
+ }, [allowPopperUse, dropdownToggleElement, destroyPopper, onHide])
289
320
 
290
321
  const handleKeydown = useCallback((event: KeyboardEvent) => {
291
- if (dropdownMenuRef.current && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
322
+ if (!dropdownMenuRef.current) {
323
+ return
324
+ }
325
+
326
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
292
327
  event.preventDefault()
293
328
  const target = event.target as HTMLElement
294
329
  const items = [
@@ -311,28 +346,40 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
311
346
  dropdownToggleElement?.focus()
312
347
  }
313
348
  },
314
- [autoClose, handleHide]
349
+ [autoClose, dropdownToggleElement, handleHide]
315
350
  )
316
351
 
317
- const handleMouseUp = useCallback(
318
- (event: Event) => {
352
+ const handleClick = useCallback(
353
+ (event: MouseEvent) => {
319
354
  if (!dropdownToggleElement || !dropdownMenuRef.current) {
320
355
  return
321
356
  }
322
357
 
323
- if (dropdownToggleElement.contains(event.target as HTMLElement)) {
358
+ if ((event as MouseEvent).button === 2) {
359
+ return
360
+ }
361
+
362
+ const composedPath = event.composedPath()
363
+ const isOnToggle = composedPath.includes(dropdownToggleElement)
364
+ const isOnMenu = composedPath.includes(dropdownMenuRef.current)
365
+
366
+ if (isOnToggle) {
367
+ return
368
+ }
369
+
370
+ const target = event.target as HTMLElement | null
371
+ const FORM_TAG_RE = /^(input|select|option|textarea|form|button|label)$/i
372
+
373
+ if (isOnMenu && target && FORM_TAG_RE.test(target.tagName)) {
324
374
  return
325
375
  }
326
376
 
327
377
  if (
328
378
  autoClose === true ||
329
- (autoClose === 'inside' &&
330
- dropdownMenuRef.current.contains(event.target as HTMLElement)) ||
331
- (autoClose === 'outside' &&
332
- !dropdownMenuRef.current.contains(event.target as HTMLElement))
379
+ (autoClose === 'inside' && isOnMenu) ||
380
+ (autoClose === 'outside' && !isOnMenu)
333
381
  ) {
334
- setTimeout(() => handleHide(), 1)
335
- return
382
+ handleHide()
336
383
  }
337
384
  },
338
385
  [autoClose, dropdownToggleElement, handleHide]
@@ -340,21 +387,22 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
340
387
 
341
388
  const handleShow = useCallback(
342
389
  (event?: KeyboardEvent) => {
343
- const toggleElement = dropdownToggleElement
344
390
  const menuElement = dropdownMenuRef.current
391
+ const referenceElement = getReferenceElement(reference, dropdownToggleElement, dropdownRef)
392
+ const toggleElement = dropdownToggleElement
345
393
 
346
- if (toggleElement && menuElement) {
394
+ if (menuElement && referenceElement && toggleElement) {
347
395
  setVisible(true)
348
396
 
349
397
  if (allowPopperUse) {
350
- initPopper(toggleElement, menuElement, computedPopperConfig)
398
+ initPopper(referenceElement, menuElement, computedPopperConfig)
351
399
  }
352
400
 
353
401
  toggleElement.focus()
354
402
  toggleElement.addEventListener('keydown', handleKeydown)
355
403
  menuElement.addEventListener('keydown', handleKeydown)
356
404
 
357
- window.addEventListener('mouseup', handleMouseUp)
405
+ window.addEventListener('click', handleClick)
358
406
  window.addEventListener('keyup', handleKeyup)
359
407
 
360
408
  if (event && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
@@ -365,53 +413,71 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
365
413
  }
366
414
  },
367
415
  [
368
- dropdownToggleElement,
369
416
  allowPopperUse,
370
- initPopper,
371
417
  computedPopperConfig,
418
+ dropdownToggleElement,
419
+ reference,
420
+ handleClick,
372
421
  handleKeydown,
373
- handleMouseUp,
374
422
  handleKeyup,
423
+ initPopper,
375
424
  onShow,
376
425
  ]
377
426
  )
378
427
 
379
- const contextValues = {
380
- alignment,
381
- container,
382
- dark,
383
- dropdownMenuRef,
384
- dropdownToggleRef,
385
- handleHide,
386
- handleShow,
387
- popper: allowPopperUse,
388
- portal,
389
- variant,
390
- visible: _visible,
391
- }
428
+ const contextValues = useMemo(
429
+ () => ({
430
+ alignment,
431
+ container,
432
+ dark,
433
+ dropdownMenuRef,
434
+ dropdownToggleRef,
435
+ handleHide,
436
+ handleShow,
437
+ popper: allowPopperUse,
438
+ portal,
439
+ variant,
440
+ visible: _visible,
441
+ }),
442
+ [
443
+ alignment,
444
+ container,
445
+ dark,
446
+ dropdownMenuRef,
447
+ dropdownToggleRef,
448
+ handleHide,
449
+ handleShow,
450
+ allowPopperUse,
451
+ portal,
452
+ variant,
453
+ _visible,
454
+ ]
455
+ )
392
456
 
393
457
  return (
394
458
  <CDropdownContext.Provider value={contextValues}>
395
- {variant === 'input-group' ? (
396
- <>{children}</>
397
- ) : (
398
- <Component
399
- className={classNames(
400
- variant === 'nav-item' ? 'nav-item dropdown' : variant,
401
- {
402
- 'dropdown-center': direction === 'center',
403
- 'dropup dropup-center': direction === 'dropup-center',
404
- [`${direction}`]:
405
- direction && direction !== 'center' && direction !== 'dropup-center',
406
- },
407
- className
408
- )}
409
- {...rest}
410
- ref={forkedRef}
411
- >
412
- {children}
413
- </Component>
414
- )}
459
+ <CFocusTrap active={portal && _visible} additionalContainer={dropdownMenuRef} restoreFocus>
460
+ {variant === 'input-group' ? (
461
+ <>{children}</>
462
+ ) : (
463
+ <Component
464
+ className={classNames(
465
+ variant === 'nav-item' ? 'nav-item dropdown' : variant,
466
+ {
467
+ 'dropdown-center': direction === 'center',
468
+ 'dropup dropup-center': direction === 'dropup-center',
469
+ [`${direction}`]:
470
+ direction && direction !== 'center' && direction !== 'dropup-center',
471
+ },
472
+ className
473
+ )}
474
+ {...rest}
475
+ ref={forkedRef}
476
+ >
477
+ {children}
478
+ </Component>
479
+ )}
480
+ </CFocusTrap>
415
481
  </CDropdownContext.Provider>
416
482
  )
417
483
  }
@@ -9,6 +9,7 @@ export interface CDropdownHeaderProps extends HTMLAttributes<HTMLHeadingElement>
9
9
  * Component used for the root node. Either a string to use a HTML element or a component.
10
10
  */
11
11
  as?: ElementType
12
+
12
13
  /**
13
14
  * A string of all className you want applied to the component.
14
15
  */
@@ -9,6 +9,7 @@ export interface CDropdownItemPlainProps extends HTMLAttributes<HTMLSpanElement>
9
9
  * Component used for the root node. Either a string to use a HTML element or a component.
10
10
  */
11
11
  as?: ElementType
12
+
12
13
  /**
13
14
  * A string of all className you want applied to the component.
14
15
  */
@@ -15,6 +15,7 @@ export interface CDropdownMenuProps extends HTMLAttributes<HTMLDivElement | HTML
15
15
  * Component used for the root node. Either a string to use a HTML element or a component.
16
16
  */
17
17
  as?: ElementType
18
+
18
19
  /**
19
20
  * A string of all className you want applied to the base component.
20
21
  */
@@ -13,10 +13,12 @@ export interface CDropdownToggleProps extends Omit<CButtonProps, 'type'> {
13
13
  * Enables pseudo element caret on toggler.
14
14
  */
15
15
  caret?: boolean
16
+
16
17
  /**
17
18
  * Create a custom toggler which accepts any content.
18
19
  */
19
20
  custom?: boolean
21
+
20
22
  /**
21
23
  * If a dropdown `variant` is set to `nav-item` then render the toggler as a
22
24
  * link instead of a button.
@@ -24,12 +26,22 @@ export interface CDropdownToggleProps extends Omit<CButtonProps, 'type'> {
24
26
  * @since 5.0.0
25
27
  */
26
28
  navLink?: boolean
29
+
27
30
  /**
28
31
  * Similarly, create split button dropdowns with virtually the same markup as
29
32
  * single button dropdowns, but with the addition of `.dropdown-toggle-split`
30
33
  * className for proper spacing around the dropdown caret.
31
34
  */
32
35
  split?: boolean
36
+
37
+ /**
38
+ * Screen reader label for split button dropdown toggle.
39
+ *
40
+ * @default 'Toggle Dropdown'
41
+ * @since 5.9.0
42
+ */
43
+ splitLabel?: string
44
+
33
45
  /**
34
46
  * Sets which event handlers you'd like provided to your toggle prop. You can
35
47
  * specify one trigger or an array of them.
@@ -46,6 +58,7 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
46
58
  className,
47
59
  navLink = true,
48
60
  split,
61
+ splitLabel = 'Toggle Dropdown',
49
62
  trigger = 'click',
50
63
  ...rest
51
64
  }) => {
@@ -113,7 +126,7 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
113
126
  return (
114
127
  <CButton {...togglerProps} tabIndex={0} {...rest} ref={dropdownToggleRef}>
115
128
  {children}
116
- {split && <span className="visually-hidden">Toggle Dropdown</span>}
129
+ {split && <span className="visually-hidden">{splitLabel}</span>}
117
130
  </CButton>
118
131
  )
119
132
  }
@@ -124,6 +137,7 @@ CDropdownToggle.propTypes = {
124
137
  className: PropTypes.string,
125
138
  custom: PropTypes.bool,
126
139
  split: PropTypes.bool,
140
+ splitLabel: PropTypes.string,
127
141
  trigger: triggerPropType,
128
142
  }
129
143
 
@@ -1,3 +1,4 @@
1
+ import React from 'react'
1
2
  import type { Placement } from '@popperjs/core'
2
3
  import type { Placements } from '../../types'
3
4
  import type { Alignments, Breakpoints } from './types'
@@ -49,3 +50,23 @@ export const getPlacement = (
49
50
 
50
51
  return _placement
51
52
  }
53
+
54
+ export const getReferenceElement = (
55
+ reference: 'parent' | 'toggle' | React.RefObject<HTMLElement | null> | HTMLElement,
56
+ dropdownToggleElement: HTMLElement | null,
57
+ dropdownRef: React.RefObject<HTMLElement | null>
58
+ ): HTMLElement | null => {
59
+ if (reference === 'parent') {
60
+ return dropdownRef.current
61
+ }
62
+
63
+ if (reference instanceof HTMLElement) {
64
+ return reference
65
+ }
66
+
67
+ if (reference instanceof Object && 'current' in reference) {
68
+ return reference.current
69
+ }
70
+
71
+ return dropdownToggleElement
72
+ }
@@ -1,5 +1,5 @@
1
1
  import React, { FC, ReactElement, cloneElement, useEffect, useRef } from 'react'
2
- import { mergeRefs, focusableChildren } from './utils'
2
+ import { mergeRefs, focusableChildren, getChildRef } from './utils'
3
3
 
4
4
  export interface CFocusTrapProps {
5
5
  /**
@@ -146,7 +146,10 @@ export const CFocusTrap: FC<CFocusTrapProps> = ({
146
146
 
147
147
  if (elements.length === 0) {
148
148
  container.focus({ preventScroll: true })
149
- } else if (lastTabNavDirectionRef.current === 'backward') {
149
+ return
150
+ }
151
+
152
+ if (lastTabNavDirectionRef.current === 'backward') {
150
153
  elements.at(-1)?.focus({ preventScroll: true })
151
154
  } else {
152
155
  elements[0].focus({ preventScroll: true })
@@ -161,12 +164,8 @@ export const CFocusTrap: FC<CFocusTrapProps> = ({
161
164
  tabEventSourceRef.current = container
162
165
  lastTabNavDirectionRef.current = event.shiftKey ? 'backward' : 'forward'
163
166
 
164
- if (!_additionalContainer) {
165
- return
166
- }
167
-
168
167
  const containerElements = focusableChildren(container)
169
- const additionalElements = focusableChildren(_additionalContainer)
168
+ const additionalElements = _additionalContainer ? focusableChildren(_additionalContainer) : []
170
169
 
171
170
  if (containerElements.length === 0 && additionalElements.length === 0) {
172
171
  // No focusable elements, prevent tab
@@ -174,7 +173,28 @@ export const CFocusTrap: FC<CFocusTrapProps> = ({
174
173
  return
175
174
  }
176
175
 
176
+ const focusableElements = [...containerElements, ...additionalElements]
177
+
178
+ const firstFocusableElement = focusableElements[0] as HTMLElement
179
+ const lastFocusableElement = focusableElements.at(-1) as HTMLElement
177
180
  const activeElement = document.activeElement as HTMLElement
181
+
182
+ if (event.shiftKey && activeElement === firstFocusableElement) {
183
+ event.preventDefault()
184
+ lastFocusableElement.focus()
185
+ return
186
+ }
187
+
188
+ if (!event.shiftKey && activeElement === lastFocusableElement) {
189
+ event.preventDefault()
190
+ firstFocusableElement.focus()
191
+ return
192
+ }
193
+
194
+ if (!_additionalContainer) {
195
+ return
196
+ }
197
+
178
198
  const isInContainer = containerElements.includes(activeElement)
179
199
  const isInAdditional = additionalElements.includes(activeElement)
180
200
 
@@ -245,7 +265,12 @@ export const CFocusTrap: FC<CFocusTrapProps> = ({
245
265
 
246
266
  // Attach our ref to the ONLY child — no extra wrappers
247
267
  const onlyChild = React.Children.only(children)
248
- const childRef = (onlyChild as React.ReactElement & { ref?: React.Ref<HTMLElement> }).ref
268
+
269
+ // Handle different ref access patterns between React versions
270
+ // React 19+: ref is accessed via element.props.ref
271
+ // React 18 and earlier: ref is accessed via element.ref
272
+ const childRef: React.Ref<HTMLElement> | undefined = getChildRef(onlyChild)
273
+
249
274
  const mergedRef = mergeRefs(childRef, (node: HTMLElement | null) => {
250
275
  containerRef.current = node
251
276
  })
@@ -23,6 +23,30 @@ export const focusableChildren = (element: HTMLElement): HTMLElement[] => {
23
23
  return elements.filter((el) => !isDisabled(el) && isVisible(el))
24
24
  }
25
25
 
26
+ /**
27
+ * Extracts the ref from a React element, handling version differences between React 18 and 19+.
28
+ *
29
+ * In React 18 and earlier, refs are stored directly on the element object.
30
+ * In React 19+, refs are stored in the element's props object due to changes in React's internals.
31
+ * This function automatically detects the React version and uses the appropriate access pattern.
32
+ * @param child - The React element to extract the ref from
33
+ * @returns The ref attached to the element, or undefined if no ref is present
34
+ */
35
+ export const getChildRef = (child: React.ReactElement): React.Ref<HTMLElement> | undefined => {
36
+ const major = Number(React.version?.split?.('.')[0] ?? 18)
37
+ // React 18 stores ref directly on the element
38
+ if (major <= 18 && 'ref' in child && child.ref !== undefined) {
39
+ return (child as React.ReactElement & { ref?: React.Ref<HTMLElement> }).ref
40
+ }
41
+
42
+ // React 19 stores ref in props
43
+ if (child.props && typeof child.props === 'object' && 'ref' in child.props) {
44
+ return (child.props as { ref?: React.Ref<HTMLElement> }).ref
45
+ }
46
+
47
+ return undefined
48
+ }
49
+
26
50
  /**
27
51
  * Checks if an element is disabled.
28
52
  * Considers various ways an element can be disabled including CSS classes and attributes.
@@ -56,12 +80,6 @@ export const isElement = (object: unknown): object is Element => {
56
80
  return false
57
81
  }
58
82
 
59
- // Handle jQuery objects
60
- if ('jquery' in object && object.jquery !== undefined) {
61
- const jQueryObject = object as { [key: number]: Element }
62
- return isElement(jQueryObject[0])
63
- }
64
-
65
83
  return 'nodeType' in object && typeof object.nodeType === 'number'
66
84
  }
67
85