@bexis2/bexis2-core-ui 0.4.8 → 0.4.10

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 (57) hide show
  1. package/README.md +12 -0
  2. package/dist/components/CodeEditor/CodeEditor.svelte +1 -2
  3. package/dist/components/CodeEditor/CodeEditor.svelte.d.ts +8 -8
  4. package/dist/components/Facets/Facets.svelte +108 -0
  5. package/dist/components/Facets/Facets.svelte.d.ts +24 -0
  6. package/dist/components/Facets/ShowMore.svelte +75 -0
  7. package/dist/components/Facets/ShowMore.svelte.d.ts +21 -0
  8. package/dist/components/File/FileUploader.svelte +3 -6
  9. package/dist/components/File/FileUploader.svelte.d.ts +5 -5
  10. package/dist/components/Table/ColumnsMenu.svelte +33 -0
  11. package/dist/components/Table/ColumnsMenu.svelte.d.ts +21 -0
  12. package/dist/components/Table/Table.svelte +1 -3
  13. package/dist/components/Table/Table.svelte.d.ts +12 -1
  14. package/dist/components/Table/TableContent.svelte +49 -36
  15. package/dist/components/Table/TableFilter.svelte +20 -15
  16. package/dist/components/Table/TableFilterServer.svelte +10 -12
  17. package/dist/components/Table/TablePagination.svelte +35 -13
  18. package/dist/components/Table/TablePaginationServer.svelte +7 -13
  19. package/dist/components/Table/shared.d.ts +2 -19
  20. package/dist/components/form/Checkbox.svelte.d.ts +3 -3
  21. package/dist/components/form/CheckboxKvPList.svelte.d.ts +2 -2
  22. package/dist/components/form/CheckboxList.svelte.d.ts +1 -1
  23. package/dist/components/form/DateInput.svelte.d.ts +9 -9
  24. package/dist/components/form/InputContainer.svelte.d.ts +3 -3
  25. package/dist/components/form/NumberInput.svelte.d.ts +10 -10
  26. package/dist/components/form/TextArea.svelte.d.ts +10 -10
  27. package/dist/components/form/TextInput.svelte.d.ts +10 -10
  28. package/dist/components/page/Alert.svelte +1 -2
  29. package/dist/components/page/Alert.svelte.d.ts +4 -4
  30. package/dist/components/page/Docs.svelte.d.ts +1 -1
  31. package/dist/components/page/Footer.svelte +1 -2
  32. package/dist/components/page/Header.svelte +1 -2
  33. package/dist/components/page/HelpPopUp.svelte +4 -6
  34. package/dist/components/page/HelpPopUp.svelte.d.ts +1 -1
  35. package/dist/components/page/Notification.svelte +2 -4
  36. package/dist/components/page/Page.svelte.d.ts +8 -8
  37. package/dist/components/page/Spinner.svelte.d.ts +3 -3
  38. package/dist/components/page/TablePlaceholder.svelte.d.ts +2 -2
  39. package/dist/components/page/breadcrumb/Breadcrumb.svelte +5 -8
  40. package/dist/components/toggle/Toggle.svelte +7 -14
  41. package/dist/components/toggle/Toggle.svelte.d.ts +9 -8
  42. package/dist/models/Models.d.ts +14 -6
  43. package/dist/stores/apiStores.d.ts +0 -1
  44. package/dist/stores/pageStores.d.ts +0 -1
  45. package/package.json +114 -114
  46. package/src/lib/components/Facets/Facets.svelte +120 -0
  47. package/src/lib/components/Facets/ShowMore.svelte +87 -0
  48. package/src/lib/components/Table/ColumnsMenu.svelte +37 -0
  49. package/src/lib/components/Table/TableContent.svelte +167 -141
  50. package/src/lib/components/Table/TableFilter.svelte +17 -7
  51. package/src/lib/components/Table/TableFilterServer.svelte +6 -3
  52. package/src/lib/components/Table/TablePagination.svelte +33 -5
  53. package/src/lib/components/Table/TablePaginationServer.svelte +1 -1
  54. package/src/lib/models/Models.ts +18 -7
  55. /package/src/lib/components/{file → File}/FileIcon.svelte +0 -0
  56. /package/src/lib/components/{file → File}/FileInfo.svelte +0 -0
  57. /package/src/lib/components/{file → File}/FileUploader.svelte +0 -0
package/README.md CHANGED
@@ -1,4 +1,16 @@
1
1
  # bexis-core-ui
2
+ ## 0.4.10
3
+ - Table:
4
+ - Fixes issue with sticky Tables not rendering the filters correctly.
5
+ - Fixes issues related to date picker in Tables with date filters.
6
+ - Updates default Table page sizes to [5, 10, 20, 50, 100].
7
+ - Updates the structure of server-side configuration for Tables.
8
+ - Adds new page size dropdown in Table for to fix contrast issues in the component.
9
+ - Adds showing/hiding Table columns.
10
+
11
+ - Facets:
12
+ - Adds Facets component.
13
+
2
14
  ## 0.4.8
3
15
  - page
4
16
  - add notification if api call to backend faild
@@ -53,8 +53,7 @@ const isValidJS = (str) => {
53
53
  }
54
54
  return true;
55
55
  };
56
- $:
57
- isValid = language === "json" ? isValidJSON(value) : language === "js" ? isValidJS(value) : true;
56
+ $: isValid = language === "json" ? isValidJSON(value) : language === "js" ? isValidJS(value) : true;
58
57
  </script>
59
58
 
60
59
  <div class="grid items-stretch justify-stretch gap-1">
@@ -2,14 +2,14 @@ import { SvelteComponent } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
4
  id: string;
5
- title?: string | undefined;
6
- initialValue?: string | undefined;
7
- value?: string | undefined;
8
- language?: string | undefined;
9
- dark?: boolean | undefined;
10
- toggle?: boolean | undefined;
11
- actions?: boolean | undefined;
12
- isValid?: boolean | undefined;
5
+ title?: string;
6
+ initialValue?: string;
7
+ value?: string;
8
+ language?: string;
9
+ dark?: boolean;
10
+ toggle?: boolean;
11
+ actions?: boolean;
12
+ isValid?: boolean;
13
13
  styles?: any;
14
14
  };
15
15
  events: {
@@ -0,0 +1,108 @@
1
+ <script>import { getModalStore, Modal, TreeView, TreeViewItem } from "@skeletonlabs/skeleton";
2
+ import ShowMore from "./ShowMore.svelte";
3
+ export let groupSelection = false;
4
+ export let groups;
5
+ export let selected;
6
+ export let selectedGroups = {};
7
+ export let showAll = false;
8
+ export let open = false;
9
+ const modalStore = getModalStore();
10
+ const showMore = (group) => {
11
+ modalStore.trigger({
12
+ type: "component",
13
+ title: `${group}`,
14
+ component: {
15
+ ref: ShowMore,
16
+ props: {
17
+ group,
18
+ handleSave,
19
+ handleCancel,
20
+ selected: selected[group],
21
+ items: groups[group].sort((a, b) => a.value.localeCompare(b.value))
22
+ }
23
+ }
24
+ });
25
+ };
26
+ const handleSave = (group, selectedItems) => {
27
+ selected[group] = selectedItems;
28
+ modalStore.close();
29
+ };
30
+ const handleCancel = () => {
31
+ modalStore.close();
32
+ };
33
+ const sortOptions = () => {
34
+ Object.keys(groups).forEach((group) => {
35
+ groups[group] = [
36
+ ...selected[group].sort((a, b) => {
37
+ if (a.count != void 0 && b.count != void 0) {
38
+ return b.count - a.count;
39
+ }
40
+ return a.value.localeCompare(b.value);
41
+ }),
42
+ ...groups[group].filter((item) => !selected[group].includes(item)).sort((a, b) => {
43
+ if (a.count != void 0 && b.count != void 0) {
44
+ return b.count - a.count;
45
+ }
46
+ return a.value.localeCompare(b.value);
47
+ })
48
+ ];
49
+ });
50
+ };
51
+ $: selected, sortOptions();
52
+ </script>
53
+
54
+ <TreeView selection={groupSelection} multiple={groupSelection} padding="p-1" hover="">
55
+ {#each Object.keys(groups) as group}
56
+ <TreeViewItem
57
+ name="groups"
58
+ value={group}
59
+ {open}
60
+ hyphenOpacity="opacity-0"
61
+ bind:group={selectedGroups}
62
+ bind:checked={selectedGroups[group]}
63
+ >
64
+ <p class="font-semibold">{group}</p>
65
+
66
+ <svelte:fragment slot="children">
67
+ <!-- If more than 5 choices, show the remaining in the Modal -->
68
+ {#if !showAll}
69
+ {#each groups[group].slice(0, 5) as item}
70
+ <TreeViewItem
71
+ bind:group={selected[group]}
72
+ name={group}
73
+ value={item}
74
+ hyphenOpacity="opacity-0"
75
+ spacing="space-x-3"
76
+ selection
77
+ multiple
78
+ >
79
+ <p>{item.value} ({item.count})</p>
80
+ </TreeViewItem>
81
+ {/each}
82
+ <!-- Trigger for the Modal to view all options -->
83
+ {#if groups[group].length > 5}
84
+ <TreeViewItem hyphenOpacity="opacity-0">
85
+ <button class="anchor" on:click={() => showMore(group)}>more</button></TreeViewItem
86
+ >
87
+ {/if}
88
+ {:else}
89
+ {#each groups[group] as item}
90
+ <TreeViewItem
91
+ bind:group={selected[group]}
92
+ name={group}
93
+ value={item}
94
+ hyphenOpacity="opacity-0"
95
+ spacing="space-x-3"
96
+ selection
97
+ multiple
98
+ >
99
+ <p>{item.value} ({item.count})</p>
100
+ </TreeViewItem>
101
+ {/each}
102
+ {/if}
103
+ </svelte:fragment>
104
+ </TreeViewItem>
105
+ {/each}
106
+ </TreeView>
107
+
108
+ <Modal />
@@ -0,0 +1,24 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { FacetGroup } from '../../models/Models';
3
+ declare const __propDef: {
4
+ props: {
5
+ groupSelection?: boolean;
6
+ groups: FacetGroup;
7
+ selected: FacetGroup;
8
+ selectedGroups?: {
9
+ [key: string]: boolean;
10
+ };
11
+ showAll?: boolean;
12
+ open?: boolean;
13
+ };
14
+ events: {
15
+ [evt: string]: CustomEvent<any>;
16
+ };
17
+ slots: {};
18
+ };
19
+ export type FacetsProps = typeof __propDef.props;
20
+ export type FacetsEvents = typeof __propDef.events;
21
+ export type FacetsSlots = typeof __propDef.slots;
22
+ export default class Facets extends SvelteComponent<FacetsProps, FacetsEvents, FacetsSlots> {
23
+ }
24
+ export {};
@@ -0,0 +1,75 @@
1
+ <script>export let group;
2
+ export let items;
3
+ export let selected;
4
+ export let handleSave;
5
+ export let handleCancel;
6
+ let selectedItems = selected;
7
+ const handleCheck = (e, index) => {
8
+ const target = e.target;
9
+ if (target.checked) {
10
+ selectedItems = [...selectedItems, items[index]];
11
+ } else {
12
+ selectedItems = selectedItems.filter((item) => item !== items[index]);
13
+ }
14
+ };
15
+ const selectAll = () => {
16
+ selectedItems = items;
17
+ };
18
+ const selectNone = () => {
19
+ selectedItems = [];
20
+ };
21
+ const onSave = () => {
22
+ handleSave(group, selectedItems);
23
+ };
24
+ const onCancel = () => {
25
+ selectedItems = selected;
26
+ handleCancel();
27
+ };
28
+ const gridClass = (items2) => {
29
+ if (items2.length >= 50) {
30
+ return "grid-cols-5";
31
+ } else if (items2.length >= 30) {
32
+ return "grid-cols-4";
33
+ } else if (items2.length >= 20) {
34
+ return "grid-cols-3";
35
+ }
36
+ return "grid-cols-2";
37
+ };
38
+ </script>
39
+
40
+ <div class="p-5 rounded-md bg-surface-50 dark:bg-surface-800 border-primary-500 border-2">
41
+ <!-- Header -->
42
+ <h2 class="text-xl font-semibold">{group}</h2>
43
+
44
+ <!-- Items -->
45
+ <div
46
+ class="grid {gridClass(
47
+ items
48
+ )} !gap-x-20 gap-y-2 py-10 px-2 max-h-[1000px] overflow-x-auto max-w-6xl"
49
+ >
50
+ {#each items as item, index}
51
+ <label class="flex gap-3 items-center">
52
+ <input
53
+ type="checkbox"
54
+ class="checkbox"
55
+ value={item.value}
56
+ on:click={(e) => handleCheck(e, index)}
57
+ checked={selectedItems.includes(item)}
58
+ />
59
+ <span class="whitespace-nowrap break-before-avoid break-after-avoid">{item.value}</span>
60
+ </label>
61
+ {/each}
62
+ </div>
63
+
64
+ <!-- Footer -->
65
+ <div class="flex w-full justify-between gap-5">
66
+ <div class="flex gap-3">
67
+ <button class="btn btn-sm variant-filled-tertiary" on:click={selectNone}>None</button>
68
+ <button class="btn btn-sm variant-filled-tertiary" on:click={selectAll}>All</button>
69
+ </div>
70
+ <div class="flex gap-3">
71
+ <button class="btn btn-sm variant-filled-primary" on:click={onSave}>Save</button>
72
+ <button class="btn btn-sm variant-filled-secondary" on:click={onCancel}>Cancel</button>
73
+ </div>
74
+ </div>
75
+ </div>
@@ -0,0 +1,21 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { FacetOption } from '../../models/Models';
3
+ declare const __propDef: {
4
+ props: {
5
+ group: string;
6
+ items: FacetOption[];
7
+ selected: FacetOption[];
8
+ handleSave: (group: string, selectedItems: FacetOption[]) => {};
9
+ handleCancel: () => {};
10
+ };
11
+ events: {
12
+ [evt: string]: CustomEvent<any>;
13
+ };
14
+ slots: {};
15
+ };
16
+ export type ShowMoreProps = typeof __propDef.props;
17
+ export type ShowMoreEvents = typeof __propDef.events;
18
+ export type ShowMoreSlots = typeof __propDef.slots;
19
+ export default class ShowMore extends SvelteComponent<ShowMoreProps, ShowMoreEvents, ShowMoreSlots> {
20
+ }
21
+ export {};
@@ -15,16 +15,13 @@ export let submit = "";
15
15
  export let context = "";
16
16
  export let data;
17
17
  let isUploading = false;
18
- $:
19
- model = data;
20
- $:
21
- submitBt = "submit";
18
+ $: model = data;
19
+ $: submitBt = "submit";
22
20
  let maxSize = 0;
23
21
  const dispatch = createEventDispatcher();
24
22
  let fx;
25
23
  let files = { accepted: [], rejected: [] };
26
- $:
27
- files;
24
+ $: files;
28
25
  onMount(async () => {
29
26
  if (!data) {
30
27
  load();
@@ -2,11 +2,11 @@ import { SvelteComponent } from "svelte";
2
2
  import type { fileUploaderType } from '../../models/Models.js';
3
3
  declare const __propDef: {
4
4
  props: {
5
- id?: number | undefined;
6
- version?: number | undefined;
7
- start?: string | undefined;
8
- submit?: string | undefined;
9
- context?: string | undefined;
5
+ id?: number;
6
+ version?: number;
7
+ start?: string;
8
+ submit?: string;
9
+ context?: string;
10
10
  data: fileUploaderType | undefined;
11
11
  };
12
12
  events: {
@@ -0,0 +1,33 @@
1
+ <script>import { popup } from "@skeletonlabs/skeleton";
2
+ export let columns = [];
3
+ export let tableId;
4
+ const popupCombobox = {
5
+ event: "click",
6
+ target: `${tableId}-columns-menu`,
7
+ placement: "bottom"
8
+ };
9
+ </script>
10
+
11
+ <button
12
+ type="button"
13
+ class="btn btn-sm variant-filled-primary rounded-full order-last"
14
+ use:popup={popupCombobox}>Columns</button
15
+ >
16
+
17
+ <div
18
+ class="bg-white dark:bg-surface-500 p-4 rounded-md shadow-md z-10"
19
+ data-popup="{tableId}-columns-menu"
20
+ >
21
+ {#each columns as column}
22
+ <div class="flex gap-3 items-center">
23
+ <input
24
+ type="checkbox"
25
+ bind:checked={column.visible}
26
+ disabled={columns.filter((c) => c.visible).length === 1 && column.visible}
27
+ />
28
+ <span>{column.label}</span>
29
+ </div>
30
+ {/each}
31
+
32
+ <div class="arrow bg-white dark:bg-surface-500" />
33
+ </div>
@@ -0,0 +1,21 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ columns?: {
5
+ id: string;
6
+ label: string;
7
+ visible: boolean;
8
+ }[];
9
+ tableId: string;
10
+ };
11
+ events: {
12
+ [evt: string]: CustomEvent<any>;
13
+ };
14
+ slots: {};
15
+ };
16
+ export type ColumnsMenuProps = typeof __propDef.props;
17
+ export type ColumnsMenuEvents = typeof __propDef.events;
18
+ export type ColumnsMenuSlots = typeof __propDef.slots;
19
+ export default class ColumnsMenu extends SvelteComponent<ColumnsMenuProps, ColumnsMenuEvents, ColumnsMenuSlots> {
20
+ }
21
+ export {};
@@ -2,9 +2,7 @@
2
2
  export let config;
3
3
  let fetched = false;
4
4
  const data = config.data;
5
- $:
6
- if ($data.length > 0)
7
- fetched = true;
5
+ $: if ($data.length > 0) fetched = true;
8
6
  </script>
9
7
 
10
8
  {#key fetched}
@@ -1,5 +1,16 @@
1
1
  import { SvelteComponent } from "svelte";
2
- declare const __propDef: any;
2
+ import type { TableConfig } from '../../models/Models';
3
+ declare const __propDef: {
4
+ props: {
5
+ config: TableConfig<any>;
6
+ };
7
+ events: {
8
+ action: any;
9
+ } & {
10
+ [evt: string]: CustomEvent<any>;
11
+ };
12
+ slots: {};
13
+ };
3
14
  export type TableProps = typeof __propDef.props;
4
15
  export type TableEvents = typeof __propDef.events;
5
16
  export type TableSlots = typeof __propDef.slots;
@@ -9,7 +9,8 @@ import {
9
9
  addExpandedRows,
10
10
  addColumnFilters,
11
11
  addTableFilter,
12
- addDataExport
12
+ addDataExport,
13
+ addHiddenColumns
13
14
  } from "svelte-headless-table/plugins";
14
15
  import { computePosition, autoUpdate, offset, shift, flip, arrow } from "@floating-ui/dom";
15
16
  import { SlideToggle, storePopup } from "@skeletonlabs/skeleton";
@@ -19,6 +20,7 @@ import TableFilter from "./TableFilter.svelte";
19
20
  import TableFilterServer from "./TableFilterServer.svelte";
20
21
  import TablePagination from "./TablePagination.svelte";
21
22
  import TablePaginationServer from "./TablePaginationServer.svelte";
23
+ import ColumnsMenu from "./ColumnsMenu.svelte";
22
24
  import { columnFilter, searchFilter } from "./filter";
23
25
  import {
24
26
  cellStyle,
@@ -51,27 +53,18 @@ let {
51
53
  // Whether to display the fitToScreen toggle
52
54
  search = true,
53
55
  // Whether to display the search input
54
- pageSizes = [5, 10, 15, 20],
56
+ pageSizes = [5, 10, 20, 50, 100],
55
57
  // Page sizes to display in the pagination component
56
58
  fitToScreen = true,
57
59
  // Whether to fit the table to the screen,
58
60
  exportable = false,
59
61
  // Whether to display the export button and enable export functionality
60
- serverSide = false,
61
- // Whether the table is client or server-side
62
- URL = "",
63
- // URL to fetch data from
64
- token = "",
65
- // Bearer token to authenticate the request
66
- sendModel = new Send(),
67
- // Model to send requests
68
- entityId = 0,
69
- // Entity ID to send with the request
70
- versionId = 0
71
- // Version ID to send with the request,
62
+ server
72
63
  } = config;
73
64
  let searchValue = "";
74
65
  let isFetching = false;
66
+ const serverSide = server !== void 0;
67
+ const { baseUrl, sendModel, entityId, versionId } = server ?? {};
75
68
  const filters = writable({});
76
69
  const dispatch = createEventDispatcher();
77
70
  const actionDispatcher = (obj) => dispatch("action", obj);
@@ -85,6 +78,7 @@ const table = createTable(data, {
85
78
  fn: searchFilter,
86
79
  serverSide
87
80
  }),
81
+ hideColumns: addHiddenColumns(),
88
82
  sort: addSortBy({
89
83
  disableMultiSort: true,
90
84
  serverSide
@@ -109,14 +103,24 @@ Object.keys(allCols).forEach((key) => {
109
103
  $filters = { ...$filters, [key]: {} };
110
104
  });
111
105
  const accessors = Object.keys(allCols);
106
+ const unexcludedColumns = accessors.filter((accessor) => {
107
+ const key = accessor;
108
+ if (columns !== void 0 && key in columns && columns[key].exclude === true) {
109
+ return false;
110
+ }
111
+ return true;
112
+ });
113
+ let shownColumns = unexcludedColumns.map((c) => {
114
+ const key = c;
115
+ const label = key.charAt(0).toUpperCase() + key.slice(1);
116
+ return {
117
+ id: c,
118
+ label: columns && columns[key] && columns[key].header ? columns[key].header : label,
119
+ visible: true
120
+ };
121
+ });
112
122
  const tableColumns = [
113
- ...accessors.filter((accessor) => {
114
- const key = accessor;
115
- if (columns !== void 0 && key in columns && columns[key].exclude === true) {
116
- return false;
117
- }
118
- return true;
119
- }).map((accessor) => {
123
+ ...unexcludedColumns.map((accessor) => {
120
124
  const key = accessor;
121
125
  if (columns !== void 0 && key in columns) {
122
126
  const {
@@ -246,19 +250,20 @@ const { headerRows, pageRows, tableAttrs, tableBodyAttrs, pluginStates } = table
246
250
  const { filterValue } = pluginStates.tableFilter;
247
251
  const { exportedData } = pluginStates.export;
248
252
  const { pageIndex, pageSize } = pluginStates.page;
253
+ const { hiddenColumnIds } = pluginStates.hideColumns;
249
254
  const updateTable = async () => {
255
+ if (!sendModel) throw new Error("Server-side configuration is missing");
250
256
  sendModel.limit = $pageSize;
251
257
  sendModel.offset = $pageSize * $pageIndex;
252
- sendModel.version = versionId;
253
- sendModel.id = entityId;
258
+ sendModel.version = versionId || -1;
259
+ sendModel.id = entityId || -1;
254
260
  sendModel.filter = normalizeFilters($filters);
255
261
  let fetchData;
256
262
  try {
257
263
  isFetching = true;
258
- fetchData = await fetch(URL, {
264
+ fetchData = await fetch(baseUrl || "", {
259
265
  headers: {
260
- "Content-Type": "application/json",
261
- Authorization: `Bearer ${token}`
266
+ "Content-Type": "application/json"
262
267
  },
263
268
  method: "POST",
264
269
  body: JSON.stringify(sendModel)
@@ -293,6 +298,7 @@ const updateTable = async () => {
293
298
  return response;
294
299
  };
295
300
  const sortServer = (order, id) => {
301
+ if (!sendModel) throw new Error("Server-side configuration is missing");
296
302
  if (order === void 0) {
297
303
  sendModel.order = [];
298
304
  } else {
@@ -301,22 +307,22 @@ const sortServer = (order, id) => {
301
307
  $pageIndex = 0;
302
308
  updateTable();
303
309
  };
304
- $:
305
- sortKeys = pluginStates.sort.sortKeys;
306
- $:
307
- serverSide && updateTable();
308
- $:
309
- serverSide && sortServer($sortKeys[0]?.order, $sortKeys[0]?.id);
310
+ $: sortKeys = pluginStates.sort.sortKeys;
311
+ $: serverSide && updateTable();
312
+ $: serverSide && sortServer($sortKeys[0]?.order, $sortKeys[0]?.id);
313
+ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => col.id);
310
314
  </script>
311
315
 
312
316
  <div class="grid gap-2 overflow-auto" class:w-fit={!fitToScreen} class:w-full={fitToScreen}>
313
317
  {#if $data.length > 0 || (columns && Object.keys(columns).length > 0)}
314
318
  <div class="table-container">
315
319
  <!-- Enable the search filter if table is not empty -->
316
- {#if !serverSide && search}
320
+ {#if search}
317
321
  <form
318
322
  class="flex gap-2"
319
323
  on:submit|preventDefault={() => {
324
+ if (!sendModel) throw new Error('Server-side configuration is missing');
325
+
320
326
  sendModel.q = searchValue;
321
327
  $filterValue = searchValue;
322
328
  }}
@@ -333,6 +339,8 @@ $:
333
339
  id="{tableId}-searchReset"
334
340
  class="absolute right-3 items-center"
335
341
  on:click|preventDefault={() => {
342
+ if (!sendModel) throw new Error('Server-side configuration is missing');
343
+
336
344
  searchValue = '';
337
345
  sendModel.q = '';
338
346
  $filterValue = '';
@@ -344,6 +352,8 @@ $:
344
352
  id="{tableId}-searchSubmit"
345
353
  class="btn variant-filled-primary"
346
354
  on:click|preventDefault={() => {
355
+ if (!sendModel) throw new Error('Server-side configuration is missing');
356
+
347
357
  $filterValue = searchValue;
348
358
  sendModel.q = searchValue;
349
359
  }}>Search</button
@@ -384,6 +394,9 @@ $:
384
394
  >Export as CSV</button
385
395
  >
386
396
  {/if}
397
+ {#if shownColumns.length > 0}
398
+ <ColumnsMenu bind:columns={shownColumns} {tableId} />
399
+ {/if}
387
400
  </div>
388
401
  </div>
389
402
 
@@ -436,9 +449,7 @@ $:
436
449
  <!-- Adding column filter config -->
437
450
  {#if cell.isData()}
438
451
  {#if props.colFilter?.render}
439
- <div class="">
440
- <Render of={props.colFilter.render} />
441
- </div>
452
+ <Render of={props.colFilter.render} />
442
453
  {/if}
443
454
  {/if}
444
455
  </div>
@@ -509,3 +520,5 @@ $:
509
520
  {/if}
510
521
  {/if}
511
522
  </div>
523
+
524
+ <div id="{tableId}-popups" />
@@ -1,4 +1,5 @@
1
- <script>import Fa from "svelte-fa";
1
+ <script>import Fa from "svelte-fa/src/fa.svelte";
2
+ import { onMount } from "svelte";
2
3
  import { faFilter, faPlus, faXmark } from "@fortawesome/free-solid-svg-icons";
3
4
  import { popup } from "@skeletonlabs/skeleton";
4
5
  import { FilterOptionsEnum } from "../../models/Enums";
@@ -146,7 +147,8 @@ const optionChangeHandler = (e, index) => {
146
147
  const valueChangeHandler = (e, index) => {
147
148
  dropdowns[index] = {
148
149
  ...dropdowns[index],
149
- value: type === "date" ? new Date(e.target.value) : e.target.value
150
+ value: type === "date" ? new Date(e.target.value) : e.target.value,
151
+ formValue: e.target.value
150
152
  };
151
153
  $filters = {
152
154
  ...$filters,
@@ -166,7 +168,8 @@ const addFilter = (option, value) => {
166
168
  ...dropdowns,
167
169
  {
168
170
  option,
169
- value: void 0
171
+ value: void 0,
172
+ formValue: void 0
170
173
  }
171
174
  ];
172
175
  };
@@ -179,17 +182,19 @@ const clearFilters = () => {
179
182
  dropdowns = [];
180
183
  $filters[id] = {};
181
184
  };
182
- $:
183
- type = isDate ? "date" : type;
184
- $:
185
- remainingFilters = options[type].filter(
186
- (option) => !Object.keys($filters[id]).includes(option.value)
187
- );
188
- $:
189
- addFilter(options[type][0].value, void 0);
185
+ $: type = isDate ? "date" : type;
186
+ $: remainingFilters = options[type].filter(
187
+ (option) => !Object.keys($filters[id]).includes(option.value)
188
+ );
189
+ $: addFilter(options[type][0].value, void 0);
190
+ onMount(() => {
191
+ const element = document.getElementById(popupId);
192
+ element?.parentElement?.removeChild(element);
193
+ element && document.getElementById(`${tableId}-popups`)?.appendChild(element);
194
+ });
190
195
  </script>
191
196
 
192
- <form class="">
197
+ <div id="parent-{popupId}">
193
198
  <button
194
199
  class:variant-filled-primary={active}
195
200
  class="btn w-max p-2"
@@ -200,7 +205,7 @@ $:
200
205
  <Fa icon={faFilter} size="12" />
201
206
  </button>
202
207
 
203
- <div data-popup={`${popupId}`} id={popupId} class="z-50">
208
+ <div data-popup={popupId} id={popupId} class="">
204
209
  <div class="card p-3 grid gap-2 shadow-lg w-max bg-base-100">
205
210
  <button
206
211
  class="btn variant-filled-primary btn-sm"
@@ -258,7 +263,7 @@ $:
258
263
  type="date"
259
264
  class="input p-1 border border-primary-500"
260
265
  on:input={(e) => valueChangeHandler(e, index)}
261
- bind:value={dropdown.value}
266
+ bind:value={dropdown.formValue}
262
267
  />
263
268
  {/if}
264
269
  </div>
@@ -292,4 +297,4 @@ $:
292
297
  >
293
298
  </div>
294
299
  </div>
295
- </form>
300
+ </div>