@beeblock/svelar-datatable 0.1.1 → 0.1.3

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.
@@ -1,13 +1,16 @@
1
+ import { Plugin } from '@beeblock/svelar/plugins';
1
2
  import type { DataTableConfig } from './types.js';
2
3
  interface DatatablePluginConfig {
3
4
  prefix?: string;
4
5
  defaults?: Partial<DataTableConfig>;
5
6
  }
6
- export declare class SvelarDatatablePlugin {
7
+ export declare class SvelarDatatablePlugin extends Plugin {
8
+ readonly name = "svelar-datatable";
9
+ readonly version = "0.1.2";
10
+ readonly description = "Full-featured DataTable plugin for Svelar \u2014 sorting, searching, pagination, inline editing, export, and server-side processing";
7
11
  private _config;
8
12
  constructor(config?: DatatablePluginConfig);
9
- get name(): string;
10
- get config(): DatatablePluginConfig;
13
+ get datatableConfig(): DatatablePluginConfig;
11
14
  static defaults(): Partial<DataTableConfig>;
12
15
  publishables(): {
13
16
  routes: {
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { SvelarDatatablePlugin } from './SvelarDatatablePlugin.js';
2
+ export default SvelarDatatablePlugin;
1
3
  export { SvelarDatatablePlugin } from './SvelarDatatablePlugin.js';
2
4
  export { DataTableStore } from './state/DataTableStore.js';
3
5
  export { ServerDataTableStore } from './state/ServerDataTableStore.js';
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import{fileURLToPath as I}from"url";import{dirname as P,join as V}from"path";var y={prefix:"/api",defaults:{perPage:15,perPageOptions:[10,15,25,50,100],searchDebounceMs:300,sortable:!0,searchable:!0,paginate:!0,selectable:"none",striped:!0,hover:!0,bordered:!1,compact:!1,responsive:!0,virtualScroll:!1,virtualRowHeight:48}},S=class{_config;constructor(t={}){this._config={...y,...t,defaults:{...y.defaults,...t.defaults}}}get name(){return"svelar-datatable"}get config(){return this._config}static defaults(){return{...y.defaults}}publishables(){let t=P(I(import.meta.url));return{routes:[{source:V(t,"publishable/routes/datatable.ts"),dest:"src/routes/api/datatable/+server.ts",type:"asset"}]}}};var m=class{_state;_listeners=new Set;_columns=[];_rowIdFn;_stateSaveKey=null;_lastSelectedId=null;_paginate=!0;constructor(t){this._columns=t.columns,this._stateSaveKey=t.stateSaveKey??null,this._paginate=t.paginate!==!1,this._rowIdFn=typeof t.rowId=="function"?t.rowId:s=>s[t.rowId??"id"];let e=this._loadState();this._state={allRows:t.data??[],filteredRows:[],sortedRows:[],paginatedRows:[],sort:e?.sort??[],filters:e?.filters??[],globalSearch:e?.globalSearch??"",pagination:{page:e?.page??1,perPage:t.perPage??15,total:0,lastPage:1},selectedIds:new Set,columnVisibility:e?.columnVisibility??Object.fromEntries(t.columns.map(s=>[s.key,s.visible!==!1])),columnOrder:e?.columnOrder??t.columns.map(s=>s.key),loading:!1,error:null,editingRowId:null,editingColumn:null,editorMode:null,formData:{},validationErrors:{},draw:0,excelFocusedCell:null,excelEditingCell:null,excelEditValue:""},this._recompute()}subscribe(t){return this._listeners.add(t),()=>this._listeners.delete(t)}getState(){return this._state}_notify(){for(let t of this._listeners)t()}_saveState(){if(this._stateSaveKey)try{let t={sort:this._state.sort,filters:this._state.filters,globalSearch:this._state.globalSearch,page:this._state.pagination.page,columnVisibility:this._state.columnVisibility,columnOrder:this._state.columnOrder};localStorage.setItem(this._stateSaveKey,JSON.stringify(t))}catch{}}_loadState(){if(!this._stateSaveKey)return null;try{let t=localStorage.getItem(this._stateSaveKey);return t?JSON.parse(t):null}catch{return null}}setData(t){this._state={...this._state,allRows:t},this._recompute()}setSort(t){this._state={...this._state,sort:t,pagination:{...this._state.pagination,page:1}},this._recompute(),this._saveState()}toggleSort(t,e=!1){let s=this._state.sort.find(i=>i.column===t),a;s?s.direction==="asc"?a=e?this._state.sort.map(i=>i.column===t?{...i,direction:"desc"}:i):[{column:t,direction:"desc"}]:a=e?this._state.sort.filter(i=>i.column!==t):[]:a=e?[...this._state.sort,{column:t,direction:"asc"}]:[{column:t,direction:"asc"}],this.setSort(a)}setGlobalSearch(t){this._state={...this._state,globalSearch:t,pagination:{...this._state.pagination,page:1}},this._recompute(),this._saveState()}setFilters(t){this._state={...this._state,filters:t,pagination:{...this._state.pagination,page:1}},this._recompute(),this._saveState()}setColumnFilter(t,e,s="like"){let a=this._state.filters.filter(i=>i.column!==t);e!==""&&e!==null&&e!==void 0&&a.push({column:t,value:e,operator:s}),this.setFilters(a)}setPage(t){let e=this._state.pagination.lastPage,s=Math.max(1,Math.min(t,e));this._state={...this._state,pagination:{...this._state.pagination,page:s}},this._recompute(),this._saveState()}setPerPage(t){this._state={...this._state,pagination:{...this._state.pagination,perPage:t,page:1}},this._recompute(),this._saveState()}toggleColumnVisibility(t){let e={...this._state.columnVisibility};e[t]=!e[t],this._state={...this._state,columnVisibility:e},this._notify(),this._saveState()}setColumnVisibility(t){this._state={...this._state,columnVisibility:t},this._notify(),this._saveState()}reorderColumns(t){this._state={...this._state,columnOrder:t},this._notify(),this._saveState()}getRowId(t){return this._rowIdFn(t)}toggleSelect(t){let e=new Set(this._state.selectedIds);e.has(t)?e.delete(t):e.add(t),this._lastSelectedId=t,this._state={...this._state,selectedIds:e},this._notify()}getLastSelectedId(){return this._lastSelectedId}selectSingle(t){this._state={...this._state,selectedIds:new Set([t])},this._notify()}selectAll(){let t=this._state.filteredRows.map(e=>this.getRowId(e));this._state={...this._state,selectedIds:new Set(t)},this._notify()}deselectAll(){this._state={...this._state,selectedIds:new Set},this._notify()}selectRange(t,e){let s=this._state.sortedRows,a=s.findIndex(n=>this.getRowId(n)===t),i=s.findIndex(n=>this.getRowId(n)===e);if(a===-1||i===-1)return;let o=Math.min(a,i),u=Math.max(a,i),r=new Set(this._state.selectedIds);for(let n=o;n<=u;n++)r.add(this.getRowId(s[n]));this._state={...this._state,selectedIds:r},this._notify()}getSelectedRows(){return this._state.allRows.filter(t=>this._state.selectedIds.has(this.getRowId(t)))}openEditor(t,e,s){let a=t!==null?this._state.allRows.find(o=>this.getRowId(o)===t):null,i=a?{...a}:{};this._state={...this._state,editingRowId:t,editingColumn:e,editorMode:s,formData:i,validationErrors:{}},this._notify()}closeEditor(){this._state={...this._state,editingRowId:null,editingColumn:null,editorMode:null,formData:{},validationErrors:{}},this._notify()}setFormField(t,e){this._state={...this._state,formData:{...this._state.formData,[t]:e}},this._notify()}setValidationErrors(t){this._state={...this._state,validationErrors:t},this._notify()}setLoading(t){this._state={...this._state,loading:t},this._notify()}setError(t){this._state={...this._state,error:t},this._notify()}setServerResponse(t){this._state={...this._state,allRows:t.data,filteredRows:t.data,sortedRows:t.data,paginatedRows:t.data,loading:!1,draw:t.draw,pagination:{...this._state.pagination,total:t.recordsFiltered,lastPage:Math.ceil(t.recordsFiltered/this._state.pagination.perPage)||1}},this._notify()}resetState(){if(this._state={...this._state,sort:[],filters:[],globalSearch:"",pagination:{...this._state.pagination,page:1},selectedIds:new Set},this._recompute(),this._stateSaveKey)try{localStorage.removeItem(this._stateSaveKey)}catch{}}focusCell(t,e){this._state={...this._state,excelFocusedCell:{rowIndex:t,columnKey:e}},this._notify()}startCellEdit(){let t=this._state.excelFocusedCell;if(!t)return;let e=this._state.paginatedRows[t.rowIndex];if(!e)return;let s=this._columns.find(a=>a.key===t.columnKey);!s||s.editable===!1||(this._state={...this._state,excelEditingCell:{...t},excelEditValue:e[t.columnKey]!=null?String(e[t.columnKey]):""},this._notify())}setExcelEditValue(t){this._state={...this._state,excelEditValue:t}}commitCellEdit(){let t=this._state.excelEditingCell;if(!t)return null;let e=this._state.paginatedRows[t.rowIndex];if(!e)return this.cancelCellEdit(),null;let s=this._columns.find(o=>o.key===t.columnKey),a=e[t.columnKey],i=this._state.excelEditValue;return s?.type==="number"?i=i===""?null:Number(i):s?.type==="boolean"?i=i==="true"||i==="1":i===""&&(i=null),this._state={...this._state,excelEditingCell:null,excelEditValue:""},i===a||i===null&&a==null?(this._notify(),null):(e[t.columnKey]=i,this._notify(),{row:e,columnKey:t.columnKey,oldValue:a,newValue:i})}cancelCellEdit(){this._state={...this._state,excelEditingCell:null,excelEditValue:""},this._notify()}clearExcelFocus(){this._state={...this._state,excelFocusedCell:null,excelEditingCell:null,excelEditValue:""},this._notify()}getVisibleColumns(){return this._state.columnOrder.filter(t=>this._state.columnVisibility[t]!==!1).map(t=>this._columns.find(e=>e.key===t)).filter(Boolean)}navigateCell(t){let e=this._state.excelFocusedCell,s=this._state.paginatedRows,a=this.getVisibleColumns();if(a.length===0)return null;if(!e){let r=a.find(n=>n.editable!==!1);return r&&s.length>0&&this.focusCell(0,r.key),null}let{rowIndex:i,columnKey:o}=e,u=a.findIndex(r=>r.key===o);if(u===-1)return null;switch(t){case"left":{for(let r=u-1;r>=0;r--)if(a[r].editable!==!1)return this.focusCell(i,a[r].key),null;for(let r=a.length-1;r>=0;r--)if(a[r].editable!==!1)return i>0?(this.focusCell(i-1,a[r].key),null):"page-prev";return null}case"right":{for(let r=u+1;r<a.length;r++)if(a[r].editable!==!1)return this.focusCell(i,a[r].key),null;for(let r=0;r<a.length;r++)if(a[r].editable!==!1)return i<s.length-1?(this.focusCell(i+1,a[r].key),null):"page-next";return null}case"up":return i>0?(this.focusCell(i-1,o),null):"page-prev";case"down":return i<s.length-1?(this.focusCell(i+1,o),null):"page-next"}}_recompute(){let t=[...this._state.allRows];if(this._state.globalSearch){let n=this._state.globalSearch.toLowerCase(),d=this._columns.filter(l=>l.searchable!==!1);t=t.filter(l=>d.some(p=>{let h=l[p.key];return h!=null&&String(h).toLowerCase().includes(n)}))}for(let n of this._state.filters)t=t.filter(d=>{let l=d[n.column];switch(n.operator){case"=":return l==n.value;case"!=":return l!=n.value;case">":return l>n.value;case"<":return l<n.value;case">=":return l>=n.value;case"<=":return l<=n.value;case"like":return l!=null&&String(l).toLowerCase().includes(String(n.value).toLowerCase());case"not_like":return l==null||!String(l).toLowerCase().includes(String(n.value).toLowerCase());case"in":return Array.isArray(n.value)&&n.value.includes(l);case"between":return Array.isArray(n.value)&&l>=n.value[0]&&l<=n.value[1];case"null":return l==null;case"not_null":return l!=null;default:return!0}});let e=t;this._state.sort.length>0&&(t=[...t].sort((n,d)=>{for(let l of this._state.sort){let p=this._columns.find(k=>k.key===l.column),h=n[l.column],g=d[l.column],f=0;if(h==null?f=-1:g==null?f=1:p?.type==="number"?f=Number(h)-Number(g):p?.type==="date"?f=new Date(h).getTime()-new Date(g).getTime():p?.type==="boolean"?f=(h?1:0)-(g?1:0):f=String(h).localeCompare(String(g)),f!==0)return l.direction==="desc"?-f:f}return 0}));let s=t,a=e.length,i=this._state.pagination.perPage,o,u,r;if(this._paginate){r=Math.ceil(a/i)||1,u=Math.min(this._state.pagination.page,r);let n=(u-1)*i;o=s.slice(n,n+i)}else o=s,u=1,r=1;this._state={...this._state,filteredRows:e,sortedRows:s,paginatedRows:o,pagination:{page:u,perPage:i,total:a,lastPage:r}},this._notify()}};function j(c="XSRF-TOKEN"){if(typeof document>"u")return null;let t=c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),e=document.cookie.match(new RegExp(`(?:^|;\\s*)${t}=([^;]*)`));return e?decodeURIComponent(e[1]):null}var v=class extends m{_serverUrl;_serverMethod;_drawCounter=0;_abortController=null;_fetchDebounceTimer=null;_serverColumns;_csrfCookieName;_csrfHeaderName;constructor(t){super(t),this._serverUrl=t.serverUrl,this._serverMethod=t.serverMethod??"GET",this._csrfCookieName=t.csrfCookieName??"XSRF-TOKEN",this._csrfHeaderName=t.csrfHeaderName??"X-CSRF-Token",this._serverColumns=t.columns.map(e=>({data:e.key,name:e.key,searchable:e.searchable!==!1,orderable:e.sortable!==!1}))}_buildHeaders(t={}){let e={...t},s=j(this._csrfCookieName);return s&&(e[this._csrfHeaderName]=s),e}setSort(t){let e=this.getState();this._state={...e,sort:t,pagination:{...e.pagination,page:1}},this._debouncedFetch()}setGlobalSearch(t){let e=this.getState();this._state={...e,globalSearch:t,pagination:{...e.pagination,page:1}},this._debouncedFetch()}setFilters(t){let e=this.getState();this._state={...e,filters:t,pagination:{...e.pagination,page:1}},this._debouncedFetch()}setPage(t){let e=this.getState();this._state={...e,pagination:{...e.pagination,page:t}},this._fetchFromServer()}setPerPage(t){let e=this.getState();this._state={...e,pagination:{...e.pagination,perPage:t,page:1}},this._fetchFromServer()}_debouncedFetch(){this._fetchDebounceTimer&&clearTimeout(this._fetchDebounceTimer),this._fetchDebounceTimer=setTimeout(()=>this._fetchFromServer(),300)}async _fetchFromServer(){this._abortController&&this._abortController.abort(),this._abortController=new AbortController;let t=this.getState();this.setLoading(!0),this.setError(null);let e=++this._drawCounter,s={draw:e,start:(t.pagination.page-1)*t.pagination.perPage,length:t.pagination.perPage,search:{value:t.globalSearch,regex:!1},order:t.sort.map(a=>({column:this._serverColumns.findIndex(i=>i.data===a.column),dir:a.direction})),columns:this._serverColumns.map(a=>({...a,search:{value:t.filters.find(i=>i.column===a.data)?.value??"",regex:!1}}))};try{let a;if(this._serverMethod==="POST")a=await fetch(this._serverUrl,{method:"POST",headers:this._buildHeaders({"Content-Type":"application/json"}),body:JSON.stringify(s),signal:this._abortController.signal});else{let o=new URLSearchParams;o.set("draw",String(s.draw)),o.set("start",String(s.start)),o.set("length",String(s.length)),o.set("search[value]",s.search.value),o.set("search[regex]",String(s.search.regex)),s.order.forEach((r,n)=>{o.set(`order[${n}][column]`,String(r.column)),o.set(`order[${n}][dir]`,r.dir)}),s.columns.forEach((r,n)=>{o.set(`columns[${n}][data]`,r.data),o.set(`columns[${n}][name]`,r.name),o.set(`columns[${n}][searchable]`,String(r.searchable)),o.set(`columns[${n}][orderable]`,String(r.orderable)),o.set(`columns[${n}][search][value]`,r.search.value),o.set(`columns[${n}][search][regex]`,String(r.search.regex))});let u=`${this._serverUrl}?${o.toString()}`;a=await fetch(u,{signal:this._abortController.signal})}if(!a.ok)throw new Error(`Server responded with ${a.status}`);let i=await a.json();i.draw===e&&this.setServerResponse(i)}catch(a){if(a.name==="AbortError")return;this.setLoading(!1),this.setError(a.message??"Failed to fetch data")}}async initialFetch(){await this._fetchFromServer()}destroy(){this._abortController&&this._abortController.abort(),this._fetchDebounceTimer&&clearTimeout(this._fetchDebounceTimer)}};function x(c){if(c==null)return"";let t=String(c);return t.includes(",")||t.includes('"')||t.includes(`
2
- `)||t.includes("\r")?'"'+t.replace(/"/g,'""')+'"':t}function T(c,t){let e=t.filter(i=>i.visible!==!1),s=e.map(i=>x(i.header)).join(","),a=c.map(i=>e.map(o=>x(i[o.key])).join(","));return"\uFEFF"+[s,...a].join(`\r
3
- `)}function D(c,t="export.csv"){let e=new Blob([c],{type:"text/csv;charset=utf-8;"});w(e,t)}function w(c,t){let e=URL.createObjectURL(c),s=document.createElement("a");s.href=e,s.download=t,document.body.appendChild(s),s.click(),document.body.removeChild(s),URL.revokeObjectURL(e)}async function R(c,t){let e=t.filter(o=>o.visible!==!1),s=e.map(o=>o.header).join(" "),a=c.map(o=>e.map(u=>{let r=o[u.key];return r==null?"":String(r)}).join(" ")),i=[s,...a].join(`
4
- `);await navigator.clipboard.writeText(i)}function b(c,t,e){let s=t.filter(r=>r.visible!==!1),a=s.map(r=>`<th style="border:1px solid #ddd;padding:8px 12px;text-align:left;background:#f5f5f5;font-weight:600;">${_(r.header)}</th>`).join(""),i=c.map(r=>`<tr>${s.map(d=>{let l=r[d.key];return`<td style="border:1px solid #ddd;padding:8px 12px;">${_(l==null?"":String(l))}</td>`}).join("")}</tr>`).join(""),o=`<!DOCTYPE html>
1
+ import{Plugin as V}from"@beeblock/svelar/plugins";import{fileURLToPath as j}from"url";import{dirname as x,join as T}from"path";var $=x(j(import.meta.url)),K=x($),L=T(K,"src","publishable"),S={prefix:"/api",defaults:{perPage:15,perPageOptions:[10,15,25,50,100],searchDebounceMs:300,sortable:!0,searchable:!0,paginate:!0,selectable:"none",striped:!0,hover:!0,bordered:!1,compact:!1,responsive:!0,virtualScroll:!1,virtualRowHeight:48}},m=class extends V{name="svelar-datatable";version="0.1.2";description="Full-featured DataTable plugin for Svelar \u2014 sorting, searching, pagination, inline editing, export, and server-side processing";_config;constructor(t={}){super(),this._config={...S,...t,defaults:{...S.defaults,...t.defaults}}}get datatableConfig(){return this._config}static defaults(){return{...S.defaults}}publishables(){return{routes:[{source:T(L,"routes/datatable.ts"),dest:"src/routes/api/datatable/+server.ts",type:"asset"}]}}};var _=class{_state;_listeners=new Set;_columns=[];_rowIdFn;_stateSaveKey=null;_lastSelectedId=null;_paginate=!0;constructor(t){this._columns=t.columns,this._stateSaveKey=t.stateSaveKey??null,this._paginate=t.paginate!==!1,this._rowIdFn=typeof t.rowId=="function"?t.rowId:s=>s[t.rowId??"id"];let e=this._loadState();this._state={allRows:t.data??[],filteredRows:[],sortedRows:[],paginatedRows:[],sort:e?.sort??[],filters:e?.filters??[],globalSearch:e?.globalSearch??"",pagination:{page:e?.page??1,perPage:t.perPage??15,total:0,lastPage:1},selectedIds:new Set,columnVisibility:e?.columnVisibility??Object.fromEntries(t.columns.map(s=>[s.key,s.visible!==!1])),columnOrder:e?.columnOrder??t.columns.map(s=>s.key),loading:!1,error:null,editingRowId:null,editingColumn:null,editorMode:null,formData:{},validationErrors:{},draw:0,excelFocusedCell:null,excelEditingCell:null,excelEditValue:""},this._recompute()}subscribe(t){return this._listeners.add(t),()=>this._listeners.delete(t)}getState(){return this._state}_notify(){for(let t of this._listeners)t()}_saveState(){if(this._stateSaveKey)try{let t={sort:this._state.sort,filters:this._state.filters,globalSearch:this._state.globalSearch,page:this._state.pagination.page,columnVisibility:this._state.columnVisibility,columnOrder:this._state.columnOrder};localStorage.setItem(this._stateSaveKey,JSON.stringify(t))}catch{}}_loadState(){if(!this._stateSaveKey)return null;try{let t=localStorage.getItem(this._stateSaveKey);return t?JSON.parse(t):null}catch{return null}}setData(t){this._state={...this._state,allRows:t},this._recompute()}setSort(t){this._state={...this._state,sort:t,pagination:{...this._state.pagination,page:1}},this._recompute(),this._saveState()}toggleSort(t,e=!1){let s=this._state.sort.find(i=>i.column===t),a;s?s.direction==="asc"?a=e?this._state.sort.map(i=>i.column===t?{...i,direction:"desc"}:i):[{column:t,direction:"desc"}]:a=e?this._state.sort.filter(i=>i.column!==t):[]:a=e?[...this._state.sort,{column:t,direction:"asc"}]:[{column:t,direction:"asc"}],this.setSort(a)}setGlobalSearch(t){this._state={...this._state,globalSearch:t,pagination:{...this._state.pagination,page:1}},this._recompute(),this._saveState()}setFilters(t){this._state={...this._state,filters:t,pagination:{...this._state.pagination,page:1}},this._recompute(),this._saveState()}setColumnFilter(t,e,s="like"){let a=this._state.filters.filter(i=>i.column!==t);e!==""&&e!==null&&e!==void 0&&a.push({column:t,value:e,operator:s}),this.setFilters(a)}setPage(t){let e=this._state.pagination.lastPage,s=Math.max(1,Math.min(t,e));this._state={...this._state,pagination:{...this._state.pagination,page:s}},this._recompute(),this._saveState()}setPerPage(t){this._state={...this._state,pagination:{...this._state.pagination,perPage:t,page:1}},this._recompute(),this._saveState()}toggleColumnVisibility(t){let e={...this._state.columnVisibility};e[t]=!e[t],this._state={...this._state,columnVisibility:e},this._notify(),this._saveState()}setColumnVisibility(t){this._state={...this._state,columnVisibility:t},this._notify(),this._saveState()}reorderColumns(t){this._state={...this._state,columnOrder:t},this._notify(),this._saveState()}getRowId(t){return this._rowIdFn(t)}toggleSelect(t){let e=new Set(this._state.selectedIds);e.has(t)?e.delete(t):e.add(t),this._lastSelectedId=t,this._state={...this._state,selectedIds:e},this._notify()}getLastSelectedId(){return this._lastSelectedId}selectSingle(t){this._state={...this._state,selectedIds:new Set([t])},this._notify()}selectAll(){let t=this._state.filteredRows.map(e=>this.getRowId(e));this._state={...this._state,selectedIds:new Set(t)},this._notify()}deselectAll(){this._state={...this._state,selectedIds:new Set},this._notify()}selectRange(t,e){let s=this._state.sortedRows,a=s.findIndex(n=>this.getRowId(n)===t),i=s.findIndex(n=>this.getRowId(n)===e);if(a===-1||i===-1)return;let o=Math.min(a,i),u=Math.max(a,i),r=new Set(this._state.selectedIds);for(let n=o;n<=u;n++)r.add(this.getRowId(s[n]));this._state={...this._state,selectedIds:r},this._notify()}getSelectedRows(){return this._state.allRows.filter(t=>this._state.selectedIds.has(this.getRowId(t)))}openEditor(t,e,s){let a=t!==null?this._state.allRows.find(o=>this.getRowId(o)===t):null,i=a?{...a}:{};this._state={...this._state,editingRowId:t,editingColumn:e,editorMode:s,formData:i,validationErrors:{}},this._notify()}closeEditor(){this._state={...this._state,editingRowId:null,editingColumn:null,editorMode:null,formData:{},validationErrors:{}},this._notify()}setFormField(t,e){this._state={...this._state,formData:{...this._state.formData,[t]:e}},this._notify()}setValidationErrors(t){this._state={...this._state,validationErrors:t},this._notify()}setLoading(t){this._state={...this._state,loading:t},this._notify()}setError(t){this._state={...this._state,error:t},this._notify()}setServerResponse(t){this._state={...this._state,allRows:t.data,filteredRows:t.data,sortedRows:t.data,paginatedRows:t.data,loading:!1,draw:t.draw,pagination:{...this._state.pagination,total:t.recordsFiltered,lastPage:Math.ceil(t.recordsFiltered/this._state.pagination.perPage)||1}},this._notify()}resetState(){if(this._state={...this._state,sort:[],filters:[],globalSearch:"",pagination:{...this._state.pagination,page:1},selectedIds:new Set},this._recompute(),this._stateSaveKey)try{localStorage.removeItem(this._stateSaveKey)}catch{}}focusCell(t,e){this._state={...this._state,excelFocusedCell:{rowIndex:t,columnKey:e}},this._notify()}startCellEdit(){let t=this._state.excelFocusedCell;if(!t)return;let e=this._state.paginatedRows[t.rowIndex];if(!e)return;let s=this._columns.find(a=>a.key===t.columnKey);!s||s.editable===!1||(this._state={...this._state,excelEditingCell:{...t},excelEditValue:e[t.columnKey]!=null?String(e[t.columnKey]):""},this._notify())}setExcelEditValue(t){this._state={...this._state,excelEditValue:t}}commitCellEdit(){let t=this._state.excelEditingCell;if(!t)return null;let e=this._state.paginatedRows[t.rowIndex];if(!e)return this.cancelCellEdit(),null;let s=this._columns.find(o=>o.key===t.columnKey),a=e[t.columnKey],i=this._state.excelEditValue;return s?.type==="number"?i=i===""?null:Number(i):s?.type==="boolean"?i=i==="true"||i==="1":i===""&&(i=null),this._state={...this._state,excelEditingCell:null,excelEditValue:""},i===a||i===null&&a==null?(this._notify(),null):(e[t.columnKey]=i,this._notify(),{row:e,columnKey:t.columnKey,oldValue:a,newValue:i})}cancelCellEdit(){this._state={...this._state,excelEditingCell:null,excelEditValue:""},this._notify()}clearExcelFocus(){this._state={...this._state,excelFocusedCell:null,excelEditingCell:null,excelEditValue:""},this._notify()}getVisibleColumns(){return this._state.columnOrder.filter(t=>this._state.columnVisibility[t]!==!1).map(t=>this._columns.find(e=>e.key===t)).filter(Boolean)}navigateCell(t){let e=this._state.excelFocusedCell,s=this._state.paginatedRows,a=this.getVisibleColumns();if(a.length===0)return null;if(!e){let r=a.find(n=>n.editable!==!1);return r&&s.length>0&&this.focusCell(0,r.key),null}let{rowIndex:i,columnKey:o}=e,u=a.findIndex(r=>r.key===o);if(u===-1)return null;switch(t){case"left":{for(let r=u-1;r>=0;r--)if(a[r].editable!==!1)return this.focusCell(i,a[r].key),null;for(let r=a.length-1;r>=0;r--)if(a[r].editable!==!1)return i>0?(this.focusCell(i-1,a[r].key),null):"page-prev";return null}case"right":{for(let r=u+1;r<a.length;r++)if(a[r].editable!==!1)return this.focusCell(i,a[r].key),null;for(let r=0;r<a.length;r++)if(a[r].editable!==!1)return i<s.length-1?(this.focusCell(i+1,a[r].key),null):"page-next";return null}case"up":return i>0?(this.focusCell(i-1,o),null):"page-prev";case"down":return i<s.length-1?(this.focusCell(i+1,o),null):"page-next"}}_recompute(){let t=[...this._state.allRows];if(this._state.globalSearch){let n=this._state.globalSearch.toLowerCase(),d=this._columns.filter(l=>l.searchable!==!1);t=t.filter(l=>d.some(p=>{let h=l[p.key];return h!=null&&String(h).toLowerCase().includes(n)}))}for(let n of this._state.filters)t=t.filter(d=>{let l=d[n.column];switch(n.operator){case"=":return l==n.value;case"!=":return l!=n.value;case">":return l>n.value;case"<":return l<n.value;case">=":return l>=n.value;case"<=":return l<=n.value;case"like":return l!=null&&String(l).toLowerCase().includes(String(n.value).toLowerCase());case"not_like":return l==null||!String(l).toLowerCase().includes(String(n.value).toLowerCase());case"in":return Array.isArray(n.value)&&n.value.includes(l);case"between":return Array.isArray(n.value)&&l>=n.value[0]&&l<=n.value[1];case"null":return l==null;case"not_null":return l!=null;default:return!0}});let e=t;this._state.sort.length>0&&(t=[...t].sort((n,d)=>{for(let l of this._state.sort){let p=this._columns.find(I=>I.key===l.column),h=n[l.column],g=d[l.column],f=0;if(h==null?f=-1:g==null?f=1:p?.type==="number"?f=Number(h)-Number(g):p?.type==="date"?f=new Date(h).getTime()-new Date(g).getTime():p?.type==="boolean"?f=(h?1:0)-(g?1:0):f=String(h).localeCompare(String(g)),f!==0)return l.direction==="desc"?-f:f}return 0}));let s=t,a=e.length,i=this._state.pagination.perPage,o,u,r;if(this._paginate){r=Math.ceil(a/i)||1,u=Math.min(this._state.pagination.page,r);let n=(u-1)*i;o=s.slice(n,n+i)}else o=s,u=1,r=1;this._state={...this._state,filteredRows:e,sortedRows:s,paginatedRows:o,pagination:{page:u,perPage:i,total:a,lastPage:r}},this._notify()}};function O(c="XSRF-TOKEN"){if(typeof document>"u")return null;let t=c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),e=document.cookie.match(new RegExp(`(?:^|;\\s*)${t}=([^;]*)`));return e?decodeURIComponent(e[1]):null}var v=class extends _{_serverUrl;_serverMethod;_drawCounter=0;_abortController=null;_fetchDebounceTimer=null;_serverColumns;_csrfCookieName;_csrfHeaderName;constructor(t){super(t),this._serverUrl=t.serverUrl,this._serverMethod=t.serverMethod??"GET",this._csrfCookieName=t.csrfCookieName??"XSRF-TOKEN",this._csrfHeaderName=t.csrfHeaderName??"X-CSRF-Token",this._serverColumns=t.columns.map(e=>({data:e.key,name:e.key,searchable:e.searchable!==!1,orderable:e.sortable!==!1}))}_buildHeaders(t={}){let e={...t},s=O(this._csrfCookieName);return s&&(e[this._csrfHeaderName]=s),e}setSort(t){let e=this.getState();this._state={...e,sort:t,pagination:{...e.pagination,page:1}},this._debouncedFetch()}setGlobalSearch(t){let e=this.getState();this._state={...e,globalSearch:t,pagination:{...e.pagination,page:1}},this._debouncedFetch()}setFilters(t){let e=this.getState();this._state={...e,filters:t,pagination:{...e.pagination,page:1}},this._debouncedFetch()}setPage(t){let e=this.getState();this._state={...e,pagination:{...e.pagination,page:t}},this._fetchFromServer()}setPerPage(t){let e=this.getState();this._state={...e,pagination:{...e.pagination,perPage:t,page:1}},this._fetchFromServer()}_debouncedFetch(){this._fetchDebounceTimer&&clearTimeout(this._fetchDebounceTimer),this._fetchDebounceTimer=setTimeout(()=>this._fetchFromServer(),300)}async _fetchFromServer(){this._abortController&&this._abortController.abort(),this._abortController=new AbortController;let t=this.getState();this.setLoading(!0),this.setError(null);let e=++this._drawCounter,s={draw:e,start:(t.pagination.page-1)*t.pagination.perPage,length:t.pagination.perPage,search:{value:t.globalSearch,regex:!1},order:t.sort.map(a=>({column:this._serverColumns.findIndex(i=>i.data===a.column),dir:a.direction})),columns:this._serverColumns.map(a=>({...a,search:{value:t.filters.find(i=>i.column===a.data)?.value??"",regex:!1}}))};try{let a;if(this._serverMethod==="POST")a=await fetch(this._serverUrl,{method:"POST",headers:this._buildHeaders({"Content-Type":"application/json"}),body:JSON.stringify(s),signal:this._abortController.signal});else{let o=new URLSearchParams;o.set("draw",String(s.draw)),o.set("start",String(s.start)),o.set("length",String(s.length)),o.set("search[value]",s.search.value),o.set("search[regex]",String(s.search.regex)),s.order.forEach((r,n)=>{o.set(`order[${n}][column]`,String(r.column)),o.set(`order[${n}][dir]`,r.dir)}),s.columns.forEach((r,n)=>{o.set(`columns[${n}][data]`,r.data),o.set(`columns[${n}][name]`,r.name),o.set(`columns[${n}][searchable]`,String(r.searchable)),o.set(`columns[${n}][orderable]`,String(r.orderable)),o.set(`columns[${n}][search][value]`,r.search.value),o.set(`columns[${n}][search][regex]`,String(r.search.regex))});let u=`${this._serverUrl}?${o.toString()}`;a=await fetch(u,{signal:this._abortController.signal})}if(!a.ok)throw new Error(`Server responded with ${a.status}`);let i=await a.json();i.draw===e&&this.setServerResponse(i)}catch(a){if(a.name==="AbortError")return;this.setLoading(!1),this.setError(a.message??"Failed to fetch data")}}async initialFetch(){await this._fetchFromServer()}destroy(){this._abortController&&this._abortController.abort(),this._fetchDebounceTimer&&clearTimeout(this._fetchDebounceTimer)}};function D(c){if(c==null)return"";let t=String(c);return t.includes(",")||t.includes('"')||t.includes(`
2
+ `)||t.includes("\r")?'"'+t.replace(/"/g,'""')+'"':t}function R(c,t){let e=t.filter(i=>i.visible!==!1),s=e.map(i=>D(i.header)).join(","),a=c.map(i=>e.map(o=>D(i[o.key])).join(","));return"\uFEFF"+[s,...a].join(`\r
3
+ `)}function E(c,t="export.csv"){let e=new Blob([c],{type:"text/csv;charset=utf-8;"});w(e,t)}function w(c,t){let e=URL.createObjectURL(c),s=document.createElement("a");s.href=e,s.download=t,document.body.appendChild(s),s.click(),document.body.removeChild(s),URL.revokeObjectURL(e)}async function F(c,t){let e=t.filter(o=>o.visible!==!1),s=e.map(o=>o.header).join(" "),a=c.map(o=>e.map(u=>{let r=o[u.key];return r==null?"":String(r)}).join(" ")),i=[s,...a].join(`
4
+ `);await navigator.clipboard.writeText(i)}function y(c,t,e){let s=t.filter(r=>r.visible!==!1),a=s.map(r=>`<th style="border:1px solid #ddd;padding:8px 12px;text-align:left;background:#f5f5f5;font-weight:600;">${b(r.header)}</th>`).join(""),i=c.map(r=>`<tr>${s.map(d=>{let l=r[d.key];return`<td style="border:1px solid #ddd;padding:8px 12px;">${b(l==null?"":String(l))}</td>`}).join("")}</tr>`).join(""),o=`<!DOCTYPE html>
5
5
  <html><head>
6
- <title>${_(e??"Data Export")}</title>
6
+ <title>${b(e??"Data Export")}</title>
7
7
  <style>
8
8
  body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; margin: 20px; }
9
9
  table { border-collapse: collapse; width: 100%; font-size: 13px; }
@@ -11,9 +11,9 @@ import{fileURLToPath as I}from"url";import{dirname as P,join as V}from"path";var
11
11
  @media print { h1 { margin-top: 0; } }
12
12
  </style>
13
13
  </head><body>
14
- ${e?`<h1>${_(e)}</h1>`:""}
14
+ ${e?`<h1>${b(e)}</h1>`:""}
15
15
  <table>
16
16
  <thead><tr>${a}</tr></thead>
17
17
  <tbody>${i}</tbody>
18
18
  </table>
19
- </body></html>`,u=window.open("","_blank");u&&(u.document.write(o),u.document.close(),u.focus(),setTimeout(()=>u.print(),250))}function _(c){return c.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function E(c,t,e="export.xlsx"){let s;try{s=await import("exceljs")}catch{throw new Error("exceljs is required for Excel export. Install it: npm install exceljs")}let a=new s.Workbook,i=a.addWorksheet("Data"),o=t.filter(d=>d.visible!==!1);i.columns=o.map(d=>({header:d.header,key:d.key,width:20}));let u=i.getRow(1);u.font={bold:!0},u.fill={type:"pattern",pattern:"solid",fgColor:{argb:"FFF0F0F0"}};for(let d of c){let l={};for(let p of o)l[p.key]=d[p.key]??"";i.addRow(l)}let r=await a.xlsx.writeBuffer(),n=new Blob([r],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});w(n,e)}function F(c,t,e="export.pdf"){b(c,t,e.replace(".pdf",""))}var C=class{async export(t,e,s,a){switch(t){case"csv":{let i=T(e,s);D(i,a??"export.csv");break}case"excel":await E(e,s,a??"export.xlsx");break;case"pdf":F(e,s,a??"export.pdf");break;case"clipboard":await R(e,s);break;case"print":b(e,s);break}}};export{m as DataTableStore,C as ExportManager,v as ServerDataTableStore,S as SvelarDatatablePlugin};
19
+ </body></html>`,u=window.open("","_blank");u&&(u.document.write(o),u.document.close(),u.focus(),setTimeout(()=>u.print(),250))}function b(c){return c.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function k(c,t,e="export.xlsx"){let s;try{s=await import("exceljs")}catch{throw new Error("exceljs is required for Excel export. Install it: npm install exceljs")}let a=new s.Workbook,i=a.addWorksheet("Data"),o=t.filter(d=>d.visible!==!1);i.columns=o.map(d=>({header:d.header,key:d.key,width:20}));let u=i.getRow(1);u.font={bold:!0},u.fill={type:"pattern",pattern:"solid",fgColor:{argb:"FFF0F0F0"}};for(let d of c){let l={};for(let p of o)l[p.key]=d[p.key]??"";i.addRow(l)}let r=await a.xlsx.writeBuffer(),n=new Blob([r],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});w(n,e)}function P(c,t,e="export.pdf"){y(c,t,e.replace(".pdf",""))}var C=class{async export(t,e,s,a){switch(t){case"csv":{let i=R(e,s);E(i,a??"export.csv");break}case"excel":await k(e,s,a??"export.xlsx");break;case"pdf":P(e,s,a??"export.pdf");break;case"clipboard":await F(e,s);break;case"print":y(e,s);break}}};var lt=m;export{_ as DataTableStore,C as ExportManager,v as ServerDataTableStore,m as SvelarDatatablePlugin,lt as default};
@@ -1,4 +1,8 @@
1
+ import { Controller } from '@beeblock/svelar/routing';
1
2
  import { type DataTableServiceOptions } from './DataTableService.js';
2
- export declare class DataTableController {
3
- static handle(event: any, model: any, options?: DataTableServiceOptions): Promise<Response>;
3
+ export declare class DataTableController extends Controller {
4
+ private _model;
5
+ private _options?;
6
+ constructor(model: any, options?: DataTableServiceOptions);
7
+ query(event: any): Promise<Response>;
4
8
  }
@@ -1 +1 @@
1
- var h=class{_model;_searchable=[];_orderable=[];_baseQueryFn=null;_scopes={};_computedColumns={};_activeScopes=[];constructor(e,t){this._model=e,t?.searchable&&(this._searchable=t.searchable),t?.orderable&&(this._orderable=t.orderable),t?.baseQuery&&(this._baseQueryFn=t.baseQuery),t?.scopes&&(this._scopes=t.scopes),t?.computedColumns&&(this._computedColumns=t.computedColumns)}searchable(e){return this._searchable=e,this}orderable(e){return this._orderable=e,this}setBaseQuery(e){return this._baseQueryFn=e,this}addScope(e,t){return this._scopes[e]=t,this}applyScope(e){return this._activeScopes.push(e),this}addComputedColumn(e,t){return this._computedColumns[e]=t,this}async process(e){try{let t=this._model.query();this._baseQueryFn&&this._baseQueryFn(t);let u=await t.count(),a=this._model.query();this._baseQueryFn&&this._baseQueryFn(a);for(let r of this._activeScopes){let o=this._scopes[r];o&&o(a)}for(let[r,o]of Object.entries(this._computedColumns))a=a.selectRaw(`(${o}) as ${r}`);if(e.search.value){let r=e.search.value,o=this._searchable.length>0?this._searchable:e.columns.filter(i=>i.searchable).map(i=>i.data);o.length>0&&(a=a.whereNested(i=>{for(let l=0;l<o.length;l++){let m=o[l];l===0?i.where(m,"LIKE",`%${r}%`):i.orWhere(m,"LIKE",`%${r}%`)}}))}for(let r of e.columns)r.search.value&&r.searchable&&(a=a.where(r.data,"LIKE",`%${r.search.value}%`));let c=await a.clone().count();for(let r of e.order){let o=e.columns[r.column];o&&(this._orderable.length>0?this._orderable:e.columns.filter(l=>l.orderable).map(l=>l.data)).includes(o.data)&&(a=a.orderBy(o.data,r.dir))}a=a.offset(e.start).limit(e.length);let d=await a.get();return{draw:e.draw,recordsTotal:u,recordsFiltered:c,data:d}}catch(t){return{draw:e.draw,recordsTotal:0,recordsFiltered:0,data:[],error:t.message??"Server error"}}}};function p(s){let e=parseInt(s.get("draw")??"1",10),t=parseInt(s.get("start")??"0",10),u=parseInt(s.get("length")??"15",10),a={value:s.get("search[value]")??"",regex:s.get("search[regex]")==="true"},n=[],c=0;for(;s.has(`order[${c}][column]`);)n.push({column:parseInt(s.get(`order[${c}][column]`)??"0",10),dir:s.get(`order[${c}][dir]`)??"asc"}),c++;let d=[],r=0;for(;s.has(`columns[${r}][data]`);)d.push({data:s.get(`columns[${r}][data]`)??"",name:s.get(`columns[${r}][name]`)??"",searchable:s.get(`columns[${r}][searchable]`)!=="false",orderable:s.get(`columns[${r}][orderable]`)!=="false",search:{value:s.get(`columns[${r}][search][value]`)??"",regex:s.get(`columns[${r}][search][regex]`)==="true"}}),r++;return{draw:e,start:t,length:u,search:a,order:n,columns:d}}async function y(s){return await s.json()}var b=class{static async handle(e,t,u){try{let a=new h(t,u),n;e.request.method==="POST"?n=await y(e.request):n=p(e.url.searchParams);let c=await a.process(n);return new Response(JSON.stringify(c),{status:200,headers:{"Content-Type":"application/json"}})}catch(a){let n={draw:0,recordsTotal:0,recordsFiltered:0,data:[],error:a.message??"Internal server error"};return new Response(JSON.stringify(n),{status:500,headers:{"Content-Type":"application/json"}})}}};export{b as DataTableController,h as DataTableService,p as parseDataTableRequest,y as parseDataTableRequestFromBody};
1
+ var u=class{_model;_searchable=[];_orderable=[];_baseQueryFn=null;_scopes={};_computedColumns={};_activeScopes=[];constructor(e,r){this._model=e,r?.searchable&&(this._searchable=r.searchable),r?.orderable&&(this._orderable=r.orderable),r?.baseQuery&&(this._baseQueryFn=r.baseQuery),r?.scopes&&(this._scopes=r.scopes),r?.computedColumns&&(this._computedColumns=r.computedColumns)}searchable(e){return this._searchable=e,this}orderable(e){return this._orderable=e,this}setBaseQuery(e){return this._baseQueryFn=e,this}addScope(e,r){return this._scopes[e]=r,this}applyScope(e){return this._activeScopes.push(e),this}addComputedColumn(e,r){return this._computedColumns[e]=r,this}async process(e){try{let r=this._model.query();this._baseQueryFn&&this._baseQueryFn(r);let n=await r.count(),a=this._model.query();this._baseQueryFn&&this._baseQueryFn(a);for(let t of this._activeScopes){let o=this._scopes[t];o&&o(a)}for(let[t,o]of Object.entries(this._computedColumns))a=a.selectRaw(`(${o}) as ${t}`);if(e.search.value){let t=e.search.value,o=this._searchable.length>0?this._searchable:e.columns.filter(l=>l.searchable).map(l=>l.data);o.length>0&&(a=a.whereNested(l=>{for(let c=0;c<o.length;c++){let m=o[c];c===0?l.where(m,"LIKE",`%${t}%`):l.orWhere(m,"LIKE",`%${t}%`)}}))}for(let t of e.columns)t.search.value&&t.searchable&&(a=a.where(t.data,"LIKE",`%${t.search.value}%`));let i=await a.clone().count();for(let t of e.order){let o=e.columns[t.column];o&&(this._orderable.length>0?this._orderable:e.columns.filter(c=>c.orderable).map(c=>c.data)).includes(o.data)&&(a=a.orderBy(o.data,t.dir))}a=a.offset(e.start).limit(e.length);let h=await a.get();return{draw:e.draw,recordsTotal:n,recordsFiltered:i,data:h}}catch(r){return{draw:e.draw,recordsTotal:0,recordsFiltered:0,data:[],error:r.message??"Server error"}}}};import{Controller as g}from"@beeblock/svelar/routing";function p(s){let e=parseInt(s.get("draw")??"1",10),r=parseInt(s.get("start")??"0",10),n=parseInt(s.get("length")??"15",10),a={value:s.get("search[value]")??"",regex:s.get("search[regex]")==="true"},d=[],i=0;for(;s.has(`order[${i}][column]`);)d.push({column:parseInt(s.get(`order[${i}][column]`)??"0",10),dir:s.get(`order[${i}][dir]`)??"asc"}),i++;let h=[],t=0;for(;s.has(`columns[${t}][data]`);)h.push({data:s.get(`columns[${t}][data]`)??"",name:s.get(`columns[${t}][name]`)??"",searchable:s.get(`columns[${t}][searchable]`)!=="false",orderable:s.get(`columns[${t}][orderable]`)!=="false",search:{value:s.get(`columns[${t}][search][value]`)??"",regex:s.get(`columns[${t}][search][regex]`)==="true"}}),t++;return{draw:e,start:r,length:n,search:a,order:d,columns:h}}async function b(s){return await s.json()}var y=class extends g{_model;_options;constructor(e,r){super(),this._model=e,this._options=r}async query(e){try{let r=new u(this._model,this._options),n;e.request.method==="POST"?n=await b(e.request):n=p(e.url.searchParams);let a=await r.process(n);return this.json(a)}catch(r){let n={draw:0,recordsTotal:0,recordsFiltered:0,data:[],error:r.message??"Internal server error"};return this.json(n,500)}}};export{y as DataTableController,u as DataTableService,p as parseDataTableRequest,b as parseDataTableRequestFromBody};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beeblock/svelar-datatable",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Full-featured DataTable plugin for Svelar — sorting, searching, pagination, inline editing, export, and server-side processing",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -9,22 +9,20 @@ import type { RequestHandler } from './$types';
9
9
  //
10
10
  // import { User } from '$lib/models/User';
11
11
  //
12
- // export const GET: RequestHandler = (event) =>
13
- // DataTableController.handle(event, User, {
14
- // searchable: ['name', 'email'],
15
- // sortable: ['name', 'email', 'created_at'],
16
- // });
12
+ // const ctrl = new DataTableController(User, {
13
+ // searchable: ['name', 'email'],
14
+ // orderable: ['name', 'email', 'created_at'],
15
+ // });
17
16
  //
18
- // POST is also supported for complex filter payloads:
19
- // export const POST: RequestHandler = (event) =>
20
- // DataTableController.handle(event, User);
17
+ // export const GET: RequestHandler = ctrl.handle('query');
18
+ // export const POST: RequestHandler = ctrl.handle('query');
21
19
 
22
20
  export const GET: RequestHandler = (event) => {
23
21
  // TODO: replace with your model and options
24
- throw new Error('Configure your model in this route before using DataTableController.handle()');
22
+ throw new Error('Configure your model in this route before using DataTableController');
25
23
  };
26
24
 
27
25
  export const POST: RequestHandler = (event) => {
28
26
  // TODO: replace with your model and options
29
- throw new Error('Configure your model in this route before using DataTableController.handle()');
27
+ throw new Error('Configure your model in this route before using DataTableController');
30
28
  };