diff --git a/.changeset/brown-buttons-do.md b/.changeset/brown-buttons-do.md new file mode 100644 index 00000000..6967d36b --- /dev/null +++ b/.changeset/brown-buttons-do.md @@ -0,0 +1,5 @@ +--- +'focus-trap-react': patch +--- + +Fix missing default export in typings; props no longer extend `React.AllHTMLAttributes` to allow things like `className` (those extra props have always been ignored anyway); deprecate default export; add named export in code ([#1396](https://github.com/focus-trap/focus-trap-react/issues/1396)) diff --git a/README.md b/README.md index 9ab51bed..71cb83c4 100644 --- a/README.md +++ b/README.md @@ -84,10 +84,9 @@ You can read further code examples in `demo/` (it's very simple), and [see how i Here's one more simple example: ```jsx -const React = require('react'); -const ReactDOM = require('react-dom'); // React 16-17 -const { createRoot } = require('react-dom/client'); // React 18 -const FocusTrap = require('focus-trap-react'); +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { FocusTrap } from 'focus-trap-react'; class Demo extends React.Component { constructor(props) { @@ -150,7 +149,6 @@ class Demo extends React.Component { } } -ReactDOM.render(, document.getElementById('root')); // React 16-17 createRoot(document.getElementById('root')).render(); // React 18 ``` @@ -192,14 +190,13 @@ The result can be that (depending on how you render the trap) in Strict Mode, th Example: ```jsx -const React = require('react'); -const { createRoot } = require('react-dom/client'); -const propTypes = require('prop-types'); -const FocusTrap = require('../../dist/focus-trap-react'); +import { forwardRef, Component } from 'react'; +import { createRoot } from 'react-dom/client'; +import { FocusTrap } from 'focus-trap-react'; const container = document.getElementById('demo-function-child'); -const TrapChild = React.forwardRef(function ({ onDeactivate }, ref) { +const TrapChild = forwardRef(function ({ onDeactivate }, ref) { return (

@@ -223,7 +220,7 @@ TrapChild.propTypes = { onDeactivate: propTypes.func, }; -class DemoFunctionChild extends React.Component { +class DemoFunctionChild extends Component { constructor(props) { super(props); diff --git a/demo/js/demo-animated-dialog.js b/demo/js/demo-animated-dialog.js index cce27178..0bb39b61 100644 --- a/demo/js/demo-animated-dialog.js +++ b/demo/js/demo-animated-dialog.js @@ -1,7 +1,7 @@ const { useState } = require('react'); const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const container = document.getElementById('demo-animated-dialog'); diff --git a/demo/js/demo-animated-trigger.js b/demo/js/demo-animated-trigger.js index b36f185f..2a431008 100644 --- a/demo/js/demo-animated-trigger.js +++ b/demo/js/demo-animated-trigger.js @@ -1,7 +1,7 @@ const { useState } = require('react'); const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const container = document.getElementById('demo-animated-trigger'); diff --git a/demo/js/demo-autofocus.js b/demo/js/demo-autofocus.js index eea7d652..861563c8 100644 --- a/demo/js/demo-autofocus.js +++ b/demo/js/demo-autofocus.js @@ -1,6 +1,6 @@ const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const container = document.getElementById('demo-autofocus'); diff --git a/demo/js/demo-containerelements-childless.js b/demo/js/demo-containerelements-childless.js index 5c245742..8ffd3e6e 100644 --- a/demo/js/demo-containerelements-childless.js +++ b/demo/js/demo-containerelements-childless.js @@ -1,6 +1,6 @@ const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const container = document.getElementById('demo-containerelements-childless'); diff --git a/demo/js/demo-containerelements.js b/demo/js/demo-containerelements.js index 8532baf7..ad718755 100644 --- a/demo/js/demo-containerelements.js +++ b/demo/js/demo-containerelements.js @@ -1,6 +1,6 @@ const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const container = document.getElementById('demo-containerelements'); diff --git a/demo/js/demo-defaults.js b/demo/js/demo-defaults.js index be5dd634..876dfabf 100644 --- a/demo/js/demo-defaults.js +++ b/demo/js/demo-defaults.js @@ -1,6 +1,6 @@ const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const container = document.getElementById('demo-defaults'); diff --git a/demo/js/demo-ffne.js b/demo/js/demo-ffne.js index 2973695c..a30587c1 100644 --- a/demo/js/demo-ffne.js +++ b/demo/js/demo-ffne.js @@ -1,6 +1,6 @@ const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const container = document.getElementById('demo-ffne'); diff --git a/demo/js/demo-iframe.js b/demo/js/demo-iframe.js index 3e9ebd3f..4d538cf2 100644 --- a/demo/js/demo-iframe.js +++ b/demo/js/demo-iframe.js @@ -2,7 +2,7 @@ const React = require('react'); const ReactDOM = require('react-dom'); const { createRoot } = require('react-dom/client'); const PropTypes = require('prop-types'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const { useRef, useState, useEffect } = React; const container = document.getElementById('demo-iframe'); diff --git a/demo/js/demo-setReturnFocus.js b/demo/js/demo-setReturnFocus.js index 1f56c09d..c9848f51 100644 --- a/demo/js/demo-setReturnFocus.js +++ b/demo/js/demo-setReturnFocus.js @@ -1,7 +1,7 @@ const { useState, useMemo } = require('react'); const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const container = document.getElementById('demo-setReturnFocus'); diff --git a/demo/js/demo-special-element.js b/demo/js/demo-special-element.js index f2f53cff..9de863bb 100644 --- a/demo/js/demo-special-element.js +++ b/demo/js/demo-special-element.js @@ -1,6 +1,6 @@ const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const container = document.getElementById('demo-special-element'); diff --git a/demo/js/demo-with-shadow-dom.js b/demo/js/demo-with-shadow-dom.js index 98d36160..df2cf425 100644 --- a/demo/js/demo-with-shadow-dom.js +++ b/demo/js/demo-with-shadow-dom.js @@ -1,6 +1,6 @@ const React = require('react'); const { createRoot } = require('react-dom/client'); -const FocusTrap = require('../../dist/focus-trap-react'); +const { FocusTrap } = require('../../dist/focus-trap-react'); const createShadow = function (hostEl, isOpen) { const containerEl = document.createElement('div'); diff --git a/index.d.ts b/index.d.ts index 6afe9355..81e09d5b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,14 +1,56 @@ import { Options as FocusTrapOptions } from 'focus-trap'; import * as React from 'react'; +export interface FocusTrapProps { + /** + * __Single container child__ for the trap. Use `containerElements` instead + * if you need a trap with multiple containers. + */ + children?: React.ReactNode; + + /** + * By default, the trap will be active when it mounts, so it's activated by + * mounting, and deactivated by unmounting. Use this prop to control when + * it's active while it's mounted, or if it's initially inactive. + */ + active?: boolean; + + /** + * To pause or unpause the trap while it's `active`. Primarily for use when + * you need to manage multiple traps in the same view. When paused, the trap + * retains its various event listeners, but ignores all events. + */ + paused?: boolean; + + /** + * See Focus-trap's [createOptions](https://github.com/focus-trap/focus-trap?tab=readme-ov-file#createoptions) + * for more details on available options. + */ + focusTrapOptions?: FocusTrapOptions; + + /** + * If specified, these elements will be used as the boundaries for the + * trap, __instead of the child__ specified in `children` (though + * `children` will still be rendered). + */ + containerElements?: Array; +} + +export declare class FocusTrap extends React.Component { } + +/** + * Default export of the FocusTrap component. + * @deprecated 🔺 Use the named import `{ FocusTrap }` instead. + * @description 🔺 The default export will be removed in a future release. Migrate to the named + * import `{ FocusTrap }` today to ensure future compatibility. + */ declare namespace FocusTrap { - export interface Props extends React.AllHTMLAttributes { - children?: React.ReactNode; - active?: boolean; - paused?: boolean; - focusTrapOptions?: FocusTrapOptions; - containerElements?: Array; - } + export type Props = FocusTrapProps; } -export declare class FocusTrap extends React.Component { } +/** + * @deprecated 🔺 Use the named import `{ FocusTrap }` instead. + * @description 🔺 The default export will be removed in a future release. Migrate to the named + * import `{ FocusTrap }` today to ensure future compatibility. + */ +export default FocusTrap; diff --git a/src/focus-trap-react.js b/src/focus-trap-react.js index 971c918b..12da5192 100644 --- a/src/focus-trap-react.js +++ b/src/focus-trap-react.js @@ -425,4 +425,8 @@ FocusTrap.defaultProps = { _createFocusTrap: createFocusTrap, }; +// 🔺 DEPRECATED: default export module.exports = FocusTrap; + +// named export +module.exports.FocusTrap = FocusTrap; diff --git a/test/focus-trap-react.test.js b/test/focus-trap-react.test.js index 408a371b..2f0bcc10 100644 --- a/test/focus-trap-react.test.js +++ b/test/focus-trap-react.test.js @@ -6,7 +6,7 @@ const { waitFor, } = require('@testing-library/react'); const { default: userEvent } = require('@testing-library/user-event'); -const FocusTrap = require('../src/focus-trap-react'); +const { FocusTrap } = require('../src/focus-trap-react'); const getTestFocusTrapOptions = function (focusTrapOptions) { const { tabbableOptions, ...rest } = focusTrapOptions || {};