UNPKG

polaris-glints

Version:

Glints forked polaris react

451 lines (419 loc) 18.1 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var polarisIcons = require('@shopify/polaris-icons'); var css = require('../../utilities/css.js'); var focus = require('../../utilities/focus.js'); var withinFilterContext = require('../../utilities/within-filter-context.js'); var types = require('../../types.js'); var Filters$1 = require('./Filters.scss.js'); var context = require('../../utilities/resource-list/context.js'); var Collapsible = require('../Collapsible/Collapsible.js'); var ConnectedFilterControl = require('./components/ConnectedFilterControl/ConnectedFilterControl.js'); var TagsWrapper = require('./components/TagsWrapper/TagsWrapper.js'); var Tag = require('../Tag/Tag.js'); var Sheet = require('../Sheet/Sheet.js'); var hooks = require('../../utilities/i18n/hooks.js'); var hooks$1 = require('../../utilities/media-query/hooks.js'); var ScrollLock = require('../ScrollLock/ScrollLock.js'); var Badge = require('../Badge/Badge.js'); var Text = require('../Text/Text.js'); var Icon = require('../Icon/Icon.js'); var Focus = require('../Focus/Focus.js'); var Button = require('../Button/Button.js'); var TextField = require('../TextField/TextField.js'); var Scrollable = require('../Scrollable/Scrollable.js'); var KeypressListener = require('../KeypressListener/KeypressListener.js'); var Stack = require('../Stack/Stack.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var Suffix; (function (Suffix) { Suffix["Filter"] = "Filter"; Suffix["Shortcut"] = "Shortcut"; })(Suffix || (Suffix = {})); class FiltersInner extends React.Component { constructor(...args) { super(...args); this.context = void 0; this.state = { open: false, readyForFocus: false }; this.moreFiltersButtonContainer = /*#__PURE__*/React.createRef(); this.moreFiltersDoneButtonContainer = /*#__PURE__*/React.createRef(); this.focusNode = /*#__PURE__*/React.createRef(); this.closeFilters = () => { this.setState({ open: false }, () => { if (this.moreFiltersButtonContainer.current) { focus.focusFirstFocusableNode(this.moreFiltersButtonContainer.current, false); } }); }; this.toggleFilters = () => { if (this.state.open === true) { this.closeFilters(); } else { this.openFilters(); } }; this.setReadyForFocus = newState => () => { this.setState({ readyForFocus: newState }); }; this.handleClearAll = () => { this.props.onClearAll(); this.moreFiltersDoneButtonContainer.current && focus.focusFirstFocusableNode(this.moreFiltersDoneButtonContainer.current, false); }; } render() { const { filters, queryValue, onQueryBlur, onQueryChange, onQueryFocus, focused, onClearAll, appliedFilters, onQueryClear, queryPlaceholder, children, disabled = false, helpText, hideTags, hideQueryField, disableQueryField = false, i18n, mediaQuery: { isNavigationCollapsed } } = this.props; const { resourceName } = this.context; const { open, readyForFocus } = this.state; const backdropMarkup = open ? /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(ScrollLock.ScrollLock, null), /*#__PURE__*/React__default["default"].createElement("div", { className: Filters$1["default"].Backdrop, onClick: this.closeFilters })) : null; const filtersContentMarkup = filters.map((filter, index) => { const filterIsOpen = this.state[`${filter.key}${Suffix.Filter}`] === true; const icon = filterIsOpen ? polarisIcons.ChevronUpMinor : polarisIcons.ChevronDownMinor; const className = css.classNames(Filters$1["default"].FilterTriggerContainer, filterIsOpen && Filters$1["default"].open, index === 0 && Filters$1["default"].first, filters.length !== 1 && index === filters.length - 1 && Filters$1["default"].last); const appliedFilterContent = this.getAppliedFilterContent(filter.key); const appliedFilterBadgeMarkup = appliedFilterContent ? /*#__PURE__*/React__default["default"].createElement("div", { className: Filters$1["default"].AppliedFilterBadgeContainer }, /*#__PURE__*/React__default["default"].createElement(Badge.Badge, { status: "new" }, appliedFilterContent)) : null; const collapsibleID = `${filter.key}Collapsible`; const buttonClassName = css.classNames(Filters$1["default"].FilterTrigger); return /*#__PURE__*/React__default["default"].createElement("div", { key: filter.key, className: className }, /*#__PURE__*/React__default["default"].createElement("button", { onClick: () => this.toggleFilter(filter.key), className: buttonClassName, id: `${filter.key}ToggleButton`, type: "button", "aria-controls": collapsibleID, "aria-expanded": filterIsOpen }, /*#__PURE__*/React__default["default"].createElement("div", { className: Filters$1["default"].FilterTriggerLabelContainer }, /*#__PURE__*/React__default["default"].createElement("h3", { className: Filters$1["default"].FilterTriggerTitle }, /*#__PURE__*/React__default["default"].createElement(Text.Text, { variant: "bodyMd", as: "span", color: this.props.disabled || filter.disabled ? 'subdued' : undefined }, filter.label)), /*#__PURE__*/React__default["default"].createElement("span", { className: Filters$1["default"].FilterTriggerIcon }, /*#__PURE__*/React__default["default"].createElement(Icon.Icon, { source: icon, color: "base" }))), appliedFilterBadgeMarkup), /*#__PURE__*/React__default["default"].createElement(Collapsible.Collapsible, { id: collapsibleID, open: filterIsOpen, onAnimationEnd: this.setReadyForFocus(true) }, /*#__PURE__*/React__default["default"].createElement("div", { className: Filters$1["default"].FilterNodeContainer }, /*#__PURE__*/React__default["default"].createElement(Focus.Focus, { disabled: !filterIsOpen || !readyForFocus || !open, root: this.focusNode }, this.generateFilterMarkup(filter))))); }); const appliedFiltersCount = appliedFilters ? appliedFilters.length : 0; const moreFiltersLabel = hideTags && appliedFiltersCount > 0 ? i18n.translate('Polaris.Filters.moreFiltersWithCount', { count: appliedFiltersCount }) : i18n.translate('Polaris.Filters.moreFilters'); const rightActionMarkup = filters.length ? /*#__PURE__*/React__default["default"].createElement("div", { ref: this.moreFiltersButtonContainer }, /*#__PURE__*/React__default["default"].createElement(Button.Button, { onClick: this.toggleFilters, disabled: disabled }, moreFiltersLabel)) : null; const filterResourceName = resourceName || { singular: i18n.translate('Polaris.ResourceList.defaultItemSingular'), plural: i18n.translate('Polaris.ResourceList.defaultItemPlural') }; const transformedFilters = this.transformFilters(filters); const filtersControlMarkup = /*#__PURE__*/React__default["default"].createElement(ConnectedFilterControl.ConnectedFilterControl, { rightPopoverableActions: transformedFilters, rightAction: rightActionMarkup, auxiliary: children, disabled: disabled, forceShowMorefiltersButton: filters.length > transformedFilters.length, queryFieldHidden: hideQueryField }, hideQueryField ? null : /*#__PURE__*/React__default["default"].createElement(TextField.TextField, { placeholder: queryPlaceholder || i18n.translate('Polaris.Filters.filter', { resourceName: filterResourceName.plural }), onChange: onQueryChange, onBlur: onQueryBlur, onFocus: onQueryFocus, value: queryValue, focused: focused, label: queryPlaceholder || i18n.translate('Polaris.Filters.filter', { resourceName: filterResourceName.plural }), labelHidden: true, prefix: /*#__PURE__*/React__default["default"].createElement("span", { className: Filters$1["default"].SearchIcon }, /*#__PURE__*/React__default["default"].createElement(Icon.Icon, { source: polarisIcons.SearchMinor })), clearButton: true, onClearButtonClick: onQueryClear, disabled: disabled || disableQueryField, autoComplete: "off" })); const filtersContainerHeaderClassname = css.classNames(Filters$1["default"].FiltersContainerHeader); const filtersDesktopHeaderMarkup = /*#__PURE__*/React__default["default"].createElement("div", { className: filtersContainerHeaderClassname }, /*#__PURE__*/React__default["default"].createElement(Text.Text, { variant: "headingLg", as: "h3" }, moreFiltersLabel), /*#__PURE__*/React__default["default"].createElement(Button.Button, { icon: polarisIcons.CancelSmallMinor, plain: true, accessibilityLabel: i18n.translate('Polaris.Filters.cancel'), onClick: this.closeFilters })); const filtersMobileHeaderMarkup = /*#__PURE__*/React__default["default"].createElement("div", { className: filtersContainerHeaderClassname }, /*#__PURE__*/React__default["default"].createElement(Button.Button, { icon: polarisIcons.CancelSmallMinor, plain: true, accessibilityLabel: i18n.translate('Polaris.Filters.cancel'), onClick: this.closeFilters }), /*#__PURE__*/React__default["default"].createElement(Text.Text, { variant: "headingLg", as: "h3" }, moreFiltersLabel), /*#__PURE__*/React__default["default"].createElement(Button.Button, { onClick: this.closeFilters, primary: true }, i18n.translate('Polaris.Filters.done'))); const filtersDesktopFooterClassname = css.classNames(Filters$1["default"].FiltersContainerFooter); const filtersDesktopFooterMarkup = /*#__PURE__*/React__default["default"].createElement("div", { className: filtersDesktopFooterClassname }, /*#__PURE__*/React__default["default"].createElement(Button.Button, { onClick: this.handleClearAll, disabled: !this.hasAppliedFilters() }, i18n.translate('Polaris.Filters.clearAllFilters')), /*#__PURE__*/React__default["default"].createElement("div", { ref: this.moreFiltersDoneButtonContainer }, /*#__PURE__*/React__default["default"].createElement(Button.Button, { onClick: this.closeFilters, primary: true }, i18n.translate('Polaris.Filters.done')))); const filtersMobileFooterMarkup = /*#__PURE__*/React__default["default"].createElement("div", { className: Filters$1["default"].FiltersMobileContainerFooter }, this.hasAppliedFilters() ? /*#__PURE__*/React__default["default"].createElement(Button.Button, { onClick: onClearAll, fullWidth: true }, i18n.translate('Polaris.Filters.clearAllFilters')) : /*#__PURE__*/React__default["default"].createElement("div", { className: Filters$1["default"].EmptyFooterState }, /*#__PURE__*/React__default["default"].createElement(Text.Text, { variant: "bodyMd", color: "subdued", as: "span" }, /*#__PURE__*/React__default["default"].createElement("p", null, i18n.translate('Polaris.Filters.noFiltersApplied'))))); const shouldHideTagsContainer = !appliedFilters || appliedFilters.length < 1; const tagsMarkup = !hideTags ? /*#__PURE__*/React__default["default"].createElement(TagsWrapper.TagsWrapper, { hidden: shouldHideTagsContainer }, /*#__PURE__*/React__default["default"].createElement("div", { className: Filters$1["default"].TagsContainer, "aria-live": "polite" }, (appliedFilters || []).map(filter => { return /*#__PURE__*/React__default["default"].createElement(Tag.Tag, { key: filter.key, onRemove: () => { filter.onRemove(filter.key); }, disabled: disabled }, filter.label); }))) : null; const filtersMobileContainerContentClassName = css.classNames(Filters$1["default"].FiltersMobileContainerContent); const filtersDesktopContainerContentClassName = css.classNames(Filters$1["default"].FiltersDesktopContainerContent); const filtersContainerMarkup = isNavigationCollapsed ? /*#__PURE__*/React__default["default"].createElement(Sheet.Sheet, { accessibilityLabel: moreFiltersLabel, open: open, onClose: this.closeFilters, onEntered: this.setReadyForFocus(true), onExit: this.setReadyForFocus(false) }, filtersMobileHeaderMarkup, /*#__PURE__*/React__default["default"].createElement(Scrollable.Scrollable, { className: filtersMobileContainerContentClassName, shadow: true }, filtersContentMarkup, filtersMobileFooterMarkup)) : /*#__PURE__*/React__default["default"].createElement(Sheet.Sheet, { accessibilityLabel: moreFiltersLabel, open: open, onClose: this.closeFilters, onEntered: this.setReadyForFocus(true), onExit: this.setReadyForFocus(false) }, /*#__PURE__*/React__default["default"].createElement("div", { className: Filters$1["default"].FiltersContainer }, filtersDesktopHeaderMarkup, /*#__PURE__*/React__default["default"].createElement(Scrollable.Scrollable, { className: filtersDesktopContainerContentClassName, shadow: true }, filtersContentMarkup), filtersDesktopFooterMarkup)); const helpTextMarkup = helpText ? /*#__PURE__*/React__default["default"].createElement("div", { id: "FiltersHelpText", className: Filters$1["default"].HelpText }, /*#__PURE__*/React__default["default"].createElement(Text.Text, { variant: "bodyMd", color: "subdued", as: "span" }, helpText)) : null; return /*#__PURE__*/React__default["default"].createElement(withinFilterContext.WithinFilterContext.Provider, { value: true }, /*#__PURE__*/React__default["default"].createElement("div", { className: Filters$1["default"].Filters }, filtersControlMarkup, filtersContainerMarkup, tagsMarkup, helpTextMarkup, backdropMarkup, /*#__PURE__*/React__default["default"].createElement(KeypressListener.KeypressListener, { keyCode: types.Key.Escape, handler: this.closeFilters }))); } hasAppliedFilters() { const { appliedFilters, queryValue } = this.props; const filtersApplied = Boolean(appliedFilters && appliedFilters.length > 0); const queryApplied = Boolean(queryValue && queryValue !== ''); return filtersApplied || queryApplied; } getAppliedFilterContent(key) { const { appliedFilters } = this.props; if (!appliedFilters) { return undefined; } const filter = appliedFilters.find(filter => filter.key === key); return filter == null ? undefined : filter.label; } getAppliedFilterRemoveHandler(key) { const { appliedFilters } = this.props; if (!appliedFilters) { return undefined; } const filter = appliedFilters.find(filter => filter.key === key); return filter == null ? undefined : filter.onRemove; } openFilters() { this.setState({ open: true }); } toggleFilter(key) { if (this.state[`${key}${Suffix.Filter}`] === true) { this.setState({ readyForFocus: false, [`${key}${Suffix.Filter}`]: false }); } else { this.setState({ readyForFocus: false, [`${key}${Suffix.Filter}`]: true }); } } openFilterShortcut(key) { this.setState({ [`${key}${Suffix.Shortcut}`]: true }); } closeFilterShortcut(key) { this.setState({ [`${key}${Suffix.Shortcut}`]: false }); } toggleFilterShortcut(key) { if (this.state[`${key}${Suffix.Shortcut}`] === true) { this.closeFilterShortcut(key); } else { this.openFilterShortcut(key); } } transformFilters(filters) { const transformedActions = []; getShortcutFilters(filters).forEach(filter => { const { key, label, disabled } = filter; transformedActions.push({ popoverContent: this.generateFilterMarkup(filter), popoverOpen: Boolean(this.state[`${key}${Suffix.Shortcut}`]), key, content: label, disabled, onAction: () => this.toggleFilterShortcut(key) }); }); return transformedActions; } generateFilterMarkup(filter) { const i18n = this.props.i18n; const removeCallback = this.getAppliedFilterRemoveHandler(filter.key); const removeHandler = removeCallback == null ? undefined : () => { removeCallback(filter.key); }; const clearButtonMarkup = !filter.hideClearButton && /*#__PURE__*/React__default["default"].createElement(Button.Button, { plain: true, disabled: removeHandler == null, onClick: removeHandler, accessibilityLabel: i18n.translate('Polaris.Filters.clearLabel', { filterName: filter.label }) }, i18n.translate('Polaris.Filters.clear')); return /*#__PURE__*/React__default["default"].createElement("div", { ref: this.focusNode }, /*#__PURE__*/React__default["default"].createElement(Stack.Stack, { vertical: true, spacing: "tight" }, filter.filter, clearButtonMarkup)); } } FiltersInner.contextType = context.ResourceListContext; function getShortcutFilters(filters) { return filters.filter(filter => filter.shortcut === true); } function Filters(props) { const i18n = hooks.useI18n(); const mediaQuery = hooks$1.useMediaQuery(); return /*#__PURE__*/React__default["default"].createElement(FiltersInner, Object.assign({}, props, { i18n: i18n, mediaQuery: mediaQuery })); } exports.Filters = Filters;