gp-grid-core 0.3.0 → 0.4.0

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.
Files changed (2) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var e=class{state={activeCell:null,range:null,anchor:null,selectionMode:!1};options;listeners=[];constructor(e){this.options=e}onInstruction(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e)}}emit(e){for(let t of this.listeners)t(e)}getState(){return{...this.state}}getActiveCell(){return this.state.activeCell}getSelectionRange(){return this.state.range}isSelected(e,t){let{range:n}=this.state;if(!n)return!1;let r=Math.min(n.startRow,n.endRow),i=Math.max(n.startRow,n.endRow),a=Math.min(n.startCol,n.endCol),o=Math.max(n.startCol,n.endCol);return e>=r&&e<=i&&t>=a&&t<=o}isActiveCell(e,t){let{activeCell:n}=this.state;return n?.row===e&&n?.col===t}startSelection(e,t={}){let{shift:n=!1,ctrl:r=!1}=t,{row:i,col:a}=this.clampPosition(e);n&&this.state.anchor?(this.state.range={startRow:this.state.anchor.row,startCol:this.state.anchor.col,endRow:i,endCol:a},this.state.activeCell={row:i,col:a}):(this.state.activeCell={row:i,col:a},this.state.anchor={row:i,col:a},this.state.range=null),this.state.selectionMode=r,this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell}),this.emit({type:`SET_SELECTION_RANGE`,range:this.state.range})}moveFocus(e,t=!1){if(!this.state.activeCell){this.startSelection({row:0,col:0});return}let{row:n,col:r}=this.state.activeCell,i=n,a=r;switch(e){case`up`:i=Math.max(0,n-1);break;case`down`:i=Math.min(this.options.getRowCount()-1,n+1);break;case`left`:a=Math.max(0,r-1);break;case`right`:a=Math.min(this.options.getColumnCount()-1,r+1);break}t?(this.state.anchor||(this.state.anchor={row:n,col:r}),this.state.range={startRow:this.state.anchor.row,startCol:this.state.anchor.col,endRow:i,endCol:a},this.state.activeCell={row:i,col:a},this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell}),this.emit({type:`SET_SELECTION_RANGE`,range:this.state.range})):(this.state.activeCell={row:i,col:a},this.state.anchor={row:i,col:a},this.state.range=null,this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell}),this.emit({type:`SET_SELECTION_RANGE`,range:null}))}selectAll(){let e=this.options.getRowCount(),t=this.options.getColumnCount();e===0||t===0||(this.state.range={startRow:0,startCol:0,endRow:e-1,endCol:t-1},this.state.activeCell||(this.state.activeCell={row:0,col:0},this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell})),this.emit({type:`SET_SELECTION_RANGE`,range:this.state.range}))}clearSelection(){this.state.activeCell=null,this.state.range=null,this.state.anchor=null,this.state.selectionMode=!1,this.emit({type:`SET_ACTIVE_CELL`,position:null}),this.emit({type:`SET_SELECTION_RANGE`,range:null})}setActiveCell(e,t){let n=this.clampPosition({row:e,col:t});this.state.activeCell=n,this.state.anchor=n,this.state.range=null,this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell}),this.emit({type:`SET_SELECTION_RANGE`,range:null})}setSelectionRange(e){this.state.range=e,this.emit({type:`SET_SELECTION_RANGE`,range:this.state.range})}getSelectedData(){let{range:e,activeCell:t}=this.state;if(!e&&!t)return[];let n=e||{startRow:t.row,startCol:t.col,endRow:t.row,endCol:t.col},r=Math.min(n.startRow,n.endRow),i=Math.max(n.startRow,n.endRow),a=Math.min(n.startCol,n.endCol),o=Math.max(n.startCol,n.endCol),s=[];for(let e=r;e<=i;e++){let t=[];for(let n=a;n<=o;n++)t.push(this.options.getCellValue(e,n));s.push(t)}return s}async copySelectionToClipboard(){let e=this.getSelectedData();if(e.length===0)return;let t=e.map(e=>e.map(e=>e==null?``:String(e)).join(` `)).join(`
1
+ var e=class{state={activeCell:null,range:null,anchor:null,selectionMode:!1};options;listeners=[];constructor(e){this.options=e}onInstruction(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e)}}emit(e){for(let t of this.listeners)t(e)}getState(){return{...this.state}}getActiveCell(){return this.state.activeCell}getSelectionRange(){return this.state.range}isSelected(e,t){let{range:n}=this.state;if(!n)return!1;let r=Math.min(n.startRow,n.endRow),i=Math.max(n.startRow,n.endRow),a=Math.min(n.startCol,n.endCol),o=Math.max(n.startCol,n.endCol);return e>=r&&e<=i&&t>=a&&t<=o}isActiveCell(e,t){let{activeCell:n}=this.state;return n?.row===e&&n?.col===t}startSelection(e,t={}){let{shift:n=!1,ctrl:r=!1}=t,{row:i,col:a}=this.clampPosition(e);n&&this.state.anchor?(this.state.range={startRow:this.state.anchor.row,startCol:this.state.anchor.col,endRow:i,endCol:a},this.state.activeCell={row:i,col:a}):(this.state.activeCell={row:i,col:a},this.state.anchor={row:i,col:a},this.state.range=null),this.state.selectionMode=r,this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell}),this.emit({type:`SET_SELECTION_RANGE`,range:this.state.range})}moveFocus(e,t=!1){if(!this.state.activeCell){this.startSelection({row:0,col:0});return}let{row:n,col:r}=this.state.activeCell,i=n,a=r;switch(e){case`up`:i=Math.max(0,n-1);break;case`down`:i=Math.min(this.options.getRowCount()-1,n+1);break;case`left`:a=Math.max(0,r-1);break;case`right`:a=Math.min(this.options.getColumnCount()-1,r+1);break}t?(this.state.anchor||(this.state.anchor={row:n,col:r}),this.state.range={startRow:this.state.anchor.row,startCol:this.state.anchor.col,endRow:i,endCol:a},this.state.activeCell={row:i,col:a},this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell}),this.emit({type:`SET_SELECTION_RANGE`,range:this.state.range})):(this.state.activeCell={row:i,col:a},this.state.anchor={row:i,col:a},this.state.range=null,this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell}),this.emit({type:`SET_SELECTION_RANGE`,range:null}))}selectAll(){let e=this.options.getRowCount(),t=this.options.getColumnCount();e===0||t===0||(this.state.range={startRow:0,startCol:0,endRow:e-1,endCol:t-1},this.state.activeCell||(this.state.activeCell={row:0,col:0},this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell})),this.emit({type:`SET_SELECTION_RANGE`,range:this.state.range}))}clearSelection(){this.state.activeCell=null,this.state.range=null,this.state.anchor=null,this.state.selectionMode=!1,this.emit({type:`SET_ACTIVE_CELL`,position:null}),this.emit({type:`SET_SELECTION_RANGE`,range:null})}setActiveCell(e,t){let n=this.clampPosition({row:e,col:t});this.state.activeCell=n,this.state.anchor=n,this.state.range=null,this.emit({type:`SET_ACTIVE_CELL`,position:this.state.activeCell}),this.emit({type:`SET_SELECTION_RANGE`,range:null})}setSelectionRange(e){this.state.range=e,this.emit({type:`SET_SELECTION_RANGE`,range:this.state.range})}getSelectedData(){let{range:e,activeCell:t}=this.state;if(!e&&!t)return[];let n=e||{startRow:t.row,startCol:t.col,endRow:t.row,endCol:t.col},r=Math.min(n.startRow,n.endRow),i=Math.max(n.startRow,n.endRow),a=Math.min(n.startCol,n.endCol),o=Math.max(n.startCol,n.endCol),s=[];for(let e=r;e<=i;e++){let t=[];for(let n=a;n<=o;n++)t.push(this.options.getCellValue(e,n));s.push(t)}return s}async copySelectionToClipboard(){if(typeof navigator>`u`||typeof document>`u`)return;let e=this.getSelectedData();if(e.length===0)return;let t=e.map(e=>e.map(e=>e==null?``:String(e)).join(` `)).join(`
2
2
  `);try{await navigator.clipboard.writeText(t)}catch{let e=document.createElement(`textarea`);e.value=t,e.style.position=`fixed`,e.style.left=`-9999px`,document.body.appendChild(e),e.select(),document.execCommand(`copy`),document.body.removeChild(e)}}clampPosition(e){let t=this.options.getRowCount(),n=this.options.getColumnCount();return{row:Math.max(0,Math.min(e.row,t-1)),col:Math.max(0,Math.min(e.col,n-1))}}},t=class{state=null;options;listeners=[];constructor(e){this.options=e}onInstruction(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e)}}emit(e){for(let t of this.listeners)t(e)}getState(){return this.state?{...this.state}:null}isActive(){return this.state!==null}startFillDrag(e){this.state={sourceRange:e,targetRow:e.endRow,targetCol:e.endCol},this.emit({type:`START_FILL`,sourceRange:e})}updateFillDrag(e,t){if(!this.state)return;let n=this.options.getRowCount(),r=this.options.getColumnCount();e=Math.max(0,Math.min(e,n-1)),t=Math.max(0,Math.min(t,r-1)),this.state.targetRow=e,this.state.targetCol=t,this.emit({type:`UPDATE_FILL`,targetRow:e,targetCol:t})}commitFillDrag(){if(!this.state)return;let{sourceRange:e,targetRow:t,targetCol:n}=this.state,r=this.calculateFilledCells(e,t,n);for(let{row:e,col:t,value:n}of r)this.options.setCellValue(e,t,n);this.emit({type:`COMMIT_FILL`,filledCells:r}),this.state=null}cancelFillDrag(){this.state&&(this.state=null,this.emit({type:`CANCEL_FILL`}))}calculateFilledCells(e,t,n){let r=[],i=Math.min(e.startRow,e.endRow),a=Math.max(e.startRow,e.endRow),o=Math.min(e.startCol,e.endCol),s=Math.max(e.startCol,e.endCol),c=t>a,l=t<i;if(c||l)for(let e=o;e<=s;e++){let n=this.getSourceColumnValues(i,a,e),o=this.detectPattern(n);if(c)for(let i=a+1;i<=t;i++){let t=i-a-1,s=this.applyPattern(o,n,t);r.push({row:i,col:e,value:s})}else if(l)for(let a=i-1;a>=t;a--){let t=i-a-1,s=this.applyPattern(o,n,t,!0);r.push({row:a,col:e,value:s})}}return r}getSourceColumnValues(e,t,n){let r=[];for(let i=e;i<=t;i++)r.push(this.options.getCellValue(i,n));return r}detectPattern(e){if(e.length===0)return{type:`constant`,value:null};if(e.length===1)return{type:`constant`,value:e[0]??null};let t=e.map(e=>typeof e==`number`?e:Number(e));if(t.every(e=>!isNaN(e))){let e=[];for(let n=1;n<t.length;n++)e.push(t[n]-t[n-1]);if(e.every(t=>t===e[0])&&e[0]!==void 0)return{type:`arithmetic`,start:t[0],step:e[0]}}return{type:`repeat`,values:e}}applyPattern(e,t,n,r=!1){switch(e.type){case`constant`:return e.value;case`arithmetic`:{let i=r?-(n+1):n+1;return(r?e.start:e.start+e.step*(t.length-1))+e.step*i}case`repeat`:{let t=e.values.length;if(t===0)return null;if(r){let r=(t-1-n%t+t)%t;return e.values[r]??null}return e.values[n%t]??null}}}},n=class{state={slots:new Map,rowToSlot:new Map,nextSlotId:0};options;listeners=[];batchListeners=[];constructor(e){this.options=e}onInstruction(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e)}}onBatchInstruction(e){return this.batchListeners.push(e),()=>{this.batchListeners=this.batchListeners.filter(t=>t!==e)}}emit(e){for(let t of this.listeners)t(e);for(let t of this.batchListeners)t([e])}emitBatch(e){if(e.length!==0){for(let t of this.batchListeners)t(e);for(let t of e)for(let e of this.listeners)e(t)}}getSlotForRow(e){return this.state.rowToSlot.get(e)}getSlots(){return this.state.slots}syncSlots(){let e=this.options.getScrollTop(),t=this.options.getRowHeight(),n=this.options.getViewportHeight(),r=this.options.getTotalRows(),i=this.options.getOverscan(),a=Math.max(0,Math.floor(e/t)-i),o=Math.min(r-1,Math.ceil((e+n)/t)+i);if(r===0||o<a){this.destroyAllSlots();return}let s=new Set;for(let e=a;e<=o;e++)s.add(e);let c=[],l=[];for(let[e,t]of this.state.slots)s.has(t.rowIndex)?s.delete(t.rowIndex):(l.push(e),this.state.rowToSlot.delete(t.rowIndex));let u=Array.from(s);for(let e=0;e<u.length;e++){let t=u[e],n=this.options.getRowData(t);if(e<l.length){let r=l[e],i=this.state.slots.get(r),a=this.getRowTranslateY(t);i.rowIndex=t,i.rowData=n??{},i.translateY=a,this.state.rowToSlot.set(t,r),c.push({type:`ASSIGN_SLOT`,slotId:r,rowIndex:t,rowData:n??{}}),c.push({type:`MOVE_SLOT`,slotId:r,translateY:a})}else{let e=`slot-${this.state.nextSlotId++}`,r=this.getRowTranslateY(t),i={slotId:e,rowIndex:t,rowData:n??{},translateY:r};this.state.slots.set(e,i),this.state.rowToSlot.set(t,e),c.push({type:`CREATE_SLOT`,slotId:e}),c.push({type:`ASSIGN_SLOT`,slotId:e,rowIndex:t,rowData:n??{}}),c.push({type:`MOVE_SLOT`,slotId:e,translateY:r})}}for(let e=u.length;e<l.length;e++){let t=l[e];this.state.slots.delete(t),c.push({type:`DESTROY_SLOT`,slotId:t})}for(let[e,t]of this.state.slots){let n=this.getRowTranslateY(t.rowIndex);t.translateY!==n&&(t.translateY=n,c.push({type:`MOVE_SLOT`,slotId:e,translateY:n}))}this.emitBatch(c)}destroyAllSlots(){let e=[];for(let t of this.state.slots.keys())e.push({type:`DESTROY_SLOT`,slotId:t});this.state.slots.clear(),this.state.rowToSlot.clear(),this.emitBatch(e)}refreshAllSlots(){let e=[],t=this.options.getTotalRows();for(let[n,r]of this.state.slots)if(r.rowIndex>=0&&r.rowIndex<t){let t=this.options.getRowData(r.rowIndex),i=this.getRowTranslateY(r.rowIndex);r.rowData=t??{},r.translateY=i,e.push({type:`ASSIGN_SLOT`,slotId:n,rowIndex:r.rowIndex,rowData:t??{}}),e.push({type:`MOVE_SLOT`,slotId:n,translateY:i})}this.emitBatch(e),this.syncSlots()}updateSlot(e){let t=this.state.rowToSlot.get(e);if(t){let n=this.options.getRowData(e);n&&this.emit({type:`ASSIGN_SLOT`,slotId:t,rowIndex:e,rowData:n})}}getRowTranslateY(e){let t=this.options.getRowHeight(),n=this.options.getHeaderHeight(),r=this.options.getScrollRatio(),i=this.options.getVirtualContentHeight(),a=this.options.getScrollTop(),o=e*t+n;if(r>=1)return o;let s=a,c=o-(s-s*r);return Math.max(0,Math.min(c,i))}},r=class{editState=null;options;listeners=[];constructor(e){this.options=e}onInstruction(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e)}}emit(e){for(let t of this.listeners)t(e)}getState(){return this.editState?{...this.editState}:null}isEditing(){return this.editState!==null}isEditingCell(e,t){return this.editState!==null&&this.editState.row===e&&this.editState.col===t}startEdit(e,t){let n=this.options.getColumn(t);if(!n||n.editable!==!0)return!1;let r=this.options.getCellValue(e,t);return this.editState={row:e,col:t,initialValue:r,currentValue:r},this.emit({type:`START_EDIT`,row:e,col:t,initialValue:r}),!0}updateValue(e){this.editState&&(this.editState.currentValue=e)}commit(){if(!this.editState)return;let{row:e,col:t,currentValue:n}=this.editState;this.options.setCellValue(e,t,n),this.emit({type:`COMMIT_EDIT`,row:e,col:t,value:n}),this.editState=null,this.emit({type:`STOP_EDIT`}),this.options.onCommit?.(e,t,n)}cancel(){this.editState=null,this.emit({type:`STOP_EDIT`})}},i=class{core;deps;isDraggingSelection=!1;isDraggingFill=!1;fillSourceRange=null;fillTarget=null;constructor(e,t){this.core=e,this.deps=t}updateDeps(e){this.deps={...this.deps,...e}}getDragState(){return{isDragging:this.isDraggingSelection||this.isDraggingFill,dragType:this.isDraggingFill?`fill`:this.isDraggingSelection?`selection`:null,fillSourceRange:this.fillSourceRange,fillTarget:this.fillTarget}}handleCellMouseDown(e,t,n){return n.button!==0||this.core.getEditState()!==null?{preventDefault:!1,stopPropagation:!1}:(this.core.selection.startSelection({row:e,col:t},{shift:n.shiftKey,ctrl:n.ctrlKey||n.metaKey}),{preventDefault:!1,stopPropagation:!1,focusContainer:!0,startDrag:n.shiftKey?void 0:`selection`})}handleCellDoubleClick(e,t){this.core.startEdit(e,t)}handleFillHandleMouseDown(e,t,n){if(!e&&!t)return{preventDefault:!1,stopPropagation:!1};let r=t??{startRow:e.row,startCol:e.col,endRow:e.row,endCol:e.col};return this.core.fill.startFillDrag(r),this.fillSourceRange=r,this.fillTarget={row:Math.max(r.startRow,r.endRow),col:Math.max(r.startCol,r.endCol)},this.isDraggingFill=!0,{preventDefault:!0,stopPropagation:!0,startDrag:`fill`}}handleHeaderClick(e,t){let n=this.core.getSortModel().find(t=>t.colId===e)?.direction,r=n==null?`asc`:n===`asc`?`desc`:null;this.core.setSort(e,r,t)}startSelectionDrag(){this.isDraggingSelection=!0}handleDragMove(e,t){if(!this.isDraggingSelection&&!this.isDraggingFill)return null;let{top:n,left:r,width:i,height:a,scrollTop:o,scrollLeft:s}=t,c=this.deps.getHeaderHeight(),l=this.deps.getColumnPositions(),u=this.deps.getColumnCount(),d=e.clientX-r+s,f=e.clientY-n-c,p=Math.max(0,Math.min(this.core.getRowIndexAtDisplayY(f,o),this.core.getRowCount()-1)),m=Math.max(0,Math.min(this.findColumnAtX(d,l),u-1));this.isDraggingSelection&&this.core.selection.startSelection({row:p,col:m},{shift:!0}),this.isDraggingFill&&(this.core.fill.updateFillDrag(p,m),this.fillTarget={row:p,col:m});let h=e.clientY-n,g=e.clientX-r;return{targetRow:p,targetCol:m,autoScroll:this.calculateAutoScroll(h,g,a,i,c)}}handleDragEnd(){this.isDraggingFill&&(this.core.fill.commitFillDrag(),this.core.refreshSlotData()),this.isDraggingSelection=!1,this.isDraggingFill=!1,this.fillSourceRange=null,this.fillTarget=null}handleWheel(e,t,n){return this.core.isScalingActive()?{dy:e*n,dx:t*n}:null}handleKeyDown(e,t,n,r){if(r||n&&e.key!==`Enter`&&e.key!==`Escape`&&e.key!==`Tab`)return{preventDefault:!1};let{selection:i}=this.core,a=e.shiftKey,o=e.ctrlKey||e.metaKey,s=(e=>{switch(e){case`ArrowUp`:return`up`;case`ArrowDown`:return`down`;case`ArrowLeft`:return`left`;case`ArrowRight`:return`right`;default:return null}})(e.key);if(s)return i.moveFocus(s,a),{preventDefault:!0,scrollToCell:i.getActiveCell()??void 0};switch(e.key){case`Enter`:return n?this.core.commitEdit():t&&this.core.startEdit(t.row,t.col),{preventDefault:!0};case`Escape`:return n?this.core.cancelEdit():i.clearSelection(),{preventDefault:!0};case`Tab`:return n&&this.core.commitEdit(),i.moveFocus(a?`left`:`right`,!1),{preventDefault:!0};case`a`:if(o)return i.selectAll(),{preventDefault:!0};break;case`c`:if(o)return i.copySelectionToClipboard(),{preventDefault:!0};break;case`F2`:return t&&!n&&this.core.startEdit(t.row,t.col),{preventDefault:!0};case`Delete`:case`Backspace`:if(t&&!n)return this.core.startEdit(t.row,t.col),{preventDefault:!0};break;default:t&&!n&&!o&&e.key.length===1&&this.core.startEdit(t.row,t.col);break}return{preventDefault:!1}}findColumnAtX(e,t){for(let n=0;n<t.length-1;n++)if(e>=t[n]&&e<t[n+1])return n;return e>=t[t.length-1]?t.length-2:0}calculateAutoScroll(e,t,n,r,i){let a=0,o=0;return e<40+i?o=-10:e>n-40&&(o=10),t<40?a=-10:t>r-40&&(a=10),a!==0||o!==0?{dx:a,dy:o}:null}};const a=1e7;var o=class{columns;dataSource;rowHeight;headerHeight;overscan;sortingEnabled;scrollTop=0;scrollLeft=0;viewportWidth=800;viewportHeight=600;cachedRows=new Map;totalRows=0;currentPageIndex=0;pageSize=1e6;sortModel=[];filterModel={};openFilterColIndex=null;selection;fill;input;slotPool;editManager;columnPositions=[];listeners=[];batchListeners=[];naturalContentHeight=0;virtualContentHeight=0;scrollRatio=1;constructor(a){this.columns=a.columns,this.dataSource=a.dataSource,this.rowHeight=a.rowHeight,this.headerHeight=a.headerHeight??a.rowHeight,this.overscan=a.overscan??3,this.sortingEnabled=a.sortingEnabled??!0,this.computeColumnPositions(),this.selection=new e({getRowCount:()=>this.totalRows,getColumnCount:()=>this.columns.length,getCellValue:(e,t)=>this.getCellValue(e,t),getRowData:e=>this.cachedRows.get(e),getColumn:e=>this.columns[e]}),this.selection.onInstruction(e=>this.emit(e)),this.fill=new t({getRowCount:()=>this.totalRows,getColumnCount:()=>this.columns.length,getCellValue:(e,t)=>this.getCellValue(e,t),getColumn:e=>this.columns[e],setCellValue:(e,t,n)=>this.setCellValue(e,t,n)}),this.fill.onInstruction(e=>this.emit(e)),this.slotPool=new n({getRowHeight:()=>this.rowHeight,getHeaderHeight:()=>this.headerHeight,getOverscan:()=>this.overscan,getScrollTop:()=>this.scrollTop,getViewportHeight:()=>this.viewportHeight,getTotalRows:()=>this.totalRows,getScrollRatio:()=>this.scrollRatio,getVirtualContentHeight:()=>this.virtualContentHeight,getRowData:e=>this.cachedRows.get(e)}),this.slotPool.onBatchInstruction(e=>this.emitBatch(e)),this.editManager=new r({getColumn:e=>this.columns[e],getCellValue:(e,t)=>this.getCellValue(e,t),setCellValue:(e,t,n)=>this.setCellValue(e,t,n),onCommit:e=>{this.slotPool.updateSlot(e)}}),this.editManager.onInstruction(e=>this.emit(e)),this.input=new i(this,{getHeaderHeight:()=>this.headerHeight,getRowHeight:()=>this.rowHeight,getColumnPositions:()=>this.columnPositions,getColumnCount:()=>this.columns.length})}onInstruction(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e)}}onBatchInstruction(e){return this.batchListeners.push(e),()=>{this.batchListeners=this.batchListeners.filter(t=>t!==e)}}emit(e){for(let t of this.listeners)t(e);for(let t of this.batchListeners)t([e])}emitBatch(e){if(e.length!==0){for(let t of this.batchListeners)t(e);for(let t of e)for(let e of this.listeners)e(t)}}async initialize(){await this.fetchData(),this.slotPool.syncSlots(),this.emitContentSize(),this.emitHeaders()}setViewport(e,t,n,r){let i=this.scrollRatio<1?e/this.scrollRatio:e,a=this.viewportWidth!==n||this.viewportHeight!==r;if(!(this.scrollTop!==i||this.scrollLeft!==t||a))return;this.scrollTop=i,this.scrollLeft=t,this.viewportWidth=n,this.viewportHeight=r,this.slotPool.syncSlots();let o=this.getVisibleRowRange();this.emit({type:`UPDATE_VISIBLE_RANGE`,start:o.start,end:o.end}),a&&this.emitContentSize()}async fetchData(){this.emit({type:`DATA_LOADING`});try{let e={pagination:{pageIndex:this.currentPageIndex,pageSize:this.pageSize},sort:this.sortModel.length>0?this.sortModel:void 0,filter:Object.keys(this.filterModel).length>0?this.filterModel:void 0},t=await this.dataSource.fetch(e);this.cachedRows.clear(),t.rows.forEach((e,t)=>{this.cachedRows.set(this.currentPageIndex*this.pageSize+t,e)}),this.totalRows=t.totalRows,t.totalRows>t.rows.length&&this.currentPageIndex===0&&await this.fetchAllData(),this.emit({type:`DATA_LOADED`,totalRows:this.totalRows})}catch(e){this.emit({type:`DATA_ERROR`,error:e instanceof Error?e.message:String(e)})}}async fetchAllData(){let e=Math.ceil(this.totalRows/this.pageSize);for(let t=1;t<e;t++){let e={pagination:{pageIndex:t,pageSize:this.pageSize},sort:this.sortModel.length>0?this.sortModel:void 0,filter:Object.keys(this.filterModel).length>0?this.filterModel:void 0};(await this.dataSource.fetch(e)).rows.forEach((e,n)=>{this.cachedRows.set(t*this.pageSize+n,e)})}}async setSort(e,t,n=!1){if(!this.sortingEnabled||this.columns.find(t=>(t.colId??t.field)===e)?.sortable===!1)return;let r=this.sortModel.findIndex(t=>t.colId===e);n?t===null?r>=0&&this.sortModel.splice(r,1):r>=0?this.sortModel[r].direction=t:this.sortModel.push({colId:e,direction:t}):this.sortModel=t===null?[]:[{colId:e,direction:t}],await this.fetchData(),this.slotPool.refreshAllSlots(),this.emitHeaders()}async setFilter(e,t){this.columns.find(t=>(t.colId??t.field)===e)?.filterable!==!1&&(t===null||typeof t==`string`&&t.trim()===``||typeof t==`object`&&t.conditions&&t.conditions.length===0?delete this.filterModel[e]:typeof t==`string`?this.filterModel[e]={conditions:[{type:`text`,operator:`contains`,value:t}],combination:`and`}:this.filterModel[e]=t,await this.fetchData(),this.slotPool.refreshAllSlots(),this.emitContentSize(),this.emitHeaders())}hasActiveFilter(e){let t=this.filterModel[e];return t?t.conditions.length>0:!1}isColumnSortable(e){return this.sortingEnabled?this.columns[e]?.sortable!==!1:!1}isColumnFilterable(e){return this.columns[e]?.filterable!==!1}getDistinctValuesForColumn(e,t=500){let n=this.columns.find(t=>(t.colId??t.field)===e);if(!n)return[];let r=new Map;for(let e of this.cachedRows.values()){let i=this.getFieldValue(e,n.field);if(Array.isArray(i)){let e=[...i].sort((e,t)=>String(e).localeCompare(String(t),void 0,{numeric:!0,sensitivity:`base`})),n=JSON.stringify(e);if(!r.has(n)&&(r.set(n,e),r.size>=t))break}else{let e=JSON.stringify(i);if(!r.has(e)&&(r.set(e,i),r.size>=t))break}}let i=Array.from(r.values());return i.sort((e,t)=>{let n=Array.isArray(e)?e.join(`, `):String(e??``),r=Array.isArray(t)?t.join(`, `):String(t??``);return n.localeCompare(r,void 0,{numeric:!0,sensitivity:`base`})}),i}openFilterPopup(e,t){if(this.openFilterColIndex===e){this.closeFilterPopup();return}let n=this.columns[e];if(!n||!this.isColumnFilterable(e))return;let r=n.colId??n.field,i=this.getDistinctValuesForColumn(r);this.openFilterColIndex=e,this.emit({type:`OPEN_FILTER_POPUP`,colIndex:e,column:n,anchorRect:t,distinctValues:i,currentFilter:this.filterModel[r]})}closeFilterPopup(){this.openFilterColIndex=null,this.emit({type:`CLOSE_FILTER_POPUP`})}getSortModel(){return[...this.sortModel]}getFilterModel(){return{...this.filterModel}}startEdit(e,t){this.editManager.startEdit(e,t)}updateEditValue(e){this.editManager.updateValue(e)}commitEdit(){this.editManager.commit()}cancelEdit(){this.editManager.cancel()}getEditState(){return this.editManager.getState()}getCellValue(e,t){let n=this.cachedRows.get(e);if(!n)return null;let r=this.columns[t];return r?this.getFieldValue(n,r.field):null}setCellValue(e,t,n){let r=this.cachedRows.get(e);if(!r||typeof r!=`object`)return;let i=this.columns[t];i&&this.setFieldValue(r,i.field,n)}getFieldValue(e,t){let n=t.split(`.`),r=e;for(let e of n){if(typeof r!=`object`||!r)return null;r=r[e]}return r??null}setFieldValue(e,t,n){let r=t.split(`.`),i=e;for(let e=0;e<r.length-1;e++){let t=r[e];t in i||(i[t]={}),i=i[t]}let a=r[r.length-1];i[a]=n}computeColumnPositions(){this.columnPositions=[0];let e=0;for(let t of this.columns)e+=t.width,this.columnPositions.push(e)}emitContentSize(){let e=this.columnPositions[this.columnPositions.length-1]??0;this.naturalContentHeight=this.totalRows*this.rowHeight+this.headerHeight,this.naturalContentHeight>a?(this.virtualContentHeight=a,this.scrollRatio=a/this.naturalContentHeight):(this.virtualContentHeight=this.naturalContentHeight,this.scrollRatio=1),this.emit({type:`SET_CONTENT_SIZE`,width:e,height:this.virtualContentHeight,viewportWidth:this.viewportWidth})}emitHeaders(){let e=new Map;this.sortModel.forEach((t,n)=>{e.set(t.colId,{direction:t.direction,index:n+1})});for(let t=0;t<this.columns.length;t++){let n=this.columns[t],r=n.colId??n.field,i=e.get(r);this.emit({type:`UPDATE_HEADER`,colIndex:t,column:n,sortDirection:i?.direction,sortIndex:i?.index,sortable:this.isColumnSortable(t),filterable:this.isColumnFilterable(t),hasFilter:this.hasActiveFilter(r)})}}getColumns(){return this.columns}getColumnPositions(){return[...this.columnPositions]}getRowCount(){return this.totalRows}getRowHeight(){return this.rowHeight}getHeaderHeight(){return this.headerHeight}getTotalWidth(){return this.columnPositions[this.columnPositions.length-1]??0}getTotalHeight(){return this.virtualContentHeight||this.totalRows*this.rowHeight+this.headerHeight}isScalingActive(){return this.scrollRatio<1}getNaturalHeight(){return this.naturalContentHeight||this.totalRows*this.rowHeight+this.headerHeight}getScrollRatio(){return this.scrollRatio}getVisibleRowRange(){let e=this.viewportHeight-this.headerHeight,t=Math.max(0,Math.floor(this.scrollTop/this.rowHeight)),n=Math.min(this.totalRows-1,Math.ceil((this.scrollTop+e)/this.rowHeight)-1);return{start:t,end:Math.max(t,n)}}getScrollTopForRow(e){return e*this.rowHeight*this.scrollRatio}getRowIndexAtDisplayY(e,t){let n=e+(this.scrollRatio<1?t/this.scrollRatio:t);return Math.floor(n/this.rowHeight)}getRowData(e){return this.cachedRows.get(e)}async refresh(){await this.fetchData(),this.slotPool.refreshAllSlots(),this.emitContentSize();let e=this.getVisibleRowRange();this.emit({type:`UPDATE_VISIBLE_RANGE`,start:e.start,end:e.end})}refreshSlotData(){this.slotPool.refreshAllSlots()}async setDataSource(e){this.dataSource=e,await this.refresh()}setColumns(e){this.columns=e,this.computeColumnPositions(),this.emitContentSize(),this.emitHeaders(),this.slotPool.syncSlots()}};function s(e,t){let n=t.split(`.`),r=e;for(let e of n){if(typeof r!=`object`||!r)return null;r=r[e]}return r??null}function c(e,t){if(e==null&&t==null)return 0;if(e==null)return 1;if(t==null)return-1;let n=Number(e),r=Number(t);return!isNaN(n)&&!isNaN(r)?n-r:e instanceof Date&&t instanceof Date?e.getTime()-t.getTime():String(e).localeCompare(String(t))}function l(e,t){return[...e].sort((e,n)=>{for(let{colId:r,direction:i}of t){let t=c(s(e,r),s(n,r));if(t!==0)return i===`asc`?t:-t}return 0})}typeof self<`u`&&self.onmessage!==void 0&&(self.onmessage=e=>{let{type:t,id:n,data:r,sortModel:i}=e.data;if(t===`sort`)try{let e=l(r,i);self.postMessage({type:`sorted`,id:n,data:e})}catch(e){self.postMessage({type:`error`,id:n,error:String(e)})}});var u=class{worker=null;workerUrl=null;pendingRequests=new Map;nextRequestId=0;isTerminated=!1;async sortInWorker(e,t){if(this.isTerminated)throw Error(`SortWorkerManager has been terminated`);this.worker||this.initializeWorker();let n=this.nextRequestId++;return new Promise((r,i)=>{this.pendingRequests.set(n,{resolve:r,reject:i});let a={type:`sort`,id:n,data:e,sortModel:t};this.worker.postMessage(a)})}async sortIndices(e,t){if(this.isTerminated)throw Error(`SortWorkerManager has been terminated`);this.worker||this.initializeWorker();let n=this.nextRequestId++,r=new Float64Array(e);return new Promise((e,i)=>{this.pendingRequests.set(n,{resolve:e,reject:i});let a={type:`sortIndices`,id:n,values:r,direction:t};this.worker.postMessage(a,[r.buffer])})}async sortMultiColumn(e,t){if(this.isTerminated)throw Error(`SortWorkerManager has been terminated`);this.worker||this.initializeWorker();let n=this.nextRequestId++,r=e.map(e=>new Float64Array(e)),i=new Int8Array(t.map(e=>e===`asc`?1:-1));return new Promise((e,t)=>{this.pendingRequests.set(n,{resolve:e,reject:t});let a={type:`sortMultiColumn`,id:n,columns:r,directions:i},o=r.map(e=>e.buffer);o.push(i.buffer),this.worker.postMessage(a,o)})}async sortStringHashes(e,t,n){if(this.isTerminated)throw Error(`SortWorkerManager has been terminated`);this.worker||this.initializeWorker();let r=this.nextRequestId++;return new Promise((i,a)=>{this.pendingRequests.set(r,{resolve:e=>{let{indices:r,collisionRuns:a}=e;a.length>0&&this.resolveCollisions(r,a,n,t),i(r)},reject:a});let o={type:`sortStringHashes`,id:r,hashChunks:e,direction:t},s=e.map(e=>e.buffer);this.worker.postMessage(o,s)})}resolveCollisions(e,t,n,r){let i=r===`asc`?1:-1;for(let r=0;r<t.length;r+=2){let a=t[r],o=t[r+1],s=Array.from(e.slice(a,o)),c=n[s[0]],l=!0;for(let e=1;e<s.length;e++)if(n[s[e]]!==c){l=!1;break}if(!l){s.sort((e,t)=>i*n[e].localeCompare(n[t]));for(let t=0;t<s.length;t++)e[a+t]=s[t]}}}initializeWorker(){if(typeof Worker>`u`)throw Error(`Web Workers are not available in this environment`);let e=new Blob([`
3
3
  // Inline sort worker code
4
4
  function getFieldValue(row, field) {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "gp-grid-core",
3
3
  "description": "A high-performance, framework-agnostic TypeScript data grid core with virtual scrolling",
4
4
  "private": false,
5
- "version": "0.3.0",
5
+ "version": "0.4.0",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",