@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
215 lines (214 loc) • 6.9 kB
JavaScript
"use client";
import _extends from "@babel/runtime-corejs3/helpers/esm/extends";
var _Fragment;
import React, { useCallback, useContext, useEffect, useRef } from 'react';
import classnames from 'classnames';
import HelpButtonInstance from "./HelpButtonInstance.js";
import HeightAnimation from "../HeightAnimation.js";
import { useSharedState } from "../../shared/helpers/useSharedState.js";
import { convertJsxToString } from "../../shared/component-helper.js";
import useId from "../../shared/helpers/useId.js";
import Section from "../Section.js";
import { P } from "../../elements/index.js";
import Flex from "../Flex.js";
import CardContext from "../card/CardContext.js";
import Dialog from "../Dialog.js";
import { question as QuestionIcon, close as CloseIcon } from "../../icons/index.js";
export default function HelpButtonInline(props) {
var _help$open;
const {
contentId,
size,
help,
focusWhenOpen,
className,
children,
...rest
} = props;
const controlId = useId(contentId);
const {
data,
update
} = useSharedState(controlId, {
isOpen: (_help$open = help === null || help === void 0 ? void 0 : help.open) !== null && _help$open !== void 0 ? _help$open : false
});
const {
isOpen,
isUserIntent
} = data || {};
const wasOpenRef = useRef(undefined);
const buttonRef = useRef(null);
const toggleOpen = useCallback(() => {
update({
isOpen: !isOpen,
isUserIntent: !isOpen,
buttonRef,
focusWhenOpen
});
wasOpenRef.current = !isOpen;
}, [focusWhenOpen, isOpen, update]);
const onClickHandler = useCallback(({
event
}) => {
event.preventDefault();
toggleOpen();
}, [toggleOpen]);
const onKeyDownHandler = useCallback(event => {
if (event.currentTarget === event.target) {
switch (event.key.trim() || event.code) {
case 'Escape':
if (isOpen) {
event.preventDefault();
event.stopPropagation();
window.requestAnimationFrame(() => {
toggleOpen();
});
}
break;
}
}
}, [isOpen, toggleOpen]);
const title = convertJsxToString(help === null || help === void 0 ? void 0 : help.title);
return React.createElement(React.Fragment, null, React.createElement(HelpButtonInstance, _extends({
bounding: true,
size: size !== null && size !== void 0 ? size : 'small',
icon: HelpButtonIcon,
title: !isOpen && !wasOpenRef.current ? title : undefined
}, rest, {
id: controlId,
className: classnames('dnb-help-button__inline', className, isOpen && 'dnb-help-button__inline--open', isUserIntent && 'dnb-help-button__inline--user-intent', typeof wasOpenRef.current === 'boolean' && 'dnb-help-button__inline--was-open'),
"aria-controls": `${controlId}-content`,
"aria-expanded": isOpen,
"aria-label": title,
on_click: onClickHandler,
onKeyDown: onKeyDownHandler,
innerRef: buttonRef
})), !contentId && React.createElement(HelpButtonInlineContent, {
contentId: controlId,
help: help,
focusWhenOpen: focusWhenOpen
}, children));
}
export function HelpButtonInlineContent(props) {
var _ref;
const {
contentId,
className,
element,
children,
help: helpProp,
breakout = true,
outset = true,
roundedCorner,
focusWhenOpen: focusWhenOpenProp,
...rest
} = props;
const {
data,
update
} = useSharedState(contentId);
const {
isOpen,
focusWhenOpen = focusWhenOpenProp,
isUserIntent,
buttonRef
} = data || {};
const {
open,
title,
content,
renderAs,
noAnimation,
breakout: breakoutProp = true,
outset: outsetProp = true
} = helpProp || {};
const innerRef = useRef(null);
const cardContext = useContext(CardContext);
const breakoutFromLayout = Boolean(cardContext) && breakout && breakoutProp;
const outsetFromLayout = outset && outsetProp;
useEffect(() => {
if (isOpen && isUserIntent && focusWhenOpen) {
window.requestAnimationFrame(() => {
var _innerRef$current;
(_innerRef$current = innerRef.current) === null || _innerRef$current === void 0 || _innerRef$current.focus({
preventScroll: true
});
});
}
}, [focusWhenOpen, isOpen, isUserIntent]);
const onClose = useCallback(() => {
update({
isOpen: false,
isUserIntent: false
});
}, [update]);
const onKeyDown = useCallback(event => {
if (event.currentTarget === event.target) {
switch (event.key.trim() || event.code) {
case 'Enter':
case 'Space':
case 'Escape':
event.preventDefault();
event.stopPropagation();
window.requestAnimationFrame(() => {
var _buttonRef$current;
onClose();
buttonRef === null || buttonRef === void 0 || (_buttonRef$current = buttonRef.current) === null || _buttonRef$current === void 0 || _buttonRef$current.focus({
preventScroll: true
});
});
break;
}
}
}, [buttonRef, onClose]);
if (renderAs === 'dialog') {
return React.createElement(Dialog, {
title: title,
omitTriggerButton: true,
openState: isOpen !== null && isOpen !== void 0 ? isOpen : open,
onClose: onClose,
noAnimation: noAnimation
}, content, children);
}
const focusParams = focusWhenOpen ? {
'aria-label': convertJsxToString(title),
className: 'dnb-no-focus',
tabIndex: -1,
onKeyDown
} : {
'aria-live': 'polite',
'aria-atomic': 'true'
};
return React.createElement(HeightAnimation, {
element: element,
className: classnames('dnb-help-button__content', className),
open: (_ref = isOpen !== null && isOpen !== void 0 ? isOpen : open) !== null && _ref !== void 0 ? _ref : false
}, React.createElement(Section, _extends({
id: `${contentId}-content`
}, focusParams, {
innerRef: innerRef,
outset: outsetFromLayout,
breakout: breakoutFromLayout,
roundedCorner: roundedCorner !== null && roundedCorner !== void 0 ? roundedCorner : !breakoutFromLayout,
innerSpace: breakoutFromLayout ? {
top: 'small',
bottom: 'medium'
} : {
top: 'small',
bottom: 'medium',
left: 'medium',
right: 'x-small'
},
backgroundColor: "lavender"
}, rest), React.createElement(Flex.Vertical, {
gap: "x-small"
}, title && React.createElement(P, {
weight: "medium"
}, title), content && React.createElement(P, null, content)), children));
}
function HelpButtonIcon() {
return _Fragment || (_Fragment = React.createElement(React.Fragment, null, React.createElement(QuestionIcon, null), React.createElement(CloseIcon, null)));
}
HelpButtonInline._supportsSpacingProps = true;
HelpButtonInlineContent._supportsSpacingProps = true;
//# sourceMappingURL=HelpButtonInline.js.map