@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.
@@ -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([]), items, multiple = true, disabled = false, onchange, } = $props();
6
+ let { values = $bindable(), items, multiple = true, disabled = false, onchange, } = $props();
7
7
  function select(item) {
8
- const alreadyPresent = values.findIndex((i) => i.value === item.value) != -1;
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.filter((i) => i.value != item.value);
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.findIndex((i) => i.value === item.value) != -1;
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.findIndex(i => i.value === item.value) === -1}
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('asc'), page = $bindable(1), maxPage = undefined, rowsPerPageOptions = [
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, searchBarPlaceholder = "Type something to search...", 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();
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, page, builder
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 && !!searchBarColumns && searchBarColumns.length > 0) {
87
- builder.where(b => {
88
- b.where(searchBarColumns[0], 'ilike', '%' + params?.searchText + '%');
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], 'ilike', '%' + params?.searchText + '%');
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({ builder, sortDirection: sortDirection || 'asc' });
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({ page, maxPage, rowsPerPage, totalElements })}
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) * rowsPerPage} of {totalElements}
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: 10px;
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>
@@ -3,5 +3,5 @@
3
3
  --filters-button-cancel-default-color: rgb(var(--global-color-primary-400));
4
4
  --filters-default-one-edit-menu-max-height: 100%;
5
5
  --filters-default-wrapper-width: auto;
6
- --filters-default-button-height: 28px;
6
+ --filters-default-button-height: 20px;
7
7
  }
@@ -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 filter" : "Applica filtro", 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'
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 = '20rem', onaddFilterClick, onapplyFilter, onremoveAllFilters, onremoveFilter, customSnippet: customInternalSnippet, customChipSnippet, appendSnippet, contentSnippet, onclick: onclickInternal, onkeydown, } = $props();
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 ? '22px' : '0px'} style:--filter-dot-content={activeFilters.length > 0 ? `"${activeFilters.length}"` : '""'}>
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 name="mdi-close-circle" onclick={handleRemoveAllFilters}></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 name="mdi-close-circle" onclick={handleRemoveAllFilters}></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
- <h1>{addFilterLabel}</h1>
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 class="form-container" style:background-color={mAndDown ? 'transparent' : 'rgb(var(--global-color-background-100))'} style:width={mAndDown ? '100%' : '50vw'} style:box-sizing="border-box">
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
- <h1>{addFilterLabel}</h1>
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-background-color="var(--filters-button-cancel-background-color, var(--filters-button-cancel-default-background-color))"
751
- --button-color="var(--filters-button-cancel-color, var(--filters-button-cancel-default-color))"
752
- --button-hover-background-color="rgb(var(--global-color-primary-500))"
753
- --button-hover-box-shadow="0 0 0.5rem rgba(0, 0, 0, 0.3)"
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-primary-400))"
782
+ --button-color="rgb(var(--global-color-contrast-900))"
761
783
  --button-background-color="transparent"
762
- --button-hover-background-color="rgb(var(--global-color-primary-500))"
763
- --button-hover-box-shadow="0 0 0.5rem rgba(0, 0, 0, 0.3)"
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="100px"
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: .6rem;
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: -40%;
822
- left: calc(100% - 10px);
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: 5px;
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: 20px;
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: 2px 8px 2px 8px;
877
- border-radius: 20px;
878
- margin-left: 5px;
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: .7rem;
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: 10px 20px 10px 20px;
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
- padding: 20px;
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: 0 0 8px 8px;
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
- let { filter = $bindable(undefined), lang = 'en', backIcon = "mdi-arrow-left", betweenFromLabel = lang === 'en' ? "From" : "Da", betweenToLabel = lang === 'en' ? "To" : "A", labelsMapper, forceApplyValid = false, tmpFilter = $bindable(undefined), onbackClick, onkeypress, onclick: onclickInternal, onclose, customSnippet, filterActionsSnippet, titleSnippet, } = $props();
12
- // function handleApplyFilterClick() {
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 : { ...filter };
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 '../../../css/main.css';
2
- import './SearchBar.css';
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
- placeholder={placeholder}
35
+ {placeholder}
38
36
  maxlength="512"
39
37
  tabindex="0"
40
38
  bind:this={input}
41
- bind:value={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 1px var(
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
- --search-bar-max-width,
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 'svelte/elements';
2
- import '../../../css/main.css';
3
- import './SearchBar.css';
4
- import type { Snippet } from 'svelte';
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: 0 0 0.5rem rgba(0, 0, 0, 0.3);
23
+ --button-default-box-shadow: none;
24
24
  --button-default-text-font-weight: 600;
25
25
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@likable-hair/svelte",
3
3
  "description": "A Svelte component for likablehair and others",
4
- "version": "4.0.18",
4
+ "version": "4.0.20",
5
5
  "scripts": {
6
6
  "host": "vite --host",
7
7
  "dev": "vite dev",