From 14028655df1b94a1722d6e329174947db45db477 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sun, 21 Apr 2019 17:17:10 +0200 Subject: Move composer Dropdown from features/composer to features/compose --- .../composer/options/dropdown/content/index.js | 146 ------------- .../options/dropdown/content/item/index.js | 129 ------------ .../features/composer/options/dropdown/index.js | 229 --------------------- 3 files changed, 504 deletions(-) delete mode 100644 app/javascript/flavours/glitch/features/composer/options/dropdown/content/index.js delete mode 100644 app/javascript/flavours/glitch/features/composer/options/dropdown/content/item/index.js delete mode 100644 app/javascript/flavours/glitch/features/composer/options/dropdown/index.js (limited to 'app/javascript/flavours/glitch/features/composer/options/dropdown') diff --git a/app/javascript/flavours/glitch/features/composer/options/dropdown/content/index.js b/app/javascript/flavours/glitch/features/composer/options/dropdown/content/index.js deleted file mode 100644 index b76410561..000000000 --- a/app/javascript/flavours/glitch/features/composer/options/dropdown/content/index.js +++ /dev/null @@ -1,146 +0,0 @@ -// Package imports. -import PropTypes from 'prop-types'; -import React from 'react'; -import spring from 'react-motion/lib/spring'; - -// Components. -import ComposerOptionsDropdownContentItem from './item'; - -// Utils. -import { withPassive } from 'flavours/glitch/util/dom_helpers'; -import Motion from 'flavours/glitch/util/optional_motion'; -import { assignHandlers } from 'flavours/glitch/util/react_helpers'; - -// Handlers. -const handlers = { - // When the document is clicked elsewhere, we close the dropdown. - handleDocumentClick ({ target }) { - const { node } = this; - const { onClose } = this.props; - if (onClose && node && !node.contains(target)) { - onClose(); - } - }, - - // Stores our node in `this.node`. - handleRef (node) { - this.node = node; - }, -}; - -// The spring to use with our motion. -const springMotion = spring(1, { - damping: 35, - stiffness: 400, -}); - -// The component. -export default class ComposerOptionsDropdownContent extends React.PureComponent { - - // Constructor. - constructor (props) { - super(props); - assignHandlers(this, handlers); - - // Instance variables. - this.node = null; - - this.state = { - mounted: false, - }; - } - - // On mounting, we add our listeners. - componentDidMount () { - const { handleDocumentClick } = this.handlers; - document.addEventListener('click', handleDocumentClick, false); - document.addEventListener('touchend', handleDocumentClick, withPassive); - this.setState({ mounted: true }); - } - - // On unmounting, we remove our listeners. - componentWillUnmount () { - const { handleDocumentClick } = this.handlers; - document.removeEventListener('click', handleDocumentClick, false); - document.removeEventListener('touchend', handleDocumentClick, withPassive); - } - - // Rendering. - render () { - const { mounted } = this.state; - const { handleRef } = this.handlers; - const { - items, - onChange, - onClose, - style, - value, - } = this.props; - - // The result. - return ( - - {({ opacity, scaleX, scaleY }) => ( - // It should not be transformed when mounting because the resulting - // size will be used to determine the coordinate of the menu by - // react-overlays -
- {items ? items.map( - ({ - name, - ...rest - }) => ( - - ) - ) : null} -
- )} -
- ); - } - -} - -// Props. -ComposerOptionsDropdownContent.propTypes = { - items: PropTypes.arrayOf(PropTypes.shape({ - icon: PropTypes.string, - meta: PropTypes.node, - name: PropTypes.string.isRequired, - on: PropTypes.bool, - text: PropTypes.node, - })), - onChange: PropTypes.func, - onClose: PropTypes.func, - style: PropTypes.object, - value: PropTypes.string, -}; - -// Default props. -ComposerOptionsDropdownContent.defaultProps = { style: {} }; diff --git a/app/javascript/flavours/glitch/features/composer/options/dropdown/content/item/index.js b/app/javascript/flavours/glitch/features/composer/options/dropdown/content/item/index.js deleted file mode 100644 index 68a52083f..000000000 --- a/app/javascript/flavours/glitch/features/composer/options/dropdown/content/item/index.js +++ /dev/null @@ -1,129 +0,0 @@ -// Package imports. -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React from 'react'; -import Toggle from 'react-toggle'; - -// Components. -import Icon from 'flavours/glitch/components/icon'; - -// Utils. -import { assignHandlers } from 'flavours/glitch/util/react_helpers'; - -// Handlers. -const handlers = { - - // This function activates the dropdown item. - handleActivate (e) { - const { - name, - onChange, - onClose, - options: { on }, - } = this.props; - - // If the escape key was pressed, we close the dropdown. - if (e.key === 'Escape' && onClose) { - onClose(); - - // Otherwise, we both close the dropdown and change the value. - } else if (onChange && (!e.key || e.key === 'Enter')) { - e.preventDefault(); // Prevents change in focus on click - if ((on === null || typeof on === 'undefined') && onClose) { - onClose(); - } - onChange(name); - } - }, -}; - -// The component. -export default class ComposerOptionsDropdownContentItem extends React.PureComponent { - - // Constructor. - constructor (props) { - super(props); - assignHandlers(this, handlers); - } - - // Rendering. - render () { - const { handleActivate } = this.handlers; - const { - active, - options: { - icon, - meta, - on, - text, - }, - } = this.props; - const computedClass = classNames('composer--options--dropdown--content--item', { - active, - lengthy: meta, - 'toggled-off': !on && on !== null && typeof on !== 'undefined', - 'toggled-on': on, - 'with-icon': icon, - }); - - // The result. - return ( -
- {function () { - - // We render a `` if we were provided an `on` - // property, and otherwise show an `` if available. - switch (true) { - case on !== null && typeof on !== 'undefined': - return ( - - ); - case !!icon: - return ( - - ); - default: - return null; - } - }()} - {meta ? ( -
- {text} - {meta} -
- ) : -
- {text} -
} -
- ); - } - -}; - -// Props. -ComposerOptionsDropdownContentItem.propTypes = { - active: PropTypes.bool, - name: PropTypes.string, - onChange: PropTypes.func, - onClose: PropTypes.func, - options: PropTypes.shape({ - icon: PropTypes.string, - meta: PropTypes.node, - on: PropTypes.bool, - text: PropTypes.node, - }), -}; diff --git a/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js b/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js deleted file mode 100644 index 7817cc964..000000000 --- a/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js +++ /dev/null @@ -1,229 +0,0 @@ -// Package imports. -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React from 'react'; -import Overlay from 'react-overlays/lib/Overlay'; - -// Components. -import IconButton from 'flavours/glitch/components/icon_button'; -import ComposerOptionsDropdownContent from './content'; - -// Utils. -import { isUserTouching } from 'flavours/glitch/util/is_mobile'; -import { assignHandlers } from 'flavours/glitch/util/react_helpers'; - -// Handlers. -const handlers = { - - // Closes the dropdown. - handleClose () { - this.setState({ open: false }); - }, - - // The enter key toggles the dropdown's open state, and the escape - // key closes it. - handleKeyDown ({ key }) { - const { - handleClose, - handleToggle, - } = this.handlers; - switch (key) { - case 'Enter': - handleToggle(key); - break; - case 'Escape': - handleClose(); - break; - } - }, - - // Creates an action modal object. - handleMakeModal () { - const component = this; - const { - items, - onChange, - onModalOpen, - onModalClose, - value, - } = this.props; - - // Required props. - if (!(onChange && onModalOpen && onModalClose && items)) { - return null; - } - - // The object. - return { - actions: items.map( - ({ - name, - ...rest - }) => ({ - ...rest, - active: value && name === value, - name, - onClick (e) { - e.preventDefault(); // Prevents focus from changing - onModalClose(); - onChange(name); - }, - onPassiveClick (e) { - e.preventDefault(); // Prevents focus from changing - onChange(name); - component.setState({ needsModalUpdate: true }); - }, - }) - ), - }; - }, - - // Toggles opening and closing the dropdown. - handleToggle ({ target }) { - const { handleMakeModal } = this.handlers; - const { onModalOpen } = this.props; - const { open } = this.state; - - // If this is a touch device, we open a modal instead of the - // dropdown. - if (isUserTouching()) { - - // This gets the modal to open. - const modal = handleMakeModal(); - - // If we can, we then open the modal. - if (modal && onModalOpen) { - onModalOpen(modal); - return; - } - } - - const { top } = target.getBoundingClientRect(); - this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' }); - // Otherwise, we just set our state to open. - this.setState({ open: !open }); - }, - - // If our modal is open and our props update, we need to also update - // the modal. - handleUpdate () { - const { handleMakeModal } = this.handlers; - const { onModalOpen } = this.props; - const { needsModalUpdate } = this.state; - - // Gets our modal object. - const modal = handleMakeModal(); - - // Reopens the modal with the new object. - if (needsModalUpdate && modal && onModalOpen) { - onModalOpen(modal); - } - }, -}; - -// The component. -export default class ComposerOptionsDropdown extends React.PureComponent { - - // Constructor. - constructor (props) { - super(props); - assignHandlers(this, handlers); - this.state = { - needsModalUpdate: false, - open: false, - placement: 'bottom', - }; - } - - // Updates our modal as necessary. - componentDidUpdate (prevProps) { - const { handleUpdate } = this.handlers; - const { items } = this.props; - const { needsModalUpdate } = this.state; - if (needsModalUpdate && items.find( - (item, i) => item.on !== prevProps.items[i].on - )) { - handleUpdate(); - this.setState({ needsModalUpdate: false }); - } - } - - // Rendering. - render () { - const { - handleClose, - handleKeyDown, - handleToggle, - } = this.handlers; - const { - active, - disabled, - title, - icon, - items, - onChange, - value, - } = this.props; - const { open, placement } = this.state; - const computedClass = classNames('composer--options--dropdown', { - active, - open, - top: placement === 'top', - }); - - // The result. - return ( -
- - - - -
- ); - } - -} - -// Props. -ComposerOptionsDropdown.propTypes = { - active: PropTypes.bool, - disabled: PropTypes.bool, - icon: PropTypes.string, - items: PropTypes.arrayOf(PropTypes.shape({ - icon: PropTypes.string, - meta: PropTypes.node, - name: PropTypes.string.isRequired, - on: PropTypes.bool, - text: PropTypes.node, - })).isRequired, - onChange: PropTypes.func, - onModalClose: PropTypes.func, - onModalOpen: PropTypes.func, - title: PropTypes.string, - value: PropTypes.string, -}; -- cgit