@deque/cauldron-react 6.24.0 → 6.25.0-canary.bc36343e

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.
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- type ActionMenuTriggerProps = Pick<React.HTMLAttributes<HTMLButtonElement>, 'children' | 'onClick' | 'onKeyDown' | 'aria-expanded' | 'aria-haspopup'> & {
2
+ type ActionMenuTriggerProps = Pick<React.HTMLAttributes<HTMLButtonElement>, 'children' | 'onClick' | 'onKeyDown' | 'aria-expanded' | 'aria-haspopup' | 'aria-controls'> & {
3
3
  ref: React.RefObject<HTMLButtonElement>;
4
4
  };
5
5
  type ActionMenuTriggerFunction = (props: ActionMenuTriggerProps, open: boolean) => React.ReactElement;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ interface DialogContextValue {
3
+ headingId: string;
4
+ headingRef: React.RefObject<HTMLHeadingElement>;
5
+ headingLevel: number;
6
+ onClose: () => void;
7
+ forceAction: boolean;
8
+ closeButtonText: string;
9
+ }
10
+ declare const DialogContext: React.Context<DialogContextValue | null>;
11
+ declare function useDialogContext(): DialogContextValue;
12
+ export { DialogContext, useDialogContext };
13
+ export type { DialogContextValue };
@@ -6,7 +6,7 @@ export interface DialogProps extends React.HTMLAttributes<HTMLDivElement> {
6
6
  dialogRef?: React.Ref<HTMLDivElement>;
7
7
  onClose?: () => void;
8
8
  forceAction?: boolean;
9
- heading: string | React.ReactElement<any> | {
9
+ heading?: string | React.ReactElement<any> | {
10
10
  text: React.ReactElement<any> | string;
11
11
  level: number | undefined;
12
12
  };
@@ -32,4 +32,28 @@ declare const DialogFooter: {
32
32
  ({ children, className, align, ...other }: DialogFooterProps): React.JSX.Element;
33
33
  displayName: string;
34
34
  };
35
- export { Dialog, DialogContent, DialogFooter };
35
+ export type DialogHeaderProps = React.HTMLAttributes<HTMLDivElement> & {
36
+ className?: string;
37
+ };
38
+ declare const DialogHeader: {
39
+ ({ children, className, ...other }: DialogHeaderProps): React.JSX.Element;
40
+ displayName: string;
41
+ };
42
+ export interface DialogHeadingProps extends React.HTMLAttributes<HTMLHeadingElement> {
43
+ children: React.ReactNode;
44
+ className?: string;
45
+ level?: number;
46
+ }
47
+ declare const DialogHeading: {
48
+ ({ children, className, level: levelProp, ...other }: DialogHeadingProps): React.JSX.Element;
49
+ displayName: string;
50
+ };
51
+ export interface DialogCloseButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
52
+ children?: React.ReactNode;
53
+ className?: string;
54
+ }
55
+ declare const DialogCloseButton: {
56
+ ({ children, className, ...other }: DialogCloseButtonProps): React.JSX.Element | null;
57
+ displayName: string;
58
+ };
59
+ export { Dialog, DialogContent, DialogFooter, DialogHeader, DialogHeading, DialogCloseButton };
@@ -4,6 +4,18 @@ interface ModalProps extends Omit<DialogProps, 'forceAction'> {
4
4
  variant?: 'info';
5
5
  }
6
6
  declare const Modal: ({ children, className, variant, ...other }: ModalProps) => React.JSX.Element;
7
+ declare const ModalHeader: {
8
+ ({ children, className, ...other }: import("../Dialog").DialogHeaderProps): React.JSX.Element;
9
+ displayName: string;
10
+ };
11
+ declare const ModalHeading: {
12
+ ({ children, className, level: levelProp, ...other }: import("../Dialog").DialogHeadingProps): React.JSX.Element;
13
+ displayName: string;
14
+ };
15
+ declare const ModalCloseButton: {
16
+ ({ children, className, ...other }: import("../Dialog").DialogCloseButtonProps): React.JSX.Element | null;
17
+ displayName: string;
18
+ };
7
19
  declare const ModalContent: {
8
20
  ({ children, className, align, ...other }: import("../Dialog").DialogContentProps): React.JSX.Element;
9
21
  displayName: string;
@@ -13,4 +25,4 @@ declare const ModalFooter: {
13
25
  displayName: string;
14
26
  };
15
27
  export default Modal;
16
- export { Modal, ModalContent, ModalFooter };
28
+ export { Modal, ModalHeader, ModalHeading, ModalCloseButton, ModalContent, ModalFooter };
package/lib/index.d.ts CHANGED
@@ -14,8 +14,8 @@ export { default as TopBar, TopBarTrigger, TopBarMenu, TopBarItem } from './comp
14
14
  export { default as NavBar, NavItem } from './components/NavBar';
15
15
  export { default as SideBar } from './components/SideBar';
16
16
  export { Alert, AlertContent, AlertActions } from './components/Alert';
17
- export { Dialog, DialogContent, DialogFooter } from './components/Dialog';
18
- export { default as Modal, ModalContent, ModalFooter } from './components/Modal';
17
+ export { Dialog, DialogHeader, DialogHeading, DialogCloseButton, DialogContent, DialogFooter } from './components/Dialog';
18
+ export { default as Modal, ModalCloseButton, ModalHeader, ModalHeading, ModalContent, ModalFooter } from './components/Modal';
19
19
  export { default as SkipLink } from './components/SkipLink';
20
20
  export { default as Button } from './components/Button';
21
21
  export { default as IconButton } from './components/IconButton';
package/lib/index.js CHANGED
@@ -1517,6 +1517,15 @@ function useFocusTrap(target, options) {
1517
1517
  return focusTrap;
1518
1518
  }
1519
1519
 
1520
+ var DialogContext = React.createContext(null);
1521
+ function useDialogContext() {
1522
+ var context = React.useContext(DialogContext);
1523
+ if (!context) {
1524
+ throw new Error('Dialog compound components must be rendered within a Dialog');
1525
+ }
1526
+ return context;
1527
+ }
1528
+
1520
1529
  var isEscape = function (event) {
1521
1530
  return event.key === 'Escape' || event.key === 'Esc' || event.keyCode === 27;
1522
1531
  };
@@ -1526,6 +1535,9 @@ var Dialog = React.forwardRef(function (_a, ref) {
1526
1535
  var _f = tslib.__read(nextId.useId(1, 'dialog-title-'), 1), headingId = _f[0];
1527
1536
  var headingRef = React.useRef(null);
1528
1537
  var isolatorRef = React.useRef();
1538
+ var headingLevel = typeof heading === 'object' && 'level' in heading && heading.level
1539
+ ? heading.level
1540
+ : 2;
1529
1541
  var handleClose = React.useCallback(function () {
1530
1542
  var _a;
1531
1543
  (_a = isolatorRef.current) === null || _a === void 0 ? void 0 : _a.deactivate();
@@ -1577,6 +1589,29 @@ var Dialog = React.forwardRef(function (_a, ref) {
1577
1589
  disabled: !show,
1578
1590
  initialFocusElement: headingRef
1579
1591
  });
1592
+ React.useEffect(function () {
1593
+ if (show && !heading && dialogRef.current) {
1594
+ var hasHeading = dialogRef.current.querySelector('.Dialog__heading');
1595
+ if (process.env.NODE_ENV !== 'production' && !hasHeading) {
1596
+ throw Error('Dialog: No heading provided. When using a custom header, include a DialogHeading component for accessibility.');
1597
+ }
1598
+ }
1599
+ }, [show, heading]);
1600
+ var contextValue = React.useMemo(function () { return ({
1601
+ headingId: headingId,
1602
+ headingRef: headingRef,
1603
+ headingLevel: headingLevel,
1604
+ onClose: handleClose,
1605
+ forceAction: forceAction,
1606
+ closeButtonText: closeButtonText
1607
+ }); }, [
1608
+ headingId,
1609
+ headingRef,
1610
+ headingLevel,
1611
+ handleClose,
1612
+ forceAction,
1613
+ closeButtonText
1614
+ ]);
1580
1615
  if (!show || !isBrowser()) {
1581
1616
  return null;
1582
1617
  }
@@ -1586,23 +1621,18 @@ var Dialog = React.forwardRef(function (_a, ref) {
1586
1621
  : portal
1587
1622
  : // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
1588
1623
  document.body;
1589
- var closeButton = !forceAction ? (React__default["default"].createElement("button", { className: "Dialog__close", type: "button", onClick: handleClose },
1590
- React__default["default"].createElement(Icon, { type: "close", "aria-hidden": "true" }),
1591
- React__default["default"].createElement(Offscreen, null, closeButtonText))) : null;
1592
- var HeadingLevel = "h".concat(typeof heading === 'object' && 'level' in heading && heading.level
1593
- ? heading.level
1594
- : 2);
1595
1624
  var dialog = (React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside },
1596
1625
  React__default["default"].createElement("div", tslib.__assign({ role: "dialog", className: classNames__default["default"]('Dialog', className, {
1597
1626
  'Dialog--show': show
1598
1627
  }), ref: dialogRef, "aria-labelledby": headingId }, other),
1599
- React__default["default"].createElement("div", { className: "Dialog__inner" },
1600
- React__default["default"].createElement("div", { className: "Dialog__header" },
1601
- React__default["default"].createElement(HeadingLevel, { className: "Dialog__heading", ref: headingRef, tabIndex: -1, id: headingId }, typeof heading === 'object' && 'text' in heading
1602
- ? heading.text
1603
- : heading),
1604
- closeButton),
1605
- children))));
1628
+ React__default["default"].createElement(DialogContext.Provider, { value: contextValue },
1629
+ React__default["default"].createElement("div", { className: "Dialog__inner" },
1630
+ heading ? (React__default["default"].createElement(DialogHeader, null,
1631
+ React__default["default"].createElement(DialogHeading, null, typeof heading === 'object' && 'text' in heading
1632
+ ? heading.text
1633
+ : heading),
1634
+ React__default["default"].createElement(DialogCloseButton, null))) : null,
1635
+ children)))));
1606
1636
  return reactDom.createPortal(dialog,
1607
1637
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
1608
1638
  portalElement || document.body);
@@ -1626,6 +1656,30 @@ var DialogFooter = function (_a) {
1626
1656
  }) }, other), children));
1627
1657
  };
1628
1658
  DialogFooter.displayName = 'DialogFooter';
1659
+ var DialogHeader = function (_a) {
1660
+ var children = _a.children, className = _a.className, other = tslib.__rest(_a, ["children", "className"]);
1661
+ return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Dialog__header', className) }, other), children));
1662
+ };
1663
+ DialogHeader.displayName = 'DialogHeader';
1664
+ var DialogHeading = function (_a) {
1665
+ var children = _a.children, className = _a.className, levelProp = _a.level, other = tslib.__rest(_a, ["children", "className", "level"]);
1666
+ var _b = useDialogContext(), headingId = _b.headingId, headingRef = _b.headingRef, headingLevel = _b.headingLevel;
1667
+ var HeadingLevel = "h".concat(levelProp !== null && levelProp !== void 0 ? levelProp : headingLevel);
1668
+ return (React__default["default"].createElement(HeadingLevel, tslib.__assign({ className: classNames__default["default"]('Dialog__heading', className), ref: headingRef, tabIndex: -1, id: headingId }, other), children));
1669
+ };
1670
+ DialogHeading.displayName = 'DialogHeading';
1671
+ var DialogCloseButton = function (_a) {
1672
+ var children = _a.children, className = _a.className, other = tslib.__rest(_a, ["children", "className"]);
1673
+ var _b = useDialogContext(), onClose = _b.onClose, forceAction = _b.forceAction, closeButtonText = _b.closeButtonText;
1674
+ if (forceAction && process.env.NODE_ENV !== 'production') {
1675
+ console.warn('DialogCloseButton: Component will not render because forceAction is true. Remove DialogCloseButton from your custom header when using forceAction.');
1676
+ return null;
1677
+ }
1678
+ return (React__default["default"].createElement("button", tslib.__assign({ className: classNames__default["default"]('Dialog__close', className), type: "button", onClick: onClose }, other), children !== null && children !== void 0 ? children : (React__default["default"].createElement(React__default["default"].Fragment, null,
1679
+ React__default["default"].createElement(Icon, { type: "close", "aria-hidden": "true" }),
1680
+ React__default["default"].createElement(Offscreen, null, closeButtonText)))));
1681
+ };
1682
+ DialogCloseButton.displayName = 'DialogCloseButton';
1629
1683
 
1630
1684
  var Alert = function (_a) {
1631
1685
  var children = _a.children, className = _a.className, _b = _a.variant, variant = _b === void 0 ? 'default' : _b, heading = _a.heading, other = tslib.__rest(_a, ["children", "className", "variant", "heading"]);
@@ -1649,6 +1703,9 @@ var Modal = function (_a) {
1649
1703
  'Modal--info': variant === 'info'
1650
1704
  }) }, other, { forceAction: false }), children));
1651
1705
  };
1706
+ var ModalHeader = DialogHeader;
1707
+ var ModalHeading = DialogHeading;
1708
+ var ModalCloseButton = DialogCloseButton;
1652
1709
  var ModalContent = DialogContent;
1653
1710
  var ModalFooter = DialogFooter;
1654
1711
 
@@ -5260,6 +5317,7 @@ var ActionMenu = React.forwardRef(function (_a, ref) {
5260
5317
  var actionMenuRef = useSharedRef(ref);
5261
5318
  var actionMenuListRef = useSharedRef(actionMenuList.props.ref);
5262
5319
  var _f = tslib.__read(nextId.useId(1, 'menu-trigger'), 1), triggerId = _f[0];
5320
+ var _g = tslib.__read(nextId.useId(1, 'menu'), 1), menuId = _g[0];
5263
5321
  var handleTriggerClick = React.useCallback(function (event) {
5264
5322
  // istanbul ignore else
5265
5323
  if (!event.defaultPrevented) {
@@ -5293,6 +5351,9 @@ var ActionMenu = React.forwardRef(function (_a, ref) {
5293
5351
  setOpen(false);
5294
5352
  }
5295
5353
  }, []);
5354
+ var handleOverlayBlur = React.useCallback(function () {
5355
+ setOpen(false);
5356
+ }, []);
5296
5357
  var handleAction = React.useCallback(function (key, event) {
5297
5358
  // istanbul ignore else
5298
5359
  if (!event.defaultPrevented) {
@@ -5312,13 +5373,16 @@ var ActionMenu = React.forwardRef(function (_a, ref) {
5312
5373
  (_c = triggerRef.current) === null || _c === void 0 ? void 0 : _c.focus();
5313
5374
  }
5314
5375
  }, [open]);
5315
- var overlay = (React__default["default"].createElement(AnchoredOverlay, tslib.__assign({ ref: actionMenuRef, role: "presentation", className: classNames__default["default"]('ActionMenu', className), open: open, onOpenChange: setOpen, target: triggerRef, placement: placement, offset: 4, portal: portal, style: tslib.__assign({ display: !open ? 'none' : undefined }, style) }, props), React__default["default"].cloneElement(actionMenuList, {
5376
+ var hidden = renderInTrigger && !open;
5377
+ var overlay = (React__default["default"].createElement(AnchoredOverlay, tslib.__assign({ ref: actionMenuRef, role: "presentation", className: classNames__default["default"]('ActionMenu', className), open: open, onOpenChange: setOpen, target: triggerRef, placement: placement, offset: 4, portal: portal, style: tslib.__assign({ display: !open ? 'none' : undefined }, style), "aria-hidden": hidden, onBlur: handleOverlayBlur }, props), React__default["default"].cloneElement(actionMenuList, {
5316
5378
  ref: actionMenuListRef,
5379
+ id: menuId,
5317
5380
  role: 'menu',
5318
5381
  onAction: handleAction,
5319
5382
  'aria-labelledby': triggerId,
5320
5383
  focusStrategy: focusStrategy,
5321
- focusDisabledOptions: true
5384
+ focusDisabledOptions: true,
5385
+ hidden: hidden
5322
5386
  })));
5323
5387
  var triggerProps = React.useMemo(function () {
5324
5388
  return {
@@ -5327,9 +5391,10 @@ var ActionMenu = React.forwardRef(function (_a, ref) {
5327
5391
  onClick: handleTriggerClick,
5328
5392
  onKeyDown: handleTriggerKeyDown,
5329
5393
  'aria-expanded': open,
5330
- 'aria-haspopup': 'menu'
5394
+ 'aria-haspopup': 'menu',
5395
+ 'aria-controls': menuId
5331
5396
  };
5332
- }, [handleTriggerClick, open]);
5397
+ }, [handleTriggerClick, open, menuId]);
5333
5398
  if (renderInTrigger) {
5334
5399
  // istanbul ignore next
5335
5400
  if (portal && process.env.NODE_ENV !== 'production') {
@@ -5458,8 +5523,11 @@ exports.DescriptionList = DescriptionList;
5458
5523
  exports.DescriptionListItem = DescriptionListItem;
5459
5524
  exports.DescriptionTerm = DescriptionTerm;
5460
5525
  exports.Dialog = Dialog;
5526
+ exports.DialogCloseButton = DialogCloseButton;
5461
5527
  exports.DialogContent = DialogContent;
5462
5528
  exports.DialogFooter = DialogFooter;
5529
+ exports.DialogHeader = DialogHeader;
5530
+ exports.DialogHeading = DialogHeading;
5463
5531
  exports.Drawer = Drawer;
5464
5532
  exports.EmptyState = EmptyState;
5465
5533
  exports.ExpandCollapsePanel = ExpandCollapsePanel;
@@ -5480,8 +5548,11 @@ exports.Main = Main;
5480
5548
  exports.MenuBar = TopBar$1;
5481
5549
  exports.MenuItem = MenuItem;
5482
5550
  exports.Modal = Modal;
5551
+ exports.ModalCloseButton = ModalCloseButton;
5483
5552
  exports.ModalContent = ModalContent;
5484
5553
  exports.ModalFooter = ModalFooter;
5554
+ exports.ModalHeader = ModalHeader;
5555
+ exports.ModalHeading = ModalHeading;
5485
5556
  exports.NavBar = NavBar;
5486
5557
  exports.NavItem = NavItem;
5487
5558
  exports.Notice = Notice;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deque/cauldron-react",
3
- "version": "6.24.0",
3
+ "version": "6.25.0-canary.bc36343e",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Fully accessible react components library for Deque Cauldron",
6
6
  "homepage": "https://cauldron.dequelabs.com/",