@agile-team/mach-table 0.18.1 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ "use strict";var D=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var C=(e,r)=>{for(var n in r)D(e,n,{get:r[n],enumerable:!0})},I=(e,r,n,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let t of x(r))!N.call(e,t)&&t!==n&&D(e,t,{get:()=>r[t],enumerable:!(o=R(r,t))||o.enumerable});return e};var S=e=>I(D({},"__esModule",{value:!0}),e);var K={};C(K,{createWorkerDataProcessor:()=>v,installGridDataWorker:()=>G,processFieldDataRequest:()=>k});module.exports=S(K);var O=new Set(["__proto__","prototype","constructor"]);function L(e){return typeof e!="string"||e.length===0?!1:e.split(".").every(n=>n.length>0&&!O.has(n))}function f(e,r){if(e==null||!L(r))return;if(r.indexOf(".")<0)return e[r];let o=e,t=0;for(;t<r.length;){if(o==null)return;let a=r.indexOf(".",t);if(a<0){o=o[r.slice(t)];break}o=o[r.slice(t,a)],t=a+1}return o}var T=typeof Intl<"u"?new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"}):null;function M(e,r){let n=e==null||e==="",o=r==null||r==="";if(n&&o)return 0;if(n)return 1;if(o)return-1;if(typeof e=="number"&&typeof r=="number")return isNaN(e)&&isNaN(r)?0:isNaN(e)?1:isNaN(r)?-1:e-r;if(e instanceof Date&&r instanceof Date)return e.getTime()-r.getTime();if(typeof e=="boolean"&&typeof r=="boolean")return e===r?0:e?1:-1;let t=String(e),a=String(r);return T?T.compare(t,a):t.localeCompare(a)}function q(e){return e==null?"":String(e).toLowerCase()}function _(e,r,n){let o=q(e),t=r.map(a=>{let s=(a.value??"").toLowerCase();switch(a.match){case"contains":return o.includes(s);case"notContains":return!o.includes(s);case"equals":return o===s;case"notEquals":return o!==s;case"startsWith":return o.startsWith(s);case"endsWith":return o.endsWith(s);case"blank":return o==="";case"notBlank":return o!=="";default:return!0}});return t.length===0?!0:n==="or"?t.some(Boolean):t.every(Boolean)}function A(e,r,n){let o=r.map(t=>{let a=e==null||e==="";if(t.match==="blank")return a;if(t.match==="notBlank")return!a;if(a)return!1;let s=typeof e=="number"?e:Number(e);if(isNaN(s))return!1;let i=t.value;if(i==null||isNaN(i))return!1;switch(t.match){case"equals":return s===i;case"notEquals":return s!==i;case"lessThan":return s<i;case"lessThanOrEqual":return s<=i;case"greaterThan":return s>i;case"greaterThanOrEqual":return s>=i;case"inRange":return s>=i&&s<=(t.value2??i);default:return!0}});return o.length===0?!0:n==="or"?o.some(Boolean):o.every(Boolean)}function m(e){if(e==null||e==="")return null;if(e instanceof Date)return isNaN(e.getTime())?null:e.getTime();if(typeof e=="number")return e;let r=Date.parse(String(e));return isNaN(r)?null:r}function B(e,r,n){let o=r.map(t=>{let a=m(e)==null;if(t.match==="blank")return a;if(t.match==="notBlank")return!a;if(a)return!1;let s=m(e),i=t.value!=null?m(t.value):null;if(i==null)return!1;switch(t.match){case"equals":return s===i;case"notEquals":return s!==i;case"lessThan":return s<i;case"greaterThan":return s>i;case"inRange":{let d=t.value2!=null?m(t.value2):null;return d!=null?s>=i&&s<=d:s>=i}default:return!0}});return o.length===0?!0:n==="or"?o.some(Boolean):o.every(Boolean)}function j(e,r){return r.length===0?!0:r.some(n=>n==null&&e==null||n===e)}function b(e,r){let n=r.type!=="set"&&r.operator==="or"?"or":"and";switch(r.type){case"text":return _(e,r.conditions,n);case"number":return A(e,r.conditions,n);case"date":return B(e,r.conditions,n);case"set":return j(e,r.values);default:return!0}}function w(e,r,n){if(e.kind==="condition"){let t=n.get(e.colId);return t==null||b(f(r,t),e.filter)}let o=e.operator==="or"?e.children.some(t=>w(t,r,n)):e.children.every(t=>w(t,r,n));return e.not?!o:o}function H(e,r,n){for(let[o,t]of Object.entries(r.filterModel)){let a=n.get(o);if(a!=null&&!b(f(e,a),t))return!1}return!0}function Q(e,r,n){return n.every(o=>r.columns.some(t=>{let a=t.field==null?null:f(e,t.field);return String(a??"").toLowerCase().includes(o)}))}function U(e,r,n,o){return!H(e,r,n)||r.advancedFilterModel&&!w(r.advancedFilterModel.root,e,n)?!1:Q(e,r,o)}function z(e,r,n){r.sortModel.length!==0&&e.sort((o,t)=>{for(let a of r.sortModel){let s=n.get(a.colId);if(!s)continue;let i=M(f(o.data,s),f(t.data,s));if(i!==0)return a.direction==="desc"?-i:i}return o.order-t.order})}function J(e){if(!e?.())return;let r=new Error("Data processing aborted");throw r.name="AbortError",r}async function k(e,r={}){let n=new Map(e.columns.flatMap(s=>s.field?[[s.colId,s.field]]:[])),o=e.quickFilterText?.trim().toLowerCase().split(/\s+/).filter(Boolean)??[],t=Math.max(100,Math.trunc(r.yieldEvery??2e3)),a=[];for(let s=0;s<e.rows.length;s++){J(r.isCancelled),s>0&&s%t===0&&await new Promise(d=>setTimeout(d,0));let i=e.rows[s];U(i.data,e,n,o)&&a.push({id:i.id,data:i.data,order:s})}return z(a,e,n),{rowIds:a.map(s=>s.id)}}function G(e){let r=new Set;e.addEventListener("message",n=>{let o=n.data;if(o.type==="mach-table:cancel"){r.add(o.requestId);return}let{requestId:t}=o;r.delete(t),k(o.payload,{isCancelled:()=>r.has(t)}).then(a=>{r.has(t)||e.postMessage({type:"mach-table:result",requestId:t,rowIds:a.rowIds})}).catch(a=>{r.has(t)||e.postMessage({type:"mach-table:error",requestId:t,message:a instanceof Error?a.message:String(a)})}).finally(()=>r.delete(t))})}function h(e){if(e instanceof Error)return e;let r=new Error(typeof e=="string"?e:"Data processing aborted");return r.name="AbortError",r}function v(e,r={}){let n=null,o=0,t=!1,a=new Map,s=c=>{for(let l of a.values())l.signal.removeEventListener("abort",l.abort),l.reject(c);a.clear()},i=c=>{let l=c.data;if(!l||l.type!=="mach-table:result"&&l.type!=="mach-table:error")return;let u=a.get(l.requestId);u&&(a.delete(l.requestId),u.signal.removeEventListener("abort",u.abort),l.type==="mach-table:result"?u.resolve({rowIds:l.rowIds}):u.reject(new Error(l.message)))},d=c=>{c.removeEventListener("message",i),c.removeEventListener("error",P)},P=c=>{let l=n;n=null,l&&(d(l),l.terminate()),s(c.error??new Error(c.message||"Grid data worker failed"))},E=()=>{if(n)return n;if(t)throw new Error("Worker data processor has been destroyed");return n=e(),n.addEventListener("message",i),n.addEventListener("error",P),n};return{process(c){if(c.signal.aborted)return Promise.reject(h(c.signal.reason));let l=++o;return new Promise((u,y)=>{let g=()=>{a.get(l)&&(a.delete(l),n?.postMessage({type:"mach-table:cancel",requestId:l}),y(h(c.signal.reason)))};a.set(l,{resolve:u,reject:y,signal:c.signal,abort:g}),c.signal.addEventListener("abort",g,{once:!0});let{signal:W,...F}=c;try{E().postMessage({type:"mach-table:process",requestId:l,payload:F})}catch(p){a.delete(l),c.signal.removeEventListener("abort",g),y(p instanceof Error?p:new Error(String(p)))}})},destroy(){if(!t){if(t=!0,s(h("Worker data processor destroyed")),n){let c=n;d(c),r.terminateOnDestroy!==!1&&c.terminate()}n=null}}}}0&&(module.exports={createWorkerDataProcessor,installGridDataWorker,processFieldDataRequest});
2
+ //# sourceMappingURL=worker.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/worker.ts","../src/lib/path.ts","../src/lib/compare.ts","../src/services/filterService.ts","../src/lib/workerDataProcessor.ts"],"sourcesContent":["export {\n createWorkerDataProcessor,\n installGridDataWorker,\n processFieldDataRequest\n} from \"./lib/workerDataProcessor\";\nexport type {\n GridWorkerProcessMessage,\n GridWorkerCancelMessage,\n GridWorkerRequestMessage,\n GridWorkerResponseMessage,\n WorkerDataProcessorOptions,\n GridDataProcessorPayload,\n FieldDataProcessorOptions,\n GridDataWorkerScope\n} from \"./lib/workerDataProcessor\";\nexport type {\n GridDataProcessor,\n GridDataProcessorColumn,\n GridDataProcessorRequest,\n GridDataProcessorResult,\n GridDataProcessorRow\n} from \"./types/options\";\n","const UNSAFE_PATH_SEGMENTS = new Set([\"__proto__\", \"prototype\", \"constructor\"]);\n\nexport function isSafePath(path: string): boolean {\n if (typeof path !== \"string\" || path.length === 0) return false;\n const parts = path.split(\".\");\n return parts.every((part) => part.length > 0 && !UNSAFE_PATH_SEGMENTS.has(part));\n}\n\nexport function getByPath(obj: any, path: string): any {\n if (obj == null) return undefined;\n if (!isSafePath(path)) return undefined;\n const dot = path.indexOf(\".\");\n if (dot < 0) return obj[path];\n let cur = obj;\n let start = 0;\n while (start < path.length) {\n if (cur == null) return undefined;\n const idx = path.indexOf(\".\", start);\n if (idx < 0) {\n cur = cur[path.slice(start)];\n break;\n }\n cur = cur[path.slice(start, idx)];\n start = idx + 1;\n }\n return cur;\n}\n\nexport function setByPath(obj: any, path: string, value: any): boolean {\n if (obj == null || !isSafePath(path)) return false;\n const parts = path.split(\".\");\n let cur = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if ((typeof cur !== \"object\" && typeof cur !== \"function\") || cur === null) return false;\n if (cur[parts[i]] == null) cur[parts[i]] = {};\n cur = cur[parts[i]];\n }\n if ((typeof cur !== \"object\" && typeof cur !== \"function\") || cur === null) return false;\n cur[parts[parts.length - 1]] = value;\n return true;\n}\n","const collator = typeof Intl !== \"undefined\"\n ? new Intl.Collator(undefined, { numeric: true, sensitivity: \"base\" })\n : null;\n\nexport function defaultComparator(valueA: any, valueB: any): number {\n const aEmpty = valueA == null || valueA === \"\";\n const bEmpty = valueB == null || valueB === \"\";\n if (aEmpty && bEmpty) return 0;\n if (aEmpty) return 1;\n if (bEmpty) return -1;\n\n if (typeof valueA === \"number\" && typeof valueB === \"number\") {\n if (isNaN(valueA) && isNaN(valueB)) return 0;\n if (isNaN(valueA)) return 1;\n if (isNaN(valueB)) return -1;\n return valueA - valueB;\n }\n if (valueA instanceof Date && valueB instanceof Date) {\n return valueA.getTime() - valueB.getTime();\n }\n if (typeof valueA === \"boolean\" && typeof valueB === \"boolean\") {\n return valueA === valueB ? 0 : valueA ? 1 : -1;\n }\n const a = String(valueA);\n const b = String(valueB);\n return collator ? collator.compare(a, b) : a.localeCompare(b);\n}\n","import type { ColumnFilter, FilterModel, TextFilterCondition, NumberFilterCondition, DateFilterCondition } from \"../types/colDef\";\nimport type { AdvancedFilterModel, AdvancedFilterNode } from \"../types/advancedFilter\";\nimport type { RowNode } from \"../types/row\";\nimport type { Column } from \"./column\";\n\nfunction textOf(value: any): string {\n return value == null ? \"\" : String(value).toLowerCase();\n}\n\nexport function evaluateTextFilter(value: any, conditions: TextFilterCondition[], operator: \"and\" | \"or\"): boolean {\n const v = textOf(value);\n const results = conditions.map((c) => {\n const fv = (c.value ?? \"\").toLowerCase();\n switch (c.match) {\n case \"contains\":\n return v.includes(fv);\n case \"notContains\":\n return !v.includes(fv);\n case \"equals\":\n return v === fv;\n case \"notEquals\":\n return v !== fv;\n case \"startsWith\":\n return v.startsWith(fv);\n case \"endsWith\":\n return v.endsWith(fv);\n case \"blank\":\n return v === \"\";\n case \"notBlank\":\n return v !== \"\";\n default:\n return true;\n }\n });\n if (results.length === 0) return true;\n return operator === \"or\" ? results.some(Boolean) : results.every(Boolean);\n}\n\nexport function evaluateNumberFilter(value: any, conditions: NumberFilterCondition[], operator: \"and\" | \"or\"): boolean {\n const results = conditions.map((c) => {\n const isBlank = value == null || value === \"\";\n if (c.match === \"blank\") return isBlank;\n if (c.match === \"notBlank\") return !isBlank;\n if (isBlank) return false;\n const n = typeof value === \"number\" ? value : Number(value);\n if (isNaN(n)) return false;\n const f = c.value;\n if (f == null || isNaN(f)) return false;\n switch (c.match) {\n case \"equals\":\n return n === f;\n case \"notEquals\":\n return n !== f;\n case \"lessThan\":\n return n < f;\n case \"lessThanOrEqual\":\n return n <= f;\n case \"greaterThan\":\n return n > f;\n case \"greaterThanOrEqual\":\n return n >= f;\n case \"inRange\":\n return n >= f && n <= (c.value2 ?? f);\n default:\n return true;\n }\n });\n if (results.length === 0) return true;\n return operator === \"or\" ? results.some(Boolean) : results.every(Boolean);\n}\n\nfunction toTime(value: any): number | null {\n if (value == null || value === \"\") return null;\n if (value instanceof Date) return isNaN(value.getTime()) ? null : value.getTime();\n if (typeof value === \"number\") return value;\n const t = Date.parse(String(value));\n return isNaN(t) ? null : t;\n}\n\nexport function evaluateDateFilter(value: any, conditions: DateFilterCondition[], operator: \"and\" | \"or\"): boolean {\n const results = conditions.map((c) => {\n const isBlank = toTime(value) == null;\n if (c.match === \"blank\") return isBlank;\n if (c.match === \"notBlank\") return !isBlank;\n if (isBlank) return false;\n const t = toTime(value)!;\n const f = c.value != null ? toTime(c.value) : null;\n if (f == null) return false;\n switch (c.match) {\n case \"equals\":\n return t === f;\n case \"notEquals\":\n return t !== f;\n case \"lessThan\":\n return t < f;\n case \"greaterThan\":\n return t > f;\n case \"inRange\": {\n const f2 = c.value2 != null ? toTime(c.value2) : null;\n return f2 != null ? t >= f && t <= f2 : t >= f;\n }\n default:\n return true;\n }\n });\n if (results.length === 0) return true;\n return operator === \"or\" ? results.some(Boolean) : results.every(Boolean);\n}\n\nexport function evaluateSetFilter(value: any, filterValues: (string | number | null)[]): boolean {\n if (filterValues.length === 0) return true;\n return filterValues.some((v) => (v == null && value == null) || v === value);\n}\n\nexport function evaluateColumnFilter(value: any, filter: ColumnFilter): boolean {\n const operator = filter.type !== \"set\" && filter.operator === \"or\" ? \"or\" : \"and\";\n switch (filter.type) {\n case \"text\":\n return evaluateTextFilter(value, filter.conditions, operator);\n case \"number\":\n return evaluateNumberFilter(value, filter.conditions, operator);\n case \"date\":\n return evaluateDateFilter(value, filter.conditions, operator);\n case \"set\":\n return evaluateSetFilter(value, filter.values);\n default:\n return true;\n }\n}\n\nfunction evaluateAdvancedNode(\n node: AdvancedFilterNode,\n columns: ReadonlyMap<string, Column>,\n row: RowNode<any>,\n getCellValue: (row: RowNode<any>, column: Column) => any\n): boolean {\n if (node.kind === \"condition\") {\n const column = columns.get(node.colId);\n return !column || evaluateColumnFilter(getCellValue(row, column), node.filter);\n }\n const passed = node.operator === \"or\"\n ? node.children.some((child) => evaluateAdvancedNode(child, columns, row, getCellValue))\n : node.children.every((child) => evaluateAdvancedNode(child, columns, row, getCellValue));\n return node.not ? !passed : passed;\n}\n\nexport function evaluateAdvancedFilter(\n row: RowNode<any>,\n columns: Column[],\n model: AdvancedFilterModel | null,\n getCellValue: (row: RowNode<any>, column: Column) => any\n): boolean {\n if (!model) return true;\n return evaluateAdvancedNode(model.root, new Map(columns.map((column) => [column.id, column])), row, getCellValue);\n}\n\nexport function doesNodePassFilters(\n node: RowNode<any>,\n columns: Column[],\n filterModel: FilterModel,\n advancedFilterModel: AdvancedFilterModel | null,\n quickFilter: string | null,\n getCellValue: (node: RowNode<any>, column: Column) => any\n): boolean {\n for (const colId of Object.keys(filterModel)) {\n const filter = filterModel[colId];\n const column = columns.find((c) => c.id === colId);\n if (!column) continue;\n const value = getCellValue(node, column);\n if (!evaluateColumnFilter(value, filter)) return false;\n }\n\n if (!evaluateAdvancedFilter(node, columns, advancedFilterModel, getCellValue)) return false;\n\n if (quickFilter && quickFilter.trim() !== \"\") {\n const tokens = quickFilter.trim().toLowerCase().split(/\\s+/);\n for (const token of tokens) {\n const hit = columns.some((column) => textOf(getCellValue(node, column)).includes(token));\n if (!hit) return false;\n }\n }\n\n return true;\n}\n","import type {\n GridDataProcessor,\n GridDataProcessorRequest,\n GridDataProcessorResult\n} from \"../types/options\";\nimport type { AdvancedFilterNode } from \"../types/advancedFilter\";\nimport { getByPath } from \"./path\";\nimport { defaultComparator } from \"./compare\";\nimport { evaluateColumnFilter } from \"../services/filterService\";\n\nexport type GridDataProcessorPayload<TData = any> = Omit<GridDataProcessorRequest<TData>, \"signal\">;\n\nexport interface GridWorkerProcessMessage<TData = any> {\n type: \"mach-table:process\";\n requestId: number;\n payload: GridDataProcessorPayload<TData>;\n}\n\nexport interface GridWorkerCancelMessage {\n type: \"mach-table:cancel\";\n requestId: number;\n}\n\nexport type GridWorkerRequestMessage<TData = any> =\n | GridWorkerProcessMessage<TData>\n | GridWorkerCancelMessage;\n\nexport type GridWorkerResponseMessage =\n | { type: \"mach-table:result\"; requestId: number; rowIds: readonly string[] }\n | { type: \"mach-table:error\"; requestId: number; message: string };\n\nexport interface WorkerDataProcessorOptions {\n /** Terminate the lazily-created worker when the grid is destroyed. Defaults to true. */\n terminateOnDestroy?: boolean;\n}\n\nexport interface FieldDataProcessorOptions {\n /** Cooperative cancellation/yield granularity. Defaults to 2,000 rows. */\n yieldEvery?: number;\n isCancelled?: () => boolean;\n}\n\ninterface ProcessedRow<TData> {\n id: string;\n data: TData;\n order: number;\n}\n\nfunction evaluateAdvancedRow<TData>(\n node: AdvancedFilterNode,\n data: TData,\n fields: ReadonlyMap<string, string>\n): boolean {\n if (node.kind === \"condition\") {\n const field = fields.get(node.colId);\n return field == null || evaluateColumnFilter(getByPath(data, field), node.filter);\n }\n const passed = node.operator === \"or\"\n ? node.children.some((child) => evaluateAdvancedRow(child, data, fields))\n : node.children.every((child) => evaluateAdvancedRow(child, data, fields));\n return node.not ? !passed : passed;\n}\n\nfunction passesColumnFilters<TData>(\n data: TData,\n request: GridDataProcessorPayload<TData>,\n fields: ReadonlyMap<string, string>\n): boolean {\n for (const [colId, filter] of Object.entries(request.filterModel)) {\n const field = fields.get(colId);\n if (field != null && !evaluateColumnFilter(getByPath(data, field), filter)) return false;\n }\n return true;\n}\n\nfunction passesQuickFilter<TData>(\n data: TData,\n request: GridDataProcessorPayload<TData>,\n tokens: readonly string[]\n): boolean {\n return tokens.every((token) => request.columns.some((column) => {\n const value = column.field == null ? null : getByPath(data, column.field);\n return String(value ?? \"\").toLowerCase().includes(token);\n }));\n}\n\nfunction passesWorkerFilters<TData>(\n data: TData,\n request: GridDataProcessorPayload<TData>,\n fields: ReadonlyMap<string, string>,\n quickTokens: readonly string[]\n): boolean {\n if (!passesColumnFilters(data, request, fields)) return false;\n if (request.advancedFilterModel && !evaluateAdvancedRow(request.advancedFilterModel.root, data, fields)) return false;\n return passesQuickFilter(data, request, quickTokens);\n}\n\nfunction sortProcessedRows<TData>(\n rows: ProcessedRow<TData>[],\n request: GridDataProcessorPayload<TData>,\n fields: ReadonlyMap<string, string>\n): void {\n if (request.sortModel.length === 0) return;\n rows.sort((left, right) => {\n for (const sort of request.sortModel) {\n const field = fields.get(sort.colId);\n if (!field) continue;\n const compared = defaultComparator(getByPath(left.data, field), getByPath(right.data, field));\n if (compared !== 0) return sort.direction === \"desc\" ? -compared : compared;\n }\n return left.order - right.order;\n });\n}\n\nfunction throwIfCancelled(isCancelled?: () => boolean): void {\n if (!isCancelled?.()) return;\n const error = new Error(\"Data processing aborted\");\n error.name = \"AbortError\";\n throw error;\n}\n\n/** Built-in serializable field-path processor intended to run inside an application Worker. */\nexport async function processFieldDataRequest<TData = any>(\n request: GridDataProcessorPayload<TData>,\n options: FieldDataProcessorOptions = {}\n): Promise<GridDataProcessorResult> {\n const fields = new Map(\n request.columns.flatMap((column) => column.field ? [[column.colId, column.field] as const] : [])\n );\n const quickTokens = request.quickFilterText?.trim().toLowerCase().split(/\\s+/).filter(Boolean) ?? [];\n const yieldEvery = Math.max(100, Math.trunc(options.yieldEvery ?? 2_000));\n const filtered: ProcessedRow<TData>[] = [];\n for (let index = 0; index < request.rows.length; index++) {\n throwIfCancelled(options.isCancelled);\n if (index > 0 && index % yieldEvery === 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, 0));\n }\n const row = request.rows[index];\n if (passesWorkerFilters(row.data, request, fields, quickTokens)) {\n filtered.push({ id: row.id, data: row.data, order: index });\n }\n }\n sortProcessedRows(filtered, request, fields);\n return { rowIds: filtered.map((row) => row.id) };\n}\n\nexport interface GridDataWorkerScope {\n addEventListener(type: \"message\", listener: (event: MessageEvent<GridWorkerRequestMessage>) => void): void;\n postMessage(message: GridWorkerResponseMessage): void;\n}\n\n/** Installs the standard field-path protocol in a dedicated Worker module. */\nexport function installGridDataWorker(scope: GridDataWorkerScope): void {\n const cancelled = new Set<number>();\n scope.addEventListener(\"message\", (event) => {\n const message = event.data;\n if (message.type === \"mach-table:cancel\") {\n cancelled.add(message.requestId);\n return;\n }\n const { requestId } = message;\n cancelled.delete(requestId);\n void processFieldDataRequest(message.payload, {\n isCancelled: () => cancelled.has(requestId)\n }).then((result) => {\n if (!cancelled.has(requestId)) {\n scope.postMessage({ type: \"mach-table:result\", requestId, rowIds: result.rowIds });\n }\n }).catch((error) => {\n if (!cancelled.has(requestId)) {\n scope.postMessage({\n type: \"mach-table:error\",\n requestId,\n message: error instanceof Error ? error.message : String(error)\n });\n }\n }).finally(() => cancelled.delete(requestId));\n });\n}\n\nfunction abortError(reason?: unknown): Error {\n if (reason instanceof Error) return reason;\n const error = new Error(typeof reason === \"string\" ? reason : \"Data processing aborted\");\n error.name = \"AbortError\";\n return error;\n}\n\n/**\n * Adapts a dedicated Web Worker to GridDataProcessor without Blob URLs or eval.\n * The host controls the worker URL, keeping CSP and bundler behavior explicit.\n */\nexport function createWorkerDataProcessor<TData = any>(\n createWorker: () => Worker,\n options: WorkerDataProcessorOptions = {}\n): GridDataProcessor<TData> {\n let worker: Worker | null = null;\n let sequence = 0;\n let destroyed = false;\n const pending = new Map<number, {\n resolve: (result: GridDataProcessorResult) => void;\n reject: (reason: unknown) => void;\n signal: AbortSignal;\n abort: () => void;\n }>();\n\n const settleAll = (reason: unknown) => {\n for (const entry of pending.values()) {\n entry.signal.removeEventListener(\"abort\", entry.abort);\n entry.reject(reason);\n }\n pending.clear();\n };\n\n const handleMessage = (event: MessageEvent<GridWorkerResponseMessage>) => {\n const message = event.data;\n if (!message || (message.type !== \"mach-table:result\" && message.type !== \"mach-table:error\")) return;\n const entry = pending.get(message.requestId);\n if (!entry) return;\n pending.delete(message.requestId);\n entry.signal.removeEventListener(\"abort\", entry.abort);\n if (message.type === \"mach-table:result\") entry.resolve({ rowIds: message.rowIds });\n else entry.reject(new Error(message.message));\n };\n\n const detachWorker = (target: Worker): void => {\n target.removeEventListener(\"message\", handleMessage);\n target.removeEventListener(\"error\", handleError);\n };\n\n const handleError = (event: ErrorEvent) => {\n const failed = worker;\n worker = null;\n if (failed) {\n detachWorker(failed);\n failed.terminate();\n }\n settleAll(event.error ?? new Error(event.message || \"Grid data worker failed\"));\n };\n\n const ensureWorker = (): Worker => {\n if (worker) return worker;\n if (destroyed) throw new Error(\"Worker data processor has been destroyed\");\n worker = createWorker();\n worker.addEventListener(\"message\", handleMessage);\n worker.addEventListener(\"error\", handleError);\n return worker;\n };\n\n return {\n process(request) {\n if (request.signal.aborted) return Promise.reject(abortError(request.signal.reason));\n const requestId = ++sequence;\n return new Promise<GridDataProcessorResult>((resolve, reject) => {\n const abort = () => {\n const entry = pending.get(requestId);\n if (!entry) return;\n pending.delete(requestId);\n worker?.postMessage({ type: \"mach-table:cancel\", requestId } satisfies GridWorkerCancelMessage);\n reject(abortError(request.signal.reason));\n };\n pending.set(requestId, { resolve, reject, signal: request.signal, abort });\n request.signal.addEventListener(\"abort\", abort, { once: true });\n const { signal: _signal, ...payload } = request;\n void _signal;\n try {\n ensureWorker().postMessage({\n type: \"mach-table:process\",\n requestId,\n payload\n } satisfies GridWorkerProcessMessage<TData>);\n } catch (error) {\n pending.delete(requestId);\n request.signal.removeEventListener(\"abort\", abort);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n });\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n settleAll(abortError(\"Worker data processor destroyed\"));\n if (worker) {\n const current = worker;\n detachWorker(current);\n if (options.terminateOnDestroy !== false) current.terminate();\n }\n worker = null;\n }\n };\n}\n"],"mappings":"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","names":["worker_exports","__export","createWorkerDataProcessor","installGridDataWorker","processFieldDataRequest","__toCommonJS","UNSAFE_PATH_SEGMENTS","isSafePath","path","part","getByPath","obj","cur","start","idx","collator","defaultComparator","valueA","valueB","aEmpty","bEmpty","a","b","textOf","value","evaluateTextFilter","conditions","operator","v","results","c","fv","evaluateNumberFilter","isBlank","n","f","toTime","t","evaluateDateFilter","f2","evaluateSetFilter","filterValues","evaluateColumnFilter","filter","evaluateAdvancedRow","node","data","fields","field","evaluateColumnFilter","getByPath","passed","child","passesColumnFilters","request","colId","filter","passesQuickFilter","tokens","token","column","value","passesWorkerFilters","quickTokens","sortProcessedRows","rows","left","right","sort","compared","defaultComparator","throwIfCancelled","isCancelled","error","processFieldDataRequest","options","yieldEvery","filtered","index","resolve","row","installGridDataWorker","scope","cancelled","event","message","requestId","result","abortError","reason","createWorkerDataProcessor","createWorker","worker","sequence","destroyed","pending","settleAll","entry","handleMessage","detachWorker","target","handleError","failed","ensureWorker","reject","abort","_signal","payload","current"]}
@@ -0,0 +1 @@
1
+ export { ap as FieldDataProcessorOptions, ay as GridDataProcessor, az as GridDataProcessorColumn, aA as GridDataProcessorPayload, aB as GridDataProcessorRequest, aC as GridDataProcessorResult, aD as GridDataProcessorRow, aE as GridDataWorkerScope, aU as GridWorkerCancelMessage, aV as GridWorkerProcessMessage, aW as GridWorkerRequestMessage, aX as GridWorkerResponseMessage, bF as WorkerDataProcessorOptions, bK as createWorkerDataProcessor, bL as installGridDataWorker, bM as processFieldDataRequest } from './worker-P1ks_WSx.cjs';
@@ -0,0 +1 @@
1
+ export { ap as FieldDataProcessorOptions, ay as GridDataProcessor, az as GridDataProcessorColumn, aA as GridDataProcessorPayload, aB as GridDataProcessorRequest, aC as GridDataProcessorResult, aD as GridDataProcessorRow, aE as GridDataWorkerScope, aU as GridWorkerCancelMessage, aV as GridWorkerProcessMessage, aW as GridWorkerRequestMessage, aX as GridWorkerResponseMessage, bF as WorkerDataProcessorOptions, bK as createWorkerDataProcessor, bL as installGridDataWorker, bM as processFieldDataRequest } from './worker-P1ks_WSx.js';
package/dist/worker.js ADDED
@@ -0,0 +1,2 @@
1
+ var E=new Set(["__proto__","prototype","constructor"]);function W(e){return typeof e!="string"||e.length===0?!1:e.split(".").every(n=>n.length>0&&!E.has(n))}function f(e,r){if(e==null||!W(r))return;if(r.indexOf(".")<0)return e[r];let o=e,t=0;for(;t<r.length;){if(o==null)return;let a=r.indexOf(".",t);if(a<0){o=o[r.slice(t)];break}o=o[r.slice(t,a)],t=a+1}return o}var k=typeof Intl<"u"?new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"}):null;function P(e,r){let n=e==null||e==="",o=r==null||r==="";if(n&&o)return 0;if(n)return 1;if(o)return-1;if(typeof e=="number"&&typeof r=="number")return isNaN(e)&&isNaN(r)?0:isNaN(e)?1:isNaN(r)?-1:e-r;if(e instanceof Date&&r instanceof Date)return e.getTime()-r.getTime();if(typeof e=="boolean"&&typeof r=="boolean")return e===r?0:e?1:-1;let t=String(e),a=String(r);return k?k.compare(t,a):t.localeCompare(a)}function F(e){return e==null?"":String(e).toLowerCase()}function R(e,r,n){let o=F(e),t=r.map(a=>{let s=(a.value??"").toLowerCase();switch(a.match){case"contains":return o.includes(s);case"notContains":return!o.includes(s);case"equals":return o===s;case"notEquals":return o!==s;case"startsWith":return o.startsWith(s);case"endsWith":return o.endsWith(s);case"blank":return o==="";case"notBlank":return o!=="";default:return!0}});return t.length===0?!0:n==="or"?t.some(Boolean):t.every(Boolean)}function x(e,r,n){let o=r.map(t=>{let a=e==null||e==="";if(t.match==="blank")return a;if(t.match==="notBlank")return!a;if(a)return!1;let s=typeof e=="number"?e:Number(e);if(isNaN(s))return!1;let i=t.value;if(i==null||isNaN(i))return!1;switch(t.match){case"equals":return s===i;case"notEquals":return s!==i;case"lessThan":return s<i;case"lessThanOrEqual":return s<=i;case"greaterThan":return s>i;case"greaterThanOrEqual":return s>=i;case"inRange":return s>=i&&s<=(t.value2??i);default:return!0}});return o.length===0?!0:n==="or"?o.some(Boolean):o.every(Boolean)}function m(e){if(e==null||e==="")return null;if(e instanceof Date)return isNaN(e.getTime())?null:e.getTime();if(typeof e=="number")return e;let r=Date.parse(String(e));return isNaN(r)?null:r}function N(e,r,n){let o=r.map(t=>{let a=m(e)==null;if(t.match==="blank")return a;if(t.match==="notBlank")return!a;if(a)return!1;let s=m(e),i=t.value!=null?m(t.value):null;if(i==null)return!1;switch(t.match){case"equals":return s===i;case"notEquals":return s!==i;case"lessThan":return s<i;case"greaterThan":return s>i;case"inRange":{let d=t.value2!=null?m(t.value2):null;return d!=null?s>=i&&s<=d:s>=i}default:return!0}});return o.length===0?!0:n==="or"?o.some(Boolean):o.every(Boolean)}function C(e,r){return r.length===0?!0:r.some(n=>n==null&&e==null||n===e)}function D(e,r){let n=r.type!=="set"&&r.operator==="or"?"or":"and";switch(r.type){case"text":return R(e,r.conditions,n);case"number":return x(e,r.conditions,n);case"date":return N(e,r.conditions,n);case"set":return C(e,r.values);default:return!0}}function h(e,r,n){if(e.kind==="condition"){let t=n.get(e.colId);return t==null||D(f(r,t),e.filter)}let o=e.operator==="or"?e.children.some(t=>h(t,r,n)):e.children.every(t=>h(t,r,n));return e.not?!o:o}function I(e,r,n){for(let[o,t]of Object.entries(r.filterModel)){let a=n.get(o);if(a!=null&&!D(f(e,a),t))return!1}return!0}function S(e,r,n){return n.every(o=>r.columns.some(t=>{let a=t.field==null?null:f(e,t.field);return String(a??"").toLowerCase().includes(o)}))}function O(e,r,n,o){return!I(e,r,n)||r.advancedFilterModel&&!h(r.advancedFilterModel.root,e,n)?!1:S(e,r,o)}function L(e,r,n){r.sortModel.length!==0&&e.sort((o,t)=>{for(let a of r.sortModel){let s=n.get(a.colId);if(!s)continue;let i=P(f(o.data,s),f(t.data,s));if(i!==0)return a.direction==="desc"?-i:i}return o.order-t.order})}function q(e){if(!e?.())return;let r=new Error("Data processing aborted");throw r.name="AbortError",r}async function T(e,r={}){let n=new Map(e.columns.flatMap(s=>s.field?[[s.colId,s.field]]:[])),o=e.quickFilterText?.trim().toLowerCase().split(/\s+/).filter(Boolean)??[],t=Math.max(100,Math.trunc(r.yieldEvery??2e3)),a=[];for(let s=0;s<e.rows.length;s++){q(r.isCancelled),s>0&&s%t===0&&await new Promise(d=>setTimeout(d,0));let i=e.rows[s];O(i.data,e,n,o)&&a.push({id:i.id,data:i.data,order:s})}return L(a,e,n),{rowIds:a.map(s=>s.id)}}function _(e){let r=new Set;e.addEventListener("message",n=>{let o=n.data;if(o.type==="mach-table:cancel"){r.add(o.requestId);return}let{requestId:t}=o;r.delete(t),T(o.payload,{isCancelled:()=>r.has(t)}).then(a=>{r.has(t)||e.postMessage({type:"mach-table:result",requestId:t,rowIds:a.rowIds})}).catch(a=>{r.has(t)||e.postMessage({type:"mach-table:error",requestId:t,message:a instanceof Error?a.message:String(a)})}).finally(()=>r.delete(t))})}function b(e){if(e instanceof Error)return e;let r=new Error(typeof e=="string"?e:"Data processing aborted");return r.name="AbortError",r}function A(e,r={}){let n=null,o=0,t=!1,a=new Map,s=c=>{for(let l of a.values())l.signal.removeEventListener("abort",l.abort),l.reject(c);a.clear()},i=c=>{let l=c.data;if(!l||l.type!=="mach-table:result"&&l.type!=="mach-table:error")return;let u=a.get(l.requestId);u&&(a.delete(l.requestId),u.signal.removeEventListener("abort",u.abort),l.type==="mach-table:result"?u.resolve({rowIds:l.rowIds}):u.reject(new Error(l.message)))},d=c=>{c.removeEventListener("message",i),c.removeEventListener("error",w)},w=c=>{let l=n;n=null,l&&(d(l),l.terminate()),s(c.error??new Error(c.message||"Grid data worker failed"))},M=()=>{if(n)return n;if(t)throw new Error("Worker data processor has been destroyed");return n=e(),n.addEventListener("message",i),n.addEventListener("error",w),n};return{process(c){if(c.signal.aborted)return Promise.reject(b(c.signal.reason));let l=++o;return new Promise((u,y)=>{let g=()=>{a.get(l)&&(a.delete(l),n?.postMessage({type:"mach-table:cancel",requestId:l}),y(b(c.signal.reason)))};a.set(l,{resolve:u,reject:y,signal:c.signal,abort:g}),c.signal.addEventListener("abort",g,{once:!0});let{signal:G,...v}=c;try{M().postMessage({type:"mach-table:process",requestId:l,payload:v})}catch(p){a.delete(l),c.signal.removeEventListener("abort",g),y(p instanceof Error?p:new Error(String(p)))}})},destroy(){if(!t){if(t=!0,s(b("Worker data processor destroyed")),n){let c=n;d(c),r.terminateOnDestroy!==!1&&c.terminate()}n=null}}}}export{A as createWorkerDataProcessor,_ as installGridDataWorker,T as processFieldDataRequest};
2
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/path.ts","../src/lib/compare.ts","../src/services/filterService.ts","../src/lib/workerDataProcessor.ts"],"sourcesContent":["const UNSAFE_PATH_SEGMENTS = new Set([\"__proto__\", \"prototype\", \"constructor\"]);\n\nexport function isSafePath(path: string): boolean {\n if (typeof path !== \"string\" || path.length === 0) return false;\n const parts = path.split(\".\");\n return parts.every((part) => part.length > 0 && !UNSAFE_PATH_SEGMENTS.has(part));\n}\n\nexport function getByPath(obj: any, path: string): any {\n if (obj == null) return undefined;\n if (!isSafePath(path)) return undefined;\n const dot = path.indexOf(\".\");\n if (dot < 0) return obj[path];\n let cur = obj;\n let start = 0;\n while (start < path.length) {\n if (cur == null) return undefined;\n const idx = path.indexOf(\".\", start);\n if (idx < 0) {\n cur = cur[path.slice(start)];\n break;\n }\n cur = cur[path.slice(start, idx)];\n start = idx + 1;\n }\n return cur;\n}\n\nexport function setByPath(obj: any, path: string, value: any): boolean {\n if (obj == null || !isSafePath(path)) return false;\n const parts = path.split(\".\");\n let cur = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if ((typeof cur !== \"object\" && typeof cur !== \"function\") || cur === null) return false;\n if (cur[parts[i]] == null) cur[parts[i]] = {};\n cur = cur[parts[i]];\n }\n if ((typeof cur !== \"object\" && typeof cur !== \"function\") || cur === null) return false;\n cur[parts[parts.length - 1]] = value;\n return true;\n}\n","const collator = typeof Intl !== \"undefined\"\n ? new Intl.Collator(undefined, { numeric: true, sensitivity: \"base\" })\n : null;\n\nexport function defaultComparator(valueA: any, valueB: any): number {\n const aEmpty = valueA == null || valueA === \"\";\n const bEmpty = valueB == null || valueB === \"\";\n if (aEmpty && bEmpty) return 0;\n if (aEmpty) return 1;\n if (bEmpty) return -1;\n\n if (typeof valueA === \"number\" && typeof valueB === \"number\") {\n if (isNaN(valueA) && isNaN(valueB)) return 0;\n if (isNaN(valueA)) return 1;\n if (isNaN(valueB)) return -1;\n return valueA - valueB;\n }\n if (valueA instanceof Date && valueB instanceof Date) {\n return valueA.getTime() - valueB.getTime();\n }\n if (typeof valueA === \"boolean\" && typeof valueB === \"boolean\") {\n return valueA === valueB ? 0 : valueA ? 1 : -1;\n }\n const a = String(valueA);\n const b = String(valueB);\n return collator ? collator.compare(a, b) : a.localeCompare(b);\n}\n","import type { ColumnFilter, FilterModel, TextFilterCondition, NumberFilterCondition, DateFilterCondition } from \"../types/colDef\";\nimport type { AdvancedFilterModel, AdvancedFilterNode } from \"../types/advancedFilter\";\nimport type { RowNode } from \"../types/row\";\nimport type { Column } from \"./column\";\n\nfunction textOf(value: any): string {\n return value == null ? \"\" : String(value).toLowerCase();\n}\n\nexport function evaluateTextFilter(value: any, conditions: TextFilterCondition[], operator: \"and\" | \"or\"): boolean {\n const v = textOf(value);\n const results = conditions.map((c) => {\n const fv = (c.value ?? \"\").toLowerCase();\n switch (c.match) {\n case \"contains\":\n return v.includes(fv);\n case \"notContains\":\n return !v.includes(fv);\n case \"equals\":\n return v === fv;\n case \"notEquals\":\n return v !== fv;\n case \"startsWith\":\n return v.startsWith(fv);\n case \"endsWith\":\n return v.endsWith(fv);\n case \"blank\":\n return v === \"\";\n case \"notBlank\":\n return v !== \"\";\n default:\n return true;\n }\n });\n if (results.length === 0) return true;\n return operator === \"or\" ? results.some(Boolean) : results.every(Boolean);\n}\n\nexport function evaluateNumberFilter(value: any, conditions: NumberFilterCondition[], operator: \"and\" | \"or\"): boolean {\n const results = conditions.map((c) => {\n const isBlank = value == null || value === \"\";\n if (c.match === \"blank\") return isBlank;\n if (c.match === \"notBlank\") return !isBlank;\n if (isBlank) return false;\n const n = typeof value === \"number\" ? value : Number(value);\n if (isNaN(n)) return false;\n const f = c.value;\n if (f == null || isNaN(f)) return false;\n switch (c.match) {\n case \"equals\":\n return n === f;\n case \"notEquals\":\n return n !== f;\n case \"lessThan\":\n return n < f;\n case \"lessThanOrEqual\":\n return n <= f;\n case \"greaterThan\":\n return n > f;\n case \"greaterThanOrEqual\":\n return n >= f;\n case \"inRange\":\n return n >= f && n <= (c.value2 ?? f);\n default:\n return true;\n }\n });\n if (results.length === 0) return true;\n return operator === \"or\" ? results.some(Boolean) : results.every(Boolean);\n}\n\nfunction toTime(value: any): number | null {\n if (value == null || value === \"\") return null;\n if (value instanceof Date) return isNaN(value.getTime()) ? null : value.getTime();\n if (typeof value === \"number\") return value;\n const t = Date.parse(String(value));\n return isNaN(t) ? null : t;\n}\n\nexport function evaluateDateFilter(value: any, conditions: DateFilterCondition[], operator: \"and\" | \"or\"): boolean {\n const results = conditions.map((c) => {\n const isBlank = toTime(value) == null;\n if (c.match === \"blank\") return isBlank;\n if (c.match === \"notBlank\") return !isBlank;\n if (isBlank) return false;\n const t = toTime(value)!;\n const f = c.value != null ? toTime(c.value) : null;\n if (f == null) return false;\n switch (c.match) {\n case \"equals\":\n return t === f;\n case \"notEquals\":\n return t !== f;\n case \"lessThan\":\n return t < f;\n case \"greaterThan\":\n return t > f;\n case \"inRange\": {\n const f2 = c.value2 != null ? toTime(c.value2) : null;\n return f2 != null ? t >= f && t <= f2 : t >= f;\n }\n default:\n return true;\n }\n });\n if (results.length === 0) return true;\n return operator === \"or\" ? results.some(Boolean) : results.every(Boolean);\n}\n\nexport function evaluateSetFilter(value: any, filterValues: (string | number | null)[]): boolean {\n if (filterValues.length === 0) return true;\n return filterValues.some((v) => (v == null && value == null) || v === value);\n}\n\nexport function evaluateColumnFilter(value: any, filter: ColumnFilter): boolean {\n const operator = filter.type !== \"set\" && filter.operator === \"or\" ? \"or\" : \"and\";\n switch (filter.type) {\n case \"text\":\n return evaluateTextFilter(value, filter.conditions, operator);\n case \"number\":\n return evaluateNumberFilter(value, filter.conditions, operator);\n case \"date\":\n return evaluateDateFilter(value, filter.conditions, operator);\n case \"set\":\n return evaluateSetFilter(value, filter.values);\n default:\n return true;\n }\n}\n\nfunction evaluateAdvancedNode(\n node: AdvancedFilterNode,\n columns: ReadonlyMap<string, Column>,\n row: RowNode<any>,\n getCellValue: (row: RowNode<any>, column: Column) => any\n): boolean {\n if (node.kind === \"condition\") {\n const column = columns.get(node.colId);\n return !column || evaluateColumnFilter(getCellValue(row, column), node.filter);\n }\n const passed = node.operator === \"or\"\n ? node.children.some((child) => evaluateAdvancedNode(child, columns, row, getCellValue))\n : node.children.every((child) => evaluateAdvancedNode(child, columns, row, getCellValue));\n return node.not ? !passed : passed;\n}\n\nexport function evaluateAdvancedFilter(\n row: RowNode<any>,\n columns: Column[],\n model: AdvancedFilterModel | null,\n getCellValue: (row: RowNode<any>, column: Column) => any\n): boolean {\n if (!model) return true;\n return evaluateAdvancedNode(model.root, new Map(columns.map((column) => [column.id, column])), row, getCellValue);\n}\n\nexport function doesNodePassFilters(\n node: RowNode<any>,\n columns: Column[],\n filterModel: FilterModel,\n advancedFilterModel: AdvancedFilterModel | null,\n quickFilter: string | null,\n getCellValue: (node: RowNode<any>, column: Column) => any\n): boolean {\n for (const colId of Object.keys(filterModel)) {\n const filter = filterModel[colId];\n const column = columns.find((c) => c.id === colId);\n if (!column) continue;\n const value = getCellValue(node, column);\n if (!evaluateColumnFilter(value, filter)) return false;\n }\n\n if (!evaluateAdvancedFilter(node, columns, advancedFilterModel, getCellValue)) return false;\n\n if (quickFilter && quickFilter.trim() !== \"\") {\n const tokens = quickFilter.trim().toLowerCase().split(/\\s+/);\n for (const token of tokens) {\n const hit = columns.some((column) => textOf(getCellValue(node, column)).includes(token));\n if (!hit) return false;\n }\n }\n\n return true;\n}\n","import type {\n GridDataProcessor,\n GridDataProcessorRequest,\n GridDataProcessorResult\n} from \"../types/options\";\nimport type { AdvancedFilterNode } from \"../types/advancedFilter\";\nimport { getByPath } from \"./path\";\nimport { defaultComparator } from \"./compare\";\nimport { evaluateColumnFilter } from \"../services/filterService\";\n\nexport type GridDataProcessorPayload<TData = any> = Omit<GridDataProcessorRequest<TData>, \"signal\">;\n\nexport interface GridWorkerProcessMessage<TData = any> {\n type: \"mach-table:process\";\n requestId: number;\n payload: GridDataProcessorPayload<TData>;\n}\n\nexport interface GridWorkerCancelMessage {\n type: \"mach-table:cancel\";\n requestId: number;\n}\n\nexport type GridWorkerRequestMessage<TData = any> =\n | GridWorkerProcessMessage<TData>\n | GridWorkerCancelMessage;\n\nexport type GridWorkerResponseMessage =\n | { type: \"mach-table:result\"; requestId: number; rowIds: readonly string[] }\n | { type: \"mach-table:error\"; requestId: number; message: string };\n\nexport interface WorkerDataProcessorOptions {\n /** Terminate the lazily-created worker when the grid is destroyed. Defaults to true. */\n terminateOnDestroy?: boolean;\n}\n\nexport interface FieldDataProcessorOptions {\n /** Cooperative cancellation/yield granularity. Defaults to 2,000 rows. */\n yieldEvery?: number;\n isCancelled?: () => boolean;\n}\n\ninterface ProcessedRow<TData> {\n id: string;\n data: TData;\n order: number;\n}\n\nfunction evaluateAdvancedRow<TData>(\n node: AdvancedFilterNode,\n data: TData,\n fields: ReadonlyMap<string, string>\n): boolean {\n if (node.kind === \"condition\") {\n const field = fields.get(node.colId);\n return field == null || evaluateColumnFilter(getByPath(data, field), node.filter);\n }\n const passed = node.operator === \"or\"\n ? node.children.some((child) => evaluateAdvancedRow(child, data, fields))\n : node.children.every((child) => evaluateAdvancedRow(child, data, fields));\n return node.not ? !passed : passed;\n}\n\nfunction passesColumnFilters<TData>(\n data: TData,\n request: GridDataProcessorPayload<TData>,\n fields: ReadonlyMap<string, string>\n): boolean {\n for (const [colId, filter] of Object.entries(request.filterModel)) {\n const field = fields.get(colId);\n if (field != null && !evaluateColumnFilter(getByPath(data, field), filter)) return false;\n }\n return true;\n}\n\nfunction passesQuickFilter<TData>(\n data: TData,\n request: GridDataProcessorPayload<TData>,\n tokens: readonly string[]\n): boolean {\n return tokens.every((token) => request.columns.some((column) => {\n const value = column.field == null ? null : getByPath(data, column.field);\n return String(value ?? \"\").toLowerCase().includes(token);\n }));\n}\n\nfunction passesWorkerFilters<TData>(\n data: TData,\n request: GridDataProcessorPayload<TData>,\n fields: ReadonlyMap<string, string>,\n quickTokens: readonly string[]\n): boolean {\n if (!passesColumnFilters(data, request, fields)) return false;\n if (request.advancedFilterModel && !evaluateAdvancedRow(request.advancedFilterModel.root, data, fields)) return false;\n return passesQuickFilter(data, request, quickTokens);\n}\n\nfunction sortProcessedRows<TData>(\n rows: ProcessedRow<TData>[],\n request: GridDataProcessorPayload<TData>,\n fields: ReadonlyMap<string, string>\n): void {\n if (request.sortModel.length === 0) return;\n rows.sort((left, right) => {\n for (const sort of request.sortModel) {\n const field = fields.get(sort.colId);\n if (!field) continue;\n const compared = defaultComparator(getByPath(left.data, field), getByPath(right.data, field));\n if (compared !== 0) return sort.direction === \"desc\" ? -compared : compared;\n }\n return left.order - right.order;\n });\n}\n\nfunction throwIfCancelled(isCancelled?: () => boolean): void {\n if (!isCancelled?.()) return;\n const error = new Error(\"Data processing aborted\");\n error.name = \"AbortError\";\n throw error;\n}\n\n/** Built-in serializable field-path processor intended to run inside an application Worker. */\nexport async function processFieldDataRequest<TData = any>(\n request: GridDataProcessorPayload<TData>,\n options: FieldDataProcessorOptions = {}\n): Promise<GridDataProcessorResult> {\n const fields = new Map(\n request.columns.flatMap((column) => column.field ? [[column.colId, column.field] as const] : [])\n );\n const quickTokens = request.quickFilterText?.trim().toLowerCase().split(/\\s+/).filter(Boolean) ?? [];\n const yieldEvery = Math.max(100, Math.trunc(options.yieldEvery ?? 2_000));\n const filtered: ProcessedRow<TData>[] = [];\n for (let index = 0; index < request.rows.length; index++) {\n throwIfCancelled(options.isCancelled);\n if (index > 0 && index % yieldEvery === 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, 0));\n }\n const row = request.rows[index];\n if (passesWorkerFilters(row.data, request, fields, quickTokens)) {\n filtered.push({ id: row.id, data: row.data, order: index });\n }\n }\n sortProcessedRows(filtered, request, fields);\n return { rowIds: filtered.map((row) => row.id) };\n}\n\nexport interface GridDataWorkerScope {\n addEventListener(type: \"message\", listener: (event: MessageEvent<GridWorkerRequestMessage>) => void): void;\n postMessage(message: GridWorkerResponseMessage): void;\n}\n\n/** Installs the standard field-path protocol in a dedicated Worker module. */\nexport function installGridDataWorker(scope: GridDataWorkerScope): void {\n const cancelled = new Set<number>();\n scope.addEventListener(\"message\", (event) => {\n const message = event.data;\n if (message.type === \"mach-table:cancel\") {\n cancelled.add(message.requestId);\n return;\n }\n const { requestId } = message;\n cancelled.delete(requestId);\n void processFieldDataRequest(message.payload, {\n isCancelled: () => cancelled.has(requestId)\n }).then((result) => {\n if (!cancelled.has(requestId)) {\n scope.postMessage({ type: \"mach-table:result\", requestId, rowIds: result.rowIds });\n }\n }).catch((error) => {\n if (!cancelled.has(requestId)) {\n scope.postMessage({\n type: \"mach-table:error\",\n requestId,\n message: error instanceof Error ? error.message : String(error)\n });\n }\n }).finally(() => cancelled.delete(requestId));\n });\n}\n\nfunction abortError(reason?: unknown): Error {\n if (reason instanceof Error) return reason;\n const error = new Error(typeof reason === \"string\" ? reason : \"Data processing aborted\");\n error.name = \"AbortError\";\n return error;\n}\n\n/**\n * Adapts a dedicated Web Worker to GridDataProcessor without Blob URLs or eval.\n * The host controls the worker URL, keeping CSP and bundler behavior explicit.\n */\nexport function createWorkerDataProcessor<TData = any>(\n createWorker: () => Worker,\n options: WorkerDataProcessorOptions = {}\n): GridDataProcessor<TData> {\n let worker: Worker | null = null;\n let sequence = 0;\n let destroyed = false;\n const pending = new Map<number, {\n resolve: (result: GridDataProcessorResult) => void;\n reject: (reason: unknown) => void;\n signal: AbortSignal;\n abort: () => void;\n }>();\n\n const settleAll = (reason: unknown) => {\n for (const entry of pending.values()) {\n entry.signal.removeEventListener(\"abort\", entry.abort);\n entry.reject(reason);\n }\n pending.clear();\n };\n\n const handleMessage = (event: MessageEvent<GridWorkerResponseMessage>) => {\n const message = event.data;\n if (!message || (message.type !== \"mach-table:result\" && message.type !== \"mach-table:error\")) return;\n const entry = pending.get(message.requestId);\n if (!entry) return;\n pending.delete(message.requestId);\n entry.signal.removeEventListener(\"abort\", entry.abort);\n if (message.type === \"mach-table:result\") entry.resolve({ rowIds: message.rowIds });\n else entry.reject(new Error(message.message));\n };\n\n const detachWorker = (target: Worker): void => {\n target.removeEventListener(\"message\", handleMessage);\n target.removeEventListener(\"error\", handleError);\n };\n\n const handleError = (event: ErrorEvent) => {\n const failed = worker;\n worker = null;\n if (failed) {\n detachWorker(failed);\n failed.terminate();\n }\n settleAll(event.error ?? new Error(event.message || \"Grid data worker failed\"));\n };\n\n const ensureWorker = (): Worker => {\n if (worker) return worker;\n if (destroyed) throw new Error(\"Worker data processor has been destroyed\");\n worker = createWorker();\n worker.addEventListener(\"message\", handleMessage);\n worker.addEventListener(\"error\", handleError);\n return worker;\n };\n\n return {\n process(request) {\n if (request.signal.aborted) return Promise.reject(abortError(request.signal.reason));\n const requestId = ++sequence;\n return new Promise<GridDataProcessorResult>((resolve, reject) => {\n const abort = () => {\n const entry = pending.get(requestId);\n if (!entry) return;\n pending.delete(requestId);\n worker?.postMessage({ type: \"mach-table:cancel\", requestId } satisfies GridWorkerCancelMessage);\n reject(abortError(request.signal.reason));\n };\n pending.set(requestId, { resolve, reject, signal: request.signal, abort });\n request.signal.addEventListener(\"abort\", abort, { once: true });\n const { signal: _signal, ...payload } = request;\n void _signal;\n try {\n ensureWorker().postMessage({\n type: \"mach-table:process\",\n requestId,\n payload\n } satisfies GridWorkerProcessMessage<TData>);\n } catch (error) {\n pending.delete(requestId);\n request.signal.removeEventListener(\"abort\", abort);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n });\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n settleAll(abortError(\"Worker data processor destroyed\"));\n if (worker) {\n const current = worker;\n detachWorker(current);\n if (options.terminateOnDestroy !== false) current.terminate();\n }\n worker = null;\n }\n };\n}\n"],"mappings":"AAAA,IAAMA,EAAuB,IAAI,IAAI,CAAC,YAAa,YAAa,aAAa,CAAC,EAEvE,SAASC,EAAWC,EAAuB,CAChD,OAAI,OAAOA,GAAS,UAAYA,EAAK,SAAW,EAAU,GAC5CA,EAAK,MAAM,GAAG,EACf,MAAOC,GAASA,EAAK,OAAS,GAAK,CAACH,EAAqB,IAAIG,CAAI,CAAC,CACjF,CAEO,SAASC,EAAUC,EAAUH,EAAmB,CAErD,GADIG,GAAO,MACP,CAACJ,EAAWC,CAAI,EAAG,OAEvB,GADYA,EAAK,QAAQ,GAAG,EAClB,EAAG,OAAOG,EAAIH,CAAI,EAC5B,IAAII,EAAMD,EACNE,EAAQ,EACZ,KAAOA,EAAQL,EAAK,QAAQ,CAC1B,GAAII,GAAO,KAAM,OACjB,IAAME,EAAMN,EAAK,QAAQ,IAAKK,CAAK,EACnC,GAAIC,EAAM,EAAG,CACXF,EAAMA,EAAIJ,EAAK,MAAMK,CAAK,CAAC,EAC3B,KACF,CACAD,EAAMA,EAAIJ,EAAK,MAAMK,EAAOC,CAAG,CAAC,EAChCD,EAAQC,EAAM,CAChB,CACA,OAAOF,CACT,CC1BA,IAAMG,EAAW,OAAO,KAAS,IAC7B,IAAI,KAAK,SAAS,OAAW,CAAE,QAAS,GAAM,YAAa,MAAO,CAAC,EACnE,KAEG,SAASC,EAAkBC,EAAaC,EAAqB,CAClE,IAAMC,EAASF,GAAU,MAAQA,IAAW,GACtCG,EAASF,GAAU,MAAQA,IAAW,GAC5C,GAAIC,GAAUC,EAAQ,MAAO,GAC7B,GAAID,EAAQ,MAAO,GACnB,GAAIC,EAAQ,MAAO,GAEnB,GAAI,OAAOH,GAAW,UAAY,OAAOC,GAAW,SAClD,OAAI,MAAMD,CAAM,GAAK,MAAMC,CAAM,EAAU,EACvC,MAAMD,CAAM,EAAU,EACtB,MAAMC,CAAM,EAAU,GACnBD,EAASC,EAElB,GAAID,aAAkB,MAAQC,aAAkB,KAC9C,OAAOD,EAAO,QAAQ,EAAIC,EAAO,QAAQ,EAE3C,GAAI,OAAOD,GAAW,WAAa,OAAOC,GAAW,UACnD,OAAOD,IAAWC,EAAS,EAAID,EAAS,EAAI,GAE9C,IAAMI,EAAI,OAAOJ,CAAM,EACjBK,EAAI,OAAOJ,CAAM,EACvB,OAAOH,EAAWA,EAAS,QAAQM,EAAGC,CAAC,EAAID,EAAE,cAAcC,CAAC,CAC9D,CCrBA,SAASC,EAAOC,EAAoB,CAClC,OAAOA,GAAS,KAAO,GAAK,OAAOA,CAAK,EAAE,YAAY,CACxD,CAEO,SAASC,EAAmBD,EAAYE,EAAmCC,EAAiC,CACjH,IAAMC,EAAIL,EAAOC,CAAK,EAChBK,EAAUH,EAAW,IAAKI,GAAM,CACpC,IAAMC,GAAMD,EAAE,OAAS,IAAI,YAAY,EACvC,OAAQA,EAAE,MAAO,CACf,IAAK,WACH,OAAOF,EAAE,SAASG,CAAE,EACtB,IAAK,cACH,MAAO,CAACH,EAAE,SAASG,CAAE,EACvB,IAAK,SACH,OAAOH,IAAMG,EACf,IAAK,YACH,OAAOH,IAAMG,EACf,IAAK,aACH,OAAOH,EAAE,WAAWG,CAAE,EACxB,IAAK,WACH,OAAOH,EAAE,SAASG,CAAE,EACtB,IAAK,QACH,OAAOH,IAAM,GACf,IAAK,WACH,OAAOA,IAAM,GACf,QACE,MAAO,EACX,CACF,CAAC,EACD,OAAIC,EAAQ,SAAW,EAAU,GAC1BF,IAAa,KAAOE,EAAQ,KAAK,OAAO,EAAIA,EAAQ,MAAM,OAAO,CAC1E,CAEO,SAASG,EAAqBR,EAAYE,EAAqCC,EAAiC,CACrH,IAAME,EAAUH,EAAW,IAAKI,GAAM,CACpC,IAAMG,EAAUT,GAAS,MAAQA,IAAU,GAC3C,GAAIM,EAAE,QAAU,QAAS,OAAOG,EAChC,GAAIH,EAAE,QAAU,WAAY,MAAO,CAACG,EACpC,GAAIA,EAAS,MAAO,GACpB,IAAMC,EAAI,OAAOV,GAAU,SAAWA,EAAQ,OAAOA,CAAK,EAC1D,GAAI,MAAMU,CAAC,EAAG,MAAO,GACrB,IAAMC,EAAIL,EAAE,MACZ,GAAIK,GAAK,MAAQ,MAAMA,CAAC,EAAG,MAAO,GAClC,OAAQL,EAAE,MAAO,CACf,IAAK,SACH,OAAOI,IAAMC,EACf,IAAK,YACH,OAAOD,IAAMC,EACf,IAAK,WACH,OAAOD,EAAIC,EACb,IAAK,kBACH,OAAOD,GAAKC,EACd,IAAK,cACH,OAAOD,EAAIC,EACb,IAAK,qBACH,OAAOD,GAAKC,EACd,IAAK,UACH,OAAOD,GAAKC,GAAKD,IAAMJ,EAAE,QAAUK,GACrC,QACE,MAAO,EACX,CACF,CAAC,EACD,OAAIN,EAAQ,SAAW,EAAU,GAC1BF,IAAa,KAAOE,EAAQ,KAAK,OAAO,EAAIA,EAAQ,MAAM,OAAO,CAC1E,CAEA,SAASO,EAAOZ,EAA2B,CACzC,GAAIA,GAAS,MAAQA,IAAU,GAAI,OAAO,KAC1C,GAAIA,aAAiB,KAAM,OAAO,MAAMA,EAAM,QAAQ,CAAC,EAAI,KAAOA,EAAM,QAAQ,EAChF,GAAI,OAAOA,GAAU,SAAU,OAAOA,EACtC,IAAMa,EAAI,KAAK,MAAM,OAAOb,CAAK,CAAC,EAClC,OAAO,MAAMa,CAAC,EAAI,KAAOA,CAC3B,CAEO,SAASC,EAAmBd,EAAYE,EAAmCC,EAAiC,CACjH,IAAME,EAAUH,EAAW,IAAKI,GAAM,CACpC,IAAMG,EAAUG,EAAOZ,CAAK,GAAK,KACjC,GAAIM,EAAE,QAAU,QAAS,OAAOG,EAChC,GAAIH,EAAE,QAAU,WAAY,MAAO,CAACG,EACpC,GAAIA,EAAS,MAAO,GACpB,IAAMI,EAAID,EAAOZ,CAAK,EAChBW,EAAIL,EAAE,OAAS,KAAOM,EAAON,EAAE,KAAK,EAAI,KAC9C,GAAIK,GAAK,KAAM,MAAO,GACtB,OAAQL,EAAE,MAAO,CACf,IAAK,SACH,OAAOO,IAAMF,EACf,IAAK,YACH,OAAOE,IAAMF,EACf,IAAK,WACH,OAAOE,EAAIF,EACb,IAAK,cACH,OAAOE,EAAIF,EACb,IAAK,UAAW,CACd,IAAMI,EAAKT,EAAE,QAAU,KAAOM,EAAON,EAAE,MAAM,EAAI,KACjD,OAAOS,GAAM,KAAOF,GAAKF,GAAKE,GAAKE,EAAKF,GAAKF,CAC/C,CACA,QACE,MAAO,EACX,CACF,CAAC,EACD,OAAIN,EAAQ,SAAW,EAAU,GAC1BF,IAAa,KAAOE,EAAQ,KAAK,OAAO,EAAIA,EAAQ,MAAM,OAAO,CAC1E,CAEO,SAASW,EAAkBhB,EAAYiB,EAAmD,CAC/F,OAAIA,EAAa,SAAW,EAAU,GAC/BA,EAAa,KAAMb,GAAOA,GAAK,MAAQJ,GAAS,MAASI,IAAMJ,CAAK,CAC7E,CAEO,SAASkB,EAAqBlB,EAAYmB,EAA+B,CAC9E,IAAMhB,EAAWgB,EAAO,OAAS,OAASA,EAAO,WAAa,KAAO,KAAO,MAC5E,OAAQA,EAAO,KAAM,CACnB,IAAK,OACH,OAAOlB,EAAmBD,EAAOmB,EAAO,WAAYhB,CAAQ,EAC9D,IAAK,SACH,OAAOK,EAAqBR,EAAOmB,EAAO,WAAYhB,CAAQ,EAChE,IAAK,OACH,OAAOW,EAAmBd,EAAOmB,EAAO,WAAYhB,CAAQ,EAC9D,IAAK,MACH,OAAOa,EAAkBhB,EAAOmB,EAAO,MAAM,EAC/C,QACE,MAAO,EACX,CACF,CChFA,SAASC,EACPC,EACAC,EACAC,EACS,CACT,GAAIF,EAAK,OAAS,YAAa,CAC7B,IAAMG,EAAQD,EAAO,IAAIF,EAAK,KAAK,EACnC,OAAOG,GAAS,MAAQC,EAAqBC,EAAUJ,EAAME,CAAK,EAAGH,EAAK,MAAM,CAClF,CACA,IAAMM,EAASN,EAAK,WAAa,KAC7BA,EAAK,SAAS,KAAMO,GAAUR,EAAoBQ,EAAON,EAAMC,CAAM,CAAC,EACtEF,EAAK,SAAS,MAAOO,GAAUR,EAAoBQ,EAAON,EAAMC,CAAM,CAAC,EAC3E,OAAOF,EAAK,IAAM,CAACM,EAASA,CAC9B,CAEA,SAASE,EACPP,EACAQ,EACAP,EACS,CACT,OAAW,CAACQ,EAAOC,CAAM,IAAK,OAAO,QAAQF,EAAQ,WAAW,EAAG,CACjE,IAAMN,EAAQD,EAAO,IAAIQ,CAAK,EAC9B,GAAIP,GAAS,MAAQ,CAACC,EAAqBC,EAAUJ,EAAME,CAAK,EAAGQ,CAAM,EAAG,MAAO,EACrF,CACA,MAAO,EACT,CAEA,SAASC,EACPX,EACAQ,EACAI,EACS,CACT,OAAOA,EAAO,MAAOC,GAAUL,EAAQ,QAAQ,KAAMM,GAAW,CAC9D,IAAMC,EAAQD,EAAO,OAAS,KAAO,KAAOV,EAAUJ,EAAMc,EAAO,KAAK,EACxE,OAAO,OAAOC,GAAS,EAAE,EAAE,YAAY,EAAE,SAASF,CAAK,CACzD,CAAC,CAAC,CACJ,CAEA,SAASG,EACPhB,EACAQ,EACAP,EACAgB,EACS,CAET,MADI,CAACV,EAAoBP,EAAMQ,EAASP,CAAM,GAC1CO,EAAQ,qBAAuB,CAACV,EAAoBU,EAAQ,oBAAoB,KAAMR,EAAMC,CAAM,EAAU,GACzGU,EAAkBX,EAAMQ,EAASS,CAAW,CACrD,CAEA,SAASC,EACPC,EACAX,EACAP,EACM,CACFO,EAAQ,UAAU,SAAW,GACjCW,EAAK,KAAK,CAACC,EAAMC,IAAU,CACzB,QAAWC,KAAQd,EAAQ,UAAW,CACpC,IAAMN,EAAQD,EAAO,IAAIqB,EAAK,KAAK,EACnC,GAAI,CAACpB,EAAO,SACZ,IAAMqB,EAAWC,EAAkBpB,EAAUgB,EAAK,KAAMlB,CAAK,EAAGE,EAAUiB,EAAM,KAAMnB,CAAK,CAAC,EAC5F,GAAIqB,IAAa,EAAG,OAAOD,EAAK,YAAc,OAAS,CAACC,EAAWA,CACrE,CACA,OAAOH,EAAK,MAAQC,EAAM,KAC5B,CAAC,CACH,CAEA,SAASI,EAAiBC,EAAmC,CAC3D,GAAI,CAACA,IAAc,EAAG,OACtB,IAAMC,EAAQ,IAAI,MAAM,yBAAyB,EACjD,MAAAA,EAAM,KAAO,aACPA,CACR,CAGA,eAAsBC,EACpBpB,EACAqB,EAAqC,CAAC,EACJ,CAClC,IAAM5B,EAAS,IAAI,IACjBO,EAAQ,QAAQ,QAASM,GAAWA,EAAO,MAAQ,CAAC,CAACA,EAAO,MAAOA,EAAO,KAAK,CAAU,EAAI,CAAC,CAAC,CACjG,EACMG,EAAcT,EAAQ,iBAAiB,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO,GAAK,CAAC,EAC7FsB,EAAa,KAAK,IAAI,IAAK,KAAK,MAAMD,EAAQ,YAAc,GAAK,CAAC,EAClEE,EAAkC,CAAC,EACzC,QAASC,EAAQ,EAAGA,EAAQxB,EAAQ,KAAK,OAAQwB,IAAS,CACxDP,EAAiBI,EAAQ,WAAW,EAChCG,EAAQ,GAAKA,EAAQF,IAAe,GACtC,MAAM,IAAI,QAAeG,GAAY,WAAWA,EAAS,CAAC,CAAC,EAE7D,IAAMC,EAAM1B,EAAQ,KAAKwB,CAAK,EAC1BhB,EAAoBkB,EAAI,KAAM1B,EAASP,EAAQgB,CAAW,GAC5Dc,EAAS,KAAK,CAAE,GAAIG,EAAI,GAAI,KAAMA,EAAI,KAAM,MAAOF,CAAM,CAAC,CAE9D,CACA,OAAAd,EAAkBa,EAAUvB,EAASP,CAAM,EACpC,CAAE,OAAQ8B,EAAS,IAAKG,GAAQA,EAAI,EAAE,CAAE,CACjD,CAQO,SAASC,EAAsBC,EAAkC,CACtE,IAAMC,EAAY,IAAI,IACtBD,EAAM,iBAAiB,UAAYE,GAAU,CAC3C,IAAMC,EAAUD,EAAM,KACtB,GAAIC,EAAQ,OAAS,oBAAqB,CACxCF,EAAU,IAAIE,EAAQ,SAAS,EAC/B,MACF,CACA,GAAM,CAAE,UAAAC,CAAU,EAAID,EACtBF,EAAU,OAAOG,CAAS,EACrBZ,EAAwBW,EAAQ,QAAS,CAC5C,YAAa,IAAMF,EAAU,IAAIG,CAAS,CAC5C,CAAC,EAAE,KAAMC,GAAW,CACbJ,EAAU,IAAIG,CAAS,GAC1BJ,EAAM,YAAY,CAAE,KAAM,oBAAqB,UAAAI,EAAW,OAAQC,EAAO,MAAO,CAAC,CAErF,CAAC,EAAE,MAAOd,GAAU,CACbU,EAAU,IAAIG,CAAS,GAC1BJ,EAAM,YAAY,CAChB,KAAM,mBACN,UAAAI,EACA,QAASb,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,CAChE,CAAC,CAEL,CAAC,EAAE,QAAQ,IAAMU,EAAU,OAAOG,CAAS,CAAC,CAC9C,CAAC,CACH,CAEA,SAASE,EAAWC,EAAyB,CAC3C,GAAIA,aAAkB,MAAO,OAAOA,EACpC,IAAMhB,EAAQ,IAAI,MAAM,OAAOgB,GAAW,SAAWA,EAAS,yBAAyB,EACvF,OAAAhB,EAAM,KAAO,aACNA,CACT,CAMO,SAASiB,EACdC,EACAhB,EAAsC,CAAC,EACb,CAC1B,IAAIiB,EAAwB,KACxBC,EAAW,EACXC,EAAY,GACVC,EAAU,IAAI,IAOdC,EAAaP,GAAoB,CACrC,QAAWQ,KAASF,EAAQ,OAAO,EACjCE,EAAM,OAAO,oBAAoB,QAASA,EAAM,KAAK,EACrDA,EAAM,OAAOR,CAAM,EAErBM,EAAQ,MAAM,CAChB,EAEMG,EAAiBd,GAAmD,CACxE,IAAMC,EAAUD,EAAM,KACtB,GAAI,CAACC,GAAYA,EAAQ,OAAS,qBAAuBA,EAAQ,OAAS,mBAAqB,OAC/F,IAAMY,EAAQF,EAAQ,IAAIV,EAAQ,SAAS,EACtCY,IACLF,EAAQ,OAAOV,EAAQ,SAAS,EAChCY,EAAM,OAAO,oBAAoB,QAASA,EAAM,KAAK,EACjDZ,EAAQ,OAAS,oBAAqBY,EAAM,QAAQ,CAAE,OAAQZ,EAAQ,MAAO,CAAC,EAC7EY,EAAM,OAAO,IAAI,MAAMZ,EAAQ,OAAO,CAAC,EAC9C,EAEMc,EAAgBC,GAAyB,CAC7CA,EAAO,oBAAoB,UAAWF,CAAa,EACnDE,EAAO,oBAAoB,QAASC,CAAW,CACjD,EAEMA,EAAejB,GAAsB,CACzC,IAAMkB,EAASV,EACfA,EAAS,KACLU,IACFH,EAAaG,CAAM,EACnBA,EAAO,UAAU,GAEnBN,EAAUZ,EAAM,OAAS,IAAI,MAAMA,EAAM,SAAW,yBAAyB,CAAC,CAChF,EAEMmB,EAAe,IAAc,CACjC,GAAIX,EAAQ,OAAOA,EACnB,GAAIE,EAAW,MAAM,IAAI,MAAM,0CAA0C,EACzE,OAAAF,EAASD,EAAa,EACtBC,EAAO,iBAAiB,UAAWM,CAAa,EAChDN,EAAO,iBAAiB,QAASS,CAAW,EACrCT,CACT,EAEA,MAAO,CACL,QAAQtC,EAAS,CACf,GAAIA,EAAQ,OAAO,QAAS,OAAO,QAAQ,OAAOkC,EAAWlC,EAAQ,OAAO,MAAM,CAAC,EACnF,IAAMgC,EAAY,EAAEO,EACpB,OAAO,IAAI,QAAiC,CAACd,EAASyB,IAAW,CAC/D,IAAMC,EAAQ,IAAM,CACJV,EAAQ,IAAIT,CAAS,IAEnCS,EAAQ,OAAOT,CAAS,EACxBM,GAAQ,YAAY,CAAE,KAAM,oBAAqB,UAAAN,CAAU,CAAmC,EAC9FkB,EAAOhB,EAAWlC,EAAQ,OAAO,MAAM,CAAC,EAC1C,EACAyC,EAAQ,IAAIT,EAAW,CAAE,QAAAP,EAAS,OAAAyB,EAAQ,OAAQlD,EAAQ,OAAQ,MAAAmD,CAAM,CAAC,EACzEnD,EAAQ,OAAO,iBAAiB,QAASmD,EAAO,CAAE,KAAM,EAAK,CAAC,EAC9D,GAAM,CAAE,OAAQC,EAAS,GAAGC,CAAQ,EAAIrD,EAExC,GAAI,CACFiD,EAAa,EAAE,YAAY,CACzB,KAAM,qBACN,UAAAjB,EACA,QAAAqB,CACF,CAA2C,CAC7C,OAASlC,EAAO,CACdsB,EAAQ,OAAOT,CAAS,EACxBhC,EAAQ,OAAO,oBAAoB,QAASmD,CAAK,EACjDD,EAAO/B,aAAiB,MAAQA,EAAQ,IAAI,MAAM,OAAOA,CAAK,CAAC,CAAC,CAClE,CACF,CAAC,CACH,EACA,SAAU,CACR,GAAI,CAAAqB,EAGJ,IAFAA,EAAY,GACZE,EAAUR,EAAW,iCAAiC,CAAC,EACnDI,EAAQ,CACV,IAAMgB,EAAUhB,EAChBO,EAAaS,CAAO,EAChBjC,EAAQ,qBAAuB,IAAOiC,EAAQ,UAAU,CAC9D,CACAhB,EAAS,KACX,CACF,CACF","names":["UNSAFE_PATH_SEGMENTS","isSafePath","path","part","getByPath","obj","cur","start","idx","collator","defaultComparator","valueA","valueB","aEmpty","bEmpty","a","b","textOf","value","evaluateTextFilter","conditions","operator","v","results","c","fv","evaluateNumberFilter","isBlank","n","f","toTime","t","evaluateDateFilter","f2","evaluateSetFilter","filterValues","evaluateColumnFilter","filter","evaluateAdvancedRow","node","data","fields","field","evaluateColumnFilter","getByPath","passed","child","passesColumnFilters","request","colId","filter","passesQuickFilter","tokens","token","column","value","passesWorkerFilters","quickTokens","sortProcessedRows","rows","left","right","sort","compared","defaultComparator","throwIfCancelled","isCancelled","error","processFieldDataRequest","options","yieldEvery","filtered","index","resolve","row","installGridDataWorker","scope","cancelled","event","message","requestId","result","abortError","reason","createWorkerDataProcessor","createWorker","worker","sequence","destroyed","pending","settleAll","entry","handleMessage","detachWorker","target","handleError","failed","ensureWorker","reject","abort","_signal","payload","current"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agile-team/mach-table",
3
- "version": "0.18.1",
3
+ "version": "0.19.1",
4
4
  "description": "Enterprise-grade, framework-agnostic TypeScript data grid with virtualization, editing, grouping and extensibility",
5
5
  "keywords": [
6
6
  "data-grid",
@@ -43,6 +43,16 @@
43
43
  "default": "./dist/index.cjs"
44
44
  }
45
45
  },
46
+ "./worker": {
47
+ "import": {
48
+ "types": "./dist/worker.d.ts",
49
+ "default": "./dist/worker.js"
50
+ },
51
+ "require": {
52
+ "types": "./dist/worker.d.cts",
53
+ "default": "./dist/worker.cjs"
54
+ }
55
+ },
46
56
  "./styles/mach-table.css": {
47
57
  "types": "./styles/mach-table.css.d.ts",
48
58
  "default": "./styles/mach-table.css"
@@ -60,5 +70,6 @@
60
70
  "typecheck": "tsc --noEmit",
61
71
  "test": "vitest run",
62
72
  "test:coverage": "vitest run --coverage"
63
- }
73
+ },
74
+ "readme": "<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/ChenyCHENYU/MachTable/main/assets/mach-table-logo.svg\" alt=\"MachTable\" width=\"760\" />\n</p>\n\n# @agile-team/mach-table\n\nEnterprise-grade, framework-independent TypeScript data grid. Zero runtime dependencies, virtualized rows and columns, polished cell/full-row editing, async validation, action columns, change tracking, versioned state and resilient infinite loading.\n\n```bash\npnpm add @agile-team/mach-table\n```\n\n```ts\nimport { createGrid } from \"@agile-team/mach-table\";\nimport \"@agile-team/mach-table/styles/mach-table.css\";\n\nconst api = createGrid(document.querySelector(\"#grid\")!, {\n columnDefs: [\n { field: \"id\", headerName: \"ID\", width: 120 },\n { field: \"name\", headerName: \"Name\", flex: 1, editable: true }\n ],\n rowData: [{ id: \"1\", name: \"MachTable\" }],\n rowKey: \"id\",\n enableColumnResize: true,\n stateKey: \"customer-list\"\n});\n\n// Required for native integrations when the host is removed.\napi.destroy();\n```\n\nComplex business workflows use first-class APIs instead of adapter-specific glue:\n\n```ts\nconst state = api.getState();\nawait api.saveChanges((changes) => orderApi.save(changes));\napi.rollbackChanges();\nconsole.info(api.getDiagnostics());\n\nawait api.applyTransactionAsync({ update: realtimeRows });\napi.applyState(state);\n```\n\n0.19 adds a lower-cost rendering pipeline and a smaller, more discoverable imperative surface without removing the flat 0.x API:\n\n```ts\napi.batch((grid) => {\n grid.rows.apply({ update: changedRows });\n grid.columns.setVisible(\"internalNote\", false);\n grid.refreshCells({ rowIds: changedIds, columns: [\"status\"] });\n});\n\nconsole.info(api.diagnostics.get().updates);\n```\n\nFor very large remote datasets, opt into random-access blocks. Sequential infinite loading remains the compatibility default:\n\n```ts\nconst options = {\n datasource,\n datasourceMode: \"block\" as const,\n datasourceRowCount: 1_000_000,\n blockSize: 200,\n maxBlocksInCache: 12,\n blockPrefetch: 1\n};\n\nawait api.rows.ensureLoaded(40_000, 40_200, { signal });\nconsole.info(api.rows.getCacheSnapshot());\n```\n\nWorker runtime helpers are intentionally split from the default entry:\n\n```ts\nimport { createWorkerDataProcessor, installGridDataWorker } from \"@agile-team/mach-table/worker\";\n```\n\n0.18 added governed runtime APIs, nested filters, named views, conflict-aware saves and performance evidence:\n\n```ts\nconst views = createGridViewManager(api, { scope: \"tenant:user:orders\" });\nawait views.save(\"My pending orders\");\n\nconst result = await api.saveChangesDetailed(orderApi.saveChanges);\nconsole.table(result.failures);\nconsole.table(result.conflicts);\nconsole.info(api.getDiagnostics().performance);\n```\n\n`GridState` v1 inputs migrate to v2 automatically. `GridFeature` manifests can declare `version`, `requires` and `conflicts`; invalid graphs are isolated before setup side effects run. JavaScript/JSON option patches are sanitized from the same metadata registry used by Core and framework adapters.\n\n0.13 added a built-in/headless column workbench and cancellable lazy trees:\n\n```ts\napi.openColumnWorkbench();\nconst columns = api.getColumnWorkbenchItems();\n\nconst treeOptions = {\n treeData: true,\n isTreeRowExpandable: ({ data }) => data.hasChildren,\n loadTreeChildren: ({ data, signal }) => catalogApi.children(data.id, { signal })\n};\n```\n\nXLSX stays outside Core; install `@agile-team/mach-table-xlsx` only on Excel routes.\n\nPolished editing and row actions are built in rather than adapter-specific:\n\n```ts\nimport { rowActionsColumn } from \"@agile-team/mach-table\";\n\nconst options = {\n editType: \"fullRow\" as const,\n columnDefs: [\n { field: \"name\", editable: true },\n { field: \"age\", editable: true, cellEditor: \"number\" },\n rowActionsColumn({ onView, onDelete, overflow: \"drawer\" })\n ]\n};\n```\n\nCell mode remains the default and renders a subtle pencil plus inline confirm/cancel controls. Use `editableIndicator: \"always\" | \"hover\" | \"none\"` to match the page density.\n\n0.14 removes common page glue with automatic GridState persistence, an explicit error overlay, compact row keys and framework-neutral toolbar commands:\n\n```ts\nimport { createMachTableCommands } from \"@agile-team/mach-table\";\n\nconst commands = createMachTableCommands({ getApi: () => api });\ncommands.search(\"pending\");\nawait commands.refresh();\n\napi.setOverlay(\"error\", () => \"Request failed. Please retry.\");\n```\n\n`rowKey: \"id\"` is shorthand for a stable field path; `getRowId` remains available for derived IDs and wins when both are present. `domLayout: \"autoHeight\"` is intended only for small client-side tables—normal virtual layout remains the large-data default.\n\nColumn resizing is deliberately opt-in. Set `enableColumnResize: true`; add `stateKey` to remember the complete workspace, or `columnStateKey` to remember only widths/order/visibility/pinning/sort. Pointer cancellation rolls back, completed drags persist once, and untouched automatic/flex columns remain responsive.\n\nFor framework applications use the official adapters:\n\n- Vue 3: [`@agile-team/mach-table-vue`](https://www.npmjs.com/package/@agile-team/mach-table-vue)\n- React 18+: [`@agile-team/mach-table-react`](https://www.npmjs.com/package/@agile-team/mach-table-react)\n\nDocumentation: [Quick start](https://github.com/ChenyCHENYU/MachTable/blob/main/docs/guide/getting-started.md) · [Enterprise integration](https://github.com/ChenyCHENYU/MachTable/blob/main/docs/guide/enterprise-integration.md) · [API](https://github.com/ChenyCHENYU/MachTable/tree/main/docs/api)\n\n> Overlay strings render as text by default. Prefer HTMLElement factories for rich content; enable `allowUnsafeOverlayHtml` only for fully trusted static markup.\n\nSource-available © ChenyCHENYU (Agile Team). Any use requires prior written authorization. See the [license](https://github.com/ChenyCHENYU/MachTable/blob/main/LICENSE) and [authorization process](https://github.com/ChenyCHENYU/MachTable/blob/main/LICENSING.md).\n"
64
75
  }
@@ -65,6 +65,7 @@
65
65
  -webkit-font-smoothing: antialiased;
66
66
  -moz-osx-font-smoothing: grayscale;
67
67
  font-variant-numeric: tabular-nums;
68
+ contain: layout style;
68
69
  }
69
70
 
70
71
  .mach-root.mach-dom-layout--auto-height {
@@ -562,6 +563,29 @@
562
563
  line-height: calc(var(--mach-row-h) - 2px);
563
564
  }
564
565
 
566
+ .mach-cell--loading {
567
+ pointer-events: none;
568
+ }
569
+
570
+ .mach-cell-loading-bar {
571
+ display: block;
572
+ height: 8px;
573
+ max-width: 132px;
574
+ border-radius: 999px;
575
+ background: linear-gradient(90deg, var(--mach-row-hover-bg), var(--mach-border-color), var(--mach-row-hover-bg));
576
+ background-size: 200% 100%;
577
+ animation: mach-cell-loading 1.25s ease-in-out infinite;
578
+ }
579
+
580
+ @keyframes mach-cell-loading {
581
+ from { background-position: 200% 0; }
582
+ to { background-position: -200% 0; }
583
+ }
584
+
585
+ @media (prefers-reduced-motion: reduce) {
586
+ .mach-cell-loading-bar { animation: none; }
587
+ }
588
+
565
589
  .mach-cell--num {
566
590
  justify-content: flex-end;
567
591
  }