@toolbox-web/grid 2.0.0-alpha → 2.0.0-rc.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.
@@ -8,6 +8,54 @@ export type { AggregatorFn, AggregatorRef } from '../../core/internal/aggregator
8
8
  export type { ExpandCollapseAnimation } from '../../core/types';
9
9
  /** Map of field names to aggregator references */
10
10
  export type AggregatorMap = Record<string, import('../../core/internal/aggregators').AggregatorRef>;
11
+ /**
12
+ * Pre-defined group definition for server-side grouping.
13
+ *
14
+ * When groups are provided externally (e.g. from a server), this interface
15
+ * describes each group's structure. The plugin renders these groups as
16
+ * collapsible headers and emits events when users expand/collapse them,
17
+ * allowing the consumer to lazily load row data.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const groups: GroupDefinition[] = [
22
+ * { key: 'Engineering', value: 'Engineering', rowCount: 150 },
23
+ * { key: 'Sales', value: 'Sales', rowCount: 89 },
24
+ * { key: 'Marketing', value: 'Marketing', rowCount: 42,
25
+ * children: [
26
+ * { key: 'Digital', value: 'Digital', rowCount: 20 },
27
+ * { key: 'Brand', value: 'Brand', rowCount: 22 },
28
+ * ],
29
+ * },
30
+ * ];
31
+ * ```
32
+ */
33
+ export interface GroupDefinition {
34
+ /** Unique group identifier. */
35
+ key: string;
36
+ /** Display value for the group header. */
37
+ value: unknown;
38
+ /** Expected row count from server (for display in group header). */
39
+ rowCount?: number;
40
+ /** Nested child groups for multi-level grouping. */
41
+ children?: GroupDefinition[];
42
+ /** Server-computed aggregate values keyed by field name. */
43
+ aggregates?: Record<string, unknown>;
44
+ }
45
+ /** Detail payload for `group-expand` event. */
46
+ export interface GroupExpandDetail {
47
+ /** The key of the group being expanded. */
48
+ groupKey: string;
49
+ /** The full path of group keys from root to this group. */
50
+ groupPath: string[];
51
+ }
52
+ /** Detail payload for `group-collapse` event. */
53
+ export interface GroupCollapseDetail {
54
+ /** The key of the group being collapsed. */
55
+ groupKey: string;
56
+ /** The full path of group keys from root to this group. */
57
+ groupPath: string[];
58
+ }
11
59
  /**
12
60
  * Default expanded state for group rows.
13
61
  * - `boolean`: true = expand all, false = collapse all
@@ -21,8 +69,60 @@ export interface GroupingRowsConfig {
21
69
  /**
22
70
  * Callback to determine group path for a row.
23
71
  * Return an array of group keys, a single key, null/false to skip grouping.
72
+ *
73
+ * Mutually exclusive with `groups` — when `groups` is provided, `groupOn` is ignored.
24
74
  */
25
75
  groupOn?: (row: any) => any[] | any | null | false;
76
+ /**
77
+ * Pre-defined group structure for server-side grouping.
78
+ *
79
+ * When provided, the plugin renders these groups as collapsible headers
80
+ * instead of analyzing row data with `groupOn`.
81
+ *
82
+ * Accepts:
83
+ * - A static `GroupDefinition[]` array
84
+ * - An async callback `() => Promise<GroupDefinition[]>` that fetches groups on attach
85
+ *
86
+ * When combined with {@link GroupingRowsConfig.rows | rows}, the plugin handles
87
+ * the full lifecycle automatically — loading indicator, data fetch, and render.
88
+ *
89
+ * @example Static groups
90
+ * ```typescript
91
+ * new GroupingRowsPlugin({
92
+ * groups: [
93
+ * { key: 'Engineering', value: 'Engineering', rowCount: 150 },
94
+ * { key: 'Sales', value: 'Sales', rowCount: 89 },
95
+ * ],
96
+ * });
97
+ * ```
98
+ *
99
+ * @example Async groups with lazy-loaded rows
100
+ * ```typescript
101
+ * new GroupingRowsPlugin({
102
+ * groups: () => fetch('/api/groups').then(r => r.json()),
103
+ * rows: (group) => fetch(`/api/groups/${group.key}/rows`).then(r => r.json()),
104
+ * });
105
+ * ```
106
+ */
107
+ groups?: GroupDefinition[] | (() => Promise<GroupDefinition[]>);
108
+ /**
109
+ * Callback to lazily load rows for an expanded group.
110
+ *
111
+ * When a user expands a group, the plugin calls this callback with the
112
+ * group definition. The plugin manages the loading indicator automatically.
113
+ *
114
+ * If not provided, use the imperative {@link GroupingRowsPlugin.setGroupRows | setGroupRows()}
115
+ * API and listen for `group-expand` events instead.
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * new GroupingRowsPlugin({
120
+ * groups: () => fetch('/api/groups').then(r => r.json()),
121
+ * rows: (group) => fetch(`/api/groups/${group.key}/rows`).then(r => r.json()),
122
+ * });
123
+ * ```
124
+ */
125
+ rows?: (group: GroupDefinition) => Promise<unknown[]>;
26
126
  /**
27
127
  * Default expanded state for group rows.
28
128
  * - `true`: Expand all groups initially
@@ -178,6 +278,10 @@ declare module '../../core/types' {
178
278
  interface DataGridEventMap {
179
279
  /** Fired when a row group is expanded or collapsed. @group Grouping Events */
180
280
  'group-toggle': GroupToggleDetail;
281
+ /** Fired when a pre-defined group is expanded. @group Grouping Events */
282
+ 'group-expand': GroupExpandDetail;
283
+ /** Fired when a pre-defined group is collapsed. @group Grouping Events */
284
+ 'group-collapse': GroupCollapseDetail;
181
285
  }
182
286
  interface PluginNameMap {
183
287
  groupingRows: import('./GroupingRowsPlugin').GroupingRowsPlugin;
@@ -1,2 +1,2 @@
1
- function e(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function t(t,o,r,s){return`${e(r,s)} ${t}: ${o}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(t)}`}["__otorp__","__retteGenifed__","__retteSenifed__","rotcurtsnoc","wodniw","sihTlabolg","labolg","ssecorp","noitcnuF","tropmi","lave","tcelfeR","yxorP","rorrE","stnemugra","tnemucod","noitacol","eikooc","egarotSlacol","egarotSnoisses","BDdexedni","hctef","tseuqeRpttHLMX","tekcoSbeW","rekroW","rekroWderahS","rekroWecivreS","renepo","tnerap","pot","semarf","fles"].map(e=>e.split("").reverse().join(""));const o=/* @__PURE__ */new Set(["script","iframe","object","embed","form","input","button","textarea","select","link","meta","base","style","template","slot","portal","frame","frameset","applet","noscript","noembed","plaintext","xmp","listing"]),r=/^on\w+$/i,s=/* @__PURE__ */new Set(["href","src","action","formaction","data","srcdoc","xlink:href","poster","srcset"]),i=/^\s*(javascript|vbscript|data|blob):/i;function n(e){if(!e||"string"!=typeof e)return"";if(-1===e.indexOf("<"))return e;const t=document.createElement("template");return t.innerHTML=e,function(e){const t=[],n=e.querySelectorAll("*");for(const a of n){const e=a.tagName.toLowerCase();if(o.has(e)){t.push(a);continue}if("svg"===e||"http://www.w3.org/2000/svg"===a.namespaceURI){if(Array.from(a.attributes).some(e=>r.test(e.name)||"href"===e.name||"xlink:href"===e.name)){t.push(a);continue}}const n=[];for(const t of a.attributes){const e=t.name.toLowerCase();r.test(e)?n.push(t.name):(s.has(e)&&i.test(t.value)||"style"===e&&/expression\s*\(|javascript:|behavior\s*:/i.test(t.value))&&n.push(t.name)}n.forEach(e=>a.removeAttribute(e))}t.forEach(e=>e.remove())}(t.content),t.innerHTML}const a='<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>',l={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:a,filterActive:a,print:"🖨️"};class c{static dependencies;static manifest;aliases;version="undefined"!=typeof __GRID_VERSION__?__GRID_VERSION__:"dev";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}attach(e){this.#e?.abort(),this.#e=new AbortController,this.grid=e,this.config={...this.defaultConfig,...this.userConfig}}detach(){this.#e?.abort(),this.#e=void 0}getPlugin(e){return this.grid?.getPlugin(e)}emit(e,t){this.grid?.dispatchEvent?.(new CustomEvent(e,{detail:t,bubbles:!0}))}emitCancelable(e,t){const o=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(o),o.defaultPrevented}on(e,t){this.grid?._pluginManager?.subscribe(this,e,t)}off(e){this.grid?._pluginManager?.unsubscribe(this,e)}emitPluginEvent(e,t){this.grid?._pluginManager?.emitPluginEvent(e,t)}requestRender(){this.grid?.requestRender?.()}requestColumnsRender(){this.grid?.requestColumnsRender?.()}requestRenderWithFocus(){this.grid?.requestRenderWithFocus?.()}requestAfterRender(){this.grid?.requestAfterRender?.()}requestVirtualRefresh(){this.grid?.requestVirtualRefresh?.()}get rows(){return this.grid?.rows??[]}get sourceRows(){return this.grid?.sourceRows??[]}get columns(){return this.grid?.columns??[]}get visibleColumns(){return this.grid?._visibleColumns??[]}get gridElement(){return this.grid?._hostElement}get disconnectSignal(){return this.#e?.signal??this.grid?.disconnectSignal}get gridIcons(){const e=this.grid?.gridConfig?.icons??{};return{...l,...e}}get isAnimationEnabled(){const e=this.grid?.effectiveConfig?.animation?.mode??"reduced-motion";if(!1===e||"off"===e)return!1;if(!0===e||"on"===e)return!0;const t=this.gridElement;if(t){return"0"!==getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()}return!0}get animationDuration(){const e=this.gridElement;if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(),o=parseInt(t,10);if(!isNaN(o))return o}return 200}setIcon(e,t,o){e.dataset.icon=t.replace(/([A-Z])/g,"-$1").toLowerCase(),"collapse"===t?e.dataset.expanded="":"expand"===t&&delete e.dataset.expanded;const r=this.#t(t,o);void 0!==r?"string"==typeof r?e.innerHTML=n(r):r instanceof HTMLElement&&(e.innerHTML="",e.appendChild(r.cloneNode(!0))):e.innerHTML=""}#t(e,t){return void 0!==t?t:this.grid?.gridConfig?.icons?.[e]}updateSortIndicator(e,t){e.querySelector('[part~="sort-indicator"], .sort-indicator')?.remove();const o=document.createElement("span");o.setAttribute("part","sort-indicator"),o.className="sort-indicator",t?(e.setAttribute("aria-sort","asc"===t?"ascending":"descending"),e.setAttribute("data-sort",t),this.setIcon(o,"asc"===t?"sortAsc":"sortDesc")):(e.setAttribute("aria-sort","none"),e.removeAttribute("data-sort"),this.setIcon(o,"sortNone"));const r=e.querySelector(".tbw-filter-btn")??e.querySelector(".resize-handle");return r?e.insertBefore(o,r):e.appendChild(o),o}warn(o,r){void 0!==r?console.warn(t(o,r,this.gridElement.id,this.name)):console.warn(`${e(this.gridElement.id,this.name)} ${o}`)}throwDiagnostic(e,o){throw new Error(t(e,o,this.gridElement.id,this.name))}}function d(e,t){return Math.floor(e/t)}async function u(e,t,o,r){const s=function(e,t){return{start:e*t,end:(e+1)*t}}(t,o);return e.getRows({startRow:s.start,endRow:s.end,sortModel:r.sortModel,filterModel:r.filterModel})}function h(e,t,o){const r=d(e,t),s=o.get(r);if(!s)return;return s[e%t]}class g extends c{static manifest={incompatibleWith:[{name:"groupingRows",reason:"Row grouping requires the full dataset to compute group boundaries. ServerSidePlugin lazy-loads rows in blocks, so groups cannot be built client-side. Server-side grouping would require hierarchical loading (group headers first, then rows on expand)."},{name:"tree",reason:"TreePlugin requires the full hierarchy to flatten and manage expansion state. ServerSidePlugin lazy-loads rows in blocks and cannot provide nested children on demand. Server-side tree would require lazy child loading as nodes expand."},{name:"pivot",reason:"PivotPlugin requires the full dataset to compute aggregations. ServerSidePlugin lazy-loads rows in blocks, so pivot aggregation cannot be performed client-side."}]};name="serverSide";get defaultConfig(){return{pageSize:100,cacheBlockSize:100,maxConcurrentRequests:2}}dataSource=null;totalRowCount=0;loadedBlocks=/* @__PURE__ */new Map;loadingBlocks=/* @__PURE__ */new Set;lastRequestId=0;scrollDebounceTimer;managedRows=[];detach(){this.dataSource=null,this.totalRowCount=0,this.loadedBlocks.clear(),this.loadingBlocks.clear(),this.managedRows=[],this.lastRequestId=0,this.scrollDebounceTimer&&(clearTimeout(this.scrollDebounceTimer),this.scrollDebounceTimer=void 0)}loadRequiredBlocks(){if(!this.dataSource)return;const e=this.grid,t=this.config.cacheBlockSize??100,o={startRow:e._virtualization.start,endRow:e._virtualization.end},r=function(e,t,o){const r=d(e,o),s=d(t-1,o),i=[];for(let n=r;n<=s;n++)i.push(n);return i}(o.startRow,o.endRow,t);for(const s of r)if(!this.loadedBlocks.has(s)&&!this.loadingBlocks.has(s)){if(this.loadingBlocks.size>=(this.config.maxConcurrentRequests??2))break;this.loadingBlocks.add(s),u(this.dataSource,s,t,{}).then(e=>{this.loadedBlocks.set(s,e.rows),this.totalRowCount=e.totalRowCount,this.loadingBlocks.delete(s);const o=s*t;for(let t=0;t<e.rows.length;t++)o+t<this.managedRows.length&&(this.managedRows[o+t]=e.rows[t]);this.requestVirtualRefresh(),this.loadRequiredBlocks()}).catch(()=>{this.loadingBlocks.delete(s)})}}processRows(e){if(!this.dataSource)return[...e];const t=this.config.cacheBlockSize??100;for(;this.managedRows.length<this.totalRowCount;){const e=this.managedRows.length;this.managedRows.push({__loading:!0,__index:e})}this.managedRows.length=this.totalRowCount;for(let o=0;o<this.totalRowCount;o++){const e=h(o,t,this.loadedBlocks);e&&(this.managedRows[o]=e)}return this.managedRows}onScroll(e){this.dataSource&&(this.loadRequiredBlocks(),this.scrollDebounceTimer&&clearTimeout(this.scrollDebounceTimer),this.scrollDebounceTimer=setTimeout(()=>{this.loadRequiredBlocks()},100))}setDataSource(e){this.dataSource=e,this.loadedBlocks.clear(),this.loadingBlocks.clear(),this.managedRows=[];u(e,0,this.config.cacheBlockSize??100,{}).then(e=>{this.loadedBlocks.set(0,e.rows),this.totalRowCount=e.totalRowCount,this.requestRender()})}refresh(){this.dataSource&&(this.loadedBlocks.clear(),this.loadingBlocks.clear(),this.managedRows=[],this.requestRender())}purgeCache(){this.loadedBlocks.clear(),this.managedRows=[]}getTotalRowCount(){return this.totalRowCount}isRowLoaded(e){const t=d(e,this.config.cacheBlockSize??100);return this.loadedBlocks.has(t)}getLoadedBlockCount(){return this.loadedBlocks.size}}export{g as ServerSidePlugin};
1
+ function e(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function t(t,o,r,s){return`${e(r,s)} ${t}: ${o}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(t)}`}["__otorp__","__retteGenifed__","__retteSenifed__","rotcurtsnoc","wodniw","sihTlabolg","labolg","ssecorp","noitcnuF","tropmi","lave","tcelfeR","yxorP","rorrE","stnemugra","tnemucod","noitacol","eikooc","egarotSlacol","egarotSnoisses","BDdexedni","hctef","tseuqeRpttHLMX","tekcoSbeW","rekroW","rekroWderahS","rekroWecivreS","renepo","tnerap","pot","semarf","fles"].map(e=>e.split("").reverse().join(""));const o=/* @__PURE__ */new Set(["script","iframe","object","embed","form","input","button","textarea","select","link","meta","base","style","template","slot","portal","frame","frameset","applet","noscript","noembed","plaintext","xmp","listing"]),r=/^on\w+$/i,s=/* @__PURE__ */new Set(["href","src","action","formaction","data","srcdoc","xlink:href","poster","srcset"]),i=/^\s*(javascript|vbscript|data|blob):/i;function n(e){if(!e||"string"!=typeof e)return"";if(-1===e.indexOf("<"))return e;const t=document.createElement("template");return t.innerHTML=e,function(e){const t=[],n=e.querySelectorAll("*");for(const a of n){const e=a.tagName.toLowerCase();if(o.has(e)){t.push(a);continue}if("svg"===e||"http://www.w3.org/2000/svg"===a.namespaceURI){if(Array.from(a.attributes).some(e=>r.test(e.name)||"href"===e.name||"xlink:href"===e.name)){t.push(a);continue}}const n=[];for(const t of a.attributes){const e=t.name.toLowerCase();r.test(e)?n.push(t.name):(s.has(e)&&i.test(t.value)||"style"===e&&/expression\s*\(|javascript:|behavior\s*:/i.test(t.value))&&n.push(t.name)}n.forEach(e=>a.removeAttribute(e))}t.forEach(e=>e.remove())}(t.content),t.innerHTML}const a='<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>',l={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:a,filterActive:a,print:"🖨️"};class c{static dependencies;static manifest;aliases;version="undefined"!=typeof __GRID_VERSION__?__GRID_VERSION__:"dev";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}attach(e){this.#e?.abort(),this.#e=new AbortController,this.grid=e,this.config={...this.defaultConfig,...this.userConfig}}detach(){this.#e?.abort(),this.#e=void 0}getPlugin(e){return this.grid?.getPlugin(e)}emit(e,t){this.grid?.dispatchEvent?.(new CustomEvent(e,{detail:t,bubbles:!0}))}emitCancelable(e,t){const o=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(o),o.defaultPrevented}on(e,t){this.grid?._pluginManager?.subscribe(this,e,t)}off(e){this.grid?._pluginManager?.unsubscribe(this,e)}emitPluginEvent(e,t){this.grid?._pluginManager?.emitPluginEvent(e,t)}requestRender(){this.grid?.requestRender?.()}requestColumnsRender(){this.grid?.requestColumnsRender?.()}requestRenderWithFocus(){this.grid?.requestRenderWithFocus?.()}requestAfterRender(){this.grid?.requestAfterRender?.()}requestVirtualRefresh(){this.grid?.requestVirtualRefresh?.()}get rows(){return this.grid?.rows??[]}get sourceRows(){return this.grid?.sourceRows??[]}get columns(){return this.grid?.columns??[]}get visibleColumns(){return this.grid?._visibleColumns??[]}get gridElement(){return this.grid?._hostElement}get disconnectSignal(){return this.#e?.signal??this.grid?.disconnectSignal}get gridIcons(){const e=this.grid?.gridConfig?.icons??{};return{...l,...e}}get isAnimationEnabled(){const e=this.grid?.effectiveConfig?.animation?.mode??"reduced-motion";if(!1===e||"off"===e)return!1;if(!0===e||"on"===e)return!0;const t=this.gridElement;if(t){return"0"!==getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()}return!0}get animationDuration(){const e=this.gridElement;if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(),o=parseInt(t,10);if(!isNaN(o))return o}return 200}setIcon(e,t,o){e.dataset.icon=t.replace(/([A-Z])/g,"-$1").toLowerCase(),"collapse"===t?e.dataset.expanded="":"expand"===t&&delete e.dataset.expanded;const r=this.#t(t,o);void 0!==r?"string"==typeof r?e.innerHTML=n(r):r instanceof HTMLElement&&(e.innerHTML="",e.appendChild(r.cloneNode(!0))):e.innerHTML=""}#t(e,t){return void 0!==t?t:this.grid?.gridConfig?.icons?.[e]}updateSortIndicator(e,t){e.querySelector('[part~="sort-indicator"], .sort-indicator')?.remove();const o=document.createElement("span");o.setAttribute("part","sort-indicator"),o.className="sort-indicator",t?(e.setAttribute("aria-sort","asc"===t?"ascending":"descending"),e.setAttribute("data-sort",t),this.setIcon(o,"asc"===t?"sortAsc":"sortDesc")):(e.setAttribute("aria-sort","none"),e.removeAttribute("data-sort"),this.setIcon(o,"sortNone"));const r=e.querySelector(".tbw-filter-btn")??e.querySelector(".resize-handle");return r?e.insertBefore(o,r):e.appendChild(o),o}warn(o,r){void 0!==r?console.warn(t(o,r,this.gridElement.id,this.name)):console.warn(`${e(this.gridElement.id,this.name)} ${o}`)}throwDiagnostic(e,o){throw new Error(t(e,o,this.gridElement.id,this.name))}}function d(e,t){return Math.floor(e/t)}async function u(e,t,o,r){const s=function(e,t){return{start:e*t,end:(e+1)*t}}(t,o);return e.getRows({startRow:s.start,endRow:s.end,sortModel:r.sortModel,filterModel:r.filterModel})}function h(e,t,o){const r=d(e,t),s=o.get(r);if(!s)return;return s[e%t]}class g extends c{static manifest={incompatibleWith:[{name:"tree",reason:"TreePlugin requires the full hierarchy to flatten and manage expansion state. ServerSidePlugin lazy-loads rows in blocks and cannot provide nested children on demand. Server-side tree would require lazy child loading as nodes expand."},{name:"pivot",reason:"PivotPlugin requires the full dataset to compute aggregations. ServerSidePlugin lazy-loads rows in blocks, so pivot aggregation cannot be performed client-side."}]};name="serverSide";get defaultConfig(){return{pageSize:100,cacheBlockSize:100,maxConcurrentRequests:2}}dataSource=null;totalRowCount=0;loadedBlocks=/* @__PURE__ */new Map;loadingBlocks=/* @__PURE__ */new Set;lastRequestId=0;scrollDebounceTimer;managedRows=[];detach(){this.dataSource=null,this.totalRowCount=0,this.loadedBlocks.clear(),this.loadingBlocks.clear(),this.managedRows=[],this.lastRequestId=0,this.scrollDebounceTimer&&(clearTimeout(this.scrollDebounceTimer),this.scrollDebounceTimer=void 0)}loadRequiredBlocks(){if(!this.dataSource)return;const e=this.grid,t=this.config.cacheBlockSize??100,o={startRow:e._virtualization.start,endRow:e._virtualization.end},r=function(e,t,o){const r=d(e,o),s=d(t-1,o),i=[];for(let n=r;n<=s;n++)i.push(n);return i}(o.startRow,o.endRow,t);for(const s of r)if(!this.loadedBlocks.has(s)&&!this.loadingBlocks.has(s)){if(this.loadingBlocks.size>=(this.config.maxConcurrentRequests??2))break;this.loadingBlocks.add(s),u(this.dataSource,s,t,{}).then(e=>{this.loadedBlocks.set(s,e.rows),this.totalRowCount=e.totalRowCount,this.loadingBlocks.delete(s);const o=s*t;for(let t=0;t<e.rows.length;t++)o+t<this.managedRows.length&&(this.managedRows[o+t]=e.rows[t]);this.requestVirtualRefresh(),this.loadRequiredBlocks()}).catch(()=>{this.loadingBlocks.delete(s)})}}processRows(e){if(!this.dataSource)return[...e];const t=this.config.cacheBlockSize??100;for(;this.managedRows.length<this.totalRowCount;){const e=this.managedRows.length;this.managedRows.push({__loading:!0,__index:e})}this.managedRows.length=this.totalRowCount;for(let o=0;o<this.totalRowCount;o++){const e=h(o,t,this.loadedBlocks);e&&(this.managedRows[o]=e)}return this.managedRows}onScroll(e){this.dataSource&&(this.loadRequiredBlocks(),this.scrollDebounceTimer&&clearTimeout(this.scrollDebounceTimer),this.scrollDebounceTimer=setTimeout(()=>{this.loadRequiredBlocks()},100))}setDataSource(e){this.dataSource=e,this.loadedBlocks.clear(),this.loadingBlocks.clear(),this.managedRows=[];u(e,0,this.config.cacheBlockSize??100,{}).then(e=>{this.loadedBlocks.set(0,e.rows),this.totalRowCount=e.totalRowCount,this.requestRender()})}refresh(){this.dataSource&&(this.loadedBlocks.clear(),this.loadingBlocks.clear(),this.managedRows=[],this.requestRender())}purgeCache(){this.loadedBlocks.clear(),this.managedRows=[]}getTotalRowCount(){return this.totalRowCount}isRowLoaded(e){const t=d(e,this.config.cacheBlockSize??100);return this.loadedBlocks.has(t)}getLoadedBlockCount(){return this.loadedBlocks.size}}export{g as ServerSidePlugin};
2
2
  //# sourceMappingURL=index.js.map