@pnp/spfx-controls-react
Version:
Reusable React controls for SharePoint Framework solutions
378 lines • 21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Carousel = void 0;
var tslib_1 = require("tslib");
var Button_1 = require("@fluentui/react/lib/Button");
var icons_1 = require("@uifabric/icons");
(0, icons_1.initializeIcons)();
var React = tslib_1.__importStar(require("react"));
var Carousel_module_scss_1 = tslib_1.__importDefault(require("./Carousel.module.scss"));
var ICarouselProps_1 = require("./ICarouselProps");
var lib_1 = require("@uifabric/utilities/lib");
var ICarouselState_1 = require("./ICarouselState");
var Spinner_1 = require("@fluentui/react/lib/Spinner");
var common_1 = require("@pnp/common");
var telemetry = tslib_1.__importStar(require("../../common/telemetry"));
var CarouselImage_1 = tslib_1.__importDefault(require("./CarouselImage"));
var ICarouselProps_2 = require("./ICarouselProps");
var Styling_1 = require("@fluentui/react/lib/Styling");
var Carousel = /** @class */ (function (_super) {
tslib_1.__extends(Carousel, _super);
function Carousel(props) {
var _this = _super.call(this, props) || this;
_this.renderSlide = function (element) {
var _a;
var isAnimated = _this.props.slide !== false && !_this.props.triggerPageEvent;
var _b = _this.state, currentIndex = _b.currentIndex, previousIndex = _b.previousIndex, slideRight = _b.slideRight;
if (!isAnimated || previousIndex === undefined) {
return [React.createElement("div", { key: currentIndex, className: Carousel_module_scss_1.default.slideWrapper }, element)];
}
var previousElement = _this.getElementToDisplay(previousIndex);
var result = [];
result.push(React.createElement("div", { key: currentIndex, className: (0, lib_1.css)(Carousel_module_scss_1.default.slideWrapper, (_a = {},
_a[Carousel_module_scss_1.default.slideFromLeft] = slideRight,
_a[Carousel_module_scss_1.default.slideFromRight] = !slideRight,
_a)) }, element));
if (slideRight) {
result.push(React.createElement("div", { key: previousIndex, className: (0, lib_1.css)(Carousel_module_scss_1.default.slideWrapper, Carousel_module_scss_1.default.slideRight, Carousel_module_scss_1.default.right) }, previousElement));
}
else {
result.unshift(React.createElement("div", { key: previousIndex, className: (0, lib_1.css)(Carousel_module_scss_1.default.slideWrapper, Carousel_module_scss_1.default.slideLeft, Carousel_module_scss_1.default.left) }, previousElement));
}
return result;
};
_this.getIndicatorsElement = function () {
var _a;
var _b = _this.props, indicators = _b.indicators, _c = _b.indicatorShape, indicatorShape = _c === void 0 ? ICarouselProps_1.CarouselIndicatorShape.rectangle : _c, onRenderIndicator = _b.onRenderIndicator, triggerPageEvent = _b.triggerPageEvent, indicatorClassName = _b.indicatorClassName, indicatorStyle = _b.indicatorStyle;
var _d = _this.state.currentIndex, currentIndex = _d === void 0 ? 0 : _d;
if (indicators === false) {
return null;
}
var elementsCount = triggerPageEvent ? _this.props.elementsCount : (0, common_1.isArray)(_this.props.element) ? _this.props.element.length : 1;
var indicatorElements = [];
var _loop_1 = function (i) {
var _e;
if (onRenderIndicator) {
indicatorElements.push(onRenderIndicator(i, _this.onIndicatorClick));
}
else {
indicatorElements.push(React.createElement("li", { className: (0, lib_1.css)(indicatorClassName, (_e = {},
_e[Carousel_module_scss_1.default.active] = i === currentIndex,
_e)), style: indicatorStyle, onClick: function (e) { return _this.onIndicatorClick(e, i); } }));
}
};
for (var i = 0; i < elementsCount; i++) {
_loop_1(i);
}
if (onRenderIndicator) {
return React.createElement("div", { className: Carousel_module_scss_1.default.indicators }, indicatorElements);
}
else {
return React.createElement("ol", { className: (0, lib_1.css)((_a = {},
_a[Carousel_module_scss_1.default.indicators] = true,
_a[Carousel_module_scss_1.default.circle] = indicatorShape === ICarouselProps_1.CarouselIndicatorShape.circle,
_a[Carousel_module_scss_1.default.rectangle] = indicatorShape === ICarouselProps_1.CarouselIndicatorShape.rectangle,
_a[Carousel_module_scss_1.default.square] = indicatorShape === ICarouselProps_1.CarouselIndicatorShape.square,
_a)) }, indicatorElements);
}
};
_this.onIndicatorClick = function (e, index) {
_this.startCycle();
if (_this.props.onSelect) {
_this.props.onSelect(index);
}
var currentIndex = _this.state.currentIndex;
_this.setState({
currentIndex: index,
previousIndex: currentIndex,
slideRight: index < currentIndex
});
};
/**
* Merges the styles of the components.
*/
_this.getMergedStyles = function (componentStyles, userStyles) {
var mergedStyles = userStyles ? (0, lib_1.css)(componentStyles, userStyles) : (0, lib_1.css)(componentStyles);
return mergedStyles;
};
/**
* Determines if the carousel button can be clicked.
*/
_this.isCarouselButtonDisabled = function (nextButton) {
// false by default
var isInfinite = _this.props.isInfinite !== undefined ? _this.props.isInfinite : false;
var currentIndex = _this.state.currentIndex;
var result = false;
// Use validation from parent control or calcualte it based on the current index
if (nextButton) {
result = _this.props.canMoveNext !== undefined ?
!_this.props.canMoveNext :
(currentIndex === _this.props.element.length - 1) && !isInfinite;
}
else {
result = _this.props.canMovePrev !== undefined ?
!_this.props.canMovePrev :
(0 === currentIndex) && !isInfinite;
}
return result;
};
/**
* Handles carousel button click.
*/
_this.onCarouselButtonClicked = function (nextButtonClicked) {
_this.startCycle();
var currentIndex = _this.state.currentIndex;
var nextIndex = _this.state.currentIndex;
var processingState = ICarouselState_1.ProcessingState.processing;
// Trigger parent control to update provided element
if (_this.props.triggerPageEvent) {
var canMove = nextButtonClicked ? _this.props.canMoveNext !== false : _this.props.canMovePrev !== false;
if (canMove) {
// Index validation needs to be done by the parent control specyfing canMove Next|Prev
nextIndex = nextButtonClicked ? (currentIndex + 1) : (currentIndex - 1);
// Trigger parent to provide new data
_this.props.triggerPageEvent(nextIndex);
processingState = ICarouselState_1.ProcessingState.processing;
}
}
else {
nextIndex = _this.getNextIndex(nextButtonClicked);
if (nextIndex !== currentIndex) {
if (nextButtonClicked && _this.props.onMoveNextClicked) {
_this.props.onMoveNextClicked(nextIndex);
}
else if (_this.props.onMovePrevClicked) {
_this.props.onMovePrevClicked(nextIndex);
}
}
processingState = ICarouselState_1.ProcessingState.idle;
}
if (nextIndex !== currentIndex) {
if (_this.props.onSelect) {
_this.props.onSelect(nextIndex);
}
_this.setState({
currentIndex: nextIndex,
previousIndex: currentIndex,
slideRight: !nextButtonClicked,
processingState: processingState
});
}
};
/**
* Returns next index after carousel button is clicked.
*/
_this.getNextIndex = function (nextButtonClicked) {
var currentIndex = _this.state.currentIndex;
var nextIndex = currentIndex;
var isInfinite = _this.props.isInfinite !== undefined ? _this.props.isInfinite : false;
var length = _this.props.element.length;
// Next Button clicked
if (nextButtonClicked) {
// If there is next element
if (currentIndex < length - 1) {
nextIndex = currentIndex + 1;
}
// In no more elements are available but it isInfiniteLoop -> reset index to the first element
else if (isInfinite) {
nextIndex = 0;
}
}
// Prev Button clicked
else {
if (currentIndex - 1 >= 0) {
// If there is previous element
nextIndex = currentIndex - 1;
}
else if (isInfinite) {
// If there is no previous element but isInfitineLoop -> reset index to the last element
nextIndex = length - 1;
}
}
return nextIndex;
};
/**
* Returns current element to be displayed.
*/
_this.getElementToDisplay = function (currentIndex) {
var element = _this.props.element;
var result = null;
var arrayLen;
// If no element has been provided.
if (!element) {
result = null;
}
else if ((0, common_1.isArray)(element) && (arrayLen = element.length) > 0) {
// Retrieve proper element from the array
if (currentIndex >= 0 && arrayLen > currentIndex) {
var arrayEl = element[currentIndex]; // eslint-disable-line @typescript-eslint/no-explicit-any
result = 'props' in arrayEl ? arrayEl :
React.createElement(CarouselImage_1.default, tslib_1.__assign({}, arrayEl));
}
}
else {
result = element;
}
return result;
};
_this.startCycle = function () {
var _a = _this.props, interval = _a.interval, triggerPageEvent = _a.triggerPageEvent;
if (_this._intervalId) {
if (triggerPageEvent) {
clearTimeout(_this._intervalId);
}
else {
clearInterval(_this._intervalId);
}
}
if (interval !== null) {
var intervalValue = interval || 5000;
if (!triggerPageEvent) {
_this._intervalId = window.setInterval(_this.moveNext, intervalValue);
}
else {
_this._intervalId = window.setTimeout(_this.moveNext, intervalValue);
}
}
};
_this.moveNext = function () {
if (!_this.isCarouselButtonDisabled(true)) {
_this.onCarouselButtonClicked(true);
}
else {
if (_this._intervalId) {
if (_this.props.triggerPageEvent) {
clearTimeout(_this._intervalId);
}
else {
clearInterval(_this._intervalId);
}
}
}
};
_this.pauseCycle = function () {
if (_this._intervalId) {
if (_this.props.triggerPageEvent) {
clearTimeout(_this._intervalId);
}
else {
clearInterval(_this._intervalId);
}
}
};
var currentIndex = props.startIndex ? props.startIndex : 0;
telemetry.track('ReactCarousel', {});
_this.state = {
currentIndex: currentIndex,
processingState: ICarouselState_1.ProcessingState.idle
};
return _this;
}
/**
* Handles component update lifecycle method.
* @param prevProps
*/
Carousel.prototype.componentDidUpdate = function (prevProps) {
var currProps = this.props;
var prevPropsElementKey = prevProps.triggerPageEvent && prevProps.element ? prevProps.element.key : null;
var nextPropsElementKey = currProps.triggerPageEvent && currProps.element ? currProps.element.key : null;
// Checking if component is in processing state and the key of the current element has been changed
if (this.state.processingState === ICarouselState_1.ProcessingState.processing && nextPropsElementKey !== null && prevPropsElementKey !== nextPropsElementKey) {
this.setState({
processingState: ICarouselState_1.ProcessingState.idle
});
this.startCycle(); // restarting cycle when new slide is available
}
};
Carousel.prototype.componentDidMount = function () {
// starting auto cycling
this.startCycle();
};
Carousel.prototype.render = function () {
var _this = this;
var _a = this.state, currentIndex = _a.currentIndex, processingState = _a.processingState;
var _b = this.props, containerStyles = _b.containerStyles, contentContainerStyles = _b.contentContainerStyles, containerButtonsStyles = _b.containerButtonsStyles, prevButtonStyles = _b.prevButtonStyles, nextButtonStyles = _b.nextButtonStyles, loadingComponentContainerStyles = _b.loadingComponentContainerStyles, _c = _b.prevButtonIconName, prevButtonIconName = _c === void 0 ? 'ChevronLeft' : _c, _d = _b.nextButtonIconName, nextButtonIconName = _d === void 0 ? 'ChevronRight' : _d, _e = _b.prevButtonAriaLabel, prevButtonAriaLabel = _e === void 0 ? 'Previous item' : _e, _f = _b.nextButtonAriaLabel, nextButtonAriaLabel = _f === void 0 ? 'Next item' : _f, _g = _b.loadingComponent, loadingComponent = _g === void 0 ? React.createElement(Spinner_1.Spinner, null) : _g, pauseOnHover = _b.pauseOnHover, interval = _b.interval, indicatorsDisplay = _b.indicatorsDisplay, rootStyles = _b.rootStyles, indicatorsContainerStyles = _b.indicatorsContainerStyles, contentHeight = _b.contentHeight;
var processing = processingState === ICarouselState_1.ProcessingState.processing;
var prevButtonDisabled = processing || this.isCarouselButtonDisabled(false);
var nextButtonDisabled = processing || this.isCarouselButtonDisabled(true);
var element = this.getElementToDisplay(currentIndex);
var contentContainerCustomClassName = undefined;
if (contentContainerStyles) {
contentContainerCustomClassName = contentContainerStyles;
}
else if (contentHeight) {
contentContainerCustomClassName = (0, Styling_1.mergeStyles)({
height: "".concat(contentHeight, "px")
});
}
return (React.createElement("div", { className: this.getMergedStyles(Carousel_module_scss_1.default.root, rootStyles) },
React.createElement("div", { className: this.getMergedStyles(Carousel_module_scss_1.default.container, containerStyles) },
React.createElement("div", { className: this.getMergedStyles(this.getButtonContainerStyles(), containerButtonsStyles), onClick: function () { if (!prevButtonDisabled) {
_this.onCarouselButtonClicked(false);
} } },
React.createElement(Button_1.IconButton, { ariaLabel: prevButtonAriaLabel, className: this.getMergedStyles(this.getButtonStyles(false), prevButtonStyles), iconProps: { iconName: prevButtonIconName }, disabled: prevButtonDisabled, onClick: function () { _this.onCarouselButtonClicked(false); } })),
React.createElement("div", { className: this.getMergedStyles(Carousel_module_scss_1.default.contentContainer, contentContainerCustomClassName), onMouseOver: pauseOnHover && interval !== null ? this.pauseCycle : undefined, onTouchStart: pauseOnHover && interval !== null ? this.pauseCycle : undefined, onMouseLeave: pauseOnHover && interval !== null ? this.startCycle : undefined, onTouchEnd: pauseOnHover && interval !== null ? this.startCycle : undefined },
processing &&
React.createElement("div", { className: this.getMergedStyles(Carousel_module_scss_1.default.loadingComponent, loadingComponentContainerStyles) }, loadingComponent),
!processing && this.renderSlide(element),
indicatorsDisplay !== ICarouselProps_2.CarouselIndicatorsDisplay.block && this.getIndicatorsElement()),
React.createElement("div", { className: this.getMergedStyles(this.getButtonContainerStyles(), containerButtonsStyles), onClick: function () { if (!nextButtonDisabled) {
_this.onCarouselButtonClicked(true);
} } },
React.createElement(Button_1.IconButton, { ariaLabel: nextButtonAriaLabel, className: this.getMergedStyles(this.getButtonStyles(true), nextButtonStyles), iconProps: { iconName: nextButtonIconName }, disabled: nextButtonDisabled, onClick: function () { _this.onCarouselButtonClicked(true); } }))),
indicatorsDisplay === ICarouselProps_2.CarouselIndicatorsDisplay.block &&
React.createElement("div", { className: this.getMergedStyles(Carousel_module_scss_1.default.indicatorsContainer, indicatorsContainerStyles) }, this.getIndicatorsElement())));
};
/**
* Return merged styles for Button containers.
*/
Carousel.prototype.getButtonContainerStyles = function () {
var buttonsDisplayMode = this.props.buttonsDisplay ? this.props.buttonsDisplay : ICarouselProps_1.CarouselButtonsDisplay.block;
var buttonDisplayModeCss = "";
switch (buttonsDisplayMode) {
case ICarouselProps_1.CarouselButtonsDisplay.block:
buttonDisplayModeCss = Carousel_module_scss_1.default.blockButtonsContainer;
break;
case ICarouselProps_1.CarouselButtonsDisplay.buttonsOnly:
buttonDisplayModeCss = Carousel_module_scss_1.default.buttonsOnlyContainer;
break;
case ICarouselProps_1.CarouselButtonsDisplay.hidden:
buttonDisplayModeCss = Carousel_module_scss_1.default.hiddenButtonsContainer;
break;
default:
return "";
}
var buttonsLocation = this.props.buttonsLocation ? this.props.buttonsLocation : ICarouselProps_1.CarouselButtonsLocation.center;
var buttonsLocationCss = "";
switch (buttonsLocation) {
case ICarouselProps_1.CarouselButtonsLocation.top:
buttonsLocationCss = Carousel_module_scss_1.default.blockButtonsContainer;
break;
case ICarouselProps_1.CarouselButtonsLocation.center:
buttonsLocationCss = Carousel_module_scss_1.default.centralButtonsContainer;
break;
case ICarouselProps_1.CarouselButtonsLocation.bottom:
buttonsLocationCss = Carousel_module_scss_1.default.bottomButtonsContainer;
break;
default:
return "";
}
var result = (0, lib_1.css)(buttonDisplayModeCss, buttonsLocationCss);
return result;
};
/**
* Return merged styles for Buttons.
* @param nextButton
*/
Carousel.prototype.getButtonStyles = function (nextButton) {
var buttonsDisplayMode = this.props.buttonsDisplay ? this.props.buttonsDisplay : ICarouselProps_1.CarouselButtonsDisplay.block;
var result = "";
if (buttonsDisplayMode === ICarouselProps_1.CarouselButtonsDisplay.buttonsOnly) {
result = nextButton ? Carousel_module_scss_1.default.buttonsOnlyNextButton : Carousel_module_scss_1.default.buttonsOnlyPrevButton;
}
return (0, lib_1.css)(result);
};
return Carousel;
}(React.Component));
exports.Carousel = Carousel;
//# sourceMappingURL=Carousel.js.map