@fluentui/react-northstar
Version:
A themable React component library.
258 lines (254 loc) • 11.7 kB
JavaScript
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
;