UNPKG

react-fex-gallery

Version:

React gallery powered by FEX.net API

1,351 lines (1,135 loc) 360 kB
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var React = require('react'); var React__default = _interopDefault(React); var styled = require('styled-components'); var styled__default = _interopDefault(styled); 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 _taggedTemplateLiteralLoose(strings, raw) { if (!raw) { raw = strings.slice(0); } strings.raw = raw; return strings; } // A type of promise-like that resolves synchronously and supports only one observer const _iteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator"))) : "@@iterator"; const _asyncIteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.asyncIterator || (Symbol.asyncIterator = Symbol("Symbol.asyncIterator"))) : "@@asyncIterator"; // Asynchronously call a function and send errors to recovery continuation function _catch(body, recover) { try { var result = body(); } catch(e) { return recover(e); } if (result && result.then) { return result.then(void 0, recover); } return result; } // Asynchronously await a promise and pass the result to a finally continuation function _finallyRethrows(body, finalizer) { try { var result = body(); } catch (e) { return finalizer(true, e); } if (result && result.then) { return result.then(finalizer.bind(null, false), finalizer.bind(null, true)); } return finalizer(false, result); } var fetchData = function fetchData(_ref) { var _ref$method = _ref.method, method = _ref$method === void 0 ? 'GET' : _ref$method, _ref$data = _ref.data, data = _ref$data === void 0 ? {} : _ref$data, url = _ref.url; try { var init = { method: method, mode: 'cors', cache: 'no-cache', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, redirect: 'follow', referrerPolicy: 'no-referrer' }; if (method !== 'GET') { init = _extends({}, init, { body: JSON.stringify(data) }); } return Promise.resolve(_catch(function () { return Promise.resolve(fetch(url, init)).then(function (response) { return Promise.resolve(response.json()); }); }, function (e) { throw e; })); } catch (e) { return Promise.reject(e); } }; var defaultContentText = { highlighted: 'Выделено', clearHighlighted: 'Снять выделение', pluralize: { image: { one: 'изображение', two: 'изображения', five: 'изображений' } }, showHighlighted: 'Показать выделенные', showAll: 'Показать все', show: 'Показать', download: 'Скачать', copy: 'Копировать', print: 'Распечатать', fileInfo: 'Информация о файле', "delete": 'Удалить', search: 'Поиск', close: 'Закрыть', highlightedSearch: 'Поиск по выделенным', loadingImages: 'Загрузка изображений...', fileProperties: 'Свойства файла', size: 'Размер', created: 'Создан', fileExtension: 'Формат файла' }; var initialState = { currentIndex: 0, images: [], showInfo: false, view: 'gallery', imagesCount: 0, selectedImages: [], contentText: defaultContentText, accessRights: 'read', folderName: '', methods: {}, searchQuery: '' }; var toggleSelectedImage = function toggleSelectedImage(selectedImages, image, allImages) { var exist = selectedImages.find(function (i) { return i.id === image.id; }); if (exist) { return selectedImages.filter(function (i) { return i.id !== image.id; }); } return [].concat(selectedImages, [image]).sort(function (a, b) { return allImages.indexOf(a) - allImages.indexOf(b); }); }; var reducer = function reducer(state, action) { switch (action.type) { case 'reset-gallery': return initialState; case 'unselect-all': return _extends({}, state, { selectedImages: [], showOnlySelected: false }); case 'switch-show-info': return _extends({}, state, { showInfo: !state.showInfo, infoForImage: action.infoForImage }); case 'change-show-info': return _extends({}, state, { showInfo: action.showInfo, infoForImage: action.infoForImage }); case 'switch-view': return _extends({}, state, { prevView: state.view, view: action.view }); case 'append-images': return _extends({}, state, { images: [].concat(state.images, action.images) }); case 'set-images': return _extends({}, state, { images: [].concat(action.images) }); case 'toggle-selected-item': return _extends({}, state, { selectedImages: toggleSelectedImage(state.selectedImages, action.image, state.images) }); case 'toggle-show-only-selected': return _extends({}, state, { showOnlySelected: !state.showOnlySelected }); case 'set-search-image-query': return _extends({}, state, { searchQuery: action.query }); case 'clear-search-image-query': return _extends({}, state, { searchQuery: '' }); case 'set-current-index': return _extends({}, state, { currentIndex: action.index <= state.imagesCount - 1 ? action.index : 0 }); case 'append-response': return _extends({}, state, { apiEndpointPagination: action.pagination, images: [].concat(state.images, action.images), apiEndpoint: action.endPoint, currentIndex: action.setNextIndex ? state.currentIndex + 1 : action.setLastIndex ? [].concat(state.images, action.images).length - 1 : state.currentIndex }); case 'show-notifier': return _extends({}, state, { notifier: action.message }); case 'clear-notifier': return _extends({}, state, { notifier: undefined }); case 'after-delete-images': { return _extends({}, state, { currentIndex: action.newIndex ? action.newIndex : state.currentIndex, imagesCount: action.count ? action.count : state.imagesCount, images: action.images ? action.images : state.images }); } case 'set-images-count': { return _extends({}, state, { imagesCount: action.imagesCount, currentIndex: state.currentIndex <= action.imagesCount - 1 ? state.currentIndex : 0 }); } } return state; }; var useStore = function useStore(_state) { var _useReducer = React.useReducer(reducer, _extends({}, initialState, _state)), state = _useReducer[0], dispatch = _useReducer[1]; var withMiddleware = function withMiddleware(dispatch) { return function (action) { try { var _temp5 = function _temp5(_result3) { if (_exit2) return _result3; if (action.type === 'after-delete-images') { dispatch({ type: 'unselect-all' }); } }; var _exit2 = false; dispatch(action); if (action.type === 'toggle-selected-item') { if (state.showOnlySelected && state.selectedImages.length <= 1) { dispatch({ type: 'unselect-all' }); } if (state.view === 'grid' && state.selectedImages.length === 1 && state.selectedImages.find(function (i) { return i.id === action.image.id; })) { dispatch({ type: 'change-show-info', showInfo: false }); } } if (action.type === 'unselect-all') { if (state.view === 'grid' && state.showInfo) { dispatch({ type: 'change-show-info', showInfo: false }); } } var _temp6 = function () { if (action.type === 'fetch-more-images') { return function () { if (state.apiEndpoint) { return _finallyRethrows(function () { return _catch(function () { var _state$apiEndpointPag; function _temp2() { anchor.remove(); } var anchor = document.createElement('a'); anchor.href = state.apiEndpoint; var search = new URLSearchParams(anchor.search); if (((_state$apiEndpointPag = state.apiEndpointPagination) === null || _state$apiEndpointPag === void 0 ? void 0 : _state$apiEndpointPag.pages.toString()) === search.get('page') || window.FEX_GALLERY_QUEUE_BUSY) { _exit2 = true; return; } window.FEX_GALLERY_QUEUE_BUSY = true; dispatch({ type: 'show-notifier', message: state.contentText.loadingImages }); var _temp = function () { var _state$apiEndpointPag2; if (action.fetchAll && ((_state$apiEndpointPag2 = state.apiEndpointPagination) === null || _state$apiEndpointPag2 === void 0 ? void 0 : _state$apiEndpointPag2.pages)) { var currentPage = parseInt(!!search.get('page') ? search.get('page') : '1'); var array = []; for (var i = currentPage + 1; i <= state.apiEndpointPagination.pages; i++) { search.set('page', i.toString()); anchor.search = '?' + search; array.push(anchor.href); } return Promise.resolve(Promise.all([].concat(array.map(function (i) { return fetchData({ url: i }); })))).then(function (promises) { var images = []; var pagination = { count: 0, page: 0, pages: 0, per_page: 0 }; promises.forEach(function (promise, index) { if (index === promises.length - 1) { pagination = promise.pagination; } images = [].concat(images, promise.children); }); if (promises.length) { dispatch({ type: 'append-response', images: images, pagination: pagination, endPoint: anchor.href, setLastIndex: true }); } }); } else { search.forEach(function (value, key) { if (key === 'page') { search.set('page', (parseInt(value) + 1).toString()); } }); anchor.search = '?' + search; return Promise.resolve(fetchData({ url: anchor.href })).then(function (response) { if (response) { dispatch({ type: 'append-response', images: response.children, pagination: response.pagination, endPoint: anchor.href, setNextIndex: action.setNextIndex }); } }); } }(); return _temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp); }, function (e) { console.error(e); }); }, function (_wasThrown, _result) { dispatch({ type: 'clear-notifier' }); window.FEX_GALLERY_QUEUE_BUSY = false; if (_wasThrown) throw _result; return _result; }); } else { if (state.methods.onReachEnd) { if (!window.FEX_GALLERY_QUEUE_BUSY) { var _state$methods$onReac, _state$methods; window.FEX_GALLERY_QUEUE_BUSY = true; dispatch({ type: 'show-notifier', message: state.contentText.loadingImages }); (_state$methods$onReac = (_state$methods = state.methods).onReachEnd) === null || _state$methods$onReac === void 0 ? void 0 : _state$methods$onReac.call(_state$methods, action.fetchAll).then(function (images) { if (images) { dispatch({ type: 'set-images', images: images }); if (action.fetchAll) { dispatch({ type: 'set-current-index', index: images.length - 1 }); } } })["finally"](function () { dispatch({ type: 'clear-notifier' }); window.FEX_GALLERY_QUEUE_BUSY = false; }); } } } }(); } }(); return Promise.resolve(_temp6 && _temp6.then ? _temp6.then(_temp5) : _temp5(_temp6)); } catch (e) { return Promise.reject(e); } }; }; return [state, withMiddleware(dispatch)]; }; var AppContext = React__default.createContext({ state: initialState, dispatch: {} }); var useAppContext = function useAppContext() { var _useContext = React.useContext(AppContext), state = _useContext.state, dispatch = _useContext.dispatch; return { state: state, dispatch: dispatch }; }; function _templateObject4() { var data = _taggedTemplateLiteralLoose(["\n width: 100vw;\n height: 100vh;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n position: fixed;\n z-index: 99;\n display: flex;\n align-items: center;\n justify-content: center;\n"]); _templateObject4 = function _templateObject4() { return data; }; return data; } function _templateObject3() { var data = _taggedTemplateLiteralLoose(["\n color: #1facf7;\n font-size: 90px;\n text-indent: -9999em;\n overflow: hidden;\n width: 1em;\n height: 1em;\n border-radius: 50%;\n margin: 72px auto;\n position: relative;\n -webkit-transform: translateZ(0);\n -ms-transform: translateZ(0);\n transform: translateZ(0);\n animation: ", " 1.7s infinite ease, ", " 1.7s infinite ease;\n"]); _templateObject3 = function _templateObject3() { return data; }; return data; } function _templateObject2() { var data = _taggedTemplateLiteralLoose(["\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n"]); _templateObject2 = function _templateObject2() { return data; }; return data; } function _templateObject() { var data = _taggedTemplateLiteralLoose(["\n 0% {\n box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;\n }\n 5%,\n 95% {\n box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;\n }\n 10%,\n 59% {\n box-shadow: 0 -0.83em 0 -0.4em, -0.087em -0.825em 0 -0.42em, -0.173em -0.812em 0 -0.44em, -0.256em -0.789em 0 -0.46em, -0.297em -0.775em 0 -0.477em;\n }\n 20% {\n box-shadow: 0 -0.83em 0 -0.4em, -0.338em -0.758em 0 -0.42em, -0.555em -0.617em 0 -0.44em, -0.671em -0.488em 0 -0.46em, -0.749em -0.34em 0 -0.477em;\n }\n 38% {\n box-shadow: 0 -0.83em 0 -0.4em, -0.377em -0.74em 0 -0.42em, -0.645em -0.522em 0 -0.44em, -0.775em -0.297em 0 -0.46em, -0.82em -0.09em 0 -0.477em;\n }\n 100% {\n box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;\n }\n"]); _templateObject = function _templateObject() { return data; }; return data; } var load6 = styled.keyframes(_templateObject()); var round = styled.keyframes(_templateObject2()); var Loader = styled__default.div(_templateObject3(), load6, round); var FullscreenLoaderWrapper = styled__default.div(_templateObject4()); function _templateObject13() { var data = _taggedTemplateLiteralLoose(["\n padding-right: 32px;\n padding-left: 0;\n justify-content: flex-end;\n"]); _templateObject13 = function _templateObject13() { return data; }; return data; } function _templateObject12() { var data = _taggedTemplateLiteralLoose(["\n width: 50%;\n height: 100%;\n cursor: pointer;\n display: flex;\n align-items: center;\n padding-left: 32px;\n justify-content: flex-start;\n\n svg {\n transition: fill .225s;\n fill: rgba(255, 255, 255, .25);\n }\n\n &:hover {\n svg {\n fill: #fff;\n }\n }\n"]); _templateObject12 = function _templateObject12() { return data; }; return data; } function _templateObject11() { var data = _taggedTemplateLiteralLoose(["\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n z-index: 2;\n"]); _templateObject11 = function _templateObject11() { return data; }; return data; } function _templateObject10() { var data = _taggedTemplateLiteralLoose(["\n max-height: 90px;\n max-width: 768px;\n width: 100%;\n margin: 0 auto;\n overflow: hidden;\n position: relative;\n z-index: 2;\n"]); _templateObject10 = function _templateObject10() { return data; }; return data; } function _templateObject9() { var data = _taggedTemplateLiteralLoose(["\n height: 104px;\n min-height: 104px;\n position: relative;\n"]); _templateObject9 = function _templateObject9() { return data; }; return data; } function _templateObject8() { var data = _taggedTemplateLiteralLoose(["\n padding: 12px 16px;\n font-size: 13px;\n line-height: 16px;\n color: #828282;\n text-align: center;\n position: relative;\n transform: translateY(10px);\n"]); _templateObject8 = function _templateObject8() { return data; }; return data; } function _templateObject7() { var data = _taggedTemplateLiteralLoose(["\n padding: ", ";\n height: ", ";\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n\n img {\n max-width: 100%;\n max-height: 100%;\n width: auto;\n height: auto;\n display: block;\n margin: auto;\n position: relative;\n z-index: 1;\n opacity: 0;\n animation: ", " .35s ease-out forwards;\n user-select: none;\n\n &.next {\n animation-name: ", ";\n }\n\n &.prev {\n animation-name: ", ";\n }\n }\n\n ", " {\n position: absolute;\n }\n"]); _templateObject7 = function _templateObject7() { return data; }; return data; } function _templateObject6() { var data = _taggedTemplateLiteralLoose(["\n max-height: 90px;\n max-width: 768px;\n width: 100%;\n margin: 0 auto;\n overflow: hidden;\n position: relative;\n z-index: 2;\n"]); _templateObject6 = function _templateObject6() { return data; }; return data; } function _templateObject5() { var data = _taggedTemplateLiteralLoose(["\n height: calc(100% - 104px);\n position: relative;\n display: flex;\n flex-direction: column;\n"]); _templateObject5 = function _templateObject5() { return data; }; return data; } function _templateObject4$1() { var data = _taggedTemplateLiteralLoose(["\n height: 100%;\n display: flex;\n flex-direction: column;\n"]); _templateObject4$1 = function _templateObject4() { return data; }; return data; } function _templateObject3$1() { var data = _taggedTemplateLiteralLoose(["\n 0% {\n transform: translateX(-20px);\n opacity: .5;\n }\n\n 100% {\n transform: none;\n opacity: 1;\n }\n"]); _templateObject3$1 = function _templateObject3() { return data; }; return data; } function _templateObject2$1() { var data = _taggedTemplateLiteralLoose(["\n 0% {\n transform: scale(.9);\n opacity: .5;\n }\n\n 100% {\n transform: none;\n opacity: 1;\n }\n"]); _templateObject2$1 = function _templateObject2() { return data; }; return data; } function _templateObject$1() { var data = _taggedTemplateLiteralLoose(["\n 0% {\n transform: translateX(20px);\n opacity: .5;\n }\n\n 100% {\n transform: none;\n opacity: 1;\n }\n"]); _templateObject$1 = function _templateObject() { return data; }; return data; } var slideImageNext = styled.keyframes(_templateObject$1()); var slideImageFirst = styled.keyframes(_templateObject2$1()); var slideImagePrev = styled.keyframes(_templateObject3$1()); var GalleryStyled = styled__default.div(_templateObject4$1()); var GalleryTop = styled__default.div(_templateObject5()); var GalleryTopPromo = styled__default.div(_templateObject6()); var GalleryImageHolder = styled__default.div(_templateObject7(), function (_ref) { var additionalHeight = _ref.additionalHeight; return additionalHeight > 0 ? '12px 80px' : '24px 80px 6px'; }, function (_ref2) { var additionalHeight = _ref2.additionalHeight; return "calc(100% - " + (40 + additionalHeight) + "px)"; }, slideImageFirst, slideImageNext, slideImagePrev, Loader); var GalleryImageName = styled__default.div(_templateObject8()); var GalleryBottom = styled__default.div(_templateObject9()); var GalleryBottomPromo = styled__default.div(_templateObject10()); var GalleryTopDirectionWrapper = styled__default.div(_templateObject11()); var GalleryTopDirection = styled__default.div(_templateObject12()); var GalleryTopDirectionOpposite = styled__default(GalleryTopDirection)(_templateObject13()); function _extends$1() { _extends$1 = 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$1.apply(this, arguments); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function areInputsEqual(newInputs, lastInputs) { if (newInputs.length !== lastInputs.length) { return false; } for (var i = 0; i < newInputs.length; i++) { if (newInputs[i] !== lastInputs[i]) { return false; } } return true; } function memoizeOne(resultFn, isEqual) { if (isEqual === void 0) { isEqual = areInputsEqual; } var lastThis; var lastArgs = []; var lastResult; var calledOnce = false; function memoized() { var newArgs = []; for (var _i = 0; _i < arguments.length; _i++) { newArgs[_i] = arguments[_i]; } if (calledOnce && lastThis === this && isEqual(newArgs, lastArgs)) { return lastResult; } lastResult = resultFn.apply(this, newArgs); calledOnce = true; lastThis = this; lastArgs = newArgs; return lastResult; } return memoized; } // Animation frame based implementation of setTimeout. // Inspired by Joe Lambert, https://gist.github.com/joelambert/1002116#file-requesttimeout-js var hasNativePerformanceNow = typeof performance === 'object' && typeof performance.now === 'function'; var now = hasNativePerformanceNow ? function () { return performance.now(); } : function () { return Date.now(); }; function cancelTimeout(timeoutID) { cancelAnimationFrame(timeoutID.id); } function requestTimeout(callback, delay) { var start = now(); function tick() { if (now() - start >= delay) { callback.call(null); } else { timeoutID.id = requestAnimationFrame(tick); } } var timeoutID = { id: requestAnimationFrame(tick) }; return timeoutID; } var size = -1; // This utility copied from "dom-helpers" package. function getScrollbarSize(recalculate) { if (recalculate === void 0) { recalculate = false; } if (size === -1 || recalculate) { var div = document.createElement('div'); var style = div.style; style.width = '50px'; style.height = '50px'; style.overflow = 'scroll'; document.body.appendChild(div); size = div.offsetWidth - div.clientWidth; document.body.removeChild(div); } return size; } var cachedRTLResult = null; // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements. // Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left). // Safari's elastic bounce makes detecting this even more complicated wrt potential false positives. // The safest way to check this is to intentionally set a negative offset, // and then verify that the subsequent "scroll" event matches the negative offset. // If it does not match, then we can assume a non-standard RTL scroll implementation. function getRTLOffsetType(recalculate) { if (recalculate === void 0) { recalculate = false; } if (cachedRTLResult === null || recalculate) { var outerDiv = document.createElement('div'); var outerStyle = outerDiv.style; outerStyle.width = '50px'; outerStyle.height = '50px'; outerStyle.overflow = 'scroll'; outerStyle.direction = 'rtl'; var innerDiv = document.createElement('div'); var innerStyle = innerDiv.style; innerStyle.width = '100px'; innerStyle.height = '100px'; outerDiv.appendChild(innerDiv); document.body.appendChild(outerDiv); if (outerDiv.scrollLeft > 0) { cachedRTLResult = 'positive-descending'; } else { outerDiv.scrollLeft = 1; if (outerDiv.scrollLeft === 0) { cachedRTLResult = 'negative'; } else { cachedRTLResult = 'positive-ascending'; } } document.body.removeChild(outerDiv); return cachedRTLResult; } return cachedRTLResult; } var IS_SCROLLING_DEBOUNCE_INTERVAL = 150; var defaultItemKey = function defaultItemKey(_ref) { var columnIndex = _ref.columnIndex, rowIndex = _ref.rowIndex; return rowIndex + ":" + columnIndex; }; // In DEV mode, this Set helps us only log a warning once per component instance. // This avoids spamming the console every time a render happens. var devWarningsOverscanCount = null; var devWarningsOverscanRowsColumnsCount = null; var devWarningsTagName = null; if (process.env.NODE_ENV !== 'production') { if (typeof window !== 'undefined' && typeof window.WeakSet !== 'undefined') { devWarningsOverscanCount = /*#__PURE__*/ new WeakSet(); devWarningsOverscanRowsColumnsCount = /*#__PURE__*/ new WeakSet(); devWarningsTagName = /*#__PURE__*/ new WeakSet(); } } function createGridComponent(_ref2) { var _class, _temp; var getColumnOffset = _ref2.getColumnOffset, getColumnStartIndexForOffset = _ref2.getColumnStartIndexForOffset, getColumnStopIndexForStartIndex = _ref2.getColumnStopIndexForStartIndex, getColumnWidth = _ref2.getColumnWidth, getEstimatedTotalHeight = _ref2.getEstimatedTotalHeight, getEstimatedTotalWidth = _ref2.getEstimatedTotalWidth, getOffsetForColumnAndAlignment = _ref2.getOffsetForColumnAndAlignment, getOffsetForRowAndAlignment = _ref2.getOffsetForRowAndAlignment, getRowHeight = _ref2.getRowHeight, getRowOffset = _ref2.getRowOffset, getRowStartIndexForOffset = _ref2.getRowStartIndexForOffset, getRowStopIndexForStartIndex = _ref2.getRowStopIndexForStartIndex, initInstanceProps = _ref2.initInstanceProps, shouldResetStyleCacheOnItemSizeChange = _ref2.shouldResetStyleCacheOnItemSizeChange, validateProps = _ref2.validateProps; return _temp = _class = /*#__PURE__*/ function (_PureComponent) { _inheritsLoose(Grid, _PureComponent); // Always use explicit constructor for React components. // It produces less code after transpilation. (#26) // eslint-disable-next-line no-useless-constructor function Grid(props) { var _this; _this = _PureComponent.call(this, props) || this; _this._instanceProps = initInstanceProps(_this.props, _assertThisInitialized(_assertThisInitialized(_this))); _this._resetIsScrollingTimeoutId = null; _this._outerRef = void 0; _this.state = { instance: _assertThisInitialized(_assertThisInitialized(_this)), isScrolling: false, horizontalScrollDirection: 'forward', scrollLeft: typeof _this.props.initialScrollLeft === 'number' ? _this.props.initialScrollLeft : 0, scrollTop: typeof _this.props.initialScrollTop === 'number' ? _this.props.initialScrollTop : 0, scrollUpdateWasRequested: false, verticalScrollDirection: 'forward' }; _this._callOnItemsRendered = void 0; _this._callOnItemsRendered = memoizeOne(function (overscanColumnStartIndex, overscanColumnStopIndex, overscanRowStartIndex, overscanRowStopIndex, visibleColumnStartIndex, visibleColumnStopIndex, visibleRowStartIndex, visibleRowStopIndex) { return _this.props.onItemsRendered({ overscanColumnStartIndex: overscanColumnStartIndex, overscanColumnStopIndex: overscanColumnStopIndex, overscanRowStartIndex: overscanRowStartIndex, overscanRowStopIndex: overscanRowStopIndex, visibleColumnStartIndex: visibleColumnStartIndex, visibleColumnStopIndex: visibleColumnStopIndex, visibleRowStartIndex: visibleRowStartIndex, visibleRowStopIndex: visibleRowStopIndex }); }); _this._callOnScroll = void 0; _this._callOnScroll = memoizeOne(function (scrollLeft, scrollTop, horizontalScrollDirection, verticalScrollDirection, scrollUpdateWasRequested) { return _this.props.onScroll({ horizontalScrollDirection: horizontalScrollDirection, scrollLeft: scrollLeft, scrollTop: scrollTop, verticalScrollDirection: verticalScrollDirection, scrollUpdateWasRequested: scrollUpdateWasRequested }); }); _this._getItemStyle = void 0; _this._getItemStyle = function (rowIndex, columnIndex) { var _this$props = _this.props, columnWidth = _this$props.columnWidth, direction = _this$props.direction, rowHeight = _this$props.rowHeight; var itemStyleCache = _this._getItemStyleCache(shouldResetStyleCacheOnItemSizeChange && columnWidth, shouldResetStyleCacheOnItemSizeChange && direction, shouldResetStyleCacheOnItemSizeChange && rowHeight); var key = rowIndex + ":" + columnIndex; var style; if (itemStyleCache.hasOwnProperty(key)) { style = itemStyleCache[key]; } else { var _style; itemStyleCache[key] = style = (_style = { position: 'absolute' }, _style[direction === 'rtl' ? 'right' : 'left'] = getColumnOffset(_this.props, columnIndex, _this._instanceProps), _style.top = getRowOffset(_this.props, rowIndex, _this._instanceProps), _style.height = getRowHeight(_this.props, rowIndex, _this._instanceProps), _style.width = getColumnWidth(_this.props, columnIndex, _this._instanceProps), _style); } return style; }; _this._getItemStyleCache = void 0; _this._getItemStyleCache = memoizeOne(function (_, __, ___) { return {}; }); _this._onScroll = function (event) { var _event$currentTarget = event.currentTarget, clientHeight = _event$currentTarget.clientHeight, clientWidth = _event$currentTarget.clientWidth, scrollLeft = _event$currentTarget.scrollLeft, scrollTop = _event$currentTarget.scrollTop, scrollHeight = _event$currentTarget.scrollHeight, scrollWidth = _event$currentTarget.scrollWidth; _this.setState(function (prevState) { if (prevState.scrollLeft === scrollLeft && prevState.scrollTop === scrollTop) { // Scroll position may have been updated by cDM/cDU, // In which case we don't need to trigger another render, // And we don't want to update state.isScrolling. return null; } var direction = _this.props.direction; // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements. // This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left). // It's also easier for this component if we convert offsets to the same format as they would be in for ltr. // So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it. var calculatedScrollLeft = scrollLeft; if (direction === 'rtl') { switch (getRTLOffsetType()) { case 'negative': calculatedScrollLeft = -scrollLeft; break; case 'positive-descending': calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft; break; } } // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds. calculatedScrollLeft = Math.max(0, Math.min(calculatedScrollLeft, scrollWidth - clientWidth)); var calculatedScrollTop = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight)); return { isScrolling: true, horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward', scrollLeft: calculatedScrollLeft, scrollTop: calculatedScrollTop, verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward', scrollUpdateWasRequested: false }; }, _this._resetIsScrollingDebounced); }; _this._outerRefSetter = function (ref) { var outerRef = _this.props.outerRef; _this._outerRef = ref; if (typeof outerRef === 'function') { outerRef(ref); } else if (outerRef != null && typeof outerRef === 'object' && outerRef.hasOwnProperty('current')) { outerRef.current = ref; } }; _this._resetIsScrollingDebounced = function () { if (_this._resetIsScrollingTimeoutId !== null) { cancelTimeout(_this._resetIsScrollingTimeoutId); } _this._resetIsScrollingTimeoutId = requestTimeout(_this._resetIsScrolling, IS_SCROLLING_DEBOUNCE_INTERVAL); }; _this._resetIsScrolling = function () { _this._resetIsScrollingTimeoutId = null; _this.setState({ isScrolling: false }, function () { // Clear style cache after state update has been committed. // This way we don't break pure sCU for items that don't use isScrolling param. _this._getItemStyleCache(-1); }); }; return _this; } Grid.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) { validateSharedProps(nextProps, prevState); validateProps(nextProps); return null; }; var _proto = Grid.prototype; _proto.scrollTo = function scrollTo(_ref3) { var scrollLeft = _ref3.scrollLeft, scrollTop = _ref3.scrollTop; if (scrollLeft !== undefined) { scrollLeft = Math.max(0, scrollLeft); } if (scrollTop !== undefined) { scrollTop = Math.max(0, scrollTop); } this.setState(function (prevState) { if (scrollLeft === undefined) { scrollLeft = prevState.scrollLeft; } if (scrollTop === undefined) { scrollTop = prevState.scrollTop; } if (prevState.scrollLeft === scrollLeft && prevState.scrollTop === scrollTop) { return null; } return { horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward', scrollLeft: scrollLeft, scrollTop: scrollTop, scrollUpdateWasRequested: true, verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward' }; }, this._resetIsScrollingDebounced); }; _proto.scrollToItem = function scrollToItem(_ref4) { var _ref4$align = _ref4.align, align = _ref4$align === void 0 ? 'auto' : _ref4$align, columnIndex = _ref4.columnIndex, rowIndex = _ref4.rowIndex; var _this$props2 = this.props, columnCount = _this$props2.columnCount, height = _this$props2.height, rowCount = _this$props2.rowCount, width = _this$props2.width; var _this$state = this.state, scrollLeft = _this$state.scrollLeft, scrollTop = _this$state.scrollTop; var scrollbarSize = getScrollbarSize(); if (columnIndex !== undefined) { columnIndex = Math.max(0, Math.min(columnIndex, columnCount - 1)); } if (rowIndex !== undefined) { rowIndex = Math.max(0, Math.min(rowIndex, rowCount - 1)); } var estimatedTotalHeight = getEstimatedTotalHeight(this.props, this._instanceProps); var estimatedTotalWidth = getEstimatedTotalWidth(this.props, this._instanceProps); // The scrollbar size should be considered when scrolling an item into view, // to ensure it's fully visible. // But we only need to account for its size when it's actually visible. var horizontalScrollbarSize = estimatedTotalWidth > width ? scrollbarSize : 0; var verticalScrollbarSize = estimatedTotalHeight > height ? scrollbarSize : 0; this.scrollTo({ scrollLeft: columnIndex !== undefined ? getOffsetForColumnAndAlignment(this.props, columnIndex, align, scrollLeft, this._instanceProps, verticalScrollbarSize) : scrollLeft, scrollTop: rowIndex !== undefined ? getOffsetForRowAndAlignment(this.props, rowIndex, align, scrollTop, this._instanceProps, horizontalScrollbarSize) : scrollTop }); }; _proto.componentDidMount = function componentDidMount() { var _this$props3 = this.props, initialScrollLeft = _this$props3.initialScrollLeft, initialScrollTop = _this$props3.initialScrollTop; if (this._outerRef != null) { var outerRef = this._outerRef; if (typeof initialScrollLeft === 'number') { outerRef.scrollLeft = initialScrollLeft; } if (typeof initialScrollTop === 'number') { outerRef.scrollTop = initialScrollTop; } } this._callPropsCallbacks(); }; _proto.componentDidUpdate = function componentDidUpdate() { var direction = this.props.direction; var _this$state2 = this.state, scrollLeft = _this$state2.scrollLeft, scrollTop = _this$state2.scrollTop, scrollUpdateWasRequested = _this$state2.scrollUpdateWasRequested; if (scrollUpdateWasRequested && this._outerRef != null) { // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements. // This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left). // So we need to determine which browser behavior we're dealing with, and mimic it. var outerRef = this._outerRef; if (direction === 'rtl') { switch (getRTLOffsetType()) { case 'negative': outerRef.scrollLeft = -scrollLeft; break; case 'positive-ascending': outerRef.scrollLeft = scrollLeft; break; default: var clientWidth = outerRef.clientWidth, scrollWidth = outerRef.scrollWidth; outerRef.scrollLeft = scrollWidth - clientWidth - scrollLeft; break; } } else { outerRef.scrollLeft = Math.max(0, scrollLeft); } outerRef.scrollTop = Math.max(0, scrollTop); } this._callPropsCallbacks(); }; _proto.componentWillUnmount = function componentWillUnmount() { if (this._resetIsScrollingTimeoutId !== null) { cancelTimeout(this._resetIsScrollingTimeoutId); } }; _proto.render = function render() { var _this$props4 = this.props, children = _this$props4.children, className = _this$props4.className, columnCount = _this$props4.columnCount, direction = _this$props4.direction, height = _this$props4.height, innerRef = _this$props4.innerRef, innerElementType = _this$props4.innerElementType, innerTagName = _this$props4.innerTagName, itemData = _this$props4.itemData, _this$props4$itemKey = _this$props4.itemKey, itemKey = _this$props4$itemKey === void 0 ? defaultItemKey : _this$props4$itemKey, outerElementType = _this$props4.outerElementType, outerTagName = _this$props4.outerTagName, rowCount = _this$props4.rowCount, style = _this$props4.style, useIsScrolling = _this$props4.useIsScrolling, width = _this$props4.width; var isScrolling = this.state.isScrolling; var _this$_getHorizontalR = this._getHorizontalRangeToRender(), columnStartIndex = _this$_getHorizontalR[0], columnStopIndex = _this$_getHorizontalR[1]; var _this$_getVerticalRan = this._getVerticalRangeToRender(), rowStartIndex = _this$_getVerticalRan[0], rowStopIndex = _this$_getVerticalRan[1]; var items = []; if (columnCount > 0 && rowCount) { for (var _rowIndex = rowStartIndex; _rowIndex <= rowStopIndex; _rowIndex++) { for (var _columnIndex = columnStartIndex; _columnIndex <= columnStopIndex; _columnIndex++) { items.push(React.createElement(children, { columnIndex: _columnIndex, data: itemData, isScrolling: useIsScrolling ? isScrolling : undefined, key: itemKey({ columnIndex: _columnIndex, data: itemData, rowIndex: _rowIndex }), rowIndex: _rowIndex, style: this._getItemStyle(_rowIndex, _columnIndex) })); } } } // Read this value AFTER items have been created, // So their actual sizes (if variable) are taken into consideration. var estimatedTotalHeight = getEstimatedTotalHeight(this.props, this._instanceProps); var estimatedTotalWidth = getEstimatedTotalWidth(this.props, this._instanceProps); return React.createElement(outerElementType || outerTagName || 'div', { className: className, onScroll: this._onScroll, ref: this._outerRefSetter, style: _extends$1({ position: 'relative', height: height, width: width, overflow: 'auto', WebkitOverflowScrolling: 'touch', willChange: 'transform', direction: direction }, style) }, React.createElement(innerElementType || innerTagName || 'div', { children: items, ref: innerRef, style: { height: estimatedTotalHeight, pointerEvents: isScrolling ? 'none' : undefined, width: estimatedTotalWidth } })); }; _proto._callPropsCallbacks = function _callPropsCallbacks() { var _this$props5 = this.props, columnCount = _this$props5.columnCount, onItemsRendered = _this$props5.onItemsRendered, onScroll = _this$props5.onScroll, rowCount = _this$props5.rowCount; if (typeof onItemsRendered === 'function') { if (columnCount > 0 && rowCount > 0) { var _this$_getHorizontalR2 = this._getHorizontalRangeToRender(), _overscanColumnStartIndex = _this$_getHorizontalR2[0], _overscanColumnStopIndex = _this$_getHorizontalR2[1], _visibleColumnStartIndex = _this$_getHorizontalR2[2], _visibleColumnStopIndex = _this$_getHorizontalR2[3]; var _this$_getVerticalRan2 = this._getVerticalRangeToRender(), _overscanRowStartIndex = _this$_getVerticalRan2[0], _overscanRowStopIndex = _this$_getVerticalRan2[1], _visibleRowStartIndex = _this$_getVerticalRan2[2], _visibleRowStopIndex = _this$_getVerticalRan2[3]; this._callOnItemsRendered(_overscanColumnStartIndex, _overscanColumnStopIndex, _overscanRowStartIndex, _overscanRowStopIndex, _visibleColumnStartIndex, _visibleColumnStopIndex, _visibleRowStartIndex, _visibleRowStopIndex); } } if (typeof onScroll === 'function') { var _this$state3 = this.state, _horizontalScrollDirection = _this$state3.horizontalScrollDirection, _scrollLeft = _this$state3.scrollLeft, _scrollTop = _this$state3.scrollTop, _scrollUpdateWasRequested = _this$state3.scrollUpdateWasRequested, _verticalScrollDirection = _this$state3.verticalScrollDirection; this._callOnScroll(_scrollLeft, _scrollTop, _horizontalScrollDirection, _verticalScrollDirection, _scrollUpdateWasRequested); } }; // Lazily create and cache item styles while scrolling, // So that pure component sCU will prevent re-renders. // We maintain this cache, and pass a style prop rather than index, // So that List can clear cached styles and force item re-render if necessary. _proto._getHorizontalRangeToRender = function _getHorizontalRangeToRender() { var _this$props6 = this.props, columnCount = _this$props6.columnCount, overscanColumnCount = _this$props6.overscanColumnCount, overscanColumnsCount = _this$props6.overscanColumnsCount, overscanCount = _this$props6.overscanCount, rowCount = _this$props6.rowCount; var _this$state4 = this.state, horizontalScrollDirection = _this$state4.horizontalScrollDirection, isScrolling = _this$state4.isScrolling, scrollLeft = _this$state4.scrollLeft; var overscanCountResolved = overscanColumnCount || overscanColumnsCount || overscanCount || 1; if (columnCount === 0 || rowCount === 0) { return [0, 0, 0, 0]; } var startIndex = getColumnStartIndexForOffset(this.props, scrollLeft, this._instanceProps); var stopIndex = getColumnStopIndexForStartIndex(this.props, startIndex, scrollLeft, this._instanceProps); // Overscan by one item in each direction so that tab/focus works. // If there isn't at least one extra item, tab loops back around. var overscanBackward = !isScrolling || horizontalScrollDirection === 'backward' ? Math.max(1, overscanCountResolved) : 1; var overscanForward = !isScrolling || horizontalScrollDirection === 'forward' ? Math.max(1, overscanCountResolved) : 1; return [Math.max(0, startIndex - overscanBackward), Math.max(0, Math.min(columnCount - 1, stopIndex + overscanForward)), startIndex, stopIndex]; }; _proto._getVerticalRangeToRender = function _getVerticalRangeToRender() { var _this$props7 = this.props, columnCount = _this$props7.columnCount, overscanCount = _this$props7.overscanCount, overscanRowCount = _this$props7.overscanRowCount, overscanRowsCount = _this$props7.overscanRowsCount, rowCount = _this$props7.rowCount; var _this$state5 = this.state, isScrolling = _this$state5.isScrolling, verticalScrollDirection = _this$state5.verticalScrollDirection, scrollTop = _this$state5.scrollTop; var overscanCountResolved = overscanRowCount || overscanRowsCount || overscanCount || 1; if (columnCount === 0 || rowCount === 0) { return [0, 0, 0, 0]; } var startIndex = getRowStartIndexForOffset(this.props, scrollTop, this._instanceProps); var stopIndex = getRowStopIndexForStartIndex(this.props, startIndex, scrollTop, this._instanceProps); // Overscan by one item in each direction so that tab/focus works. // If there isn't at least one extra item, tab loops back around. var overscanBackward = !isScrolling || verticalScrollDirection === 'backward' ? Math.max(1, overscanCountResolved) : 1; var overscanForward = !isScrolling || verticalScrollDirection === 'fo