@bexis2/bexis2-core-ui 0.3.11 → 0.3.13

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 (30) hide show
  1. package/README.md +10 -0
  2. package/dist/components/File/FileUploader.svelte +3 -3
  3. package/dist/components/Table/TableContent.svelte +202 -119
  4. package/dist/components/Table/TableFilter.svelte +146 -102
  5. package/dist/components/Table/TableFilter.svelte.d.ts +2 -3
  6. package/dist/components/Table/TableFilterServer.svelte +274 -0
  7. package/dist/components/Table/TableFilterServer.svelte.d.ts +22 -0
  8. package/dist/components/Table/TablePagination.svelte +72 -39
  9. package/dist/components/Table/TablePaginationServer.svelte +125 -0
  10. package/dist/components/Table/TablePaginationServer.svelte.d.ts +21 -0
  11. package/dist/components/Table/filter.js +40 -78
  12. package/dist/components/Table/shared.d.ts +32 -0
  13. package/dist/components/Table/shared.js +117 -0
  14. package/dist/components/form/DropdownKvP.svelte.d.ts +4 -4
  15. package/dist/components/form/MultiSelect.svelte.d.ts +6 -6
  16. package/dist/models/Enums.d.ts +18 -0
  17. package/dist/models/Enums.js +20 -0
  18. package/dist/models/Models.d.ts +43 -2
  19. package/dist/models/Models.js +28 -1
  20. package/package.json +2 -2
  21. package/src/lib/components/Table/TableContent.svelte +227 -151
  22. package/src/lib/components/Table/TableFilter.svelte +166 -102
  23. package/src/lib/components/Table/TableFilterServer.svelte +310 -0
  24. package/src/lib/components/Table/TablePagination.svelte +75 -39
  25. package/src/lib/components/Table/TablePaginationServer.svelte +133 -0
  26. package/src/lib/components/Table/filter.ts +42 -86
  27. package/src/lib/components/Table/shared.ts +141 -0
  28. package/src/lib/components/file/FileUploader.svelte +3 -3
  29. package/src/lib/models/Enums.ts +22 -0
  30. package/src/lib/models/Models.ts +63 -2
@@ -31,3 +31,21 @@ export declare enum notificationType {
31
31
  error = 2,
32
32
  surface = 3
33
33
  }
34
+ export declare enum FilterOptionsEnum {
35
+ 'e' = "e",
36
+ 'ne' = "ne",
37
+ 'gt' = "gt",
38
+ 'lt' = "lt",
39
+ 'gte' = "gte",
40
+ 'lte' = "lte",
41
+ 'c' = "c",
42
+ 'nc' = "nc",
43
+ 'sw' = "sw",
44
+ 'ew' = "ew",
45
+ 'o' = "o",
46
+ 'sf' = "sf",
47
+ 'a' = "a",
48
+ 'u' = "u",
49
+ 'b' = "b",
50
+ 'no' = "no"
51
+ }
@@ -39,3 +39,23 @@ export var notificationType;
39
39
  notificationType[notificationType["error"] = 2] = "error";
40
40
  notificationType[notificationType["surface"] = 3] = "surface";
41
41
  })(notificationType || (notificationType = {}));
42
+ // Server-side table fitler types
43
+ export var FilterOptionsEnum;
44
+ (function (FilterOptionsEnum) {
45
+ FilterOptionsEnum["e"] = "e";
46
+ FilterOptionsEnum["ne"] = "ne";
47
+ FilterOptionsEnum["gt"] = "gt";
48
+ FilterOptionsEnum["lt"] = "lt";
49
+ FilterOptionsEnum["gte"] = "gte";
50
+ FilterOptionsEnum["lte"] = "lte";
51
+ FilterOptionsEnum["c"] = "c";
52
+ FilterOptionsEnum["nc"] = "nc";
53
+ FilterOptionsEnum["sw"] = "sw";
54
+ FilterOptionsEnum["ew"] = "ew";
55
+ FilterOptionsEnum["o"] = "o";
56
+ FilterOptionsEnum["sf"] = "sf";
57
+ FilterOptionsEnum["a"] = "a";
58
+ FilterOptionsEnum["u"] = "u";
59
+ FilterOptionsEnum["b"] = "b";
60
+ FilterOptionsEnum["no"] = "no"; // Not on (date)
61
+ })(FilterOptionsEnum || (FilterOptionsEnum = {}));
@@ -1,7 +1,7 @@
1
1
  import type { SvelteComponent } from 'svelte';
2
2
  import type { ColumnFilterFn } from 'svelte-headless-table/lib/plugins';
3
3
  import type { Writable } from 'svelte/store';
4
- import type { decimalCharacterType, notificationType, orientationType, textMarkerType, textSeperatorType } from './Enums';
4
+ import type { FilterOptionsEnum, decimalCharacterType, notificationType, orientationType, textMarkerType, textSeperatorType } from './Enums';
5
5
  export interface linkType {
6
6
  label: string;
7
7
  url: string;
@@ -83,7 +83,7 @@ export interface Columns {
83
83
  export interface TableConfig<T> {
84
84
  id: string;
85
85
  data: Writable<T[]>;
86
- resizable?: 'rows' | 'columns' | 'both';
86
+ resizable?: 'none' | 'rows' | 'columns' | 'both';
87
87
  toggle?: boolean;
88
88
  fitToScreen?: boolean;
89
89
  height?: null | number;
@@ -93,6 +93,12 @@ export interface TableConfig<T> {
93
93
  pageSizes?: number[];
94
94
  defaultPageSize?: number;
95
95
  optionsComponent?: typeof SvelteComponent;
96
+ serverSide?: boolean;
97
+ URL?: string;
98
+ token?: string;
99
+ sendModel?: Send;
100
+ entityId?: number;
101
+ versionId?: number;
96
102
  }
97
103
  export interface keyValuePairType {
98
104
  id: number;
@@ -123,3 +129,38 @@ export interface notificationStoreType {
123
129
  message: string;
124
130
  btnStyle: string;
125
131
  }
132
+ export type ServerColumn = {
133
+ column: string;
134
+ exclude?: boolean;
135
+ instructions?: {
136
+ missingValues?: {
137
+ [key: string | number]: string;
138
+ };
139
+ displayPattern?: string;
140
+ };
141
+ };
142
+ export type OrderBy = {
143
+ column: string;
144
+ direction: 'asc' | 'desc';
145
+ };
146
+ export type Filter = {
147
+ column: string;
148
+ filterBy: FilterOptionsEnum;
149
+ value: string | number | Date | boolean;
150
+ };
151
+ export declare class Send {
152
+ id: number;
153
+ limit: number;
154
+ offset: number;
155
+ version?: number;
156
+ filter: Filter[];
157
+ order: OrderBy[];
158
+ constructor();
159
+ }
160
+ export declare class Receive {
161
+ count: number;
162
+ data: any[];
163
+ send: Send;
164
+ columns?: ServerColumn[];
165
+ constructor();
166
+ }
@@ -1 +1,28 @@
1
- export {};
1
+ export class Send {
2
+ id;
3
+ limit;
4
+ offset;
5
+ version;
6
+ filter;
7
+ order;
8
+ constructor() {
9
+ this.id = 0;
10
+ this.limit = 10;
11
+ this.offset = 0;
12
+ this.version = 0;
13
+ this.filter = [];
14
+ this.order = [];
15
+ }
16
+ }
17
+ export class Receive {
18
+ count;
19
+ data;
20
+ send;
21
+ columns;
22
+ constructor() {
23
+ this.count = 0;
24
+ this.data = [];
25
+ this.send = new Send();
26
+ this.columns = [];
27
+ }
28
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bexis2/bexis2-core-ui",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -79,7 +79,7 @@
79
79
  "svelte": "^3.54.0",
80
80
  "svelte-codemirror-editor": "^1.1.0",
81
81
  "svelte-fa": "^3.0.4",
82
- "svelte-file-dropzone": "^2.0.1",
82
+ "svelte-file-dropzone": "^2.0.4",
83
83
  "svelte-headless-table": "^0.17.3",
84
84
  "svelte-select": "5.8.3",
85
85
  "vest": "^4.6.11"
@@ -1,5 +1,9 @@
1
1
  <script lang="ts">
2
2
  import { createEventDispatcher } from 'svelte';
3
+ import { readable, writable } from 'svelte/store';
4
+
5
+ import Fa from 'svelte-fa';
6
+ import { faXmark } from '@fortawesome/free-solid-svg-icons';
3
7
  import { createTable, Subscribe, Render, createRender } from 'svelte-headless-table';
4
8
  import {
5
9
  addSortBy,
@@ -11,13 +15,26 @@
11
15
  } from 'svelte-headless-table/plugins';
12
16
  import { computePosition, autoUpdate, offset, shift, flip, arrow } from '@floating-ui/dom';
13
17
  import { SlideToggle, storePopup } from '@skeletonlabs/skeleton';
18
+ import type { PaginationConfig } from 'svelte-headless-table/lib/plugins/addPagination';
14
19
 
15
20
  storePopup.set({ computePosition, autoUpdate, offset, shift, flip, arrow });
16
21
 
17
22
  import TableFilter from './TableFilter.svelte';
23
+ import TableFilterServer from './TableFilterServer.svelte';
18
24
  import TablePagination from './TablePagination.svelte';
25
+ import TablePaginationServer from './TablePaginationServer.svelte';
19
26
  import { columnFilter, searchFilter } from './filter';
27
+ import {
28
+ cellStyle,
29
+ exportAsCsv,
30
+ fixedWidth,
31
+ normalizeFilters,
32
+ resetResize,
33
+ convertServerColumns
34
+ } from './shared';
35
+ import { Receive, Send } from '$lib/models/Models';
20
36
  import type { TableConfig } from '$lib/models/Models';
37
+ import type { FilterOptionsEnum } from '$models/Enums';
21
38
 
22
39
  export let config: TableConfig<any>;
23
40
 
@@ -34,9 +51,21 @@
34
51
  toggle = false, // Whether to display the fitToScreen toggle
35
52
  pageSizes = [5, 10, 15, 20], // Page sizes to display in the pagination component
36
53
  fitToScreen = true, // Whether to fit the table to the screen,
37
- exportable = false // Whether to display the export button and enable export functionality
54
+ exportable = false, // Whether to display the export button and enable export functionality
55
+ serverSide = false, // Whether the table is client or server-side
56
+ URL = '', // URL to fetch data from
57
+ token = '', // Bearer token to authenticate the request
58
+ sendModel = new Send(), // Model to send requests
59
+ entityId = 0, // Entity ID to send with the request
60
+ versionId = 0 // Version ID to send with the request
38
61
  } = config;
39
62
 
63
+ let searchValue = '';
64
+
65
+ const filters = writable<{
66
+ [key: string]: { [key in FilterOptionsEnum]?: number | string | Date };
67
+ }>({});
68
+
40
69
  // Creatign a type to access keys of the objects in the data store
41
70
  type AccessorType = keyof (typeof $data)[number];
42
71
 
@@ -44,14 +73,29 @@
44
73
  const dispatch = createEventDispatcher();
45
74
  const actionDispatcher = (obj) => dispatch('action', obj);
46
75
 
76
+ const serverItems = serverSide ? writable<Number>(0) : undefined;
77
+ const serverItemCount = serverSide
78
+ ? readable<Number>(0, (set) => {
79
+ serverItems!.subscribe((val) => set(val));
80
+ })
81
+ : undefined;
82
+
47
83
  // Initializing the table
48
84
  const table = createTable(data, {
49
85
  colFilter: addColumnFilters(),
50
86
  tableFilter: addTableFilter({
51
- fn: searchFilter
87
+ fn: searchFilter,
88
+ serverSide
89
+ }),
90
+ sort: addSortBy({
91
+ disableMultiSort: true,
92
+ serverSide
52
93
  }),
53
- sort: addSortBy({ disableMultiSort: true }),
54
- page: addPagination({ initialPageSize: defaultPageSize }),
94
+ page: addPagination({
95
+ initialPageSize: defaultPageSize,
96
+ serverSide,
97
+ serverItemCount
98
+ } as PaginationConfig),
55
99
  expand: addExpandedRows(),
56
100
  export: addDataExport({ format: 'csv' })
57
101
  });
@@ -66,8 +110,14 @@
66
110
  }
67
111
  });
68
112
  });
113
+
114
+ Object.keys(allCols).forEach((key) => {
115
+ $filters = { ...$filters, [key]: {} };
116
+ });
117
+
69
118
  // Creating an array of all the keys
70
119
  const accessors: AccessorType[] = Object.keys(allCols) as AccessorType[];
120
+
71
121
  // Configuring every table column with the provided options
72
122
  const tableColumns = [
73
123
  ...accessors
@@ -111,7 +161,6 @@
111
161
  // Sorting config
112
162
  sort: {
113
163
  disable: disableSorting,
114
- invert: true,
115
164
  getSortValue: (row) => {
116
165
  // If provided, use the custom sorting function toSortableValueFn(), or just use the value
117
166
  return toSortableValueFn ? toSortableValueFn(row) : row;
@@ -128,14 +177,25 @@
128
177
  : columnFilter({ filterValue, value: val });
129
178
  },
130
179
  render: ({ filterValue, values, id }) => {
131
- // If provided, use the custom filter component, or use the default TableFilter component
132
- return createRender(colFilterComponent ?? TableFilter, {
133
- filterValue,
134
- id,
135
- tableId,
136
- values,
137
- toFilterableValueFn
138
- });
180
+ filterValue.set($filters[key]);
181
+ return serverSide
182
+ ? createRender(TableFilterServer, {
183
+ id,
184
+ tableId,
185
+ values,
186
+ updateTable,
187
+ pageIndex,
188
+ toFilterableValueFn,
189
+ filters
190
+ })
191
+ : createRender(colFilterComponent ?? TableFilter, {
192
+ filterValue,
193
+ id,
194
+ tableId,
195
+ values,
196
+ toFilterableValueFn,
197
+ filters
198
+ });
139
199
  }
140
200
  }
141
201
  : undefined,
@@ -149,7 +209,6 @@
149
209
  }
150
210
  });
151
211
  } else {
152
- // Default configuration for unconfigured columns
153
212
  return table.column({
154
213
  header: key,
155
214
  accessor: accessor,
@@ -159,19 +218,28 @@
159
218
  },
160
219
  plugins: {
161
220
  // Sorting enabled by default
162
- sort: {
163
- invert: true
164
- },
221
+ sort: {},
165
222
  // Filtering enabled by default
166
223
  colFilter: {
167
224
  fn: columnFilter,
168
- render: ({ filterValue, values, id }) =>
169
- createRender(TableFilter, {
170
- filterValue,
171
- id,
172
- tableId,
173
- values
174
- })
225
+ render: ({ filterValue, values, id }) => {
226
+ return serverSide
227
+ ? createRender(TableFilterServer, {
228
+ id,
229
+ tableId,
230
+ values,
231
+ updateTable,
232
+ pageIndex,
233
+ filters
234
+ })
235
+ : createRender(TableFilter, {
236
+ filterValue,
237
+ id,
238
+ tableId,
239
+ values,
240
+ filters
241
+ });
242
+ }
175
243
  }
176
244
  }
177
245
  });
@@ -209,96 +277,90 @@
209
277
  const { filterValue } = pluginStates.tableFilter;
210
278
  // CSV content to be exported. If unexportable, then null
211
279
  const { exportedData } = pluginStates.export;
280
+ // Page configuration
281
+ const { pageIndex, pageSize } = pluginStates.page;
212
282
 
213
- // Function to determine minWidth for a column to simplify the logic in the HTML
214
- const minWidth = (id: string) => {
215
- if (columns && id in columns) {
216
- return columns[id].minWidth ?? 0;
217
- }
218
- return 0;
219
- };
220
- // Function to determine fixedWidth for a column to simplify the logic in the HTML
221
- const fixedWidth = (id: string) => {
222
- if (columns && id in columns) {
223
- return columns[id].fixedWidth ?? 0;
283
+ // TODO: Add loading animation for server-side fetch requests
284
+ const updateTable = async () => {
285
+ sendModel.limit = $pageSize;
286
+ sendModel.offset = $pageSize * $pageIndex;
287
+ sendModel.version = versionId;
288
+ sendModel.id = entityId;
289
+ sendModel.filter = normalizeFilters($filters);
290
+
291
+ const fetchData = await fetch(URL, {
292
+ headers: {
293
+ 'Content-Type': 'application/json',
294
+ Authorization: `Bearer ${token}`
295
+ },
296
+ method: 'POST',
297
+ body: JSON.stringify(sendModel)
298
+ });
299
+
300
+ const response: Receive = await fetchData.json();
301
+
302
+ // Format server columns to the client columns
303
+ if (response.columns !== undefined) {
304
+ columns = convertServerColumns(response.columns);
224
305
  }
225
- return 0;
226
- };
227
- // Function to create custom styles for the columns to simplify the logic in the HTML
228
- const cellStyle = (id: string) => {
229
- const minW = minWidth(id);
230
- const fixedW = fixedWidth(id);
231
- const styles: string[] = [];
232
-
233
- // If minWidth is provided, add to styles
234
- minW && styles.push(`min-width: ${minW}px`);
235
- // If fixedWidth is provided, add to styles
236
- fixedW && styles.push(`width: ${fixedW}px`);
237
- // Create and return styles separated by ';'
238
- return styles.join(';');
306
+
307
+ // Update data store
308
+ $data = response.data;
309
+ $serverItems = response.count;
310
+
311
+ return response;
239
312
  };
240
313
 
241
- // Resetting the resized columns and/or rows
242
- const resetResize = () => {
243
- // Run only if resizable is not none
244
- if (resizable === 'columns' || resizable === 'both') {
245
- $headerRows.forEach((row) => {
246
- row.cells.forEach((cell) => {
247
- const minW = minWidth(cell.id);
248
- const fixedW = fixedWidth(cell.id);
249
- // If a fixedWidth is provided for a column, then reset the width to that value
250
- fixedW &&
251
- document
252
- .getElementById(`th-${tableId}-${cell.id}`)
253
- ?.style.setProperty('width', `${fixedW}px`);
254
- // If a minWidth is provided for a column, then reset the width to that value
255
- minW &&
256
- document
257
- .getElementById(`th-${tableId}-${cell.id}`)
258
- ?.style.setProperty('min-width', `${minW}px`);
259
- // If neither minWidth nor fixedWidth provided for a column, then reset the width to auto
260
- !minW &&
261
- !fixedW &&
262
- document.getElementById(`th-${tableId}-${cell.id}`)?.style.setProperty('width', 'auto');
263
- });
264
- });
314
+ const sortServer = (order: 'asc' | 'desc' | undefined, id: string) => {
315
+ // Set parameter for sorting
316
+ if (order === undefined) {
317
+ sendModel.order = [];
318
+ } else {
319
+ sendModel.order = [{ column: id, direction: order }];
265
320
  }
266
321
 
267
- if (resizable === 'rows' || resizable === 'both') {
268
- $pageRows.forEach((row) => {
269
- row.cells.forEach((cell) => {
270
- // Reset all row heights to auto
271
- document
272
- .getElementById(`${tableId}-${cell.id}-${row.id}`)
273
- ?.style.setProperty('height', 'auto');
274
- });
275
- });
276
- }
277
- };
322
+ // Reset pagination
323
+ $pageIndex = 0;
278
324
 
279
- const exportAsCsv = () => {
280
- // Creating a hidden anchor element to download the CSV file
281
- const anchor = document.createElement('a');
282
- anchor.style.display = 'none';
283
- anchor.href = `data:text/csv;charset=utf-8,${encodeURIComponent($exportedData)}`;
284
- anchor.download = `${tableId}.csv`;
285
- document.body.appendChild(anchor);
286
- anchor.click();
287
- document.body.removeChild(anchor);
325
+ updateTable();
288
326
  };
327
+
328
+ $: sortKeys = pluginStates.sort.sortKeys;
329
+ $: serverSide && updateTable();
330
+ $: serverSide && sortServer($sortKeys[0]?.order, $sortKeys[0]?.id);
289
331
  </script>
290
332
 
291
333
  <div class="grid gap-2 overflow-auto" class:w-fit={!fitToScreen} class:w-full={fitToScreen}>
292
334
  <div class="table-container">
293
335
  <!-- Enable the search filter if table is not empty -->
294
336
  {#if $data.length > 0}
295
- <input
296
- class="input p-2 border border-primary-500"
297
- type="text"
298
- bind:value={$filterValue}
299
- placeholder="Search rows..."
300
- id="{tableId}-search"
301
- />
337
+ {#if !serverSide}
338
+ <div class="flex gap-2">
339
+ <div class="relative w-full flex items-center">
340
+ <input
341
+ class="input p-2 border border-primary-500"
342
+ type="text"
343
+ bind:value={searchValue}
344
+ placeholder="Search rows..."
345
+ id="{tableId}-search"
346
+ /><button
347
+ type="reset"
348
+ class="absolute right-3 items-center"
349
+ on:click|preventDefault={() => {
350
+ searchValue = '';
351
+ $filterValue = '';
352
+ }}><Fa icon={faXmark} /></button
353
+ >
354
+ </div>
355
+ <button
356
+ type="button"
357
+ class="btn variant-filled-primary"
358
+ on:click|preventDefault={() => {
359
+ $filterValue = searchValue;
360
+ }}>Search</button
361
+ >
362
+ </div>
363
+ {/if}
302
364
  <div class="flex justify-between items-center py-2 w-full">
303
365
  <div>
304
366
  <!-- Enable the fitToScreen toggle if toggle === true -->
@@ -319,14 +381,17 @@
319
381
  <button
320
382
  type="button"
321
383
  class="btn btn-sm variant-filled-primary rounded-full order-last"
322
- on:click|preventDefault={resetResize}>Reset sizing</button
384
+ on:click|preventDefault={() =>
385
+ resetResize($headerRows, $pageRows, tableId, columns, resizable)}
386
+ >Reset sizing</button
323
387
  >
324
388
  {/if}
325
389
  {#if exportable}
326
390
  <button
327
391
  type="button"
328
392
  class="btn btn-sm variant-filled-primary rounded-full order-last"
329
- on:click|preventDefault={exportAsCsv}>Export as CSV</button
393
+ on:click|preventDefault={() => exportAsCsv(tableId, $exportedData)}
394
+ >Export as CSV</button
330
395
  >
331
396
  {/if}
332
397
  </div>
@@ -349,46 +414,45 @@
349
414
  rowProps={headerRow.props()}
350
415
  let:rowProps
351
416
  >
352
- <tr {...rowAttrs} class="bg-primary-300 dark:bg-primary-500 items-stretch">
417
+ <tr {...rowAttrs} class="bg-primary-300 dark:bg-primary-500">
353
418
  {#each headerRow.cells as cell (cell.id)}
354
419
  <Subscribe attrs={cell.attrs()} props={cell.props()} let:props let:attrs>
355
- <th
356
- scope="col"
357
- class="!p-2 overflow-auto"
358
- class:resize-x={(resizable === 'columns' || resizable === 'both') &&
359
- !fixedWidth(cell.id)}
360
- {...attrs}
361
- id="th-{tableId}-{cell.id}"
362
- style={cellStyle(cell.id)}
363
- >
364
- <div class="flex justify-between items-center">
365
- <div class="flex gap-1 whitespace-pre-wrap">
366
- <!-- Adding sorting config and styling -->
367
- <span
368
- class:underline={props.sort.order}
369
- class:normal-case={cell.id !== cell.label}
370
- class:cursor-pointer={!props.sort.disabled}
371
- on:click={props.sort.toggle}
372
- on:keydown={props.sort.toggle}
373
- >
374
- {cell.render()}
375
- </span>
376
- <div class="w-2">
377
- {#if props.sort.order === 'asc'}
378
-
379
- {:else if props.sort.order === 'desc'}
380
-
381
- {/if}
382
- </div>
383
- </div>
384
- <!-- Adding column filter config -->
385
- {#if cell.isData()}
386
- {#if props.colFilter?.render}
387
- <div class="">
388
- <Render of={props.colFilter.render} />
420
+ <th scope="col" class="!p-2" {...attrs} style={cellStyle(cell.id, columns)}>
421
+ <div
422
+ class="overflow-auto"
423
+ class:resize-x={(resizable === 'columns' || resizable === 'both') &&
424
+ !fixedWidth(cell.id, columns)}
425
+ id="th-{tableId}-{cell.id}"
426
+ >
427
+ <div class="flex justify-between items-center">
428
+ <div class="flex gap-1 whitespace-pre-wrap">
429
+ <!-- Adding sorting config and styling -->
430
+ <span
431
+ class:underline={props.sort.order}
432
+ class:normal-case={cell.id !== cell.label}
433
+ class:cursor-pointer={!props.sort.disabled}
434
+ on:click={props.sort.toggle}
435
+ on:keydown={props.sort.toggle}
436
+ >
437
+ {cell.render()}
438
+ </span>
439
+ <div class="w-2">
440
+ {#if props.sort.order === 'asc'}
441
+
442
+ {:else if props.sort.order === 'desc'}
443
+
444
+ {/if}
389
445
  </div>
446
+ </div>
447
+ <!-- Adding column filter config -->
448
+ {#if cell.isData()}
449
+ {#if props.colFilter?.render}
450
+ <div class="">
451
+ <Render of={props.colFilter.render} />
452
+ </div>
453
+ {/if}
390
454
  {/if}
391
- {/if}
455
+ </div>
392
456
  </div>
393
457
  </th>
394
458
  </Subscribe>
@@ -409,20 +473,21 @@
409
473
  <tr {...rowAttrs} id="{tableId}-row-{row.id}" class="">
410
474
  {#each row.cells as cell, index (cell?.id)}
411
475
  <Subscribe attrs={cell.attrs()} let:attrs>
412
- <td
413
- {...attrs}
414
- class="!p-2 overflow-auto {index === 0 &&
415
- (resizable === 'rows' || resizable === 'both')
416
- ? 'resize-y'
417
- : ''}"
418
- id="{tableId}-{cell.id}-{row.id}"
419
- >
420
- <!-- Adding config for initial rowHeight, if provided -->
476
+ <td {...attrs} class="!p-2">
421
477
  <div
422
- class="flex items-center"
423
- style="height: {rowHeight ? `${rowHeight}px` : 'auto'};"
478
+ class=" overflow-auto h-max {index === 0 &&
479
+ (resizable === 'rows' || resizable === 'both')
480
+ ? 'resize-y'
481
+ : ''}"
482
+ id="{tableId}-{cell.id}-{row.id}"
424
483
  >
425
- <div class="grow h-full"><Render of={cell.render()} /></div>
484
+ <!-- Adding config for initial rowHeight, if provided -->
485
+ <div
486
+ class="flex items-center overflow-auto"
487
+ style="height: {rowHeight ? `${rowHeight}px` : 'auto'};"
488
+ >
489
+ <div class="grow h-full"><Render of={cell.render()} /></div>
490
+ </div>
426
491
  </div>
427
492
  </td>
428
493
  </Subscribe>
@@ -437,6 +502,17 @@
437
502
  </div>
438
503
  {#if $data.length > 0}
439
504
  <!-- Adding pagination, if table is not empty -->
440
- <TablePagination pageConfig={pluginStates.page} {pageSizes} id={tableId} />
505
+ {#if serverSide}
506
+ <TablePaginationServer
507
+ {pageIndex}
508
+ {pageSize}
509
+ {serverItemCount}
510
+ {updateTable}
511
+ {pageSizes}
512
+ id={tableId}
513
+ />
514
+ {:else}
515
+ <TablePagination pageConfig={pluginStates.page} {pageSizes} id={tableId} />
516
+ {/if}
441
517
  {/if}
442
518
  </div>