@likable-hair/svelte 4.0.18 → 4.0.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/dist/components/composed/forms/ToggleList.svelte +7 -7
- package/dist/components/composed/list/PaginatedTable.svelte +56 -47
- package/dist/components/composed/search/Filters.css +1 -1
- package/dist/components/composed/search/Filters.svelte +86 -33
- package/dist/components/composed/search/MobileFilterEditor.svelte +46 -60
- package/dist/components/composed/search/SearchBar.css +1 -0
- package/dist/components/composed/search/SearchBar.svelte +13 -33
- package/dist/components/composed/search/SearchBar.svelte.d.ts +4 -4
- package/dist/components/simple/buttons/Button.css +1 -1
- package/package.json +1 -1
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
|
|
4
4
|
<script lang="ts" generics="Data">import '../../../css/main.css';
|
|
5
5
|
import Chip from "../../simple/navigation/Chip.svelte";
|
|
6
|
-
let { values = $bindable(
|
|
6
|
+
let { values = $bindable(), items, multiple = true, disabled = false, onchange, } = $props();
|
|
7
7
|
function select(item) {
|
|
8
|
-
const alreadyPresent = values
|
|
8
|
+
const alreadyPresent = values?.findIndex((i) => i.value === item.value) !== -1;
|
|
9
9
|
if (!alreadyPresent) {
|
|
10
10
|
if (multiple)
|
|
11
|
-
values = [...values, item];
|
|
11
|
+
values = [...(values || []), item];
|
|
12
12
|
else
|
|
13
13
|
values = [item];
|
|
14
14
|
if (onchange) {
|
|
@@ -23,19 +23,19 @@ function select(item) {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
function unselect(item) {
|
|
26
|
-
values = values
|
|
26
|
+
values = values?.filter((i) => i.value != item.value);
|
|
27
27
|
if (onchange) {
|
|
28
28
|
onchange({
|
|
29
29
|
detail: {
|
|
30
30
|
unselect: item,
|
|
31
31
|
select: undefined,
|
|
32
|
-
selection: values,
|
|
32
|
+
selection: values || [],
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
function toggle(item) {
|
|
38
|
-
const alreadyPresent = values
|
|
38
|
+
const alreadyPresent = values?.findIndex((i) => i.value === item.value) !== -1;
|
|
39
39
|
if (alreadyPresent)
|
|
40
40
|
unselect(item);
|
|
41
41
|
else
|
|
@@ -55,7 +55,7 @@ function toggle(item) {
|
|
|
55
55
|
{#each (items || []) as item}
|
|
56
56
|
<div class="chip">
|
|
57
57
|
<Chip
|
|
58
|
-
outlined={values
|
|
58
|
+
outlined={!values || values?.findIndex(i => i.value === item.value) === -1}
|
|
59
59
|
onclick={() => toggle(item)}
|
|
60
60
|
buttonTabIndex={0}
|
|
61
61
|
truncateText
|
|
@@ -5,16 +5,16 @@ import {} from "svelte";
|
|
|
5
5
|
import Filters from "../search/Filters.svelte";
|
|
6
6
|
import SearchBar from "../search/SearchBar.svelte";
|
|
7
7
|
import Converter from "../../../utils/filters/filters";
|
|
8
|
-
let { headers = [], items = [], sortedBy = $bindable(undefined), sortDirection = $bindable(
|
|
8
|
+
let { headers = [], items = [], sortedBy = $bindable(undefined), sortDirection = $bindable("asc"), page = $bindable(1), maxPage = undefined, rowsPerPageOptions = [
|
|
9
9
|
{ label: "20", value: 20 },
|
|
10
10
|
{ label: "50", value: 50 },
|
|
11
11
|
{ label: "100", value: 100 },
|
|
12
|
-
], hideRowsPerPage = false, totalElements = undefined, rowsPerPage = $bindable(20), filters = $bindable([]), searchBarColumns = undefined, searchBarVisible = true,
|
|
12
|
+
], hideRowsPerPage = false, totalElements = undefined, rowsPerPage = $bindable(20), filters = $bindable([]), searchBarColumns = undefined, searchBarVisible = true, lang = "en", editFilterMode = "one-edit", showActiveFilters = true, resizableColumns = false, resizedColumnSizeWithPadding = {}, pointerOnRowHover = undefined, doubleClickActive = false, doubleClickDelay = 250, calculateRowStyles = undefined, calculateRowClasses = undefined, class: clazz = {}, onfiltersChange, onpaginationChange, onremoveFilter, onremoveAllFilters, customFilterChipSnippet, customFilterSnippet, filterAppendSnippet, onrowClick, onrowDoubleClick, appendSnippet, customSnippet, headerLabelSnippet, headerSnippet, rowActionsSnippet, onsort, footerSnippet, rangeDescriptorSnippet, searchBarSnippet, noDataSnippet, oncolumnResize, } = $props();
|
|
13
13
|
let searchBarInput = $state(), searchText = $state(), sortModify;
|
|
14
14
|
let rowsPerPageSelection = $state([]);
|
|
15
15
|
$effect(() => {
|
|
16
16
|
rowsPerPageSelection = [
|
|
17
|
-
{ label: rowsPerPage.toString(), value: rowsPerPage }
|
|
17
|
+
{ label: rowsPerPage.toString(), value: rowsPerPage },
|
|
18
18
|
];
|
|
19
19
|
});
|
|
20
20
|
$effect(() => {
|
|
@@ -30,8 +30,10 @@ function handlePaginationChange() {
|
|
|
30
30
|
if (onpaginationChange) {
|
|
31
31
|
onpaginationChange({
|
|
32
32
|
detail: {
|
|
33
|
-
rowsPerPage,
|
|
34
|
-
|
|
33
|
+
rowsPerPage,
|
|
34
|
+
page,
|
|
35
|
+
builder,
|
|
36
|
+
},
|
|
35
37
|
});
|
|
36
38
|
}
|
|
37
39
|
}
|
|
@@ -40,8 +42,8 @@ function handleSearchChange(searchText) {
|
|
|
40
42
|
if (onfiltersChange) {
|
|
41
43
|
onfiltersChange({
|
|
42
44
|
detail: {
|
|
43
|
-
builder
|
|
44
|
-
}
|
|
45
|
+
builder,
|
|
46
|
+
},
|
|
45
47
|
});
|
|
46
48
|
}
|
|
47
49
|
}
|
|
@@ -53,8 +55,8 @@ function handleFiltersChange() {
|
|
|
53
55
|
if (onfiltersChange) {
|
|
54
56
|
onfiltersChange({
|
|
55
57
|
detail: {
|
|
56
|
-
builder
|
|
57
|
-
}
|
|
58
|
+
builder,
|
|
59
|
+
},
|
|
58
60
|
});
|
|
59
61
|
}
|
|
60
62
|
}
|
|
@@ -81,19 +83,24 @@ function buildFilters(params) {
|
|
|
81
83
|
let converter = new Converter();
|
|
82
84
|
let builder;
|
|
83
85
|
builder = converter.createBuilder({
|
|
84
|
-
filters: filters || []
|
|
86
|
+
filters: filters || [],
|
|
85
87
|
});
|
|
86
|
-
if (!!params?.searchText &&
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
if (!!params?.searchText &&
|
|
89
|
+
!!searchBarColumns &&
|
|
90
|
+
searchBarColumns.length > 0) {
|
|
91
|
+
builder.where((b) => {
|
|
92
|
+
b.where(searchBarColumns[0], "ilike", "%" + params?.searchText + "%");
|
|
89
93
|
for (let i = 1; i < searchBarColumns.length; i += 1) {
|
|
90
|
-
b.orWhere(searchBarColumns[i],
|
|
94
|
+
b.orWhere(searchBarColumns[i], "ilike", "%" + params?.searchText + "%");
|
|
91
95
|
}
|
|
92
96
|
});
|
|
93
97
|
}
|
|
94
98
|
if (!!sortedBy) {
|
|
95
99
|
if (sortModify) {
|
|
96
|
-
builder = sortModify({
|
|
100
|
+
builder = sortModify({
|
|
101
|
+
builder,
|
|
102
|
+
sortDirection: sortDirection || "asc",
|
|
103
|
+
});
|
|
97
104
|
}
|
|
98
105
|
else {
|
|
99
106
|
builder.orderBy(sortedBy, sortDirection || "asc");
|
|
@@ -104,35 +111,36 @@ function buildFilters(params) {
|
|
|
104
111
|
</script>
|
|
105
112
|
|
|
106
113
|
<div class="paginated-table">
|
|
107
|
-
{#if searchBarVisible}
|
|
108
|
-
{#if searchBarSnippet}
|
|
109
|
-
{@render searchBarSnippet({ handleSearchChange })}
|
|
110
|
-
{:else}
|
|
111
|
-
<div class="search-bar-container">
|
|
112
|
-
<SearchBar
|
|
113
|
-
placeholder={searchBarPlaceholder}
|
|
114
|
-
bind:input={searchBarInput}
|
|
115
|
-
bind:value={searchText}
|
|
116
|
-
>
|
|
117
|
-
</SearchBar>
|
|
118
|
-
</div>
|
|
119
|
-
{/if}
|
|
120
|
-
{/if}
|
|
121
114
|
<div class="filter-container">
|
|
115
|
+
{#if searchBarVisible}
|
|
116
|
+
{#if searchBarSnippet}
|
|
117
|
+
{@render searchBarSnippet({ handleSearchChange })}
|
|
118
|
+
{:else}
|
|
119
|
+
<div class="search-bar-container">
|
|
120
|
+
<SearchBar
|
|
121
|
+
bind:input={searchBarInput}
|
|
122
|
+
bind:value={searchText}
|
|
123
|
+
--search-bar-default-height="36px"
|
|
124
|
+
--search-bar-default-border-radius="4px"
|
|
125
|
+
--search-bar-default-ring-color="rgb(var(--global-color-background-300),.6)"
|
|
126
|
+
--search-bar-default-background-color="rgb(var(--global-color-background-300),.4)"
|
|
127
|
+
></SearchBar>
|
|
128
|
+
</div>
|
|
129
|
+
{/if}
|
|
130
|
+
{/if}
|
|
122
131
|
<Filters
|
|
123
132
|
bind:filters
|
|
124
133
|
onapplyFilter={handleFiltersChange}
|
|
125
134
|
onremoveFilter={handleRemoveFilter}
|
|
126
135
|
onremoveAllFilters={handleRemoveAllFilters}
|
|
127
|
-
--filters-default-wrapper-width="100%"
|
|
136
|
+
--filters-default-wrapper-width={!!searchBarVisible ? undefined : "100%"}
|
|
128
137
|
{lang}
|
|
129
138
|
{editFilterMode}
|
|
130
139
|
{showActiveFilters}
|
|
131
140
|
appendSnippet={filterAppendSnippet}
|
|
132
141
|
customChipSnippet={customFilterChipSnippet}
|
|
133
142
|
customSnippet={customFilterSnippet}
|
|
134
|
-
>
|
|
135
|
-
</Filters>
|
|
143
|
+
></Filters>
|
|
136
144
|
</div>
|
|
137
145
|
<SimpleTable
|
|
138
146
|
{headers}
|
|
@@ -158,12 +166,11 @@ function buildFilters(params) {
|
|
|
158
166
|
{headerLabelSnippet}
|
|
159
167
|
{noDataSnippet}
|
|
160
168
|
{oncolumnResize}
|
|
161
|
-
>
|
|
162
|
-
</SimpleTable>
|
|
169
|
+
></SimpleTable>
|
|
163
170
|
|
|
164
171
|
<div class="footer">
|
|
165
172
|
{#if footerSnippet}
|
|
166
|
-
{@render footerSnippet({
|
|
173
|
+
{@render footerSnippet({
|
|
167
174
|
hideRowsPerPage,
|
|
168
175
|
rowsPerPageOptions,
|
|
169
176
|
rowsPerPageSelection,
|
|
@@ -171,7 +178,7 @@ function buildFilters(params) {
|
|
|
171
178
|
page,
|
|
172
179
|
maxPage,
|
|
173
180
|
rowsPerPage,
|
|
174
|
-
handlePaginationChange
|
|
181
|
+
handlePaginationChange,
|
|
175
182
|
})}
|
|
176
183
|
{:else}
|
|
177
184
|
{#if !hideRowsPerPage}
|
|
@@ -189,17 +196,20 @@ function buildFilters(params) {
|
|
|
189
196
|
{/if}
|
|
190
197
|
{#if totalElements !== undefined}
|
|
191
198
|
{#if rangeDescriptorSnippet}
|
|
192
|
-
{@render rangeDescriptorSnippet({
|
|
199
|
+
{@render rangeDescriptorSnippet({
|
|
200
|
+
page,
|
|
201
|
+
maxPage,
|
|
202
|
+
rowsPerPage,
|
|
203
|
+
totalElements,
|
|
204
|
+
})}
|
|
193
205
|
{:else}
|
|
194
206
|
<div class="range-descriptor">
|
|
195
|
-
viewing {((page || 1) - 1) * rowsPerPage} - {(page || 1) *
|
|
207
|
+
viewing {((page || 1) - 1) * rowsPerPage} - {(page || 1) *
|
|
208
|
+
rowsPerPage} of {totalElements}
|
|
196
209
|
</div>
|
|
197
210
|
{/if}
|
|
198
211
|
{/if}
|
|
199
|
-
<Paginator
|
|
200
|
-
bind:page
|
|
201
|
-
{maxPage}
|
|
202
|
-
onchange={handlePaginationChange}
|
|
212
|
+
<Paginator bind:page {maxPage} onchange={handlePaginationChange}
|
|
203
213
|
></Paginator>
|
|
204
214
|
{/if}
|
|
205
215
|
</div>
|
|
@@ -214,7 +224,7 @@ function buildFilters(params) {
|
|
|
214
224
|
}
|
|
215
225
|
|
|
216
226
|
.range-descriptor {
|
|
217
|
-
font-size: .7rem;
|
|
227
|
+
font-size: 0.7rem;
|
|
218
228
|
}
|
|
219
229
|
|
|
220
230
|
.footer {
|
|
@@ -225,11 +235,10 @@ function buildFilters(params) {
|
|
|
225
235
|
}
|
|
226
236
|
|
|
227
237
|
.filter-container {
|
|
228
|
-
margin-top: var(--paginated-table-filter-container-margin-top, 10px);
|
|
229
238
|
display: flex;
|
|
230
239
|
align-items: center;
|
|
231
240
|
flex-direction: row;
|
|
232
|
-
gap:
|
|
241
|
+
gap: 12px;
|
|
233
242
|
width: 100%;
|
|
234
243
|
}
|
|
235
244
|
|
|
@@ -238,6 +247,7 @@ function buildFilters(params) {
|
|
|
238
247
|
--paginated-table-search-bar-container-padding,
|
|
239
248
|
var(--paginated-table-search-bar-container-default-padding, 0)
|
|
240
249
|
);
|
|
250
|
+
flex-grow: 1;
|
|
241
251
|
}
|
|
242
252
|
|
|
243
253
|
@media only screen and (max-width: 768px) {
|
|
@@ -245,5 +255,4 @@ function buildFilters(params) {
|
|
|
245
255
|
display: none;
|
|
246
256
|
}
|
|
247
257
|
}
|
|
248
|
-
|
|
249
|
-
</style>
|
|
258
|
+
</style>
|
|
@@ -19,7 +19,7 @@ import Dialog from '../../simple/dialogs/Dialog.svelte';
|
|
|
19
19
|
import Validator from '../../../utils/filters/validator';
|
|
20
20
|
import ToolTip from '../common/ToolTip.svelte';
|
|
21
21
|
import { DateTime } from 'luxon';
|
|
22
|
-
let { filters = $bindable([]), lang = 'en', addFilterLabel = lang === 'en' ? "Filters" : "Filtri", cancelFilterLabel = lang === 'en' ? "Cancel" : "Annulla", applyFilterLabel = lang === 'en' ? "Apply
|
|
22
|
+
let { filters = $bindable([]), lang = 'en', addFilterLabel = lang === 'en' ? "Filters" : "Filtri", cancelFilterLabel = lang === 'en' ? "Cancel" : "Annulla", applyFilterLabel = lang === 'en' ? "Apply filters" : "Applica filtri", showActiveFilters = true, filterTitleLabel = lang === 'en' ? "Filter by" : "Filtra per", dateLocale = lang === 'en' ? 'en' : 'it', betweenSeparator = lang === 'en' ? "and" : "e", trueString = lang === 'en' ? "true" : "vero", falseString = lang === 'en' ? "false" : "falso", editFilterMode = 'one-edit', labelsMapper = lang === 'en'
|
|
23
23
|
? {
|
|
24
24
|
equal: { extended: 'equal to', short: 'equal' },
|
|
25
25
|
like: { short: 'includes' },
|
|
@@ -39,7 +39,7 @@ let { filters = $bindable([]), lang = 'en', addFilterLabel = lang === 'en' ? "Fi
|
|
|
39
39
|
lower: { short: 'minore', extended: 'minore di' },
|
|
40
40
|
between: { short: 'compreso', extended: 'è compreso tra' },
|
|
41
41
|
different: { short: 'diverso', extended: 'diverso da' }
|
|
42
|
-
}, drawerSpace = '
|
|
42
|
+
}, drawerSpace = '60vh', onaddFilterClick, onapplyFilter, onremoveAllFilters, onremoveFilter, customSnippet: customInternalSnippet, customChipSnippet, appendSnippet, contentSnippet, onclick: onclickInternal, onkeydown, } = $props();
|
|
43
43
|
let open = $state(false), mobileOpen = $state(false), activator = $state();
|
|
44
44
|
function handleAddFilterClick() {
|
|
45
45
|
if (onaddFilterClick) {
|
|
@@ -321,7 +321,7 @@ function onclick(event, stopPropagation = false) {
|
|
|
321
321
|
|
|
322
322
|
<MediaQuery>
|
|
323
323
|
{#snippet defaultSnippet({ mAndDown})}
|
|
324
|
-
<div class="filters-wrapper" class:mobile={mAndDown} style:--filter-dot-size={activeFilters.length > 0 ? '
|
|
324
|
+
<div class="filters-wrapper" class:mobile={mAndDown} style:--filter-dot-size={activeFilters.length > 0 ? '16px' : '0px'} style:--filter-dot-content={activeFilters.length > 0 ? `"${activeFilters.length}"` : '""'}>
|
|
325
325
|
<div class="filters-container" class:mobile={mAndDown} class:hidden={mAndDown && (!showActiveFilters || activeFilters.length == 0)}>
|
|
326
326
|
{#if showActiveFilters}
|
|
327
327
|
{#each activeFilters as filter}
|
|
@@ -332,6 +332,7 @@ function onclick(event, stopPropagation = false) {
|
|
|
332
332
|
<Chip
|
|
333
333
|
label
|
|
334
334
|
close
|
|
335
|
+
--chip-border-radius="4px"
|
|
335
336
|
onclose={() => handleRemoveFilter(filter)}
|
|
336
337
|
onclick={() => handleActiveFilterClick(filter)}
|
|
337
338
|
>
|
|
@@ -385,7 +386,7 @@ function onclick(event, stopPropagation = false) {
|
|
|
385
386
|
<span class="more-items" bind:this={moreItemsActivator}>+{filter.values.length - 1}</span>
|
|
386
387
|
<ToolTip activator={moreItemsActivator}>
|
|
387
388
|
<div class="more-tooltip-content">
|
|
388
|
-
<ul>
|
|
389
|
+
<ul style:margin="0px">
|
|
389
390
|
{#each filter.values as value}
|
|
390
391
|
<li><div class="truncate-text">{value.label}</div></li>
|
|
391
392
|
{/each}
|
|
@@ -408,6 +409,7 @@ function onclick(event, stopPropagation = false) {
|
|
|
408
409
|
>
|
|
409
410
|
<Button
|
|
410
411
|
--button-color="var(--chip-color, var(--chip-default-color))"
|
|
412
|
+
--button-border-radius="4px"
|
|
411
413
|
--button-height="var(--filters-button-height, var(--filters-default-button-height))"
|
|
412
414
|
onclick={handleAddFilterClick}
|
|
413
415
|
>
|
|
@@ -415,7 +417,11 @@ function onclick(event, stopPropagation = false) {
|
|
|
415
417
|
<Icon name="mdi-filter"></Icon>
|
|
416
418
|
{addFilterLabel}
|
|
417
419
|
<div class="remove-filters" class:hidden={activeFilters.length <= 0}>
|
|
418
|
-
<Icon
|
|
420
|
+
<Icon
|
|
421
|
+
name="mdi-close-circle"
|
|
422
|
+
onclick={handleRemoveAllFilters}
|
|
423
|
+
--icon-hover-color="var(--chip-color, var(--chip-default-color))"
|
|
424
|
+
></Icon>
|
|
419
425
|
</div>
|
|
420
426
|
</div>
|
|
421
427
|
</Button>
|
|
@@ -430,6 +436,8 @@ function onclick(event, stopPropagation = false) {
|
|
|
430
436
|
>
|
|
431
437
|
<Button
|
|
432
438
|
--button-color="var(--chip-color, var(--chip-default-color))"
|
|
439
|
+
--button-hover-color="var(--chip-color, var(--chip-default-color))"
|
|
440
|
+
--button-border-radius="4px"
|
|
433
441
|
--button-height="var(--filters-button-height, var(--filters-default-button-height))"
|
|
434
442
|
onclick={handleAddFilterClick}
|
|
435
443
|
>
|
|
@@ -437,7 +445,11 @@ function onclick(event, stopPropagation = false) {
|
|
|
437
445
|
<Icon name="mdi-filter"></Icon>
|
|
438
446
|
{addFilterLabel}
|
|
439
447
|
<div class="remove-filters" class:hidden={activeFilters.length <= 0}>
|
|
440
|
-
<Icon
|
|
448
|
+
<Icon
|
|
449
|
+
name="mdi-close-circle"
|
|
450
|
+
onclick={handleRemoveAllFilters}
|
|
451
|
+
--icon-hover-color="var(--chip-color, var(--chip-default-color))"
|
|
452
|
+
></Icon>
|
|
441
453
|
</div>
|
|
442
454
|
</div>
|
|
443
455
|
</Button>
|
|
@@ -536,9 +548,9 @@ function onclick(event, stopPropagation = false) {
|
|
|
536
548
|
>
|
|
537
549
|
<div class="form-container" style:background-color={mAndDown ? 'transparent' : 'rgb(var(--global-color-background-100))'} style:width={mAndDown ? '100%' : '50vw'} style:box-sizing="border-box">
|
|
538
550
|
<div class="header">
|
|
539
|
-
<
|
|
551
|
+
<div>{addFilterLabel}</div>
|
|
540
552
|
</div>
|
|
541
|
-
<div class="body">
|
|
553
|
+
<div class="drawer-body">
|
|
542
554
|
{#if contentSnippet}
|
|
543
555
|
{@render contentSnippet({ mAndDown, updateMultiFilterValues, filters, handleRemoveAllFilters })}
|
|
544
556
|
{:else}
|
|
@@ -706,12 +718,19 @@ function onclick(event, stopPropagation = false) {
|
|
|
706
718
|
{:else if editFilterMode === 'multi-edit'}
|
|
707
719
|
<Dialog
|
|
708
720
|
bind:open={open}
|
|
721
|
+
_overlayOpacity="50%"
|
|
722
|
+
_overlayBackdropFilter="blur(4px)"
|
|
709
723
|
>
|
|
710
|
-
<div
|
|
724
|
+
<div
|
|
725
|
+
class="form-container"
|
|
726
|
+
style:background-color={mAndDown ? 'transparent' : 'rgb(var(--global-color-background-100))'}
|
|
727
|
+
style:width={mAndDown ? '100%' : '800px'}
|
|
728
|
+
style:box-sizing="border-box"
|
|
729
|
+
>
|
|
711
730
|
<div class="header">
|
|
712
|
-
<
|
|
731
|
+
<div>{addFilterLabel}</div>
|
|
713
732
|
</div>
|
|
714
|
-
<div class="body">
|
|
733
|
+
<div class="dialog-body">
|
|
715
734
|
{#if contentSnippet}
|
|
716
735
|
{@render contentSnippet({ mAndDown, updateMultiFilterValues, filters, handleRemoveAllFilters })}
|
|
717
736
|
{:else}
|
|
@@ -744,30 +763,37 @@ function onclick(event, stopPropagation = false) {
|
|
|
744
763
|
</div>
|
|
745
764
|
{/if}
|
|
746
765
|
</div>
|
|
747
|
-
<div class="footer">
|
|
766
|
+
<div class="dialog-footer">
|
|
748
767
|
<div class="actions" style:padding-bottom={mAndDown ? '20px' : undefined}>
|
|
749
768
|
<Button
|
|
750
|
-
--button-
|
|
751
|
-
--button-color="
|
|
752
|
-
--button-
|
|
753
|
-
--button-
|
|
769
|
+
--button-color="rgb(var(--global-color-contrast-900))"
|
|
770
|
+
--button-background-color="transparent"
|
|
771
|
+
--button-focus-background-color="rgb(var(--global-color-background-200, .5))"
|
|
772
|
+
--button-active-background-color="rgb(var(--global-color-background-200, .5))"
|
|
773
|
+
--button-hover-background-color="rgb(var(--global-color-background-200, .5))"
|
|
774
|
+
--button-hover-box-shadow="none"
|
|
754
775
|
--button-box-shadow="none"
|
|
776
|
+
--button-padding="12px 16px"
|
|
755
777
|
onclick={handleCancelFilterClick}
|
|
756
778
|
>
|
|
757
779
|
{cancelFilterLabel}
|
|
758
780
|
</Button>
|
|
759
781
|
<Button
|
|
760
|
-
--button-color="rgb(var(--global-color-
|
|
782
|
+
--button-color="rgb(var(--global-color-contrast-900))"
|
|
761
783
|
--button-background-color="transparent"
|
|
762
|
-
--button-
|
|
763
|
-
--button-
|
|
784
|
+
--button-focus-background-color="rgb(var(--global-color-background-200, .5))"
|
|
785
|
+
--button-active-background-color="rgb(var(--global-color-background-200, .5))"
|
|
786
|
+
--button-hover-background-color="rgb(var(--global-color-background-200, .5))"
|
|
787
|
+
--button-hover-box-shadow="none"
|
|
764
788
|
--button-box-shadow="none"
|
|
789
|
+
--button-padding="12px 16px"
|
|
765
790
|
onclick={handleMultiEditRemoveClick}
|
|
766
791
|
>
|
|
767
792
|
{lang == 'en' ? "Remove filters" : "Rimuovi filtri"}
|
|
768
793
|
</Button>
|
|
769
794
|
<Button
|
|
770
|
-
--button-min-width="
|
|
795
|
+
--button-min-width="fit-content"
|
|
796
|
+
--button-padding="12px 16px"
|
|
771
797
|
onclick={handleApplyMultiFilterClick}
|
|
772
798
|
>
|
|
773
799
|
{applyFilterLabel}
|
|
@@ -783,6 +809,9 @@ function onclick(event, stopPropagation = false) {
|
|
|
783
809
|
|
|
784
810
|
|
|
785
811
|
<style>
|
|
812
|
+
* {
|
|
813
|
+
box-sizing: border-box;
|
|
814
|
+
}
|
|
786
815
|
|
|
787
816
|
.sub-filter-button {
|
|
788
817
|
display: flex;
|
|
@@ -798,7 +827,6 @@ function onclick(event, stopPropagation = false) {
|
|
|
798
827
|
}
|
|
799
828
|
|
|
800
829
|
.filter-button-content .remove-filters {
|
|
801
|
-
margin: 0px 8px 0px 8px;
|
|
802
830
|
color: rgb(var(--global-color-primary-100));
|
|
803
831
|
}
|
|
804
832
|
|
|
@@ -813,15 +841,16 @@ function onclick(event, stopPropagation = false) {
|
|
|
813
841
|
.filter-button::before {
|
|
814
842
|
content: var(--filter-dot-content, '0');
|
|
815
843
|
text-align: center;
|
|
816
|
-
font-size: .
|
|
844
|
+
font-size: .5rem;
|
|
817
845
|
background-color: rgb(var(--global-color-background-500));
|
|
818
846
|
color: rgb(var(--global-color-contrast-700));
|
|
819
847
|
position: absolute;
|
|
820
848
|
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
|
|
821
|
-
top: -
|
|
822
|
-
|
|
849
|
+
top: -16%;
|
|
850
|
+
right: -8%;
|
|
823
851
|
border-radius: 100px;
|
|
824
852
|
width: var(--filter-dot-size, 0px);
|
|
853
|
+
line-height: 16px;
|
|
825
854
|
height: var(--filter-dot-size, 0px);
|
|
826
855
|
}
|
|
827
856
|
|
|
@@ -840,7 +869,7 @@ function onclick(event, stopPropagation = false) {
|
|
|
840
869
|
.filters-container {
|
|
841
870
|
display: flex;
|
|
842
871
|
flex-wrap: wrap;
|
|
843
|
-
gap:
|
|
872
|
+
gap: 8px;
|
|
844
873
|
align-items: center;
|
|
845
874
|
}
|
|
846
875
|
|
|
@@ -852,7 +881,7 @@ function onclick(event, stopPropagation = false) {
|
|
|
852
881
|
.filters-wrapper {
|
|
853
882
|
display: flex;
|
|
854
883
|
align-items: start;
|
|
855
|
-
gap:
|
|
884
|
+
gap: 8px;
|
|
856
885
|
max-width: 100%;
|
|
857
886
|
width: var(
|
|
858
887
|
--filters-wrapper-width,
|
|
@@ -873,13 +902,13 @@ function onclick(event, stopPropagation = false) {
|
|
|
873
902
|
|
|
874
903
|
.more-items {
|
|
875
904
|
position: relative;
|
|
876
|
-
padding:
|
|
877
|
-
border-radius:
|
|
878
|
-
margin-left:
|
|
905
|
+
padding: 0px 6px;
|
|
906
|
+
border-radius: 8px;
|
|
907
|
+
margin-left: 2px;
|
|
879
908
|
background-color: rgb(var(--global-color-grey-50));
|
|
880
909
|
color: rgb(var(--global-color-primary-500));
|
|
881
910
|
font-weight: 800;
|
|
882
|
-
font-size:
|
|
911
|
+
font-size: 10px;
|
|
883
912
|
}
|
|
884
913
|
|
|
885
914
|
.more-tooltip-content {
|
|
@@ -887,7 +916,7 @@ function onclick(event, stopPropagation = false) {
|
|
|
887
916
|
text-overflow: ellipsis;
|
|
888
917
|
width: fit-content;
|
|
889
918
|
border-radius: 6px;
|
|
890
|
-
padding:
|
|
919
|
+
padding: 16px;
|
|
891
920
|
text-align: left;
|
|
892
921
|
background-color: rgb(var(--global-color-background-200));
|
|
893
922
|
color: rgb(var(--global-color-background-950));
|
|
@@ -913,7 +942,7 @@ function onclick(event, stopPropagation = false) {
|
|
|
913
942
|
|
|
914
943
|
.form-container {
|
|
915
944
|
border-radius: 10px;
|
|
916
|
-
|
|
945
|
+
box-shadow: 0 0 1px 1px rgb(var(--global-color-background-200));
|
|
917
946
|
height: 100%;
|
|
918
947
|
max-height: 90vh;
|
|
919
948
|
overflow-y: auto;
|
|
@@ -963,7 +992,31 @@ function onclick(event, stopPropagation = false) {
|
|
|
963
992
|
.header {
|
|
964
993
|
font-weight: 600;
|
|
965
994
|
font-size: 1.5rem;
|
|
966
|
-
padding:
|
|
995
|
+
padding: 16px;
|
|
996
|
+
height: 64px;
|
|
997
|
+
display: flex;
|
|
998
|
+
align-items: center;
|
|
999
|
+
border-bottom: 1px solid rgb(var(--global-color-background-200));
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
.drawer-body {
|
|
1003
|
+
padding: 16px;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.dialog-body {
|
|
1007
|
+
padding: 16px;
|
|
1008
|
+
height: calc(90vh - 164px);
|
|
1009
|
+
max-height: calc(90vh - 164px);
|
|
1010
|
+
overflow-y: auto;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
.dialog-footer {
|
|
1014
|
+
height: 64px;
|
|
1015
|
+
padding: 16px;
|
|
1016
|
+
display: flex;
|
|
1017
|
+
align-items: center;
|
|
1018
|
+
justify-content: flex-end;
|
|
1019
|
+
border-top: 1px solid rgb(var(--global-color-background-200));
|
|
967
1020
|
}
|
|
968
1021
|
|
|
969
1022
|
</style>
|
|
@@ -8,17 +8,11 @@ import { fly } from "svelte/transition";
|
|
|
8
8
|
import Autocomplete from "../../simple/forms/Autocomplete.svelte";
|
|
9
9
|
import Checkbox from "../../simple/forms/Checkbox.svelte";
|
|
10
10
|
import ToggleList from "../forms/ToggleList.svelte";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// if(!!filter && !!tmpFilter) {
|
|
14
|
-
// filter = {...tmpFilter}
|
|
15
|
-
// filter.active = true
|
|
16
|
-
// dispatch('apply')
|
|
17
|
-
// }
|
|
18
|
-
// }
|
|
11
|
+
import lodash from 'lodash';
|
|
12
|
+
let { filter = $bindable(), lang = 'en', backIcon = "mdi-arrow-left", betweenFromLabel = lang === 'en' ? "From" : "Da", betweenToLabel = lang === 'en' ? "To" : "A", labelsMapper, forceApplyValid = false, tmpFilter = $bindable(), onbackClick, onkeypress, onclick: onclickInternal, onclose, customSnippet, filterActionsSnippet, titleSnippet, } = $props();
|
|
19
13
|
let step = $state();
|
|
20
14
|
function initTmpFilter() {
|
|
21
|
-
tmpFilter = filter === undefined ? undefined :
|
|
15
|
+
tmpFilter = filter === undefined ? undefined : lodash.cloneDeep(filter);
|
|
22
16
|
if (!!tmpFilter && tmpFilter.advanced) {
|
|
23
17
|
if (['string', 'number', 'date', 'select'].includes(tmpFilter.type) && Object.keys(tmpFilter).includes('mode')) {
|
|
24
18
|
//@ts-ignore
|
|
@@ -39,14 +33,53 @@ function initTmpFilter() {
|
|
|
39
33
|
step = "editor";
|
|
40
34
|
}
|
|
41
35
|
}
|
|
36
|
+
let advancedModeOptions = $state(), advancedModeSelectedOption = $state();
|
|
37
|
+
let calendarOpened = $state(false), calendarOpened2 = $state(false);
|
|
38
|
+
// TODO I don't like that there is a single dropdown to handle all filter advance mode.
|
|
39
|
+
// In some case would be necessary to handle more than one selection and this code
|
|
40
|
+
// could become non sense
|
|
41
|
+
function handleAdvancedModeSelection() {
|
|
42
|
+
if (!!advancedModeSelectedOption && !!tmpFilter) {
|
|
43
|
+
if (tmpFilter.type == 'date')
|
|
44
|
+
tmpFilter.mode = advancedModeSelectedOption;
|
|
45
|
+
else if (tmpFilter.type == 'string')
|
|
46
|
+
tmpFilter.mode = advancedModeSelectedOption;
|
|
47
|
+
else if (tmpFilter.type == 'number')
|
|
48
|
+
tmpFilter.mode = advancedModeSelectedOption;
|
|
49
|
+
else if (tmpFilter.type == 'select')
|
|
50
|
+
tmpFilter.mode = advancedModeSelectedOption;
|
|
51
|
+
step = 'editor';
|
|
52
|
+
canRenderOptions = false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
let canRenderOptions = $state(true);
|
|
56
|
+
let applyFilterDisabled = $derived(!Validator.isValid(tmpFilter) && !forceApplyValid);
|
|
57
|
+
let lastSyncedFilter = $state(filter);
|
|
42
58
|
$effect(() => {
|
|
43
|
-
if (!!filter) {
|
|
59
|
+
if (!tmpFilter || !step || (!!filter && !lodash.isEqual($state.snapshot(filter), $state.snapshot(lastSyncedFilter)))) {
|
|
44
60
|
initTmpFilter();
|
|
61
|
+
lastSyncedFilter = filter;
|
|
45
62
|
}
|
|
46
|
-
});
|
|
47
|
-
let advancedModeOptions = $state(), advancedModeSelectedOption = $state();
|
|
48
|
-
$effect(() => {
|
|
49
63
|
if (!!tmpFilter) {
|
|
64
|
+
if (tmpFilter.type == 'bool') {
|
|
65
|
+
if (tmpFilter.value === undefined) {
|
|
66
|
+
tmpFilter.value = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (tmpFilter.type == 'select') {
|
|
70
|
+
if (tmpFilter.values === undefined) {
|
|
71
|
+
tmpFilter.values = [];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (tmpFilter.type == 'date' && tmpFilter.mode == 'between') {
|
|
75
|
+
if (!tmpFilter.from)
|
|
76
|
+
tmpFilter.from = new Date();
|
|
77
|
+
if (!tmpFilter.to)
|
|
78
|
+
tmpFilter.to = new Date();
|
|
79
|
+
}
|
|
80
|
+
if (!tmpFilter.advanced) {
|
|
81
|
+
advancedModeSelectedOption = undefined;
|
|
82
|
+
}
|
|
50
83
|
let modes;
|
|
51
84
|
if (tmpFilter.type == 'string') {
|
|
52
85
|
modes = STRING_MODES;
|
|
@@ -70,45 +103,6 @@ $effect(() => {
|
|
|
70
103
|
}
|
|
71
104
|
}
|
|
72
105
|
});
|
|
73
|
-
$effect(() => {
|
|
74
|
-
if (!tmpFilter?.advanced) {
|
|
75
|
-
advancedModeSelectedOption = undefined;
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
let calendarOpened = $state(false), calendarOpened2 = $state(false);
|
|
79
|
-
// TODO I don't like that there is a singlo dropdow to handle all filter advance mode.
|
|
80
|
-
// In some case would be necessary to handle more than one selection and this code
|
|
81
|
-
// could become non sense
|
|
82
|
-
function handleAdvancedModeSelection() {
|
|
83
|
-
if (!!advancedModeSelectedOption && !!tmpFilter) {
|
|
84
|
-
if (tmpFilter.type == 'date')
|
|
85
|
-
tmpFilter.mode = advancedModeSelectedOption;
|
|
86
|
-
else if (tmpFilter.type == 'string')
|
|
87
|
-
tmpFilter.mode = advancedModeSelectedOption;
|
|
88
|
-
else if (tmpFilter.type == 'number')
|
|
89
|
-
tmpFilter.mode = advancedModeSelectedOption;
|
|
90
|
-
else if (tmpFilter.type == 'select')
|
|
91
|
-
tmpFilter.mode = advancedModeSelectedOption;
|
|
92
|
-
step = 'editor';
|
|
93
|
-
canRenderOptions = false;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
let canRenderOptions = $state(true);
|
|
97
|
-
let applyFilterDisabled = $derived(!Validator.isValid(tmpFilter) && !forceApplyValid);
|
|
98
|
-
$effect(() => {
|
|
99
|
-
if (!!tmpFilter && tmpFilter.type == 'bool') {
|
|
100
|
-
if (tmpFilter.value === undefined) {
|
|
101
|
-
tmpFilter.value = false;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
$effect(() => {
|
|
106
|
-
if (!!tmpFilter && tmpFilter.type == 'select') {
|
|
107
|
-
if (tmpFilter.values === undefined) {
|
|
108
|
-
tmpFilter.values = [];
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
106
|
function handleModeBackClick() {
|
|
113
107
|
if (onbackClick) {
|
|
114
108
|
onbackClick();
|
|
@@ -128,14 +122,6 @@ function handleEditorBackCLick() {
|
|
|
128
122
|
}, 100);
|
|
129
123
|
}
|
|
130
124
|
}
|
|
131
|
-
$effect(() => {
|
|
132
|
-
if (!!tmpFilter && tmpFilter.type == 'date' && tmpFilter.mode == 'between') {
|
|
133
|
-
if (!tmpFilter.from)
|
|
134
|
-
tmpFilter.from = new Date();
|
|
135
|
-
if (!tmpFilter.to)
|
|
136
|
-
tmpFilter.to = new Date();
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
125
|
function onclick(event) {
|
|
140
126
|
event.stopPropagation();
|
|
141
127
|
if (onclickInternal) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
:root {
|
|
2
2
|
--search-bar-default-ring-color: rgb(var(--global-color-contrast-100));
|
|
3
|
+
--search-bar-default-ring-width: 1px;
|
|
3
4
|
--search-bar-default-background-color: rgb(var(--global-color-background-100));
|
|
4
5
|
--search-bar-default-border-radius: 0.5rem;
|
|
5
6
|
--search-bar-default-height: 3rem;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
<script lang="ts">import
|
|
2
|
-
import
|
|
1
|
+
<script lang="ts">import "../../../css/main.css";
|
|
2
|
+
import "./SearchBar.css";
|
|
3
3
|
let { input = $bindable(undefined), value = $bindable(undefined), placeholder = undefined, class: clazz = {}, onblur, onchange, onfocus, oninput, onkeydown, iconSnippet, inputSnippet, } = $props();
|
|
4
4
|
</script>
|
|
5
5
|
|
|
6
|
-
<div
|
|
7
|
-
class="search-bar-container {clazz.container}"
|
|
8
|
-
>
|
|
6
|
+
<div class="search-bar-container {clazz.container}">
|
|
9
7
|
{#if iconSnippet}
|
|
10
8
|
{@render iconSnippet()}
|
|
11
9
|
{:else}
|
|
@@ -34,11 +32,11 @@ let { input = $bindable(undefined), value = $bindable(undefined), placeholder =
|
|
|
34
32
|
autocapitalize="off"
|
|
35
33
|
enterkeyhint="search"
|
|
36
34
|
spellcheck="false"
|
|
37
|
-
|
|
35
|
+
{placeholder}
|
|
38
36
|
maxlength="512"
|
|
39
37
|
tabindex="0"
|
|
40
38
|
bind:this={input}
|
|
41
|
-
bind:value
|
|
39
|
+
bind:value
|
|
42
40
|
{oninput}
|
|
43
41
|
{onchange}
|
|
44
42
|
{onkeydown}
|
|
@@ -47,15 +45,12 @@ let { input = $bindable(undefined), value = $bindable(undefined), placeholder =
|
|
|
47
45
|
class="input {clazz.input}"
|
|
48
46
|
/>
|
|
49
47
|
{/if}
|
|
50
|
-
|
|
51
48
|
</div>
|
|
52
49
|
|
|
53
50
|
<style>
|
|
54
51
|
.search-bar-container {
|
|
55
|
-
box-shadow: inset 0 0 0
|
|
56
|
-
--search-bar-ring-color,
|
|
57
|
-
var(--search-bar-default-ring-color)
|
|
58
|
-
);
|
|
52
|
+
box-shadow: inset 0 0 0 var(--search-bar-ring-width, var(--search-bar-default-ring-width))
|
|
53
|
+
var(--search-bar-ring-color, var(--search-bar-default-ring-color));
|
|
59
54
|
background-color: var(
|
|
60
55
|
--search-bar-background-color,
|
|
61
56
|
var(--search-bar-default-background-color)
|
|
@@ -64,33 +59,18 @@ let { input = $bindable(undefined), value = $bindable(undefined), placeholder =
|
|
|
64
59
|
--search-bar-border-radius,
|
|
65
60
|
var(--search-bar-default-border-radius)
|
|
66
61
|
);
|
|
67
|
-
height: var(
|
|
68
|
-
--search-bar-height,
|
|
69
|
-
var(--search-bar-default-height)
|
|
70
|
-
);
|
|
62
|
+
height: var(--search-bar-height, var(--search-bar-default-height));
|
|
71
63
|
display: flex;
|
|
72
64
|
align-items: center;
|
|
73
65
|
gap: 0.5rem;
|
|
74
|
-
padding: var(
|
|
75
|
-
--search-bar-padding,
|
|
76
|
-
var(--search-bar-default-padding)
|
|
77
|
-
);
|
|
66
|
+
padding: var(--search-bar-padding, var(--search-bar-default-padding));
|
|
78
67
|
box-sizing: border-box;
|
|
79
|
-
max-width: var(
|
|
80
|
-
|
|
81
|
-
var(--search-bar-default-max-width)
|
|
82
|
-
);
|
|
83
|
-
width: var(
|
|
84
|
-
--search-bar-width,
|
|
85
|
-
var(--search-bar-default-width)
|
|
86
|
-
);
|
|
68
|
+
max-width: var(--search-bar-max-width, var(--search-bar-default-max-width));
|
|
69
|
+
width: var(--search-bar-width, var(--search-bar-default-width));
|
|
87
70
|
}
|
|
88
71
|
|
|
89
72
|
.input {
|
|
90
|
-
font-size: var(
|
|
91
|
-
--search-bar-font-size,
|
|
92
|
-
var(--search-bar-default-font-size)
|
|
93
|
-
);
|
|
73
|
+
font-size: var(--search-bar-font-size, var(--search-bar-default-font-size));
|
|
94
74
|
line-height: var(
|
|
95
75
|
--search-bar-line-height,
|
|
96
76
|
var(--search-bar-default-line-height)
|
|
@@ -110,4 +90,4 @@ let { input = $bindable(undefined), value = $bindable(undefined), placeholder =
|
|
|
110
90
|
width: 1.25rem;
|
|
111
91
|
stroke: currentColor;
|
|
112
92
|
}
|
|
113
|
-
</style>
|
|
93
|
+
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ChangeEventHandler, FocusEventHandler, FormEventHandler, KeyboardEventHandler } from
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import type { Snippet } from
|
|
1
|
+
import type { ChangeEventHandler, FocusEventHandler, FormEventHandler, KeyboardEventHandler } from "svelte/elements";
|
|
2
|
+
import "../../../css/main.css";
|
|
3
|
+
import "./SearchBar.css";
|
|
4
|
+
import type { Snippet } from "svelte";
|
|
5
5
|
interface Props {
|
|
6
6
|
input?: HTMLElement;
|
|
7
7
|
value?: string;
|
|
@@ -20,6 +20,6 @@
|
|
|
20
20
|
--button-default-text-active-background-color: rgb(var(--global-color-primary-500), 0.4);
|
|
21
21
|
--button-default-icon-active-color: rgb(var(--global-color-primary-500));
|
|
22
22
|
--button-default-icon-focus-color: rgb(var(--global-color-primary-500));
|
|
23
|
-
--button-default-box-shadow:
|
|
23
|
+
--button-default-box-shadow: none;
|
|
24
24
|
--button-default-text-font-weight: 600;
|
|
25
25
|
}
|