@bexis2/bexis2-core-ui 0.4.22 → 0.4.24

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.
package/README.md CHANGED
@@ -1,4 +1,20 @@
1
1
  # bexis-core-ui
2
+ ## 0.4.24
3
+ - Table
4
+ - Adds option for enabling/disabling show/hide column menu in table.
5
+ - Adds option to show number of items displayed instead of number of pages.
6
+ - Fixes an issue where "0" values return empty string.
7
+
8
+ - Facets
9
+ - Fixes an issue with truncation of text in Facet headers and options.
10
+
11
+ ## 0.4.23
12
+ - Table
13
+ - fix resizing issues after page size or page index changes
14
+ - Add Select All and Deselect All in columns menu
15
+ - Convert JSON to CSV and export as CSV
16
+ - Export as JSON to fix special characters and encoding issues
17
+
2
18
  ## 0.4.22
3
19
  - Facets
4
20
  - Replace column class function with more efficient solution
@@ -147,10 +147,14 @@ $: selectedGroups, mapSelected("groups");
147
147
  hyphenOpacity="opacity-0"
148
148
  bind:checked={selectedGroups[group.name]}
149
149
  bind:group={selectedGroups}
150
+ regionSymbol="shrink-0"
150
151
  >
151
- <p class="font-semibold whitespace-nowrap">
152
- {group.displayName}{group.count !== undefined ? ` (${group.count})` : ''}
153
- </p>
152
+ <div class="grid grid-flow-col gap-2">
153
+ <p class="font-semibold whitespace-nowrap truncate" title={group.displayName}>
154
+ {group.displayName}
155
+ </p>
156
+ <span>{group.count !== undefined ? ` (${group.count})` : ''}</span>
157
+ </div>
154
158
 
155
159
  <svelte:fragment slot="children">
156
160
  <!-- If more than 5 choices, show the remaining in the Modal -->
@@ -166,9 +170,9 @@ $: selectedGroups, mapSelected("groups");
166
170
  selection
167
171
  multiple
168
172
  >
169
- <div class="flex gap-2">
170
- <p class="w-max grow truncate">
171
- <span title={item.displayName}>{item.displayName}</span>
173
+ <div class="grid grid-flow-col gap-2">
174
+ <p class="truncate">
175
+ <span class="" title={item.displayName}>{item.displayName}</span>
172
176
  </p>
173
177
  <span>({item.count})</span>
174
178
  </div>
@@ -193,9 +197,9 @@ $: selectedGroups, mapSelected("groups");
193
197
  selection
194
198
  multiple
195
199
  >
196
- <div class="flex gap-2">
197
- <p class="w-max grow truncate">
198
- <span title={item.displayName}>{item.displayName}</span>
200
+ <div class="grid grid-flow-col gap-2">
201
+ <p class="truncate">
202
+ <span class="" title={item.displayName}>{item.displayName}</span>
199
203
  </p>
200
204
  <span>({item.count})</span>
201
205
  </div>
@@ -1,32 +1,58 @@
1
- <script>import { popup } from "@skeletonlabs/skeleton";
1
+ <script>import Fa from "svelte-fa";
2
+ import { faEye } from "@fortawesome/free-solid-svg-icons";
3
+ import { popup } from "@skeletonlabs/skeleton";
2
4
  export let columns = [];
3
5
  export let tableId;
4
6
  const popupCombobox = {
5
7
  event: "click",
6
8
  target: `${tableId}-columns-menu`,
7
- placement: "bottom"
9
+ placement: "bottom",
10
+ closeQuery: ""
11
+ };
12
+ const selectAll = () => {
13
+ columns = columns.map((column) => ({ ...column, visible: true }));
14
+ };
15
+ const deselectAll = () => {
16
+ columns = columns.map((column) => ({ ...column, visible: false }));
17
+ columns[0].visible = true;
8
18
  };
9
19
  </script>
10
20
 
11
21
  <button
12
22
  type="button"
13
- title="Hide or show columns"
14
- class="btn btn-sm variant-filled-primary rounded-full order-last"
23
+ class="btn btn-sm variant-filled-primary rounded-full order-last gap-2"
15
24
  aria-label="Open menu to hide/show columns"
16
- use:popup={popupCombobox}>Columns</button
25
+ use:popup={popupCombobox}><Fa icon={faEye} /> Columns</button
17
26
  >
18
-
19
27
  <div
20
- class="bg-white dark:bg-surface-500 p-4 rounded-md shadow-md z-10"
28
+ class="bg-white dark:bg-surface-500 p-4 px-5 rounded-md shadow-md z-10 border border-primary-500"
21
29
  data-popup="{tableId}-columns-menu"
22
30
  >
31
+ <div class="flex items-center gap-4 pb-5 grow justify-between">
32
+ <button
33
+ on:click|preventDefault={selectAll}
34
+ type="button"
35
+ class="btn p-0 text-sm grow underline text-primary-600"
36
+ >
37
+ Select All
38
+ </button>
39
+ <div class="border border-r border-neutral-200 h-6" />
40
+ <button
41
+ on:click|preventDefault={deselectAll}
42
+ type="button"
43
+ class="btn p-0 text-sm grow underline text-neutral-500"
44
+ >
45
+ Deselect All
46
+ </button>
47
+ </div>
23
48
  {#each columns as column}
24
49
  <div class="flex gap-3 items-center">
25
50
  <label for={column.id} class="cursor-pointer" title={column.label}></label>
26
51
  <input
27
52
  aria-label={`${column.visible ? 'Hide' : 'Show'} ${column.label} column`}
28
53
  type="checkbox"
29
- id = {column.id}
54
+ class="checkbox"
55
+ id={column.id}
30
56
  bind:checked={column.visible}
31
57
  title={`${column.visible ? 'Hide' : 'Show'} ${column.label} column`}
32
58
  disabled={columns.filter((c) => c.visible).length === 1 && column.visible}
@@ -35,5 +61,5 @@ const popupCombobox = {
35
61
  </div>
36
62
  {/each}
37
63
 
38
- <div class="arrow bg-white dark:bg-surface-500" />
64
+ <div class="arrow bg-white dark:bg-surface-500 border-l border-t border-primary-500" />
39
65
  </div>
@@ -1,7 +1,7 @@
1
- <script>import { createEventDispatcher } from "svelte";
1
+ <script>import { afterUpdate, createEventDispatcher, onDestroy } from "svelte";
2
2
  import { readable, writable } from "svelte/store";
3
3
  import Fa from "svelte-fa";
4
- import { faXmark } from "@fortawesome/free-solid-svg-icons";
4
+ import { faCompress, faDownload, faXmark } from "@fortawesome/free-solid-svg-icons";
5
5
  import { createTable, Subscribe, Render, createRender } from "svelte-headless-table";
6
6
  import {
7
7
  addSortBy,
@@ -21,16 +21,9 @@ 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 * as utils from "./utils";
24
25
  import { columnFilter, searchFilter } from "./filter";
25
- import {
26
- cellStyle,
27
- exportAsCsv,
28
- fixedWidth,
29
- normalizeFilters,
30
- resetResize,
31
- convertServerColumns
32
- } from "./shared";
33
- import { Receive, Send } from "../../models/Models";
26
+ import { Send } from "../../models/Models";
34
27
  export let config;
35
28
  let {
36
29
  id: tableId,
@@ -39,6 +32,8 @@ let {
39
32
  // Data store
40
33
  columns,
41
34
  // Column configuration
35
+ showColumnsMenu = false,
36
+ // Whether to display the columns menu
42
37
  resizable = "none",
43
38
  // Resizability config
44
39
  height = null,
@@ -55,6 +50,8 @@ let {
55
50
  // Whether to display the search input
56
51
  pageSizes = [5, 10, 20, 50, 100],
57
52
  // Page sizes to display in the pagination component
53
+ pageIndexStringType = "pages",
54
+ // pages by default
58
55
  fitToScreen = true,
59
56
  // Whether to fit the table to the screen,
60
57
  exportable = false,
@@ -63,11 +60,14 @@ let {
63
60
  } = config;
64
61
  let searchValue = "";
65
62
  let isFetching = false;
63
+ let tableRef;
66
64
  const serverSide = server !== void 0;
67
- const { baseUrl, entityId, versionId, sendModel = new Send() } = server ?? {};
65
+ const { sendModel = new Send() } = server ?? {};
68
66
  const filters = writable({});
69
67
  const dispatch = createEventDispatcher();
70
68
  const actionDispatcher = (obj) => dispatch("action", obj);
69
+ const rowHeights = writable({});
70
+ const colWidths = writable([]);
71
71
  const serverItems = serverSide ? writable(0) : void 0;
72
72
  const serverItemCount = serverSide ? readable(0, (set) => {
73
73
  serverItems.subscribe((val) => set(val));
@@ -89,7 +89,7 @@ const table = createTable(data, {
89
89
  serverItemCount
90
90
  }),
91
91
  expand: addExpandedRows(),
92
- export: addDataExport({ format: "csv" })
92
+ export: addDataExport({ format: "json" })
93
93
  });
94
94
  const allCols = {};
95
95
  $data.forEach((item) => {
@@ -165,7 +165,7 @@ const tableColumns = [
165
165
  id,
166
166
  tableId,
167
167
  values,
168
- updateTable,
168
+ updateTable: updateTableWithParams,
169
169
  pageIndex,
170
170
  toFilterableValueFn,
171
171
  filters,
@@ -195,7 +195,7 @@ const tableColumns = [
195
195
  header: key,
196
196
  accessor,
197
197
  cell: ({ value }) => {
198
- return value ? value : "";
198
+ return value ?? "";
199
199
  },
200
200
  plugins: {
201
201
  // Sorting enabled by default
@@ -208,7 +208,7 @@ const tableColumns = [
208
208
  id,
209
209
  tableId,
210
210
  values,
211
- updateTable,
211
+ updateTable: updateTableWithParams,
212
212
  pageIndex,
213
213
  filters
214
214
  }) : createRender(TableFilter, {
@@ -246,57 +246,11 @@ if (optionsComponent !== void 0) {
246
246
  );
247
247
  }
248
248
  const createdTableColumns = table.createColumns(tableColumns);
249
- const { headerRows, pageRows, tableAttrs, tableBodyAttrs, pluginStates } = table.createViewModel(createdTableColumns);
249
+ const { headerRows, pageRows, tableAttrs, tableBodyAttrs, pluginStates, rows } = table.createViewModel(createdTableColumns);
250
250
  const { filterValue } = pluginStates.tableFilter;
251
251
  const { exportedData } = pluginStates.export;
252
252
  const { pageIndex, pageSize } = pluginStates.page;
253
253
  const { hiddenColumnIds } = pluginStates.hideColumns;
254
- const updateTable = async () => {
255
- if (!sendModel) throw new Error("Server-side configuration is missing");
256
- sendModel.limit = $pageSize;
257
- sendModel.offset = $pageSize * $pageIndex;
258
- sendModel.version = versionId || -1;
259
- sendModel.id = entityId || -1;
260
- sendModel.filter = normalizeFilters($filters);
261
- let fetchData;
262
- try {
263
- isFetching = true;
264
- fetchData = await fetch(baseUrl || "", {
265
- headers: {
266
- "Content-Type": "application/json"
267
- },
268
- method: "POST",
269
- body: JSON.stringify(sendModel)
270
- });
271
- } catch (error) {
272
- throw new Error(`Network error: ${error.message}`);
273
- } finally {
274
- isFetching = false;
275
- }
276
- if (!fetchData.ok) {
277
- throw new Error("Failed to fetch data");
278
- }
279
- const response = await fetchData.json();
280
- if (response.columns !== void 0) {
281
- columns = convertServerColumns(response.columns, columns);
282
- const clientCols = response.columns.reduce((acc, col) => {
283
- acc[col.key] = col.column;
284
- return acc;
285
- }, {});
286
- const tmpArr = [];
287
- response.data.forEach((row, index) => {
288
- const tmp = {};
289
- Object.keys(row).forEach((key) => {
290
- tmp[clientCols[key]] = row[key];
291
- });
292
- tmpArr.push(tmp);
293
- });
294
- dispatch("fetch", columns);
295
- $data = tmpArr;
296
- }
297
- $serverItems = response.count;
298
- return response;
299
- };
300
254
  const sortServer = (order, id) => {
301
255
  if (!sendModel) throw new Error("Server-side configuration is missing");
302
256
  if (order === void 0) {
@@ -305,10 +259,76 @@ const sortServer = (order, id) => {
305
259
  sendModel.order = [{ column: id, direction: order }];
306
260
  }
307
261
  $pageIndex = 0;
308
- updateTable();
262
+ updateTableWithParams();
309
263
  };
264
+ const updateTableWithParams = async () => {
265
+ isFetching = true;
266
+ const result = await utils.updateTable(
267
+ $pageSize,
268
+ $pageIndex,
269
+ server,
270
+ $filters,
271
+ data,
272
+ serverItems,
273
+ columns,
274
+ dispatch
275
+ );
276
+ isFetching = false;
277
+ return result;
278
+ };
279
+ const getDimensions = () => {
280
+ if (!tableRef) return;
281
+ if (resizable === "none") return;
282
+ else if (resizable === "columns") {
283
+ observeHeaderColumns();
284
+ } else if (resizable === "rows") {
285
+ observeFirstCells();
286
+ } else {
287
+ observeHeaderColumns();
288
+ observeFirstCells();
289
+ }
290
+ };
291
+ const resizeRowsObserver = new ResizeObserver(() => {
292
+ utils.getMaxCellHeightInRow(
293
+ tableRef,
294
+ resizable,
295
+ optionsComponent,
296
+ rowHeights,
297
+ tableId,
298
+ rowHeight
299
+ );
300
+ });
301
+ const resizeColumnsObserver = new ResizeObserver(() => {
302
+ utils.getMinCellWidthInColumn(tableRef, colWidths, $headerRows[0].cells.length, resizable);
303
+ });
304
+ const observeFirstCells = () => {
305
+ if (!tableRef) return;
306
+ tableRef.querySelectorAll("tbody tr td:first-child").forEach((cell) => {
307
+ resizeRowsObserver.observe(cell);
308
+ });
309
+ return resizeRowsObserver;
310
+ };
311
+ const observeHeaderColumns = () => {
312
+ if (!tableRef) return;
313
+ tableRef.querySelectorAll("thead tr th").forEach((cell) => {
314
+ resizeColumnsObserver.observe(cell);
315
+ });
316
+ };
317
+ afterUpdate(() => {
318
+ if (resizable !== "rows" && resizable !== "both") {
319
+ return;
320
+ }
321
+ const e = tableRef?.querySelector(`#${tableId}-row-${$pageRows[0].id}`);
322
+ if (e) {
323
+ getDimensions();
324
+ }
325
+ });
326
+ onDestroy(() => {
327
+ resizeColumnsObserver.disconnect();
328
+ resizeRowsObserver.disconnect();
329
+ });
310
330
  $: sortKeys = pluginStates.sort.sortKeys;
311
- $: serverSide && updateTable();
331
+ $: serverSide && updateTableWithParams();
312
332
  $: serverSide && sortServer($sortKeys[0]?.order, $sortKeys[0]?.id);
313
333
  $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => col.id);
314
334
  </script>
@@ -377,7 +397,8 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
377
397
  {/if}
378
398
 
379
399
  <div
380
- class="flex justify-between items-center w-full {search && 'py-2'} {!search &&
400
+ class="flex justify-between overflow-x-auto items-center w-full {search &&
401
+ 'py-2'} {!search &&
381
402
  (shownColumns.length > 0 || toggle || resizable !== 'none' || exportable) &&
382
403
  'pb-2'}"
383
404
  >
@@ -404,25 +425,26 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
404
425
  {#if resizable !== 'none'}
405
426
  <button
406
427
  type="button"
407
- title="Reset column and row sizing"
408
- class="btn btn-sm variant-filled-primary rounded-full order-last"
428
+ class="btn btn-sm variant-filled-primary rounded-full order-last flex gap-2 items-center"
409
429
  aria-label="Reset sizing of columns and rows"
410
430
  on:click|preventDefault={() =>
411
- resetResize($headerRows, $pageRows, tableId, columns, resizable)}
412
- >Reset sizing</button
431
+ utils.resetResize($headerRows, $pageRows, tableId, columns, resizable)}
432
+ ><Fa icon={faCompress} /> Reset sizing</button
413
433
  >
414
434
  {/if}
435
+ <!-- Enable export as CSV button if exportable === true -->
415
436
  {#if exportable}
416
437
  <button
417
438
  type="button"
418
- title="Export table data as CSV"
419
- class="btn btn-sm variant-filled-primary rounded-full order-last"
439
+ class="btn btn-sm variant-filled-primary rounded-full order-last flex items-center gap-2"
420
440
  aria-label="Export table data as CSV"
421
- on:click|preventDefault={() => exportAsCsv(tableId, $exportedData)}
422
- >Export as CSV</button
441
+ on:click|preventDefault={() =>
442
+ utils.exportAsCsv(tableId, utils.jsonToCsv($exportedData))}
443
+ ><Fa icon={faDownload} /> Export as CSV</button
423
444
  >
424
445
  {/if}
425
- {#if shownColumns.length > 0}
446
+ <!-- Enable show/hide columns menu if showColumnsMenu === true -->
447
+ {#if showColumnsMenu && shownColumns.length > 0}
426
448
  <ColumnsMenu bind:columns={shownColumns} {tableId} />
427
449
  {/if}
428
450
  </div>
@@ -430,6 +452,7 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
430
452
 
431
453
  <div class="overflow-auto" style="height: {height}px">
432
454
  <table
455
+ bind:this={tableRef}
433
456
  {...$tableAttrs}
434
457
  class="table table-auto table-compact bg-tertiary-500/30 dark:bg-tertiary-900/10 overflow-clip"
435
458
  id="{tableId}-table"
@@ -446,14 +469,29 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
446
469
  let:rowProps
447
470
  >
448
471
  <tr {...rowAttrs} class="bg-primary-300 dark:bg-primary-800">
449
- {#each headerRow.cells as cell (cell.id)}
472
+ {#each headerRow.cells as cell, index (cell.id)}
450
473
  <Subscribe attrs={cell.attrs()} props={cell.props()} let:props let:attrs>
451
- <th scope="col" class="!p-2" {...attrs} style={cellStyle(cell.id, columns)}>
474
+ <th
475
+ scope="col"
476
+ class="!p-2"
477
+ {...attrs}
478
+ style={`
479
+ width: ${cell.isData() ? 'auto' : '0'};
480
+ ${utils.cellStyle(cell.id, columns)}
481
+ `}
482
+ >
452
483
  <div
453
484
  class="overflow-auto"
454
485
  class:resize-x={(resizable === 'columns' || resizable === 'both') &&
455
- !fixedWidth(cell.id, columns)}
486
+ !utils.fixedWidth(cell.id, columns)}
456
487
  id="th-{tableId}-{cell.id}"
488
+ style={`
489
+ min-width: ${
490
+ utils.minWidth(cell.id, columns)
491
+ ? utils.minWidth(cell.id, columns)
492
+ : $colWidths[index]
493
+ }px;
494
+ `}
457
495
  >
458
496
  <div class="flex justify-between items-center">
459
497
  <div class="flex gap-1 whitespace-pre-wrap">
@@ -504,20 +542,34 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
504
542
  <tr {...rowAttrs} id="{tableId}-row-{row.id}" class="">
505
543
  {#each row.cells as cell, index (cell?.id)}
506
544
  <Subscribe attrs={cell.attrs()} let:attrs>
507
- <td {...attrs} class="!p-2">
545
+ <td {...attrs} class="">
508
546
  <div
509
- class=" overflow-auto h-max {index === 0 &&
547
+ class=" h-full {index === 0 &&
510
548
  (resizable === 'rows' || resizable === 'both')
511
- ? 'resize-y'
512
- : ''}"
549
+ ? 'resize-y overflow-auto'
550
+ : 'block'}"
513
551
  id="{tableId}-{cell.id}-{row.id}"
552
+ style={utils.getResizeStyles($rowHeights, row.id, index)}
514
553
  >
515
554
  <!-- Adding config for initial rowHeight, if provided -->
516
555
  <div
517
- class="flex items-center overflow-auto"
518
- style="height: {rowHeight ? `${rowHeight}px` : 'auto'};"
556
+ class="flex items-start overflow-auto"
557
+ style={`
558
+ max-height: ${$rowHeights && $rowHeights[+row.id] ? `${$rowHeights[+row.id].max}px` : 'auto'};
559
+ `}
519
560
  >
520
- <div class="grow h-full"><Render of={cell.render()} /></div>
561
+ <div
562
+ class="grow overflow-auto"
563
+ style={cell.isData()
564
+ ? `width: ${
565
+ utils.minWidth(cell.id, columns)
566
+ ? utils.minWidth(cell.id, columns)
567
+ : $colWidths[index]
568
+ }px;`
569
+ : 'max-width: min-content;'}
570
+ >
571
+ <Render of={cell.render()} />
572
+ </div>
521
573
  </div>
522
574
  </div>
523
575
  </td>
@@ -554,12 +606,19 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
554
606
  {pageIndex}
555
607
  {pageSize}
556
608
  {serverItemCount}
557
- {updateTable}
609
+ updateTable={updateTableWithParams}
558
610
  {pageSizes}
611
+ {pageIndexStringType}
559
612
  id={tableId}
560
613
  />
561
614
  {:else}
562
- <TablePagination pageConfig={pluginStates.page} {pageSizes} id={tableId} />
615
+ <TablePagination
616
+ itemCount={$rows.length}
617
+ pageConfig={pluginStates.page}
618
+ {pageSizes}
619
+ id={tableId}
620
+ {pageIndexStringType}
621
+ />
563
622
  {/if}
564
623
  {/if}
565
624
  </div>
@@ -6,7 +6,6 @@ declare const __propDef: {
6
6
  };
7
7
  events: {
8
8
  action: CustomEvent<any>;
9
- fetch: CustomEvent<any>;
10
9
  } & {
11
10
  [evt: string]: CustomEvent<any>;
12
11
  };
@@ -7,9 +7,12 @@ import {
7
7
  faChevronDown
8
8
  } from "@fortawesome/free-solid-svg-icons";
9
9
  import { ListBox, ListBoxItem, popup } from "@skeletonlabs/skeleton";
10
+ export let itemCount;
10
11
  export let pageConfig;
11
12
  export let pageSizes;
13
+ export let pageIndexStringType;
12
14
  export let id;
15
+ let indexInformation = "";
13
16
  const { pageIndex, pageCount, pageSize, hasNextPage, hasPreviousPage } = pageConfig;
14
17
  const goToFirstPage = () => $pageIndex = 0;
15
18
  const goToLastPage = () => $pageIndex = $pageCount - 1;
@@ -32,11 +35,22 @@ const pageSizePopup = {
32
35
  placement: "bottom",
33
36
  closeQuery: ".listbox-item"
34
37
  };
38
+ const getIndexInfomationString = () => {
39
+ if (pageIndexStringType === "pages") {
40
+ return $pageCount > 0 ? `Page ${$pageIndex + 1} of ${$pageCount}` : "No pages";
41
+ } else {
42
+ return itemCount === 0 ? "No items" : `Displaying items ${$pageIndex * $pageSize + 1} - ${Math.min(
43
+ ($pageIndex + 1) * $pageSize,
44
+ itemCount
45
+ )} of ${Math.min($pageCount * $pageSize, itemCount)}`;
46
+ }
47
+ };
35
48
  $: goToFirstPageDisabled = !$pageIndex;
36
49
  $: goToLastPageDisabled = $pageIndex == $pageCount - 1;
37
50
  $: goToNextPageDisabled = !$hasNextPage;
38
51
  $: goToPreviousPageDisabled = !$hasPreviousPage;
39
52
  $: $pageSize = pageSizeDropdownValue;
53
+ $: $pageCount, $pageIndex, $pageSize, indexInformation = getIndexInfomationString();
40
54
  </script>
41
55
 
42
56
  <div class="flex justify-between w-full items-stretch gap-10">
@@ -114,12 +128,6 @@ $: $pageSize = pageSizeDropdownValue;
114
128
  >
115
129
  </div>
116
130
  <div class="flex justify-end items-center">
117
- <span class="text-sm text-gray-500">
118
- {#if $pageCount > 0}
119
- Page {$pageIndex + 1} of {$pageCount}
120
- {:else}
121
- No pages
122
- {/if}
123
- </span>
131
+ <span class="text-sm text-gray-500">{indexInformation}</span>
124
132
  </div>
125
133
  </div>
@@ -1,8 +1,10 @@
1
1
  import { SvelteComponent } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
+ itemCount: any;
4
5
  pageConfig: any;
5
6
  pageSizes: any;
7
+ pageIndexStringType: any;
6
8
  id: any;
7
9
  };
8
10
  events: {
@@ -8,6 +8,7 @@ import {
8
8
  export let id;
9
9
  export let pageIndex;
10
10
  export let pageSize;
11
+ export let pageIndexStringType;
11
12
  export let pageSizes;
12
13
  export let serverItemCount;
13
14
  export let updateTable;
@@ -15,6 +16,7 @@ let goToFirstPageDisabled = true;
15
16
  let goToLastPageDisabled = true;
16
17
  let goToNextPageDisabled = true;
17
18
  let goToPreviousPageDisabled = true;
19
+ let indexInformation = "";
18
20
  const handleChange = (e) => {
19
21
  const value = e.target.value;
20
22
  if (value > pageCount) {
@@ -45,12 +47,20 @@ const goTo = (dst) => {
45
47
  }
46
48
  updateTable();
47
49
  };
50
+ const getIndexInfomationString = () => {
51
+ if (pageIndexStringType === "pages") {
52
+ return pageCount > 0 ? `Page ${$pageIndex + 1} of ${pageCount}` : "No pages";
53
+ } else {
54
+ return `Showing ${$pageIndex * $pageSize + 1} - ${($pageIndex + 1) * $pageSize} of ${pageCount * $pageSize} items`;
55
+ }
56
+ };
48
57
  $: pageCount = Math.ceil($serverItemCount / $pageSize);
49
58
  $: goToFirstPageDisabled = !$pageIndex;
50
59
  $: goToLastPageDisabled = $pageIndex == pageCount - 1;
51
60
  $: goToNextPageDisabled = $pageIndex == pageCount - 1;
52
61
  $: goToPreviousPageDisabled = !$pageIndex;
53
62
  $: $pageSize && updateTable();
63
+ $: pageCount, $pageIndex, $pageSize, indexInformation = getIndexInfomationString();
54
64
  updateTable();
55
65
  </script>
56
66
 
@@ -113,15 +123,7 @@ updateTable();
113
123
  </div>
114
124
  <div class="flex justify-end items-center">
115
125
  <span class="text-sm text-gray-500">
116
- {#if pageCount > 0}
117
- {#if pageCount == 1}
118
- 1 page
119
- {:else}
120
- {pageCount} pages
121
- {/if}
122
- {:else}
123
- No pages
124
- {/if}
126
+ {indexInformation}
125
127
  </span>
126
128
  </div>
127
129
  </div>
@@ -4,6 +4,7 @@ declare const __propDef: {
4
4
  id: any;
5
5
  pageIndex: any;
6
6
  pageSize: any;
7
+ pageIndexStringType: any;
7
8
  pageSizes: any;
8
9
  serverItemCount: any;
9
10
  updateTable: any;