@carry0987/paginator
Version:
An advanced pagination library
1,138 lines (1,116 loc) • 116 kB
JavaScript
function reportError(...error) {
console.error(...error);
}
function throwError(message) {
throw new Error(message);
}
var errorUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
reportError: reportError,
throwError: throwError
});
function getElem(ele, mode, parent) {
// Return generic Element type or NodeList
if (typeof ele !== 'string') {
return ele;
}
let searchContext = document;
if (mode === null && parent) {
searchContext = parent;
}
else if (mode && mode instanceof Node && 'querySelector' in mode) {
searchContext = mode;
}
else if (parent && parent instanceof Node && 'querySelector' in parent) {
searchContext = parent;
}
// If mode is 'all', search for all elements that match, otherwise, search for the first match
// Casting the result as E or NodeList
return mode === 'all' ? searchContext.querySelectorAll(ele) : searchContext.querySelector(ele);
}
function hasParent(ele, selector, maxDepth = Infinity, returnElement = false) {
let parent = ele.parentElement;
let depth = 0;
while (parent && depth < maxDepth) {
if (parent.matches(selector)) {
return returnElement ? parent : true;
}
parent = parent.parentElement;
depth++;
}
return returnElement ? null : false;
}
function isObject(item) {
return typeof item === 'object' && item !== null && !isArray(item);
}
function isFunction(item) {
return typeof item === 'function';
}
function isString(item) {
return typeof item === 'string';
}
function isArray(item) {
return Array.isArray(item);
}
function isEmpty(value) {
// Check for number
if (typeof value === 'number') {
return false;
}
// Check for string
if (typeof value === 'string' && value.length === 0) {
return true;
}
// Check for array
if (isArray(value) && value.length === 0) {
return true;
}
// Check for object
if (isObject(value) && Object.keys(value).length === 0) {
return true;
}
// Check for any falsy values
return !value;
}
function deepMerge(target, ...sources) {
if (!sources.length)
return target;
const source = sources.shift();
if (source) {
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
const sourceKey = key;
const value = source[sourceKey];
const targetKey = key;
if (isObject(value) || isArray(value)) {
if (!target[targetKey] || typeof target[targetKey] !== 'object') {
target[targetKey] = isArray(value) ? [] : {};
}
deepMerge(target[targetKey], value);
}
else {
target[targetKey] = value;
}
}
}
}
return deepMerge(target, ...sources);
}
function shallowMerge(target, ...sources) {
sources.forEach((source) => {
if (source) {
Object.keys(source).forEach((key) => {
const targetKey = key;
target[targetKey] = source[targetKey];
});
}
});
return target;
}
function generateUUID$1() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0, v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
function setUrlParam(url, params, overwrite = true) {
let originalUrl;
let ignoreArray = [];
// Determine if URLSource object is being used
if (typeof url === 'object') {
originalUrl = url.url; // Extract the URL string
if (Array.isArray(url.ignore)) {
ignoreArray = url.ignore.map((part) => {
return part.startsWith('?') || part.startsWith('&') ? part.substring(1) : part;
});
}
else if (typeof url.ignore === 'string') {
let part = url.ignore;
if (part.startsWith('?') || part.startsWith('&')) {
part = part.substring(1);
}
ignoreArray.push(part);
}
}
else {
originalUrl = url;
}
const urlObj = new URL(originalUrl);
// If params is null, remove all
if (params === null) {
urlObj.search = ''; // Remove all search params
return urlObj.toString();
}
// Extract search string
let searchString = urlObj.search.substring(1); // Remove the leading '?'
// Split the search string into parameters
const paramsList = searchString.length > 0 ? searchString.split('&') : [];
const ignoredParams = [];
const otherParams = [];
for (const param of paramsList) {
if (ignoreArray.includes(param)) {
ignoredParams.push(param);
}
else {
otherParams.push(param);
}
}
const urlSearchParams = new URLSearchParams(otherParams.join('&'));
// Process remaining logic to set params
for (const [paramName, paramValue] of Object.entries(params)) {
const valueStr = paramValue === null ? '' : String(paramValue);
if (!overwrite && urlSearchParams.has(paramName)) {
continue;
}
urlSearchParams.set(paramName, valueStr);
}
const newSearchParams = ignoredParams.concat(urlSearchParams
.toString()
.split('&')
.filter((p) => p));
const finalSearchString = newSearchParams.join('&');
urlObj.search = finalSearchString ? '?' + finalSearchString : '';
return urlObj.toString();
}
// Append form data
function appendFormData(options, formData = new FormData()) {
const { data, parentKey = '' } = options;
if (data instanceof FormData) {
data.forEach((value, key) => {
formData.append(key, value);
});
}
else if (data !== null && typeof data === 'object') {
// Check if it is Blob or File, if so, add directly
if (data instanceof Blob || data instanceof File) {
const formKey = parentKey || 'file'; // If no key is specified, the default is 'file'
formData.append(formKey, data);
}
else {
// Traverse object properties
Object.keys(data).forEach((key) => {
const value = data[key];
const formKey = parentKey ? `${parentKey}[${key}]` : key;
if (value !== null && typeof value === 'object') {
// Recursively call to handle nested objects
appendFormData({ data: value, parentKey: formKey }, formData);
}
else if (value !== null) {
// Handle non-empty values, add directly
formData.append(formKey, String(value));
}
});
}
}
else if (data !== null) {
// Non-object and non-null values, add directly
formData.append(parentKey, data);
}
// If you don't want to add null values to FormData, you can do nothing here
// Or if you want to convert null to other forms, you can handle it here
return formData;
}
// Encode form data before send
function encodeFormData(data, parentKey = '') {
if (data instanceof FormData) {
return data;
}
const options = {
data: data,
parentKey: parentKey
};
return appendFormData(options);
}
// Convert FormData to URLParams
function formDataToURLParams(formData) {
const params = {};
formData.forEach((value, key) => {
// Assume formData values are strings, additional parsing can be added if needed
if (typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number' || value === null) {
params[key] = value;
}
else {
// Convert any non-string values to string if necessary
params[key] = value.toString();
}
});
return params;
}
// Convert a generic body to URLParams
function bodyToURLParams(body) {
const params = {};
if (body instanceof FormData) {
return formDataToURLParams(body);
}
else if (typeof body === 'object') {
// Handle generic object by iterating over its keys
Object.entries(body).forEach(([key, value]) => {
if (typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean' ||
value === null) {
params[key] = value;
}
else {
params[key] = JSON.stringify(value); // Serialize complex objects
}
});
}
return params;
}
// Fetch API
async function doFetch(options) {
const { url, method = 'GET', headers = {}, cache = 'no-cache', mode = 'cors', credentials = 'same-origin', body = null, beforeSend = null, success = null, error = null } = options;
let requestURL = url;
const initHeaders = headers instanceof Headers ? headers : new Headers(headers);
const init = {
method: method,
mode: mode,
headers: initHeaders,
cache: cache,
credentials: credentials
};
if (body && body !== null && method.toUpperCase() === 'GET') {
const params = bodyToURLParams(body);
requestURL = setUrlParam(typeof url === 'string' ? url : url.toString(), params, true);
}
else if (body && body !== null && ['PUT', 'POST', 'DELETE'].includes(method.toUpperCase())) {
let data = body;
if (!(body instanceof FormData)) {
data = JSON.stringify(body);
if (!(init.headers instanceof Headers)) {
init.headers = new Headers(init.headers);
}
init.headers.append('Content-Type', 'application/json');
}
init.body = data;
}
// Handle different types of URL
let request;
if (typeof requestURL === 'string' || requestURL instanceof URL) {
request = new Request(requestURL, init);
}
else if (requestURL instanceof Request) {
request = requestURL;
}
else {
throw new Error('Invalid URL type');
}
try {
const createRequest = await new Promise((resolve) => {
beforeSend?.();
resolve(request);
});
const response = await fetch(createRequest);
if (response.ok) {
if (typeof success === 'function') {
// Clone the response and parse the clone
const clonedResponse = response.clone();
const responseData = (await clonedResponse.json());
success?.(responseData);
}
}
else {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response;
}
catch (caughtError) {
const errorObj = caughtError instanceof Error ? caughtError : new Error(String(caughtError));
error?.(errorObj);
throw errorObj;
}
}
// Send data
async function sendData(options) {
const { url, data, method = 'POST', headers, cache, mode, credentials, success, error, beforeSend, encode = true } = options;
const fetchOptions = {
url: url,
method: method,
headers: headers,
cache: cache,
mode: mode,
credentials: credentials,
body: encode && method.toUpperCase() !== 'GET' ? encodeFormData(data) : data,
beforeSend: beforeSend,
success: success,
error: error
};
return (await doFetch(fetchOptions)).json();
}
// Alias for sendData
const fetchData = sendData;
class Utils {
static throwError = errorUtils.throwError;
static getElem = getElem;
static hasParent = hasParent;
static deepMerge = deepMerge;
static shallowMerge = shallowMerge;
static generateUUID = generateUUID$1;
static isEmpty = isEmpty;
static isObject = isObject;
static isArray = isArray;
static isString = isString;
static isFunction = isFunction;
static fetchData = fetchData;
static encodeFormData = encodeFormData;
static isNumeric(value) {
return !isNaN(parseFloat(value)) && isFinite(value);
}
static composeClassNames(...classNames) {
classNames = classNames.filter((className) => !!className); // Remove empty class names
return classNames.length > 0 ? classNames.join(' ') : '';
}
static isPageItem(element) {
const checkList = ['J-pagination-page', 'J-pagination-previous', 'J-pagination-next'];
const classList = element.classList;
for (let i = 0; i < checkList.length; i++) {
if (classList.contains(checkList[i])) {
return true;
}
}
return false;
}
}
class Base {
_id;
constructor(id) {
this._id = id || Utils.generateUUID();
}
get id() {
return this._id;
}
}
function camelCase(str) {
if (!str)
return '';
const words = str.split(' ');
// Do not convert strings that are already in camelCase format
if (words.length === 1 && /([a-z][A-Z])+/g.test(str)) {
return str;
}
return words
.map(function (word, index) {
// If it is the first word, lowercase all the chars
if (index == 0) {
return word.toLowerCase();
}
// If it is not the first word only upper case the first char and lowercase the rest
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
})
.join('');
}
var PluginPosition;
(function (PluginPosition) {
PluginPosition[PluginPosition["Header"] = 0] = "Header";
PluginPosition[PluginPosition["Body"] = 1] = "Body";
PluginPosition[PluginPosition["Footer"] = 2] = "Footer";
PluginPosition[PluginPosition["Cell"] = 3] = "Cell";
})(PluginPosition || (PluginPosition = {}));
/**
* Centralized logging lib
*
* This class needs some improvements but so far it has been used to have a coherent way to log
*/
let Logger$1 = class Logger {
format(message, type) {
return `[Paginator] [${type.toUpperCase()}]: ${message}`;
}
error(message, throwException = false) {
const msg = this.format(message, 'error');
if (throwException) {
throw Error(msg);
}
else {
console.error(msg);
}
}
warn(message) {
console.warn(this.format(message, 'warn'));
}
info(message) {
console.info(this.format(message, 'info'));
}
};
var log$1 = new Logger$1();
var n$1,l$2,u$3,t$2,i$2,r$2,o$2,e$2,f$3,c$2,s$2,a$2,h$3,p$2={},v$3=[],y$3=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,w$3=Array.isArray;function d$2(n,l){for(var u in l)n[u]=l[u];return n}function g$3(n){n&&n.parentNode&&n.parentNode.removeChild(n);}function _$3(l,u,t){var i,r,o,e={};for(o in u)"key"==o?i=u[o]:"ref"==o?r=u[o]:e[o]=u[o];if(arguments.length>2&&(e.children=arguments.length>3?n$1.call(arguments,2):t),"function"==typeof l&&null!=l.defaultProps)for(o in l.defaultProps) void 0===e[o]&&(e[o]=l.defaultProps[o]);return m$1(l,e,i,r,null)}function m$1(n,t,i,r,o){var e={type:n,props:t,key:i,ref:r,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:null==o?++u$3:o,__i:-1,__u:0};return null==o&&null!=l$2.vnode&&l$2.vnode(e),e}function b$2(){return {current:null}}function k$1(n){return n.children}function x$2(n,l){this.props=n,this.context=l;}function S(n,l){if(null==l)return n.__?S(n.__,n.__i+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?S(n):null}function C$1(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 C$1(n)}}function M(n){(!n.__d&&(n.__d=true)&&i$2.push(n)&&!$.__r++||r$2!=l$2.debounceRendering)&&((r$2=l$2.debounceRendering)||o$2)($);}function $(){for(var n,u,t,r,o,f,c,s=1;i$2.length;)i$2.length>s&&i$2.sort(e$2),n=i$2.shift(),s=i$2.length,n.__d&&(t=void 0,r=void 0,o=(r=(u=n).__v).__e,f=[],c=[],u.__P&&((t=d$2({},r)).__v=r.__v+1,l$2.vnode&&l$2.vnode(t),O(u.__P,t,r,u.__n,u.__P.namespaceURI,32&r.__u?[o]:null,f,null==o?S(r):o,!!(32&r.__u),c),t.__v=r.__v,t.__.__k[t.__i]=t,N$1(f,t,c),r.__e=r.__=null,t.__e!=o&&C$1(t)));$.__r=0;}function I(n,l,u,t,i,r,o,e,f,c,s){var a,h,y,w,d,g,_,m=t&&t.__k||v$3,b=l.length;for(f=P$1(u,l,m,f,b),a=0;a<b;a++)null!=(y=u.__k[a])&&(h=-1==y.__i?p$2:m[y.__i]||p$2,y.__i=a,g=O(n,y,h,i,r,o,e,f,c,s),w=y.__e,y.ref&&h.ref!=y.ref&&(h.ref&&B$2(h.ref,null,y),s.push(y.ref,y.__c||w,y)),null==d&&null!=w&&(d=w),(_=!!(4&y.__u))||h.__k===y.__k?f=A$2(y,f,n,_):"function"==typeof y.type&&void 0!==g?f=g:w&&(f=w.nextSibling),y.__u&=-7);return u.__e=d,f}function P$1(n,l,u,t,i){var r,o,e,f,c,s=u.length,a=s,h=0;for(n.__k=new Array(i),r=0;r<i;r++)null!=(o=l[r])&&"boolean"!=typeof o&&"function"!=typeof o?(f=r+h,(o=n.__k[r]="string"==typeof o||"number"==typeof o||"bigint"==typeof o||o.constructor==String?m$1(null,o,null,null,null):w$3(o)?m$1(k$1,{children:o},null,null,null):null==o.constructor&&o.__b>0?m$1(o.type,o.props,o.key,o.ref?o.ref:null,o.__v):o).__=n,o.__b=n.__b+1,e=null,-1!=(c=o.__i=L(o,u,f,a))&&(a--,(e=u[c])&&(e.__u|=2)),null==e||null==e.__v?(-1==c&&(i>s?h--:i<s&&h++),"function"!=typeof o.type&&(o.__u|=4)):c!=f&&(c==f-1?h--:c==f+1?h++:(c>f?h--:h++,o.__u|=4))):n.__k[r]=null;if(a)for(r=0;r<s;r++)null!=(e=u[r])&&0==(2&e.__u)&&(e.__e==t&&(t=S(e)),D$2(e,e));return t}function A$2(n,l,u,t){var i,r;if("function"==typeof n.type){for(i=n.__k,r=0;i&&r<i.length;r++)i[r]&&(i[r].__=n,l=A$2(i[r],l,u,t));return l}n.__e!=l&&(t&&(l&&n.type&&!l.parentNode&&(l=S(n)),u.insertBefore(n.__e,l||null)),l=n.__e);do{l=l&&l.nextSibling;}while(null!=l&&8==l.nodeType);return l}function H$1(n,l){return l=l||[],null==n||"boolean"==typeof n||(w$3(n)?n.some(function(n){H$1(n,l);}):l.push(n)),l}function L(n,l,u,t){var i,r,o,e=n.key,f=n.type,c=l[u],s=null!=c&&0==(2&c.__u);if(null===c&&null==n.key||s&&e==c.key&&f==c.type)return u;if(t>(s?1:0))for(i=u-1,r=u+1;i>=0||r<l.length;)if(null!=(c=l[o=i>=0?i--:r++])&&0==(2&c.__u)&&e==c.key&&f==c.type)return o;return -1}function T$2(n,l,u){"-"==l[0]?n.setProperty(l,null==u?"":u):n[l]=null==u?"":"number"!=typeof u||y$3.test(l)?u:u+"px";}function j$2(n,l,u,t,i){var r,o;n:if("style"==l)if("string"==typeof u)n.style.cssText=u;else {if("string"==typeof t&&(n.style.cssText=t=""),t)for(l in t)u&&l in u||T$2(n.style,l,"");if(u)for(l in u)t&&u[l]==t[l]||T$2(n.style,l,u[l]);}else if("o"==l[0]&&"n"==l[1])r=l!=(l=l.replace(f$3,"$1")),o=l.toLowerCase(),l=o in n||"onFocusOut"==l||"onFocusIn"==l?o.slice(2):l.slice(2),n.l||(n.l={}),n.l[l+r]=u,u?t?u.u=t.u:(u.u=c$2,n.addEventListener(l,r?a$2:s$2,r)):n.removeEventListener(l,r?a$2:s$2,r);else {if("http://www.w3.org/2000/svg"==i)l=l.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!=l&&"height"!=l&&"href"!=l&&"list"!=l&&"form"!=l&&"tabIndex"!=l&&"download"!=l&&"rowSpan"!=l&&"colSpan"!=l&&"role"!=l&&"popover"!=l&&l in n)try{n[l]=null==u?"":u;break n}catch(n){}"function"==typeof u||(null==u||false===u&&"-"!=l[4]?n.removeAttribute(l):n.setAttribute(l,"popover"==l&&1==u?"":u));}}function F$3(n){return function(u){if(this.l){var t=this.l[u.type+n];if(null==u.t)u.t=c$2++;else if(u.t<t.u)return;return t(l$2.event?l$2.event(u):u)}}}function O(n,u,t,i,r,o,e,f,c,s){var a,h,p,v,y,_,m,b,S,C,M,$,P,A,H,L,T,j=u.type;if(null!=u.constructor)return null;128&t.__u&&(c=!!(32&t.__u),o=[f=u.__e=t.__e]),(a=l$2.__b)&&a(u);n:if("function"==typeof j)try{if(b=u.props,S="prototype"in j&&j.prototype.render,C=(a=j.contextType)&&i[a.__c],M=a?C?C.props.value:a.__:i,t.__c?m=(h=u.__c=t.__c).__=h.__E:(S?u.__c=h=new j(b,M):(u.__c=h=new x$2(b,M),h.constructor=j,h.render=E$2),C&&C.sub(h),h.props=b,h.state||(h.state={}),h.context=M,h.__n=i,p=h.__d=!0,h.__h=[],h._sb=[]),S&&null==h.__s&&(h.__s=h.state),S&&null!=j.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=d$2({},h.__s)),d$2(h.__s,j.getDerivedStateFromProps(b,h.__s))),v=h.props,y=h.state,h.__v=u,p)S&&null==j.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),S&&null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else {if(S&&null==j.getDerivedStateFromProps&&b!==v&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(b,M),!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(b,h.__s,M)||u.__v==t.__v){for(u.__v!=t.__v&&(h.props=b,h.state=h.__s,h.__d=!1),u.__e=t.__e,u.__k=t.__k,u.__k.some(function(n){n&&(n.__=u);}),$=0;$<h._sb.length;$++)h.__h.push(h._sb[$]);h._sb=[],h.__h.length&&e.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(b,h.__s,M),S&&null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(v,y,_);});}if(h.context=M,h.props=b,h.__P=n,h.__e=!1,P=l$2.__r,A=0,S){for(h.state=h.__s,h.__d=!1,P&&P(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,P&&P(u),a=h.render(h.props,h.state,h.context),h.state=h.__s;}while(h.__d&&++A<25);h.state=h.__s,null!=h.getChildContext&&(i=d$2(d$2({},i),h.getChildContext())),S&&!p&&null!=h.getSnapshotBeforeUpdate&&(_=h.getSnapshotBeforeUpdate(v,y)),L=a,null!=a&&a.type===k$1&&null==a.key&&(L=V$1(a.props.children)),f=I(n,w$3(L)?L:[L],u,t,i,r,o,e,f,c,s),h.base=u.__e,u.__u&=-161,h.__h.length&&e.push(h),m&&(h.__E=h.__=null);}catch(n){if(u.__v=null,c||null!=o)if(n.then){for(u.__u|=c?160:128;f&&8==f.nodeType&&f.nextSibling;)f=f.nextSibling;o[o.indexOf(f)]=null,u.__e=f;}else {for(T=o.length;T--;)g$3(o[T]);z$1(u);}else u.__e=t.__e,u.__k=t.__k,n.then||z$1(u);l$2.__e(n,u,t);}else null==o&&u.__v==t.__v?(u.__k=t.__k,u.__e=t.__e):f=u.__e=q$3(t.__e,u,t,i,r,o,e,c,s);return (a=l$2.diffed)&&a(u),128&u.__u?void 0:f}function z$1(n){n&&n.__c&&(n.__c.__e=true),n&&n.__k&&n.__k.forEach(z$1);}function N$1(n,u,t){for(var i=0;i<t.length;i++)B$2(t[i],t[++i],t[++i]);l$2.__c&&l$2.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u);});}catch(n){l$2.__e(n,u.__v);}});}function V$1(n){return "object"!=typeof n||null==n||n.__b&&n.__b>0?n:w$3(n)?n.map(V$1):d$2({},n)}function q$3(u,t,i,r,o,e,f,c,s){var a,h,v,y,d,_,m,b=i.props,k=t.props,x=t.type;if("svg"==x?o="http://www.w3.org/2000/svg":"math"==x?o="http://www.w3.org/1998/Math/MathML":o||(o="http://www.w3.org/1999/xhtml"),null!=e)for(a=0;a<e.length;a++)if((d=e[a])&&"setAttribute"in d==!!x&&(x?d.localName==x:3==d.nodeType)){u=d,e[a]=null;break}if(null==u){if(null==x)return document.createTextNode(k);u=document.createElementNS(o,x,k.is&&k),c&&(l$2.__m&&l$2.__m(t,e),c=false),e=null;}if(null==x)b===k||c&&u.data==k||(u.data=k);else {if(e=e&&n$1.call(u.childNodes),b=i.props||p$2,!c&&null!=e)for(b={},a=0;a<u.attributes.length;a++)b[(d=u.attributes[a]).name]=d.value;for(a in b)if(d=b[a],"children"==a);else if("dangerouslySetInnerHTML"==a)v=d;else if(!(a in k)){if("value"==a&&"defaultValue"in k||"checked"==a&&"defaultChecked"in k)continue;j$2(u,a,null,d,o);}for(a in k)d=k[a],"children"==a?y=d:"dangerouslySetInnerHTML"==a?h=d:"value"==a?_=d:"checked"==a?m=d:c&&"function"!=typeof d||b[a]===d||j$2(u,a,d,b[a],o);if(h)c||v&&(h.__html==v.__html||h.__html==u.innerHTML)||(u.innerHTML=h.__html),t.__k=[];else if(v&&(u.innerHTML=""),I("template"==t.type?u.content:u,w$3(y)?y:[y],t,i,r,"foreignObject"==x?"http://www.w3.org/1999/xhtml":o,e,f,e?e[0]:i.__k&&S(i,0),c,s),null!=e)for(a=e.length;a--;)g$3(e[a]);c||(a="value","progress"==x&&null==_?u.removeAttribute("value"):null!=_&&(_!==u[a]||"progress"==x&&!_||"option"==x&&_!=b[a])&&j$2(u,a,_,b[a],o),a="checked",null!=m&&m!=u[a]&&j$2(u,a,m,b[a],o));}return u}function B$2(n,u,t){try{if("function"==typeof n){var i="function"==typeof n.__u;i&&n.__u(),i&&null==u||(n.__u=n(u));}else n.current=u;}catch(n){l$2.__e(n,t);}}function D$2(n,u,t){var i,r;if(l$2.unmount&&l$2.unmount(n),(i=n.ref)&&(i.current&&i.current!=n.__e||B$2(i,null,u)),null!=(i=n.__c)){if(i.componentWillUnmount)try{i.componentWillUnmount();}catch(n){l$2.__e(n,u);}i.base=i.__P=null;}if(i=n.__k)for(r=0;r<i.length;r++)i[r]&&D$2(i[r],u,t||"function"!=typeof n.type);t||g$3(n.__e),n.__c=n.__=n.__e=void 0;}function E$2(n,l,u){return this.constructor(n,u)}function G$1(u,t,i){var r,o,e,f;t==document&&(t=document.documentElement),l$2.__&&l$2.__(u,t),o=(r="function"=="undefined")?null:t.__k,e=[],f=[],O(t,u=(t).__k=_$3(k$1,null,[u]),o||p$2,p$2,t.namespaceURI,o?null:t.firstChild?n$1.call(t.childNodes):null,e,o?o.__e:t.firstChild,r,f),N$1(e,u,f);}function Q$1(n){function l(n){var u,t;return this.getChildContext||(u=new Set,(t={})[l.__c]=this,this.getChildContext=function(){return t},this.componentWillUnmount=function(){u=null;},this.shouldComponentUpdate=function(n){this.props.value!=n.value&&u.forEach(function(n){n.__e=true,M(n);});},this.sub=function(n){u.add(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u&&u.delete(n),l&&l.call(n);};}),n.children}return l.__c="__cC"+h$3++,l.__=n,l.Provider=l.__l=(l.Consumer=function(n,l){return n.children(l)}).contextType=l,l}n$1=v$3.slice,l$2={__e:function(n,l,u,t){for(var i,r,o;l=l.__;)if((i=l.__c)&&!i.__)try{if((r=i.constructor)&&null!=r.getDerivedStateFromError&&(i.setState(r.getDerivedStateFromError(n)),o=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(n,t||{}),o=i.__d),o)return i.__E=i}catch(l){n=l;}throw n}},u$3=0,t$2=function(n){return null!=n&&null==n.constructor},x$2.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!=this.state?this.__s:this.__s=d$2({},this.state),"function"==typeof n&&(n=n(d$2({},u),this.props)),n&&d$2(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),M(this));},x$2.prototype.forceUpdate=function(n){this.__v&&(this.__e=true,n&&this.__h.push(n),M(this));},x$2.prototype.render=k$1,i$2=[],o$2="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,e$2=function(n,l){return n.__v.__b-l.__v.__b},$.__r=0,f$3=/(PointerCapture)$|Capture$/i,c$2=0,s$2=F$3(false),a$2=F$3(true),h$3=0;
class Header extends Base {
_columns;
constructor() {
super();
this._columns = [];
}
get columns() {
return this._columns;
}
set columns(columns) {
this._columns = columns;
}
get visibleColumns() {
return this._columns.filter((column) => !column.hidden);
}
setID(columns) {
const cols = columns || this.columns || [];
for (const column of cols) {
if (!column.id && typeof column.name === 'string') {
// Let's guess the column ID if it's undefined
column.id = camelCase(column.name);
}
if (!column.id) {
log$1.error('Could not find a valid ID for one of the columns. Make sure a valid "id" is set for all columns.');
}
}
}
populatePlugins(pluginManager, columns) {
// Populate the cell columns
for (const column of columns) {
if (column.plugin !== undefined) {
pluginManager.add({
...column.plugin,
position: PluginPosition.Cell
});
}
}
}
/**
* Creates a new Header from a Config object
* This method generates a new ID for the Header and all nested elements
* It also populates the plugin manager with the plugins from the columns
*
* @param config
*/
static createFromConfig(config) {
const header = new Header();
if (config.options.columns) {
header.columns = Header.fromColumns(config.options.columns).columns;
}
else if (Header.isJsonPayload(config.options.data)) {
// If data[0] is an object but not an Array
// used for when a JSON payload is provided
header.columns = Object.keys(config.options.data[0]).map((name) => {
return { name: name };
});
}
if (header.columns.length) {
header.setID();
header.populatePlugins(config.internal.plugin, header.columns);
return header;
}
return undefined;
}
/**
* Returns an array of leaf columns (last columns in the tree)
*
* @param columns
*/
static leafColumns(columns) {
let result = [];
const cols = columns || [];
if (cols && cols.length) {
for (const col of cols) {
result.push(col);
}
}
return result;
}
/**
* Converts the tree-like format of Header to a tabular format
*
* @param columns
*/
static tabularFormat(columns) {
return columns.length ? [columns] : [];
}
static isJsonPayload(data) {
return !!data && data instanceof Array && typeof data[0] === 'object' && !(data[0] instanceof Array);
}
static fromColumns(columns) {
const header = new Header();
for (const column of columns) {
if (typeof column === 'string' || t$2(column)) {
header.columns.push({
name: column
});
}
else if (typeof column === 'object') {
const typedColumn = column;
// TColumn type
header.columns.push(typedColumn);
}
}
return header;
}
}
// Container status
var Status;
(function (Status) {
Status[Status["Init"] = 0] = "Init";
Status[Status["Loading"] = 1] = "Loading";
Status[Status["Loaded"] = 2] = "Loaded";
Status[Status["Rendered"] = 3] = "Rendered";
Status[Status["Error"] = 4] = "Error";
})(Status || (Status = {}));
/**
* Base Storage class. All storage implementation must inherit this class
*/
class Storage {
}
class MemoryStorage extends Storage {
data = () => [];
beforeDataLoad;
constructor(data, beforeDataLoad) {
super();
this.set(data);
this.beforeDataLoad = beforeDataLoad;
}
async get() {
if (Utils.isFunction(this.beforeDataLoad)) {
this.beforeDataLoad();
}
// Get the data
const data = await this.data();
return {
data: data,
total: data.length
};
}
set(data) {
if (data instanceof Array) {
this.data = () => data;
}
else if (data instanceof Function) {
this.data = data;
}
return this;
}
}
class ServerStorage extends Storage {
options;
beforeDataLoad;
constructor(options, beforeDataLoad) {
super();
this.options = options;
this.beforeDataLoad = beforeDataLoad;
}
handler(response) {
if (typeof this.options.handle === 'function') {
return this.options.handle(response);
}
return Promise.resolve(response);
}
async get(options) {
// `this.options` is the initial config object
// `options` is the runtime config passed by the pipeline (e.g. search component)
const opts = {
...this.options,
...options
};
const fetchParam = {
url: opts.url,
data: Utils.encodeFormData(opts.body || {}),
...opts.param
};
// If `options.data` is provided, the current ServerStorage
// implementation will be ignored and we let options.data to
// handle the request. Useful when HTTP client needs to be
// replaced with something else
if (Utils.isFunction(opts.data)) {
return opts.data(opts);
}
// If `options.param.beforeSend` is not a function and `this.beforeDataLoad` is a function
if (!Utils.isFunction(opts.param?.beforeSend) && Utils.isFunction(this.beforeDataLoad)) {
fetchParam.beforeSend = this.beforeDataLoad;
}
return await Utils.fetchData(fetchParam)
.then(this.handler.bind(this))
.then((res) => {
return {
data: opts.processData ? opts.processData(res) : [],
total: typeof opts.total === 'function' ? opts.total(res) : 0
};
})
.catch((error) => {
log$1.error(`Error in get method: ${error.message}`, true);
return Promise.reject(error);
});
}
}
class StorageUtils {
/**
* Accepts a Config object and tries to guess and return a Storage type
*
* @param config
*/
static createFromConfig(config) {
let storage = null;
if (config.options.data) {
storage = new MemoryStorage(config.options.data, config.options.beforeDataLoad);
}
if (config.options.server) {
storage = new ServerStorage(config.options.server, config.options.beforeDataLoad);
}
if (!storage) {
throw new Error('Could not determine the storage type');
}
return storage;
}
}
var ProcessorType;
(function (ProcessorType) {
ProcessorType[ProcessorType["Initiator"] = 0] = "Initiator";
ProcessorType[ProcessorType["ServerLimit"] = 1] = "ServerLimit";
ProcessorType[ProcessorType["Extractor"] = 2] = "Extractor";
ProcessorType[ProcessorType["Transformer"] = 3] = "Transformer";
ProcessorType[ProcessorType["Limit"] = 4] = "Limit";
})(ProcessorType || (ProcessorType = {}));
/**
* Centralized logging lib
*
* This class needs some improvements but so far it has been used to have a coherent way to log
*/
class Logger {
format(message, type) {
return `[Pipeline-JS] [${type.toUpperCase()}]: ${message}`;
}
error(message, throwException = false) {
const msg = this.format(message, 'error');
if (throwException) {
throw Error(msg);
}
else {
console.error(msg);
}
}
warn(message) {
console.warn(this.format(message, 'warn'));
}
info(message) {
console.info(this.format(message, 'info'));
}
}
var log = new Logger();
let EventEmitter$1 = class EventEmitter {
// Initialize callbacks with an empty object
callbacks = {};
/**
* Initializes the callbacks for a given event. If the event does not already have
* an entry in the callbacks object, a new empty array is created for it.
* @param event - The name of the event to initialize. If not provided, it checks
* for undefined events and initializes them if needed.
*/
init(event) {
if (event && !this.callbacks[event]) {
this.callbacks[event] = [];
}
}
/**
* Checks if a listener is a valid function. Throws a TypeError if the listener
* is not a function.
* @param listener - The listener to check. Should be a function that either returns void
* or a Promise that resolves to void.
*/
checkListener(listener) {
if (typeof listener !== 'function') {
throw new TypeError('The listener must be a function');
}
}
/**
* Checks whether a specific event has been registered within the emitter.
* @param event - The name of the event to check for existence.
* @returns A boolean indicating whether the event exists in the callbacks.
*/
hasEvent(event) {
return this.callbacks[event] !== undefined;
}
/**
* Retrieves all the listeners currently registered to the emitter.
* @returns An object containing all registered events and their associated listeners.
* Each key is a string representing the event name, mapping to an array of
* listener functions.
*/
listeners() {
return this.callbacks;
}
/**
* Adds a listener function for the specified event. This method is an alias for the
* `on` method, purely for semantic purposes.
* @param event - The name of the event to listen to.
* @param listener - The function to invoke when the event is emitted. Can be asynchronous.
* @returns The instance of the EventEmitter for method chaining.
*/
addListener(event, listener) {
return this.on(event, listener);
}
/**
* Clears all listeners for a specific event or, if no event is provided, clears all
* listeners for all events.
* @param event - Optional. The name of the event whose listeners should be cleared.
* If omitted, all event listeners are cleared.
* @returns The instance of the EventEmitter for method chaining.
*/
clearListener(event) {
if (event) {
this.callbacks[event] = [];
}
else {
this.callbacks = {};
}
return this;
}
/**
* Adds a listener for a specific event type. Initializes the event if it's not already
* present and ensures the listener is valid.
* @param event - The name of the event to listen to.
* @param listener - The function to call when the event is emitted. Can return a promise.
* @returns The instance of the EventEmitter for method chaining.
*/
on(event, listener) {
this.checkListener(listener);
this.init(event);
this.callbacks[event].push(listener);
return this;
}
/**
* Removes a listener from a specific event. If no listener is provided, all listeners
* for the event are removed.
* @param event - The name of the event to remove a listener from.
* @param listener - Optional. The specific listener to remove. If not provided, all
* listeners for the event are removed.
* @returns The instance of the EventEmitter for method chaining.
*/
off(event, listener) {
if (listener) {
this.checkListener(listener);
}
const eventName = event;
this.init();
if (!this.callbacks[eventName] || this.callbacks[eventName].length === 0) {
// There is no callbacks with this key
return this;
}
if (listener) {
this.callbacks[eventName] = this.callbacks[eventName].filter((value) => value !== listener);
}
else {
// Remove all listeners if no specific listener is provided
this.callbacks[eventName] = [];
}
return this;
}
/**
* Emits an event, invoking all registered listeners for that event with the provided
* arguments. If any listener returns a promise, the method itself will return a promise
* that resolves when all listeners have been processed.
* @param event - The name of the event to emit.
* @param args - Arguments to pass to each listener when invoked.
* @returns A boolean or a promise resolving to a boolean indicating if listeners were
* successfully called and resolved/ran without error.
*/
emit(event, ...args) {
const eventName = event;
// Initialize the event
this.init(eventName);
// If there are no callbacks, return false
if (this.callbacks[eventName].length <= 0) {
return false;
}
// Get all results
const results = this.callbacks[eventName].map((callback) => {
try {
// Execute callback and capture the result
const result = callback(...args);
// If result is a promise, wrap it in Promise.resolve to handle uniformly
return result instanceof Promise ? result : Promise.resolve(result);
}
catch (e) {
console.error(`Error in event listener for event: ${eventName}`, e); // Logging error
// Even if an error occurs, continue processing other callbacks
return Promise.resolve();
}
});
// Check if any result is a promise
const hasPromise = results.some((result) => result instanceof Promise);
// If there is at least one promise, return a promise that resolves when all promises resolve
if (hasPromise) {
return Promise.all(results)
.then(() => true)
.catch((e) => {
console.error(`Error handling promises for event: ${eventName}`, e); // Logging error
return false;
});
}
else {
// If no promises, return true
return true;
}
}
/**
* Adds a listener for a specific event that will only be invoked once. After the first
* invocation, the listener will be automatically removed.
* @param event - The name of the event to listen to once.
* @param listener - The function to invoke once when the event is emitted.
* @returns The instance of the EventEmitter for method chaining.
*/
once(event, listener) {
this.checkListener(listener);
const onceListener = (...args) => {
// Use a sync wrapper to ensure the listener is removed immediately after execution
const result = listener(...args);
// Remove the listener immediately
this.off(event, onceListener);
// Handle async listeners by wrapping the result in Promise.resolve
return result instanceof Promise ? result : Promise.resolve(result);
};
return this.on(event, onceListener);
}
};
class Pipeline extends EventEmitter$1 {
// Available steps for this pipeline
_steps = new Map();
// Used to cache the results of processors using their id field
cache = new Map();
// Keeps the index of the last updated processor in the registered
// processors list and will be used to invalidate the cache
// -1 means all new processors should be processed
lastProcessorIndexUpdated = -1;
constructor(steps) {
super();
if (steps) {
steps.forEach((step) => this.register(step));
}
}
/**
* Clears the `cache` array
*/
clearCache() {
this.cache = new Map();
this.lastProcessorIndexUpdated = -1;
}
/**
* Registers a new processor
*
* @param processor
* @param priority
*/
register(processor, priority = -1) {
if (!processor) {
throw Error('Processor is not defined');
}
if (processor.type === null) {
throw Error('Processor type is not defined');
}
if (this.findProcessorIndexByID(processor.id) > -1) {
throw Error(`Processor ID ${processor.id} is already defined`);
}
// Binding the propsUpdated callback to the Pipeline
processor.on('propsUpdated', this.processorPropsUpdated.bind(this, processor));
this.addProcessorByPriority(processor, priority);
this.afterRegistered(processor);
return processor;
}
/**
* Tries to register a new processor
* @param processor
* @param priority
*/
tryRegister(processor, priority = -1) {
try {
return this.register(processor, priority);
}
catch (_) {
return undefined;
}
}
/**
* Removes a processor from the list
*
* @param processor
*/
unregister(processor) {
if (!processor)
return;
if (this.findProcessorIndexByID(processor.id) === -1)
return;
const subSteps = this._steps.get(processor.type);
if (subSteps && subSteps.length) {
this._steps.set(processor.type, subSteps.filter((proc) => proc.id !== processor.id));
// Remove the event listener
processor.off('propsUpdated', this.processorPropsUpdated.bind(this, processor));
this.emit('updated', processor);
}
}
/**
* Registers a new processor
*
* @param processor
* @param priority
*/
addProcessorByPriority(processor, priority = -1) {
let subSteps = this._steps.get(processor.type);
if (!subSteps) {
const newSubStep = [];
this._steps.set(processor.type, newSubStep);
subSteps = newSubStep;
}
if (priority < 0 || priority >= subSteps.length) {
subSteps.push(processor);
}
else {
subSteps.splice(priority, 0, processor);
}
}
/**
* Flattens the _steps Map and returns a list of steps with their correct priorities
*/
get steps() {
let steps = [];
for (const type of this.getSortedProcessorTypes()) {
const subSteps = this._steps.get(type);
if (subSteps && subSteps.length) {
steps = steps.concat(subSteps);
}
}
// To remove any undefined elements
return steps.filter((s) => s);
}
/**
* Accepts ProcessType and returns an array of the registered processes
* with the give type
*
* @param type
*/
getStepsByType(type) {
return this.steps.filter((process) => process.type === type);
}
/**
* Returns a list of ProcessorType according to their priority
*/
getSortedProcessorTypes() {
return Array.from(this._steps.keys()).sort((a, b) => Number(a) - Number(b));
}
async process(data) {
const lastProcessorIndexUpdated = this.lastProcessorIndexUpdated;
const steps = this.steps;
let prev = data;
try {
for (const processor of steps) {
const processorIndex = this.findProcessorIndexByID(processor.id);
if (processorIndex >= lastProcessorIndexUpdated) {
// We should execute process() here since the last
// updated processor was before "processor".
// This is to ensure that we always have correct and up to date
// data from processors and also to skip them when necessary
prev = await processor.process(prev);
this.cache.set(processor.id, prev);
}
else {
// Cached results already exist
prev = this.cache.get(processor.id);
if (prev === undefined) {
prev = await processor.process(prev);
}
}
}
}
catch (e) {
log.error(e);
// Trigger the onError callback
this.emit('error', prev);
throw e;
}
// Means the pipeline is up to date
this.lastProcessorIndexUpdated = steps.length;
// Triggers the afterProcess callbacks with the results
this.emit('afterProcess', prev);
return prev;
}
async processInParallel(data) {
const steps = this.steps;
// No need for processor index check because all processors run in parallel
const results = await Promise.all(steps.map((processor) => processor.process(data)));
results.forEach((result, index) => this.cache.set(steps[index].id, result));
this.lastProcessorIndexUpdated = steps.length;
this.emit('afterProcess', results);
return results;
}
/**
* Removes all processors from the pipeline
*/
clearProcessors() {
this._steps.clear();
this.clearCache();
}
/**
* Returns processor by ID
*
* @param id
*/
getProcessorByID(processorID) {
const index = this.findProcessorIndexByID(processorID);
return index > -1 ? this.steps[index] : null;
}
/**
* Returns the registered processor's index in _steps array
*
* @param processorID
*/
findProcessorIndexByID(processorID) {
return this.steps.findIndex((p) => p.id == processorID);
}
async runProcessorByID(processorID, dataOrRunAllFollowing, runAllFollowing = true) {
const processorIndex = this.findProcessorIndexByID(processorID);
if (processorIndex === -1) {
throw Error(`Processor ID ${processorID} not found`);
}
// Determine the actual type of dataOrRunAllFollowing
let data;
if (typeof dataOrRunAllFollowing === 'boolean') {
runAllFollowing = dataOrRunAllFollowing;
}
else {
data = dataOrRunAllFollowing;
}
if (runAllFollowing) {
this.lastProcessorIndexUpdated = processorIndex;
// Clear cache for all processors after the rerun processor
this.clearCacheAfterProcessorIndex(processorIndex);
}
else {
// If not re-running all, just clear the cache for the specific processor
this.cache.delete(processorID);
}
return data ? this.process(data) : this.process();
}
/**
* Clears the cache for all processors after the specified index
*
* @param index
*/
clearCacheAfterProcessorIndex(index) {
this.steps.slice(index).forEach((processor) => {
this.cache.delete(processor.id);
});
}
/**
* Sets the last updates processors index locally
* This is used to invalid or skip a processor in
* the process() method
*/
setLastProcessorIndex(processor) {
const processorIndex = this.findProcessorIndexByID(processor.id);
if (this.lastProcessorIndexUpdated > processorIndex) {
this.lastProcessorIndexUpdated = processorIndex;
}
}
processorPropsUpdated(processor) {
this.setLastProcessorIndex(processor);
this.emit('propsUpdated');
this.emit('updated', processor);
}
afterRegistered(processor) {
this.setLastProcessorIndex(processor);
this.emit('afterRegister');
this.emit('updated', processor);
}
}
function deepEqual(obj1, obj2) {