@deque/cauldron-react 6.6.1 → 6.7.0-canary.099092f1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,6 +22,10 @@ yarn add @deque/cauldron-react @deque/cauldron-styles
22
22
 
23
23
  To get started, follow our [usage guide](https://cauldron.dequelabs.com/#usage) that includes setup instructions and necessary dependencies. Further documentation is also available at [cauldron.dequelabs.com](https://cauldron.dequelabs.com) that includes documentation for every available Cauldron component.
24
24
 
25
+ ## Attribution
26
+
27
+ Some Cauldron icons use Font Awesome Free and Font Awesome Pro. Their licenses can be found here: [Font Awesome Free License](https://fontawesome.com/license/free) and [Font Awesome Pro License](https://fontawesome.com/license).
28
+
25
29
  ## Contribute
26
30
 
27
31
  If you're interested in contributing to Cauldron, you can check out our [contribution guide](https://github.com/dequelabs/cauldron/blob/develop/CONTRIBUTING.md) as well as our [code of conduct](https://github.com/dequelabs/cauldron/blob/develop/CODE_OF_CONDUCT.md).
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ function _interopNamespace(e) {
6
+ if (e && e.__esModule) return e;
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n["default"] = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
24
+
25
+ var _path;
26
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
27
+ const SvgBrokenImage = props => /*#__PURE__*/React__namespace.createElement("svg", _extends({
28
+ viewBox: "0 0 24 24",
29
+ fill: "currentColor",
30
+ height: 24,
31
+ width: 24
32
+ }, props), _path || (_path = /*#__PURE__*/React__namespace.createElement("path", {
33
+ d: "M22.154 0H1.846c-.49 0-.96.23-1.305.639C.195 1.049 0 1.603 0 2.182v19.636c0 .579.195 1.134.54 1.543.347.41.817.639 1.306.639h7.385a.831.831 0 0 0 .54-.206c.157-.134.274-.323.335-.54l1.712-6.065 4.22-1.994a.935.935 0 0 0 .31-.242c.088-.105.158-.23.205-.366l1.687-4.984 5.132-2.023a.952.952 0 0 0 .455-.398A1.23 1.23 0 0 0 24 6.545V2.182c0-.579-.195-1.134-.54-1.543C23.112.229 22.642 0 22.153 0ZM10.2 16.019l-1.636 5.8H1.846V18l6-7.09 3.51 4.147-.625.293a.933.933 0 0 0-.327.266c-.092.115-.16.253-.203.403Zm11.953-10.26-4.907 1.933a.908.908 0 0 0-.342.242 1.117 1.117 0 0 0-.224.388l-1.698 5.021-1.762.839-4.07-4.81c-.346-.409-.815-.638-1.305-.638s-.959.23-1.305.638l-4.695 5.542V2.182h20.308v3.577Zm1.463 4.5a.852.852 0 0 0-.4-.194.789.789 0 0 0-.432.044l-2.746 1.082a.908.908 0 0 0-.341.241 1.117 1.117 0 0 0-.224.388l-1.652 4.878-4.127 1.951a.934.934 0 0 0-.328.265 1.146 1.146 0 0 0-.204.403l-.916 3.246a1.28 1.28 0 0 0-.037.51c.021.17.078.333.163.474.086.14.198.254.329.333.13.079.274.12.42.12h9.032c.49 0 .96-.23 1.305-.639.346-.41.541-.964.541-1.543V11.145c0-.173-.035-.343-.101-.497a1.062 1.062 0 0 0-.282-.388v-.001Zm-1.463 11.56h-7.75l.374-1.33 4.098-1.937a.936.936 0 0 0 .31-.242c.088-.104.158-.229.204-.366l1.639-4.842 1.125-.443v9.16Z"
34
+ })));
35
+
36
+ exports["default"] = SvgBrokenImage;
package/lib/cauldron.css CHANGED
@@ -39,6 +39,12 @@
39
39
  }
40
40
  }
41
41
 
42
+ a.Button--primary,
43
+ a.Button--secondary,
44
+ a.Button--thin {
45
+ font-weight: var(--font-weight-medium);
46
+ }
47
+
42
48
  a.Button--primary,
43
49
  a.Button--secondary {
44
50
  text-decoration: none;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { ContentNode } from '../../types';
3
+ declare const BottomSheet: React.ForwardRefExoticComponent<{
4
+ label: ContentNode;
5
+ closeButtonText?: ContentNode | undefined;
6
+ open?: boolean | undefined;
7
+ } & React.HTMLAttributes<HTMLDivElement> & Pick<import("../Drawer").DrawerProps<HTMLElement> & React.RefAttributes<HTMLDivElement>, "open" | "onClose" | "portal" | "focusOptions"> & React.RefAttributes<HTMLDivElement>>;
8
+ export default BottomSheet;
@@ -4,23 +4,7 @@ export interface ClickOutsideListenerProps<T extends HTMLElement = HTMLElement>
4
4
  onClickOutside: (e: MouseEvent | TouchEvent) => void;
5
5
  mouseEvent?: 'mousedown' | 'click' | 'mouseup' | false;
6
6
  touchEvent?: 'touchstart' | 'touchend' | false;
7
- target?: T;
8
- }
9
- export default class ClickOutsideListener extends React.Component<ClickOutsideListenerProps> {
10
- static displayName: string;
11
- static defaultProps: {
12
- mouseEvent: string;
13
- touchEvent: string;
14
- };
15
- private nodeRef;
16
- handleEvent: (event: MouseEvent | TouchEvent) => void;
17
- componentDidMount(): void;
18
- componentDidUpdate(prevProps: ClickOutsideListenerProps): void;
19
- componentWillUnmount(): void;
20
- private attachEventListeners;
21
- private removeEventListeners;
22
- resolveRef: (node: HTMLElement) => void;
23
- render(): React.FunctionComponentElement<{
24
- ref: (node: HTMLElement) => void;
25
- }> | null;
7
+ target?: T | React.RefObject<T> | React.MutableRefObject<T>;
26
8
  }
9
+ declare const _default: React.ForwardRefExoticComponent<ClickOutsideListenerProps<HTMLElement> & React.RefAttributes<HTMLElement>>;
10
+ export default _default;
@@ -1,10 +1,15 @@
1
1
  import React from 'react';
2
2
  import { SyntaxHighlighterProps } from 'react-syntax-highlighter';
3
+ import type { ContentNode } from '../../types';
4
+ import CopyButton from '../CopyButton';
3
5
  type Props = {
4
6
  children: string;
5
7
  language?: 'javascript' | 'css' | 'html' | 'yaml';
6
8
  className?: string;
7
9
  scrollable?: boolean;
10
+ label?: ContentNode;
11
+ allowCopy?: boolean;
12
+ copyButtonProps?: React.ComponentProps<typeof CopyButton>;
8
13
  } & SyntaxHighlighterProps & React.HTMLAttributes<HTMLDivElement>;
9
14
  declare const Code: React.ComponentType<React.PropsWithChildren<Props>>;
10
15
  export default Code;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ export interface DrawerProps<T extends HTMLElement = HTMLElement> extends React.HTMLAttributes<HTMLDivElement> {
3
+ children: React.ReactNode;
4
+ position: 'top' | 'bottom' | 'left' | 'right';
5
+ open?: boolean;
6
+ behavior?: 'modal' | 'non-modal';
7
+ focusOptions?: {
8
+ initialFocus?: T | React.RefObject<T> | React.MutableRefObject<T>;
9
+ returnFocus?: T | React.RefObject<T> | React.MutableRefObject<T>;
10
+ };
11
+ onClose?: () => void;
12
+ portal?: React.RefObject<HTMLElement> | HTMLElement;
13
+ }
14
+ declare const Drawer: React.ForwardRefExoticComponent<DrawerProps<HTMLElement> & React.RefAttributes<HTMLDivElement>>;
15
+ export default Drawer;
@@ -2,6 +2,6 @@
2
2
  * GENERATED CODE. DO NOT EDIT DIRECTLY!
3
3
  */
4
4
  /** IconType represents each valid icon type. */
5
- export type IconType = 'add-user' | 'arrow-circle-up' | 'arrow-circle-down' | 'arrow-circle-left' | 'arrow-circle-right' | 'arrow-up' | 'arrow-down' | 'arrow-left' | 'arrow-right' | 'arrows-alt' | 'bolt' | 'caution' | 'check-circle' | 'check-shield' | 'check-solid' | 'check' | 'checkbox-checked' | 'checkbox-unchecked' | 'chevron-double-up' | 'chevron-double-down' | 'chevron-double-left' | 'chevron-double-right' | 'chevron-up' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'clipboard' | 'clock' | 'close' | 'code' | 'copy' | 'download' | 'dropper' | 'exchange' | 'export-solid' | 'external-link' | 'eye' | 'filter-solid' | 'filter' | 'flag' | 'gears' | 'github' | 'grid' | 'hamburger-menu' | 'hashtag' | 'highlight' | 'info-circle-alt' | 'info-circle' | 'info-square' | 'kabob' | 'link' | 'linkedin' | 'list' | 'lock' | 'magnifying-glass' | 'menu' | 'minus' | 'new-releases' | 'new' | 'no' | 'pencil' | 'person-running' | 'play' | 'plus' | 'question-circle-alt' | 'question-circle' | 'radio-checked' | 'radio-unchecked' | 'recycle-square' | 'recycle' | 'resend' | 'robot' | 'run-again' | 'save' | 'share-nodes' | 'share' | 'sort-triangle' | 'sort' | 'star' | 'step-back' | 'step-forward' | 'sun' | 'table-sort-ascending' | 'table-sort-descending' | 'tag' | 'target' | 'trash' | 'triangle-up' | 'triangle-down' | 'triangle-left' | 'triangle-right' | 'twitter' | 'upload';
5
+ export type IconType = 'add-user' | 'arrow-circle-up' | 'arrow-circle-down' | 'arrow-circle-left' | 'arrow-circle-right' | 'arrow-up' | 'arrow-down' | 'arrow-left' | 'arrow-right' | 'arrows-alt' | 'bolt' | 'broken-image' | 'caution' | 'check-circle' | 'check-shield' | 'check-solid' | 'check' | 'checkbox-checked' | 'checkbox-unchecked' | 'chevron-double-up' | 'chevron-double-down' | 'chevron-double-left' | 'chevron-double-right' | 'chevron-up' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'clipboard' | 'clock' | 'close' | 'code' | 'copy' | 'download' | 'dropper' | 'exchange' | 'export-solid' | 'external-link' | 'eye' | 'filter-solid' | 'filter' | 'flag' | 'gears' | 'github' | 'grid' | 'hamburger-menu' | 'hashtag' | 'highlight' | 'images' | 'info-circle-alt' | 'info-circle' | 'info-square' | 'kabob' | 'link' | 'linkedin' | 'list' | 'lock' | 'magnifying-glass' | 'menu' | 'minus' | 'new-releases' | 'new' | 'no' | 'pencil' | 'person-running' | 'play' | 'plus' | 'question-circle-alt' | 'question-circle' | 'radio-checked' | 'radio-unchecked' | 'recycle-square' | 'recycle' | 'resend' | 'robot' | 'run-again' | 'save' | 'share-nodes' | 'share' | 'sort-triangle' | 'sort' | 'star' | 'step-back' | 'step-forward' | 'sun' | 'table-sort-ascending' | 'table-sort-descending' | 'tag' | 'target' | 'trash' | 'triangle-up' | 'triangle-down' | 'triangle-left' | 'triangle-right' | 'twitter' | 'upload';
6
6
  /** iconTypes holds each valid icon type. */
7
7
  export declare const iconTypes: string[];
package/lib/images.js ADDED
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ function _interopNamespace(e) {
6
+ if (e && e.__esModule) return e;
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n["default"] = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
24
+
25
+ var _path;
26
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
27
+ const SvgImages = props => /*#__PURE__*/React__namespace.createElement("svg", _extends({
28
+ xmlns: "http://www.w3.org/2000/svg",
29
+ viewBox: "0 0 576 512",
30
+ height: 24,
31
+ width: 24
32
+ }, props), _path || (_path = /*#__PURE__*/React__namespace.createElement("path", {
33
+ d: "M160 32c-35.3 0-64 28.7-64 64v224c0 35.3 28.7 64 64 64h352c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H160zm236 106.7 96 144c4.9 7.4 5.4 16.8 1.2 24.6S480.9 320 472 320H200c-9.2 0-17.6-5.3-21.6-13.6s-2.9-18.2 2.9-25.4l64-80c4.6-5.7 11.4-9 18.7-9s14.2 3.3 18.7 9l17.3 21.6 56-84c4.5-6.6 12-10.6 20-10.6s15.5 4 20 10.7zM192 128a32 32 0 1 1 64 0 32 32 0 1 1-64 0zm-144-8c0-13.3-10.7-24-24-24S0 106.7 0 120v224c0 75.1 60.9 136 136 136h320c13.3 0 24-10.7 24-24s-10.7-24-24-24H136c-48.6 0-88-39.4-88-88V120z",
34
+ fill: "currentColor"
35
+ })));
36
+
37
+ exports["default"] = SvgImages;
package/lib/index.d.ts CHANGED
@@ -59,6 +59,8 @@ export { default as Popover } from './components/Popover';
59
59
  export { default as Timeline, TimelineItem } from './components/Timeline';
60
60
  export { default as TextEllipsis } from './components/TextEllipsis';
61
61
  export { default as CopyButton } from './components/CopyButton';
62
+ export { default as Drawer } from './components/Drawer';
63
+ export { default as BottomSheet } from './components/BottomSheet';
62
64
  /**
63
65
  * Helpers / Utils
64
66
  */
package/lib/index.js CHANGED
@@ -114,6 +114,7 @@ var iconTypes = [
114
114
  'arrow-right',
115
115
  'arrows-alt',
116
116
  'bolt',
117
+ 'broken-image',
117
118
  'caution',
118
119
  'check-circle',
119
120
  'check-shield',
@@ -149,6 +150,7 @@ var iconTypes = [
149
150
  'hamburger-menu',
150
151
  'hashtag',
151
152
  'highlight',
153
+ 'images',
152
154
  'info-circle-alt',
153
155
  'info-circle',
154
156
  'info-square',
@@ -205,6 +207,7 @@ function __variableDynamicImportRuntime0__(path) {
205
207
  case './icons/arrow.svg': return Promise.resolve().then(function () { return require('./arrow.js'); });
206
208
  case './icons/arrows-alt.svg': return Promise.resolve().then(function () { return require('./arrows-alt.js'); });
207
209
  case './icons/bolt.svg': return Promise.resolve().then(function () { return require('./bolt.js'); });
210
+ case './icons/broken-image.svg': return Promise.resolve().then(function () { return require('./broken-image.js'); });
208
211
  case './icons/caution.svg': return Promise.resolve().then(function () { return require('./caution.js'); });
209
212
  case './icons/check-circle.svg': return Promise.resolve().then(function () { return require('./check-circle.js'); });
210
213
  case './icons/check-shield.svg': return Promise.resolve().then(function () { return require('./check-shield.js'); });
@@ -234,6 +237,7 @@ function __variableDynamicImportRuntime0__(path) {
234
237
  case './icons/hamburger-menu.svg': return Promise.resolve().then(function () { return require('./hamburger-menu.js'); });
235
238
  case './icons/hashtag.svg': return Promise.resolve().then(function () { return require('./hashtag.js'); });
236
239
  case './icons/highlight.svg': return Promise.resolve().then(function () { return require('./highlight.js'); });
240
+ case './icons/images.svg': return Promise.resolve().then(function () { return require('./images.js'); });
237
241
  case './icons/info-circle-alt.svg': return Promise.resolve().then(function () { return require('./info-circle-alt.js'); });
238
242
  case './icons/info-circle.svg': return Promise.resolve().then(function () { return require('./info-circle.js'); });
239
243
  case './icons/info-square.svg': return Promise.resolve().then(function () { return require('./info-square.js'); });
@@ -789,74 +793,70 @@ var OptionsMenuWrapper = function (_a) {
789
793
  return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('OptionsMenu', menuAlignment(align), className) }, other)));
790
794
  };
791
795
 
792
- var ClickOutsideListener = /** @class */ (function (_super) {
793
- tslib.__extends(ClickOutsideListener, _super);
794
- function ClickOutsideListener() {
795
- var _this = _super !== null && _super.apply(this, arguments) || this;
796
- _this.handleEvent = function (event) {
797
- var _a = _this, nodeRef = _a.nodeRef, props = _a.props;
798
- var onClickOutside = props.onClickOutside, target = props.target;
799
- if (event.defaultPrevented) {
800
- return;
801
- }
802
- var eventTarget = event.target;
803
- if ((target && !target.contains(eventTarget)) ||
804
- (nodeRef && !nodeRef.contains(eventTarget))) {
805
- onClickOutside(event);
806
- }
807
- };
808
- _this.attachEventListeners = function () {
809
- var _a = _this.props, mouseEvent = _a.mouseEvent, touchEvent = _a.touchEvent;
810
- typeof mouseEvent === 'string' &&
811
- document.addEventListener(mouseEvent, _this.handleEvent);
812
- typeof touchEvent === 'string' &&
813
- document.addEventListener(touchEvent, _this.handleEvent);
814
- };
815
- _this.removeEventListeners = function (mouseEvent, touchEvent) {
816
- typeof mouseEvent === 'string' &&
817
- document.removeEventListener(mouseEvent, _this.handleEvent);
818
- typeof touchEvent === 'string' &&
819
- document.removeEventListener(touchEvent, _this.handleEvent);
820
- };
821
- _this.resolveRef = function (node) {
822
- _this.nodeRef = node;
823
- // If child has its own ref, we want to update
824
- // its ref with the newly cloned node
825
- var ref = _this.props.children.ref;
826
- setRef(ref, node);
827
- };
828
- return _this;
796
+ /**
797
+ * When an element can be passed as a value that is either an element or an
798
+ * elementRef, this will resolve the property down to the resulting element
799
+ */
800
+ function resolveElement(elementOrRef) {
801
+ if (elementOrRef instanceof Element) {
802
+ return elementOrRef;
829
803
  }
830
- ClickOutsideListener.prototype.componentDidMount = function () {
831
- this.attachEventListeners();
832
- };
833
- ClickOutsideListener.prototype.componentDidUpdate = function (prevProps) {
834
- var _a = this.props, mouseEvent = _a.mouseEvent, touchEvent = _a.touchEvent;
835
- if (prevProps.mouseEvent !== mouseEvent ||
836
- prevProps.touchEvent !== touchEvent) {
837
- this.removeEventListeners(prevProps.mouseEvent, prevProps.touchEvent);
838
- this.attachEventListeners();
804
+ if (elementOrRef &&
805
+ typeof elementOrRef === 'object' &&
806
+ 'current' in elementOrRef &&
807
+ elementOrRef.current instanceof Element) {
808
+ return elementOrRef.current;
809
+ }
810
+ return null;
811
+ }
812
+
813
+ function ClickOutsideListener(_a, ref) {
814
+ var children = _a.children, _b = _a.mouseEvent, mouseEvent = _b === void 0 ? 'click' : _b, _c = _a.touchEvent, touchEvent = _c === void 0 ? 'touchend' : _c, target = _a.target, _d = _a.onClickOutside, onClickOutside = _d === void 0 ? function () { return null; } : _d;
815
+ var childElementRef = React.useRef();
816
+ var handleEvent = function (event) {
817
+ if (event.defaultPrevented) {
818
+ return;
819
+ }
820
+ var eventTarget = event.target;
821
+ var elementTarget = resolveElement(target);
822
+ if (target && !(elementTarget === null || elementTarget === void 0 ? void 0 : elementTarget.contains(eventTarget))) {
823
+ onClickOutside(event);
824
+ // If a target is passed in via a prop, we defer to utilizing that
825
+ // target instead of a child element target
826
+ return;
827
+ }
828
+ if (childElementRef.current &&
829
+ !childElementRef.current.contains(eventTarget)) {
830
+ onClickOutside(event);
839
831
  }
840
832
  };
841
- ClickOutsideListener.prototype.componentWillUnmount = function () {
842
- var _a = this.props, mouseEvent = _a.mouseEvent, touchEvent = _a.touchEvent;
843
- this.removeEventListeners(mouseEvent, touchEvent);
844
- };
845
- ClickOutsideListener.prototype.render = function () {
846
- var _a = this, props = _a.props, resolveRef = _a.resolveRef;
847
- return !props.children
848
- ? null
849
- : React__default["default"].cloneElement(props.children, {
850
- ref: resolveRef
851
- });
852
- };
853
- ClickOutsideListener.displayName = 'ClickOutsideListener';
854
- ClickOutsideListener.defaultProps = {
855
- mouseEvent: 'click',
856
- touchEvent: 'touchend'
833
+ var resolveRef = function (node) {
834
+ childElementRef.current = node;
835
+ // Ref for this component should pass-through to the child node
836
+ setRef(ref, node);
837
+ // If child has its own ref, we want to update
838
+ // its ref with the newly cloned node
839
+ var childRef = children.ref;
840
+ setRef(childRef, node);
857
841
  };
858
- return ClickOutsideListener;
859
- }(React__default["default"].Component));
842
+ React.useEffect(function () {
843
+ typeof mouseEvent === 'string' &&
844
+ document.addEventListener(mouseEvent, handleEvent);
845
+ typeof touchEvent === 'string' &&
846
+ document.addEventListener(touchEvent, handleEvent);
847
+ return function () {
848
+ typeof mouseEvent === 'string' &&
849
+ document.removeEventListener(mouseEvent, handleEvent);
850
+ typeof touchEvent === 'string' &&
851
+ document.removeEventListener(touchEvent, handleEvent);
852
+ };
853
+ }, [mouseEvent, touchEvent]);
854
+ return !children
855
+ ? null
856
+ : React__default["default"].cloneElement(children, { ref: resolveRef });
857
+ }
858
+ ClickOutsideListener.displayName = 'ClickOutsideListener';
859
+ var ClickOutsideListener$1 = React__default["default"].forwardRef(ClickOutsideListener);
860
860
 
861
861
  var _a$2 = tslib.__read([38, 40, 9, 13, 32, 27], 6), up = _a$2[0], down$1 = _a$2[1], tab = _a$2[2], enter = _a$2[3], space = _a$2[4], esc = _a$2[5];
862
862
  var OptionsMenuList = /** @class */ (function (_super) {
@@ -962,7 +962,7 @@ var OptionsMenuList = /** @class */ (function (_super) {
962
962
  // Key event is being handled in componentDidMount
963
963
  /* eslint-disable jsx-a11y/click-events-have-key-events */
964
964
  /* eslint-disable jsx-a11y/role-supports-aria-props */
965
- return (React__default["default"].createElement(ClickOutsideListener, { onClickOutside: this.handleClickOutside, mouseEvent: clickOutsideEventActive, touchEvent: clickOutsideEventActive },
965
+ return (React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: this.handleClickOutside, mouseEvent: clickOutsideEventActive, touchEvent: clickOutsideEventActive },
966
966
  React__default["default"].createElement("ul", tslib.__assign({}, other, { className: classNames__default["default"]('OptionsMenu__list', className), "aria-expanded": show, role: "menu", onClick: handleClick, ref: function (el) {
967
967
  _this.menuRef = el;
968
968
  if (menuRef) {
@@ -1310,7 +1310,7 @@ var SideBar = /** @class */ (function (_super) {
1310
1310
  var _b = this.props, children = _b.children, className = _b.className, show = _b.show; _b.onDismiss; var navProps = _b.navProps, other = tslib.__rest(_b, ["children", "className", "show", "onDismiss", "navProps"]);
1311
1311
  /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
1312
1312
  return (React__default["default"].createElement(React.Fragment, null,
1313
- React__default["default"].createElement(ClickOutsideListener, { onClickOutside: this.handleClickOutside },
1313
+ React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: this.handleClickOutside },
1314
1314
  React__default["default"].createElement("nav", tslib.__assign({}, navProps),
1315
1315
  React__default["default"].createElement("ul", tslib.__assign({ className: classNames__default["default"]('SideBar', className, animateClass) }, other, { ref: this.navList, onKeyDown: this.onKeyDown }), children))),
1316
1316
  React__default["default"].createElement(Scrim, { show: !wide && show })));
@@ -1449,7 +1449,7 @@ var Dialog = /** @class */ (function (_super) {
1449
1449
  escapeDeactivates: false,
1450
1450
  fallbackFocus: '.Dialog__heading'
1451
1451
  } },
1452
- React__default["default"].createElement(ClickOutsideListener, { onClickOutside: this.handleClickOutside },
1452
+ React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: this.handleClickOutside },
1453
1453
  React__default["default"].createElement("div", tslib.__assign({ role: "dialog", className: classNames__default["default"]('Dialog', className, {
1454
1454
  'Dialog--show': show
1455
1455
  }), ref: function (el) {
@@ -1665,6 +1665,46 @@ function hasIdRef(ids, id) {
1665
1665
  return idRefs(ids).has(id);
1666
1666
  }
1667
1667
 
1668
+ var isEscapeKey = function (event) {
1669
+ return event.key === 'Escape' || event.key === 'Esc' || event.keyCode === 27;
1670
+ };
1671
+ /**
1672
+ * When a component needs to implement an escape handler, such as in modal
1673
+ * dialogs, useEscapeKey will handle the events and call the provided callback
1674
+ * handler when an escape key event has been fired.
1675
+ *
1676
+ * @example
1677
+ * useEscapeKey(() => close())
1678
+ */
1679
+ function useEscapeKey(options, dependencies) {
1680
+ if (dependencies === void 0) { dependencies = []; }
1681
+ var callback = options.callback;
1682
+ var event = options.event || 'keyup';
1683
+ var target = resolveElement(options.target) || document.body;
1684
+ var active = typeof options.active === 'boolean' ? options.active : true;
1685
+ React.useEffect(function () {
1686
+ var eventListener = function (event) {
1687
+ if (isEscapeKey(event) &&
1688
+ (options.defaultPrevented ? !event.defaultPrevented : true)) {
1689
+ callback(event);
1690
+ }
1691
+ };
1692
+ if (active) {
1693
+ target === null || target === void 0 ? void 0 : target.addEventListener(event, eventListener, options.capture);
1694
+ }
1695
+ return function () {
1696
+ target === null || target === void 0 ? void 0 : target.removeEventListener(event, eventListener, options.capture);
1697
+ };
1698
+ }, tslib.__spreadArray([
1699
+ active,
1700
+ callback,
1701
+ event,
1702
+ target,
1703
+ options.capture,
1704
+ options.defaultPrevented
1705
+ ], tslib.__read(dependencies), false));
1706
+ }
1707
+
1668
1708
  var TIP_HIDE_DELAY = 100;
1669
1709
  // fires a custom "cauldron:tooltip:show" / "cauldron:tooltip:hide" event
1670
1710
  // to allow projects using cauldron to hook into when a tooltip is shown/hidden
@@ -1753,30 +1793,14 @@ function Tooltip(_a) {
1753
1793
  attributes.popper['data-popper-placement']) ||
1754
1794
  initialPlacement;
1755
1795
  // Only listen to key ups when the tooltip is visible
1756
- React.useEffect(function () {
1757
- var handleEscape = function (event) {
1758
- if (event.key === 'Escape' ||
1759
- event.key === 'Esc' ||
1760
- event.keyCode === 27) {
1761
- event.preventDefault();
1762
- setShowTooltip(false);
1763
- }
1764
- };
1765
- var targetElement = document.body;
1766
- if (showTooltip && typeof showProp !== 'boolean') {
1767
- targetElement.addEventListener('keyup', handleEscape, { capture: true });
1768
- }
1769
- else {
1770
- targetElement.removeEventListener('keyup', handleEscape, {
1771
- capture: true
1772
- });
1773
- }
1774
- return function () {
1775
- targetElement.removeEventListener('keyup', handleEscape, {
1776
- capture: true
1777
- });
1778
- };
1779
- }, [showTooltip, showProp]);
1796
+ useEscapeKey({
1797
+ callback: function (event) {
1798
+ event.preventDefault();
1799
+ setShowTooltip(false);
1800
+ },
1801
+ capture: true,
1802
+ active: showTooltip && typeof showProp !== 'boolean'
1803
+ }, [setShowTooltip]);
1780
1804
  // Handle hover and focus events for the targetElement
1781
1805
  React.useEffect(function () {
1782
1806
  if (typeof showProp !== 'boolean') {
@@ -2540,6 +2564,117 @@ var SearchField = React.forwardRef(function (_a, ref) {
2540
2564
  });
2541
2565
  SearchField.displayName = 'SearchField';
2542
2566
 
2567
+ /**
2568
+ * When a component needs to track an internal ref on a component that has a
2569
+ * forwarded ref, useSharedRef will return a MutableRefObject<T> that will
2570
+ * correctly invoke the parent ref as well providing an internal ref.
2571
+ *
2572
+ * @example
2573
+ * React.forwardRef(function Component({ children }, ref) {
2574
+ * const internalRef = useSharedRef<HTMLElement>(ref)
2575
+ * if (internalRef.current) {
2576
+ * // do something with the internal ref...
2577
+ * }
2578
+ * return (<div ref={internalRef}>...</div>)
2579
+ * })
2580
+ */
2581
+ function useSharedRef(ref) {
2582
+ var internalRef = React.useRef();
2583
+ React.useEffect(function () {
2584
+ setRef(ref, internalRef.current);
2585
+ }, [ref]);
2586
+ return internalRef;
2587
+ }
2588
+
2589
+ function copyTextToClipboard(text) {
2590
+ return tslib.__awaiter(this, void 0, void 0, function () {
2591
+ var copied, element, range, selection;
2592
+ return tslib.__generator(this, function (_a) {
2593
+ switch (_a.label) {
2594
+ case 0:
2595
+ copied = false;
2596
+ if (!('clipboard' in navigator)) return [3 /*break*/, 5];
2597
+ _a.label = 1;
2598
+ case 1:
2599
+ _a.trys.push([1, 3, , 4]);
2600
+ return [4 /*yield*/, navigator.clipboard.writeText(text)];
2601
+ case 2:
2602
+ _a.sent();
2603
+ copied = true;
2604
+ return [3 /*break*/, 4];
2605
+ case 3:
2606
+ _a.sent();
2607
+ return [3 /*break*/, 4];
2608
+ case 4: return [3 /*break*/, 6];
2609
+ case 5:
2610
+ element = document.createElement('span');
2611
+ element.textContent = text;
2612
+ element.setAttribute('aria-hidden', 'true');
2613
+ element.style.position = 'absolute';
2614
+ element.style.height = '1px';
2615
+ element.style.width = '1px';
2616
+ element.style.overflow = 'hidden';
2617
+ element.style.clip = 'rect(1px, 1px, 1px, 1px)';
2618
+ element.style.marginTop = '-1px';
2619
+ element.style.webkitUserSelect = 'text';
2620
+ element.style.userSelect = 'text';
2621
+ document.body.appendChild(element);
2622
+ range = document.createRange();
2623
+ selection = document.getSelection();
2624
+ range.selectNodeContents(element);
2625
+ selection === null || selection === void 0 ? void 0 : selection.addRange(range);
2626
+ try {
2627
+ document.execCommand(text);
2628
+ copied = true;
2629
+ }
2630
+ catch (ex) {
2631
+ // no fallback
2632
+ }
2633
+ element.remove();
2634
+ _a.label = 6;
2635
+ case 6: return [2 /*return*/, copied];
2636
+ }
2637
+ });
2638
+ });
2639
+ }
2640
+
2641
+ var NOTIFICATION_TIMEOUT_MS = 2000;
2642
+ var CopyButton = React.forwardRef(function (_a, ref) {
2643
+ var className = _a.className, value = _a.value, _b = _a.variant, variant = _b === void 0 ? 'tertiary' : _b, _c = _a.children, children = _c === void 0 ? 'Copy' : _c, _d = _a.notificationLabel, notificationLabel = _d === void 0 ? 'Copied' : _d, _e = _a.hideVisibleLabel, hideVisibleLabel = _e === void 0 ? false : _e, _f = _a.tooltipPlacement, tooltipPlacement = _f === void 0 ? 'auto' : _f, onCopy = _a.onCopy, props = tslib.__rest(_a, ["className", "value", "variant", "children", "notificationLabel", "hideVisibleLabel", "tooltipPlacement", "onCopy"]);
2644
+ var _g = tslib.__read(React.useState(false), 2), copied = _g[0], setCopied = _g[1];
2645
+ var copyButtonRef = useSharedRef(ref);
2646
+ var handleClick = React.useCallback(function () {
2647
+ copyTextToClipboard(value);
2648
+ setCopied(true);
2649
+ if (typeof onCopy === 'function') {
2650
+ onCopy(value);
2651
+ }
2652
+ }, [value, onCopy]);
2653
+ React.useEffect(function () {
2654
+ var timeoutId = setTimeout(function () {
2655
+ setCopied(false);
2656
+ }, NOTIFICATION_TIMEOUT_MS);
2657
+ return function () {
2658
+ clearTimeout(timeoutId);
2659
+ };
2660
+ }, [copied]);
2661
+ // The visibility of the tooltip only needs to be controlled
2662
+ // when we are visually displaying the notification label
2663
+ var showTooltip = hideVisibleLabel && !copied ? undefined : copied ? true : false;
2664
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
2665
+ React__default["default"].createElement(Button, tslib.__assign({ className: classNames__default["default"](className, {
2666
+ 'Button--condensed': hideVisibleLabel
2667
+ }), ref: copyButtonRef, variant: variant, onClick: handleClick }, props),
2668
+ React__default["default"].createElement(Icon, { type: copied ? 'check-solid' : 'copy' }),
2669
+ hideVisibleLabel ? React__default["default"].createElement(Offscreen, null, children) : children),
2670
+ React__default["default"].createElement(Tooltip, { target: copyButtonRef, placement: tooltipPlacement, association: "none", show: showTooltip }, hideVisibleLabel && !copied ? children : notificationLabel),
2671
+ typeof document !== 'undefined' &&
2672
+ reactDom.createPortal(React__default["default"].createElement(Offscreen, { "aria-live": "polite" }, copied ? notificationLabel : ' '),
2673
+ // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
2674
+ document.body)));
2675
+ });
2676
+ CopyButton.displayName = 'CopyButton';
2677
+
2543
2678
  SyntaxHighlighter__default["default"].registerLanguage('javascript', js__default["default"]);
2544
2679
  SyntaxHighlighter__default["default"].registerLanguage('css', css__default["default"]);
2545
2680
  SyntaxHighlighter__default["default"].registerLanguage('html', xml__default["default"]);
@@ -2547,9 +2682,10 @@ SyntaxHighlighter__default["default"].registerLanguage('yaml', yaml__default["de
2547
2682
  // HACK: This is a workaround for a bug in react-syntax-highlighter's types.
2548
2683
  var Highlighter = SyntaxHighlighter__default["default"];
2549
2684
  var Code = function (_a) {
2550
- var children = _a.children, className = _a.className, _b = _a.scrollable, scrollable = _b === void 0 ? false : _b, props = tslib.__rest(_a, ["children", "className", "scrollable"]);
2685
+ var children = _a.children, className = _a.className, _b = _a.scrollable, scrollable = _b === void 0 ? false : _b, label = _a.label, _c = _a.allowCopy, allowCopy = _c === void 0 ? false : _c, copyButtonProps = _a.copyButtonProps, props = tslib.__rest(_a, ["children", "className", "scrollable", "label", "allowCopy", "copyButtonProps"]);
2551
2686
  var ref = React.useRef(null);
2552
- var _c = tslib.__read(React.useState(false), 2), scrollableRegion = _c[0], setScrollableRegion = _c[1];
2687
+ var _d = tslib.__read(React.useState(false), 2), scrollableRegion = _d[0], setScrollableRegion = _d[1];
2688
+ var _e = tslib.__read(nextId.useId(1, 'code'), 1), id = _e[0];
2553
2689
  // react-syntax-highlighter does not provide direct access to its dom elements
2554
2690
  // via refs, but we can specify the wrapping tags to bypass this limitation
2555
2691
  // see: https://github.com/react-syntax-highlighter/react-syntax-highlighter/issues/335
@@ -2573,9 +2709,13 @@ var Code = function (_a) {
2573
2709
  setScrollableRegion(false);
2574
2710
  };
2575
2711
  }, [scrollable]);
2576
- return (React__default["default"].createElement(Highlighter, tslib.__assign({}, props, { PreTag: PreWithRef, useInlineStyles: false, className: classNames__default["default"]('Code', className, {
2577
- 'Code--scrollable': scrollable
2578
- }), tabIndex: scrollableRegion ? 0 : undefined }), children));
2712
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
2713
+ (label || allowCopy) && (React__default["default"].createElement("div", { className: "Code__Header" },
2714
+ label && React__default["default"].createElement("span", { id: "".concat(id, "-label") }, label),
2715
+ allowCopy && React__default["default"].createElement(CopyButton, tslib.__assign({ value: children }, copyButtonProps)))),
2716
+ React__default["default"].createElement(Highlighter, tslib.__assign({}, props, { PreTag: PreWithRef, useInlineStyles: false, className: classNames__default["default"]('Code', className, {
2717
+ 'Code--scrollable': scrollable
2718
+ }), tabIndex: scrollableRegion ? 0 : undefined }), children)));
2579
2719
  };
2580
2720
  Code.displayName = 'Code';
2581
2721
 
@@ -2585,28 +2725,6 @@ function AxeLoader() {
2585
2725
  React__default["default"].createElement("path", { fill: "currentColor", d: "M379 549.9h-27.6v-16.7c-7.4 13.5-22.8 20.2-39 20.2-37.1 0-58.9-28.9-58.9-61.6 0-36.5 26.4-61.4 58.9-61.4 21.1 0 34 11.2 39 20.5V434H379v115.9zm-97.8-57.4c0 14.3 10.3 35.2 35.2 35.2 15.4 0 25.5-8 30.8-18.6 2.7-5.1 4-10.5 4.4-16.2.2-5.5-.8-11.2-3.2-16.2-4.9-11-15.6-20.5-32.3-20.5-22.4 0-35 18.1-35 36.1v.2zM436.2 488.9l-39-54.8h33.3l22.6 35.6 22.6-35.6h32.9l-38.8 54.8 43.2 61h-34L453.1 510l-26.2 39.9h-33.5l42.8-61z" })));
2586
2726
  }
2587
2727
 
2588
- /**
2589
- * When a component needs to track an internal ref on a component that has a
2590
- * forwarded ref, useSharedRef will return a MutableRefObject<T> that will
2591
- * correctly invoke the parent ref as well providing an internal ref.
2592
- *
2593
- * @example
2594
- * React.forwardRef(function Component({ children }, ref) {
2595
- * const internalRef = useSharedRef<HTMLElement>(ref)
2596
- * if (internalRef.current) {
2597
- * // do something with the internal ref...
2598
- * }
2599
- * return (<div ref={internalRef}>...</div>)
2600
- * })
2601
- */
2602
- function useSharedRef(ref) {
2603
- var internalRef = React.useRef();
2604
- React.useEffect(function () {
2605
- setRef(ref, internalRef.current);
2606
- }, [ref]);
2607
- return internalRef;
2608
- }
2609
-
2610
2728
  var LoaderOverlay = React.forwardRef(function (_a, ref) {
2611
2729
  var className = _a.className, label = _a.label, children = _a.children, focusOnInitialRender = _a.focusOnInitialRender, _b = _a.focusTrap, focusTrap = _b === void 0 ? false : _b, other = tslib.__rest(_a, ["className", "label", "children", "focusOnInitialRender", "focusTrap"]);
2612
2730
  var overlayRef = useSharedRef(ref);
@@ -3198,25 +3316,10 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3198
3316
  mediaQueryList.removeEventListener('change', listener);
3199
3317
  };
3200
3318
  }, []);
3201
- React.useEffect(function () {
3202
- var handleEscape = function (event) {
3203
- if (event.key === 'Escape' ||
3204
- event.key === 'Esc' ||
3205
- event.keyCode === 27) {
3206
- setCollapsed(true);
3207
- }
3208
- };
3209
- var targetElement = document.body;
3210
- if (isFocusTrap) {
3211
- targetElement.addEventListener('keyup', handleEscape);
3212
- }
3213
- else {
3214
- targetElement.removeEventListener('keyup', handleEscape);
3215
- }
3216
- return function () {
3217
- targetElement.removeEventListener('keyup', handleEscape);
3218
- };
3219
- }, [isFocusTrap]);
3319
+ useEscapeKey({
3320
+ callback: function () { return setCollapsed(true); },
3321
+ active: isFocusTrap
3322
+ }, [setCollapsed]);
3220
3323
  var handleClickOutside = function () {
3221
3324
  if (!isCollapsed && isFocusTrap) {
3222
3325
  setCollapsed(true);
@@ -3232,7 +3335,7 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3232
3335
  allowOutsideClick: true,
3233
3336
  fallbackFocus: columnLeftRef.current
3234
3337
  }, containerElements: [columnLeftRef.current] }),
3235
- React__default["default"].createElement(ClickOutsideListener, { onClickOutside: handleClickOutside, target: columnLeftRef.current }),
3338
+ React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside, target: columnLeftRef.current }),
3236
3339
  isCollapsed ? null : skipLink,
3237
3340
  showPanel ? ColumnLeftComponent : null,
3238
3341
  ColumnRightComponent)));
@@ -3264,8 +3367,8 @@ var iconTypeMap = {
3264
3367
  };
3265
3368
  var Notice = React.forwardRef(function (_a, ref) {
3266
3369
  var _b;
3267
- var _c = _a.type, type = _c === void 0 ? 'info' : _c, title = _a.title, icon = _a.icon, _d = _a.variant, variant = _d === void 0 ? 'default' : _d, children = _a.children, otherProps = tslib.__rest(_a, ["type", "title", "icon", "variant", "children"]);
3268
- return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Notice', (_b = {},
3370
+ var className = _a.className, _c = _a.type, type = _c === void 0 ? 'info' : _c, title = _a.title, icon = _a.icon, _d = _a.variant, variant = _d === void 0 ? 'default' : _d, children = _a.children, otherProps = tslib.__rest(_a, ["className", "type", "title", "icon", "variant", "children"]);
3371
+ return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Notice', className, (_b = {},
3269
3372
  _b["Notice--".concat(type)] = type,
3270
3373
  _b["Notice--condensed"] = variant === 'condensed',
3271
3374
  _b)), ref: ref }, otherProps),
@@ -3999,24 +4102,6 @@ var Popover = React.forwardRef(function (_a, ref) {
3999
4102
  }
4000
4103
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute('aria-expanded', Boolean(show).toString());
4001
4104
  }, [show, popoverRef.current]);
4002
- React.useEffect(function () {
4003
- var handleEscape = function (event) {
4004
- if (event.key === 'Escape' ||
4005
- event.key === 'Esc' ||
4006
- event.keyCode === 27) {
4007
- handleClosePopover();
4008
- }
4009
- };
4010
- if (show) {
4011
- document.body.addEventListener('keyup', handleEscape);
4012
- }
4013
- else {
4014
- document.body.removeEventListener('keyup', handleEscape);
4015
- }
4016
- return function () {
4017
- document.body.removeEventListener('keyup', handleEscape);
4018
- };
4019
- }, [show]);
4020
4105
  React.useEffect(function () {
4021
4106
  var attrText = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-controls');
4022
4107
  var hasPopupAttr = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-haspopup');
@@ -4043,13 +4128,17 @@ var Popover = React.forwardRef(function (_a, ref) {
4043
4128
  onClose();
4044
4129
  }
4045
4130
  };
4131
+ useEscapeKey({
4132
+ callback: handleClosePopover,
4133
+ active: show
4134
+ }, [show]);
4046
4135
  if (!show || !isBrowser())
4047
4136
  return null;
4048
4137
  return reactDom.createPortal(React__default["default"].createElement(FocusTrap__default["default"], { focusTrapOptions: {
4049
4138
  allowOutsideClick: true,
4050
4139
  fallbackFocus: '.Popover__borderLeft'
4051
4140
  } },
4052
- React__default["default"].createElement(ClickOutsideListener, { onClickOutside: handleClickOutside },
4141
+ React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside },
4053
4142
  React__default["default"].createElement("div", tslib.__assign({ id: id, className: classNames__default["default"]('Popover', "Popover--".concat(placement), className, {
4054
4143
  'Popover--hidden': !show,
4055
4144
  'Popover--prompt': variant === 'prompt'
@@ -4120,94 +4209,132 @@ var TextEllipsis = React__default["default"].forwardRef(function (_a, ref) {
4120
4209
  });
4121
4210
  TextEllipsis.displayName = 'TextEllipsis';
4122
4211
 
4123
- function copyTextToClipboard(text) {
4124
- return tslib.__awaiter(this, void 0, void 0, function () {
4125
- var copied, element, range, selection;
4126
- return tslib.__generator(this, function (_a) {
4127
- switch (_a.label) {
4128
- case 0:
4129
- copied = false;
4130
- if (!('clipboard' in navigator)) return [3 /*break*/, 5];
4131
- _a.label = 1;
4132
- case 1:
4133
- _a.trys.push([1, 3, , 4]);
4134
- return [4 /*yield*/, navigator.clipboard.writeText(text)];
4135
- case 2:
4136
- _a.sent();
4137
- copied = true;
4138
- return [3 /*break*/, 4];
4139
- case 3:
4140
- _a.sent();
4141
- return [3 /*break*/, 4];
4142
- case 4: return [3 /*break*/, 6];
4143
- case 5:
4144
- element = document.createElement('span');
4145
- element.textContent = text;
4146
- element.setAttribute('aria-hidden', 'true');
4147
- element.style.position = 'absolute';
4148
- element.style.height = '1px';
4149
- element.style.width = '1px';
4150
- element.style.overflow = 'hidden';
4151
- element.style.clip = 'rect(1px, 1px, 1px, 1px)';
4152
- element.style.marginTop = '-1px';
4153
- element.style.webkitUserSelect = 'text';
4154
- element.style.userSelect = 'text';
4155
- document.body.appendChild(element);
4156
- range = document.createRange();
4157
- selection = document.getSelection();
4158
- range.selectNodeContents(element);
4159
- selection === null || selection === void 0 ? void 0 : selection.addRange(range);
4160
- try {
4161
- document.execCommand(text);
4162
- copied = true;
4163
- }
4164
- catch (ex) {
4165
- // no fallback
4166
- }
4167
- element.remove();
4168
- _a.label = 6;
4169
- case 6: return [2 /*return*/, copied];
4170
- }
4171
- });
4172
- });
4173
- }
4174
-
4175
- var NOTIFICATION_TIMEOUT_MS = 2000;
4176
- var CopyButton = React.forwardRef(function (_a, ref) {
4177
- var className = _a.className, value = _a.value, _b = _a.variant, variant = _b === void 0 ? 'tertiary' : _b, _c = _a.children, children = _c === void 0 ? 'Copy' : _c, _d = _a.notificationLabel, notificationLabel = _d === void 0 ? 'Copied' : _d, _e = _a.hideVisibleLabel, hideVisibleLabel = _e === void 0 ? false : _e, _f = _a.tooltipPlacement, tooltipPlacement = _f === void 0 ? 'auto' : _f, onCopy = _a.onCopy, props = tslib.__rest(_a, ["className", "value", "variant", "children", "notificationLabel", "hideVisibleLabel", "tooltipPlacement", "onCopy"]);
4178
- var _g = tslib.__read(React.useState(false), 2), copied = _g[0], setCopied = _g[1];
4179
- var copyButtonRef = useSharedRef(ref);
4180
- var handleClick = React.useCallback(function () {
4181
- copyTextToClipboard(value);
4182
- setCopied(true);
4183
- if (typeof onCopy === 'function') {
4184
- onCopy(value);
4212
+ var Drawer = React.forwardRef(function (_a, ref) {
4213
+ var children = _a.children, className = _a.className, position = _a.position, _b = _a.open, open = _b === void 0 ? false : _b, _c = _a.behavior, behavior = _c === void 0 ? 'modal' : _c, _d = _a.focusOptions, focusOptions = _d === void 0 ? {} : _d, portal = _a.portal, onClose = _a.onClose, style = _a.style, props = tslib.__rest(_a, ["children", "className", "position", "open", "behavior", "focusOptions", "portal", "onClose", "style"]);
4214
+ var drawerRef = useSharedRef(ref);
4215
+ var openRef = React.useRef(!!open);
4216
+ var previousActiveElementRef = React.useRef(null);
4217
+ var focusInitial = focusOptions.initialFocus, focusReturn = focusOptions.returnFocus;
4218
+ var _e = tslib.__read(React.useState(!!open), 2), isTransitioning = _e[0], setIsTransitioning = _e[1];
4219
+ var isModal = behavior === 'modal';
4220
+ var handleClose = React.useCallback(function () {
4221
+ // istanbul ignore next
4222
+ if (open && typeof onClose === 'function') {
4223
+ onClose();
4185
4224
  }
4186
- }, [value, onCopy]);
4225
+ }, [open, onClose]);
4187
4226
  React.useEffect(function () {
4188
- var timeoutId = setTimeout(function () {
4189
- setCopied(false);
4190
- }, NOTIFICATION_TIMEOUT_MS);
4227
+ // jsdom does not trigger transitionend event
4228
+ // istanbul ignore next
4229
+ var transitionEndHandler = function () { return setIsTransitioning(false); };
4230
+ document.addEventListener('transitionend', transitionEndHandler);
4191
4231
  return function () {
4192
- clearTimeout(timeoutId);
4232
+ document.removeEventListener('transitionend', transitionEndHandler);
4193
4233
  };
4194
- }, [copied]);
4195
- // The visibility of the tooltip only needs to be controlled
4196
- // when we are visually displaying the notification label
4197
- var showTooltip = hideVisibleLabel && !copied ? undefined : copied ? true : false;
4198
- return (React__default["default"].createElement(React__default["default"].Fragment, null,
4199
- React__default["default"].createElement(Button, tslib.__assign({ className: classNames__default["default"](className, {
4200
- 'Button--condensed': hideVisibleLabel
4201
- }), ref: copyButtonRef, variant: variant, onClick: handleClick }, props),
4202
- React__default["default"].createElement(Icon, { type: copied ? 'check-solid' : 'copy' }),
4203
- hideVisibleLabel ? React__default["default"].createElement(Offscreen, null, children) : children),
4204
- React__default["default"].createElement(Tooltip, { target: copyButtonRef, placement: tooltipPlacement, association: "none", show: showTooltip }, hideVisibleLabel && !copied ? children : notificationLabel),
4205
- typeof document !== 'undefined' &&
4206
- reactDom.createPortal(React__default["default"].createElement(Offscreen, { "aria-live": "polite" }, copied ? notificationLabel : ' '),
4207
- // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
4208
- document.body)));
4234
+ }, [setIsTransitioning]);
4235
+ React.useEffect(function () {
4236
+ if (openRef.current !== open) {
4237
+ setIsTransitioning(true);
4238
+ }
4239
+ openRef.current = open;
4240
+ }, [open, setIsTransitioning]);
4241
+ React.useEffect(function () {
4242
+ if (!isModal) {
4243
+ return;
4244
+ }
4245
+ var isolator = new AriaIsolate(drawerRef.current);
4246
+ if (open) {
4247
+ isolator.activate();
4248
+ }
4249
+ else {
4250
+ isolator.deactivate();
4251
+ }
4252
+ return function () {
4253
+ isolator.deactivate();
4254
+ };
4255
+ }, [isModal, open]);
4256
+ React.useLayoutEffect(function () {
4257
+ var _a, _b, _c;
4258
+ if (open) {
4259
+ previousActiveElementRef.current =
4260
+ document.activeElement;
4261
+ var initialFocusElement = resolveElement(focusInitial);
4262
+ if (initialFocusElement) {
4263
+ initialFocusElement.focus();
4264
+ }
4265
+ else {
4266
+ var focusable = (_a = drawerRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(focusableSelector);
4267
+ if (focusable) {
4268
+ focusable.focus();
4269
+ }
4270
+ else {
4271
+ // fallback focus
4272
+ (_b = drawerRef.current) === null || _b === void 0 ? void 0 : _b.focus();
4273
+ }
4274
+ }
4275
+ }
4276
+ else if (previousActiveElementRef.current) {
4277
+ var returnFocusElement = resolveElement(focusReturn);
4278
+ if (returnFocusElement) {
4279
+ returnFocusElement.focus();
4280
+ }
4281
+ else {
4282
+ // fallback focus
4283
+ (_c = previousActiveElementRef.current) === null || _c === void 0 ? void 0 : _c.focus();
4284
+ }
4285
+ }
4286
+ }, [open, focusInitial, focusReturn]);
4287
+ useEscapeKey({ callback: handleClose, active: open, defaultPrevented: true }, [onClose]);
4288
+ // istanbul ignore next
4289
+ if (!isBrowser()) {
4290
+ return null;
4291
+ }
4292
+ var portalElement = resolveElement(portal);
4293
+ return reactDom.createPortal(React__default["default"].createElement(React__default["default"].Fragment, null,
4294
+ React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClose, mouseEvent: open ? undefined : false, touchEvent: open ? undefined : false, target: drawerRef },
4295
+ React__default["default"].createElement(FocusTrap__default["default"], { active: !!isModal && !!open, focusTrapOptions: {
4296
+ allowOutsideClick: true,
4297
+ escapeDeactivates: false,
4298
+ clickOutsideDeactivates: false,
4299
+ initialFocus: false,
4300
+ setReturnFocus: false,
4301
+ fallbackFocus: function () { return drawerRef.current; }
4302
+ } },
4303
+ React__default["default"].createElement("div", tslib.__assign({ ref: drawerRef, className: classNames__default["default"](className, 'Drawer', {
4304
+ 'Drawer--open': !!open,
4305
+ 'Drawer--top': position === 'top',
4306
+ 'Drawer--bottom': position === 'bottom',
4307
+ 'Drawer--left': position === 'left',
4308
+ 'Drawer--right': position === 'right'
4309
+ }), "aria-hidden": !open || undefined, style: tslib.__assign({ visibility: !open && !isTransitioning ? 'hidden' : undefined }, style), tabIndex: open ? -1 : undefined }, props), children))),
4310
+ React__default["default"].createElement(Scrim, { show: !!open && !!isModal })), portalElement ||
4311
+ (
4312
+ // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
4313
+ document === null || document === void 0 ? void 0 : document.body));
4209
4314
  });
4210
- CopyButton.displayName = 'CopyButton';
4315
+ Drawer.displayName = 'Drawer';
4316
+
4317
+ var BottomSheet = React.forwardRef(function (_a, ref) {
4318
+ var label = _a.label, children = _a.children, className = _a.className, _b = _a.closeButtonText, closeButtonText = _b === void 0 ? 'Close' : _b, _c = _a.open, open = _c === void 0 ? false : _c, onClose = _a.onClose, focusOptions = _a.focusOptions, props = tslib.__rest(_a, ["label", "children", "className", "closeButtonText", "open", "onClose", "focusOptions"]);
4319
+ var bottomSheetRef = useSharedRef(ref);
4320
+ var _d = tslib.__read(nextId.useId(1, 'bottom-sheet-label'), 1), labelId = _d[0];
4321
+ var handleClose = React.useCallback(function () {
4322
+ // istanbul ignore else
4323
+ if (typeof onClose === 'function') {
4324
+ onClose();
4325
+ }
4326
+ }, [onClose]);
4327
+ return (React__default["default"].createElement(Drawer, tslib.__assign({ open: open, onClose: handleClose, focusOptions: tslib.__assign({ initialFocus: bottomSheetRef }, focusOptions) }, props, { behavior: "modal", position: "bottom" }),
4328
+ React__default["default"].createElement("div", { ref: bottomSheetRef, className: classNames__default["default"]('BottomSheet', className), tabIndex: -1, role: "dialog", "aria-labelledby": labelId },
4329
+ React__default["default"].createElement("div", { className: "BottomSheet__header" },
4330
+ React__default["default"].createElement("div", { id: labelId, className: "BottomSheet__title" }, label),
4331
+ React__default["default"].createElement(IconButton, { icon: "close", label: closeButtonText, "aria-label": "".concat(closeButtonText), onClick: handleClose, tooltipProps: {
4332
+ show: false,
4333
+ association: 'none'
4334
+ } })),
4335
+ React__default["default"].createElement("div", { className: "BottomSheet__contents" }, children))));
4336
+ });
4337
+ BottomSheet.displayName = 'BottomSheet';
4211
4338
 
4212
4339
  var LIGHT_THEME_CLASS = 'cauldron--theme-light';
4213
4340
  var DARK_THEME_CLASS = 'cauldron--theme-dark';
@@ -4288,12 +4415,13 @@ exports.AlertContent = AlertContent;
4288
4415
  exports.AriaIsolate = AriaIsolate;
4289
4416
  exports.Badge = Badge;
4290
4417
  exports.BadgeLabel = BadgeLabel;
4418
+ exports.BottomSheet = BottomSheet;
4291
4419
  exports.Breadcrumb = Breadcrumb;
4292
4420
  exports.BreadcrumbItem = BreadcrumbItem;
4293
4421
  exports.BreadcrumbLink = BreadcrumbLink;
4294
4422
  exports.Button = Button;
4295
4423
  exports.Checkbox = Checkbox;
4296
- exports.ClickOutsideListener = ClickOutsideListener;
4424
+ exports.ClickOutsideListener = ClickOutsideListener$1;
4297
4425
  exports.Code = Code;
4298
4426
  exports.ColumnGroupHeader = ColumnGroupHeader;
4299
4427
  exports.ColumnHeader = ColumnHeader;
@@ -4311,6 +4439,7 @@ exports.DescriptionTerm = DescriptionTerm;
4311
4439
  exports.Dialog = Dialog;
4312
4440
  exports.DialogContent = DialogContent;
4313
4441
  exports.DialogFooter = DialogFooter;
4442
+ exports.Drawer = Drawer;
4314
4443
  exports.ExpandCollapsePanel = ExpandCollapsePanel;
4315
4444
  exports.FieldWrap = FieldWrap;
4316
4445
  exports.Icon = Icon;
@@ -0,0 +1,6 @@
1
+ import type { RefObject, MutableRefObject } from 'react';
2
+ /**
3
+ * When an element can be passed as a value that is either an element or an
4
+ * elementRef, this will resolve the property down to the resulting element
5
+ */
6
+ export default function resolveElement<T extends Element = Element>(elementOrRef: T | RefObject<T> | MutableRefObject<T> | undefined): T | null;
@@ -0,0 +1,17 @@
1
+ import { type DependencyList } from 'react';
2
+ /**
3
+ * When a component needs to implement an escape handler, such as in modal
4
+ * dialogs, useEscapeKey will handle the events and call the provided callback
5
+ * handler when an escape key event has been fired.
6
+ *
7
+ * @example
8
+ * useEscapeKey(() => close())
9
+ */
10
+ export default function useEscapeKey<T extends HTMLElement = HTMLElement>(options: {
11
+ active?: boolean;
12
+ callback: (event: KeyboardEvent) => void;
13
+ event?: 'keydown' | 'keypress' | 'keyup';
14
+ target?: T | React.RefObject<T> | React.MutableRefObject<T>;
15
+ defaultPrevented?: boolean;
16
+ capture?: boolean;
17
+ }, dependencies?: DependencyList): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deque/cauldron-react",
3
- "version": "6.6.1",
3
+ "version": "6.7.0-canary.099092f1",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Fully accessible react components library for Deque Cauldron",
6
6
  "homepage": "https://cauldron.dequelabs.com/",