@likable-hair/svelte 3.2.12 → 3.3.1

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 (43) hide show
  1. package/dist/components/composed/common/MenuOrDrawer.svelte +2 -1
  2. package/dist/components/composed/common/MenuOrDrawer.svelte.d.ts +1 -0
  3. package/dist/components/composed/common/QuickActions.css +12 -0
  4. package/dist/components/composed/common/QuickActions.svelte +362 -0
  5. package/dist/components/composed/common/QuickActions.svelte.d.ts +37 -0
  6. package/dist/components/composed/forms/ConfirmOrCancelButtons.svelte +5 -0
  7. package/dist/components/composed/forms/CountriesAutocomplete.svelte +1 -2
  8. package/dist/components/composed/forms/CountriesAutocomplete.svelte.d.ts +1 -0
  9. package/dist/components/composed/forms/LabelAndSelect.svelte +66 -0
  10. package/dist/components/composed/forms/LabelAndSelect.svelte.d.ts +38 -0
  11. package/dist/components/composed/forms/LabelAndTextField.svelte +87 -0
  12. package/dist/components/composed/forms/LabelAndTextField.svelte.d.ts +44 -0
  13. package/dist/components/composed/list/DynamicTable.css +18 -0
  14. package/dist/components/composed/list/DynamicTable.svelte +1717 -0
  15. package/dist/components/composed/list/DynamicTable.svelte.d.ts +406 -0
  16. package/dist/components/composed/search/DynamicFilters.svelte +182 -0
  17. package/dist/components/composed/search/DynamicFilters.svelte.d.ts +29 -0
  18. package/dist/components/composed/search/FilterEditor.svelte +12 -8
  19. package/dist/components/composed/search/Filters.svelte +18 -3
  20. package/dist/components/composed/search/Filters.svelte.d.ts +3 -2
  21. package/dist/components/composed/search/MobileFilterEditor.svelte +5 -5
  22. package/dist/components/simple/common/Divider.css +3 -0
  23. package/dist/components/simple/common/Divider.svelte +13 -0
  24. package/dist/components/simple/common/Divider.svelte.d.ts +22 -0
  25. package/dist/components/simple/common/InfiniteScroll.svelte +37 -0
  26. package/dist/components/simple/common/InfiniteScroll.svelte.d.ts +21 -0
  27. package/dist/components/simple/common/VerticalDraggableList.svelte +52 -0
  28. package/dist/components/simple/common/VerticalDraggableList.svelte.d.ts +34 -0
  29. package/dist/components/simple/forms/Checkbox.svelte +24 -1
  30. package/dist/components/simple/forms/Checkbox.svelte.d.ts +3 -1
  31. package/dist/components/simple/forms/Select.css +14 -0
  32. package/dist/components/simple/forms/Select.svelte +92 -0
  33. package/dist/components/simple/forms/Select.svelte.d.ts +28 -0
  34. package/dist/components/simple/forms/Switch.css +14 -0
  35. package/dist/components/simple/forms/Switch.svelte +85 -72
  36. package/dist/components/simple/forms/Switch.svelte.d.ts +7 -10
  37. package/dist/index.d.ts +7 -0
  38. package/dist/index.js +7 -0
  39. package/dist/utils/filters/filters.d.ts +11 -7
  40. package/dist/utils/filters/filters.js +15 -3
  41. package/dist/utils/filters/quickFilters.d.ts +109 -0
  42. package/dist/utils/filters/quickFilters.js +1 -0
  43. package/package.json +3 -2
@@ -0,0 +1,1717 @@
1
+ <script>import {
2
+ Checkbox,
3
+ Chip,
4
+ Converter,
5
+ CountriesAutocomplete,
6
+ DatePickerTextField,
7
+ Drawer,
8
+ FilterBuilder,
9
+ FlagIcon,
10
+ Icon,
11
+ MediaQuery,
12
+ Menu,
13
+ ToolTip
14
+ } from "../../..";
15
+ import { DateTime } from "luxon";
16
+ import { createEventDispatcher } from "svelte";
17
+ import { quintOut } from "svelte/easing";
18
+ import { crossfade } from "svelte/transition";
19
+ import Filters from "../search/Filters.svelte";
20
+ import ConfirmOrCancelButtons from "../forms/ConfirmOrCancelButtons.svelte";
21
+ import { flip } from "svelte/animate";
22
+ import InfiniteScroll from "../../simple/common/InfiniteScroll.svelte";
23
+ import Divider from "../../simple/common/Divider.svelte";
24
+ import VerticalDraggableList from "../../simple/common/VerticalDraggableList.svelte";
25
+ import Button from "../../simple/buttons/Button.svelte";
26
+ import SimpleTextField from "../../simple/forms/SimpleTextField.svelte";
27
+ import Autocomplete from "../../simple/forms/Autocomplete.svelte";
28
+ import LabelAndSelect from "../forms/LabelAndSelect.svelte";
29
+ import LabelAndTextField from "../forms/LabelAndTextField.svelte";
30
+ import DynamicFilters from "../search/DynamicFilters.svelte";
31
+ import QuickActions, {} from "../common/QuickActions.svelte";
32
+ import "./DynamicTable.css";
33
+ import Switch from "../../simple/forms/Switch.svelte";
34
+ const [send, receive] = crossfade({
35
+ duration: 500,
36
+ fallback(node, params) {
37
+ const style = getComputedStyle(node);
38
+ const transform = style.transform === "none" ? "" : style.transform;
39
+ return {
40
+ duration: 500,
41
+ easing: quintOut,
42
+ css: (t) => `
43
+ transform: ${transform} scale(${t});
44
+ opacity: ${t}
45
+ `
46
+ };
47
+ }
48
+ });
49
+ let clazz = {};
50
+ export { clazz as class };
51
+ const dispatch = createEventDispatcher();
52
+ export let headers = [], headersToShowInTable = headers, subHeaders = [], customizeHeaders = false, rows = [], sortedBy = void 0, sortDirection = "asc", cellEdit = false, noItemsText = "No items to show", showSelect = false, showSelectContainer = true, selectMode = "single", selectedItems = [], showExpand = false, loading = false, disabled = false, filters = [], searchBarColumns = void 0, searchBarVisible = false, searchBarPlaceholder = "Type to search for identification code, description and MRN...", filtersVisible = false, quickFiltersVisible = false, lang = "en", editFilterMode = "one-edit", showActiveFilters = true, quickFilters = [], actionsForSelectedItems = [], hasMoreToLoad = false, totalRows = rows.length;
53
+ let openCellEditor = false, cellEditorActivator, cellEditorContainer, menuElementCellEditor, menuElementQuickFilters, cellEditorInfoActive, saveEditDisabled = false, searchText = void 0, searchBarInput = void 0, openQuickFilter = false, quickFilterActivator, quickFilterActive, globalBuilder = new FilterBuilder(), slotSelectActionsContainer, isSelectedAll = false, calendarOpened = false, calendarOpened2 = false, selectedIndexes = [], cellEditorIndexRow, cellEditorIndexHeader, cellEditorSubItem;
54
+ let openHeaderDrawer = false, headersToSelect = !!headers ? headers.filter((h) => {
55
+ return !headersToShowInTable.find((hst) => hst.value == h.value);
56
+ }).map((h) => {
57
+ return {
58
+ id: h.value,
59
+ name: h.label
60
+ };
61
+ }) : [], headersToShow = headersToShowInTable.map((h) => {
62
+ return {
63
+ id: h.value,
64
+ name: h.label
65
+ };
66
+ }), infoActivators = Array(headersToShowInTable.length);
67
+ let totalBatchLength = 0, expandedRows = [];
68
+ function saveHeadersToShow() {
69
+ dispatch("saveHeadersToShow", {
70
+ headersToShow
71
+ });
72
+ openHeaderDrawer = false;
73
+ }
74
+ function handleHeaderClick(header) {
75
+ if (header.sortable && !loading) {
76
+ if (!!sortedBy && header.value == sortedBy) {
77
+ if (sortDirection == "asc")
78
+ sortDirection = "desc";
79
+ else if (sortDirection == "desc") {
80
+ sortedBy = void 0;
81
+ }
82
+ } else {
83
+ sortedBy = header.value;
84
+ sortDirection = "asc";
85
+ }
86
+ handleSearchChange(searchText);
87
+ dispatch("sort", {
88
+ sortedBy,
89
+ sortDirection
90
+ });
91
+ }
92
+ }
93
+ function handleRowClick(item) {
94
+ if (disabled || loading)
95
+ return;
96
+ dispatch("rowClick", {
97
+ item
98
+ });
99
+ }
100
+ function handleCellClick(mouseEvent, item, cellEditorInfo, value, indexRow, indexHeader, subItem) {
101
+ if (disabled || loading)
102
+ return;
103
+ if (cellEdit && cellEditorInfo && !item.disableEdit) {
104
+ if (!cellEditorActivator) {
105
+ let target = mouseEvent.target;
106
+ cellEditorActivator = target;
107
+ cellEditorIndexRow = indexRow;
108
+ cellEditorIndexHeader = indexHeader;
109
+ cellEditorSubItem = subItem;
110
+ cellEditorInfoActive = {
111
+ ...cellEditorInfo,
112
+ value,
113
+ item
114
+ };
115
+ openCellEditor = !openCellEditor;
116
+ const element = target.getBoundingClientRect();
117
+ const windowHeight = window.innerHeight;
118
+ const windowWidth = window.innerWidth;
119
+ if (openCellEditor) {
120
+ setTimeout(() => {
121
+ if (windowHeight - element.bottom < 300) {
122
+ cellEditorContainer.style.bottom = `${windowHeight - element.top}px`;
123
+ } else {
124
+ cellEditorContainer.style.top = `${element.bottom}px`;
125
+ }
126
+ if (windowWidth - element.right < 400) {
127
+ cellEditorContainer.style.right = `${windowWidth - element.left - cellEditorActivator.clientWidth}px`;
128
+ }
129
+ }, 0);
130
+ }
131
+ }
132
+ }
133
+ dispatch("cellClick", {
134
+ item
135
+ });
136
+ }
137
+ function handleSaveClick() {
138
+ cellEditorIndexHeader = void 0;
139
+ cellEditorIndexRow = void 0;
140
+ cellEditorSubItem = void 0;
141
+ dispatch("saveCellEdit", {
142
+ item: cellEditorInfoActive
143
+ });
144
+ cellEditorActivator = void 0;
145
+ openCellEditor = false;
146
+ }
147
+ function handleCancelClick() {
148
+ cellEditorIndexHeader = void 0;
149
+ cellEditorIndexRow = void 0;
150
+ cellEditorSubItem = void 0;
151
+ cellEditorActivator = void 0;
152
+ openCellEditor = false;
153
+ quickFilterActivator = void 0;
154
+ openQuickFilter = false;
155
+ }
156
+ function handleSelect(item, shiftKeyPressed) {
157
+ let index = selectedItems.findIndex((i) => i.id == item.id);
158
+ if (index == -1) {
159
+ if (selectMode == "single") {
160
+ selectedItems = [item];
161
+ selectedIndexes = [rows.findIndex((r) => r.item.id == item.id)];
162
+ } else if (selectMode == "multiple") {
163
+ if (shiftKeyPressed && selectedIndexes.length > 0 && !isSelectedAll) {
164
+ let lastSelectedIndex = selectedIndexes[selectedIndexes.length - 1], selectedIndex = rows.findIndex((r) => r.item.id == item.id);
165
+ if (selectedIndex != -1) {
166
+ if (selectedIndex < lastSelectedIndex) {
167
+ let x = lastSelectedIndex;
168
+ lastSelectedIndex = selectedIndex - 1;
169
+ selectedIndex = x;
170
+ }
171
+ for (let i = lastSelectedIndex + 1; i <= selectedIndex; i++) {
172
+ if (!selectedItems.find((selectedItem) => selectedItem.id == rows[i].item.id)) {
173
+ selectedItems = [...selectedItems, rows[i].item];
174
+ }
175
+ }
176
+ }
177
+ } else {
178
+ selectedItems = [...selectedItems, item];
179
+ selectedIndexes.push(rows.findIndex((r) => r.item.id == item.id));
180
+ }
181
+ }
182
+ } else {
183
+ selectedItems = selectedItems.filter((i) => i.id != item.id);
184
+ selectedIndexes = selectedIndexes.filter((r) => r != rows.findIndex((r2) => r2.item.id == item.id));
185
+ isSelectedAll = false;
186
+ }
187
+ }
188
+ function handleSelectAll() {
189
+ if (selectMode == "multiple") {
190
+ if (selectedItems.length == rows.length) {
191
+ selectedItems = [];
192
+ selectedIndexes = [];
193
+ isSelectedAll = false;
194
+ } else {
195
+ selectedItems = rows.map((r) => r.item);
196
+ isSelectedAll = true;
197
+ }
198
+ }
199
+ }
200
+ function expandRow(row) {
201
+ let index = expandedRows.findIndex((r) => r.item.id == row.item.id);
202
+ if (index == -1) {
203
+ expandedRows = [...expandedRows, row];
204
+ } else {
205
+ expandedRows = expandedRows.filter((r) => r.item.id != row.item.id);
206
+ }
207
+ }
208
+ function formatDate(dateTime, dateFormat) {
209
+ return dateTime.setLocale(dateFormat.locale).toFormat(dateFormat.format);
210
+ }
211
+ $: {
212
+ if (!showExpand) {
213
+ totalBatchLength = rows.length;
214
+ } else {
215
+ totalBatchLength = rows.reduce(
216
+ (acc, row) => acc + row.subItems.length,
217
+ rows.length
218
+ );
219
+ }
220
+ if (!!cellEditorInfoActive && cellEditorInfoActive.type.key == "number" && (cellEditorInfoActive.type.params?.min != void 0 && cellEditorInfoActive.value < cellEditorInfoActive.type.params.min || cellEditorInfoActive.type.params?.max != void 0 && cellEditorInfoActive.value > cellEditorInfoActive.type.params.max)) {
221
+ saveEditDisabled = true;
222
+ } else {
223
+ saveEditDisabled = false;
224
+ }
225
+ if (!!isSelectedAll && rows.length > 0 && !loading && !disabled && selectedItems.length < rows.length) {
226
+ selectedItems = rows.map((r) => r.item);
227
+ }
228
+ }
229
+ function searchTextBuilder(searchText2) {
230
+ let builder;
231
+ let converter = new Converter();
232
+ builder = converter.createBuilder({
233
+ filters: filters || []
234
+ });
235
+ if (!!searchText2 && !!searchBarColumns && searchBarColumns.length > 0) {
236
+ builder.where((b) => {
237
+ b.where(searchBarColumns[0], "ilike", "%" + searchText2 + "%");
238
+ for (let i = 1; i < searchBarColumns.length; i += 1) {
239
+ b.orWhere(searchBarColumns[i], "ilike", "%" + searchText2 + "%");
240
+ }
241
+ });
242
+ }
243
+ if (!!sortedBy) {
244
+ builder.orderBy(sortedBy, sortDirection || "asc");
245
+ }
246
+ return builder;
247
+ }
248
+ let syncTimer;
249
+ function handleSearchChange(searchText2) {
250
+ clearTimeout(syncTimer);
251
+ syncTimer = setTimeout(async () => {
252
+ globalBuilder = searchTextBuilder(searchText2);
253
+ for (let i = 0; i < quickFilters.length; i++) {
254
+ globalBuilder = quickFilterBuilder(globalBuilder, quickFilters[i]);
255
+ }
256
+ handleFiltersChange();
257
+ }, 800);
258
+ }
259
+ $:
260
+ if (searchText != void 0)
261
+ handleSearchChange(searchText);
262
+ function handleFiltersChange() {
263
+ dispatch("filtersChange", {
264
+ builder: globalBuilder
265
+ });
266
+ }
267
+ function handleClearQuickFilter(quickFilter, dispatchFiltersChange = true) {
268
+ if (quickFilter.type.key == "custom") {
269
+ quickFilter.type.value = void 0;
270
+ quickFilter.type.missingValue = void 0;
271
+ if (dispatchFiltersChange) {
272
+ dispatch("removeCustomQuickFilter", { quickFilter });
273
+ }
274
+ } else if (quickFilter.type.key == "string") {
275
+ quickFilter.type.value = void 0;
276
+ quickFilter.type.missingValue = void 0;
277
+ } else if (quickFilter.type.key == "number") {
278
+ quickFilter.type.value = void 0;
279
+ quickFilter.type.missingValue = void 0;
280
+ } else if (quickFilter.type.key == "boolean") {
281
+ quickFilter.type.value = void 0;
282
+ } else if (quickFilter.type.key == "country") {
283
+ quickFilter.type.selected = void 0;
284
+ quickFilter.type.missingValue = void 0;
285
+ } else if (quickFilter.type.key == "date") {
286
+ quickFilter.type.from = void 0;
287
+ quickFilter.type.to = void 0;
288
+ } else if (quickFilter.type.key == "multi-select") {
289
+ quickFilter.type.values = [];
290
+ quickFilter.type.missingValue = false;
291
+ quickFilter.type.missingValue = void 0;
292
+ }
293
+ if (dispatchFiltersChange) {
294
+ quickFilter.active = false;
295
+ }
296
+ globalBuilder = searchTextBuilder(searchText);
297
+ for (let i = 0; i < quickFilters.length; i++) {
298
+ if (quickFilters[i].active) {
299
+ globalBuilder = quickFilterBuilder(
300
+ globalBuilder,
301
+ quickFilters[i],
302
+ false
303
+ );
304
+ }
305
+ }
306
+ if (dispatchFiltersChange) {
307
+ quickFilters = quickFilters;
308
+ handleFiltersChange();
309
+ }
310
+ return globalBuilder;
311
+ }
312
+ function handleSearchBoxKeydown(e) {
313
+ if (e.key == "Enter") {
314
+ handleFiltersChange();
315
+ }
316
+ }
317
+ function handleQuickFilterClick(mouseEvent, quickFilter) {
318
+ handleCancelClick();
319
+ setTimeout(() => {
320
+ if (quickFilter) {
321
+ if (!quickFilterActivator) {
322
+ let target = mouseEvent.target;
323
+ quickFilterActivator = target;
324
+ quickFilterActive = quickFilter;
325
+ openQuickFilter = !openQuickFilter;
326
+ }
327
+ }
328
+ }, 300);
329
+ }
330
+ function setQuickFilterMissingValue(quickFilter) {
331
+ if (quickFilter.type.key == "custom") {
332
+ quickFilter.type.missingValue = true;
333
+ quickFilter.type.value = void 0;
334
+ } else if (quickFilter.type.key == "multi-select") {
335
+ quickFilter.type.missingValue = true;
336
+ quickFilter.type.values = [];
337
+ } else if (quickFilter.type.key == "string") {
338
+ quickFilter.type.missingValue = true;
339
+ quickFilter.type.value = void 0;
340
+ } else if (quickFilter.type.key == "country") {
341
+ quickFilter.type.missingValue = true;
342
+ quickFilter.type.selected = void 0;
343
+ } else if (quickFilter.type.key == "number") {
344
+ quickFilter.type.missingValue = true;
345
+ quickFilter.type.value = void 0;
346
+ }
347
+ handleApplyClick(quickFilter);
348
+ }
349
+ function setQuickFilterValue(quickFilter, value) {
350
+ if (quickFilter.type.key == "custom") {
351
+ quickFilter.type.value = value;
352
+ } else if (quickFilter.type.key == "boolean") {
353
+ quickFilter.type.value = value;
354
+ }
355
+ handleApplyClick(quickFilter);
356
+ }
357
+ function handleApplyClick(quickFilter, dispatchCustomFilterClick = false) {
358
+ if (quickFilter.type.key == "custom" && dispatchCustomFilterClick) {
359
+ dispatch("applyCustomQuickFilter", { quickFilter, setQuickFilterValue });
360
+ } else {
361
+ quickFilter.active = true;
362
+ quickFilters = quickFilters;
363
+ globalBuilder = quickFilterBuilder(globalBuilder, quickFilter);
364
+ handleFiltersChange();
365
+ quickFilterActivator = void 0;
366
+ openQuickFilter = false;
367
+ }
368
+ }
369
+ function quickFilterBuilder(builder, quickFilter, clearPreaviousValue = true) {
370
+ if (quickFilter.type.key == "custom") {
371
+ let value = quickFilter.type.value, missingValue = quickFilter.type.missingValue;
372
+ if (clearPreaviousValue) {
373
+ builder = handleClearQuickFilter(quickFilter, false);
374
+ }
375
+ quickFilter.type.value = value;
376
+ quickFilter.type.missingValue = missingValue;
377
+ builder = quickFilter.type.modify({
378
+ builder,
379
+ value: { value, missingValue }
380
+ });
381
+ } else if (quickFilter.type.key == "string") {
382
+ let value = quickFilter.type.value, missingValue = quickFilter.type.missingValue;
383
+ if (clearPreaviousValue) {
384
+ builder = handleClearQuickFilter(quickFilter, false);
385
+ }
386
+ quickFilter.type.value = value;
387
+ quickFilter.type.missingValue = missingValue;
388
+ if (quickFilter.type.modify) {
389
+ builder = quickFilter.type.modify({
390
+ builder,
391
+ value: { value, missingValue }
392
+ });
393
+ }
394
+ if (!!quickFilter.column) {
395
+ if (missingValue) {
396
+ builder.whereNull(quickFilter.column);
397
+ } else if (!!value) {
398
+ builder.where(
399
+ quickFilter.column,
400
+ quickFilter.type.mode ?? "equal",
401
+ value
402
+ );
403
+ }
404
+ }
405
+ } else if (quickFilter.type.key == "boolean") {
406
+ let value = quickFilter.type.value;
407
+ if (clearPreaviousValue) {
408
+ builder = handleClearQuickFilter(quickFilter, false);
409
+ }
410
+ quickFilter.type.value = value;
411
+ if (quickFilter.type.modify) {
412
+ builder = quickFilter.type.modify({
413
+ builder,
414
+ value
415
+ });
416
+ }
417
+ if (!!quickFilter.column && value != void 0) {
418
+ builder.where(quickFilter.column, value);
419
+ }
420
+ } else if (quickFilter.type.key == "country") {
421
+ let value = quickFilter.type.selected, missingValue = quickFilter.type.missingValue;
422
+ if (clearPreaviousValue) {
423
+ builder = handleClearQuickFilter(quickFilter, false);
424
+ }
425
+ quickFilter.type.selected = value;
426
+ quickFilter.type.missingValue = missingValue;
427
+ const values = value?.map((item) => item.value);
428
+ if (quickFilter.type.modify) {
429
+ builder = quickFilter.type.modify({
430
+ builder,
431
+ value: { values, missingValue }
432
+ });
433
+ }
434
+ if (!!quickFilter.column) {
435
+ if (missingValue) {
436
+ builder.whereNull(quickFilter.column);
437
+ } else if (!!values && values.length > 0) {
438
+ builder.whereIn(quickFilter.column, values);
439
+ }
440
+ }
441
+ } else if (quickFilter.type.key == "date") {
442
+ let from = quickFilter.type.from, to = quickFilter.type.to;
443
+ if (clearPreaviousValue) {
444
+ builder = handleClearQuickFilter(quickFilter, false);
445
+ }
446
+ quickFilter.type.from = from;
447
+ quickFilter.type.to = to;
448
+ if (quickFilter.type.modify) {
449
+ builder = quickFilter.type.modify({
450
+ builder,
451
+ value: { from, to }
452
+ });
453
+ } else if (!!quickFilter.column) {
454
+ if (!!from) {
455
+ builder.where(
456
+ quickFilter.column,
457
+ ">=",
458
+ DateTime.fromJSDate(from).toString()
459
+ );
460
+ }
461
+ if (!!to) {
462
+ builder.where(
463
+ quickFilter.column,
464
+ "<=",
465
+ DateTime.fromJSDate(to).toString()
466
+ );
467
+ }
468
+ }
469
+ } else if (quickFilter.type.key == "multi-select") {
470
+ let value = quickFilter.type.values, missingValue = quickFilter.type.missingValue;
471
+ if (clearPreaviousValue) {
472
+ builder = handleClearQuickFilter(quickFilter, false);
473
+ }
474
+ quickFilter.type.values = value;
475
+ quickFilter.type.missingValue = missingValue;
476
+ const values = value.map((item) => item.value);
477
+ if (quickFilter.type.modify) {
478
+ builder = quickFilter.type.modify({
479
+ builder,
480
+ value: { values, missingValue }
481
+ });
482
+ } else if (quickFilter.column) {
483
+ if (missingValue) {
484
+ builder.whereNull(quickFilter.column);
485
+ } else if (values.length > 0) {
486
+ builder.whereIn(quickFilter.column, values);
487
+ }
488
+ }
489
+ } else if (quickFilter.type.key == "number") {
490
+ let value = quickFilter.type.value, missingValue = quickFilter.type.missingValue;
491
+ if (clearPreaviousValue) {
492
+ builder = handleClearQuickFilter(quickFilter, false);
493
+ }
494
+ quickFilter.type.value = value;
495
+ quickFilter.type.missingValue = missingValue;
496
+ if (quickFilter.type.modify) {
497
+ builder = quickFilter.type.modify({
498
+ builder,
499
+ value: { value, missingValue }
500
+ });
501
+ }
502
+ if (quickFilter.column) {
503
+ if (missingValue) {
504
+ builder.whereNull(quickFilter.column);
505
+ } else if (!!value) {
506
+ builder.where(quickFilter.column, value);
507
+ }
508
+ }
509
+ }
510
+ if (!!sortedBy) {
511
+ builder.orderBy(sortedBy, sortDirection || "asc");
512
+ }
513
+ return builder;
514
+ }
515
+ function updateFilterValues(filter, updateMultiFilterValues) {
516
+ let newValue = {}, newValid = false, newMode = filter.type == "date" || filter.type == "number" || filter.type == "select" || filter.type == "string" ? filter.mode : void 0;
517
+ if (filter.type == "select") {
518
+ newValue = filter.values;
519
+ if (newValue.length > 0) {
520
+ newValid = true;
521
+ }
522
+ } else if ("mode" in filter && filter.mode == "between") {
523
+ newValue.to = filter.to;
524
+ newValue.from = filter.from;
525
+ if (!!newValue.from || !!newValue.to) {
526
+ newValid = true;
527
+ }
528
+ } else {
529
+ newValue = filter.value;
530
+ if (!!newValue) {
531
+ newValid = true;
532
+ }
533
+ }
534
+ updateMultiFilterValues(filter.name, newValue, newValid, newMode);
535
+ }
536
+ function handleRemoveAllFilters(removeAllFilters) {
537
+ if (!!removeAllFilters) {
538
+ removeAllFilters();
539
+ }
540
+ dispatch("removeAllFilters", {});
541
+ handleSearchChange(searchText);
542
+ }
543
+ function handleRemoveFilter(filter) {
544
+ dispatch("removeFilter", { filter });
545
+ handleSearchChange(searchText);
546
+ }
547
+ function handleLoadMore() {
548
+ dispatch("fetchData", {});
549
+ }
550
+ </script>
551
+
552
+ {#if !!rows && Array.isArray(rows) && !!headersToShowInTable && Array.isArray(headersToShowInTable)}
553
+ <QuickActions
554
+ {selectedItems}
555
+ {showSelectContainer}
556
+ {isSelectedAll}
557
+ {totalRows}
558
+ {slotSelectActionsContainer}
559
+ {disabled}
560
+ {loading}
561
+ {actionsForSelectedItems}
562
+ />
563
+
564
+ <slot name="search-bar" {handleSearchChange}>
565
+ <div class="search-bar-container">
566
+ {#if searchBarVisible}
567
+ <SimpleTextField
568
+ placeholder={searchBarPlaceholder}
569
+ appendInnerIcon="mdi-magnify"
570
+ bind:value={searchText}
571
+ bind:input={searchBarInput}
572
+ on:keydown={handleSearchBoxKeydown}
573
+ --simple-textfield-default-width="450px"
574
+ --simple-textfield-border-radius= 0.5rem
575
+ --simple-textfield-background-color= transparent
576
+ --simple-textfield-box-shadow= 'inset 0 0 0 1px rgb(var(--global-color-background-500))'
577
+ --simple-textfield-focus-box-shadow='inset 0 0 0 2px rgb(var(--global-color-primary-500))'
578
+ />
579
+ {/if}
580
+
581
+ {#if filtersVisible}
582
+ <div style="margin-left: 20px;">
583
+ <Filters
584
+ bind:filters
585
+ on:applyFilter={() => {
586
+ handleSearchChange(searchText);
587
+ }}
588
+ on:removeFilter={e => { handleRemoveFilter(e.detail.filter) }}
589
+ on:removeAllFilters={() => handleRemoveAllFilters()}
590
+ --filters-default-wrapper-width="100%"
591
+ {lang}
592
+ {editFilterMode}
593
+ {showActiveFilters}
594
+ >
595
+ <svelte:fragment slot="append">
596
+ <slot name="filter-append" />
597
+ </svelte:fragment>
598
+ <svelte:fragment slot="custom-chip" let:filter>
599
+ <slot name="custom-filter-chip" {filter} />
600
+ </svelte:fragment>
601
+ <svelte:fragment
602
+ slot="custom"
603
+ let:filter
604
+ let:updateFunction
605
+ let:mAndDown
606
+ >
607
+ <slot name="custom-filter" {filter} {updateFunction} {mAndDown} />
608
+ </svelte:fragment>
609
+
610
+ <svelte:fragment slot="content" let:mAndDown let:filters let:updateMultiFilterValues let:handleRemoveAllFilters={removeAllFilters}>
611
+ {#key filters}
612
+ <DynamicFilters
613
+ {lang}
614
+ {filters}
615
+ {mAndDown}
616
+ on:change={e => updateFilterValues(e.detail.filter, updateMultiFilterValues)}
617
+ on:removeAllFilters={() => handleRemoveAllFilters(removeAllFilters)}
618
+ >
619
+ <svelte:fragment slot="custom" let:filter let:mAndDown>
620
+ <slot name="custom-filter" {filter} {updateMultiFilterValues} {mAndDown}></slot>
621
+ </svelte:fragment>
622
+ </DynamicFilters>
623
+ {/key}
624
+ </svelte:fragment>
625
+ </Filters>
626
+ </div>
627
+ {/if}
628
+ </div>
629
+ </slot>
630
+
631
+ {#if quickFiltersVisible}
632
+ <div class="quick-filters">
633
+ {#if !!quickFilters && quickFilters.length > 0}
634
+ {#each quickFilters as quickFilter}
635
+ <div
636
+ class={quickFilter.active ? "active-quick-filters" : "non-active-quick-filters"}
637
+ >
638
+ <button
639
+ on:click={(e) => {
640
+ handleQuickFilterClick(e, quickFilter);
641
+ }}
642
+ >
643
+ <div class="quick-filter-icon">
644
+ <Icon name={quickFilter.icon} --icon-size="20px" />
645
+ {quickFilter.title}
646
+ </div>
647
+ </button>
648
+ {#if quickFilter.active}
649
+ <div style:padding-top="1px" style:padding-right="3px">
650
+ <Icon
651
+ name="mdi-close-circle"
652
+ click
653
+ --icon-size="14px"
654
+ on:click={() => {
655
+ handleClearQuickFilter(quickFilter);
656
+ }}
657
+ />
658
+ </div>
659
+ {/if}
660
+ </div>
661
+ {/each}
662
+ {/if}
663
+ </div>
664
+ {/if}
665
+
666
+ <div class="table-container">
667
+ <table style="display: table;" class="table">
668
+ <thead class="table-header">
669
+ <tr>
670
+ {#if !!showSelect && !showExpand && rows.length > 0}
671
+ <th
672
+ style:width="30px"
673
+ style:min-width="30px"
674
+ style:text-align="center"
675
+ >
676
+ {#if selectMode === "multiple"}
677
+ <Checkbox
678
+ id="select-all"
679
+ value={selectedItems.length == totalBatchLength}
680
+ disabled={disabled || loading}
681
+ on:change={handleSelectAll}
682
+ />
683
+ {/if}
684
+ </th>
685
+ {/if}
686
+ {#if showExpand}
687
+ <th
688
+ style:min-width="60px"
689
+ style:text-align="center"
690
+ />
691
+ {/if}
692
+ {#each headersToShowInTable as head, index}
693
+ <th
694
+ style:width={head.width}
695
+ style:min-width={head.minWidth}
696
+ class:sortable={head.sortable}
697
+ on:click={() => handleHeaderClick(head)}
698
+ >
699
+ <slot name="header" {head}>
700
+ <span class="header-label">
701
+ <slot name="headerLabel">
702
+ <div bind:this={infoActivators[index]}>
703
+ {head.label}
704
+ {#if !!head.info}
705
+ <Icon
706
+ name="mdi-help-circle-outline"
707
+ --icon-size="16px"
708
+ />
709
+ {/if}
710
+ </div>
711
+ {#if !!head.info}
712
+ <ToolTip
713
+ appearTimeout={1000}
714
+ activator={infoActivators[index]}
715
+ >
716
+ <div
717
+ style:background-color='rgb(var(--global-color-background-300), .95)'
718
+ style:border-radius="5px"
719
+ style:padding="10px"
720
+ >
721
+ {head.info}
722
+ </div>
723
+ </ToolTip>
724
+ {/if}
725
+ </slot>
726
+ </span>
727
+ {#if head.sortable}
728
+ <span
729
+ class="header-sort-icon"
730
+ class:active={sortedBy == head.value}
731
+ class:asc={sortDirection == "asc"}
732
+ class:desc={sortDirection == "desc"}
733
+ >
734
+ {#if sortDirection == "asc"}
735
+ <Icon name="mdi-arrow-up" />
736
+ {:else}
737
+ <Icon name="mdi-arrow-down" />
738
+ {/if}
739
+ </span>
740
+ {/if}
741
+ </slot>
742
+ </th>
743
+ {/each}
744
+ {#if $$slots.rowActions || $$slots.append}
745
+ <th>
746
+ <slot name="append" index={-1} items={undefined} />
747
+ </th>
748
+ {/if}
749
+ {#if customizeHeaders}
750
+ <th
751
+ style:width="30px"
752
+ style:min-width="30px"
753
+ style:text-align="center"
754
+ >
755
+ <div style="display: flex; gap: 8px;">
756
+ <Icon
757
+ name="mdi-plus-circle-outline"
758
+ click
759
+ on:click={() => (openHeaderDrawer = true)}
760
+ />
761
+ </div>
762
+ </th>
763
+ {/if}
764
+ </tr>
765
+ {#if loading}
766
+ <tr>
767
+ <th
768
+ colspan={headersToShowInTable.length + 1}
769
+ class="loading"
770
+ style="text-align: center;"
771
+ style:border="none"
772
+ style:cursor="default"
773
+ style:font-size="1.2em"
774
+ style:padding="0px"
775
+ >
776
+ <div class="loader-line" />
777
+ </th>
778
+ </tr>
779
+ {/if}
780
+ </thead>
781
+
782
+ <tbody>
783
+ {#if rows.length == 0}
784
+ <tr>
785
+ <td
786
+ colspan={headersToShowInTable.length + 1}
787
+ style="text-align: center;"
788
+ style:border="none"
789
+ style:cursor="default"
790
+ style:padding="10px"
791
+ style:font-size="1.2em"
792
+ >
793
+ {noItemsText}
794
+ </td>
795
+ </tr>
796
+ {:else}
797
+ {#each rows as row, indexRow}
798
+ <tr
799
+ class="item-row"
800
+ style:background-color={
801
+ !!row.item.disableEdit ?
802
+ !!row.item.rowDisableBackgroundColor ?
803
+ row.item.rowDisableBackgroundColor :
804
+ 'var(--dynamic-table-row-disabled-background-color, var(--dynamic-table-row-default-disabled-background-color))' :
805
+ expandedRows.findIndex((r) => r.item.id == row.item.id ) != -1 ?
806
+ 'var(--dynamic-table-expanded-row-background-color, var(--dynamic-table-expanded-row-default-background-color))' :
807
+ !!selectedItems.find(i => i.id == row.item.id) ?
808
+ 'var(--dynamic-table-selected-row-background-color, var(--dynamic-table-selected-row-default-background-color))' :
809
+ ""
810
+ }
811
+ class:row-activator={cellEditorIndexRow == indexRow && !cellEditorSubItem}
812
+ on:click={() => handleRowClick(row)}
813
+ >
814
+ {#if !!showSelect && !showExpand}
815
+ <td style:padding-left="0px" style:text-align="center">
816
+ <Checkbox
817
+ id={row.item.id}
818
+ value={selectedItems.findIndex(
819
+ (i) => i.id == row.item.id
820
+ ) != -1}
821
+ disabled={disabled || loading}
822
+ on:change={(e) => handleSelect(row.item, e.detail.shiftKeyPressed)}
823
+ />
824
+ </td>
825
+ {/if}
826
+ {#if showExpand}
827
+ <td style:padding-left="0px" style:text-align="center">
828
+ <Icon
829
+ name={expandedRows.findIndex(
830
+ (r) => r.item.id == row.item.id
831
+ ) == -1
832
+ ? "mdi-chevron-down"
833
+ : "mdi-chevron-up"}
834
+ click
835
+ --icon-size="24px"
836
+ on:click={() => expandRow(row)}
837
+ />
838
+ </td>
839
+ {/if}
840
+ {#each headersToShowInTable as header, indexHeader}
841
+ <td
842
+ class:hover-cell={cellEdit && !loading && !!header.cellEditorInfo}
843
+ class:cell-edit-activator={cellEditorIndexHeader == indexHeader && cellEditorIndexRow == indexRow && !cellEditorSubItem}
844
+ on:click={(e) => {
845
+ handleCellClick(
846
+ e,
847
+ row.item,
848
+ header.cellEditorInfo,
849
+ row.item[header.value],
850
+ indexRow,
851
+ indexHeader,
852
+ false
853
+ );
854
+ }}
855
+ >
856
+ {#if header.type.key == "custom"}
857
+ <slot
858
+ name="custom"
859
+ index={indexRow}
860
+ columnIndex={indexHeader}
861
+ {header}
862
+ {row}
863
+ />
864
+ {:else if header.type.key == "date"}
865
+ {formatDate(row.item[header.value], header.type.params)}
866
+ {:else if header.type.key == "icon"}
867
+ <Icon
868
+ --icon-color={header.type.params?.color}
869
+ --icon-size={header.type.params?.size}
870
+ name={header.type.params?.name || ""}
871
+ />
872
+ {:else if header.type.key == "string"}
873
+ {#if row.item[header.value] !== undefined && row.item[header.value] !== null}
874
+ {row.item[header.value]}
875
+ {:else if !!header.type.params?.nullText}
876
+ {#if typeof header.type.params.nullText == "function"}
877
+ {header.type.params.nullText(row.item)}
878
+ {:else}
879
+ {header.type.params.nullText}
880
+ {/if}
881
+ {:else}
882
+ <div style="display: flex; justify-content: center;">-</div>
883
+ {/if}
884
+ {:else}
885
+ {row.item[header.value]}
886
+ {/if}
887
+ </td>
888
+ {/each}
889
+ {#if $$slots.rowActions || $$slots.append}
890
+ <td class={clazz.cell || ""}>
891
+ <slot name="rowActions" index={indexRow} {row} />
892
+ <slot name="append" index={indexRow} {row} />
893
+ </td>
894
+ {/if}
895
+ </tr>
896
+ {#if showExpand}
897
+ {#if expandedRows.findIndex((r) => r.item.id == row.item.id) != -1}
898
+ <tr>
899
+ <td
900
+ colspan={headersToShowInTable.length + 1}
901
+ style:border="none"
902
+ >
903
+ <table style="display: table;">
904
+ <thead class="table-header table-subheader">
905
+ <tr>
906
+ {#each subHeaders as subHeader}
907
+ <th
908
+ style:width={subHeader.width}
909
+ style:min-width={subHeader.minWidth}
910
+ class:sortable={subHeader.sortable}
911
+ on:click={() => handleHeaderClick(subHeader)}
912
+ >
913
+ <slot name="header" {subHeader}>
914
+ <span class="header-label">
915
+ <slot name="headerLabel">
916
+ {subHeader.label}
917
+ </slot>
918
+ </span>
919
+ {#if subHeader.sortable}
920
+ <span
921
+ class="header-sort-icon"
922
+ class:active={sortedBy == subHeader.value}
923
+ class:asc={sortDirection == "asc"}
924
+ class:desc={sortDirection == "desc"}
925
+ >
926
+ {#if sortDirection == "asc"}
927
+ <Icon name="mdi-arrow-up" />
928
+ {:else}
929
+ <Icon name="mdi-arrow-down" />
930
+ {/if}
931
+ </span>
932
+ {/if}
933
+ </slot>
934
+ </th>
935
+ {/each}
936
+ {#if $$slots.subRowActions || $$slots.subAppend}
937
+ <th>
938
+ <slot
939
+ name="subAppend"
940
+ index={-1}
941
+ items={undefined}
942
+ />
943
+ </th>
944
+ {/if}
945
+ </tr>
946
+ </thead>
947
+
948
+ <tbody>
949
+ {#each row.subItems as subItem, indexSubItem}
950
+ <tr
951
+ on:click={() => handleRowClick(subItem)}
952
+ class:row-activator={cellEditorIndexRow == indexSubItem && cellEditorSubItem}
953
+ >
954
+ {#each subHeaders as subHeader, indexSubHeader}
955
+ <td
956
+ class:cell-edit-activator={cellEditorIndexHeader == indexSubHeader && cellEditorIndexRow == indexSubItem && cellEditorSubItem}
957
+ class:hover-cell={cellEdit}
958
+ on:click={(e) => {
959
+ handleCellClick(
960
+ e,
961
+ subItem,
962
+ subHeader.cellEditorInfo,
963
+ subItem[subHeader.value],
964
+ indexSubItem,
965
+ indexSubHeader,
966
+ true
967
+ );
968
+ }}
969
+ >
970
+ {#if subHeader.type.key == "custom"}
971
+ <slot
972
+ name="custom-subheader"
973
+ index={indexSubItem}
974
+ columnIndex={indexSubHeader}
975
+ {subHeader}
976
+ {subItem}
977
+ />
978
+ {:else if subHeader.type.key == "date"}
979
+ {formatDate(
980
+ subItem[subHeader.value],
981
+ subHeader.type.params
982
+ )}
983
+ {:else if subHeader.type.key == "icon"}
984
+ <Icon
985
+ --icon-color={subHeader.type.params?.color}
986
+ --icon-size={subHeader.type.params?.size}
987
+ name={subHeader.type.params?.name || ""}
988
+ />
989
+ {:else if subHeader.type.key == "string"}
990
+ {#if subItem[subHeader.value] !== undefined && subItem[subHeader.value] !== null}
991
+ {subItem[subHeader.value]}
992
+ {:else if !!subHeader.type.params?.nullText}
993
+ {#if typeof subHeader.type.params.nullText == "function"}
994
+ {subHeader.type.params.nullText(subItem)}
995
+ {:else}
996
+ {subHeader.type.params.nullText}
997
+ {/if}
998
+ {:else}
999
+ {subItem[subHeader.value]}
1000
+ {/if}
1001
+ {:else}
1002
+ {subItem[subHeader.value]}
1003
+ {/if}
1004
+ </td>
1005
+ {/each}
1006
+ {#if $$slots.subRowActions || $$slots.subAppend}
1007
+ <td class={clazz.cell || ""}>
1008
+ <slot
1009
+ name="subRowActions"
1010
+ index={indexSubItem}
1011
+ {subItem}
1012
+ />
1013
+ <slot
1014
+ name="subAppend"
1015
+ index={indexSubItem}
1016
+ {subItem}
1017
+ />
1018
+ </td>
1019
+ {/if}
1020
+ </tr>
1021
+ {/each}
1022
+ </tbody>
1023
+ </table>
1024
+ </td>
1025
+ </tr>
1026
+ {/if}
1027
+ {/if}
1028
+ {/each}
1029
+ {/if}
1030
+ </tbody>
1031
+ </table>
1032
+ <InfiniteScroll
1033
+ on:loadMore={handleLoadMore}
1034
+ treshold={100}
1035
+ hasMore={hasMoreToLoad}
1036
+ />
1037
+ </div>
1038
+ {/if}
1039
+
1040
+ <Menu
1041
+ bind:open={openCellEditor}
1042
+ activator={cellEditorActivator}
1043
+ bind:menuElement={menuElementCellEditor}
1044
+ _top={undefined}
1045
+ openingId="cell-editor"
1046
+ >
1047
+ <div
1048
+ class="cell-editor-container"
1049
+ bind:this={cellEditorContainer}
1050
+ >
1051
+ <div style:grid-column="1 / 3">
1052
+ {#if cellEditorInfoActive.type.key === "string"}
1053
+ <LabelAndTextField
1054
+ label={cellEditorInfoActive.title}
1055
+ description={cellEditorInfoActive.description}
1056
+ name={cellEditorInfoActive.title}
1057
+ info={cellEditorInfoActive.info}
1058
+ type="text"
1059
+ orientation="horizontal"
1060
+ bind:value={cellEditorInfoActive.value}
1061
+ --simple-textfield-border-radius= 0.5rem
1062
+ --simple-textfield-background-color= transparent
1063
+ --simple-textfield-box-shadow= 'inset 0 0 0 1px rgb(var(--global-color-background-500))'
1064
+ --simple-textfield-focus-box-shadow='inset 0 0 0 2px rgb(var(--global-color-primary-500))'
1065
+ />
1066
+ {:else if cellEditorInfoActive.type.key === "number"}
1067
+ <LabelAndTextField
1068
+ label={cellEditorInfoActive.title}
1069
+ description={cellEditorInfoActive.description}
1070
+ name={cellEditorInfoActive.title}
1071
+ info={cellEditorInfoActive.info}
1072
+ type="number"
1073
+ orientation="horizontal"
1074
+ error={saveEditDisabled}
1075
+ bind:value={cellEditorInfoActive.value}
1076
+ --simple-textfield-border-radius= 0.5rem
1077
+ --simple-textfield-background-color= transparent
1078
+ --simple-textfield-box-shadow= 'inset 0 0 0 1px rgb(var(--global-color-background-500))'
1079
+ --simple-textfield-focus-box-shadow='inset 0 0 0 2px rgb(var(--global-color-primary-500))'
1080
+ />
1081
+ {:else if cellEditorInfoActive.type.key === "select"}
1082
+ <LabelAndSelect
1083
+ label={cellEditorInfoActive.title}
1084
+ description={cellEditorInfoActive.description}
1085
+ name={cellEditorInfoActive.title}
1086
+ info={cellEditorInfoActive.info}
1087
+ options={cellEditorInfoActive.type.params.options}
1088
+ orientation="horizontal"
1089
+ bind:value={cellEditorInfoActive.value}
1090
+ />
1091
+ {:else if cellEditorInfoActive.type.key === "boolean"}
1092
+ <div class="container">
1093
+ <Checkbox
1094
+ id={cellEditorInfoActive.title}
1095
+ bind:value={cellEditorInfoActive.value}
1096
+ />
1097
+ <label style:margin-left="0.7rem" for={cellEditorInfoActive.title}
1098
+ >{cellEditorInfoActive.title}
1099
+ </label>
1100
+ </div>
1101
+ {/if}
1102
+ </div>
1103
+
1104
+ <div style:margin-top="10px" style:grid-row="2" style:grid-column="1 / 3">
1105
+ <Divider --divider-color=rgb(var(--global-color-contrast-100) />
1106
+ </div>
1107
+ <div style:grid-row="3" style:grid-column="2" style:margin-top="-15px">
1108
+ <ConfirmOrCancelButtons
1109
+ confirmDisable={saveEditDisabled}
1110
+ confirmText="Save"
1111
+ cancelText="Cancel"
1112
+ on:cancel-click={handleCancelClick}
1113
+ on:confirm-click={handleSaveClick}
1114
+ />
1115
+ </div>
1116
+ </div>
1117
+ </Menu>
1118
+
1119
+ <Menu
1120
+ bind:open={openQuickFilter}
1121
+ activator={quickFilterActivator}
1122
+ bind:menuElement={menuElementQuickFilters}
1123
+ anchor="bottom"
1124
+ openingId="quick-filter"
1125
+ closeOnClickOutside
1126
+ >
1127
+ <div
1128
+ class="quick-filter-container"
1129
+ >
1130
+ <div style:grid-column="1 / 3">
1131
+ {#if quickFilterActive.type.key == 'custom'}
1132
+ <slot name="custom-quick-filter" quickFilter={quickFilterActive} {setQuickFilterMissingValue}>
1133
+ </slot>
1134
+ {:else if quickFilterActive.type.key === "string"}
1135
+ <div class="space-between" style="font-weight: 500;">
1136
+ {quickFilterActive.title}
1137
+ {#if !!quickFilterActive.type.missingLabel}
1138
+ <button
1139
+ on:click={() =>
1140
+ setQuickFilterMissingValue(quickFilterActive)}
1141
+ >{quickFilterActive.type.missingLabel}</button
1142
+ >
1143
+ {/if}
1144
+ </div>
1145
+ <LabelAndTextField
1146
+ description={quickFilterActive.description}
1147
+ name={quickFilterActive.title}
1148
+ info={quickFilterActive.info}
1149
+ type="text"
1150
+ bind:value={quickFilterActive.type.value}
1151
+ --simple-textfield-border-radius= 0.5rem
1152
+ --simple-textfield-background-color= transparent
1153
+ --simple-textfield-box-shadow= 'inset 0 0 0 1px rgb(var(--global-color-background-500))'
1154
+ --simple-textfield-focus-box-shadow='inset 0 0 0 2px rgb(var(--global-color-primary-500))'
1155
+ />
1156
+ {:else if quickFilterActive.type.key === "number"}
1157
+ <div class="space-between" style="font-weight: 500; margin-bottom: 8px;">
1158
+ {quickFilterActive.title}
1159
+ {#if !!quickFilterActive.type.missingLabel}
1160
+ <button
1161
+ on:click={() =>
1162
+ setQuickFilterMissingValue(quickFilterActive)}
1163
+ >{quickFilterActive.type.missingLabel}</button
1164
+ >
1165
+ {/if}
1166
+ </div>
1167
+ <LabelAndTextField
1168
+ description={quickFilterActive.description}
1169
+ name={quickFilterActive.title}
1170
+ info={quickFilterActive.info}
1171
+ type="number"
1172
+ orientation="horizontal"
1173
+ error={saveEditDisabled}
1174
+ bind:value={quickFilterActive.type.value}
1175
+ --simple-textfield-border-radius= 0.5rem
1176
+ --simple-textfield-background-color= transparent
1177
+ --simple-textfield-box-shadow= 'inset 0 0 0 1px rgb(var(--global-color-background-500))'
1178
+ --simple-textfield-focus-box-shadow='inset 0 0 0 2px rgb(var(--global-color-primary-500))'
1179
+ />
1180
+ {:else if quickFilterActive.type.key === "multi-select"}
1181
+ <div class="space-between" style="font-weight: 500; margin-bottom: 8px;">
1182
+ {quickFilterActive.title}
1183
+ {#if !!quickFilterActive.type.missingLabel}
1184
+ <button
1185
+ on:click={() =>
1186
+ setQuickFilterMissingValue(quickFilterActive)}
1187
+ >{quickFilterActive.type.missingLabel}</button
1188
+ >
1189
+ {/if}
1190
+ </div>
1191
+ <Autocomplete
1192
+ multiple
1193
+ items={quickFilterActive.type.items}
1194
+ bind:values={quickFilterActive.type.values}
1195
+ --autocomplete-border="1px solid rgb(var(--global-color-background-500))"
1196
+ --autocomplete-focus-box-shadow="0 0 0 2px rgb(var(--global-color-primary-500))"
1197
+ >
1198
+ <svelte:fragment slot="selection" let:selection let:unselect>
1199
+ <slot name="selection" {selection} {unselect}>
1200
+ <div tabindex="-1">
1201
+ <Chip
1202
+ close={true}
1203
+ on:close={() => unselect(selection)}
1204
+ --chip-default-border-radius="var(--autocomplete-border-radius, var(--autocomplete-default-border-radius))"
1205
+ buttonTabIndex={-1}
1206
+ truncateText
1207
+ >
1208
+ <slot name="chip-label" {selection}>
1209
+ {#if !!quickFilterActive.type.countriesAlpha2 && quickFilterActive.type.countriesAlpha2.find((c) => c.value == selection.value)}
1210
+ <div>
1211
+ <FlagIcon
1212
+ alpha2={quickFilterActive.type.countriesAlpha2
1213
+ .find((c) => c.value == selection.value)
1214
+ ?.label?.toString()
1215
+ .toLowerCase() ?? ""}
1216
+ --flag-icon-size="16px"
1217
+ />
1218
+ </div>
1219
+ {/if}
1220
+ {selection.label}
1221
+ </slot>
1222
+ </Chip>
1223
+ </div>
1224
+ </slot>
1225
+ </svelte:fragment>
1226
+ <svelte:fragment slot="item-label" let:item>
1227
+ <slot name="item-label" {item}>
1228
+ {#if !!quickFilterActive.type.countriesAlpha2 && quickFilterActive.type.countriesAlpha2.find((c) => c.value == item.value)}
1229
+ <FlagIcon
1230
+ alpha2={quickFilterActive.type.countriesAlpha2
1231
+ .find((c) => c.value == item.value)
1232
+ ?.label?.toString()
1233
+ .toLowerCase() ?? ""}
1234
+ />
1235
+ {/if}
1236
+ {item.label}
1237
+ </slot>
1238
+ </svelte:fragment>
1239
+ </Autocomplete>
1240
+ {:else if quickFilterActive.type.key === "boolean"}
1241
+ {#if quickFilterActive.type.params}
1242
+ <div class="vertical-quick-filters">
1243
+ <button
1244
+ on:click={() => setQuickFilterValue(quickFilterActive, true)}
1245
+ >
1246
+ {quickFilterActive.type.params.labelTrue}
1247
+ </button>
1248
+ <button
1249
+ on:click={() => setQuickFilterValue(quickFilterActive, false)}
1250
+ >
1251
+ {quickFilterActive.type.params.labelFalse}
1252
+ </button>
1253
+ <button
1254
+ on:click={() => setQuickFilterValue(quickFilterActive, undefined)}
1255
+ >
1256
+ All
1257
+ </button>
1258
+ </div>
1259
+ {/if}
1260
+ {:else if quickFilterActive.type.key === "country"}
1261
+ <div class="space-between" style="font-weight: 500; margin-bottom: 8px;">
1262
+ {quickFilterActive.title}
1263
+ {#if !!quickFilterActive.type.missingLabel}
1264
+ <button
1265
+ on:click={() =>
1266
+ setQuickFilterMissingValue(quickFilterActive)}
1267
+ >{quickFilterActive.type.missingLabel}</button
1268
+ >
1269
+ {/if}
1270
+ </div>
1271
+ <CountriesAutocomplete
1272
+ bind:selected={quickFilterActive.type.selected}
1273
+ {...((!!quickFilterActive.type.countriesOptions && quickFilterActive.type.countriesOptions.length > 0) && {
1274
+ items: quickFilterActive.type.countriesOptions,
1275
+ })}
1276
+ autocompleteProps={{
1277
+ placeholder: !!quickFilterActive.type.selected
1278
+ ? quickFilterActive.type.selected.length > 0
1279
+ ? ""
1280
+ : quickFilterActive.description
1281
+ : quickFilterActive.description,
1282
+ multiple: true,
1283
+ }}
1284
+ --autocomplete-border="1px solid rgb(var(--global-color-background-500))"
1285
+ --autocomplete-focus-box-shadow="0 0 0 2px rgb(var(--global-color-primary-500))"
1286
+ />
1287
+ {:else if quickFilterActive.type.key === "date"}
1288
+ <div on:click|stopPropagation role="presentation" tabindex="-1">
1289
+ <div>
1290
+ <DatePickerTextField
1291
+ bind:selectedDate={quickFilterActive.type.from}
1292
+ placeholder={"From"}
1293
+ --simple-textfield-width="100%"
1294
+ --simple-textfield-border-radius= 0.5rem
1295
+ --simple-textfield-background-color= transparent
1296
+ --simple-textfield-box-shadow= 'inset 0 0 0 1px rgb(var(--global-color-background-500))'
1297
+ --simple-textfield-focus-box-shadow='inset 0 0 0 2px rgb(var(--global-color-primary-500))'
1298
+ flipOnOverflow
1299
+ bind:menuOpened={calendarOpened}
1300
+ on:day-click={() => (calendarOpened = false)}
1301
+ >
1302
+ <svelte:fragment slot="append-inner">
1303
+ <Icon
1304
+ name="mdi-close-circle"
1305
+ click
1306
+ on:click={() => {
1307
+ if (
1308
+ !!quickFilterActive &&
1309
+ quickFilterActive.type.key === "date"
1310
+ ) {
1311
+ quickFilterActive.type.from = undefined;
1312
+ }
1313
+ }}
1314
+ />
1315
+ </svelte:fragment>
1316
+ </DatePickerTextField>
1317
+ </div>
1318
+ <div>
1319
+ <DatePickerTextField
1320
+ bind:selectedDate={quickFilterActive.type.to}
1321
+ placeholder={"To"}
1322
+ --simple-textfield-width="100%"
1323
+ --simple-textfield-border-radius= 0.5rem
1324
+ --simple-textfield-background-color= transparent
1325
+ --simple-textfield-box-shadow= 'inset 0 0 0 1px rgb(var(--global-color-background-500))'
1326
+ --simple-textfield-focus-box-shadow='inset 0 0 0 2px rgb(var(--global-color-primary-500))'
1327
+ flipOnOverflow
1328
+ bind:menuOpened={calendarOpened2}
1329
+ on:day-click={() => (calendarOpened2 = false)}
1330
+ >
1331
+ <svelte:fragment slot="append-inner">
1332
+ <Icon
1333
+ name="mdi-close-circle"
1334
+ click
1335
+ on:click={() => {
1336
+ if (
1337
+ !!quickFilterActive &&
1338
+ quickFilterActive.type.key === "date"
1339
+ ) {
1340
+ quickFilterActive.type.to = undefined;
1341
+ }
1342
+ }}
1343
+ />
1344
+ </svelte:fragment>
1345
+ </DatePickerTextField>
1346
+ </div>
1347
+ </div>
1348
+ {/if}
1349
+ </div>
1350
+
1351
+ {#if quickFilterActive.type.key != "boolean"}
1352
+ <div style:margin-top="10px" style:grid-row="2" style:grid-column="1 / 3">
1353
+ <Divider --divider-color=rgb(var(--global-color-contrast-100)) />
1354
+ </div>
1355
+ <div style:grid-row="3" style:grid-column="2" style:margin-top="-15px">
1356
+ <ConfirmOrCancelButtons
1357
+ confirmDisable={saveEditDisabled}
1358
+ confirmText="Apply"
1359
+ cancelText="Cancel"
1360
+ on:cancel-click={handleCancelClick}
1361
+ on:confirm-click={() => handleApplyClick(quickFilterActive, quickFilterActive.type.key == 'custom')}
1362
+ />
1363
+ </div>
1364
+ {/if}
1365
+ </div>
1366
+ </Menu>
1367
+
1368
+ <MediaQuery let:sAndDown>
1369
+ <Drawer
1370
+ bind:open={openHeaderDrawer}
1371
+ _space={sAndDown ? "60vh" : "20vw"}
1372
+ position={sAndDown ? "bottom" : "right"}
1373
+ >
1374
+ <div style="padding: 20px;">
1375
+ <div class="personalize-header">Personalize your headers</div>
1376
+
1377
+ <span class="headers-show grid-col-1">Headers shown in table</span>
1378
+
1379
+ {#if headersToShow}
1380
+ <VerticalDraggableList
1381
+ items={headersToShow}
1382
+ on:changeOrder={(e) => {
1383
+ headersToShow = e.detail.items;
1384
+ }}
1385
+ >
1386
+ <svelte:fragment slot="item" let:item>
1387
+ <Switch
1388
+ --switch-label-width="90%"
1389
+ value={headersToShow.find((h) => h.id == item.id) != undefined}
1390
+ label={item.name}
1391
+ on:change={(e) => {
1392
+ if (e.detail.value == false) {
1393
+ headersToShow = headersToShow.filter((h) => h.id != item.id);
1394
+ headersToSelect = [...headersToSelect, item];
1395
+ }
1396
+ }}
1397
+ />
1398
+ </svelte:fragment>
1399
+ </VerticalDraggableList>
1400
+ {/if}
1401
+ <Divider --divider-color=rgb(var(--global-color-contrast-100) />
1402
+ <span class="headers-show grid-col-1">Headers to show</span>
1403
+ {#if headersToSelect && headersToSelect.length > 0}
1404
+ {#each headersToSelect as header (header.id)}
1405
+ <div
1406
+ animate:flip
1407
+ in:receive={{ key: header }}
1408
+ out:send={{ key: header }}
1409
+ class="headers-show grid-col-1"
1410
+ >
1411
+ <Switch
1412
+ --switch-label-width="90%"
1413
+ value={false}
1414
+ label={header.name}
1415
+ on:change={(e) => {
1416
+ if (e.detail.value == true) {
1417
+ headersToSelect = headersToSelect.filter(
1418
+ (h) => h.id != header.id
1419
+ );
1420
+ headersToShow = [...headersToShow, header];
1421
+ }
1422
+ }}
1423
+ />
1424
+ </div>
1425
+ {/each}
1426
+ {:else}
1427
+ <div class="headers-show grid-col-1">
1428
+ <span style="text-align: center;">No headers to add</span>
1429
+ </div>
1430
+ {/if}
1431
+ <div style="width: 100%; display: flex; justify-content: center;">
1432
+ <Button
1433
+ class="mr-3 mt-5"
1434
+ --button-width="70%"
1435
+ on:click={saveHeadersToShow}
1436
+ >
1437
+ Save preferences
1438
+ </Button>
1439
+ </div>
1440
+ </div>
1441
+ </Drawer>
1442
+ </MediaQuery>
1443
+
1444
+ <style>
1445
+ .table-container {
1446
+ overflow-x: auto;
1447
+ overflow-y: auto;
1448
+ max-height: var(
1449
+ --dynamic-table-max-height,
1450
+ var(--dynamic-table-default-max-height)
1451
+ );
1452
+ }
1453
+
1454
+ .table {
1455
+ background-color: var(
1456
+ --dynamic-table-background-color,
1457
+ var(--dynamic-table-default-background-color)
1458
+ );
1459
+ border-collapse: separate;
1460
+ }
1461
+
1462
+ .table-header {
1463
+ position: sticky;
1464
+ top: 0;
1465
+ z-index: 1;
1466
+ }
1467
+
1468
+ .table-header th {
1469
+ padding: var(
1470
+ --dynamic-table-header-padding,
1471
+ var(--dynamic-table-default-header-padding)
1472
+ );
1473
+ font-size: var(
1474
+ --dynamic-table-header-font-size,
1475
+ var(--dynamic-table-default-header-font-size)
1476
+ );
1477
+ font-weight: var(
1478
+ --dynamic-table-header-font-weight,
1479
+ var(--dynamic-table-default-header-font-weight)
1480
+ );
1481
+ background-color: var(
1482
+ --dynamic-table-header-background-color,
1483
+ var(--dynamic-table-default-header-background-color)
1484
+ );
1485
+ }
1486
+
1487
+ .table-subheader th {
1488
+ background-color: var(
1489
+ --dynamic-table-subheader-background-color,
1490
+ var(--dynamic-table-default-subheader-background-color)
1491
+ );
1492
+ }
1493
+
1494
+ .table-header th.sortable {
1495
+ cursor: pointer;
1496
+ transition: all 0.1s ease-in;
1497
+ user-select: none;
1498
+ }
1499
+
1500
+ .table-header th.sortable:hover {
1501
+ color: var(
1502
+ --dynamic-table-header-hover-color,
1503
+ var(--dynamic-table-default-hover-color)
1504
+ );
1505
+ }
1506
+
1507
+ .header-label {
1508
+ margin-right: 5px;
1509
+ font-size: small;
1510
+ }
1511
+
1512
+ .header-sort-icon {
1513
+ display: none;
1514
+ }
1515
+
1516
+ .header-sort-icon.active {
1517
+ display: inline;
1518
+ }
1519
+
1520
+ .table-header th:first-child {
1521
+ border-top-left-radius: var(
1522
+ --dynamic-table-header-border-radius,
1523
+ var(--dynamic-table-default-header-border-radius)
1524
+ );
1525
+ border-bottom-left-radius: var(
1526
+ --dynamic-table-header-border-radius,
1527
+ var(--dynamic-table-default-header-border-radius)
1528
+ );
1529
+ }
1530
+
1531
+ .table-header th:last-child {
1532
+ border-top-right-radius: var(
1533
+ --dynamic-table-header-border-radius,
1534
+ var(--dynamic-table-default-header-border-radius)
1535
+ );
1536
+ border-bottom-right-radius: var(
1537
+ --dynamic-table-header-border-radius,
1538
+ var(--dynamic-table-default-header-border-radius)
1539
+ );
1540
+ }
1541
+
1542
+ .thead {
1543
+ height: var(
1544
+ --dynamic-table-header-height,
1545
+ var(--dynamic-table-default-header-height)
1546
+ );
1547
+ }
1548
+
1549
+ table {
1550
+ border-collapse: collapse;
1551
+ width: 100%;
1552
+ }
1553
+
1554
+ th {
1555
+ text-align: start;
1556
+ padding-left: 10px;
1557
+ min-width: 100px;
1558
+ }
1559
+
1560
+ td {
1561
+ padding-left: 10px;
1562
+ border: 1px solid transparent;
1563
+ }
1564
+
1565
+ .hover-cell:hover, .hover-cell:focus, .cell-edit-activator {
1566
+ cursor: pointer;
1567
+ border: 1px solid rgb(var(--global-color-contrast-800));
1568
+ border-radius: 5px;
1569
+ }
1570
+
1571
+ .item-row:hover {
1572
+ background-color: var(
1573
+ --dynamic-table-row-background-color-hover,
1574
+ var(--dynamic-table-row-default-background-color-hover)
1575
+ );
1576
+ }
1577
+
1578
+ .cell-editor-container {
1579
+ display: grid;
1580
+ grid-template-columns: 1fr 1fr;
1581
+ justify-content: center;
1582
+ align-items: center;
1583
+ box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.2);
1584
+ position: fixed;
1585
+ padding: 10px;
1586
+ border-radius: 10px;
1587
+ background-color: var(
1588
+ --dynamic-table-cell-editor-background-color,
1589
+ var(--dynamic-table-cell-editor-default-background-color)
1590
+ );
1591
+ height: 200px;
1592
+ width: 500px;
1593
+ }
1594
+
1595
+ .row-activator {
1596
+ background-color: var(
1597
+ --dynamic-table-row-background-color-hover,
1598
+ var(--dynamic-table-row-default-background-color-hover)
1599
+ );
1600
+ }
1601
+
1602
+ .quick-filter-container {
1603
+ display: grid;
1604
+ grid-template-columns: 1fr 1fr;
1605
+ justify-content: center;
1606
+ align-items: center;
1607
+ box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.2);
1608
+ position: fixed;
1609
+ padding: 10px;
1610
+ border-radius: 10px;
1611
+ background-color: var(
1612
+ --dynamic-table-quick-filter-background-color,
1613
+ var(--dynamic-table-quick-filter-default-background-color)
1614
+ );
1615
+ }
1616
+
1617
+ .container {
1618
+ display: flex;
1619
+ align-items: center;
1620
+ }
1621
+
1622
+ .loader-line {
1623
+ margin-top: -1px;
1624
+ height: 5px;
1625
+ position: relative;
1626
+ overflow: hidden;
1627
+ background-color: rgb(var(--global-color-background-500));
1628
+ -webkit-border-radius: 20px;
1629
+ -moz-border-radius: 20px;
1630
+ border-radius: 20px;
1631
+ }
1632
+
1633
+ .loader-line:before {
1634
+ content: "";
1635
+ position: absolute;
1636
+ left: -50%;
1637
+ height: 5px;
1638
+ width: 40%;
1639
+ background-color: rgb(var(--global-color-primary-500));
1640
+ -webkit-animation: lineAnim 1s linear infinite;
1641
+ -moz-animation: lineAnim 1s linear infinite;
1642
+ animation: lineAnim 1s linear infinite;
1643
+ -webkit-border-radius: 20px;
1644
+ -moz-border-radius: 20px;
1645
+ border-radius: 20px;
1646
+ }
1647
+
1648
+ .search-bar-container {
1649
+ display: flex;
1650
+ flex-direction: row;
1651
+ margin-bottom: 20px;
1652
+ }
1653
+
1654
+ .quick-filters {
1655
+ display: flex;
1656
+ flex-direction: row;
1657
+ margin-bottom: 10px;
1658
+ }
1659
+
1660
+ .vertical-quick-filters {
1661
+ display: flex;
1662
+ flex-direction: column;
1663
+ align-items: start;
1664
+ width: 130px;
1665
+ }
1666
+
1667
+ @keyframes lineAnim {
1668
+ 0% {
1669
+ left: -40%;
1670
+ }
1671
+ 50% {
1672
+ left: 20%;
1673
+ width: 80%;
1674
+ }
1675
+ 100% {
1676
+ left: 100%;
1677
+ width: 100%;
1678
+ }
1679
+ }
1680
+
1681
+ .space-between {
1682
+ display: flex;
1683
+ justify-content: space-between;
1684
+ }
1685
+
1686
+ .active-quick-filters {
1687
+ display: flex;
1688
+ margin-right: 15px;
1689
+ background-color: rgb(var(--global-color-primary-500));
1690
+ border-radius: 5px;
1691
+ width: fit-content;
1692
+ }
1693
+
1694
+ .non-active-quick-filters {
1695
+ display: flex;
1696
+ margin-right: 16px;
1697
+ }
1698
+
1699
+ .quick-filter-icon {
1700
+ display: flex;
1701
+ gap: 4px;
1702
+ margin: 0 8px;
1703
+ }
1704
+
1705
+ .personalize-header {
1706
+ font-size: 20px;
1707
+ line-height: 28px;
1708
+ font-weight: 700;
1709
+ padding: 20px;
1710
+ }
1711
+
1712
+ .headers-show {
1713
+ display: grid;
1714
+ gap: 12px;
1715
+ padding: 8px;
1716
+ }
1717
+ </style>