UNPKG

@fluent-windows/core

Version:

React components that inspired by Microsoft's Fluent Design System.

128 lines (118 loc) 4.4 kB
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import * as React from 'react'; import { MoreLine as MoreLineIcon } from '@fluent-windows/icons'; // TODO treeShaking import { useClickOutside, useReveal, usePopper } from '@fluent-windows/hooks'; // TODO treeShaking import { omit } from '../utils'; import Box from '../Box'; import { styles } from './Command.styled'; import Secondary from './components/Secondary'; import Content from './components/Content'; import Portal from '../Portal'; import Item from '../Item'; import Transition from '../Transition'; import { CommandPropTypes } from './Command.type'; import { createUseStyles } from 'react-jss'; import classNames from 'classnames'; export const name = 'Command'; const useStyles = createUseStyles(styles, { name }); export const CommandContext = React.createContext(false); const Command = React.forwardRef((props, ref) => { const { as = 'div', className: classNameProp, acrylic = false, reveal = false, children, ...rest } = props; const classes = useStyles(props); const className = classNames(classes.root, classNameProp); const container = React.useMemo(() => React.Children.toArray(children).reduce((acc, cur) => { if (cur.type.displayName === 'FCommandContent') { return { ...acc, content: [...acc.content, cur] }; } else if (cur.type.displayName === 'FCommandSecondary') { return { ...acc, secondary: cur.props.children }; } return { ...acc, standard: [...acc.standard, cur] }; }, { content: [], standard: [], secondary: null }), [children]); // Reveal does not take effect when using acrylic const _reveal = React.useMemo(() => acrylic ? false : reveal, [acrylic, reveal]); const [RevealWrapper] = useReveal(); // Secondary Popup related const [secondaryVisible, setSecondaryVisible] = React.useState(false); const handleSecondaryVisible = React.useCallback(() => { if (secondaryVisible) return; setSecondaryVisible(visible => !visible); }, [secondaryVisible]); // Click on the area outside the More menu to close the More menu. const [referenceRef, popperRef] = usePopper({ placement: 'bottom-end' }); useClickOutside(popperRef, event => { // @ts-ignore if (!referenceRef.current || referenceRef.current.contains(event.target)) return; setSecondaryVisible(visible => !visible); }); const otherProps = omit(rest, ['display', 'backgroundColor', 'color']); return React.createElement(Box, _extends({ ref: ref, as: as, acrylic: acrylic, className: className, backgroundColor: "standard.light2" }, otherProps), React.createElement(CommandContext.Provider, { value: _reveal }, !!container.content.length && React.createElement("div", { className: classes.content }, container.content), React.createElement("div", { className: classes.primary }, _reveal ? container.standard.map((child, i) => React.createElement(RevealWrapper, { key: i }, child)) : container.standard), container.secondary !== null && (_reveal ? React.createElement(RevealWrapper, null, React.createElement(Item, { ref: referenceRef, style: { height: '100%' }, onClick: handleSecondaryVisible, prefix: React.createElement(MoreLineIcon, null) })) : React.createElement(Item, { ref: referenceRef, onClick: handleSecondaryVisible, prefix: React.createElement(MoreLineIcon, null) })), React.createElement(Portal, null, React.createElement(Transition, { visible: secondaryVisible, wrapper: true, mountOnEnter: true, unmountOnExit: true }, React.createElement(Box, { ref: popperRef, acrylic: acrylic, backgroundColor: "standard.light2", className: classes.secondaryRoot }, container.secondary))))); }); Object.defineProperty(Command, 'Secondary', { get() { return Secondary; } }); Object.defineProperty(Command, 'Content', { get() { return Content; } }); Command.displayName = `F${name}`; Command.propTypes = CommandPropTypes; Command.defaultProps = { reveal: false }; export default Command;