@bexis2/bexis2-core-ui 0.2.15 → 0.2.16
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 +8 -1
- package/dist/components/Table/Table.svelte +101 -86
- package/dist/components/Table/TableFilter.svelte +2 -2
- package/dist/models/Models.d.ts +1 -0
- package/package.json +1 -1
- package/src/lib/components/Table/Table.svelte +262 -246
- package/src/lib/components/Table/TableFilter.svelte +2 -2
- package/src/lib/models/Models.ts +134 -133
package/README.md
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# bexis-core-ui
|
|
2
|
+
## v0.2.16
|
|
3
|
+
- Table
|
|
4
|
+
- width - fit to screen
|
|
5
|
+
- Cell - drag to change the height
|
|
6
|
+
- define a height to scroll the content
|
|
7
|
+
- header allways on top whie scrolling
|
|
8
|
+
|
|
2
9
|
## v0.2.15
|
|
3
10
|
- Page - centered -> min width defined
|
|
4
|
-
- MultiSelect -> add
|
|
11
|
+
- MultiSelect -> add clearable
|
|
5
12
|
|
|
6
13
|
## v0.2.14
|
|
7
14
|
- change fileUploaderModel to FileUploaderType
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
addTableFilter
|
|
9
9
|
} from "svelte-headless-table/plugins";
|
|
10
10
|
import { computePosition, autoUpdate, offset, shift, flip, arrow } from "@floating-ui/dom";
|
|
11
|
-
import { storePopup } from "@skeletonlabs/skeleton";
|
|
11
|
+
import { SlideToggle, storePopup } from "@skeletonlabs/skeleton";
|
|
12
12
|
storePopup.set({ computePosition, autoUpdate, offset, shift, flip, arrow });
|
|
13
13
|
import TableFilter from "./TableFilter.svelte";
|
|
14
14
|
import TablePagination from "./TablePagination.svelte";
|
|
@@ -18,10 +18,12 @@ let {
|
|
|
18
18
|
id: tableId,
|
|
19
19
|
data,
|
|
20
20
|
columns,
|
|
21
|
+
height = null,
|
|
21
22
|
optionsComponent,
|
|
22
23
|
defaultPageSize = 10,
|
|
23
24
|
pageSizes = [5, 10, 15, 20]
|
|
24
25
|
} = config;
|
|
26
|
+
let fitToScreen = true;
|
|
25
27
|
const dispatch = createEventDispatcher();
|
|
26
28
|
const actionDispatcher = (obj) => dispatch("action", obj);
|
|
27
29
|
const table = createTable(data, {
|
|
@@ -128,88 +130,101 @@ if (optionsComponent !== void 0) {
|
|
|
128
130
|
const createdTableColumns = table.createColumns(tableColumns);
|
|
129
131
|
const { headerRows, pageRows, tableAttrs, tableBodyAttrs, pluginStates } = table.createViewModel(createdTableColumns);
|
|
130
132
|
const { filterValue } = pluginStates.tableFilter;
|
|
131
|
-
</script>
|
|
132
|
-
|
|
133
|
-
<div class="grid gap-2">
|
|
134
|
-
<div class="table-container">
|
|
135
|
-
{#if $data.length > 0}
|
|
136
|
-
<input
|
|
137
|
-
class="input p-2 mb-2 border border-primary-500"
|
|
138
|
-
type="text"
|
|
139
|
-
bind:value={$filterValue}
|
|
140
|
-
placeholder="Search rows..."
|
|
141
|
-
/>
|
|
142
|
-
{/if}
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
{
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
</
|
|
133
|
+
</script>
|
|
134
|
+
|
|
135
|
+
<div class="grid gap-2 overflow-auto" class:w-max={!fitToScreen} class:w-full={fitToScreen}>
|
|
136
|
+
<div class="table-container">
|
|
137
|
+
{#if $data.length > 0}
|
|
138
|
+
<input
|
|
139
|
+
class="input p-2 mb-2 border border-primary-500"
|
|
140
|
+
type="text"
|
|
141
|
+
bind:value={$filterValue}
|
|
142
|
+
placeholder="Search rows..."
|
|
143
|
+
/>
|
|
144
|
+
{/if}
|
|
145
|
+
<SlideToggle
|
|
146
|
+
name="slider-label"
|
|
147
|
+
active="bg-primary-500"
|
|
148
|
+
size="sm"
|
|
149
|
+
checked={fitToScreen}
|
|
150
|
+
on:change={() => (fitToScreen = !fitToScreen)}>Fit to screen</SlideToggle
|
|
151
|
+
>
|
|
152
|
+
|
|
153
|
+
<div class="overflow-auto" style="height: {height}px">
|
|
154
|
+
<table {...$tableAttrs} class="table table-compact bg-tertiary-200 overflow-clip">
|
|
155
|
+
<thead class={height != null ? `sticky top-0` : ''}>
|
|
156
|
+
{#each $headerRows as headerRow (headerRow.id)}
|
|
157
|
+
<Subscribe
|
|
158
|
+
rowAttrs={headerRow.attrs()}
|
|
159
|
+
let:rowAttrs
|
|
160
|
+
rowProps={headerRow.props()}
|
|
161
|
+
let:rowProps
|
|
162
|
+
>
|
|
163
|
+
<tr {...rowAttrs} class="bg-primary-300">
|
|
164
|
+
{#each headerRow.cells as cell (cell.id)}
|
|
165
|
+
<Subscribe attrs={cell.attrs()} props={cell.props()} let:props let:attrs>
|
|
166
|
+
<th scope="col" class="!p-2 w-min" {...attrs}>
|
|
167
|
+
<div class="flex w-full justify-between items-center">
|
|
168
|
+
<div class="flex gap-1 whitespace-pre-wrap">
|
|
169
|
+
<span
|
|
170
|
+
class:underline={props.sort.order}
|
|
171
|
+
class:normal-case={cell.id !== cell.label}
|
|
172
|
+
class:cursor-pointer={!props.sort.disabled}
|
|
173
|
+
on:click={props.sort.toggle}
|
|
174
|
+
on:keydown={props.sort.toggle}
|
|
175
|
+
>
|
|
176
|
+
{cell.render()}
|
|
177
|
+
</span>
|
|
178
|
+
<div class="w-2">
|
|
179
|
+
{#if props.sort.order === 'asc'}
|
|
180
|
+
▾
|
|
181
|
+
{:else if props.sort.order === 'desc'}
|
|
182
|
+
▴
|
|
183
|
+
{/if}
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
{#if cell.isData()}
|
|
187
|
+
{#if props.colFilter?.render}
|
|
188
|
+
<div class="">
|
|
189
|
+
<Render of={props.colFilter.render} />
|
|
190
|
+
</div>
|
|
191
|
+
{/if}
|
|
192
|
+
{/if}
|
|
193
|
+
</div>
|
|
194
|
+
</th>
|
|
195
|
+
</Subscribe>
|
|
196
|
+
{/each}
|
|
197
|
+
</tr>
|
|
198
|
+
</Subscribe>
|
|
199
|
+
{:else}
|
|
200
|
+
<p class="items-center justify-center flex w-full p-10 italic">Nothing to show here.</p>
|
|
201
|
+
{/each}
|
|
202
|
+
</thead>
|
|
203
|
+
|
|
204
|
+
<tbody class="overflow-auto" {...$tableBodyAttrs}>
|
|
205
|
+
{#each $pageRows as row (row.id)}
|
|
206
|
+
<Subscribe rowAttrs={row.attrs()} let:rowAttrs>
|
|
207
|
+
<tr {...rowAttrs}>
|
|
208
|
+
{#each row.cells as cell (cell?.id)}
|
|
209
|
+
<Subscribe attrs={cell.attrs()} let:attrs>
|
|
210
|
+
<td {...attrs} class="!p-2 w-max focus:resize">
|
|
211
|
+
<div
|
|
212
|
+
class="flex items-center h-max overflow-x-auto resize-none hover:resize"
|
|
213
|
+
class:max-w-md={!fitToScreen}
|
|
214
|
+
>
|
|
215
|
+
<Render of={cell.render()} />
|
|
216
|
+
</div>
|
|
217
|
+
</td>
|
|
218
|
+
</Subscribe>
|
|
219
|
+
{/each}
|
|
220
|
+
</tr>
|
|
221
|
+
</Subscribe>
|
|
222
|
+
{/each}
|
|
223
|
+
</tbody>
|
|
224
|
+
</table>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
{#if $data.length > 0}
|
|
228
|
+
<TablePagination pageConfig={pluginStates.page} {pageSizes} />
|
|
229
|
+
{/if}
|
|
230
|
+
</div>
|
|
@@ -115,8 +115,8 @@ if (type === "object") {
|
|
|
115
115
|
<Fa icon={faFilter} size="12" />
|
|
116
116
|
</button>
|
|
117
117
|
|
|
118
|
-
<div data-popup={`${popupId}`}>
|
|
119
|
-
<div class="card p-3
|
|
118
|
+
<div data-popup={`${popupId}`} class="z-50">
|
|
119
|
+
<div class="card p-3 grid gap-2 shadow-lg w-min bg-base-100">
|
|
120
120
|
<button
|
|
121
121
|
class="btn variant-filled-primary btn-sm"
|
|
122
122
|
type="button"
|
package/dist/models/Models.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,246 +1,262 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { createEventDispatcher } from 'svelte';
|
|
3
|
-
import { createTable, Subscribe, Render, createRender } from 'svelte-headless-table';
|
|
4
|
-
import {
|
|
5
|
-
addSortBy,
|
|
6
|
-
addPagination,
|
|
7
|
-
addExpandedRows,
|
|
8
|
-
addColumnFilters,
|
|
9
|
-
addTableFilter
|
|
10
|
-
} from 'svelte-headless-table/plugins';
|
|
11
|
-
import { computePosition, autoUpdate, offset, shift, flip, arrow } from '@floating-ui/dom';
|
|
12
|
-
import { storePopup } from '@skeletonlabs/skeleton';
|
|
13
|
-
|
|
14
|
-
storePopup.set({ computePosition, autoUpdate, offset, shift, flip, arrow });
|
|
15
|
-
|
|
16
|
-
import TableFilter from './TableFilter.svelte';
|
|
17
|
-
import TablePagination from './TablePagination.svelte';
|
|
18
|
-
import { columnFilter, searchFilter } from './filter';
|
|
19
|
-
import type { TableConfig } from '$lib/models/Models';
|
|
20
|
-
|
|
21
|
-
export let config: TableConfig<any>;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { createEventDispatcher } from 'svelte';
|
|
3
|
+
import { createTable, Subscribe, Render, createRender } from 'svelte-headless-table';
|
|
4
|
+
import {
|
|
5
|
+
addSortBy,
|
|
6
|
+
addPagination,
|
|
7
|
+
addExpandedRows,
|
|
8
|
+
addColumnFilters,
|
|
9
|
+
addTableFilter
|
|
10
|
+
} from 'svelte-headless-table/plugins';
|
|
11
|
+
import { computePosition, autoUpdate, offset, shift, flip, arrow } from '@floating-ui/dom';
|
|
12
|
+
import { SlideToggle, storePopup } from '@skeletonlabs/skeleton';
|
|
13
|
+
|
|
14
|
+
storePopup.set({ computePosition, autoUpdate, offset, shift, flip, arrow });
|
|
15
|
+
|
|
16
|
+
import TableFilter from './TableFilter.svelte';
|
|
17
|
+
import TablePagination from './TablePagination.svelte';
|
|
18
|
+
import { columnFilter, searchFilter } from './filter';
|
|
19
|
+
import type { TableConfig } from '$lib/models/Models';
|
|
20
|
+
|
|
21
|
+
export let config: TableConfig<any>;
|
|
22
|
+
|
|
23
|
+
let {
|
|
24
|
+
id: tableId,
|
|
25
|
+
data,
|
|
26
|
+
columns,
|
|
27
|
+
height = null,
|
|
28
|
+
optionsComponent,
|
|
29
|
+
defaultPageSize = 10,
|
|
30
|
+
pageSizes = [5, 10, 15, 20]
|
|
31
|
+
} = config;
|
|
32
|
+
let fitToScreen = true;
|
|
33
|
+
|
|
34
|
+
type AccessorType = keyof (typeof $data)[number];
|
|
35
|
+
|
|
36
|
+
const dispatch = createEventDispatcher();
|
|
37
|
+
const actionDispatcher = (obj) => dispatch('action', obj);
|
|
38
|
+
|
|
39
|
+
const table = createTable(data, {
|
|
40
|
+
colFilter: addColumnFilters(),
|
|
41
|
+
tableFilter: addTableFilter({
|
|
42
|
+
fn: searchFilter
|
|
43
|
+
}),
|
|
44
|
+
sort: addSortBy({ disableMultiSort: true }),
|
|
45
|
+
page: addPagination({ initialPageSize: defaultPageSize }),
|
|
46
|
+
expand: addExpandedRows()
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const accessors: AccessorType[] =
|
|
50
|
+
$data.length > 0 ? (Object.keys($data[0]) as AccessorType[]) : [];
|
|
51
|
+
|
|
52
|
+
const tableColumns = [
|
|
53
|
+
...accessors
|
|
54
|
+
.filter((accessor) => {
|
|
55
|
+
const key = accessor as string;
|
|
56
|
+
if (columns !== undefined && key in columns && columns[key].exclude === true) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
})
|
|
61
|
+
.map((accessor) => {
|
|
62
|
+
const key = accessor as string;
|
|
63
|
+
if (columns !== undefined && key in columns) {
|
|
64
|
+
const {
|
|
65
|
+
header,
|
|
66
|
+
colFilterFn,
|
|
67
|
+
colFilterComponent,
|
|
68
|
+
instructions,
|
|
69
|
+
disableFiltering = false,
|
|
70
|
+
disableSorting = false
|
|
71
|
+
} = columns[key];
|
|
72
|
+
|
|
73
|
+
const { toSortableValueFn, toFilterableValueFn, toStringFn, renderComponent } =
|
|
74
|
+
instructions ?? {};
|
|
75
|
+
|
|
76
|
+
return table.column({
|
|
77
|
+
header: header ?? key,
|
|
78
|
+
accessor: accessor,
|
|
79
|
+
cell: ({ value, row }) => {
|
|
80
|
+
return renderComponent
|
|
81
|
+
? createRender(renderComponent, { value, row })
|
|
82
|
+
: toStringFn
|
|
83
|
+
? toStringFn(value)
|
|
84
|
+
: value;
|
|
85
|
+
},
|
|
86
|
+
plugins: {
|
|
87
|
+
sort: {
|
|
88
|
+
disable: disableSorting,
|
|
89
|
+
invert: true,
|
|
90
|
+
getSortValue: (row) => {
|
|
91
|
+
return toSortableValueFn ? toSortableValueFn(row) : row;
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
colFilter: !disableFiltering
|
|
95
|
+
? {
|
|
96
|
+
fn: ({ filterValue, value }) => {
|
|
97
|
+
const val = toFilterableValueFn ? toFilterableValueFn(value) : value;
|
|
98
|
+
|
|
99
|
+
return colFilterFn
|
|
100
|
+
? colFilterFn({ filterValue, value: val })
|
|
101
|
+
: columnFilter({ filterValue, value: val });
|
|
102
|
+
},
|
|
103
|
+
render: ({ filterValue, values, id }) => {
|
|
104
|
+
return createRender(colFilterComponent ?? TableFilter, {
|
|
105
|
+
filterValue,
|
|
106
|
+
id,
|
|
107
|
+
tableId,
|
|
108
|
+
values,
|
|
109
|
+
toFilterableValueFn
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
: undefined,
|
|
114
|
+
tableFilter: {
|
|
115
|
+
getFilterValue: (row) => {
|
|
116
|
+
return toStringFn ? toStringFn(row) : row;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
} else {
|
|
122
|
+
return table.column({
|
|
123
|
+
header: key,
|
|
124
|
+
accessor: accessor,
|
|
125
|
+
plugins: {
|
|
126
|
+
sort: {
|
|
127
|
+
invert: true
|
|
128
|
+
},
|
|
129
|
+
colFilter: {
|
|
130
|
+
fn: columnFilter,
|
|
131
|
+
render: ({ filterValue, values, id }) =>
|
|
132
|
+
createRender(TableFilter, {
|
|
133
|
+
filterValue,
|
|
134
|
+
id,
|
|
135
|
+
tableId,
|
|
136
|
+
values
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
if (optionsComponent !== undefined) {
|
|
146
|
+
tableColumns.push(
|
|
147
|
+
table.display({
|
|
148
|
+
id: 'options',
|
|
149
|
+
header: '',
|
|
150
|
+
cell: ({ row }, _) => {
|
|
151
|
+
return createRender(optionsComponent!, {
|
|
152
|
+
row: row.isData() ? row.original : null,
|
|
153
|
+
dispatchFn: actionDispatcher
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}) as any
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const createdTableColumns = table.createColumns(tableColumns);
|
|
161
|
+
|
|
162
|
+
const { headerRows, pageRows, tableAttrs, tableBodyAttrs, pluginStates } =
|
|
163
|
+
table.createViewModel(createdTableColumns);
|
|
164
|
+
const { filterValue } = pluginStates.tableFilter;
|
|
165
|
+
</script>
|
|
166
|
+
|
|
167
|
+
<div class="grid gap-2 overflow-auto" class:w-max={!fitToScreen} class:w-full={fitToScreen}>
|
|
168
|
+
<div class="table-container">
|
|
169
|
+
{#if $data.length > 0}
|
|
170
|
+
<input
|
|
171
|
+
class="input p-2 mb-2 border border-primary-500"
|
|
172
|
+
type="text"
|
|
173
|
+
bind:value={$filterValue}
|
|
174
|
+
placeholder="Search rows..."
|
|
175
|
+
/>
|
|
176
|
+
{/if}
|
|
177
|
+
<SlideToggle
|
|
178
|
+
name="slider-label"
|
|
179
|
+
active="bg-primary-500"
|
|
180
|
+
size="sm"
|
|
181
|
+
checked={fitToScreen}
|
|
182
|
+
on:change={() => (fitToScreen = !fitToScreen)}>Fit to screen</SlideToggle
|
|
183
|
+
>
|
|
184
|
+
|
|
185
|
+
<div class="overflow-auto" style="height: {height}px">
|
|
186
|
+
<table {...$tableAttrs} class="table table-compact bg-tertiary-200 overflow-clip">
|
|
187
|
+
<thead class={height != null ? `sticky top-0` : ''}>
|
|
188
|
+
{#each $headerRows as headerRow (headerRow.id)}
|
|
189
|
+
<Subscribe
|
|
190
|
+
rowAttrs={headerRow.attrs()}
|
|
191
|
+
let:rowAttrs
|
|
192
|
+
rowProps={headerRow.props()}
|
|
193
|
+
let:rowProps
|
|
194
|
+
>
|
|
195
|
+
<tr {...rowAttrs} class="bg-primary-300">
|
|
196
|
+
{#each headerRow.cells as cell (cell.id)}
|
|
197
|
+
<Subscribe attrs={cell.attrs()} props={cell.props()} let:props let:attrs>
|
|
198
|
+
<th scope="col" class="!p-2 w-min" {...attrs}>
|
|
199
|
+
<div class="flex w-full justify-between items-center">
|
|
200
|
+
<div class="flex gap-1 whitespace-pre-wrap">
|
|
201
|
+
<span
|
|
202
|
+
class:underline={props.sort.order}
|
|
203
|
+
class:normal-case={cell.id !== cell.label}
|
|
204
|
+
class:cursor-pointer={!props.sort.disabled}
|
|
205
|
+
on:click={props.sort.toggle}
|
|
206
|
+
on:keydown={props.sort.toggle}
|
|
207
|
+
>
|
|
208
|
+
{cell.render()}
|
|
209
|
+
</span>
|
|
210
|
+
<div class="w-2">
|
|
211
|
+
{#if props.sort.order === 'asc'}
|
|
212
|
+
▾
|
|
213
|
+
{:else if props.sort.order === 'desc'}
|
|
214
|
+
▴
|
|
215
|
+
{/if}
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
{#if cell.isData()}
|
|
219
|
+
{#if props.colFilter?.render}
|
|
220
|
+
<div class="">
|
|
221
|
+
<Render of={props.colFilter.render} />
|
|
222
|
+
</div>
|
|
223
|
+
{/if}
|
|
224
|
+
{/if}
|
|
225
|
+
</div>
|
|
226
|
+
</th>
|
|
227
|
+
</Subscribe>
|
|
228
|
+
{/each}
|
|
229
|
+
</tr>
|
|
230
|
+
</Subscribe>
|
|
231
|
+
{:else}
|
|
232
|
+
<p class="items-center justify-center flex w-full p-10 italic">Nothing to show here.</p>
|
|
233
|
+
{/each}
|
|
234
|
+
</thead>
|
|
235
|
+
|
|
236
|
+
<tbody class="overflow-auto" {...$tableBodyAttrs}>
|
|
237
|
+
{#each $pageRows as row (row.id)}
|
|
238
|
+
<Subscribe rowAttrs={row.attrs()} let:rowAttrs>
|
|
239
|
+
<tr {...rowAttrs}>
|
|
240
|
+
{#each row.cells as cell (cell?.id)}
|
|
241
|
+
<Subscribe attrs={cell.attrs()} let:attrs>
|
|
242
|
+
<td {...attrs} class="!p-2 w-max focus:resize">
|
|
243
|
+
<div
|
|
244
|
+
class="flex items-center h-max overflow-x-auto resize-none hover:resize"
|
|
245
|
+
class:max-w-md={!fitToScreen}
|
|
246
|
+
>
|
|
247
|
+
<Render of={cell.render()} />
|
|
248
|
+
</div>
|
|
249
|
+
</td>
|
|
250
|
+
</Subscribe>
|
|
251
|
+
{/each}
|
|
252
|
+
</tr>
|
|
253
|
+
</Subscribe>
|
|
254
|
+
{/each}
|
|
255
|
+
</tbody>
|
|
256
|
+
</table>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
{#if $data.length > 0}
|
|
260
|
+
<TablePagination pageConfig={pluginStates.page} {pageSizes} />
|
|
261
|
+
{/if}
|
|
262
|
+
</div>
|
|
@@ -123,8 +123,8 @@
|
|
|
123
123
|
<Fa icon={faFilter} size="12" />
|
|
124
124
|
</button>
|
|
125
125
|
|
|
126
|
-
<div data-popup={`${popupId}`}>
|
|
127
|
-
<div class="card p-3
|
|
126
|
+
<div data-popup={`${popupId}`} class="z-50">
|
|
127
|
+
<div class="card p-3 grid gap-2 shadow-lg w-min bg-base-100">
|
|
128
128
|
<button
|
|
129
129
|
class="btn variant-filled-primary btn-sm"
|
|
130
130
|
type="button"
|
package/src/lib/models/Models.ts
CHANGED
|
@@ -1,133 +1,134 @@
|
|
|
1
|
-
import type { SvelteComponent } from 'svelte';
|
|
2
|
-
import type { ColumnFilterFn } from 'svelte-headless-table/lib/plugins';
|
|
3
|
-
import type { Writable } from 'svelte/store';
|
|
4
|
-
|
|
5
|
-
import {decimalCharacterType, orientationType,textMarkerType,textSeperatorType} from './Enums'
|
|
6
|
-
|
|
7
|
-
// page
|
|
8
|
-
export interface linkType {
|
|
9
|
-
label: string;
|
|
10
|
-
url: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Form
|
|
14
|
-
export interface inputType {
|
|
15
|
-
id: string;
|
|
16
|
-
label: string;
|
|
17
|
-
feedback: string[];
|
|
18
|
-
invalid: boolean;
|
|
19
|
-
valid: boolean;
|
|
20
|
-
required: boolean;
|
|
21
|
-
placeholder: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface fileInfoType {
|
|
25
|
-
name: string;
|
|
26
|
-
type: string;
|
|
27
|
-
length: number;
|
|
28
|
-
description: string;
|
|
29
|
-
validationHash: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface fileUploaderType {
|
|
33
|
-
accept: string[];
|
|
34
|
-
existingFiles: fileInfoType[];
|
|
35
|
-
descriptionType: number;
|
|
36
|
-
multiple: boolean;
|
|
37
|
-
maxSize: number;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface asciiFileReaderInfoType extends fileReaderInfoType {
|
|
41
|
-
cells: boolean[];
|
|
42
|
-
seperator: textSeperatorType;
|
|
43
|
-
textMarker: textMarkerType;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
export interface fileReaderInfoType {
|
|
48
|
-
decimal: decimalCharacterType;
|
|
49
|
-
orientation: orientationType;
|
|
50
|
-
offset: number;
|
|
51
|
-
variables: number;
|
|
52
|
-
data: number;
|
|
53
|
-
unit: number;
|
|
54
|
-
description: number;
|
|
55
|
-
dateformat: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
export interface filesType {
|
|
60
|
-
accepted: Blob[];
|
|
61
|
-
rejected: Blob[];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export type userType = {
|
|
65
|
-
name: string;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export interface fileObjType {
|
|
69
|
-
path: string;
|
|
70
|
-
lastModified: number;
|
|
71
|
-
lastModifiedDate: Date;
|
|
72
|
-
name: string;
|
|
73
|
-
size: number;
|
|
74
|
-
type: string;
|
|
75
|
-
webkitRelativePath: string;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface ColumnInstructions {
|
|
79
|
-
toStringFn?: (value: any) => string;
|
|
80
|
-
toSortableValueFn?: (value: any) => string | number;
|
|
81
|
-
toFilterableValueFn?: (value: any) => string | number | Date;
|
|
82
|
-
renderComponent?: typeof SvelteComponent;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Table column type
|
|
86
|
-
export interface Column {
|
|
87
|
-
header?: string;
|
|
88
|
-
exclude?: boolean; // false by default
|
|
89
|
-
instructions?: ColumnInstructions;
|
|
90
|
-
disableFiltering?: boolean; // false by default
|
|
91
|
-
disableSorting?: boolean; // false by default
|
|
92
|
-
colFilterFn?: ColumnFilterFn;
|
|
93
|
-
colFilterComponent?: typeof SvelteComponent;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export interface Columns {
|
|
97
|
-
[key: string]: Column;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Table config type
|
|
101
|
-
export interface TableConfig<T> {
|
|
102
|
-
id: string;
|
|
103
|
-
data: Writable<T[]>;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
1
|
+
import type { SvelteComponent } from 'svelte';
|
|
2
|
+
import type { ColumnFilterFn } from 'svelte-headless-table/lib/plugins';
|
|
3
|
+
import type { Writable } from 'svelte/store';
|
|
4
|
+
|
|
5
|
+
import {decimalCharacterType, orientationType,textMarkerType,textSeperatorType} from './Enums'
|
|
6
|
+
|
|
7
|
+
// page
|
|
8
|
+
export interface linkType {
|
|
9
|
+
label: string;
|
|
10
|
+
url: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Form
|
|
14
|
+
export interface inputType {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
feedback: string[];
|
|
18
|
+
invalid: boolean;
|
|
19
|
+
valid: boolean;
|
|
20
|
+
required: boolean;
|
|
21
|
+
placeholder: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface fileInfoType {
|
|
25
|
+
name: string;
|
|
26
|
+
type: string;
|
|
27
|
+
length: number;
|
|
28
|
+
description: string;
|
|
29
|
+
validationHash: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface fileUploaderType {
|
|
33
|
+
accept: string[];
|
|
34
|
+
existingFiles: fileInfoType[];
|
|
35
|
+
descriptionType: number;
|
|
36
|
+
multiple: boolean;
|
|
37
|
+
maxSize: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface asciiFileReaderInfoType extends fileReaderInfoType {
|
|
41
|
+
cells: boolean[];
|
|
42
|
+
seperator: textSeperatorType;
|
|
43
|
+
textMarker: textMarkerType;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
export interface fileReaderInfoType {
|
|
48
|
+
decimal: decimalCharacterType;
|
|
49
|
+
orientation: orientationType;
|
|
50
|
+
offset: number;
|
|
51
|
+
variables: number;
|
|
52
|
+
data: number;
|
|
53
|
+
unit: number;
|
|
54
|
+
description: number;
|
|
55
|
+
dateformat: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
export interface filesType {
|
|
60
|
+
accepted: Blob[];
|
|
61
|
+
rejected: Blob[];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type userType = {
|
|
65
|
+
name: string;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export interface fileObjType {
|
|
69
|
+
path: string;
|
|
70
|
+
lastModified: number;
|
|
71
|
+
lastModifiedDate: Date;
|
|
72
|
+
name: string;
|
|
73
|
+
size: number;
|
|
74
|
+
type: string;
|
|
75
|
+
webkitRelativePath: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ColumnInstructions {
|
|
79
|
+
toStringFn?: (value: any) => string;
|
|
80
|
+
toSortableValueFn?: (value: any) => string | number;
|
|
81
|
+
toFilterableValueFn?: (value: any) => string | number | Date;
|
|
82
|
+
renderComponent?: typeof SvelteComponent;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Table column type
|
|
86
|
+
export interface Column {
|
|
87
|
+
header?: string;
|
|
88
|
+
exclude?: boolean; // false by default
|
|
89
|
+
instructions?: ColumnInstructions;
|
|
90
|
+
disableFiltering?: boolean; // false by default
|
|
91
|
+
disableSorting?: boolean; // false by default
|
|
92
|
+
colFilterFn?: ColumnFilterFn;
|
|
93
|
+
colFilterComponent?: typeof SvelteComponent;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface Columns {
|
|
97
|
+
[key: string]: Column;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Table config type
|
|
101
|
+
export interface TableConfig<T> {
|
|
102
|
+
id: string;
|
|
103
|
+
data: Writable<T[]>;
|
|
104
|
+
height?: null | number;
|
|
105
|
+
columns?: Columns;
|
|
106
|
+
pageSizes?: number[];
|
|
107
|
+
defaultPageSize?: number;
|
|
108
|
+
optionsComponent?: typeof SvelteComponent;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// lists
|
|
112
|
+
export interface keyValuePairType {
|
|
113
|
+
id: number;
|
|
114
|
+
text: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface listItemType {
|
|
118
|
+
id: number;
|
|
119
|
+
text: string;
|
|
120
|
+
group: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
//help
|
|
124
|
+
export interface helpItemType {
|
|
125
|
+
id?: string;
|
|
126
|
+
name: string;
|
|
127
|
+
description: string;
|
|
128
|
+
link?: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface helpStoreType {
|
|
132
|
+
itemId?: string;
|
|
133
|
+
helpItems: helpItemType[];
|
|
134
|
+
}
|