@bexis2/bexis2-core-ui 0.4.95 → 0.4.97

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 (89) hide show
  1. package/README.md +105 -24
  2. package/dist/components/CodeEditor/CodeEditor.svelte +2 -2
  3. package/dist/components/Facets/ShowMore.svelte +4 -6
  4. package/dist/components/File/FileUploader.svelte +6 -3
  5. package/dist/components/Table/Table.svelte +31 -5
  6. package/dist/components/Table/TableContent.svelte +226 -27
  7. package/dist/components/Table/TableFilter.svelte +25 -12
  8. package/dist/components/Table/TableFilterServer.svelte +51 -6
  9. package/dist/components/Table/TablePaginationServer.svelte +27 -8
  10. package/dist/components/Table/clientDB.d.ts +22 -0
  11. package/dist/components/Table/clientDB.js +236 -0
  12. package/dist/components/Table/filter.js +21 -2
  13. package/dist/components/Table/tableWorker.d.ts +1 -0
  14. package/dist/components/Table/tableWorker.js +179 -0
  15. package/dist/components/Table/utils.d.ts +1 -2
  16. package/dist/components/Table/utils.js +64 -31
  17. package/dist/components/form/CheckboxKvPList.svelte +15 -15
  18. package/dist/components/form/CheckboxList.svelte +1 -1
  19. package/dist/components/form/DateInput.svelte +12 -1
  20. package/dist/components/form/DatePickerInput.svelte +51 -29
  21. package/dist/components/form/Dropdown.svelte +14 -3
  22. package/dist/components/form/DropdownKvP.svelte +13 -2
  23. package/dist/components/form/InputContainer.svelte +17 -15
  24. package/dist/components/form/MultiSelect.svelte +30 -29
  25. package/dist/components/form/NumberInput.svelte +12 -1
  26. package/dist/components/form/TextArea.svelte +12 -1
  27. package/dist/components/form/TextInput.svelte +12 -1
  28. package/dist/components/page/Alert.svelte +5 -1
  29. package/dist/components/page/BackToTop.svelte +3 -1
  30. package/dist/components/page/Docs.svelte +9 -2
  31. package/dist/components/page/GoToTop.svelte +14 -15
  32. package/dist/components/page/Page.svelte +50 -56
  33. package/dist/components/page/breadcrumb/BreadcrumbDataCaller.js +11 -15
  34. package/dist/components/page/menu/MenuAccountBar.svelte +1 -5
  35. package/dist/components/page/menu/MenuDataCaller.js +1 -1
  36. package/dist/components/page/menu/MenuItem.svelte +9 -7
  37. package/dist/components/page/menu/MenuSublist.svelte +7 -5
  38. package/dist/components/page/menu/SettingsBar.svelte +4 -1
  39. package/dist/components/toggle/Toggle.svelte +9 -9
  40. package/dist/css/core.ui.postcss +1 -2
  41. package/dist/services/Api.js +4 -4
  42. package/dist/services/BaseCaller.js +1 -1
  43. package/package.json +114 -114
  44. package/src/lib/components/CodeEditor/CodeEditor.svelte +4 -4
  45. package/src/lib/components/Facets/Facets.svelte +2 -2
  46. package/src/lib/components/Facets/ShowMore.svelte +4 -6
  47. package/src/lib/components/File/FileUploader.svelte +17 -14
  48. package/src/lib/components/Table/Table.svelte +32 -5
  49. package/src/lib/components/Table/TableContent.svelte +261 -38
  50. package/src/lib/components/Table/TableFilter.svelte +34 -8
  51. package/src/lib/components/Table/TableFilterServer.svelte +65 -9
  52. package/src/lib/components/Table/TablePagination.svelte +6 -2
  53. package/src/lib/components/Table/TablePaginationServer.svelte +36 -10
  54. package/src/lib/components/Table/clientDB.js +236 -0
  55. package/src/lib/components/Table/filter.ts +44 -24
  56. package/src/lib/components/Table/tableWorker.js +179 -0
  57. package/src/lib/components/Table/utils.ts +80 -46
  58. package/src/lib/components/form/Checkbox.svelte +1 -1
  59. package/src/lib/components/form/CheckboxKvPList.svelte +15 -16
  60. package/src/lib/components/form/CheckboxList.svelte +1 -1
  61. package/src/lib/components/form/DateInput.svelte +13 -2
  62. package/src/lib/components/form/DatePickerInput.svelte +51 -29
  63. package/src/lib/components/form/Dropdown.svelte +14 -3
  64. package/src/lib/components/form/DropdownKvP.svelte +13 -2
  65. package/src/lib/components/form/InputContainer.svelte +18 -17
  66. package/src/lib/components/form/MultiSelect.svelte +30 -29
  67. package/src/lib/components/form/NumberInput.svelte +21 -12
  68. package/src/lib/components/form/TextArea.svelte +13 -2
  69. package/src/lib/components/form/TextInput.svelte +13 -2
  70. package/src/lib/components/page/Alert.svelte +5 -1
  71. package/src/lib/components/page/BackToTop.svelte +3 -1
  72. package/src/lib/components/page/Docs.svelte +9 -2
  73. package/src/lib/components/page/GoToTop.svelte +14 -15
  74. package/src/lib/components/page/Notification.svelte +1 -1
  75. package/src/lib/components/page/Page.svelte +67 -78
  76. package/src/lib/components/page/breadcrumb/Breadcrumb.svelte +2 -3
  77. package/src/lib/components/page/breadcrumb/BreadcrumbDataCaller.js +11 -15
  78. package/src/lib/components/page/menu/MenuAccountBar.svelte +1 -6
  79. package/src/lib/components/page/menu/MenuDataCaller.js +1 -1
  80. package/src/lib/components/page/menu/MenuItem.svelte +10 -8
  81. package/src/lib/components/page/menu/MenuSublist.svelte +35 -41
  82. package/src/lib/components/page/menu/SettingsBar.svelte +5 -2
  83. package/src/lib/components/toggle/Toggle.svelte +28 -30
  84. package/src/lib/css/core.ui.postcss +1 -2
  85. package/src/lib/index.ts +1 -2
  86. package/src/lib/services/Api.ts +21 -20
  87. package/src/lib/services/BaseCaller.js +1 -1
  88. package/src/lib/stores/apiStores.ts +1 -5
  89. package/src/lib/stores/pageStores.ts +0 -2
@@ -1,5 +1,5 @@
1
1
  <script>import { afterUpdate, createEventDispatcher, onDestroy, onMount } from "svelte";
2
- import { readable, writable } from "svelte/store";
2
+ import { writable } from "svelte/store";
3
3
  import Fa from "svelte-fa";
4
4
  import { faCompress, faDownload, faXmark } from "@fortawesome/free-solid-svg-icons";
5
5
  import { createTable, Subscribe, Render, createRender } from "svelte-headless-table";
@@ -21,6 +21,7 @@ import TableFilterServer from "./TableFilterServer.svelte";
21
21
  import TablePagination from "./TablePagination.svelte";
22
22
  import TablePaginationServer from "./TablePaginationServer.svelte";
23
23
  import ColumnsMenu from "./ColumnsMenu.svelte";
24
+ import ClientDB from "./clientDB.js";
24
25
  import * as utils from "./utils";
25
26
  import { columnFilter, searchFilter } from "./filter";
26
27
  import { Send } from "../../models/Models";
@@ -56,20 +57,27 @@ let {
56
57
  // Whether to display the export button and enable export functionality
57
58
  server
58
59
  } = config;
60
+ const clientDb = config.clientDb ?? false;
61
+ const clientDbSeedData = config.clientDbSeedData ?? [];
62
+ const initialServerCount = Number(config.__initialServerCount ?? 0);
59
63
  let searchValue = "";
60
64
  let isFetching = false;
61
65
  let tableRef;
62
- const serverSide = server !== void 0;
66
+ let serverItemCountValue = Number.isFinite(initialServerCount) ? initialServerCount : 0;
67
+ const serverSide = server !== void 0 || clientDb;
68
+ let _clientDbInstance = null;
69
+ let clientDbEnabled = clientDb;
70
+ let clientDbReady = false;
71
+ let clientDbInitSource = [];
72
+ let clientDbSeedSize = 0;
63
73
  const { sendModel = new Send() } = server ?? {};
64
74
  const filters = writable({});
65
75
  const dispatch = createEventDispatcher();
66
76
  const actionDispatcher = (obj) => dispatch("action", obj);
67
77
  const rowHeights = writable({});
68
78
  const colWidths = writable([]);
69
- const serverItems = serverSide ? writable(0) : void 0;
70
- const serverItemCount = serverSide ? readable(0, (set) => {
71
- serverItems.subscribe((val) => set(val));
72
- }) : void 0;
79
+ const serverItems = serverSide ? writable(Number.isFinite(initialServerCount) ? initialServerCount : 0) : void 0;
80
+ const serverItemCount = serverItems;
73
81
  const table = createTable(data, {
74
82
  colFilter: addColumnFilters(),
75
83
  tableFilter: addTableFilter({
@@ -90,13 +98,22 @@ const table = createTable(data, {
90
98
  export: addDataExport({ format: "json" })
91
99
  });
92
100
  const allCols = {};
93
- $data.forEach((item) => {
94
- Object.keys(item).forEach((key) => {
95
- if (!allCols[key]) {
96
- allCols[key] = {};
101
+ if (columns && Object.keys(columns).length > 0) {
102
+ Object.keys(columns).forEach((key) => {
103
+ if (optionsComponent !== void 0 && key === "optionsColumn") {
104
+ return;
97
105
  }
106
+ allCols[key] = {};
98
107
  });
99
- });
108
+ } else {
109
+ $data.forEach((item) => {
110
+ Object.keys(item).forEach((key) => {
111
+ if (!allCols[key]) {
112
+ allCols[key] = {};
113
+ }
114
+ });
115
+ });
116
+ }
100
117
  Object.keys(allCols).forEach((key) => {
101
118
  $filters = { ...$filters, [key]: {} };
102
119
  });
@@ -226,10 +243,21 @@ const tableColumns = [
226
243
  }
227
244
  })
228
245
  ];
246
+ const getUniqueOptionsColumnId = () => {
247
+ const used = new Set(unexcludedColumns.map((col) => String(col)));
248
+ let id = "optionsColumn";
249
+ let i = 1;
250
+ while (used.has(id)) {
251
+ id = `optionsColumn_${i}`;
252
+ i += 1;
253
+ }
254
+ return id;
255
+ };
229
256
  if (optionsComponent !== void 0) {
257
+ const optionsColumnId = getUniqueOptionsColumnId();
230
258
  tableColumns.push(
231
259
  table.display({
232
- id: "optionsColumn",
260
+ id: optionsColumnId,
233
261
  header: "",
234
262
  plugins: {
235
263
  export: {
@@ -251,7 +279,7 @@ const { filterValue } = pluginStates.tableFilter;
251
279
  const { exportedData } = pluginStates.export;
252
280
  const { pageIndex, pageSize } = pluginStates.page;
253
281
  const { hiddenColumnIds } = pluginStates.hideColumns;
254
- let prevSort = void 0;
282
+ let prevSort = [];
255
283
  const sortServer = (order, id) => {
256
284
  if (!sendModel) throw new Error("Server-side configuration is missing");
257
285
  if (order === void 0) {
@@ -259,19 +287,137 @@ const sortServer = (order, id) => {
259
287
  } else {
260
288
  sendModel.order = [{ column: id, direction: order }];
261
289
  }
262
- if (JSON.stringify(sendModel.order) !== JSON.stringify(prevSort) && prevSort !== void 0) {
290
+ if (JSON.stringify(sendModel.order) !== JSON.stringify(prevSort)) {
263
291
  $pageIndex = 0;
264
292
  $data = [];
265
293
  updateTableWithParams();
266
294
  }
267
- if (order === void 0) {
268
- prevSort = [];
269
- } else {
270
- prevSort = sendModel.order;
271
- }
295
+ prevSort = sendModel.order ? [...sendModel.order] : [];
272
296
  };
273
297
  const updateTableWithParams = async () => {
274
- if ($data.length > 0 && serverSide) {
298
+ if (clientDbEnabled) {
299
+ isFetching = true;
300
+ const filtersNormalized = utils.normalizeFilters($filters);
301
+ const q = sendModel?.q || "";
302
+ const offset2 = $pageSize * $pageIndex;
303
+ const limit = $pageSize;
304
+ if (!_clientDbInstance) {
305
+ _clientDbInstance = new ClientDB(tableId);
306
+ }
307
+ if (!clientDbReady) {
308
+ const source = clientDbInitSource.length > 0 ? clientDbInitSource : $data;
309
+ const getValue = (row, column) => {
310
+ const dot = String(column || "").replaceAll("%%%", ".");
311
+ return row[dot] ?? row[column] ?? row[dot.replaceAll(".", "%%%")];
312
+ };
313
+ const localMatches = (row) => {
314
+ if (q && q.length > 0) {
315
+ const ql = String(q).toLowerCase();
316
+ let found = false;
317
+ for (const k in row) {
318
+ const v = row[k];
319
+ if (v == null) continue;
320
+ if (String(v).toLowerCase().includes(ql)) {
321
+ found = true;
322
+ break;
323
+ }
324
+ }
325
+ if (!found) return false;
326
+ }
327
+ for (const f of filtersNormalized) {
328
+ const actual = getValue(row, f.column);
329
+ const val = f.value;
330
+ if (val == null) continue;
331
+ const aStr = String(actual ?? "").toLowerCase();
332
+ const vStr = String(val ?? "").toLowerCase();
333
+ const aNum = Number(actual);
334
+ const vNum = Number(val);
335
+ const aDate = new Date(actual).getTime();
336
+ const vDate = new Date(val).getTime();
337
+ switch (f.filterBy) {
338
+ case "c":
339
+ if (!aStr.includes(vStr)) return false;
340
+ break;
341
+ case "nc":
342
+ if (aStr.includes(vStr)) return false;
343
+ break;
344
+ case "sw":
345
+ if (!aStr.startsWith(vStr)) return false;
346
+ break;
347
+ case "ew":
348
+ if (!aStr.endsWith(vStr)) return false;
349
+ break;
350
+ case "e":
351
+ if (actual != val) return false;
352
+ break;
353
+ case "ne":
354
+ if (actual == val) return false;
355
+ break;
356
+ case "gt":
357
+ if (Number.isNaN(aNum) || Number.isNaN(vNum) || !(aNum > vNum)) return false;
358
+ break;
359
+ case "lt":
360
+ if (Number.isNaN(aNum) || Number.isNaN(vNum) || !(aNum < vNum)) return false;
361
+ break;
362
+ case "gte":
363
+ if (Number.isNaN(aNum) || Number.isNaN(vNum) || !(aNum >= vNum)) return false;
364
+ break;
365
+ case "lte":
366
+ if (Number.isNaN(aNum) || Number.isNaN(vNum) || !(aNum <= vNum)) return false;
367
+ break;
368
+ case "o":
369
+ if (Number.isNaN(aDate) || Number.isNaN(vDate) || aDate !== vDate) return false;
370
+ break;
371
+ case "sf":
372
+ case "a":
373
+ if (Number.isNaN(aDate) || Number.isNaN(vDate) || !(aDate >= vDate)) return false;
374
+ break;
375
+ case "u":
376
+ case "b":
377
+ if (Number.isNaN(aDate) || Number.isNaN(vDate) || !(aDate <= vDate)) return false;
378
+ break;
379
+ case "no":
380
+ if (Number.isNaN(aDate) || Number.isNaN(vDate) || aDate === vDate) return false;
381
+ break;
382
+ }
383
+ }
384
+ return true;
385
+ };
386
+ const filtered = source.filter(localMatches);
387
+ const order = sendModel?.order || [];
388
+ if (order.length > 0) {
389
+ const { column, direction } = order[0];
390
+ const dir = direction === "desc" ? -1 : 1;
391
+ filtered.sort((a, b) => {
392
+ const av = getValue(a, column);
393
+ const bv = getValue(b, column);
394
+ if (av == null && bv == null) return 0;
395
+ if (av == null) return -1 * dir;
396
+ if (bv == null) return 1 * dir;
397
+ if (typeof av === "number" && typeof bv === "number") return (av - bv) * dir;
398
+ return String(av).localeCompare(String(bv)) * dir;
399
+ });
400
+ }
401
+ const localRows = filtered.slice(offset2, offset2 + limit);
402
+ serverItems?.set(filtered.length);
403
+ data.set(localRows);
404
+ isFetching = false;
405
+ return { rows: localRows, total: filtered.length };
406
+ }
407
+ const res = await _clientDbInstance.query({
408
+ q,
409
+ filters: filtersNormalized,
410
+ order: sendModel?.order || [],
411
+ offset: offset2,
412
+ limit
413
+ });
414
+ const payload = res.payload ? res.payload : res;
415
+ serverItems?.set(payload.total ?? payload.totalCount ?? 0);
416
+ data.set(payload.rows ?? []);
417
+ isFetching = false;
418
+ return payload;
419
+ }
420
+ if ($data.length > 0 && serverSide && Number($serverItemCount) > 0) {
275
421
  console.log("Table is not empty");
276
422
  return;
277
423
  }
@@ -332,6 +478,9 @@ afterUpdate(() => {
332
478
  if (resizable !== "rows" && resizable !== "both") {
333
479
  return;
334
480
  }
481
+ if (!$pageRows || $pageRows.length === 0) {
482
+ return;
483
+ }
335
484
  const e = tableRef?.querySelector(`#${tableId}-row-${$pageRows[0].id}`);
336
485
  if (e) {
337
486
  getDimensions();
@@ -340,10 +489,45 @@ afterUpdate(() => {
340
489
  onDestroy(() => {
341
490
  resizeColumnsObserver.disconnect();
342
491
  resizeRowsObserver.disconnect();
492
+ if (_clientDbInstance) {
493
+ try {
494
+ _clientDbInstance.destroy();
495
+ } catch (e) {
496
+ }
497
+ }
343
498
  });
344
499
  $: sortKeys = pluginStates.sort.sortKeys;
345
- onMount(() => {
346
- if (serverSide) {
500
+ $: serverItemCountValue = clientDbEnabled ? Number($serverItemCount) > 0 ? Math.max(
501
+ Number($serverItemCount),
502
+ initialServerCount,
503
+ clientDbSeedSize,
504
+ clientDbInitSource.length,
505
+ $data.length
506
+ ) : Math.max(initialServerCount, clientDbSeedSize, clientDbInitSource.length, $data.length) : Number($serverItemCount);
507
+ onMount(async () => {
508
+ if (clientDbEnabled) {
509
+ const seed = Array.isArray(clientDbSeedData) ? clientDbSeedData : [];
510
+ const hasSeed = seed.length > 0;
511
+ clientDbSeedSize = seed.length;
512
+ if (hasSeed || $data && $data.length > 0) {
513
+ clientDbInitSource = hasSeed ? [...seed] : [...$data];
514
+ const firstPage = clientDbInitSource.slice(0, $pageSize);
515
+ serverItems?.set(clientDbInitSource.length);
516
+ data.set(firstPage);
517
+ _clientDbInstance = new ClientDB(tableId);
518
+ _clientDbInstance.init(clientDbInitSource).then(async () => {
519
+ const result = await updateTableWithParams();
520
+ clientDbReady = true;
521
+ clientDbInitSource = [];
522
+ return result;
523
+ }).catch(() => {
524
+ clientDbReady = false;
525
+ });
526
+ } else if (!_clientDbInstance) {
527
+ _clientDbInstance = new ClientDB(tableId);
528
+ }
529
+ }
530
+ if (server !== void 0) {
347
531
  updateTableWithParams();
348
532
  }
349
533
  });
@@ -358,14 +542,19 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
358
542
  {#if search}
359
543
  <form
360
544
  class="flex gap-2"
361
- on:submit|preventDefault={() => {
545
+ on:submit|preventDefault={async () => {
362
546
  if (serverSide && !sendModel) {
363
547
  throw new Error('Server-side configuration is missing');
364
548
  } else {
365
549
  sendModel.q = searchValue;
366
550
  }
367
551
 
552
+ $pageIndex = 0;
368
553
  $filterValue = searchValue;
554
+ if (serverSide) {
555
+ $data = [];
556
+ await updateTableWithParams();
557
+ }
369
558
  }}
370
559
  >
371
560
  <div class="relative w-full flex items-center">
@@ -383,15 +572,20 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
383
572
  id="{tableId}-searchReset"
384
573
  class="absolute right-3 items-center"
385
574
  aria-label="Clear search"
386
- on:click|preventDefault={() => {
575
+ on:click|preventDefault={async () => {
387
576
  if (serverSide && !sendModel) {
388
577
  throw new Error('Server-side configuration is missing');
389
578
  } else {
390
579
  sendModel.q = '';
391
580
  }
392
581
 
582
+ $pageIndex = 0;
393
583
  searchValue = '';
394
584
  $filterValue = '';
585
+ if (serverSide) {
586
+ $data = [];
587
+ await updateTableWithParams();
588
+ }
395
589
  }}><Fa icon={faXmark} /></button
396
590
  >
397
591
  </div>
@@ -401,14 +595,19 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
401
595
  id="{tableId}-searchSubmit"
402
596
  class="btn variant-filled-primary"
403
597
  aria-label="Search"
404
- on:click|preventDefault={() => {
598
+ on:click|preventDefault={async () => {
405
599
  if (serverSide && !sendModel) {
406
600
  throw new Error('Server-side configuration is missing');
407
601
  } else {
408
602
  sendModel.q = searchValue;
409
603
  }
410
604
 
605
+ $pageIndex = 0;
411
606
  $filterValue = searchValue;
607
+ if (serverSide) {
608
+ $data = [];
609
+ await updateTableWithParams();
610
+ }
412
611
  }}>Search</button
413
612
  >
414
613
  </form>
@@ -530,7 +729,7 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
530
729
  ? `Remove sorting by ${cell.label} column`
531
730
  : `Sort by ${cell.label} column in ascending order`}
532
731
  >
533
- {cell.render().replaceAll('%%%', '.')}
732
+ {String(cell.render()).replaceAll('%%%', '.')}
534
733
  </span>
535
734
  <div class="w-2">
536
735
  {#if props.sort.order === 'asc'}
@@ -625,7 +824,7 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
625
824
  <TablePaginationServer
626
825
  pageConfig={pluginStates.page}
627
826
  {pageSizes}
628
- itemCount={$serverItemCount}
827
+ itemCount={serverItemCountValue}
629
828
  updateTable={updateTableWithParams}
630
829
  id={tableId}
631
830
  {data}
@@ -16,7 +16,7 @@ let type = "string";
16
16
  let isDate = false;
17
17
  let dropdowns = [];
18
18
  $values.forEach((item) => {
19
- if (item) {
19
+ if (item !== null && item !== void 0) {
20
20
  type = typeof (toFilterableValueFn ? toFilterableValueFn(item) : item);
21
21
  if (type === "object") {
22
22
  if (toFilterableValueFn && toFilterableValueFn(item) instanceof Date) {
@@ -105,6 +105,16 @@ const options = {
105
105
  value: FilterOptionsEnum.no,
106
106
  label: "Is not on"
107
107
  }
108
+ ],
109
+ boolean: [
110
+ {
111
+ value: FilterOptionsEnum.e,
112
+ label: "Is equal to"
113
+ },
114
+ {
115
+ value: FilterOptionsEnum.ne,
116
+ label: "Is not equal to"
117
+ }
108
118
  ]
109
119
  };
110
120
  const popupId = `${tableId}-${id}`;
@@ -129,14 +139,10 @@ const getMissingValue = (value) => {
129
139
  };
130
140
  const optionChangeHandler = (e, index) => {
131
141
  delete $filters[id][dropdowns[index].option];
142
+ const val = dropdowns[index].value;
132
143
  $filters[id] = {
133
144
  ...$filters[id],
134
- [e.target.value]: (
135
- // type === 'number'
136
- // ?
137
- getMissingValue(dropdowns[index].value)
138
- )
139
- // : dropdowns[index].value
145
+ [e.target.value]: type === "boolean" ? val === "" || val === void 0 ? void 0 : getMissingValue(val) === "true" || getMissingValue(val) === true : getMissingValue(val)
140
146
  };
141
147
  $filters = $filters;
142
148
  dropdowns[index] = {
@@ -154,11 +160,7 @@ const valueChangeHandler = (e, index) => {
154
160
  ...$filters,
155
161
  [id]: {
156
162
  ...$filters[id],
157
- [dropdowns[index].option]: (
158
- // type === 'number' ?
159
- getMissingValue(e.target.value)
160
- )
161
- // : dropdowns[index].value
163
+ [dropdowns[index].option]: type === "boolean" ? e.target.value === "" ? void 0 : getMissingValue(e.target.value) === "true" || getMissingValue(e.target.value) === true : getMissingValue(e.target.value)
162
164
  }
163
165
  };
164
166
  };
@@ -265,6 +267,17 @@ onMount(() => {
265
267
  bind:value={dropdown.value}
266
268
  aria-label="Filter value"
267
269
  />
270
+ {:else if type === 'boolean'}
271
+ <select
272
+ class="select border border-primary-500 text-sm p-1"
273
+ on:change={(e) => valueChangeHandler(e, index)}
274
+ bind:value={dropdown.value}
275
+ aria-label="Filter value"
276
+ >
277
+ <option value="" disabled selected>Select value...</option>
278
+ <option value="true">True</option>
279
+ <option value="false">False</option>
280
+ </select>
268
281
  {:else}
269
282
  <input
270
283
  type="date"
@@ -16,8 +16,9 @@ let type = "string";
16
16
  let isDate = false;
17
17
  let dropdowns = [];
18
18
  $values.forEach((item) => {
19
- if (item) {
20
- type = typeof (toFilterableValueFn ? toFilterableValueFn(item) : item);
19
+ if (item !== null && item !== void 0) {
20
+ const rawType = typeof (toFilterableValueFn ? toFilterableValueFn(item) : item);
21
+ type = rawType === "bigint" ? "number" : rawType;
21
22
  if (type === "object") {
22
23
  if ((toFilterableValueFn ? toFilterableValueFn(item) : item) instanceof Date) {
23
24
  isDate = true;
@@ -104,6 +105,16 @@ const options = {
104
105
  // value: FilterOptionsEnum.no,
105
106
  // label: 'Is not on'
106
107
  // }
108
+ ],
109
+ boolean: [
110
+ {
111
+ value: FilterOptionsEnum.e,
112
+ label: "Is equal to"
113
+ },
114
+ {
115
+ value: FilterOptionsEnum.ne,
116
+ label: "Is not equal to"
117
+ }
107
118
  ]
108
119
  };
109
120
  const popupId = `${tableId}-${id}`;
@@ -114,7 +125,8 @@ const popupFeatured = {
114
125
  };
115
126
  const stringValues = $values.map((item) => toStringFn ? toStringFn(item) : item);
116
127
  const missingValues = stringValues.reduce((acc, item, index) => {
117
- acc[typeof item === "string" ? item.toLowerCase() : item] = $values[index];
128
+ const strRepresentation = String(item).toLowerCase();
129
+ acc[strRepresentation] = $values[index];
118
130
  return acc;
119
131
  }, {});
120
132
  const getMissingValue = (value) => {
@@ -122,9 +134,10 @@ const getMissingValue = (value) => {
122
134
  };
123
135
  const optionChangeHandler = (e, index) => {
124
136
  delete $filters[id][dropdowns[index].option];
137
+ const val = dropdowns[index].value;
125
138
  $filters[id] = {
126
139
  ...$filters[id],
127
- [e.target.value]: getMissingValue(dropdowns[index].value)
140
+ [e.target.value]: type === "boolean" ? val === "" || val === void 0 ? void 0 : getMissingValue(val) === "true" || getMissingValue(val) === true : getMissingValue(dropdowns[index].value)
128
141
  };
129
142
  $filters = $filters;
130
143
  dropdowns[index] = {
@@ -142,7 +155,28 @@ const valueChangeHandler = (e, index) => {
142
155
  ...$filters,
143
156
  [id]: {
144
157
  ...$filters[id],
145
- [dropdowns[index].option]: type === "number" ? parseFloat(getMissingValue(e.target.value)) || void 0 : getMissingValue(e.target.value)
158
+ [dropdowns[index].option]: (() => {
159
+ const rawVal = getMissingValue(e.target.value);
160
+ if (rawVal === "" || rawVal === void 0 || rawVal === null) {
161
+ return void 0;
162
+ }
163
+ if (type === "number") {
164
+ const cleanStr = String(rawVal).trim();
165
+ const isBigInt = /^\d+$/.test(cleanStr) && cleanStr.length >= 16;
166
+ if (isBigInt) {
167
+ try {
168
+ return BigInt(cleanStr);
169
+ } catch {
170
+ return cleanStr;
171
+ }
172
+ }
173
+ return parseFloat(cleanStr) || void 0;
174
+ }
175
+ if (type === "boolean") {
176
+ return rawVal === "true" || rawVal === true;
177
+ }
178
+ return rawVal;
179
+ })()
146
180
  }
147
181
  };
148
182
  };
@@ -241,7 +275,7 @@ $: console.log($filters);
241
275
  on:click|preventDefault={() => removeFilter(dropdown.option)}
242
276
  on:keydown|preventDefault={() => removeFilter(dropdown.option)}
243
277
  aria-label="Remove filter"
244
- >
278
+ >
245
279
  <Fa icon={faXmark} />
246
280
  </div>
247
281
  {/if}
@@ -262,6 +296,17 @@ $: console.log($filters);
262
296
  bind:value={dropdown.value}
263
297
  aria-label="Filter value"
264
298
  />
299
+ {:else if type === 'boolean'}
300
+ <select
301
+ class="select border border-primary-500 text-sm p-1"
302
+ on:change={(e) => valueChangeHandler(e, index)}
303
+ bind:value={dropdown.value}
304
+ aria-label="Filter value"
305
+ >
306
+ <option value="" disabled selected>Select value...</option>
307
+ <option value="true">True</option>
308
+ <option value="false">False</option>
309
+ </select>
265
310
  {:else}
266
311
  <input
267
312
  type="date"
@@ -7,6 +7,17 @@ export let pageSizes;
7
7
  export let id;
8
8
  export let updateTable;
9
9
  export let data;
10
+ const toCount = (value) => {
11
+ if (typeof value === "number") return Number.isNaN(value) ? 0 : value;
12
+ const parsed = Number(String(value ?? "").replace(/[^0-9.-]/g, ""));
13
+ return Number.isNaN(parsed) ? 0 : parsed;
14
+ };
15
+ const getEffectiveCount = () => {
16
+ const count = toCount(itemCount);
17
+ if (count > 0) return count;
18
+ return Array.isArray($data) ? $data.length : 0;
19
+ };
20
+ let effectiveCount = 0;
10
21
  let indexInformation = "";
11
22
  const { pageIndex, pageCount, pageSize } = pageConfig;
12
23
  let pageSizeDropdownValue = $pageSize;
@@ -17,17 +28,19 @@ const pageSizePopup = {
17
28
  closeQuery: ".listbox-item"
18
29
  };
19
30
  const getIndexInfomationString = () => {
20
- return itemCount === 0 ? "No items" : `Displaying items ${$pageIndex * $pageSize + 1} - ${Math.min(
31
+ const count = effectiveCount;
32
+ return count === 0 ? "No items" : `Displaying items ${$pageIndex * $pageSize + 1} - ${Math.min(
21
33
  ($pageIndex + 1) * $pageSize,
22
- itemCount
23
- )} of ${Math.min($pageCount * $pageSize, itemCount)}`;
34
+ count
35
+ )} of ${count}`;
24
36
  };
25
37
  function updateTableServer() {
26
38
  $data = [];
27
39
  updateTable();
28
40
  }
41
+ $: effectiveCount = getEffectiveCount();
29
42
  $: paginationSettings = {
30
- size: itemCount,
43
+ size: effectiveCount,
31
44
  limit: $pageSize,
32
45
  page: $pageIndex,
33
46
  amounts: pageSizes
@@ -52,9 +65,12 @@ $: $pageCount, $pageIndex, $pageSize, itemCount, indexInformation = getIndexInfo
52
65
  {#each pageSizes as size}
53
66
  <ListBoxItem
54
67
  bind:group={pageSizeDropdownValue}
55
- name="medium" value={size}
56
- on:click={() => { $pageSize = size; updateTableServer(); }}
57
- >{size}</ListBoxItem
68
+ name="medium"
69
+ value={size}
70
+ on:click={() => {
71
+ $pageSize = size;
72
+ updateTableServer();
73
+ }}>{size}</ListBoxItem
58
74
  >
59
75
  {/each}
60
76
  </ListBox>
@@ -63,7 +79,10 @@ $: $pageCount, $pageIndex, $pageSize, itemCount, indexInformation = getIndexInfo
63
79
  </div>
64
80
  <div class="flex justify-center">
65
81
  <Paginator
66
- on:page={(page) => {$pageIndex = page.detail; updateTableServer(); }}
82
+ on:page={(page) => {
83
+ $pageIndex = page.detail;
84
+ updateTableServer();
85
+ }}
67
86
  settings={paginationSettings}
68
87
  select="hidden"
69
88
  active="!variant-filled-secondary !text-on-secondary-token"
@@ -0,0 +1,22 @@
1
+ export default class ClientDB {
2
+ constructor(tableId: any);
3
+ tableId: any;
4
+ db: any;
5
+ init(rows: any): Promise<{
6
+ tableId: any;
7
+ count: any;
8
+ }>;
9
+ query({ q, filters, order, offset, limit }?: {
10
+ q?: string | undefined;
11
+ filters?: never[] | undefined;
12
+ order?: never[] | undefined;
13
+ offset?: number | undefined;
14
+ limit?: number | undefined;
15
+ }): Promise<{
16
+ tableId: any;
17
+ rows: any[];
18
+ total: number;
19
+ }>;
20
+ clear(): Promise<void>;
21
+ destroy(): void;
22
+ }