UNPKG

@fluentui/react-northstar

Version:
258 lines (254 loc) 11.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.accordionSlotClassNames = exports.accordionClassName = exports.Accordion = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _each2 = _interopRequireDefault(require("lodash/each")); var _invoke2 = _interopRequireDefault(require("lodash/invoke")); var _without2 = _interopRequireDefault(require("lodash/without")); var _includes2 = _interopRequireDefault(require("lodash/includes")); var _uniqueId2 = _interopRequireDefault(require("lodash/uniqueId")); var _accessibility = require("@fluentui/accessibility"); var customPropTypes = _interopRequireWildcard(require("@fluentui/react-proptypes")); var PropTypes = _interopRequireWildcard(require("prop-types")); var React = _interopRequireWildcard(require("react")); var _utils = require("../../utils"); var _AccordionTitle = require("./AccordionTitle"); var _AccordionContent = require("./AccordionContent"); var _FocusContainer = require("../../utils/accessibility/FocusHandling/FocusContainer"); var _reactBindings = require("@fluentui/react-bindings"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } var accordionClassName = 'ui-accordion'; exports.accordionClassName = accordionClassName; var accordionSlotClassNames = { content: accordionClassName + "__content", title: accordionClassName + "__title" }; /** * An Accordion represents stacked set of content sections, with action elements to toggle the display of these sections. * * @accessibility * Implements [ARIA Accordion](https://www.w3.org/TR/wai-aria-practices-1.1/#accordion) design pattern (keyboard navigation not yet supported). */ exports.accordionSlotClassNames = accordionSlotClassNames; var Accordion = /*#__PURE__*/React.forwardRef(function (props, ref) { var context = (0, _reactBindings.useFluentContext)(); var _useTelemetry = (0, _reactBindings.useTelemetry)(Accordion.displayName, context.telemetry), setStart = _useTelemetry.setStart, setEnd = _useTelemetry.setEnd; setStart(); var expanded = props.expanded, exclusive = props.exclusive, accessibility = props.accessibility, children = props.children, className = props.className, design = props.design, styles = props.styles, variables = props.variables, panels = props.panels, renderPanelContent = props.renderPanelContent, renderPanelTitle = props.renderPanelTitle, alwaysRenderPanels = props.alwaysRenderPanels; var alwaysActiveIndex = expanded ? 0 : -1; var _useAutoControlled = (0, _reactBindings.useAutoControlled)({ defaultValue: props.defaultActiveIndex, value: props.activeIndex, initialValue: exclusive ? alwaysActiveIndex : [alwaysActiveIndex] }), activeIndex = _useAutoControlled[0], setActiveIndex = _useAutoControlled[1]; var actionHandlers = { moveNext: function moveNext(e) { e.preventDefault(); focusHandler.moveNext(); }, movePrevious: function movePrevious(e) { e.preventDefault(); focusHandler.movePrevious(); }, moveFirst: function moveFirst(e) { e.preventDefault(); focusHandler.moveFirst(); }, moveLast: function moveLast(e) { e.preventDefault(); focusHandler.moveLast(); } }; var getA11yProps = (0, _reactBindings.useAccessibility)(accessibility, { debugName: Accordion.displayName, actionHandlers: actionHandlers, rtl: context.rtl }); var _useStyles = (0, _reactBindings.useStyles)(Accordion.displayName, { className: accordionClassName, mapPropsToInlineStyles: function mapPropsToInlineStyles() { return { className: className, design: design, styles: styles, variables: variables }; }, rtl: context.rtl }), classes = _useStyles.classes; var _React$useState = React.useState(), focusedIndex = _React$useState[0], setfocusedIndex = _React$useState[1]; var handleNavigationFocus = function handleNavigationFocus(index) { setfocusedIndex(index); }; var getNavigationItemsSize = function getNavigationItemsSize() { return props.panels.length; }; var unhandledProps = (0, _reactBindings.useUnhandledProps)(Accordion.handledProps, props); var ElementType = (0, _reactBindings.getElementType)(props); var focusHandler = new _FocusContainer.ContainerFocusHandler(getNavigationItemsSize, handleNavigationFocus, true); var itemRefs = React.useMemo(function () { return Array.from({ length: panels == null ? void 0 : panels.length }, function () { return /*#__PURE__*/React.createRef(); }); }, // As we are using "panels.length" it's fine to have dependency on them // eslint-disable-next-line react-hooks/exhaustive-deps [panels == null ? void 0 : panels.length]); React.useEffect(function () { var targetComponent = itemRefs[focusedIndex] && itemRefs[focusedIndex].current; targetComponent && targetComponent.focus(); }, [itemRefs, focusedIndex]); var defaultAccordionTitleId = React.useMemo(function () { return (0, _uniqueId2.default)('accordion-title-'); }, []); var defaultAccordionContentId = React.useMemo(function () { return (0, _uniqueId2.default)('accordion-content-'); }, []); var computeNewIndex = function computeNewIndex(index) { if (!isIndexActionable(index)) { return activeIndex; } if (exclusive) return index === activeIndex ? -1 : index; // check to see if index is in array, and remove it, if not then add it return (0, _includes2.default)(activeIndex, index) ? (0, _without2.default)(activeIndex, index) : [].concat(activeIndex, [index]); }; var handleTitleOverrides = function handleTitleOverrides(predefinedProps) { return { onClick: function onClick(e, titleProps) { var index = titleProps.index; var activeIndex = computeNewIndex(index); setActiveIndex(activeIndex); setfocusedIndex(index); (0, _invoke2.default)(props, 'onActiveIndexChange', e, Object.assign({}, props, { activeIndex: activeIndex })); (0, _invoke2.default)(predefinedProps, 'onClick', e, titleProps); (0, _invoke2.default)(props, 'onTitleClick', e, titleProps); }, onFocus: function onFocus(e, titleProps) { (0, _invoke2.default)(predefinedProps, 'onFocus', e, titleProps); setfocusedIndex(predefinedProps.index); } }; }; var isIndexActive = function isIndexActive(index) { return exclusive ? activeIndex === index : (0, _includes2.default)(activeIndex, index); }; /** * Checks if panel at index can be actioned upon. Used in the case of expanded accordion, * when at least a panel needs to stay active. Will return false if expanded prop is true, * index is active and either it's an exclusive accordion or if there are no other active * panels open besides this one. * * @param index - The index of the panel. * @returns If the panel can be set active/inactive. */ var isIndexActionable = function isIndexActionable(index) { if (!isIndexActive(index)) { return true; } return !expanded || !exclusive && activeIndex.length > 1; }; var renderPanels = function renderPanels() { var children = []; focusHandler.syncFocusedIndex(focusedIndex); (0, _each2.default)(panels, function (panel, index) { var content = panel.content, title = panel.title; var active = isIndexActive(+index); var canBeCollapsed = isIndexActionable(+index); var titleId = title['id'] || "" + defaultAccordionTitleId + index; var contentId = content['id'] || "" + defaultAccordionContentId + index; var contentRef = itemRefs[index]; children.push((0, _utils.createShorthand)(_AccordionTitle.AccordionTitle, title, { defaultProps: function defaultProps() { return { className: accordionSlotClassNames.title, active: active, index: +index, contentRef: contentRef, canBeCollapsed: canBeCollapsed, id: titleId, accordionContentId: contentId }; }, overrideProps: handleTitleOverrides, render: renderPanelTitle })); if (alwaysRenderPanels || active) { children.push((0, _utils.createShorthand)(_AccordionContent.AccordionContent, content, { defaultProps: function defaultProps() { return { className: accordionSlotClassNames.content, active: active, id: contentId, accordionTitleId: titleId }; }, render: renderPanelContent })); } }); return children; }; var element = /*#__PURE__*/React.createElement(ElementType, (0, _extends2.default)({}, getA11yProps('root', Object.assign({ className: classes.root }, unhandledProps, { ref: ref })), _utils.rtlTextContainer.getAttributes({ forElements: [children] })), (0, _utils.childrenExist)(children) ? children : renderPanels()); setEnd(); return element; }); exports.Accordion = Accordion; Accordion.displayName = 'Accordion'; Accordion.propTypes = Object.assign({}, _utils.commonPropTypes.createCommon({ content: false }), { activeIndex: customPropTypes.every([customPropTypes.disallow(['children']), PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number])]), defaultActiveIndex: customPropTypes.every([customPropTypes.disallow(['children']), PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number])]), exclusive: PropTypes.bool, expanded: PropTypes.bool, onTitleClick: customPropTypes.every([customPropTypes.disallow(['children']), PropTypes.func]), onActiveIndexChange: PropTypes.func, panels: customPropTypes.every([customPropTypes.disallow(['children']), PropTypes.arrayOf(PropTypes.shape({ content: customPropTypes.itemShorthand, title: customPropTypes.itemShorthand }))]), renderPanelTitle: PropTypes.func, renderPanelContent: PropTypes.func }); Accordion.defaultProps = { accessibility: _accessibility.accordionBehavior, as: 'dl' }; Accordion.handledProps = Object.keys(Accordion.propTypes); Accordion.Title = _AccordionTitle.AccordionTitle; Accordion.Content = _AccordionContent.AccordionContent; Accordion.create = (0, _utils.createShorthandFactory)({ Component: Accordion }); //# sourceMappingURL=Accordion.js.map