UNPKG

gridjs

Version:

Advanced table plugin

1 lines 191 kB
{"version":3,"file":"gridjs.mjs","sources":["../src/types.ts","../node_modules/preact/dist/preact.module.js","../src/pipeline/processor.ts","../src/util/id.ts","../src/base.ts","../src/view/htmlElement.tsx","../src/util/html.ts","../src/cell.ts","../src/row.ts","../src/tabular.ts","../src/util/array.ts","../src/util/eventEmitter.ts","../src/util/deepEqual.ts","../src/pipeline/filter/globalSearch.ts","../src/operator/search.ts","../src/util/className.ts","../src/pipeline/filter/serverGlobalSearch.ts","../node_modules/preact/hooks/dist/hooks.module.js","../src/hooks/useConfig.ts","../src/i18n/en_US.ts","../src/i18n/language.ts","../src/view/plugin/search/actions.ts","../src/hooks/useStore.ts","../src/hooks/useSelector.ts","../src/view/plugin/search/search.tsx","../src/util/debounce.ts","../src/pipeline/limit/pagination.ts","../src/pipeline/limit/serverPagination.ts","../src/view/plugin/pagination.tsx","../src/util/width.ts","../src/view/table/shadow.tsx","../src/util/string.ts","../src/util/log.ts","../src/plugin.ts","../src/header.ts","../src/storage/storage.ts","../src/storage/memory.ts","../src/storage/server.ts","../src/storage/storageUtils.ts","../src/pipeline/pipeline.ts","../src/pipeline/extractor/storage.ts","../src/pipeline/transformer/arrayToTabular.ts","../src/pipeline/initiator/server.ts","../src/pipeline/transformer/storageResponseToArray.ts","../src/pipeline/pipelineUtils.ts","../src/state/store.ts","../src/config.ts","../src/view/table/td.tsx","../src/view/table/tr.tsx","../src/view/table/messageRow.tsx","../src/view/table/tbody.tsx","../src/pipeline/sort/native.ts","../src/view/plugin/sort/actions.ts","../src/pipeline/sort/server.ts","../src/view/plugin/sort/sort.tsx","../src/util/throttle.ts","../src/view/plugin/resize/resize.tsx","../src/view/table/th.tsx","../src/view/table/thead.tsx","../src/util/table.ts","../src/view/actions.ts","../src/view/table/table.tsx","../src/view/headerContainer.tsx","../src/view/footerContainer.tsx","../src/view/container.tsx","../src/grid.ts"],"sourcesContent":["import { ComponentChild } from 'preact';\nimport Row from './row';\nimport { SortConfig } from './view/plugin/sort/sort';\nimport { JSXInternal } from 'preact/src/jsx';\nimport { Plugin } from './plugin';\n\nexport type OneDArray<T> = T[];\nexport type TwoDArray<T> = T[][];\n\n/**\n * Table cell types\n */\nexport type TCell = number | string | boolean | ComponentChild | HTMLElement;\n// Array of Arrays\nexport type TDataArrayRow = OneDArray<TCell>;\nexport type TDataArray = OneDArray<TDataArrayRow>;\n// Array of Objects\nexport type TDataObjectRow = { [key: string]: TCell };\nexport type TDataObject = OneDArray<TDataObjectRow>;\n// (Array of Arrays) and (Array of Objects)\nexport type TData = TDataArray | TDataObject;\n\n// Table header cell type\nexport interface TColumn {\n id?: string;\n // default data for all columns\n data?: ((row: TDataArrayRow | TDataObjectRow) => TCell) | TCell;\n // column label\n name?: string | ComponentChild;\n plugin?: Plugin<any>;\n // column width\n width?: string;\n minWidth?: string;\n sort?: SortConfig;\n columns?: OneDArray<TColumn>;\n resizable?: boolean;\n hidden?: boolean;\n formatter?: (cell: TCell, row: Row, column: TColumn) => ComponentChild;\n // HTML attributes to be added to all cells and header of this column\n attributes?:\n | ((\n // this is null when `attributes` is called for a th\n cell: TCell | null,\n row: Row | null,\n column: TColumn,\n ) => JSXInternal.HTMLAttributes<HTMLTableCellElement>)\n | JSXInternal.HTMLAttributes<HTMLTableCellElement>;\n}\n\n// Comparator function for the sorting plugin\nexport type Comparator<T> = (a: T, b: T) => number;\n\nexport interface TColumnSort {\n index: number;\n // 1 ascending, -1 descending\n direction?: 1 | -1;\n}\n\n// container status\nexport enum Status {\n Init,\n Loading,\n Loaded,\n Rendered,\n Error,\n}\n\nexport type CSSDeclaration = {\n [key: string]: string | number;\n};\n","var n,l,u,i,t,o,r,f={},e=[],c=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function s(n,l){for(var u in l)n[u]=l[u];return n}function a(n){var l=n.parentNode;l&&l.removeChild(n)}function h(l,u,i){var t,o,r,f={};for(r in u)\"key\"==r?t=u[r]:\"ref\"==r?o=u[r]:f[r]=u[r];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),\"function\"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===f[r]&&(f[r]=l.defaultProps[r]);return v(l,f,t,o,null)}function v(n,i,t,o,r){var f={type:n,props:i,key:t,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u:r};return null==r&&null!=l.vnode&&l.vnode(f),f}function y(){return{current:null}}function p(n){return n.children}function d(n,l){this.props=n,this.context=l}function _(n,l){if(null==l)return n.__?_(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return\"function\"==typeof n.type?_(n):null}function k(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return k(n)}}function b(n){(!n.__d&&(n.__d=!0)&&t.push(n)&&!g.__r++||o!==l.debounceRendering)&&((o=l.debounceRendering)||setTimeout)(g)}function g(){for(var n;g.__r=t.length;)n=t.sort(function(n,l){return n.__v.__b-l.__v.__b}),t=[],n.some(function(n){var l,u,i,t,o,r;n.__d&&(o=(t=(l=n).__v).__e,(r=l.__P)&&(u=[],(i=s({},t)).__v=t.__v+1,j(r,t,i,l.__n,void 0!==r.ownerSVGElement,null!=t.__h?[o]:null,u,null==o?_(t):o,t.__h),z(u,t),t.__e!=o&&k(t)))})}function w(n,l,u,i,t,o,r,c,s,a){var h,y,d,k,b,g,w,x=i&&i.__k||e,C=x.length;for(u.__k=[],h=0;h<l.length;h++)if(null!=(k=u.__k[h]=null==(k=l[h])||\"boolean\"==typeof k?null:\"string\"==typeof k||\"number\"==typeof k||\"bigint\"==typeof k?v(null,k,null,null,k):Array.isArray(k)?v(p,{children:k},null,null,null):k.__b>0?v(k.type,k.props,k.key,k.ref?k.ref:null,k.__v):k)){if(k.__=u,k.__b=u.__b+1,null===(d=x[h])||d&&k.key==d.key&&k.type===d.type)x[h]=void 0;else for(y=0;y<C;y++){if((d=x[y])&&k.key==d.key&&k.type===d.type){x[y]=void 0;break}d=null}j(n,k,d=d||f,t,o,r,c,s,a),b=k.__e,(y=k.ref)&&d.ref!=y&&(w||(w=[]),d.ref&&w.push(d.ref,null,k),w.push(y,k.__c||b,k)),null!=b?(null==g&&(g=b),\"function\"==typeof k.type&&k.__k===d.__k?k.__d=s=m(k,s,n):s=A(n,k,d,x,b,s),\"function\"==typeof u.type&&(u.__d=s)):s&&d.__e==s&&s.parentNode!=n&&(s=_(d))}for(u.__e=g,h=C;h--;)null!=x[h]&&N(x[h],x[h]);if(w)for(h=0;h<w.length;h++)M(w[h],w[++h],w[++h])}function m(n,l,u){for(var i,t=n.__k,o=0;t&&o<t.length;o++)(i=t[o])&&(i.__=n,l=\"function\"==typeof i.type?m(i,l,u):A(u,i,i,t,i.__e,l));return l}function x(n,l){return l=l||[],null==n||\"boolean\"==typeof n||(Array.isArray(n)?n.some(function(n){x(n,l)}):l.push(n)),l}function A(n,l,u,i,t,o){var r,f,e;if(void 0!==l.__d)r=l.__d,l.__d=void 0;else if(null==u||t!=o||null==t.parentNode)n:if(null==o||o.parentNode!==n)n.appendChild(t),r=null;else{for(f=o,e=0;(f=f.nextSibling)&&e<i.length;e+=1)if(f==t)break n;n.insertBefore(t,o),r=o}return void 0!==r?r:t.nextSibling}function C(n,l,u,i,t){var o;for(o in u)\"children\"===o||\"key\"===o||o in l||H(n,o,null,u[o],i);for(o in l)t&&\"function\"!=typeof l[o]||\"children\"===o||\"key\"===o||\"value\"===o||\"checked\"===o||u[o]===l[o]||H(n,o,l[o],u[o],i)}function $(n,l,u){\"-\"===l[0]?n.setProperty(l,u):n[l]=null==u?\"\":\"number\"!=typeof u||c.test(l)?u:u+\"px\"}function H(n,l,u,i,t){var o;n:if(\"style\"===l)if(\"string\"==typeof u)n.style.cssText=u;else{if(\"string\"==typeof i&&(n.style.cssText=i=\"\"),i)for(l in i)u&&l in u||$(n.style,l,\"\");if(u)for(l in u)i&&u[l]===i[l]||$(n.style,l,u[l])}else if(\"o\"===l[0]&&\"n\"===l[1])o=l!==(l=l.replace(/Capture$/,\"\")),l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+o]=u,u?i||n.addEventListener(l,o?T:I,o):n.removeEventListener(l,o?T:I,o);else if(\"dangerouslySetInnerHTML\"!==l){if(t)l=l.replace(/xlink(H|:h)/,\"h\").replace(/sName$/,\"s\");else if(\"href\"!==l&&\"list\"!==l&&\"form\"!==l&&\"tabIndex\"!==l&&\"download\"!==l&&l in n)try{n[l]=null==u?\"\":u;break n}catch(n){}\"function\"==typeof u||(null==u||!1===u&&-1==l.indexOf(\"-\")?n.removeAttribute(l):n.setAttribute(l,u))}}function I(n){this.l[n.type+!1](l.event?l.event(n):n)}function T(n){this.l[n.type+!0](l.event?l.event(n):n)}function j(n,u,i,t,o,r,f,e,c){var a,h,v,y,_,k,b,g,m,x,A,C,$,H,I,T=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,r=[e]),(a=l.__b)&&a(u);try{n:if(\"function\"==typeof T){if(g=u.props,m=(a=T.contextType)&&t[a.__c],x=a?m?m.props.value:a.__:t,i.__c?b=(h=u.__c=i.__c).__=h.__E:(\"prototype\"in T&&T.prototype.render?u.__c=h=new T(g,x):(u.__c=h=new d(g,x),h.constructor=T,h.render=O),m&&m.sub(h),h.props=g,h.state||(h.state={}),h.context=x,h.__n=t,v=h.__d=!0,h.__h=[],h._sb=[]),null==h.__s&&(h.__s=h.state),null!=T.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=s({},h.__s)),s(h.__s,T.getDerivedStateFromProps(g,h.__s))),y=h.props,_=h.state,v)null==T.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else{if(null==T.getDerivedStateFromProps&&g!==y&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(g,x),!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(g,h.__s,x)||u.__v===i.__v){for(h.props=g,h.state=h.__s,u.__v!==i.__v&&(h.__d=!1),h.__v=u,u.__e=i.__e,u.__k=i.__k,u.__k.forEach(function(n){n&&(n.__=u)}),A=0;A<h._sb.length;A++)h.__h.push(h._sb[A]);h._sb=[],h.__h.length&&f.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(g,h.__s,x),null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(y,_,k)})}if(h.context=x,h.props=g,h.__v=u,h.__P=n,C=l.__r,$=0,\"prototype\"in T&&T.prototype.render){for(h.state=h.__s,h.__d=!1,C&&C(u),a=h.render(h.props,h.state,h.context),H=0;H<h._sb.length;H++)h.__h.push(h._sb[H]);h._sb=[]}else do{h.__d=!1,C&&C(u),a=h.render(h.props,h.state,h.context),h.state=h.__s}while(h.__d&&++$<25);h.state=h.__s,null!=h.getChildContext&&(t=s(s({},t),h.getChildContext())),v||null==h.getSnapshotBeforeUpdate||(k=h.getSnapshotBeforeUpdate(y,_)),I=null!=a&&a.type===p&&null==a.key?a.props.children:a,w(n,Array.isArray(I)?I:[I],u,i,t,o,r,f,e,c),h.base=u.__e,u.__h=null,h.__h.length&&f.push(h),b&&(h.__E=h.__=null),h.__e=!1}else null==r&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=L(i.__e,u,i,t,o,r,f,c);(a=l.diffed)&&a(u)}catch(n){u.__v=null,(c||null!=r)&&(u.__e=e,u.__h=!!c,r[r.indexOf(e)]=null),l.__e(n,u,i)}}function z(n,u){l.__c&&l.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u)})}catch(n){l.__e(n,u.__v)}})}function L(l,u,i,t,o,r,e,c){var s,h,v,y=i.props,p=u.props,d=u.type,k=0;if(\"svg\"===d&&(o=!0),null!=r)for(;k<r.length;k++)if((s=r[k])&&\"setAttribute\"in s==!!d&&(d?s.localName===d:3===s.nodeType)){l=s,r[k]=null;break}if(null==l){if(null===d)return document.createTextNode(p);l=o?document.createElementNS(\"http://www.w3.org/2000/svg\",d):document.createElement(d,p.is&&p),r=null,c=!1}if(null===d)y===p||c&&l.data===p||(l.data=p);else{if(r=r&&n.call(l.childNodes),h=(y=i.props||f).dangerouslySetInnerHTML,v=p.dangerouslySetInnerHTML,!c){if(null!=r)for(y={},k=0;k<l.attributes.length;k++)y[l.attributes[k].name]=l.attributes[k].value;(v||h)&&(v&&(h&&v.__html==h.__html||v.__html===l.innerHTML)||(l.innerHTML=v&&v.__html||\"\"))}if(C(l,p,y,o,c),v)u.__k=[];else if(k=u.props.children,w(l,Array.isArray(k)?k:[k],u,i,t,o&&\"foreignObject\"!==d,r,e,r?r[0]:i.__k&&_(i,0),c),null!=r)for(k=r.length;k--;)null!=r[k]&&a(r[k]);c||(\"value\"in p&&void 0!==(k=p.value)&&(k!==l.value||\"progress\"===d&&!k||\"option\"===d&&k!==y.value)&&H(l,\"value\",k,y.value,!1),\"checked\"in p&&void 0!==(k=p.checked)&&k!==l.checked&&H(l,\"checked\",k,y.checked,!1))}return l}function M(n,u,i){try{\"function\"==typeof n?n(u):n.current=u}catch(n){l.__e(n,i)}}function N(n,u,i){var t,o;if(l.unmount&&l.unmount(n),(t=n.ref)&&(t.current&&t.current!==n.__e||M(t,null,u)),null!=(t=n.__c)){if(t.componentWillUnmount)try{t.componentWillUnmount()}catch(n){l.__e(n,u)}t.base=t.__P=null,n.__c=void 0}if(t=n.__k)for(o=0;o<t.length;o++)t[o]&&N(t[o],u,i||\"function\"!=typeof n.type);i||null==n.__e||a(n.__e),n.__=n.__e=n.__d=void 0}function O(n,l,u){return this.constructor(n,u)}function P(u,i,t){var o,r,e;l.__&&l.__(u,i),r=(o=\"function\"==typeof t)?null:t&&t.__k||i.__k,e=[],j(i,u=(!o&&t||i).__k=h(p,null,[u]),r||f,f,void 0!==i.ownerSVGElement,!o&&t?[t]:r?null:i.firstChild?n.call(i.childNodes):null,e,!o&&t?t:r?r.__e:i.firstChild,o),z(e,u)}function S(n,l){P(n,l,S)}function q(l,u,i){var t,o,r,f=s({},l.props);for(r in u)\"key\"==r?t=u[r]:\"ref\"==r?o=u[r]:f[r]=u[r];return arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),v(l.type,f,t||l.key,o||l.ref,null)}function B(n,l){var u={__c:l=\"__cC\"+r++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,i;return this.getChildContext||(u=[],(i={})[l]=this,this.getChildContext=function(){return i},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(b)},this.sub=function(n){u.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n)}}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n=e.slice,l={__e:function(n,l,u,i){for(var t,o,r;l=l.__;)if((t=l.__c)&&!t.__)try{if((o=t.constructor)&&null!=o.getDerivedStateFromError&&(t.setState(o.getDerivedStateFromError(n)),r=t.__d),null!=t.componentDidCatch&&(t.componentDidCatch(n,i||{}),r=t.__d),r)return t.__E=t}catch(l){n=l}throw n}},u=0,i=function(n){return null!=n&&void 0===n.constructor},d.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=s({},this.state),\"function\"==typeof n&&(n=n(s({},u),this.props)),n&&s(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),b(this))},d.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),b(this))},d.prototype.render=p,t=[],g.__r=0,r=0;export{d as Component,p as Fragment,q as cloneElement,B as createContext,h as createElement,y as createRef,h,S as hydrate,i as isValidElement,l as options,P as render,x as toChildArray};\n//# sourceMappingURL=preact.module.js.map\n","// The order of enum items define the processing order of the processor type\n// e.g. Extractor = 0 will be processed before Transformer = 1\nimport { generateUUID, ID } from '../util/id';\nimport { EventEmitter } from '../util/eventEmitter';\nimport { deepEqual } from '../util/deepEqual';\n\nexport enum ProcessorType {\n Initiator,\n ServerFilter,\n ServerSort,\n ServerLimit,\n Extractor,\n Transformer,\n Filter,\n Sort,\n Limit,\n}\n\ninterface PipelineProcessorEvents {\n propsUpdated: <T, P>(processor: PipelineProcessor<T, P>) => void;\n beforeProcess: (...args) => void;\n afterProcess: (...args) => void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface PipelineProcessorProps {}\n\nexport abstract class PipelineProcessor<\n T,\n P extends Partial<PipelineProcessorProps>,\n> extends EventEmitter<PipelineProcessorEvents> {\n public readonly id: ID;\n private _props: P;\n\n abstract get type(): ProcessorType;\n protected abstract _process(...args): T | Promise<T>;\n protected validateProps?(...args): void;\n\n constructor(props?: Partial<P>) {\n super();\n\n this._props = {} as P;\n this.id = generateUUID();\n\n if (props) this.setProps(props);\n }\n\n /**\n * process is used to call beforeProcess and afterProcess callbacks\n * This function is just a wrapper that calls _process()\n *\n * @param args\n */\n process(...args): T | Promise<T> {\n if (this.validateProps instanceof Function) {\n this.validateProps(...args);\n }\n\n this.emit('beforeProcess', ...args);\n const result = this._process(...args);\n this.emit('afterProcess', ...args);\n return result;\n }\n\n setProps(props: Partial<P>): this {\n const updatedProps = {\n ...this._props,\n ...props,\n };\n\n if (!deepEqual(updatedProps, this._props)) {\n this._props = updatedProps;\n this.emit('propsUpdated', this);\n }\n\n return this;\n }\n\n get props(): P {\n return this._props;\n }\n}\n","export type ID = string;\n\nexport function generateUUID(): ID {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0,\n v = c == 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","import { generateUUID, ID } from './util/id';\n\nclass Base {\n private readonly _id: ID;\n\n constructor(id?: ID) {\n this._id = id || generateUUID();\n }\n\n get id(): ID {\n return this._id;\n }\n}\n\nexport default Base;\n","import { h } from 'preact';\n\nexport interface HTMLContentProps {\n content: string;\n parentElement?: string;\n}\n\nexport function HTMLElement(props: HTMLContentProps) {\n return h(props.parentElement || 'span', {\n dangerouslySetInnerHTML: { __html: props.content },\n });\n}\n","import { h, VNode } from 'preact';\nimport { HTMLElement } from '../view/htmlElement';\n\nexport function decode(content: string): string {\n const value = new DOMParser().parseFromString(content, 'text/html');\n return value.documentElement.textContent;\n}\n\nexport function html(content: string, parentElement?: string): VNode {\n return h(HTMLElement, { content: content, parentElement: parentElement });\n}\n","import Base from './base';\nimport { TCell } from './types';\nimport { html } from './util/html';\nimport { ComponentChild } from 'preact';\n\nclass Cell extends Base {\n // because a Cell is a subset of TCell type\n public data: number | string | boolean | ComponentChild;\n\n constructor(data: TCell) {\n super();\n\n this.update(data);\n }\n\n private cast(data: TCell): number | string | boolean | ComponentChild {\n if (data instanceof HTMLElement) {\n return html(data.outerHTML);\n }\n\n return data;\n }\n\n /**\n * Updates the Cell's data\n *\n * @param data\n */\n public update(data: TCell): Cell {\n this.data = this.cast(data);\n return this;\n }\n}\n\nexport default Cell;\n","import Cell from './cell';\nimport Base from './base';\nimport { TCell } from './types';\n\nclass Row extends Base {\n private _cells: Cell[];\n\n constructor(cells?: Cell[]) {\n super();\n\n this.cells = cells || [];\n }\n\n public cell(index: number): Cell {\n return this._cells[index];\n }\n\n public get cells(): Cell[] {\n return this._cells;\n }\n\n public set cells(cells: Cell[]) {\n this._cells = cells;\n }\n\n public toArray(): TCell[] {\n return this.cells.map((cell) => cell.data);\n }\n\n /**\n * Creates a new Row from an array of Cell(s)\n * This method generates a new ID for the Row and all nested elements\n *\n * @param cells\n * @returns Row\n */\n static fromCells(cells: Cell[]): Row {\n return new Row(cells.map((cell) => new Cell(cell.data)));\n }\n\n get length(): number {\n return this.cells.length;\n }\n}\n\nexport default Row;\n","import Base from './base';\nimport Row from './row';\nimport Cell from './cell';\nimport { OneDArray, TCell, TwoDArray } from './types';\nimport { oneDtoTwoD } from './util/array';\n\nclass Tabular extends Base {\n private _rows: Row[];\n private _length: number;\n\n constructor(rows?: Row[] | Row) {\n super();\n\n if (rows instanceof Array) {\n this.rows = rows;\n } else if (rows instanceof Row) {\n this.rows = [rows];\n } else {\n this.rows = [];\n }\n }\n\n get rows(): Row[] {\n return this._rows;\n }\n\n set rows(rows: Row[]) {\n this._rows = rows;\n }\n\n get length(): number {\n return this._length || this.rows.length;\n }\n\n // we want to sent the length when storage is ServerStorage\n set length(len: number) {\n this._length = len;\n }\n\n public toArray(): TCell[][] {\n return this.rows.map((row) => row.toArray());\n }\n\n /**\n * Creates a new Tabular from an array of Row(s)\n * This method generates a new ID for the Tabular and all nested elements\n *\n * @param rows\n * @returns Tabular\n */\n static fromRows(rows: Row[]): Tabular {\n return new Tabular(rows.map((row) => Row.fromCells(row.cells)));\n }\n\n /**\n * Creates a new Tabular from a 2D array\n * This method generates a new ID for the Tabular and all nested elements\n *\n * @param data\n * @returns Tabular\n */\n static fromArray<T extends TCell>(\n data: OneDArray<T> | TwoDArray<T>,\n ): Tabular {\n data = oneDtoTwoD(data);\n\n return new Tabular(\n data.map((row) => new Row(row.map((cell) => new Cell(cell)))),\n );\n }\n}\n\nexport default Tabular;\n","import { OneDArray, TwoDArray } from '../types';\n\nexport function oneDtoTwoD<T>(data: OneDArray<T> | TwoDArray<T>): TwoDArray<T> {\n if (data[0] && !(data[0] instanceof Array)) {\n return [data] as TwoDArray<T>;\n }\n\n return data as TwoDArray<T>;\n}\n\nexport function flatten<T>(arrays: TwoDArray<T>): OneDArray<T> {\n return arrays.reduce((prev, x) => prev.concat(x), []);\n}\n","type EventArgs<T> = [T] extends [(...args: infer U) => any]\n ? U\n : [T] extends [void]\n ? []\n : [T];\n\n/**\n * Example:\n *\n * export interface BaseEvents<P, S> {\n * SET_STATE: (component: BaseComponent<P, S>, state: S) => void;\n * }\n */\n\nexport interface EventEmitter<EventTypes> {\n addListener<EventName extends keyof EventTypes>(\n event: EventName,\n listener: (...args: EventArgs<EventTypes[EventName]>) => void,\n ): EventEmitter<EventTypes>;\n\n on<EventName extends keyof EventTypes>(\n event: EventName,\n listener: (...args: EventArgs<EventTypes[EventName]>) => void,\n ): EventEmitter<EventTypes>;\n\n off<EventName extends keyof EventTypes>(\n event: EventName,\n listener: (...args: EventArgs<EventTypes[EventName]>) => void,\n ): EventEmitter<EventTypes>;\n\n emit<EventName extends keyof EventTypes>(\n event: EventName,\n ...args: EventArgs<EventTypes[EventName]>\n ): boolean;\n}\n\nexport class EventEmitter<EventTypes> {\n private callbacks: { [event: string]: ((...args) => void)[] };\n\n // because we are using EventEmitter as a mixin and the\n // constructor won't be called by the applyMixins function\n // see src/base.ts and src/util/applyMixin.ts\n private init(event?: string): void {\n if (!this.callbacks) {\n this.callbacks = {};\n }\n\n if (event && !this.callbacks[event]) {\n this.callbacks[event] = [];\n }\n }\n\n listeners(): { [event: string]: ((...args) => void)[] } {\n return this.callbacks;\n }\n\n on<EventName extends keyof EventTypes>(\n event: EventName,\n listener: (...args: EventArgs<EventTypes[EventName]>) => void,\n ): EventEmitter<EventTypes> {\n this.init(event as string);\n this.callbacks[event as string].push(listener);\n return this;\n }\n\n off<EventName extends keyof EventTypes>(\n event: EventName,\n listener: (...args: EventArgs<EventTypes[EventName]>) => void,\n ): EventEmitter<EventTypes> {\n const eventName = event as string;\n\n this.init();\n\n if (!this.callbacks[eventName] || this.callbacks[eventName].length === 0) {\n // there is no callbacks with this key\n return this;\n }\n\n this.callbacks[eventName] = this.callbacks[eventName].filter(\n (value) => value != listener,\n );\n\n return this;\n }\n\n emit<EventName extends keyof EventTypes>(\n event: EventName,\n ...args: EventArgs<EventTypes[EventName]>\n ): boolean {\n const eventName = event as string;\n\n this.init(eventName);\n\n if (this.callbacks[eventName].length > 0) {\n this.callbacks[eventName].forEach((value) => value(...args));\n return true;\n }\n\n return false;\n }\n}\n","/**\n * Returns true if both objects are equal\n * @param a left object\n * @param b right object\n * @returns\n */\nexport function deepEqual<A, B>(obj1: A, obj2: B) {\n // If objects are not the same type, return false\n if (typeof obj1 !== typeof obj2) {\n return false;\n }\n // If objects are both null or undefined, return true\n if (obj1 === null && obj2 === null) {\n return true;\n }\n // If objects are both primitive types, compare them directly\n if (typeof obj1 !== 'object') {\n // eslint-disable-next-line\n // @ts-ignore\n return obj1 === obj2;\n }\n // If objects are arrays, compare their elements recursively\n if (Array.isArray(obj1) && Array.isArray(obj2)) {\n if (obj1.length !== obj2.length) {\n return false;\n }\n for (let i = 0; i < obj1.length; i++) {\n if (!deepEqual(obj1[i], obj2[i])) {\n return false;\n }\n }\n return true;\n }\n // If objects are VNodes, compare their props only\n if (\n // eslint-disable-next-line no-prototype-builtins\n obj1.hasOwnProperty('constructor') &&\n // eslint-disable-next-line no-prototype-builtins\n obj2.hasOwnProperty('constructor') &&\n // eslint-disable-next-line no-prototype-builtins\n obj1.hasOwnProperty('props') &&\n // eslint-disable-next-line no-prototype-builtins\n obj2.hasOwnProperty('props') &&\n // eslint-disable-next-line no-prototype-builtins\n obj1.hasOwnProperty('key') &&\n // eslint-disable-next-line no-prototype-builtins\n obj2.hasOwnProperty('key') &&\n // eslint-disable-next-line no-prototype-builtins\n obj1.hasOwnProperty('ref') &&\n // eslint-disable-next-line no-prototype-builtins\n obj2.hasOwnProperty('ref') &&\n // eslint-disable-next-line no-prototype-builtins\n obj1.hasOwnProperty('type') &&\n // eslint-disable-next-line no-prototype-builtins\n obj2.hasOwnProperty('type')\n ) {\n return deepEqual(obj1['props'], obj2['props']);\n }\n // If objects are both objects, compare their properties recursively\n const keys1 = Object.keys(obj1);\n const keys2 = Object.keys(obj2);\n if (keys1.length !== keys2.length) {\n return false;\n }\n for (const key of keys1) {\n // eslint-disable-next-line no-prototype-builtins\n if (!obj2.hasOwnProperty(key) || !deepEqual(obj1[key], obj2[key])) {\n return false;\n }\n }\n return true;\n}\n","import search from '../../operator/search';\nimport Tabular from '../../tabular';\nimport {\n PipelineProcessor,\n PipelineProcessorProps,\n ProcessorType,\n} from '../processor';\nimport { OneDArray, TCell, TColumn } from '../../types';\n\ninterface GlobalSearchFilterProps extends PipelineProcessorProps {\n keyword: string;\n columns: OneDArray<TColumn>;\n ignoreHiddenColumns: boolean;\n selector?: (cell: TCell, rowIndex: number, cellIndex: number) => string;\n}\n\nclass GlobalSearchFilter extends PipelineProcessor<\n Tabular,\n GlobalSearchFilterProps\n> {\n get type(): ProcessorType {\n return ProcessorType.Filter;\n }\n\n _process(data: Tabular): Tabular {\n if (this.props.keyword) {\n return search(\n String(this.props.keyword).trim(),\n this.props.columns,\n this.props.ignoreHiddenColumns,\n data,\n this.props.selector,\n );\n }\n\n return data;\n }\n}\n\nexport default GlobalSearchFilter;\n","import Tabular from '../tabular';\nimport { VNode } from 'preact';\nimport { HTMLContentProps } from '../view/htmlElement';\nimport { OneDArray, TCell, TColumn } from '../types';\n\nexport default function (\n keyword: string,\n columns: OneDArray<TColumn>,\n ignoreHiddenColumns: boolean,\n tabular: Tabular,\n selector?: (cell: TCell, rowIndex: number, cellIndex: number) => string,\n): Tabular {\n // escape special regex chars\n keyword = keyword.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n\n return new Tabular(\n tabular.rows.filter((row, rowIndex) =>\n row.cells.some((cell, cellIndex) => {\n if (!cell) {\n return false;\n }\n\n if (ignoreHiddenColumns) {\n if (\n columns &&\n columns[cellIndex] &&\n typeof columns[cellIndex] === 'object'\n ) {\n const typedColumn = columns[cellIndex] as TColumn;\n if (typedColumn.hidden) {\n return false;\n }\n }\n }\n\n let data = '';\n\n if (typeof selector === 'function') {\n data = selector(cell.data, rowIndex, cellIndex);\n } else if (typeof cell.data === 'object') {\n // HTMLContent element\n const element = cell.data as VNode<HTMLContentProps>;\n if (element && element.props && element.props.content) {\n // TODO: we should only search in the content of the element. props.content is the entire HTML element\n data = element.props.content;\n }\n } else {\n // primitive types\n data = String(cell.data);\n }\n\n return new RegExp(keyword, 'gi').test(data);\n }),\n ),\n );\n}\n","import { JSXInternal } from 'preact/src/jsx';\n\nexport function className(...args: string[]): string {\n const prefix = 'gridjs';\n\n return `${prefix}${args.reduce(\n (prev: string, cur: string) => `${prev}-${cur}`,\n '',\n )}`;\n}\n\nexport function classJoin(\n ...classNames: (undefined | string | JSXInternal.SignalLike<string>)[]\n): string {\n return classNames\n .map((x) => (x ? x.toString() : ''))\n .filter((x) => x)\n .reduce((className, prev) => `${className || ''} ${prev}`, '')\n .trim();\n}\n","import {\n PipelineProcessor,\n PipelineProcessorProps,\n ProcessorType,\n} from '../processor';\nimport { ServerStorageOptions } from '../../storage/server';\n\ninterface ServerGlobalSearchFilterProps extends PipelineProcessorProps {\n keyword?: string;\n url?: (prevUrl: string, keyword: string) => string;\n body?: (prevBody: BodyInit, keyword: string) => BodyInit;\n}\n\nclass ServerGlobalSearchFilter extends PipelineProcessor<\n ServerStorageOptions,\n ServerGlobalSearchFilterProps\n> {\n get type(): ProcessorType {\n return ProcessorType.ServerFilter;\n }\n\n _process(options?: ServerStorageOptions): ServerStorageOptions {\n if (!this.props.keyword) return options;\n\n const updates = {};\n\n if (this.props.url) {\n updates['url'] = this.props.url(options.url, this.props.keyword);\n }\n\n if (this.props.body) {\n updates['body'] = this.props.body(options.body, this.props.keyword);\n }\n\n return {\n ...options,\n ...updates,\n };\n }\n}\n\nexport default ServerGlobalSearchFilter;\n","import{options as n}from\"preact\";var t,r,u,i,o=0,f=[],c=[],e=n.__b,a=n.__r,v=n.diffed,l=n.__c,m=n.unmount;function d(t,u){n.__h&&n.__h(r,t,o||u),o=0;var i=r.__H||(r.__H={__:[],__h:[]});return t>=i.__.length&&i.__.push({__V:c}),i.__[t]}function p(n){return o=1,y(B,n)}function y(n,u,i){var o=d(t++,2);if(o.t=n,!o.__c&&(o.__=[i?i(u):B(void 0,u),function(n){var t=o.__N?o.__N[0]:o.__[0],r=o.t(t,n);t!==r&&(o.__N=[r,o.__[1]],o.__c.setState({}))}],o.__c=r,!r.u)){r.u=!0;var f=r.shouldComponentUpdate;r.shouldComponentUpdate=function(n,t,r){if(!o.__c.__H)return!0;var u=o.__c.__H.__.filter(function(n){return n.__c});if(u.every(function(n){return!n.__N}))return!f||f.call(this,n,t,r);var i=!1;return u.forEach(function(n){if(n.__N){var t=n.__[0];n.__=n.__N,n.__N=void 0,t!==n.__[0]&&(i=!0)}}),!(!i&&o.__c.props===n)&&(!f||f.call(this,n,t,r))}}return o.__N||o.__}function h(u,i){var o=d(t++,3);!n.__s&&z(o.__H,i)&&(o.__=u,o.i=i,r.__H.__h.push(o))}function s(u,i){var o=d(t++,4);!n.__s&&z(o.__H,i)&&(o.__=u,o.i=i,r.__h.push(o))}function _(n){return o=5,F(function(){return{current:n}},[])}function A(n,t,r){o=6,s(function(){return\"function\"==typeof n?(n(t()),function(){return n(null)}):n?(n.current=t(),function(){return n.current=null}):void 0},null==r?r:r.concat(n))}function F(n,r){var u=d(t++,7);return z(u.__H,r)?(u.__V=n(),u.i=r,u.__h=n,u.__V):u.__}function T(n,t){return o=8,F(function(){return n},t)}function q(n){var u=r.context[n.__c],i=d(t++,9);return i.c=n,u?(null==i.__&&(i.__=!0,u.sub(r)),u.props.value):n.__}function x(t,r){n.useDebugValue&&n.useDebugValue(r?r(t):t)}function P(n){var u=d(t++,10),i=p();return u.__=n,r.componentDidCatch||(r.componentDidCatch=function(n,t){u.__&&u.__(n,t),i[1](n)}),[i[0],function(){i[1](void 0)}]}function V(){var n=d(t++,11);if(!n.__){for(var u=r.__v;null!==u&&!u.__m&&null!==u.__;)u=u.__;var i=u.__m||(u.__m=[0,0]);n.__=\"P\"+i[0]+\"-\"+i[1]++}return n.__}function b(){for(var t;t=f.shift();)if(t.__P&&t.__H)try{t.__H.__h.forEach(k),t.__H.__h.forEach(w),t.__H.__h=[]}catch(r){t.__H.__h=[],n.__e(r,t.__v)}}n.__b=function(n){r=null,e&&e(n)},n.__r=function(n){a&&a(n),t=0;var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.__V=c,n.__N=n.i=void 0})):(i.__h.forEach(k),i.__h.forEach(w),i.__h=[])),u=r},n.diffed=function(t){v&&v(t);var o=t.__c;o&&o.__H&&(o.__H.__h.length&&(1!==f.push(o)&&i===n.requestAnimationFrame||((i=n.requestAnimationFrame)||j)(b)),o.__H.__.forEach(function(n){n.i&&(n.__H=n.i),n.__V!==c&&(n.__=n.__V),n.i=void 0,n.__V=c})),u=r=null},n.__c=function(t,r){r.some(function(t){try{t.__h.forEach(k),t.__h=t.__h.filter(function(n){return!n.__||w(n)})}catch(u){r.some(function(n){n.__h&&(n.__h=[])}),r=[],n.__e(u,t.__v)}}),l&&l(t,r)},n.unmount=function(t){m&&m(t);var r,u=t.__c;u&&u.__H&&(u.__H.__.forEach(function(n){try{k(n)}catch(n){r=n}}),u.__H=void 0,r&&n.__e(r,u.__v))};var g=\"function\"==typeof requestAnimationFrame;function j(n){var t,r=function(){clearTimeout(u),g&&cancelAnimationFrame(t),setTimeout(n)},u=setTimeout(r,100);g&&(t=requestAnimationFrame(r))}function k(n){var t=r,u=n.__c;\"function\"==typeof u&&(n.__c=void 0,u()),r=t}function w(n){var t=r;n.__c=n.__(),r=t}function z(n,t){return!n||n.length!==t.length||t.some(function(t,r){return t!==n[r]})}function B(n,t){return\"function\"==typeof t?t(n):t}export{T as useCallback,q as useContext,x as useDebugValue,h as useEffect,P as useErrorBoundary,V as useId,A as useImperativeHandle,s as useLayoutEffect,F as useMemo,y as useReducer,_ as useRef,p as useState};\n//# sourceMappingURL=hooks.module.js.map\n","import { useContext } from 'preact/hooks';\nimport { Config, ConfigContext } from '../config';\n\nexport function useConfig(): Config {\n return useContext(ConfigContext);\n}\n","export default {\n search: {\n placeholder: 'Type a keyword...',\n },\n sort: {\n sortAsc: 'Sort column ascending',\n sortDesc: 'Sort column descending',\n },\n pagination: {\n previous: 'Previous',\n next: 'Next',\n navigate: (page, pages) => `Page ${page} of ${pages}`,\n page: (page) => `Page ${page}`,\n showing: 'Showing',\n of: 'of',\n to: 'to',\n results: 'results',\n },\n loading: 'Loading...',\n noRecordsFound: 'No matching records found',\n error: 'An error happened while fetching the data',\n};\n","import { useConfig } from '../hooks/useConfig';\nimport enUS from './en_US';\ntype MessageFormat = (...args) => string;\ntype Message = string | MessageFormat;\nexport type Language = { [key: string]: Message | Language };\n\nexport class Translator {\n private readonly _language: Language;\n private readonly _defaultLanguage: Language;\n\n constructor(language?: Language) {\n this._language = language;\n this._defaultLanguage = enUS;\n }\n\n /**\n * Tries to split the message with \".\" and find\n * the key in the given language\n *\n * @param message\n * @param lang\n */\n getString(message: string, lang: Language): MessageFormat {\n if (!lang || !message) return null;\n\n const splitted = message.split('.');\n const key = splitted[0];\n\n if (lang[key]) {\n const val = lang[key];\n\n if (typeof val === 'string') {\n return (): string => val;\n } else if (typeof val === 'function') {\n return val;\n } else {\n return this.getString(splitted.slice(1).join('.'), val);\n }\n }\n\n return null;\n }\n\n translate(message: string, ...args): string {\n const translated = this.getString(message, this._language);\n let messageFormat;\n\n if (translated) {\n messageFormat = translated;\n } else {\n messageFormat = this.getString(message, this._defaultLanguage);\n }\n\n if (messageFormat) {\n return messageFormat(...args);\n }\n\n return message;\n }\n}\n\nexport function useTranslator() {\n const config = useConfig();\n\n return function (message: string, ...args): string {\n return config.translator.translate(message, ...args);\n };\n}\n","export const SearchKeyword = (payload) => (state) => {\n return {\n ...state,\n search: {\n keyword: payload,\n },\n };\n};\n","import { useConfig } from './useConfig';\n\nexport function useStore() {\n const config = useConfig();\n return config.store;\n}\n","import { useEffect, useState } from 'preact/hooks';\nimport { useStore } from './useStore';\n\nexport default function useSelector<T>(selector: (state) => T) {\n const store = useStore();\n const [current, setCurrent] = useState(selector(store.getState()));\n\n useEffect(() => {\n const unsubscribe = store.subscribe(() => {\n const updated = selector(store.getState());\n\n if (current !== updated) {\n setCurrent(updated);\n }\n });\n\n return unsubscribe;\n }, []);\n\n return current;\n}\n","import { h, JSX } from 'preact';\nimport GlobalSearchFilter from '../../../pipeline/filter/globalSearch';\nimport { classJoin, className } from '../../../util/className';\nimport ServerGlobalSearchFilter from '../../../pipeline/filter/serverGlobalSearch';\nimport { TCell } from '../../../types';\nimport { useConfig } from '../../../hooks/useConfig';\nimport { useCallback, useEffect, useState } from 'preact/hooks';\nimport { useTranslator } from '../../../i18n/language';\nimport * as actions from './actions';\nimport { useStore } from '../../../hooks/useStore';\nimport useSelector from '../../../hooks/useSelector';\nimport { debounce } from '../../../util/debounce';\n\nexport interface SearchConfig {\n keyword?: string;\n ignoreHiddenColumns?: boolean;\n debounceTimeout?: number;\n selector?: (cell: TCell, rowIndex: number, cellIndex: number) => string;\n server?: {\n url?: (prevUrl: string, keyword: string) => string;\n body?: (prevBody: BodyInit, keyword: string) => BodyInit;\n };\n}\n\nexport function Search() {\n const [processor, setProcessor] = useState<\n GlobalSearchFilter | ServerGlobalSearchFilter\n >(undefined);\n const config = useConfig();\n const props = config.search as SearchConfig;\n const _ = useTranslator();\n const { dispatch } = useStore();\n const state = useSelector((state) => state.search);\n\n useEffect(() => {\n if (!processor) return;\n\n processor.setProps({\n keyword: state?.keyword,\n });\n }, [state, processor]);\n\n useEffect(() => {\n if (props.server) {\n setProcessor(\n new ServerGlobalSearchFilter({\n keyword: props.keyword,\n url: props.server.url,\n body: props.server.body,\n }),\n );\n } else {\n setProcessor(\n new GlobalSearchFilter({\n keyword: props.keyword,\n columns: config.header && config.header.columns,\n ignoreHiddenColumns:\n props.ignoreHiddenColumns ||\n props.ignoreHiddenColumns === undefined,\n selector: props.selector,\n }),\n );\n }\n\n // initial search\n if (props.keyword) dispatch(actions.SearchKeyword(props.keyword));\n }, [props]);\n\n useEffect(() => {\n if (!processor) return undefined;\n\n config.pipeline.register<object, object>(processor);\n\n return () => config.pipeline.unregister<object, object>(processor);\n }, [config, processor]);\n\n const debouncedOnInput = useCallback(\n debounce(\n (event: JSX.TargetedEvent<HTMLInputElement>) => {\n if (event.target instanceof HTMLInputElement) {\n dispatch(actions.SearchKeyword(event.target.value));\n }\n },\n processor instanceof ServerGlobalSearchFilter\n ? props.debounceTimeout || 250\n : 0,\n ),\n [props, processor],\n );\n\n return (\n <div className={className(classJoin('search', config.className?.search))}>\n <input\n type=\"search\"\n placeholder={_('search.placeholder')}\n aria-label={_('search.placeholder')}\n onInput={debouncedOnInput}\n className={classJoin(className('input'), className('search', 'input'))}\n defaultValue={state?.keyword || ''}\n />\n </div>\n );\n}\n","export const debounce = <F extends (...args: any[]) => any>(\n func: F,\n waitFor: number,\n) => {\n let timeout;\n\n return (...args: Parameters<F>): Promise<ReturnType<F>> =>\n new Promise((resolve) => {\n if (timeout) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(() => resolve(func(...args)), waitFor);\n });\n};\n","import Tabular from '../../tabular';\nimport {\n PipelineProcessor,\n PipelineProcessorProps,\n ProcessorType,\n} from '../processor';\n\ninterface PaginationLimitProps extends PipelineProcessorProps {\n page: number;\n limit: number;\n}\n\nclass PaginationLimit extends PipelineProcessor<Tabular, PaginationLimitProps> {\n protected validateProps(): void {\n if (isNaN(Number(this.props.limit)) || isNaN(Number(this.props.page))) {\n throw Error('Invalid parameters passed');\n }\n }\n\n get type(): ProcessorType {\n return ProcessorType.Limit;\n }\n\n protected _process(data: Tabular): Tabular {\n const page = this.props.page;\n const start = page * this.props.limit;\n const end = (page + 1) * this.props.limit;\n\n return new Tabular(data.rows.slice(start, end));\n }\n}\n\nexport default PaginationLimit;\n","import {\n PipelineProcessor,\n PipelineProcessorProps,\n ProcessorType,\n} from '../processor';\nimport { ServerStorageOptions } from '../../storage/server';\n\ninterface ServerPaginationLimitProps extends PipelineProcessorProps {\n page: number;\n limit: number;\n url?: (prevUrl: string, page: number, limit: number) => string;\n body?: (prevBody: BodyInit, page: number, limit: number) => BodyInit;\n}\n\nclass ServerPaginationLimit extends PipelineProcessor<\n ServerStorageOptions,\n ServerPaginationLimitProps\n> {\n get type(): ProcessorType {\n return ProcessorType.ServerLimit;\n }\n\n _process(options?: ServerStorageOptions): ServerStorageOptions {\n const updates = {};\n\n if (this.props.url) {\n updates['url'] = this.props.url(\n options.url,\n this.props.page,\n this.props.limit,\n );\n }\n\n if (this.props.body) {\n updates['body'] = this.props.body(\n options.body,\n this.props.page,\n this.props.limit,\n );\n }\n\n return {\n ...options,\n ...updates,\n };\n }\n}\n\nexport default ServerPaginationLimit;\n","import { h, Fragment } from 'preact';\nimport PaginationLimit from '../../pipeline/limit/pagination';\nimport { classJoin, className } from '../../util/className';\nimport ServerPaginationLimit from '../../pipeline/limit/serverPagination';\nimport { useConfig } from '../../hooks/useConfig';\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport { useTranslator } from '../../i18n/language';\n\nexport interface PaginationConfig {\n limit?: number;\n page?: number;\n summary?: boolean;\n nextButton?: boolean;\n prevButton?: boolean;\n buttonsCount?: number;\n resetPageOnUpdate?: boolean;\n server?: {\n url?: (prevUrl: string, page: number, limit: number) => string;\n body?: (prevBody: BodyInit, page: number, limit: number) => BodyInit;\n };\n}\n\nexport function Pagination() {\n const config = useConfig();\n const {\n server,\n summary = true,\n nextButton = true,\n prevButton = true,\n buttonsCount = 3,\n limit = 10,\n page = 0,\n resetPageOnUpdate = true,\n } = config.pagination as PaginationConfig;\n\n const processor = useRef<PaginationLimit | ServerPaginationLimit>(null);\n const [currentPage, setCurrentPage] = useState(page);\n const [total, setTotal] = useState(0);\n const _ = useTranslator();\n\n useEffect(() => {\n if (server) {\n processor.current = new ServerPaginationLimit({\n limit: limit,\n page: currentPage,\n url: server.url,\n body: server.body,\n });\n\n config.pipeline.register(processor.current);\n } else {\n processor.current = new PaginationLimit({\n limit: limit,\n page: currentPage,\n });\n\n config.pipeline.register(processor.current);\n }\n\n if (processor.current instanceof ServerPaginationLimit) {\n config.pipeline.on('afterProcess', (tabular) => setTotal(tabular.length));\n } else if (processor.current instanceof PaginationLimit) {\n // Pagination (all Limit processors) is the last step in the pipeline\n // and we assume that at this stage, we have the rows that we care about.\n // Let's grab the rows before processing Pagination and set total number of rows\n processor.current.on('beforeProcess', (tabular) =>\n setTotal(tabular.length),\n );\n }\n\n config.pipeline.on('updated', onUpdate);\n\n // we need to make sure that the state is set\n // to the default props when an error happens\n config.pipeline.on('error', () => {\n setTotal(0);\n setCurrentPage(0);\n });\n\n return () => {\n config.pipeline.unregister<object, object>(processor.current);\n config.pipeline.off('updated', onUpdate);\n };\n }, []);\n\n const onUpdate = (updatedProcessor) => {\n // this is to ensure that the current page is set to 0\n // when a processor is updated for some reason\n if (resetPageOnUpdate && updatedProcessor !== processor.current) {\n setCurrentPage(0);\n\n if (processor.current.props.page !== 0) {\n processor.current.setProps({\n page: 0,\n });\n }\n }\n };\n\n const pages = () => Math.ceil(total / limit);\n\n const setPage = (page: number) => {\n if (page >= pages() || page < 0 || page === currentPage) {\n return null;\n }\n\n setCurrentPage(page);\n\n processor.current.setProps({\n page: page,\n });\n };\n\n const renderPages = () => {\n if (buttonsCount <= 0) {\n return null;\n }\n\n // how many pagination buttons to render?\n const maxCount: number = Math.min(pages(), buttonsCount);\n\n let pagePivot = Math.min(currentPage, Math.floor(maxCount / 2));\n if (currentPage + Math.floor(maxCount / 2) >= pages()) {\n pagePivot = maxCount - (pages() - currentPage);\n }\n\n return (\n <Fragment>\n {pages() > maxCount && currentPage - pagePivot > 0 && (\n <Fragment>\n <button\n tabIndex={0}\n role=\"button\"\n onClick={() => setPage(0)}\n title={_('pagination.firstPage')}\n aria-label={_('pagination.firstPage')}\n className={config.className.paginationButton}\n >\n {_('1')}\n </button>\n <button\n tabIndex={-1}\n className={classJoin(\n className('spread'),\n config.className.paginationButton,\n )}\n >\n ...\n </button>\n </Fragment>\n )}\n\n {Array.from(Array(maxCount).keys())\n .map((i) => currentPage + (i - pagePivot))\n .map((i) => (\n <button\n tabIndex={0}\n role=\"button\"\n onClick={() => setPage(i)}\n className={classJoin(\n currentPage === i\n ? classJoin(\n className('currentPage'),\n config.className.paginationButtonCurrent,\n )\n : null,\n config.className.paginationButton,\n )}\n title={_('pagination.page', i + 1)}\n aria-label={_('pagination.page', i + 1)}\n >\n {_(`${i + 1}`)}\n </button>\n ))}\n\n {pages() > maxCount && pages() > currentPage + pagePivot + 1 && (\n <Fragment>\n <button\n tabIndex={-1}\n className={classJoin(\n className('spread'),\n config.className.paginationButton,\n )}\n >\n ...\n </button>\n <button\n tabIndex={0}\n role=\"button\"\n onClick={() => setPage(pages() - 1)}\n title={_('pagination.page', pages())}\n aria-label={_('pagination.page', pages())}\n className={config.className.paginationButton}\n >\n {_(`${pages()}`)}\n </button>\n </Fragment>\n )}\n </Fragment>\n );\n };\n\n const renderSummary = () => {\n return (\n <Fragment>\n {summary && total > 0 && (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className={classJoin(\n className('summary'),\n config.className.paginationSummary,\n )}\n title={_('pagination.navigate', currentPage + 1, pages())}\n >\n {_('pagination.showing')} <b>{_(`${currentPage * limit + 1}`)}</b>{' '}\n {_('pagination.to')}{' '}\n <b>{_(`${Math.min((currentPage + 1) * limit, total)}`)}</b>{' '}\n {_('pagination.of')} <b>{_(`${total}`)}</b>{' '}\n {_('pagination.results')}\n </div>\n )}\n