UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

481 lines (480 loc) 19.7 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.InfinityLoadButton = void 0; require("core-js/modules/web.dom-collections.iterator.js"); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _reactDom = _interopRequireDefault(require("react-dom")); var _componentHelper = require("../../shared/component-helper"); var _Context = _interopRequireDefault(require("../../shared/Context")); var _Button = _interopRequireDefault(require("../button/Button")); var _PaginationHelpers = require("./PaginationHelpers"); var _PaginationContext = _interopRequireDefault(require("./PaginationContext")); const _excluded = ["page_element"]; function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } class InfinityScroller extends _react.default.PureComponent { constructor(_props, context) { var _this; super(_props); _this = this; _defineProperty(this, "startup", () => { const { startupPage, startup_count } = this.context.pagination; const startupCount = parseFloat(startup_count); let newPageNo, skipObserver, callStartupEvent, preventWaitForDelay; for (let i = 0; i < startupCount; ++i) { newPageNo = startupPage + i; skipObserver = newPageNo < startupCount; callStartupEvent = i === 0; preventWaitForDelay = i <= startupCount - 1; this.getNewContent(newPageNo, { position: 'after', skipObserver }, { callStartupEvent, preventWaitForDelay }); } }); _defineProperty(this, "getNewContent", function (newPageNo) { let props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; let { callStartupEvent = false, preventWaitForDelay = false } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; const { pageCount, endInfinity } = _this.context.pagination; if (newPageNo > pageCount) { return endInfinity(); } const exists = _this.context.pagination.items.findIndex(obj => { return obj.pageNumber === newPageNo; }) > -1; if (exists) { return; } const items = _this.context.pagination.prefillItems(newPageNo, props); _this.context.pagination.setItems(items, () => { _this.callEventHandler(newPageNo, { callStartupEvent, preventWaitForDelay }); }); }); this.hideIndicator = (0, _componentHelper.isTrue)(context.pagination.hide_progress_indicator); this.useLoadButton = (0, _componentHelper.isTrue)(context.pagination.use_load_button); this.lastElement = _react.default.createRef(); this.callOnUnmount = []; } componentWillUnmount() { clearTimeout(this._startupTimeout); clearTimeout(this._bufferTimeout); this.callOnUnmount.forEach(f => typeof f === 'function' && f()); } waitForReachedTime(fn, params) { this.callbackBuffer = this.callbackBuffer || []; this.callbackBuffer.push({ fn, params }); this.callBuffer({ minTime: params.preventWaitForDelay ? -1 : this.context.pagination.minTime }); } callBuffer() { let { minTime = this.context.pagination.minTime } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (this.callbackBuffer.length === 0) { return; } const diff = this._lastCall > 0 ? new Date().getTime() - this._lastCall : 0; const waitTime = diff < minTime ? minTime : 0; const nextTick = () => { if (this.callbackBuffer.length > 0) { this._lastCall = new Date().getTime(); const { fn, params } = this.callbackBuffer.shift(); fn(params); this.callBuffer({ minTime: params.preventWaitForDelay ? -1 : minTime }); } }; if (minTime > 0) { clearTimeout(this._bufferTimeout); this._bufferTimeout = setTimeout(nextTick, waitTime); } else { nextTick(); } } callEventHandler(pageNumber) { let { callStartupEvent = false, preventWaitForDelay = false, callOnEnd = false, onDispatch = null } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; this.waitForReachedTime(_ref => { let { pageNumber, callStartupEvent } = _ref; const context = this.context.pagination; const createEvent = eventName => { if (isNaN(pageNumber)) { pageNumber = 1; } const ret = (0, _componentHelper.dispatchCustomElementEvent)(context, eventName, _objectSpread({ pageNumber }, context)); if (typeof onDispatch === 'function') { onDispatch(); } if (typeof ret === 'function') { this.callOnUnmount.push(ret); } }; if (callOnEnd) { createEvent('on_end'); } else { if (callStartupEvent) { createEvent('on_startup'); } else { createEvent('on_change'); } createEvent('on_load'); } }, { pageNumber, callStartupEvent, preventWaitForDelay }); } handleInfinityMarker() { const { children } = this.props; const { lowerPage, upperPage, pageCount, hasEndedInfinity, parallelLoadCount, current_page, fallback_element, marker_element, indicator_element } = this.context.pagination; const Marker = () => _react.default.createElement(InteractionMarker, { pageNumber: upperPage, markerElement: marker_element || fallback_element, onVisible: pageNumber => { let newPageNo; for (let i = 0; i < parallelLoadCount; ++i) { newPageNo = pageNumber + 1 + i; this.context.pagination.onPageUpdate(() => { this.context.pagination.setState({ upperPage: newPageNo, skipObserver: i + 1 < parallelLoadCount }); }); this.callEventHandler(newPageNo); } } }); const LoadButton = () => _react.default.createElement(InfinityLoadButton, { icon: "arrow_up", element: fallback_element, pressed_element: _react.default.createElement(_PaginationHelpers.PaginationIndicator, { indicator_element: indicator_element || fallback_element }), on_click: () => { const newPageNo = lowerPage - 1; this.context.pagination.onPageUpdate(() => { this.context.pagination.setState({ lowerPage: newPageNo }); }); this.callEventHandler(newPageNo); } }); return _react.default.createElement(_react.default.Fragment, null, parseFloat(current_page) > 0 && lowerPage > 1 && _react.default.createElement(LoadButton, null), children, !hasEndedInfinity && parseFloat(current_page) > 0 && (typeof pageCount === 'undefined' || upperPage < pageCount) && _react.default.createElement(Marker, null), !hasEndedInfinity && !this.hideIndicator && (typeof pageCount === 'undefined' || upperPage < pageCount) && _react.default.createElement(_PaginationHelpers.PaginationIndicator, { indicator_element: indicator_element || fallback_element })); } render() { const { items, pageCount, startupPage, hasEndedInfinity, parallelLoadCount, placeMakerBeforeContent, page_element, fallback_element, marker_element, indicator_element, load_button_text, loadButton } = this.context.pagination; if (!(items && items.length > 0)) { clearTimeout(this._startupTimeout); this._startupTimeout = setTimeout(this.startup, 1); return null; } if (this.context.pagination.useMarkerOnly) { return this.handleInfinityMarker(); } const Element = (0, _PaginationHelpers.preparePageElement)(page_element || _react.default.Fragment); return items.map((_ref2, idx) => { let { pageNumber, hasContent, content, ref, skipObserver, ScrollElement } = _ref2; const isLastItem = idx === items.length - 1; const Elem = hasContent && ScrollElement || Element; const marker = hasContent && !this.useLoadButton && !skipObserver && !hasEndedInfinity && (typeof pageCount === 'undefined' || pageNumber <= pageCount) && _react.default.createElement(InteractionMarker, { pageNumber: pageNumber, markerElement: marker_element || fallback_element, onVisible: pageNumber => { let newPageNo; for (let i = 0; i < parallelLoadCount; ++i) { newPageNo = pageNumber + 1 + i; this.getNewContent(newPageNo, { position: 'after', skipObserver: i + 1 < parallelLoadCount }); } } }); const showIndicator = (parallelLoadCount > 1 && idx > 0 ? isLastItem : true) && !hasContent && !this.hideIndicator; return _react.default.createElement(Elem, { key: pageNumber, ref: ref }, hasContent && startupPage > 1 && pageNumber > 1 && pageNumber <= startupPage && _react.default.createElement(InfinityLoadButton, { element: typeof loadButton === 'function' ? loadButton : fallback_element, icon: "arrow_up", text: load_button_text !== null && load_button_text !== void 0 ? load_button_text : loadButton === null || loadButton === void 0 ? void 0 : loadButton.text, icon_position: loadButton === null || loadButton === void 0 ? void 0 : loadButton.iconPosition, on_click: event => this.getNewContent(pageNumber - 1, { position: 'before', skipObserver: true, event }) }), placeMakerBeforeContent && marker, content, !placeMakerBeforeContent && marker, showIndicator && _react.default.createElement(_PaginationHelpers.PaginationIndicator, { indicator_element: indicator_element || fallback_element }), hasContent && this.useLoadButton && isLastItem && (typeof pageCount === 'undefined' || pageNumber < pageCount) && _react.default.createElement(InfinityLoadButton, { element: typeof loadButton === 'function' ? loadButton : fallback_element, text: load_button_text !== null && load_button_text !== void 0 ? load_button_text : loadButton === null || loadButton === void 0 ? void 0 : loadButton.text, icon_position: loadButton === null || loadButton === void 0 ? void 0 : loadButton.iconPosition, icon: "arrow_down", on_click: event => this.getNewContent(pageNumber + 1, { position: 'after', skipObserver: true, ScrollElement: props => hasContent && _react.default.createElement(ScrollToElement, _extends({ page_element: page_element }, props)), event }) })); }); } } exports.default = InfinityScroller; _defineProperty(InfinityScroller, "contextType", _PaginationContext.default); _defineProperty(InfinityScroller, "defaultProps", { children: null }); process.env.NODE_ENV !== "production" ? InfinityScroller.propTypes = { children: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.func]) } : void 0; class InteractionMarker extends _react.default.PureComponent { constructor(props) { super(props); _defineProperty(this, "state", { isConnected: false }); _defineProperty(this, "callReady", () => { var _this$intersectionObs; (_this$intersectionObs = this.intersectionObserver) === null || _this$intersectionObs === void 0 ? void 0 : _this$intersectionObs.disconnect(); this.intersectionObserver = null; clearTimeout(this._readyTimeout); this._readyTimeout = setTimeout(() => { if (this._isMounted) { this.setState({ isConnected: true }); } this.props.onVisible(this.props.pageNumber); }, 1); }); if (typeof props.markerElement === 'function') { (0, _componentHelper.warn)('Pagination: Please use a string or React element e.g. marker_element="tr"'); } this._ref = _react.default.createRef(); if (typeof IntersectionObserver !== 'undefined') { this.intersectionObserver = new IntersectionObserver(entries => { const [{ isIntersecting }] = entries; if (isIntersecting) { this.callReady(); } }); } else { (0, _componentHelper.warn)('Pagination is missing IntersectionObserver supported!'); } } componentDidMount() { if (this._ref.current) { var _this$intersectionObs2; this._isMounted = true; (_this$intersectionObs2 = this.intersectionObserver) === null || _this$intersectionObs2 === void 0 ? void 0 : _this$intersectionObs2.observe(this._ref.current); } } componentWillUnmount() { this._isMounted = false; if (this.intersectionObserver) { clearTimeout(this._readyTimeout); this.intersectionObserver.disconnect(); } } getContentHeight() { let height = 0; try { const sibling = (0, _componentHelper.getPreviousSibling)('dnb-table', this._ref.current); height = parseFloat(window.getComputedStyle(sibling.querySelector('tbody')).height); } catch (e) {} return height; } render() { const { markerElement } = this.props; if (this.state.isConnected || !this.intersectionObserver) { return null; } const Element = markerElement && (0, _PaginationHelpers.isTrElement)(markerElement) ? 'tr' : 'div'; const ElementChild = markerElement && (0, _PaginationHelpers.isTrElement)(markerElement) ? 'td' : 'div'; return _react.default.createElement(Element, { className: "dnb-pagination__marker dnb-table--ignore" }, _react.default.createElement(ElementChild, { className: "dnb-pagination__marker__inner", ref: this._ref })); } } _defineProperty(InteractionMarker, "defaultProps", { markerElement: null }); process.env.NODE_ENV !== "production" ? InteractionMarker.propTypes = { pageNumber: _propTypes.default.number.isRequired, onVisible: _propTypes.default.func.isRequired, markerElement: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.node, _propTypes.default.func, _propTypes.default.string]) } : void 0; class InfinityLoadButton extends _react.default.PureComponent { constructor() { super(...arguments); _defineProperty(this, "state", { isPressed: false }); _defineProperty(this, "onClickHandler", e => { this.setState({ isPressed: true }); if (typeof this.props.on_click === 'function') { this.props.on_click(e); } }); } render() { const { element, icon, text, icon_position } = this.props; const Element = element; const ElementChild = (0, _PaginationHelpers.isTrElement)(Element) ? 'td' : 'div'; return this.state.isPressed ? this.props.pressed_element : _react.default.createElement(Element, null, _react.default.createElement(ElementChild, { className: "dnb-pagination__loadbar" }, _react.default.createElement(_Button.default, { size: "medium", icon: icon, icon_position: icon_position, text: text || this.context.translation.Pagination.load_button_text, variant: "secondary", on_click: this.onClickHandler }))); } } exports.InfinityLoadButton = InfinityLoadButton; _defineProperty(InfinityLoadButton, "contextType", _Context.default); _defineProperty(InfinityLoadButton, "defaultProps", { element: 'div', pressed_element: null, icon: 'arrow_down', text: null, icon_position: 'left' }); process.env.NODE_ENV !== "production" ? InfinityLoadButton.propTypes = { element: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.node, _propTypes.default.func, _propTypes.default.string]), pressed_element: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.node, _propTypes.default.func]), icon: _propTypes.default.string.isRequired, on_click: _propTypes.default.func.isRequired, text: _propTypes.default.string, icon_position: _propTypes.default.string } : void 0; class ScrollToElement extends _react.default.PureComponent { componentDidMount() { const elem = _reactDom.default.findDOMNode(this); this.scrollToPage(elem); } scrollToPage(element) { if (element && typeof element.scrollIntoView === 'function') { element.scrollIntoView({ block: 'nearest', behavior: 'smooth' }); } } render() { const _this$props = this.props, { page_element } = _this$props, props = _objectWithoutProperties(_this$props, _excluded); const Element = (0, _PaginationHelpers.preparePageElement)(page_element || _react.default.Fragment); return _react.default.createElement(Element, props); } } _defineProperty(ScrollToElement, "defaultProps", { page_element: null }); process.env.NODE_ENV !== "production" ? ScrollToElement.propTypes = { page_element: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.node, _propTypes.default.func, _propTypes.default.string]) } : void 0; InfinityScroller._supportsSpacingProps = true; //# sourceMappingURL=PaginationInfinity.js.map