Learn more  » Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

lnguyenacl / acl-ui   js

Repository URL to install this package:

Version: 3.0.0 

/ components / SidePanel / SidePanel.js

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

const warnings = {
  missingTitle: 'Use the title property on the aclSidePanel Element to render a title',
  missingContent: 'Write some children elements to render content in the aclSidePanel'
};

// config for the panel sizes
const widths = {
  default: 'acl-panel',
  small: '--size-small',
  oneThird: '--size-one-third',
  half: '--size-half',
  threeQuarters: '--size-three-quarters',
  maximum: '--size-max'
};

// will be unique for the use in the refs later. (reference for the dom element)
const aclContainerPanel = Symbol('aclContainerPanel');

const slideDirection = {
  left: 'acl-panel--slide-left',
  right: 'acl-panel--slide-right'
};

const secondaryThemeClassName = 'acl-panel--secondary';

class SidePanel extends _react.Component {

  componentWillMount() {
    document.addEventListener('keyup', this.onEscapeKey.bind(this), false);
  }

  componentWillUnmount() {
    document.removeEventListener('keyup', this.onEscapeKey, false);
  }

  constructor(props) {
    super(props);
  }

  toggle(e) {
    const sidePanelContainer = this.refs[aclContainerPanel]; // reference to the Dom Element
    const switchClasses = () => {
      sidePanelContainer.classList.toggle('is-open');
    };

    const triggerCallbacks = () => {
      // trigger events in case any is declare.
      sidePanelContainer.classList.contains('is-open') ? this.onOpen() : this.onClose();
    };

    if (!e || !e.target.classList.contains('acl-panel-overlay')) {
      switchClasses();
      triggerCallbacks();
    } else {
      // if the overlay is not clickable we ignore the event / overlay is disabled.
      if (this.props.clickableOverlay) {
        switchClasses();
        triggerCallbacks();
      }
    }
  }

  open() {
    const sidePanelContainer = this.refs[aclContainerPanel]; // reference to the Dom Element
    sidePanelContainer.classList.add('is-open');
    this.onOpen();
  }

  close() {
    const sidePanelContainer = this.refs[aclContainerPanel]; // reference to the Dom Element
    sidePanelContainer.classList.remove('is-open');
    this.onClose();
  }

  getPanelClassName() {
    // creating initial class name container for the component ex: class="acl-panel acl-panel--slide-right acl-panel--size-max is-open"
    const direction = this.props.slideDirection !== SidePanel.defaultProps.slideDirection ? slideDirection.left : slideDirection.right;

    // assigning the width size of the container
    const width = this.props.width !== SidePanel.defaultProps.width ? `${ widths.default }${ widths[this.props.width] }` : widths.default;

    // assigning the selected secondaryTheme
    const secondaryTheme = this.props.secondaryTheme ? secondaryThemeClassName : '';

    return `${ widths.default } ${ direction } ${ width } ${ secondaryTheme }`;
  }

  getTitleIcon() {
    if (this.props.titleIcon) {
      const iconClassName = `${ this.props.titleIcon } panel-title__icon`;
      return _react2.default.createElement('i', { className: iconClassName });
    }
  }

  renderOverlay() {
    if (this.props.hasOverlay) {
      return _react2.default.createElement('div', { className: 'acl-panel-overlay', onClick: this.toggle.bind(this) });
    }
  }

  renderCloseButton() {
    if (this.props.hasCloseButton) {
      return _react2.default.createElement(
        'button',
        { className: 'panel__close', onClick: this.close.bind(this) },
        _react2.default.createElement('i', { className: 'acl-i-times close__icon' })
      );
    }
  }

  onOpen() {
    if (this.props.onOpen) {
      this.props.onOpen({ instance: this });
    }
  }

  onClose() {
    if (this.props.onClose) {
      this.props.onClose({ instance: this });
    }
  }

  onEscapeKey(e) {
    if (this.props.closeOnEscKeyDown) {
      // escape key maps to key-code `27`
      if (e.keyCode == 27 && this.props.clickableOverlay) {
        this.close();
        // if a callback is defined for on close
        if (this.props.onClose) {
          this.onClose();
        }
      }
    }
  }

  render() {
    return _react2.default.createElement(
      'div',
      null,
      _react2.default.createElement(
        'div',
        { ref: aclContainerPanel, className: `${ this.getPanelClassName.bind(this)() }` },
        this.renderCloseButton.bind(this)(),
        _react2.default.createElement(
          'div',
          { className: 'panel__body' },
          _react2.default.createElement(
            'div',
            { className: 'panel__header' },
            _react2.default.createElement(
              'h2',
              { className: 'panel__title' },
              this.getTitleIcon.bind(this)(),
              this.props.title
            )
          ),
          _react2.default.createElement(
            'div',
            { className: 'panel__content' },
            this.props.children
          )
        )
      ),
      this.renderOverlay.bind(this)()
    );
  }
}
exports.default = SidePanel;
SidePanel.propTypes = {
  /**
   * The content for the Side Panel
   */
  children: _react.PropTypes.node,
  /**
   * Text displaying as title at the top of the controller
   */
  title: _react.PropTypes.string,
  /**
   * Allow to display an icon next to the title, accept any icon string from the UI-ACL
   * @string
   */
  titleIcon: _react2.default.PropTypes.string, // TODO: maybe we should have a list of all possible icons? that way if the use pass a wrong icon display an error like icon don't exist?
  /**
   * Modify the side for displaying the panel [left, right] Default is right
   * @string One of the keys in the Object slideDirection
   */
  slideDirection: _react2.default.PropTypes.oneOf(Object.keys(slideDirection).map(key => key)), // extracting the accept values for the position property.
  /**
   * Modify the width of the panel
   * @string One of the keys in the Object Object panelWidths
   */
  width: _react2.default.PropTypes.oneOf(Object.keys(widths).map(key => key)), // extracting the accept values for the sizes property.
  /**
   * Allow to set the secondary theme of ACL
   * @string true or false, this is a string format not a boolean
   */
  secondaryTheme: _react2.default.PropTypes.bool,
  /**
   * Disable the click event for the overlay, default is click event enable
   * @string true or false, this is a string format not a boolean
   */
  clickableOverlay: _react2.default.PropTypes.bool,
  /**
   * Disable the displaying of the overlay, default is enable
   * @string true or false, this is a string format not a boolean
   */
  hasOverlay: _react2.default.PropTypes.bool,
  /**
   * Hide the close button of the top right corner, default is showing the button hasCloseButton="false"
   */
  hasCloseButton: _react2.default.PropTypes.bool,
  /**
   * Disable the event of key up "esc" default is enable
   */
  closeOnEscKeyDown: _react2.default.PropTypes.bool,
  /**
   * Callback for onOpen event
   */
  onOpen: _react2.default.PropTypes.func,
  /**
   * Callback for onClose event
   */
  onClose: _react2.default.PropTypes.func
};
SidePanel.defaultProps = {
  title: warnings.notTitle,
  children: warnings.notContent,
  width: 'default',
  slideDirection: 'right',
  clickableOverlay: true,
  hasOverlay: true,
  secondaryTheme: false,
  hasCloseButton: true,
  closeOnEscKeyDown: true
};