UNPKG

@salesforce/design-system-react

Version:

Salesforce Lightning Design System for React

378 lines (316 loc) 14.8 kB
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 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); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /* Copyright (c) 2015-present, salesforce.com, inc. All rights reserved */ /* Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */ // # Carousel Component // Implements the [Carousel design pattern](https://www.lightningdesignsystem.com/components/carousel/) in React. import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; // ### shortid // [npmjs.com/package/shortid](https://www.npmjs.com/package/shortid) // shortid is a short, non-sequential, url-friendly, unique id generator import shortid from 'shortid'; import { CAROUSEL } from '../../utilities/constants'; import { canUseDOM, canUseEventListeners } from '../../utilities/execution-environment'; import CarouselIndicators from './private/carousel-indicators'; import PreviousNextCarouselNavigator from './private/previous-next-carousel-navigator'; import CarouselItem from './private/carousel-item'; import AutoPlayButton from './private/auto-play-button'; // ### Event Helpers import KEYS from '../../utilities/key-code'; import EventUtil from '../../utilities/event'; /* eslint-disable jsx-a11y/no-static-element-interactions */ // ### Default Props var defaultProps = { assistiveText: { autoPlayButton: 'Start / Stop auto-play', nextPanel: 'Next Panel', previousPanel: 'Previous Panel' }, autoplayInterval: 4000, hasAutoplay: false, hasPreviousNextPanelNavigation: false, isInfinite: false, itemsPerPanel: 1 }; /** * A carousel allows multiple pieces of featured content to occupy an allocated amount of space. * Currently panel index and auto play cannot be controlled by the app. */ var Carousel = /*#__PURE__*/ function (_React$Component) { _inherits(Carousel, _React$Component); // ### Display Name // Always use the canonical component name as the React display name. // ### Prop Types // ### Default Props function Carousel(props) { var _this; _classCallCheck(this, Carousel); _this = _possibleConstructorReturn(this, _getPrototypeOf(Carousel).call(this, props)); _defineProperty(_assertThisInitialized(_this), "onNextPanelHandler", function () { var next = _this.state.currentPanel % _this.nrOfPanels + 1; _this.setCurrentPanel(next, _this.changeTranslationAutomatically); }); _defineProperty(_assertThisInitialized(_this), "onPreviousPanelHandler", function () { var prev = (_this.state.currentPanel + _this.nrOfPanels - 1) % _this.nrOfPanels; _this.setCurrentPanel(prev, _this.changeTranslationAutomatically); }); _defineProperty(_assertThisInitialized(_this), "onIndicatorClickHandler", function (panel) { _this.setCurrentPanel(panel, _this.changeTranslationAutomatically); }); _defineProperty(_assertThisInitialized(_this), "onAutoPlayBtnClick", function () { var isAutoPlayOn = _this.state.isAutoPlayOn; var actionToTake = isAutoPlayOn ? _this.stopAutoplay : _this.startAutoplay; _this.setState({ isAutoPlayOn: !isAutoPlayOn }); actionToTake(); }); _defineProperty(_assertThisInitialized(_this), "setDimensions", function () { if (canUseDOM && _this.stageItem !== undefined && _this.stageItem.current !== undefined && _this.stageItem.current.offsetWidth !== undefined) { _this.setState({ stageWidth: _this.stageItem.current.offsetWidth }, _this.changeTranslationAutomatically); } }); _defineProperty(_assertThisInitialized(_this), "setTranslationAmount", function (amount, cb) { _this.setState({ translateX: amount }, cb); }); _defineProperty(_assertThisInitialized(_this), "setCurrentPanel", function (amount, cb) { _this.setState({ currentPanel: amount }, cb); }); _defineProperty(_assertThisInitialized(_this), "startAutoplay", function () { _this.autoplayId = setInterval(function () { if (_this.canGoToNext()) { _this.onNextPanelHandler(); } else { _this.stopAutoplay(); } }, _this.props.autoplayInterval); }); _defineProperty(_assertThisInitialized(_this), "stopAutoplay", function () { if (_this.autoplayId) { clearInterval(_this.autoplayId); } _this.setState({ isAutoPlayOn: false }); }); _defineProperty(_assertThisInitialized(_this), "changeTranslationAutomatically", function () { _this.setTranslationAmount(-((_this.state.stageWidth || _this.stageWidth) * (_this.state.currentPanel - 1))); }); _defineProperty(_assertThisInitialized(_this), "canGoToNext", function () { return _this.state.currentPanel < _this.nrOfPanels; }); _defineProperty(_assertThisInitialized(_this), "canGoToPrevious", function () { return _this.state.currentPanel > 1; }); _defineProperty(_assertThisInitialized(_this), "handleKeyDown", function (event) { var _keyDownCallbacks; var keyDownCallbacks = (_keyDownCallbacks = {}, _defineProperty(_keyDownCallbacks, KEYS.LEFT, function () { if (_this.canGoToPrevious()) { _this.onPreviousPanelHandler(); } }), _defineProperty(_keyDownCallbacks, KEYS.RIGHT, function () { if (_this.canGoToNext()) { _this.onNextPanelHandler(); } }), _keyDownCallbacks); if (keyDownCallbacks[event.keyCode]) { EventUtil.trapImmediate(event); keyDownCallbacks[event.keyCode](); } }); var _this$props = _this.props, items = _this$props.items, itemsPerPanel = _this$props.itemsPerPanel; _this.nrOfPanels = Math.ceil(items.length / itemsPerPanel); _this.stageItem = React.createRef(); _this.state = { translateX: -1000000, currentPanel: 1, isAutoPlayOn: _this.props.hasAutoplay, stageWidth: 0 }; return _this; } _createClass(Carousel, [{ key: "componentWillMount", value: function componentWillMount() { this.generatedId = shortid.generate(); } }, { key: "componentDidMount", value: function componentDidMount() { this.setTranslationAmount(0); if (this.props.hasAutoplay) { this.startAutoplay(); } if (canUseDOM && this.stageItem !== undefined && this.stageItem.current !== undefined && this.stageItem.current.offsetWidth !== undefined) { this.stageWidth = this.stageItem.current.offsetWidth; } if (canUseEventListeners) { window.addEventListener('resize', this.setDimensions, false); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { if (canUseEventListeners) { window.removeEventListener('resize', this.setDimensions, false); } this.stopAutoplay(); } }, { key: "render", value: function render() { var _this2 = this; var _this$props2 = this.props, hasAutoplay = _this$props2.hasAutoplay, hasPreviousNextPanelNavigation = _this$props2.hasPreviousNextPanelNavigation, isInfinite = _this$props2.isInfinite; var id = this.props.id || this.generatedId; var isPreviousBtnDisabled = !(isInfinite || this.canGoToPrevious()); var isNextBtnDisabled = !(isInfinite || this.canGoToNext()); var itemWidth = (this.state.stageWidth || this.stageWidth) / this.props.itemsPerPanel; return React.createElement("div", { className: classnames('slds-carousel', this.props.className), id: id, onKeyDown: this.handleKeyDown }, React.createElement("div", { className: "slds-grid_vertical slds-col slds-path__scroller" }, hasAutoplay && React.createElement(AutoPlayButton, { assistiveText: this.props.assistiveText.autoPlayButton, isAutoPlayOn: this.state.isAutoPlayOn, onClick: this.onAutoPlayBtnClick }), React.createElement("div", { className: "slds-is-relative", style: { marginLeft: '60px', marginRight: '60px' } }, hasPreviousNextPanelNavigation && React.createElement(PreviousNextCarouselNavigator, { assistiveText: this.props.assistiveText.previousPanel, iconName: "left", isDisabled: isPreviousBtnDisabled, onClick: this.onPreviousPanelHandler, inlineStyle: { left: '-60px' } }), React.createElement("div", { ref: this.stageItem, className: "slds-carousel__stage slds-show" }, React.createElement("div", { className: "slds-carousel__panels slds-is-relative", style: { transform: "translateX(".concat(this.state.translateX, "px)") } }, this.props.items.map(function (item, index) { return React.createElement(CarouselItem, _extends({ onClick: function onClick(event) { _this2.props.onItemClick(event, { item: item }); }, onRenderItem: _this2.props.onRenderItem }, item, { isInCurrentPanel: index >= (_this2.state.currentPanel - 1) * _this2.props.itemsPerPanel && index < (_this2.state.currentPanel - 1) * _this2.props.itemsPerPanel + _this2.props.itemsPerPanel, itemWidth: itemWidth, key: item.id })); }))), hasPreviousNextPanelNavigation && React.createElement(PreviousNextCarouselNavigator, { assistiveText: this.props.assistiveText.nextPanel, iconName: "right", isDisabled: isNextBtnDisabled, onClick: this.onNextPanelHandler, inlineStyle: { right: '-60px' } })), React.createElement(CarouselIndicators, { style: this.props.indicatorStyles, noOfIndicators: this.nrOfPanels, currentIndex: this.state.currentPanel, onClick: this.onIndicatorClickHandler, items: this.props.items, itemsPerPanel: this.props.itemsPerPanel }))); } }]); return Carousel; }(React.Component); _defineProperty(Carousel, "displayName", CAROUSEL); _defineProperty(Carousel, "propTypes", { /** * Description of the carousel items for screen-readers. */ assistiveText: PropTypes.object, /** * Interval for the autoplay iteration */ autoplayInterval: PropTypes.number, /** * CSS classes that are applied to the main 'slds-carousel' classed component container */ className: PropTypes.oneOfType([PropTypes.array, PropTypes.object, PropTypes.string]), /** * Boolean showing whether the autoplay feature is available or not */ hasAutoplay: PropTypes.bool, /** * Boolean for displaying the navigation indicators (left/right arrows) of the carousel */ hasPreviousNextPanelNavigation: PropTypes.bool, /** * Id of component, if desired. If not provided an id is automatically generated */ id: PropTypes.string, /** * CSS that is applied to carousel indicators */ indicatorStyles: PropTypes.object, /** * Boolean for infinite loop navigation */ isInfinite: PropTypes.bool, /** * * **Array of item objects used by the default carousel item renderer.** * Each object can contain: * * `id`: The id of the carousel item. [REQUIRED] * * `heading`: Primary string that will be used as the heading * * `description`: Secondary string that is used to describe the item * * `buttonLabel`: If assigned a call to button action will be rendered with this text, if unassigned no button is rendered * * `imageAssistiveText`: Image alt text, if not present heading will be used instead * * `href`: Used for item link, if not provided 'javascript:void(0);' is used instead * * `src`: Item image src value */ items: PropTypes.array.isRequired, /** * Number of items to be displayed at a time in the carousel */ itemsPerPanel: PropTypes.number, /** * Accepts a custom carousel item rendering function */ onRenderItem: PropTypes.func, /** * Handler for clicking on a carousel item */ onItemClick: PropTypes.func }); _defineProperty(Carousel, "defaultProps", defaultProps); export default Carousel; //# sourceMappingURL=index.js.map