@salesforce/design-system-react
Version:
Salesforce Lightning Design System for React
378 lines (316 loc) • 14.8 kB
JavaScript
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