@deque/cauldron-react 5.8.0-canary.55b0441c → 5.8.0-canary.b09c14c1

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.
@@ -0,0 +1,31 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { Placement } from '@popperjs/core';
3
+ import { Cauldron } from '../../types';
4
+ export type PopoverVariant = 'prompt' | 'custom';
5
+ type BaseProps = React.HTMLAttributes<HTMLDivElement> & {
6
+ target: React.RefObject<HTMLElement> | HTMLElement;
7
+ variant?: PopoverVariant;
8
+ show: boolean;
9
+ onClose: () => void;
10
+ placement?: Placement;
11
+ portal?: React.RefObject<HTMLElement> | HTMLElement;
12
+ };
13
+ type CustomProps = BaseProps & {
14
+ variant: 'custom';
15
+ applyButtonText?: string;
16
+ onApply?: () => void;
17
+ closeButtonText?: string;
18
+ infoText?: ReactNode;
19
+ children: ReactNode;
20
+ } & Cauldron.LabelProps;
21
+ type PromptProps = BaseProps & {
22
+ variant: 'prompt';
23
+ applyButtonText?: string;
24
+ onApply: () => void;
25
+ closeButtonText?: string;
26
+ infoText: ReactNode;
27
+ children?: ReactNode;
28
+ };
29
+ export type PopoverProps = PromptProps | CustomProps;
30
+ declare const Popover: React.ForwardRefExoticComponent<PopoverProps & React.RefAttributes<HTMLDivElement>>;
31
+ export default Popover;
package/lib/index.d.ts CHANGED
@@ -53,6 +53,7 @@ export { default as Breadcrumb, BreadcrumbItem, BreadcrumbLink } from './compone
53
53
  export { default as TwoColumnPanel, ColumnHeader, ColumnGroupHeader, ColumnLeft, ColumnRight, ColumnList } from './components/TwoColumnPanel';
54
54
  export { default as Notice } from './components/Notice';
55
55
  export { default as Listbox, ListboxOption, ListboxGroup } from './components/Listbox';
56
+ export { default as Popover } from './components/Popover';
56
57
  /**
57
58
  * Helpers / Utils
58
59
  */
package/lib/index.js CHANGED
@@ -4162,6 +4162,131 @@ var ListboxGroup = React.forwardRef(function (_a, ref) {
4162
4162
  });
4163
4163
  ListboxGroup.displayName = 'ListboxGroup';
4164
4164
 
4165
+ var PromptPopoverContent = function (_a) {
4166
+ var onClose = _a.onClose, _b = _a.applyButtonText, applyButtonText = _b === void 0 ? 'Apply' : _b, onApply = _a.onApply, _c = _a.closeButtonText, closeButtonText = _c === void 0 ? 'Close' : _c, infoText = _a.infoText, infoTextId = _a.infoTextId;
4167
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
4168
+ React__default["default"].createElement("span", { id: infoTextId }, infoText),
4169
+ React__default["default"].createElement(Button, { className: "Popover__apply", onClick: onApply, thin: true }, applyButtonText),
4170
+ React__default["default"].createElement(Button, { className: "Popover__close", variant: "secondary", onClick: onClose, thin: true }, closeButtonText)));
4171
+ };
4172
+ var Popover = React.forwardRef(function (_a, ref) {
4173
+ var propId = _a.id, _b = _a.placement, initialPlacement = _b === void 0 ? 'auto' : _b, children = _a.children, portal = _a.portal, target = _a.target, _c = _a.variant, variant = _c === void 0 ? 'custom' : _c, _d = _a.show, show = _d === void 0 ? false : _d, onClose = _a.onClose, className = _a.className, applyButtonText = _a.applyButtonText, closeButtonText = _a.closeButtonText, infoText = _a.infoText, onApply = _a.onApply, props = tslib.__rest(_a, ["id", "placement", "children", "portal", "target", "variant", "show", "onClose", "className", "applyButtonText", "closeButtonText", "infoText", "onApply"]);
4174
+ var _e = tslib.__read(propId ? [propId] : nextId.useId(1, 'popover'), 1), id = _e[0];
4175
+ var _f = tslib.__read(React.useState(null), 2), targetElement = _f[0], setTargetElement = _f[1];
4176
+ var _g = tslib.__read(React.useState(null), 2), isolator = _g[0], setIsolator = _g[1];
4177
+ var popoverRef = useSharedRef(ref);
4178
+ var _h = tslib.__read(React.useState(null), 2), arrowElement = _h[0], setArrowElement = _h[1];
4179
+ var _j = reactPopper.usePopper(targetElement, popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current, {
4180
+ placement: initialPlacement,
4181
+ modifiers: [
4182
+ { name: 'preventOverflow', options: { padding: 8 } },
4183
+ { name: 'flip' },
4184
+ { name: 'offset', options: { offset: [0, 8] } },
4185
+ { name: 'arrow', options: { padding: 5, element: arrowElement } }
4186
+ ]
4187
+ }), styles = _j.styles, attributes = _j.attributes;
4188
+ var placement = (attributes.popper &&
4189
+ attributes.popper['data-popper-placement']) ||
4190
+ initialPlacement;
4191
+ var additionalProps = variant === 'prompt' ? { 'aria-labelledby': "".concat(id, "-label") } : {};
4192
+ // Keep targetElement in sync with target prop
4193
+ React.useEffect(function () {
4194
+ var targetElement = target && 'current' in target ? target.current : target;
4195
+ setTargetElement(targetElement);
4196
+ }, [target]);
4197
+ React.useEffect(function () {
4198
+ return function () {
4199
+ isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
4200
+ };
4201
+ }, []);
4202
+ React.useEffect(function () {
4203
+ if (!isolator)
4204
+ return;
4205
+ if (show) {
4206
+ isolator.activate();
4207
+ }
4208
+ else {
4209
+ isolator.deactivate();
4210
+ }
4211
+ return function () {
4212
+ isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
4213
+ };
4214
+ }, [show, isolator]);
4215
+ React.useEffect(function () {
4216
+ if (popoverRef.current)
4217
+ attachIsolator();
4218
+ }, [popoverRef.current]);
4219
+ React.useEffect(function () {
4220
+ if (show && popoverRef.current) {
4221
+ // Find the first focusable element inside the container
4222
+ var firstFocusableElement = popoverRef.current.querySelector(focusableSelector);
4223
+ if (firstFocusableElement instanceof HTMLElement) {
4224
+ firstFocusableElement.focus();
4225
+ }
4226
+ }
4227
+ targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute('aria-expanded', Boolean(show).toString());
4228
+ }, [show, popoverRef.current]);
4229
+ React.useEffect(function () {
4230
+ var handleEscape = function (event) {
4231
+ if (event.key === 'Escape' ||
4232
+ event.key === 'Esc' ||
4233
+ event.keyCode === 27) {
4234
+ handleClosePopover();
4235
+ }
4236
+ };
4237
+ if (show) {
4238
+ document.body.addEventListener('keyup', handleEscape);
4239
+ }
4240
+ else {
4241
+ document.body.removeEventListener('keyup', handleEscape);
4242
+ }
4243
+ return function () {
4244
+ document.body.removeEventListener('keyup', handleEscape);
4245
+ };
4246
+ }, [show]);
4247
+ React.useEffect(function () {
4248
+ var attrText = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-controls');
4249
+ var hasPopupAttr = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-haspopup');
4250
+ if (!(attrText === null || attrText === void 0 ? void 0 : attrText.includes(id)) && show) {
4251
+ targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute('aria-controls', id);
4252
+ }
4253
+ if (!hasPopupAttr) {
4254
+ targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute('aria-haspopup', 'true');
4255
+ }
4256
+ }, [targetElement, id, show]);
4257
+ var handleClickOutside = function () {
4258
+ if (show) {
4259
+ handleClosePopover();
4260
+ }
4261
+ };
4262
+ var attachIsolator = function () {
4263
+ if (popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current) {
4264
+ setIsolator(new AriaIsolate(popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current));
4265
+ }
4266
+ };
4267
+ var handleClosePopover = function () {
4268
+ isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
4269
+ if (show) {
4270
+ onClose();
4271
+ }
4272
+ };
4273
+ if (!show || !isBrowser())
4274
+ return null;
4275
+ return reactDom.createPortal(React__default["default"].createElement(FocusTrap__default["default"], { focusTrapOptions: {
4276
+ allowOutsideClick: true,
4277
+ fallbackFocus: '.Popover__borderLeft'
4278
+ } },
4279
+ React__default["default"].createElement(ClickOutsideListener, { onClickOutside: handleClickOutside },
4280
+ React__default["default"].createElement("div", tslib.__assign({ id: id, className: classNames__default["default"]('Popover', "Popover--".concat(placement), className, {
4281
+ 'Popover--hidden': !show,
4282
+ 'Popover--prompt': variant === 'prompt'
4283
+ }), ref: popoverRef, role: "dialog", style: styles.popper }, attributes.popper, props, additionalProps),
4284
+ React__default["default"].createElement("div", { className: "Popover__popoverArrow", ref: setArrowElement, style: styles.arrow }),
4285
+ React__default["default"].createElement("div", { className: "Popover__borderLeft" }),
4286
+ variant === 'prompt' ? (React__default["default"].createElement(PromptPopoverContent, { applyButtonText: applyButtonText, onApply: onApply, closeButtonText: closeButtonText, infoText: infoText || '', onClose: handleClosePopover, infoTextId: "".concat(id, "-label") })) : (children)))), (portal && 'current' in portal ? portal.current : portal) || document.body);
4287
+ });
4288
+ Popover.displayName = 'Popover';
4289
+
4165
4290
  var LIGHT_THEME_CLASS = 'cauldron--theme-light';
4166
4291
  var DARK_THEME_CLASS = 'cauldron--theme-dark';
4167
4292
  var ThemeContext = React.createContext({
@@ -4293,6 +4418,7 @@ exports.PanelContent = PanelContent;
4293
4418
  exports.PanelHeader = PanelHeader;
4294
4419
  exports.PanelTrigger = PanelTrigger$1;
4295
4420
  exports.Pointout = Pointout;
4421
+ exports.Popover = Popover;
4296
4422
  exports.ProgressBar = ProgressBar;
4297
4423
  exports.RadioCardGroup = RadioCardGroup;
4298
4424
  exports.RadioGroup = RadioGroup;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deque/cauldron-react",
3
- "version": "5.8.0-canary.55b0441c",
3
+ "version": "5.8.0-canary.b09c14c1",
4
4
  "description": "Fully accessible react components library for Deque Cauldron",
5
5
  "homepage": "https://cauldron.dequelabs.com/",
6
6
  "publishConfig": {