@bexis2/bexis2-core-ui 0.4.13 → 0.4.15

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,16 @@
1
1
  # bexis-core-ui
2
+ ## 0.4.15
3
+ - Update Facets with new params and add onChange action
4
+ - Changes structure of Facets data
5
+ - Adds on:change action
6
+
7
+ ## 0.4.14
8
+ - Table
9
+ - fixes rendering issues with Table filters and different components
10
+
11
+ - Facets
12
+ - Exports Facets component
13
+
2
14
  ## 0.4.13
3
15
  - menu
4
16
  - fix code isses
@@ -1,102 +1,162 @@
1
- <script>import { getModalStore, Modal, TreeView, TreeViewItem } from "@skeletonlabs/skeleton";
1
+ <script>import { createEventDispatcher } from "svelte";
2
+ import { getModalStore, Modal, TreeView, TreeViewItem } from "@skeletonlabs/skeleton";
2
3
  import ShowMore from "./ShowMore.svelte";
3
4
  export let groupSelection = false;
4
5
  export let groups;
5
- export let selected;
6
- export let selectedGroups = {};
7
6
  export let showAll = false;
8
7
  export let open = false;
8
+ let displayedGroups = structuredClone(groups);
9
+ let selected = groups.reduce((acc, g) => {
10
+ const children = g.children.reduce((acc2, c) => {
11
+ acc2[c.name] = {
12
+ ...c,
13
+ selected: false
14
+ };
15
+ return acc2;
16
+ }, {});
17
+ acc[g.name] = {
18
+ ...g,
19
+ children,
20
+ selected: false
21
+ };
22
+ return acc;
23
+ }, {});
24
+ let selectedItems = {};
25
+ let selectedGroups = {};
26
+ Object.keys(selected).forEach((groupName) => {
27
+ selectedItems[groupName] = {};
28
+ Object.keys(selected[groupName].children).forEach((itemName) => {
29
+ selectedItems[groupName][itemName] = false;
30
+ });
31
+ selectedGroups[groupName] = false;
32
+ });
33
+ const dispatch = createEventDispatcher();
9
34
  const modalStore = getModalStore();
10
35
  const showMore = (group) => {
11
36
  modalStore.trigger({
12
37
  type: "component",
13
- title: `${group}`,
38
+ title: `${group.displayName}`,
14
39
  component: {
15
40
  ref: ShowMore,
16
41
  props: {
17
42
  group,
18
43
  handleSave,
19
- handleCancel,
20
- selected: selected[group],
21
- items: groups[group].sort((a, b) => a.value.localeCompare(b.value))
44
+ handleCancel
22
45
  }
23
46
  }
24
47
  });
25
48
  };
26
- const handleSave = (group, selectedItems) => {
27
- selected[group] = selectedItems;
49
+ const handleSave = (group) => {
50
+ Object.keys(group.children).forEach((key) => {
51
+ selectedItems[group.name][key] = group.children[key].selected;
52
+ });
28
53
  modalStore.close();
29
54
  };
30
55
  const handleCancel = () => {
31
56
  modalStore.close();
32
57
  };
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;
58
+ const mapSelected = (type) => {
59
+ const changed = [];
60
+ if (type === "items") {
61
+ Object.keys(selectedItems).forEach((group) => {
62
+ Object.keys(selectedItems[group]).forEach((item) => {
63
+ if (selectedItems[group][item] !== selected[group].children[item].selected) {
64
+ changed.push({
65
+ parent: group,
66
+ selectedItem: item
67
+ });
68
+ selected[group].children[item].selected = selectedItems[group][item];
45
69
  }
46
- return a.value.localeCompare(b.value);
47
- })
70
+ });
71
+ });
72
+ } else {
73
+ Object.keys(selectedGroups).forEach((group) => {
74
+ if (selectedGroups[group] !== selected[group].selected) {
75
+ changed.push({
76
+ parent: null,
77
+ selectedItem: group
78
+ });
79
+ selected[group].selected = selectedGroups[group];
80
+ }
81
+ });
82
+ }
83
+ dispatch("change", changed);
84
+ };
85
+ const sortOptions = () => {
86
+ Object.keys(selected).forEach((group) => {
87
+ const checked = Object.keys(selected[group].children).filter((item) => selected[group].children[item].selected).map((item) => selected[group].children[item]).sort((a, b) => {
88
+ if (a.count != void 0 && b.count != void 0) {
89
+ return b.count - a.count;
90
+ }
91
+ return a.displayName.localeCompare(b.displayName);
92
+ }).map((item) => item.name);
93
+ const unchecked = Object.keys(selected[group].children).filter(
94
+ (item) => !checked.includes(item)
95
+ );
96
+ const groupIndex = displayedGroups.findIndex((g) => g.name === group);
97
+ displayedGroups[groupIndex].children = [
98
+ ...checked.map(
99
+ (item) => displayedGroups[groupIndex].children.find((i) => i.name === item)
100
+ ),
101
+ ...unchecked.map(
102
+ (item) => displayedGroups[groupIndex].children.find((i) => i.name === item)
103
+ )
48
104
  ];
49
105
  });
50
106
  };
51
- $: selected, sortOptions();
107
+ $: selectedItems, mapSelected("items"), sortOptions();
108
+ $: selectedGroups, mapSelected("groups");
52
109
  </script>
53
110
 
54
111
  <TreeView selection={groupSelection} multiple={groupSelection} padding="p-1" hover="">
55
- {#each Object.keys(groups) as group}
112
+ {#each displayedGroups as group}
56
113
  <TreeViewItem
57
- name="groups"
58
- value={group}
114
+ name={group.name}
115
+ value={group.name}
59
116
  {open}
60
117
  hyphenOpacity="opacity-0"
118
+ bind:checked={selectedGroups[group.name]}
61
119
  bind:group={selectedGroups}
62
- bind:checked={selectedGroups[group]}
63
120
  >
64
- <p class="font-semibold">{group}</p>
121
+ <p class="font-semibold">{group.displayName}</p>
65
122
 
66
123
  <svelte:fragment slot="children">
67
124
  <!-- If more than 5 choices, show the remaining in the Modal -->
68
125
  {#if !showAll}
69
- {#each groups[group].slice(0, 5) as item}
126
+ {#each group.children.slice(0, 5) as item}
70
127
  <TreeViewItem
71
- bind:group={selected[group]}
72
- name={group}
73
- value={item}
128
+ bind:group={selectedItems[group.name]}
129
+ name={item.name}
130
+ value={item.displayName}
74
131
  hyphenOpacity="opacity-0"
132
+ bind:checked={selectedItems[group.name][item.name]}
75
133
  spacing="space-x-3"
76
134
  selection
77
135
  multiple
78
136
  >
79
- <p>{item.value} ({item.count})</p>
137
+ <p>{item.displayName} ({item.count})</p>
80
138
  </TreeViewItem>
81
139
  {/each}
82
140
  <!-- Trigger for the Modal to view all options -->
83
- {#if groups[group].length > 5}
141
+ {#if group.children.length > 5}
84
142
  <TreeViewItem hyphenOpacity="opacity-0">
85
- <button class="anchor" on:click={() => showMore(group)}>more</button></TreeViewItem
143
+ <button class="anchor" on:click={() => showMore(selected[group.name])}>more</button
144
+ ></TreeViewItem
86
145
  >
87
146
  {/if}
88
147
  {:else}
89
- {#each groups[group] as item}
148
+ {#each group.children as item}
90
149
  <TreeViewItem
91
- bind:group={selected[group]}
92
- name={group}
93
- value={item}
150
+ bind:group={selectedItems[group.name]}
151
+ bind:checked={selectedItems[group.name][item.name]}
152
+ name={item.name}
153
+ value={item.displayName}
94
154
  hyphenOpacity="opacity-0"
95
155
  spacing="space-x-3"
96
156
  selection
97
157
  multiple
98
158
  >
99
- <p>{item.value} ({item.count})</p>
159
+ <p>{item.displayName} ({item.count})</p>
100
160
  </TreeViewItem>
101
161
  {/each}
102
162
  {/if}
@@ -3,15 +3,13 @@ import type { FacetGroup } from '../../models/Models';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  groupSelection?: boolean;
6
- groups: FacetGroup;
7
- selected: FacetGroup;
8
- selectedGroups?: {
9
- [key: string]: boolean;
10
- };
6
+ groups: FacetGroup[];
11
7
  showAll?: boolean;
12
8
  open?: boolean;
13
9
  };
14
10
  events: {
11
+ change: CustomEvent<any>;
12
+ } & {
15
13
  [evt: string]: CustomEvent<any>;
16
14
  };
17
15
  slots: {};
@@ -1,36 +1,30 @@
1
1
  <script>export let group;
2
- export let items;
3
- export let selected;
4
2
  export let handleSave;
5
3
  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
- };
4
+ let selected = structuredClone(group.children);
15
5
  const selectAll = () => {
16
- selectedItems = items;
6
+ Object.keys(selected).forEach((key) => selected[key].selected = true);
17
7
  };
18
8
  const selectNone = () => {
19
- selectedItems = [];
9
+ Object.keys(selected).forEach((key) => selected[key].selected = false);
20
10
  };
21
11
  const onSave = () => {
22
- handleSave(group, selectedItems);
12
+ handleSave({
13
+ ...group,
14
+ children: selected
15
+ });
23
16
  };
24
17
  const onCancel = () => {
25
- selectedItems = selected;
18
+ console.log(selected, group.children);
19
+ selected = structuredClone(group.children);
26
20
  handleCancel();
27
21
  };
28
- const gridClass = (items2) => {
29
- if (items2.length >= 50) {
22
+ const gridClass = (items) => {
23
+ if (items.length >= 50) {
30
24
  return "grid-cols-5";
31
- } else if (items2.length >= 30) {
25
+ } else if (items.length >= 30) {
32
26
  return "grid-cols-4";
33
- } else if (items2.length >= 20) {
27
+ } else if (items.length >= 20) {
34
28
  return "grid-cols-3";
35
29
  }
36
30
  return "grid-cols-2";
@@ -39,24 +33,20 @@ const gridClass = (items2) => {
39
33
 
40
34
  <div class="p-5 rounded-md bg-surface-50 dark:bg-surface-800 border-primary-500 border-2">
41
35
  <!-- Header -->
42
- <h2 class="text-xl font-semibold">{group}</h2>
36
+ <h2 class="text-xl font-semibold">{group.displayName}</h2>
43
37
 
44
38
  <!-- Items -->
45
39
  <div
46
40
  class="grid {gridClass(
47
- items
41
+ Object.keys(selected)
48
42
  )} !gap-x-20 gap-y-2 py-10 px-2 max-h-[1000px] overflow-x-auto max-w-6xl"
49
43
  >
50
- {#each items as item, index}
44
+ {#each Object.keys(selected) as key}
51
45
  <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>
46
+ <input type="checkbox" class="checkbox" bind:checked={selected[key].selected} />
47
+ <span class="whitespace-nowrap break-before-avoid break-after-avoid"
48
+ >{selected[key].displayName}</span
49
+ >
60
50
  </label>
61
51
  {/each}
62
52
  </div>
@@ -1,11 +1,9 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import type { FacetOption } from '../../models/Models';
2
+ import type { SelectedFacetGroup } from '../../models/Models';
3
3
  declare const __propDef: {
4
4
  props: {
5
- group: string;
6
- items: FacetOption[];
7
- selected: FacetOption[];
8
- handleSave: (group: string, selectedItems: FacetOption[]) => {};
5
+ group: SelectedFacetGroup;
6
+ handleSave: (group: SelectedFacetGroup) => {};
9
7
  handleCancel: () => {};
10
8
  };
11
9
  events: {
@@ -64,7 +64,7 @@ let {
64
64
  let searchValue = "";
65
65
  let isFetching = false;
66
66
  const serverSide = server !== void 0;
67
- const { baseUrl, sendModel, entityId, versionId } = server ?? {};
67
+ const { baseUrl, entityId, versionId, sendModel = new Send() } = server ?? {};
68
68
  const filters = writable({});
69
69
  const dispatch = createEventDispatcher();
70
70
  const actionDispatcher = (obj) => dispatch("action", obj);
@@ -361,7 +361,11 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
361
361
  </form>
362
362
  {/if}
363
363
 
364
- <div class="flex justify-between items-center w-full {search && 'py-2'}">
364
+ <div
365
+ class="flex justify-between items-center w-full {search && 'py-2'} {!search &&
366
+ (shownColumns.length > 0 || toggle || resizable !== 'none' || exportable) &&
367
+ 'pb-2'}"
368
+ >
365
369
  <div>
366
370
  <!-- Enable the fitToScreen toggle if toggle === true -->
367
371
  {#if toggle}
@@ -205,7 +205,7 @@ onMount(() => {
205
205
  <Fa icon={faFilter} size="12" />
206
206
  </button>
207
207
 
208
- <div data-popup={popupId} id={popupId} class="">
208
+ <div data-popup={popupId} id={popupId} class="z-50">
209
209
  <div class="card p-3 grid gap-2 shadow-lg w-max bg-base-100">
210
210
  <button
211
211
  class="btn variant-filled-primary btn-sm"
package/dist/index.d.ts CHANGED
@@ -19,6 +19,7 @@ import Table from './components/Table/Table.svelte';
19
19
  import TableFilter from './components/Table/TableFilter.svelte';
20
20
  import { columnFilter, searchFilter } from './components/Table/filter';
21
21
  import type { TableConfig, Columns, Column } from './models/Models';
22
+ import Facets from './components/Facets/Facets.svelte';
22
23
  import CodeEditor from './components/CodeEditor/CodeEditor.svelte';
23
24
  import Notification from './components/page/Notification.svelte';
24
25
  import TablePlaceholder from './components/page/TablePlaceholder.svelte';
@@ -38,6 +39,7 @@ export { Notification };
38
39
  export { TablePlaceholder };
39
40
  export { positionType, pageContentLayoutType, decimalCharacterType, orientationType, textMarkerType, textSeperatorType } from './models/Enums';
40
41
  export { Table, TableFilter, columnFilter, searchFilter };
42
+ export { Facets };
41
43
  export { CodeEditor };
42
44
  export type { TableConfig, Columns, Column };
43
45
  export { bexis2theme };
package/dist/index.js CHANGED
@@ -24,6 +24,8 @@ import TextArea from './components/form/TextArea.svelte';
24
24
  import Table from './components/Table/Table.svelte';
25
25
  import TableFilter from './components/Table/TableFilter.svelte';
26
26
  import { columnFilter, searchFilter } from './components/Table/filter';
27
+ //Facets
28
+ import Facets from './components/Facets/Facets.svelte';
27
29
  // CodeEditor
28
30
  import CodeEditor from './components/CodeEditor/CodeEditor.svelte';
29
31
  //notification
@@ -53,6 +55,8 @@ export { TablePlaceholder };
53
55
  export { positionType, pageContentLayoutType, decimalCharacterType, orientationType, textMarkerType, textSeperatorType } from './models/Enums';
54
56
  // Table
55
57
  export { Table, TableFilter, columnFilter, searchFilter };
58
+ // Facets
59
+ export { Facets };
56
60
  // CodeEditor
57
61
  export { CodeEditor };
58
62
  // theme
@@ -82,7 +82,7 @@ export interface Columns {
82
82
  }
83
83
  export type ServerConfig = {
84
84
  baseUrl?: string;
85
- sendModel: Send;
85
+ sendModel?: Send;
86
86
  entityId?: number;
87
87
  versionId?: number;
88
88
  };
@@ -151,13 +151,26 @@ export type Filter = {
151
151
  filterBy: FilterOptionsEnum;
152
152
  value: string | number | Date | boolean;
153
153
  };
154
- export type FacetOption = {
155
- value: string;
154
+ export interface FacetOption {
155
+ name: string;
156
+ displayName: string;
156
157
  count?: number;
157
- };
158
- export type FacetGroup = {
159
- [key: string]: FacetOption[];
160
- };
158
+ }
159
+ export interface FacetGroup {
160
+ name: string;
161
+ displayName: string;
162
+ children: FacetOption[];
163
+ count?: number;
164
+ }
165
+ export interface SelectedFacetOption extends FacetOption {
166
+ selected: boolean;
167
+ }
168
+ export interface SelectedFacetGroup extends Omit<FacetGroup, 'children'> {
169
+ selected: boolean;
170
+ children: {
171
+ [key: string]: SelectedFacetOption;
172
+ };
173
+ }
161
174
  export declare class Send {
162
175
  id: number;
163
176
  limit: number;
@@ -34,10 +34,9 @@ export class errorType {
34
34
  error;
35
35
  stackTrace;
36
36
  constructor() {
37
- this.statusText = "";
37
+ this.statusText = '';
38
38
  this.status = 0;
39
- this.error = "";
40
- this.stackTrace = "";
39
+ this.error = '';
40
+ this.stackTrace = '';
41
41
  }
42
42
  }
43
- ;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bexis2/bexis2-core-ui",
3
- "version": "0.4.13",
3
+ "version": "0.4.15",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -1,36 +1,71 @@
1
1
  <script lang="ts">
2
+ import { createEventDispatcher } from 'svelte';
2
3
  import { getModalStore, Modal, TreeView, TreeViewItem } from '@skeletonlabs/skeleton';
3
4
 
4
5
  import ShowMore from './ShowMore.svelte';
5
- import type { FacetOption, FacetGroup } from '$models/Models';
6
+ import type { FacetGroup, SelectedFacetGroup } from '$models/Models';
6
7
 
7
8
  export let groupSelection = false;
8
- export let groups: FacetGroup;
9
- export let selected: FacetGroup;
10
- export let selectedGroups: { [key: string]: boolean } = {};
9
+ export let groups: FacetGroup[];
11
10
  export let showAll = false;
12
11
  export let open = false;
13
12
 
13
+ let displayedGroups = structuredClone(groups);
14
+
15
+ let selected: { [key: string]: SelectedFacetGroup } = groups.reduce((acc, g) => {
16
+ const children = g.children.reduce((acc, c) => {
17
+ acc[c.name] = {
18
+ ...c,
19
+ selected: false
20
+ };
21
+ return acc;
22
+ }, {});
23
+
24
+ acc[g.name] = {
25
+ ...g,
26
+ children,
27
+ selected: false
28
+ };
29
+
30
+ return acc;
31
+ }, {});
32
+ let selectedItems: {
33
+ [key: string]: {
34
+ [key: string]: boolean;
35
+ };
36
+ } = {};
37
+ let selectedGroups: { [key: string]: boolean } = {};
38
+
39
+ Object.keys(selected).forEach((groupName) => {
40
+ selectedItems[groupName] = {};
41
+ Object.keys(selected[groupName].children).forEach((itemName) => {
42
+ selectedItems[groupName][itemName] = false;
43
+ });
44
+ selectedGroups[groupName] = false;
45
+ });
46
+
47
+ const dispatch = createEventDispatcher();
48
+
14
49
  const modalStore = getModalStore();
15
- const showMore = (group: string) => {
50
+ const showMore = (group: SelectedFacetGroup) => {
16
51
  modalStore.trigger({
17
52
  type: 'component',
18
- title: `${group}`,
53
+ title: `${group.displayName}`,
19
54
  component: {
20
55
  ref: ShowMore,
21
56
  props: {
22
57
  group,
23
58
  handleSave,
24
- handleCancel,
25
- selected: selected[group],
26
- items: groups[group].sort((a, b) => a.value.localeCompare(b.value))
59
+ handleCancel
27
60
  }
28
61
  }
29
62
  });
30
63
  };
31
64
 
32
- const handleSave = (group: string, selectedItems: FacetOption[]) => {
33
- selected[group] = selectedItems;
65
+ const handleSave = (group: SelectedFacetGroup) => {
66
+ Object.keys(group.children).forEach((key) => {
67
+ selectedItems[group.name][key] = group.children[key].selected;
68
+ });
34
69
  modalStore.close();
35
70
  };
36
71
 
@@ -38,77 +73,120 @@
38
73
  modalStore.close();
39
74
  };
40
75
 
76
+ const mapSelected = (type: 'items' | 'groups') => {
77
+ const changed: any = [];
78
+
79
+ if (type === 'items') {
80
+ Object.keys(selectedItems).forEach((group) => {
81
+ Object.keys(selectedItems[group]).forEach((item) => {
82
+ if (selectedItems[group][item] !== selected[group].children[item].selected) {
83
+ changed.push({
84
+ parent: group,
85
+ selectedItem: item
86
+ });
87
+ selected[group].children[item].selected = selectedItems[group][item];
88
+ }
89
+ });
90
+ });
91
+ } else {
92
+ Object.keys(selectedGroups).forEach((group) => {
93
+ if (selectedGroups[group] !== selected[group].selected) {
94
+ changed.push({
95
+ parent: null,
96
+ selectedItem: group
97
+ });
98
+ selected[group].selected = selectedGroups[group];
99
+ }
100
+ });
101
+ }
102
+
103
+ dispatch('change', changed);
104
+ };
105
+
41
106
  const sortOptions = () => {
42
107
  // Sort facets in a descending order if count exits, or sort alphabetically
43
- Object.keys(groups).forEach((group) => {
44
- groups[group] = [
45
- ...selected[group].sort((a, b) => {
108
+ Object.keys(selected).forEach((group) => {
109
+ const checked = Object.keys(selected[group].children)
110
+ .filter((item) => selected[group].children[item].selected)
111
+ .map((item) => selected[group].children[item])
112
+ .sort((a, b) => {
46
113
  if (a.count != undefined && b.count != undefined) {
47
114
  return b.count - a.count;
48
115
  }
49
- return a.value.localeCompare(b.value);
50
- }),
51
- ...groups[group]
52
- .filter((item) => !selected[group].includes(item))
53
- .sort((a, b) => {
54
- if (a.count != undefined && b.count != undefined) {
55
- return b.count - a.count;
56
- }
57
- return a.value.localeCompare(b.value);
58
- })
116
+ return a.displayName.localeCompare(b.displayName);
117
+ })
118
+ .map((item) => item.name);
119
+
120
+ const unchecked = Object.keys(selected[group].children).filter(
121
+ (item) => !checked.includes(item)
122
+ );
123
+
124
+ const groupIndex = displayedGroups.findIndex((g) => g.name === group);
125
+
126
+ displayedGroups[groupIndex].children = [
127
+ ...checked.map(
128
+ (item) => displayedGroups[groupIndex].children.find((i) => i.name === item)!
129
+ ),
130
+ ...unchecked.map(
131
+ (item) => displayedGroups[groupIndex].children.find((i) => i.name === item)!
132
+ )
59
133
  ];
60
134
  });
61
135
  };
62
136
 
63
- $: selected, sortOptions();
137
+ $: selectedItems, mapSelected('items'), sortOptions();
138
+ $: selectedGroups, mapSelected('groups');
64
139
  </script>
65
140
 
66
141
  <TreeView selection={groupSelection} multiple={groupSelection} padding="p-1" hover="">
67
- {#each Object.keys(groups) as group}
142
+ {#each displayedGroups as group}
68
143
  <TreeViewItem
69
- name="groups"
70
- value={group}
144
+ name={group.name}
145
+ value={group.name}
71
146
  {open}
72
147
  hyphenOpacity="opacity-0"
148
+ bind:checked={selectedGroups[group.name]}
73
149
  bind:group={selectedGroups}
74
- bind:checked={selectedGroups[group]}
75
150
  >
76
- <p class="font-semibold">{group}</p>
151
+ <p class="font-semibold">{group.displayName}</p>
77
152
 
78
153
  <svelte:fragment slot="children">
79
154
  <!-- If more than 5 choices, show the remaining in the Modal -->
80
155
  {#if !showAll}
81
- {#each groups[group].slice(0, 5) as item}
156
+ {#each group.children.slice(0, 5) as item}
82
157
  <TreeViewItem
83
- bind:group={selected[group]}
84
- name={group}
85
- value={item}
158
+ bind:group={selectedItems[group.name]}
159
+ name={item.name}
160
+ value={item.displayName}
86
161
  hyphenOpacity="opacity-0"
162
+ bind:checked={selectedItems[group.name][item.name]}
87
163
  spacing="space-x-3"
88
164
  selection
89
165
  multiple
90
166
  >
91
- <p>{item.value} ({item.count})</p>
167
+ <p>{item.displayName} ({item.count})</p>
92
168
  </TreeViewItem>
93
169
  {/each}
94
170
  <!-- Trigger for the Modal to view all options -->
95
- {#if groups[group].length > 5}
171
+ {#if group.children.length > 5}
96
172
  <TreeViewItem hyphenOpacity="opacity-0">
97
- <button class="anchor" on:click={() => showMore(group)}>more</button></TreeViewItem
173
+ <button class="anchor" on:click={() => showMore(selected[group.name])}>more</button
174
+ ></TreeViewItem
98
175
  >
99
176
  {/if}
100
177
  {:else}
101
- {#each groups[group] as item}
178
+ {#each group.children as item}
102
179
  <TreeViewItem
103
- bind:group={selected[group]}
104
- name={group}
105
- value={item}
180
+ bind:group={selectedItems[group.name]}
181
+ bind:checked={selectedItems[group.name][item.name]}
182
+ name={item.name}
183
+ value={item.displayName}
106
184
  hyphenOpacity="opacity-0"
107
185
  spacing="space-x-3"
108
186
  selection
109
187
  multiple
110
188
  >
111
- <p>{item.value} ({item.count})</p>
189
+ <p>{item.displayName} ({item.count})</p>
112
190
  </TreeViewItem>
113
191
  {/each}
114
192
  {/if}
@@ -1,42 +1,34 @@
1
1
  <script lang="ts">
2
- import type { FacetOption } from '$models/Models';
2
+ import type { SelectedFacetGroup } from '$models/Models';
3
3
 
4
- export let group: string; // Group name
5
- export let items: FacetOption[]; // All possible choices
6
- export let selected: FacetOption[]; // Initially selected items
7
- export let handleSave: (group: string, selectedItems: FacetOption[]) => {};
4
+ export let group: SelectedFacetGroup;
5
+ export let handleSave: (group: SelectedFacetGroup) => {};
8
6
  export let handleCancel: () => {};
9
7
 
10
- // This local variable is needed for resetting the Modal when the user cancels selection.
11
- let selectedItems = selected; // Selected items in the Modal.
12
-
13
- const handleCheck = (e, index: number) => {
14
- const target = e.target as HTMLInputElement;
15
- if (target.checked) {
16
- selectedItems = [...selectedItems, items[index]];
17
- } else {
18
- selectedItems = selectedItems.filter((item) => item !== items[index]);
19
- }
20
- };
8
+ let selected = structuredClone(group.children);
21
9
 
22
10
  const selectAll = () => {
23
- selectedItems = items;
11
+ Object.keys(selected).forEach((key) => (selected[key].selected = true));
24
12
  };
25
13
 
26
14
  const selectNone = () => {
27
- selectedItems = [];
15
+ Object.keys(selected).forEach((key) => (selected[key].selected = false));
28
16
  };
29
17
 
30
18
  const onSave = () => {
31
- handleSave(group, selectedItems);
19
+ handleSave({
20
+ ...group,
21
+ children: selected
22
+ });
32
23
  };
33
24
 
34
25
  const onCancel = () => {
35
- selectedItems = selected;
26
+ console.log(selected, group.children);
27
+ selected = structuredClone(group.children);
36
28
  handleCancel();
37
29
  };
38
30
 
39
- const gridClass = (items: FacetOption[]) => {
31
+ const gridClass = (items: any[]) => {
40
32
  if (items.length >= 50) {
41
33
  return 'grid-cols-5';
42
34
  } else if (items.length >= 30) {
@@ -51,24 +43,20 @@
51
43
 
52
44
  <div class="p-5 rounded-md bg-surface-50 dark:bg-surface-800 border-primary-500 border-2">
53
45
  <!-- Header -->
54
- <h2 class="text-xl font-semibold">{group}</h2>
46
+ <h2 class="text-xl font-semibold">{group.displayName}</h2>
55
47
 
56
48
  <!-- Items -->
57
49
  <div
58
50
  class="grid {gridClass(
59
- items
51
+ Object.keys(selected)
60
52
  )} !gap-x-20 gap-y-2 py-10 px-2 max-h-[1000px] overflow-x-auto max-w-6xl"
61
53
  >
62
- {#each items as item, index}
54
+ {#each Object.keys(selected) as key}
63
55
  <label class="flex gap-3 items-center">
64
- <input
65
- type="checkbox"
66
- class="checkbox"
67
- value={item.value}
68
- on:click={(e) => handleCheck(e, index)}
69
- checked={selectedItems.includes(item)}
70
- />
71
- <span class="whitespace-nowrap break-before-avoid break-after-avoid">{item.value}</span>
56
+ <input type="checkbox" class="checkbox" bind:checked={selected[key].selected} />
57
+ <span class="whitespace-nowrap break-before-avoid break-after-avoid"
58
+ >{selected[key].displayName}</span
59
+ >
72
60
  </label>
73
61
  {/each}
74
62
  </div>
@@ -62,7 +62,7 @@
62
62
  let searchValue = '';
63
63
  let isFetching = false;
64
64
  const serverSide = server !== undefined;
65
- const { baseUrl, sendModel, entityId, versionId } = server ?? {};
65
+ const { baseUrl, entityId, versionId, sendModel = new Send() } = server ?? {};
66
66
 
67
67
  const filters = writable<{
68
68
  [key: string]: { [key in FilterOptionsEnum]?: number | string | Date };
@@ -429,7 +429,11 @@
429
429
  </form>
430
430
  {/if}
431
431
 
432
- <div class="flex justify-between items-center w-full {search && 'py-2'}">
432
+ <div
433
+ class="flex justify-between items-center w-full {search && 'py-2'} {!search &&
434
+ (shownColumns.length > 0 || toggle || resizable !== 'none' || exportable) &&
435
+ 'pb-2'}"
436
+ >
433
437
  <div>
434
438
  <!-- Enable the fitToScreen toggle if toggle === true -->
435
439
  {#if toggle}
@@ -244,7 +244,7 @@
244
244
  <Fa icon={faFilter} size="12" />
245
245
  </button>
246
246
 
247
- <div data-popup={popupId} id={popupId} class="">
247
+ <div data-popup={popupId} id={popupId} class="z-50">
248
248
  <div class="card p-3 grid gap-2 shadow-lg w-max bg-base-100">
249
249
  <button
250
250
  class="btn variant-filled-primary btn-sm"
package/src/lib/index.ts CHANGED
@@ -30,6 +30,9 @@ import TableFilter from './components/Table/TableFilter.svelte';
30
30
  import { columnFilter, searchFilter } from './components/Table/filter';
31
31
  import type { TableConfig, Columns, Column } from './models/Models';
32
32
 
33
+ //Facets
34
+ import Facets from './components/Facets/Facets.svelte';
35
+
33
36
  // CodeEditor
34
37
  import CodeEditor from './components/CodeEditor/CodeEditor.svelte';
35
38
 
@@ -103,6 +106,9 @@ export {
103
106
  // Table
104
107
  export { Table, TableFilter, columnFilter, searchFilter };
105
108
 
109
+ // Facets
110
+ export { Facets };
111
+
106
112
  // CodeEditor
107
113
  export { CodeEditor };
108
114
 
@@ -104,10 +104,10 @@ export interface Columns {
104
104
  [key: string]: Column;
105
105
  }
106
106
 
107
- // Server config type for the table
107
+ // Server config type for the table
108
108
  export type ServerConfig = {
109
109
  baseUrl?: string; // Base URL for server-side table
110
- sendModel: Send; // Send model for server-side table
110
+ sendModel?: Send; // Send model for server-side table
111
111
  entityId?: number; // Entity ID for server-side table
112
112
  versionId?: number; // Version ID for server-side table
113
113
  };
@@ -124,7 +124,7 @@ export interface TableConfig<T> {
124
124
  rowHeight?: number; // auto by default
125
125
  columns?: Columns;
126
126
  exportable?: boolean; // false by default
127
- pageSizes?: number[]; // [5, 10, 15, 20] by default
127
+ pageSizes?: number[]; // [5, 10, 20, 50, 100] by default
128
128
  defaultPageSize?: number; // 10 by default
129
129
  optionsComponent?: typeof SvelteComponent;
130
130
 
@@ -191,14 +191,29 @@ export type Filter = {
191
191
  value: string | number | Date | boolean;
192
192
  };
193
193
 
194
- export type FacetOption = {
195
- value: string;
194
+ export interface FacetOption {
195
+ name: string;
196
+ displayName: string;
196
197
  count?: number;
197
- };
198
+ }
198
199
 
199
- export type FacetGroup = {
200
- [key: string]: FacetOption[];
201
- };
200
+ export interface FacetGroup {
201
+ name: string;
202
+ displayName: string;
203
+ children: FacetOption[];
204
+ count?: number;
205
+ }
206
+
207
+ export interface SelectedFacetOption extends FacetOption {
208
+ selected: boolean;
209
+ }
210
+
211
+ export interface SelectedFacetGroup extends Omit<FacetGroup, 'children'> {
212
+ selected: boolean;
213
+ children: {
214
+ [key: string]: SelectedFacetOption;
215
+ };
216
+ }
202
217
 
203
218
  export class Send {
204
219
  id: number;
@@ -237,14 +252,13 @@ export class Receive {
237
252
  export class errorType {
238
253
  statusText: string;
239
254
  status: number;
240
- error:string;
241
- stackTrace:string
255
+ error: string;
256
+ stackTrace: string;
242
257
 
243
258
  constructor() {
244
- this.statusText = "";
259
+ this.statusText = '';
245
260
  this.status = 0;
246
- this.error = "";
247
- this.stackTrace = "";
261
+ this.error = '';
262
+ this.stackTrace = '';
248
263
  }
249
-
250
- };
264
+ }