@bexis2/bexis2-core-ui 0.4.18 → 0.4.20
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 +16 -8
- package/dist/components/CodeEditor/CodeEditor.svelte +4 -0
- package/dist/components/Facets/Facets.svelte +57 -20
- package/dist/components/Facets/Facets.svelte.d.ts +5 -1
- package/dist/components/Facets/ShowMore.svelte +31 -18
- package/dist/components/Facets/ShowMore.svelte.d.ts +2 -2
- package/dist/components/File/FileUploader.svelte +1 -1
- package/dist/components/Table/ColumnsMenu.svelte +5 -0
- package/dist/components/Table/TableContent.svelte +32 -16
- package/dist/components/Table/TableFilter.svelte +12 -0
- package/dist/components/Table/TableFilterServer.svelte +13 -1
- package/dist/components/Table/TablePagination.svelte +11 -6
- package/dist/components/Table/TablePaginationServer.svelte +8 -0
- package/dist/components/form/Checkbox.svelte +1 -1
- package/dist/components/form/CheckboxKvPList.svelte +2 -1
- package/dist/components/form/CheckboxList.svelte +2 -2
- package/dist/components/form/DateInput.svelte +1 -1
- package/dist/components/form/DropdownKvP.svelte +1 -1
- package/dist/components/form/InputContainer.svelte +7 -1
- package/dist/components/form/MultiSelect.svelte +100 -106
- package/dist/components/form/NumberInput.svelte +1 -1
- package/dist/components/form/TextArea.svelte +1 -1
- package/dist/components/form/TextInput.svelte +1 -1
- package/dist/components/page/Alert.svelte +1 -1
- package/dist/components/page/BackToTop.svelte +1 -1
- package/dist/components/page/Docs.svelte +1 -1
- package/dist/components/page/GoToTop.svelte +1 -0
- package/dist/components/page/HelpPopUp.svelte +1 -0
- package/dist/components/page/Page.svelte +14 -19
- package/dist/components/page/menu/MenuSublist.svelte +7 -5
- package/package.json +114 -114
- package/src/lib/components/CodeEditor/CodeEditor.svelte +4 -0
- package/src/lib/components/Facets/Facets.svelte +74 -25
- package/src/lib/components/Facets/ShowMore.svelte +33 -19
- package/src/lib/components/File/FileUploader.svelte +1 -1
- package/src/lib/components/Table/ColumnsMenu.svelte +5 -0
- package/src/lib/components/Table/TableContent.svelte +32 -16
- package/src/lib/components/Table/TableFilter.svelte +12 -0
- package/src/lib/components/Table/TableFilterServer.svelte +13 -1
- package/src/lib/components/Table/TablePagination.svelte +11 -6
- package/src/lib/components/Table/TablePaginationServer.svelte +8 -0
- package/src/lib/components/form/Checkbox.svelte +1 -1
- package/src/lib/components/form/CheckboxKvPList.svelte +2 -1
- package/src/lib/components/form/CheckboxList.svelte +2 -2
- package/src/lib/components/form/DateInput.svelte +1 -1
- package/src/lib/components/form/DropdownKvP.svelte +1 -1
- package/src/lib/components/form/InputContainer.svelte +7 -1
- package/src/lib/components/form/MultiSelect.svelte +100 -106
- package/src/lib/components/form/NumberInput.svelte +1 -1
- package/src/lib/components/form/TextArea.svelte +1 -1
- package/src/lib/components/form/TextInput.svelte +1 -1
- package/src/lib/components/page/Alert.svelte +1 -1
- package/src/lib/components/page/BackToTop.svelte +1 -1
- package/src/lib/components/page/Docs.svelte +1 -1
- package/src/lib/components/page/GoToTop.svelte +1 -0
- package/src/lib/components/page/HelpPopUp.svelte +1 -0
- package/src/lib/components/page/Page.svelte +15 -20
- package/src/lib/components/page/menu/MenuSublist.svelte +11 -8
package/README.md
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
# bexis-core-ui
|
|
2
|
+
|
|
3
|
+
## 0.4.20
|
|
4
|
+
- Add aria-label to Table and other components
|
|
5
|
+
- Facets
|
|
6
|
+
- Add aria-label to Facets component
|
|
7
|
+
- sort by count if exists, reorder more view, truncate long names,
|
|
8
|
+
- Search
|
|
9
|
+
- Add aria-label to Search component
|
|
10
|
+
- Table: add column
|
|
11
|
+
## 0.4.19
|
|
12
|
+
|
|
2
13
|
## 0.4.18
|
|
3
14
|
- Updates indicator text for current page and possible number of pages in a Table
|
|
4
15
|
- Fixes client-side search on Table
|
|
5
16
|
- Adds "No rows available" text in Table if search or filter returns no rows.
|
|
6
17
|
|
|
7
|
-
## 0.4.17
|
|
8
|
-
- Table
|
|
9
|
-
- Fix client-side search
|
|
10
18
|
## 0.4.16
|
|
11
19
|
- Facets
|
|
12
20
|
- Replaces groups array with a writable store to re-render component on data manipulation.
|
|
@@ -18,9 +26,9 @@
|
|
|
18
26
|
- Adds on:change action
|
|
19
27
|
|
|
20
28
|
## 0.4.14
|
|
21
|
-
- Table
|
|
29
|
+
- Table
|
|
22
30
|
- fixes rendering issues with Table filters and different components
|
|
23
|
-
|
|
31
|
+
|
|
24
32
|
- Facets
|
|
25
33
|
- Exports Facets component
|
|
26
34
|
|
|
@@ -44,7 +52,7 @@
|
|
|
44
52
|
- Updates the structure of server-side configuration for Tables.
|
|
45
53
|
- Adds new page size dropdown in Table for to fix contrast issues in the component.
|
|
46
54
|
- Adds showing/hiding Table columns.
|
|
47
|
-
|
|
55
|
+
|
|
48
56
|
- Facets:
|
|
49
57
|
- Adds Facets component.
|
|
50
58
|
|
|
@@ -72,7 +80,7 @@
|
|
|
72
80
|
- update libs
|
|
73
81
|
- remove eslint-plugin-svelte3
|
|
74
82
|
- update svelte, sveltekit, typescript, tailwind ...
|
|
75
|
-
|
|
83
|
+
|
|
76
84
|
## 0.4.3
|
|
77
85
|
- table
|
|
78
86
|
- Enable searching on server-side
|
|
@@ -103,7 +111,7 @@
|
|
|
103
111
|
|
|
104
112
|
## 0.3.11
|
|
105
113
|
- add on:change passthrough to TextInput, TextArea, DateInput, NumberInput, CheckBox
|
|
106
|
-
|
|
114
|
+
|
|
107
115
|
## 0.3.10
|
|
108
116
|
- multi select
|
|
109
117
|
- update svelte-select libary
|
|
@@ -82,6 +82,7 @@ $: isValid = language === "json" ? isValidJSON(value) : language === "js" ? isVa
|
|
|
82
82
|
<div class="flex gap-2">
|
|
83
83
|
<button
|
|
84
84
|
class="btn variant-filled-warning"
|
|
85
|
+
title="Reset"
|
|
85
86
|
id="{id}-reset"
|
|
86
87
|
on:click|preventDefault={() => modalStore.trigger(modal)}
|
|
87
88
|
><Fa icon={faArrowRotateLeft} /></button
|
|
@@ -90,6 +91,7 @@ $: isValid = language === "json" ? isValidJSON(value) : language === "js" ? isVa
|
|
|
90
91
|
class="btn border"
|
|
91
92
|
class:bg-slate-700={dark}
|
|
92
93
|
class:bg-white={!dark}
|
|
94
|
+
title="Toggle dark mode"
|
|
93
95
|
id="{id}-toggle"
|
|
94
96
|
on:click|preventDefault={() => (dark = !dark)}
|
|
95
97
|
>
|
|
@@ -106,11 +108,13 @@ $: isValid = language === "json" ? isValidJSON(value) : language === "js" ? isVa
|
|
|
106
108
|
<div class="flex gap-2">
|
|
107
109
|
<button
|
|
108
110
|
class="btn variant-filled-warning"
|
|
111
|
+
title="Cancel"
|
|
109
112
|
id="{id}-cancel"
|
|
110
113
|
on:click|preventDefault={() => dispatch('cancel')}><Fa icon={faXmark} /></button
|
|
111
114
|
>
|
|
112
115
|
<button
|
|
113
116
|
class="btn variant-filled-primary"
|
|
117
|
+
title="Save"
|
|
114
118
|
id="{id}-save"
|
|
115
119
|
disabled={!isValid}
|
|
116
120
|
on:click|preventDefault={() => dispatch('save')}><Fa icon={faSave} /></button
|
|
@@ -5,12 +5,12 @@ export let groupSelection = false;
|
|
|
5
5
|
export let groups;
|
|
6
6
|
export let showAll = false;
|
|
7
7
|
export let open = false;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
export const showMore = (groupName) => {
|
|
9
|
+
const group = selected[groupName];
|
|
10
|
+
dispatch("showMoreOpenChange", {
|
|
11
|
+
group: group.name,
|
|
12
|
+
open: true
|
|
13
|
+
});
|
|
14
14
|
modalStore.trigger({
|
|
15
15
|
type: "component",
|
|
16
16
|
title: `${group.displayName}`,
|
|
@@ -18,19 +18,43 @@ const showMore = (group) => {
|
|
|
18
18
|
ref: ShowMore,
|
|
19
19
|
props: {
|
|
20
20
|
group,
|
|
21
|
-
|
|
21
|
+
handleApply,
|
|
22
22
|
handleCancel
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
26
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
let selected;
|
|
28
|
+
let selectedItems = {};
|
|
29
|
+
let selectedGroups = {};
|
|
30
|
+
const dispatch = createEventDispatcher();
|
|
31
|
+
const modalStore = getModalStore();
|
|
32
|
+
const handleApply = (group) => {
|
|
33
|
+
const { name: groupName, children } = group;
|
|
34
|
+
dispatch("showMoreOpenChange", {
|
|
35
|
+
group: groupName,
|
|
36
|
+
open: false
|
|
30
37
|
});
|
|
38
|
+
for (const key in children) {
|
|
39
|
+
const selectedValue = children[key].selected || false;
|
|
40
|
+
selectedItems[groupName][key] = selectedValue;
|
|
41
|
+
if (selected[groupName].children[key].selected !== selectedValue) {
|
|
42
|
+
selected[groupName].children[key].selected = selectedValue;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
dispatch("showMoreSelect", [
|
|
46
|
+
{
|
|
47
|
+
parent: groupName,
|
|
48
|
+
selected: Object.keys(children).map((key) => children[key].selected)
|
|
49
|
+
}
|
|
50
|
+
]);
|
|
31
51
|
modalStore.close();
|
|
32
52
|
};
|
|
33
|
-
const handleCancel = () => {
|
|
53
|
+
const handleCancel = (groupName) => {
|
|
54
|
+
dispatch("showMoreOpenChange", {
|
|
55
|
+
group: groupName,
|
|
56
|
+
open: false
|
|
57
|
+
});
|
|
34
58
|
modalStore.close();
|
|
35
59
|
};
|
|
36
60
|
const mapSelected = (type) => {
|
|
@@ -58,7 +82,7 @@ const mapSelected = (type) => {
|
|
|
58
82
|
}
|
|
59
83
|
});
|
|
60
84
|
}
|
|
61
|
-
changed.length && dispatch("
|
|
85
|
+
changed.length && dispatch("facetSelect", changed);
|
|
62
86
|
};
|
|
63
87
|
const sortOptions = () => {
|
|
64
88
|
Object.keys(selected).forEach((group) => {
|
|
@@ -66,11 +90,14 @@ const sortOptions = () => {
|
|
|
66
90
|
if (a.count != void 0 && b.count != void 0) {
|
|
67
91
|
return b.count - a.count;
|
|
68
92
|
}
|
|
69
|
-
return
|
|
93
|
+
return 0;
|
|
94
|
+
}).map((item) => item.name);
|
|
95
|
+
const unchecked = Object.keys(selected[group].children).filter((item) => !checked.includes(item)).map((item) => selected[group].children[item]).sort((a, b) => {
|
|
96
|
+
if (a.count != void 0 && b.count != void 0) {
|
|
97
|
+
return b.count - a.count;
|
|
98
|
+
}
|
|
99
|
+
return 0;
|
|
70
100
|
}).map((item) => item.name);
|
|
71
|
-
const unchecked = Object.keys(selected[group].children).filter(
|
|
72
|
-
(item) => !checked.includes(item)
|
|
73
|
-
);
|
|
74
101
|
const groupIndex = displayedGroups.findIndex((g) => g.name === group);
|
|
75
102
|
displayedGroups[groupIndex].children = [
|
|
76
103
|
...checked.map(
|
|
@@ -121,7 +148,7 @@ $: selectedGroups, mapSelected("groups");
|
|
|
121
148
|
bind:checked={selectedGroups[group.name]}
|
|
122
149
|
bind:group={selectedGroups}
|
|
123
150
|
>
|
|
124
|
-
<p class="font-semibold">
|
|
151
|
+
<p class="font-semibold whitespace-nowrap">
|
|
125
152
|
{group.displayName}{group.count !== undefined ? ` (${group.count})` : ''}
|
|
126
153
|
</p>
|
|
127
154
|
|
|
@@ -139,13 +166,18 @@ $: selectedGroups, mapSelected("groups");
|
|
|
139
166
|
selection
|
|
140
167
|
multiple
|
|
141
168
|
>
|
|
142
|
-
<
|
|
169
|
+
<div class="flex gap-2">
|
|
170
|
+
<p class="w-max grow truncate">
|
|
171
|
+
<span title={item.displayName}>{item.displayName}</span>
|
|
172
|
+
</p>
|
|
173
|
+
<span>({item.count})</span>
|
|
174
|
+
</div>
|
|
143
175
|
</TreeViewItem>
|
|
144
176
|
{/each}
|
|
145
177
|
<!-- Trigger for the Modal to view all options -->
|
|
146
178
|
{#if group.children.length > 5}
|
|
147
179
|
<TreeViewItem hyphenOpacity="opacity-0">
|
|
148
|
-
<button class="anchor" on:click={() => showMore(
|
|
180
|
+
<button class="anchor" on:click={() => showMore(group.name)}>more</button
|
|
149
181
|
></TreeViewItem
|
|
150
182
|
>
|
|
151
183
|
{/if}
|
|
@@ -161,7 +193,12 @@ $: selectedGroups, mapSelected("groups");
|
|
|
161
193
|
selection
|
|
162
194
|
multiple
|
|
163
195
|
>
|
|
164
|
-
<
|
|
196
|
+
<div class="flex gap-2">
|
|
197
|
+
<p class="w-max grow truncate">
|
|
198
|
+
<span title={item.displayName}>{item.displayName}</span>
|
|
199
|
+
</p>
|
|
200
|
+
<span>({item.count})</span>
|
|
201
|
+
</div>
|
|
165
202
|
</TreeViewItem>
|
|
166
203
|
{/each}
|
|
167
204
|
{/if}
|
|
@@ -7,9 +7,12 @@ declare const __propDef: {
|
|
|
7
7
|
groups: Writable<FacetGroup[]>;
|
|
8
8
|
showAll?: boolean;
|
|
9
9
|
open?: boolean;
|
|
10
|
+
showMore?: (groupName: string) => void;
|
|
10
11
|
};
|
|
11
12
|
events: {
|
|
12
|
-
|
|
13
|
+
showMoreOpenChange: CustomEvent<any>;
|
|
14
|
+
showMoreSelect: CustomEvent<any>;
|
|
15
|
+
facetSelect: CustomEvent<any>;
|
|
13
16
|
} & {
|
|
14
17
|
[evt: string]: CustomEvent<any>;
|
|
15
18
|
};
|
|
@@ -19,5 +22,6 @@ export type FacetsProps = typeof __propDef.props;
|
|
|
19
22
|
export type FacetsEvents = typeof __propDef.events;
|
|
20
23
|
export type FacetsSlots = typeof __propDef.slots;
|
|
21
24
|
export default class Facets extends SvelteComponent<FacetsProps, FacetsEvents, FacetsSlots> {
|
|
25
|
+
get showMore(): (groupName: string) => void;
|
|
22
26
|
}
|
|
23
27
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script>export let group;
|
|
2
|
-
export let
|
|
2
|
+
export let handleApply;
|
|
3
3
|
export let handleCancel;
|
|
4
4
|
let selected = structuredClone(group.children);
|
|
5
5
|
const selectAll = () => {
|
|
@@ -8,8 +8,8 @@ const selectAll = () => {
|
|
|
8
8
|
const selectNone = () => {
|
|
9
9
|
Object.keys(selected).forEach((key) => selected[key].selected = false);
|
|
10
10
|
};
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const onApply = () => {
|
|
12
|
+
handleApply({
|
|
13
13
|
...group,
|
|
14
14
|
children: selected
|
|
15
15
|
});
|
|
@@ -17,34 +17,47 @@ const onSave = () => {
|
|
|
17
17
|
const onCancel = () => {
|
|
18
18
|
console.log(selected, group.children);
|
|
19
19
|
selected = structuredClone(group.children);
|
|
20
|
-
handleCancel();
|
|
20
|
+
handleCancel(group.name);
|
|
21
21
|
};
|
|
22
22
|
const gridClass = (items) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
const ceil = Math.ceil(Math.sqrt(items.length));
|
|
24
|
+
const max = Math.max(ceil, Math.floor(items.length / 3));
|
|
25
|
+
const classes = [
|
|
26
|
+
"grid-rows-1",
|
|
27
|
+
"grid-rows-2",
|
|
28
|
+
"grid-rows-3",
|
|
29
|
+
"grid-rows-4",
|
|
30
|
+
"grid-rows-5",
|
|
31
|
+
"grid-rows-6",
|
|
32
|
+
"grid-rows-7",
|
|
33
|
+
"grid-rows-8",
|
|
34
|
+
"grid-rows-9",
|
|
35
|
+
"grid-rows-10",
|
|
36
|
+
"grid-rows-11",
|
|
37
|
+
"grid-rows-12"
|
|
38
|
+
];
|
|
39
|
+
if (max > 12) {
|
|
40
|
+
return "grid-rows-12";
|
|
41
|
+
} else return classes[max - 1 || 1];
|
|
31
42
|
};
|
|
32
43
|
</script>
|
|
33
44
|
|
|
34
|
-
<div class="p-5 rounded-md bg-surface-50 dark:bg-surface-800 border-primary-500 border-2">
|
|
45
|
+
<div class="p-5 rounded-md max-w-6xl bg-surface-50 dark:bg-surface-800 border-primary-500 border-2">
|
|
35
46
|
<!-- Header -->
|
|
36
47
|
<h2 class="text-xl font-semibold">{group.displayName}</h2>
|
|
37
48
|
|
|
38
49
|
<!-- Items -->
|
|
39
50
|
<div
|
|
40
|
-
class="
|
|
51
|
+
class="{gridClass(
|
|
41
52
|
Object.keys(selected)
|
|
42
|
-
)}
|
|
53
|
+
)} grid grid-flow-col gap-x-10 gap-y-2 py-10 px-2 h-full overflow-x-auto"
|
|
43
54
|
>
|
|
44
55
|
{#each Object.keys(selected) as key}
|
|
45
|
-
<label class="flex gap-3 items-center">
|
|
56
|
+
<label class="flex gap-3 items-center w-48">
|
|
46
57
|
<input type="checkbox" class="checkbox" bind:checked={selected[key].selected} />
|
|
47
|
-
<span
|
|
58
|
+
<span
|
|
59
|
+
title={selected[key].displayName}
|
|
60
|
+
class="whitespace-nowrap break-before-avoid break-after-avoid truncate"
|
|
48
61
|
>{selected[key].displayName}</span
|
|
49
62
|
>
|
|
50
63
|
</label>
|
|
@@ -58,7 +71,7 @@ const gridClass = (items) => {
|
|
|
58
71
|
<button class="btn btn-sm variant-filled-tertiary" on:click={selectAll}>All</button>
|
|
59
72
|
</div>
|
|
60
73
|
<div class="flex gap-3">
|
|
61
|
-
<button class="btn btn-sm variant-filled-primary" on:click={
|
|
74
|
+
<button class="btn btn-sm variant-filled-primary" on:click={onApply}>Apply</button>
|
|
62
75
|
<button class="btn btn-sm variant-filled-secondary" on:click={onCancel}>Cancel</button>
|
|
63
76
|
</div>
|
|
64
77
|
</div>
|
|
@@ -3,8 +3,8 @@ import type { SelectedFacetGroup } from '../../models/Models';
|
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
5
|
group: SelectedFacetGroup;
|
|
6
|
-
|
|
7
|
-
handleCancel: () => {};
|
|
6
|
+
handleApply: (group: SelectedFacetGroup) => {};
|
|
7
|
+
handleCancel: (groupName: string) => {};
|
|
8
8
|
};
|
|
9
9
|
events: {
|
|
10
10
|
[evt: string]: CustomEvent<any>;
|
|
@@ -121,7 +121,7 @@ async function handleSubmit() {
|
|
|
121
121
|
{/if}
|
|
122
122
|
</div>
|
|
123
123
|
|
|
124
|
-
<button id={submitBt} color="primary" style="display:none"><Fa icon={faSave} /></button>
|
|
124
|
+
<button title="Submit" id={submitBt} color="primary" style="display:none"><Fa icon={faSave} /></button>
|
|
125
125
|
{:else}
|
|
126
126
|
<!-- while data is not loaded show a loading information -->
|
|
127
127
|
|
|
@@ -10,7 +10,9 @@ const popupCombobox = {
|
|
|
10
10
|
|
|
11
11
|
<button
|
|
12
12
|
type="button"
|
|
13
|
+
title="Hide or show columns"
|
|
13
14
|
class="btn btn-sm variant-filled-primary rounded-full order-last"
|
|
15
|
+
aria-label="Open menu to hide/show columns"
|
|
14
16
|
use:popup={popupCombobox}>Columns</button
|
|
15
17
|
>
|
|
16
18
|
|
|
@@ -20,8 +22,11 @@ const popupCombobox = {
|
|
|
20
22
|
>
|
|
21
23
|
{#each columns as column}
|
|
22
24
|
<div class="flex gap-3 items-center">
|
|
25
|
+
<label for={column.id} class="cursor-pointer" title={column.label}></label>
|
|
23
26
|
<input
|
|
27
|
+
aria-label="Toggle column visibility for column {column.label}"
|
|
24
28
|
type="checkbox"
|
|
29
|
+
id = {column.id}
|
|
25
30
|
bind:checked={column.visible}
|
|
26
31
|
disabled={columns.filter((c) => c.visible).length === 1 && column.visible}
|
|
27
32
|
/>
|
|
@@ -143,8 +143,8 @@ const tableColumns = [
|
|
|
143
143
|
header: header ?? key,
|
|
144
144
|
accessor,
|
|
145
145
|
// Render the cell with the provided component, or use the toStringFn if provided, or just use the value
|
|
146
|
-
cell: ({ value, row }) => {
|
|
147
|
-
return renderComponent ? createRender(renderComponent, { value, row, dispatchFn: actionDispatcher }) : toStringFn ? toStringFn(value) : value;
|
|
146
|
+
cell: ({ value, row, column }) => {
|
|
147
|
+
return renderComponent ? createRender(renderComponent, { value, row, column, dispatchFn: actionDispatcher }) : toStringFn ? toStringFn(value) : value;
|
|
148
148
|
},
|
|
149
149
|
plugins: {
|
|
150
150
|
// Sorting config
|
|
@@ -322,10 +322,11 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
|
|
|
322
322
|
class="flex gap-2"
|
|
323
323
|
on:submit|preventDefault={() => {
|
|
324
324
|
if (serverSide && !sendModel) {
|
|
325
|
-
throw new Error('Server-side configuration is missing');
|
|
326
|
-
} else {
|
|
327
|
-
sendModel.q = searchValue;
|
|
328
|
-
}
|
|
325
|
+
throw new Error('Server-side configuration is missing');
|
|
326
|
+
} else {
|
|
327
|
+
sendModel.q = searchValue;
|
|
328
|
+
}
|
|
329
|
+
|
|
329
330
|
$filterValue = searchValue;
|
|
330
331
|
}}
|
|
331
332
|
>
|
|
@@ -333,21 +334,22 @@ sendModel.q = searchValue;
|
|
|
333
334
|
<input
|
|
334
335
|
class="input p-2 border border-primary-500"
|
|
335
336
|
type="text"
|
|
337
|
+
title="Search within all table rows"
|
|
336
338
|
bind:value={searchValue}
|
|
337
339
|
placeholder="Search rows..."
|
|
338
340
|
id="{tableId}-search"
|
|
339
341
|
/><button
|
|
340
342
|
type="reset"
|
|
343
|
+
title="Clear search"
|
|
341
344
|
id="{tableId}-searchReset"
|
|
342
345
|
class="absolute right-3 items-center"
|
|
346
|
+
aria-label="Clear search"
|
|
343
347
|
on:click|preventDefault={() => {
|
|
344
348
|
if (serverSide && !sendModel) {
|
|
345
|
-
throw new Error('Server-side configuration is missing');
|
|
346
|
-
} else {
|
|
347
|
-
sendModel.q = '';
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
$filterValue = searchValue;
|
|
349
|
+
throw new Error('Server-side configuration is missing');
|
|
350
|
+
} else {
|
|
351
|
+
sendModel.q = '';
|
|
352
|
+
}
|
|
351
353
|
|
|
352
354
|
searchValue = '';
|
|
353
355
|
$filterValue = '';
|
|
@@ -356,14 +358,15 @@ sendModel.q = '';
|
|
|
356
358
|
</div>
|
|
357
359
|
<button
|
|
358
360
|
type="submit"
|
|
361
|
+
title="Search"
|
|
359
362
|
id="{tableId}-searchSubmit"
|
|
360
363
|
class="btn variant-filled-primary"
|
|
361
364
|
on:click|preventDefault={() => {
|
|
362
365
|
if (serverSide && !sendModel) {
|
|
363
|
-
throw new Error('Server-side configuration is missing');
|
|
364
|
-
} else {
|
|
365
|
-
sendModel.q = searchValue;
|
|
366
|
-
}
|
|
366
|
+
throw new Error('Server-side configuration is missing');
|
|
367
|
+
} else {
|
|
368
|
+
sendModel.q = searchValue;
|
|
369
|
+
}
|
|
367
370
|
|
|
368
371
|
$filterValue = searchValue;
|
|
369
372
|
}}>Search</button
|
|
@@ -381,6 +384,7 @@ sendModel.q = searchValue;
|
|
|
381
384
|
{#if toggle}
|
|
382
385
|
<SlideToggle
|
|
383
386
|
name="slider-label"
|
|
387
|
+
label="Fit to screen"
|
|
384
388
|
active="bg-primary-500"
|
|
385
389
|
size="sm"
|
|
386
390
|
checked={fitToScreen}
|
|
@@ -394,6 +398,7 @@ sendModel.q = searchValue;
|
|
|
394
398
|
{#if resizable !== 'none'}
|
|
395
399
|
<button
|
|
396
400
|
type="button"
|
|
401
|
+
title="Reset column and row sizing"
|
|
397
402
|
class="btn btn-sm variant-filled-primary rounded-full order-last"
|
|
398
403
|
on:click|preventDefault={() =>
|
|
399
404
|
resetResize($headerRows, $pageRows, tableId, columns, resizable)}
|
|
@@ -403,6 +408,7 @@ sendModel.q = searchValue;
|
|
|
403
408
|
{#if exportable}
|
|
404
409
|
<button
|
|
405
410
|
type="button"
|
|
411
|
+
title="Export table data as CSV"
|
|
406
412
|
class="btn btn-sm variant-filled-primary rounded-full order-last"
|
|
407
413
|
on:click|preventDefault={() => exportAsCsv(tableId, $exportedData)}
|
|
408
414
|
>Export as CSV</button
|
|
@@ -419,6 +425,7 @@ sendModel.q = searchValue;
|
|
|
419
425
|
{...$tableAttrs}
|
|
420
426
|
class="table table-auto table-compact bg-tertiary-500/30 dark:bg-tertiary-900/10 overflow-clip"
|
|
421
427
|
id="{tableId}-table"
|
|
428
|
+
title="Table"
|
|
422
429
|
>
|
|
423
430
|
<!-- If table height is provided, making the top row sticky -->
|
|
424
431
|
<thead class={height != null && $pageRows.length > 0 ? `sticky top-0` : ''}>
|
|
@@ -444,6 +451,8 @@ sendModel.q = searchValue;
|
|
|
444
451
|
<div class="flex gap-1 whitespace-pre-wrap">
|
|
445
452
|
<!-- Adding sorting config and styling -->
|
|
446
453
|
<span
|
|
454
|
+
role="button"
|
|
455
|
+
tabindex="0"
|
|
447
456
|
class:underline={props.sort.order}
|
|
448
457
|
class:normal-case={cell.id !== cell.label}
|
|
449
458
|
class:cursor-pointer={!props.sort.disabled}
|
|
@@ -506,6 +515,13 @@ sendModel.q = searchValue;
|
|
|
506
515
|
{/each}
|
|
507
516
|
</tbody>
|
|
508
517
|
</table>
|
|
518
|
+
{#if $pageRows.length === 0}
|
|
519
|
+
<div
|
|
520
|
+
class="p-8 flex items-center justify-center bg-tertiary-500/30 dark:bg-tertiary-900/10"
|
|
521
|
+
>
|
|
522
|
+
No rows available
|
|
523
|
+
</div>
|
|
524
|
+
{/if}
|
|
509
525
|
</div>
|
|
510
526
|
</div>
|
|
511
527
|
{:else}
|
|
@@ -201,6 +201,7 @@ onMount(() => {
|
|
|
201
201
|
type="button"
|
|
202
202
|
use:popup={popupFeatured}
|
|
203
203
|
id="{popupId}-button"
|
|
204
|
+
aria-label="Open filter menu for column {id}"
|
|
204
205
|
>
|
|
205
206
|
<Fa icon={faFilter} size="12" />
|
|
206
207
|
</button>
|
|
@@ -210,6 +211,7 @@ onMount(() => {
|
|
|
210
211
|
<button
|
|
211
212
|
class="btn variant-filled-primary btn-sm"
|
|
212
213
|
type="button"
|
|
214
|
+
aria-label="Clear Filters"
|
|
213
215
|
on:click|preventDefault={() => {
|
|
214
216
|
// Set the defaults when cleared
|
|
215
217
|
clearFilters();
|
|
@@ -234,6 +236,7 @@ onMount(() => {
|
|
|
234
236
|
{#each options[type] as option (option)}
|
|
235
237
|
<option
|
|
236
238
|
value={option.value}
|
|
239
|
+
aria-label={option.label}
|
|
237
240
|
selected={dropdown.option === option.value}
|
|
238
241
|
disabled={Object.keys($filters[id]).includes(option.value) &&
|
|
239
242
|
dropdown.option !== option.value}>{option.label}</option
|
|
@@ -242,7 +245,10 @@ onMount(() => {
|
|
|
242
245
|
</select>
|
|
243
246
|
{#if dropdowns.length > 1}
|
|
244
247
|
<div
|
|
248
|
+
role="button"
|
|
249
|
+
tabindex="0"
|
|
245
250
|
class="btn variant-filled-warning btn-sm h-full"
|
|
251
|
+
aria-label="Remove filter"
|
|
246
252
|
on:click|preventDefault={() => removeFilter(dropdown.option)}
|
|
247
253
|
on:keydown|preventDefault={() => removeFilter(dropdown.option)}
|
|
248
254
|
>
|
|
@@ -257,6 +263,7 @@ onMount(() => {
|
|
|
257
263
|
class="input p-1 border border-primary-500"
|
|
258
264
|
on:input={(e) => valueChangeHandler(e, index)}
|
|
259
265
|
bind:value={dropdown.value}
|
|
266
|
+
aria-label="Filter value"
|
|
260
267
|
/>
|
|
261
268
|
{:else}
|
|
262
269
|
<input
|
|
@@ -264,6 +271,7 @@ onMount(() => {
|
|
|
264
271
|
class="input p-1 border border-primary-500"
|
|
265
272
|
on:input={(e) => valueChangeHandler(e, index)}
|
|
266
273
|
bind:value={dropdown.formValue}
|
|
274
|
+
aria-label="Filter value"
|
|
267
275
|
/>
|
|
268
276
|
{/if}
|
|
269
277
|
</div>
|
|
@@ -276,12 +284,15 @@ onMount(() => {
|
|
|
276
284
|
{#if remainingFilters.length}
|
|
277
285
|
<div
|
|
278
286
|
class="btn variant-filled-secondary btn-sm cursor-pointer"
|
|
287
|
+
role="button"
|
|
288
|
+
tabindex="0"
|
|
279
289
|
on:click|stopPropagation={() => {
|
|
280
290
|
addFilter(remainingFilters[0].value, undefined);
|
|
281
291
|
}}
|
|
282
292
|
on:keydown|stopPropagation={() => {
|
|
283
293
|
addFilter(remainingFilters[0].value, undefined);
|
|
284
294
|
}}
|
|
295
|
+
aria-label="Add filter"
|
|
285
296
|
>
|
|
286
297
|
<div class="flex gap-1 items-center"><Fa icon={faPlus} />Add Filter</div>
|
|
287
298
|
</div>
|
|
@@ -289,6 +300,7 @@ onMount(() => {
|
|
|
289
300
|
<button
|
|
290
301
|
class="btn variant-filled-primary btn-sm"
|
|
291
302
|
type="button"
|
|
303
|
+
aria-label="Apply filters"
|
|
292
304
|
on:click|preventDefault={() => {
|
|
293
305
|
$pageIndex = 0;
|
|
294
306
|
$filterValue = $filters[id];
|
|
@@ -190,6 +190,7 @@ $: console.log($filters);
|
|
|
190
190
|
type="button"
|
|
191
191
|
use:popup={popupFeatured}
|
|
192
192
|
id="{popupId}-button"
|
|
193
|
+
aria-label="Open filter menu for column {id}"
|
|
193
194
|
>
|
|
194
195
|
<Fa icon={faFilter} size="12" />
|
|
195
196
|
</button>
|
|
@@ -199,6 +200,7 @@ $: console.log($filters);
|
|
|
199
200
|
<button
|
|
200
201
|
class="btn variant-filled-primary btn-sm"
|
|
201
202
|
type="button"
|
|
203
|
+
aria-label="Clear Filters"
|
|
202
204
|
on:click|preventDefault={() => {
|
|
203
205
|
// Set the defaults when cleared
|
|
204
206
|
clearFilters();
|
|
@@ -221,6 +223,7 @@ $: console.log($filters);
|
|
|
221
223
|
{#each options[type] as option (option)}
|
|
222
224
|
<option
|
|
223
225
|
value={option.value}
|
|
226
|
+
aria-label={option.label}
|
|
224
227
|
selected={dropdown.option === option.value}
|
|
225
228
|
disabled={Object.keys($filters[id]).includes(option.value) &&
|
|
226
229
|
dropdown.option !== option.value}>{option.label}</option
|
|
@@ -229,10 +232,13 @@ $: console.log($filters);
|
|
|
229
232
|
</select>
|
|
230
233
|
{#if dropdowns.length > 1}
|
|
231
234
|
<div
|
|
235
|
+
role="button"
|
|
236
|
+
tabindex="0"
|
|
232
237
|
class="btn variant-filled-warning btn-sm h-full"
|
|
233
238
|
on:click|preventDefault={() => removeFilter(dropdown.option)}
|
|
234
239
|
on:keydown|preventDefault={() => removeFilter(dropdown.option)}
|
|
235
|
-
|
|
240
|
+
aria-label="Remove filter"
|
|
241
|
+
>
|
|
236
242
|
<Fa icon={faXmark} />
|
|
237
243
|
</div>
|
|
238
244
|
{/if}
|
|
@@ -251,6 +257,7 @@ $: console.log($filters);
|
|
|
251
257
|
class="input p-1 border border-primary-500"
|
|
252
258
|
on:input={(e) => valueChangeHandler(e, index)}
|
|
253
259
|
bind:value={dropdown.value}
|
|
260
|
+
aria-label="Filter value"
|
|
254
261
|
/>
|
|
255
262
|
{:else}
|
|
256
263
|
<input
|
|
@@ -258,6 +265,7 @@ $: console.log($filters);
|
|
|
258
265
|
class="input p-1 border border-primary-500"
|
|
259
266
|
on:input={(e) => valueChangeHandler(e, index)}
|
|
260
267
|
bind:value={dropdown.value}
|
|
268
|
+
aria-label="Filter value"
|
|
261
269
|
/>
|
|
262
270
|
{/if}
|
|
263
271
|
</div>
|
|
@@ -270,6 +278,9 @@ $: console.log($filters);
|
|
|
270
278
|
{#if remainingFilters.length}
|
|
271
279
|
<div
|
|
272
280
|
class="btn variant-filled-secondary btn-sm cursor-pointer"
|
|
281
|
+
aria-label="Add filter"
|
|
282
|
+
role="button"
|
|
283
|
+
tabindex="0"
|
|
273
284
|
on:click|stopPropagation={() => {
|
|
274
285
|
addFilter(remainingFilters[0].value, undefined);
|
|
275
286
|
}}
|
|
@@ -283,6 +294,7 @@ $: console.log($filters);
|
|
|
283
294
|
<button
|
|
284
295
|
class="btn variant-filled-primary btn-sm"
|
|
285
296
|
type="button"
|
|
297
|
+
aria-label="Apply filters"
|
|
286
298
|
on:click|preventDefault={applyFilters}>Apply</button
|
|
287
299
|
>
|
|
288
300
|
</div>
|