@likable-hair/svelte 4.2.5 → 4.3.0

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 (117) hide show
  1. package/dist/components/composed/buttons/ActivableButton.svelte +25 -7
  2. package/dist/components/composed/common/HeadersDrawer.svelte +66 -28
  3. package/dist/components/composed/common/HeadersDrawer.svelte.d.ts +22 -12
  4. package/dist/components/composed/common/MenuOrDrawer.svelte +40 -12
  5. package/dist/components/composed/common/MenuOrDrawerOptions.svelte +51 -27
  6. package/dist/components/composed/common/MenuOrDrawerOptions.svelte.d.ts +15 -10
  7. package/dist/components/composed/common/QuickActions.svelte +59 -23
  8. package/dist/components/composed/common/ToolTip.svelte +51 -32
  9. package/dist/components/composed/dashboard/DashboardShaper.svelte +280 -147
  10. package/dist/components/composed/dashboard/DashboardShaper.svelte.d.ts +54 -45
  11. package/dist/components/composed/forms/AsyncAutocomplete.svelte +81 -30
  12. package/dist/components/composed/forms/AsyncAutocomplete.svelte.d.ts +12 -5
  13. package/dist/components/composed/forms/AvatarDropdown.svelte +146 -70
  14. package/dist/components/composed/forms/AvatarDropdown.svelte.d.ts +27 -22
  15. package/dist/components/composed/forms/ConfirmOrCancelButtons.svelte +65 -19
  16. package/dist/components/composed/forms/CountriesAutocomplete.svelte +33 -4
  17. package/dist/components/composed/forms/DatePickerTextField.svelte +266 -161
  18. package/dist/components/composed/forms/Dropdown.svelte +88 -21
  19. package/dist/components/composed/forms/Dropdown.svelte.d.ts +18 -13
  20. package/dist/components/composed/forms/IconsDropdown.svelte +85 -40
  21. package/dist/components/composed/forms/IconsDropdown.svelte.d.ts +15 -8
  22. package/dist/components/composed/forms/LabelAndSelect.svelte +46 -5
  23. package/dist/components/composed/forms/LabelAndTextField.svelte +56 -3
  24. package/dist/components/composed/forms/PeriodPicker.svelte +38 -18
  25. package/dist/components/composed/forms/PeriodPicker.svelte.d.ts +32 -7
  26. package/dist/components/composed/forms/PeriodSelector.svelte +427 -312
  27. package/dist/components/composed/forms/PeriodSelector.svelte.d.ts +20 -13
  28. package/dist/components/composed/forms/ToggleList.svelte +71 -37
  29. package/dist/components/composed/forms/ToggleList.svelte.d.ts +14 -7
  30. package/dist/components/composed/forms/YearPickerTextField.svelte +154 -82
  31. package/dist/components/composed/list/DynamicTable.svelte +1372 -809
  32. package/dist/components/composed/list/DynamicTable.svelte.d.ts +85 -70
  33. package/dist/components/composed/list/EnhancedPaginatedTable.svelte +75 -32
  34. package/dist/components/composed/list/EnhancedPaginatedTable.svelte.d.ts +16 -6
  35. package/dist/components/composed/list/PaginatedTable.svelte +324 -116
  36. package/dist/components/composed/list/PaginatedTable.svelte.d.ts +26 -22
  37. package/dist/components/composed/progress/HorizontalStackedProgress.svelte +67 -29
  38. package/dist/components/composed/search/DynamicFilters.svelte +126 -91
  39. package/dist/components/composed/search/FilterEditor.svelte +169 -109
  40. package/dist/components/composed/search/Filters.svelte +385 -275
  41. package/dist/components/composed/search/GlobalSearchTextField.svelte +102 -42
  42. package/dist/components/composed/search/GlobalSearchTextField.svelte.d.ts +23 -20
  43. package/dist/components/composed/search/MobileFilterEditor.svelte +174 -120
  44. package/dist/components/composed/search/QuickFilters.svelte +124 -75
  45. package/dist/components/composed/search/SearchBar.svelte +42 -3
  46. package/dist/components/composed/search/SearchResults.svelte +48 -5
  47. package/dist/components/composed/search/SearchResults.svelte.d.ts +17 -17
  48. package/dist/components/layouts/CollapsibleSideBarLayout.svelte +100 -24
  49. package/dist/components/layouts/StableDividedSideBarLayout.svelte +74 -24
  50. package/dist/components/layouts/UnstableDividedSideBarLayout.svelte +140 -57
  51. package/dist/components/simple/buttons/Button.svelte +86 -36
  52. package/dist/components/simple/buttons/LinkButton.svelte +81 -25
  53. package/dist/components/simple/charts/BarChart.svelte +137 -105
  54. package/dist/components/simple/charts/LineChart.svelte +124 -92
  55. package/dist/components/simple/charts/PieChart.svelte +51 -23
  56. package/dist/components/simple/common/CollapsibleDivider.svelte +58 -26
  57. package/dist/components/simple/common/Divider.svelte +2 -1
  58. package/dist/components/simple/common/InfiniteScroll.svelte +60 -34
  59. package/dist/components/simple/common/MediaQuery.svelte +28 -3
  60. package/dist/components/simple/common/Menu.svelte +516 -371
  61. package/dist/components/simple/common/NoData.svelte +18 -4
  62. package/dist/components/simple/common/VerticalDraggableList.svelte +52 -26
  63. package/dist/components/simple/common/VerticalDraggableList.svelte.d.ts +20 -9
  64. package/dist/components/simple/dashboards/DashboardGridShaper.svelte +28 -22
  65. package/dist/components/simple/dates/Calendar.svelte +142 -72
  66. package/dist/components/simple/dates/DatePicker.svelte +138 -71
  67. package/dist/components/simple/dates/MonthSelector.svelte +49 -13
  68. package/dist/components/simple/dates/YearSelector.svelte +73 -30
  69. package/dist/components/simple/dialogs/Dialog.svelte +109 -59
  70. package/dist/components/simple/forms/Autocomplete.svelte +341 -164
  71. package/dist/components/simple/forms/Autocomplete.svelte.d.ts +27 -20
  72. package/dist/components/simple/forms/Checkbox.svelte +57 -29
  73. package/dist/components/simple/forms/FileInput.svelte +103 -58
  74. package/dist/components/simple/forms/FileInputList.svelte +115 -51
  75. package/dist/components/simple/forms/RadioButton.svelte +36 -3
  76. package/dist/components/simple/forms/Select.svelte +30 -3
  77. package/dist/components/simple/forms/SimpleTextField.svelte +94 -4
  78. package/dist/components/simple/forms/Switch.svelte +33 -11
  79. package/dist/components/simple/forms/Textarea.svelte +22 -5
  80. package/dist/components/simple/forms/VerticalSwitch.svelte +19 -2
  81. package/dist/components/simple/forms/VerticalTextSwitch.svelte +35 -3
  82. package/dist/components/simple/lists/BoxList.svelte +42 -11
  83. package/dist/components/simple/lists/ColorInvertedSelector.svelte +83 -25
  84. package/dist/components/simple/lists/HierarchyMenu.svelte +55 -20
  85. package/dist/components/simple/lists/Paginator.svelte +53 -34
  86. package/dist/components/simple/lists/SelectableMenuList.svelte +52 -16
  87. package/dist/components/simple/lists/SelectableVerticalList.svelte +169 -85
  88. package/dist/components/simple/lists/SelectableVerticalList.svelte.d.ts +21 -14
  89. package/dist/components/simple/lists/SidebarMenuList.svelte +127 -79
  90. package/dist/components/simple/lists/SimpleTable.svelte +442 -245
  91. package/dist/components/simple/lists/SimpleTable.svelte.d.ts +31 -22
  92. package/dist/components/simple/loaders/CircularLoader.css +1 -1
  93. package/dist/components/simple/loaders/CircularLoader.svelte +11 -3
  94. package/dist/components/simple/loaders/Skeleton.svelte +3 -2
  95. package/dist/components/simple/media/Avatar.svelte +35 -15
  96. package/dist/components/simple/media/DescriptiveAvatar.svelte +30 -4
  97. package/dist/components/simple/media/FlagIcon.svelte +13 -3
  98. package/dist/components/simple/media/Icon.svelte +21 -6
  99. package/dist/components/simple/navigation/Breadcrumb.svelte +41 -9
  100. package/dist/components/simple/navigation/Chip.svelte +65 -29
  101. package/dist/components/simple/navigation/Drawer.svelte +132 -71
  102. package/dist/components/simple/navigation/HeaderMenu.svelte +69 -25
  103. package/dist/components/simple/navigation/Navigator.svelte +45 -11
  104. package/dist/components/simple/navigation/TabSwitcher.svelte +60 -19
  105. package/dist/components/simple/notifiers/AlertBanner.svelte +59 -11
  106. package/dist/components/simple/progress/ProgressBar.svelte +26 -10
  107. package/dist/components/simple/timeline/SimpleTimeLine.svelte +52 -5
  108. package/dist/components/simple/timeline/SimpleTimeLine.svelte.d.ts +16 -9
  109. package/dist/components/simple/typography/Code.svelte +41 -12
  110. package/dist/stores/layouts/unstableSidebarOpened.d.ts +1 -1
  111. package/dist/stores/layouts/unstableSidebarOpened.js +1 -1
  112. package/dist/stores/theme.js +2 -2
  113. package/dist/utils/filters/builder.d.ts +2 -2
  114. package/dist/utils/filters/builder.js +7 -7
  115. package/dist/utils/filters/modifiers/where.d.ts +1 -1
  116. package/dist/utils/teleporter.js +4 -4
  117. package/package.json +39 -33
@@ -1,43 +1,81 @@
1
- <script lang="ts" module>export function isProgressItem(obj) {
2
- return ((obj.label === undefined || typeof obj.label === 'string') &&
3
- (obj.color === undefined || typeof obj.color === 'string') &&
4
- typeof obj.value === 'number');
5
- }
1
+ <script lang="ts" module>
2
+ export type ProgressItem = {
3
+ label?: string,
4
+ color?: string,
5
+ value: number,
6
+ valueLabel?: string | number
7
+ };
8
+
9
+ export function isProgressItem(obj: any): obj is ProgressItem {
10
+ return (
11
+ (obj.label === undefined || typeof obj.label === 'string') &&
12
+ (obj.color === undefined || typeof obj.color === 'string') &&
13
+ typeof obj.value === 'number'
14
+ );
15
+ }
6
16
  </script>
7
17
 
8
- <script lang="ts">import './HorizontalStackedProgress.css';
9
- import ProgressBar from "../../simple/progress/ProgressBar.svelte";
10
- let { progresses = [], labelVisible = true, labelValueVisible = true, labelTextVisible = true, legendVisible = false, legendValueVisible = true, legendTextVisible = true, hideLabelUnderPercentage, tooltipVisible = true, } = $props();
11
- let colors = [
18
+ <script lang="ts">
19
+ import './HorizontalStackedProgress.css'
20
+ import ProgressBar from "../../simple/progress/ProgressBar.svelte";
21
+
22
+ interface Props {
23
+ progresses?: (number | ProgressItem)[];
24
+ labelVisible?: boolean;
25
+ labelValueVisible?: boolean;
26
+ labelTextVisible?: boolean;
27
+ legendVisible?: boolean;
28
+ legendValueVisible?: boolean;
29
+ legendTextVisible?: boolean;
30
+ hideLabelUnderPercentage?: number;
31
+ tooltipVisible?: boolean
32
+ }
33
+
34
+ let {
35
+ progresses = [],
36
+ labelVisible = true,
37
+ labelValueVisible = true,
38
+ labelTextVisible = true,
39
+ legendVisible = false,
40
+ legendValueVisible = true,
41
+ legendTextVisible = true,
42
+ hideLabelUnderPercentage,
43
+ tooltipVisible = true,
44
+ }: Props = $props();
45
+
46
+ let colors = [
12
47
  'rgb(var(--global-color-primary-500))',
13
48
  'rgb(var(--global-color-primary-300))',
14
49
  'rgb(var(--global-color-primary-700))',
15
50
  'rgb(var(--global-color-primary-500), .5)',
16
51
  'rgb(var(--global-color-primary-600), .5)',
17
52
  'rgb(var(--global-color-primary-700), .5)'
18
- ];
19
- let total = $derived(progresses.reduce((p, c, i, a) => {
20
- if (isProgressItem(c)) {
21
- return p + c.value;
22
- }
23
- else {
24
- return p + c;
53
+ ]
54
+
55
+ let total = $derived(progresses.reduce<number>((p, c, i, a) => {
56
+ if(isProgressItem(c)) {
57
+ return p + c.value
58
+ } else {
59
+ return p + c
25
60
  }
26
- }, 0));
27
- let progressesItems = $derived(progresses.map((p, i) => {
28
- let item;
29
- let value = isProgressItem(p) ? p.value : p;
61
+ }, 0))
62
+
63
+ let progressesItems = $derived(progresses.map((p, i) => {
64
+ let item: ProgressItem & { percentage: number }
65
+ let value = isProgressItem(p) ? p.value : p
30
66
  // x : 100 = value : total
31
- let percentage = Number(((100 * value) / total).toFixed(2));
32
- let color = isProgressItem(p) ? p.color : colors[i % colors.length];
67
+ let percentage = Number(((100 * value) / total).toFixed(2))
68
+ let color = isProgressItem(p) ? p.color : colors[i % colors.length]
69
+
33
70
  item = {
34
- ...(isProgressItem(p) ? p : {}),
35
- color,
36
- value,
37
- percentage
38
- };
39
- return item;
40
- }).filter(p => p.value !== 0));
71
+ ...(isProgressItem(p) ? p : {}),
72
+ color,
73
+ value,
74
+ percentage
75
+ }
76
+
77
+ return item
78
+ }).filter(p => p.value !== 0))
41
79
  </script>
42
80
 
43
81
  <div class="horizontal-stacked-progress">
@@ -1,98 +1,133 @@
1
- <script lang="ts">import { FilterEditor, Icon } from "../../..";
2
- import MediaQuery from "../../simple/common/MediaQuery.svelte";
3
- import {} from "svelte";
4
- let { filters = [], lang = "en", mAndDown = false, labelsMapper = lang == 'en' ? {
5
- equal: { extended: "equal to", short: "equal" },
6
- like: { short: "includes" },
7
- ilike: { short: "includes" },
8
- contains: { short: "contains" },
9
- greater: { short: "greater", extended: "greater than" },
10
- lower: { short: "lower", extended: "lower than" },
11
- between: { short: "between", extended: "is between" },
12
- different: { short: "different", extended: "different from" },
13
- } : {
14
- equal: { extended: "uguale a", short: "uguale" },
15
- like: { short: "include" },
16
- ilike: { short: "include" },
17
- contains: { short: "contiene" },
18
- greater: { short: "maggiore", extended: "maggiore di" },
19
- lower: { short: "minore", extended: "minore di" },
20
- between: { short: "compreso", extended: "è compreso tra" },
21
- different: { short: "diverso", extended: "diverso da" },
22
- }, onchange, updateMultiFilterValues, customSnippet: customSnippetInternal, } = $props();
23
- let selectedFilter = $state();
24
- let tmpFilters = $state(filters.reduce((acc, f) => {
1
+ <script lang="ts">
2
+ import { FilterEditor, Icon } from "../../..";
3
+ import MediaQuery from "../../simple/common/MediaQuery.svelte";
4
+ import type { DateMode, Filter, NumberMode, SelectMode, StringMode } from "../../../utils/filters/filters";
5
+ import { type Snippet } from "svelte"
6
+
7
+ interface Props {
8
+ filters?: Filter[];
9
+ lang?: "it" | "en";
10
+ mAndDown?: boolean;
11
+ labelsMapper?: LabelMapper,
12
+ onchange?: (event: {
13
+ detail: {
14
+ filter: Filter
15
+ }
16
+ }) => void
17
+ customSnippet?: Snippet<[{
18
+ filter: Filter | undefined,
19
+ mAndDown: boolean,
20
+ updateCustomFilterValues: typeof updateCustomFilterValues
21
+ }]>
22
+ updateMultiFilterValues?: (filterName: string, newValue: any, newValid: boolean, mode?: NumberMode | StringMode | SelectMode | DateMode) => void
23
+ }
24
+
25
+ let {
26
+ filters = [],
27
+ lang = "en",
28
+ mAndDown = false,
29
+ labelsMapper = lang == 'en' ? {
30
+ equal: { extended: "equal to", short: "equal" },
31
+ like: { short: "includes" },
32
+ ilike: { short: "includes" },
33
+ contains: { short: "contains" },
34
+ greater: { short: "greater", extended: "greater than" },
35
+ lower: { short: "lower", extended: "lower than" },
36
+ between: { short: "between", extended: "is between" },
37
+ different: { short: "different", extended: "different from" },
38
+ } : {
39
+ equal: { extended: "uguale a", short: "uguale" },
40
+ like: { short: "include" },
41
+ ilike: { short: "include" },
42
+ contains: { short: "contiene" },
43
+ greater: { short: "maggiore", extended: "maggiore di" },
44
+ lower: { short: "minore", extended: "minore di" },
45
+ between: { short: "compreso", extended: "è compreso tra" },
46
+ different: { short: "diverso", extended: "diverso da" },
47
+ },
48
+ onchange,
49
+ updateMultiFilterValues,
50
+ customSnippet: customSnippetInternal,
51
+ }: Props = $props();
52
+
53
+ let selectedFilter: Filter | undefined = $state();
54
+ let tmpFilters: { [filterName: string]: Filter } = $state(filters.reduce((acc, f) => {
25
55
  if (f.active) {
26
- acc[f.name] = f;
56
+ acc[f.name] = f;
27
57
  }
28
58
  return acc;
29
- }, {}));
30
- function selectFilter(filter) {
31
- selectedFilter = filter === selectedFilter ? undefined : filter;
32
- }
33
- function handleKeyPress(event, filter) {
34
- if (event.key === "Enter" || event.key === " ") {
35
- selectFilter(filter);
36
- }
37
- }
38
- function handleFilterChange() {
39
- if (!!selectedFilter) {
40
- if (!!onchange) {
41
- onchange({
42
- detail: {
43
- filter: tmpFilters[selectedFilter.name]
44
- }
45
- });
46
- }
47
- filters = filters.map(f => {
48
- if (f.name === selectedFilter?.name) {
49
- return tmpFilters[selectedFilter.name];
50
- }
51
- return f;
52
- });
53
- }
54
- }
55
- function isActiveFilter(filter) {
56
- let newValue = {}, newValid = false;
57
- if (filter.type == 'select') {
58
- newValue = filter.values;
59
- if (!!newValue && newValue.length > 0) {
60
- newValid = true;
61
- }
62
- }
63
- else if ('mode' in filter && filter.mode == 'between') {
64
- newValue.to = filter.to;
65
- newValue.from = filter.from;
66
- if (newValue.from != undefined || newValue.to != undefined) {
67
- newValid = true;
68
- }
69
- }
70
- else if (filter.type == 'custom') {
71
- newValue = filter.value;
72
- if ((Array.isArray(newValue) && newValue.length > 0) || (!Array.isArray(newValue) && newValue != undefined)) {
73
- newValid = true;
74
- }
75
- }
76
- else {
77
- newValue = filter.value;
78
- if (newValue != undefined) {
79
- newValid = true;
80
- }
81
- }
82
- return newValid;
83
- }
84
- function updateCustomFilterValues(filterName, newValue, newValid, mode) {
85
- let filter = filters.find(f => f.name === filterName);
86
- if (!filter)
87
- throw new Error('cannot find filter with name ' + filterName);
88
- if (filter.type != 'custom')
89
- throw new Error('filter is not custom');
90
- filter.value = newValue;
91
- filter.active = newValid;
92
- if (updateMultiFilterValues) {
93
- updateMultiFilterValues(filterName, newValue, newValid, mode);
59
+ }, {} as { [filterName: string]: Filter }))
60
+
61
+ type LabelMapper = {
62
+ [label: string]: { extended?: string; short: string };
63
+ };
64
+
65
+ function selectFilter(filter: Filter) {
66
+ selectedFilter = filter === selectedFilter ? undefined : filter;
67
+ }
68
+
69
+ function handleKeyPress(event: any, filter: Filter) {
70
+ if (event.key === "Enter" || event.key === " ") {
71
+ selectFilter(filter);
72
+ }
73
+ }
74
+
75
+ function handleFilterChange() {
76
+ if(!!selectedFilter){
77
+ if(!!onchange){
78
+ onchange({
79
+ detail: {
80
+ filter: tmpFilters[selectedFilter.name]
81
+ }
82
+ })
83
+ }
84
+ filters = filters.map(f => {
85
+ if (f.name === selectedFilter?.name) {
86
+ return tmpFilters[selectedFilter.name]
87
+ }
88
+ return f
89
+ })
90
+ }
91
+ }
92
+
93
+ function isActiveFilter(filter: Filter) {
94
+ let newValue: any = {},
95
+ newValid: boolean = false
96
+ if(filter.type == 'select') {
97
+ newValue = filter.values
98
+ if(!!newValue && newValue.length > 0) {
99
+ newValid = true
100
+ }
101
+ } else if('mode' in filter && filter.mode == 'between') {
102
+ newValue.to = filter.to
103
+ newValue.from = filter.from
104
+ if(newValue.from != undefined || newValue.to != undefined) {
105
+ newValid = true
106
+ }
107
+ } else if (filter.type == 'custom') {
108
+ newValue = filter.value
109
+ if ((Array.isArray(newValue) && newValue.length > 0) || (!Array.isArray(newValue) && newValue != undefined)) {
110
+ newValid = true;
111
+ }
112
+ } else {
113
+ newValue = filter.value
114
+ if(newValue != undefined) {
115
+ newValid = true
116
+ }
94
117
  }
95
- }
118
+ return newValid
119
+ }
120
+
121
+ function updateCustomFilterValues(filterName: string, newValue: any, newValid: boolean, mode?: NumberMode | StringMode | SelectMode | DateMode) {
122
+ let filter = filters.find(f => f.name === filterName)
123
+ if(!filter) throw new Error('cannot find filter with name ' + filterName)
124
+ if(filter.type != 'custom') throw new Error('filter is not custom')
125
+ filter.value = newValue
126
+ filter.active = newValid
127
+ if(updateMultiFilterValues){
128
+ updateMultiFilterValues(filterName, newValue, newValid, mode)
129
+ }
130
+ }
96
131
  </script>
97
132
 
98
133
  <MediaQuery>
@@ -1,119 +1,179 @@
1
- <script lang="ts">import Dropdown from "../forms/Dropdown.svelte";
2
- import { GENERIC_MODES, SELECT_MODES, STRING_MODES } from '../../../utils/filters/filters';
3
- import SimpleTextField from "../../simple/forms/SimpleTextField.svelte";
4
- import DatePickerTextField from "../forms/DatePickerTextField.svelte";
5
- import Validator from "../../../utils/filters/validator";
6
- import Autocomplete, {} from "../../simple/forms/Autocomplete.svelte";
7
- import Checkbox from "../../simple/forms/Checkbox.svelte";
8
- import Icon from "../../simple/media/Icon.svelte";
9
- import ToggleList from "../forms/ToggleList.svelte";
10
- import { tick } from "svelte";
11
- let { filter = $bindable(), lang = 'en', betweenFromLabel = lang === 'en' ? "From" : "Da", betweenToLabel = lang === 'en' ? "To" : "A", labelsMapper, forceApplyValid = false, editFilterMode = 'one-edit', tmpFilter = $bindable(), mobile = false, onchange, onclick: onclickInternal, onkeypress, customSnippet, filterActionsSnippet, } = $props();
12
- let advancedModeOptions = $state(), advancedModeSelectedOptions = $state([]);
13
- function closeDropDown() {
14
- dropdownOpened = false;
15
- }
16
- $effect(() => {
17
- if (!!filter && !tmpFilter) {
18
- tick().then(() => {
19
- tmpFilter = filter === undefined ? undefined : { ...filter };
20
- closeDropDown();
21
- });
1
+ <script lang="ts">
2
+ import type { Filter, NumberMode, SelectMode, StringMode } from "../../../utils/filters/filters";
3
+ import Dropdown from "../forms/Dropdown.svelte";
4
+ import { GENERIC_MODES, SELECT_MODES, STRING_MODES } from '../../../utils/filters/filters';
5
+ import type { DateMode } from "../../../utils/filters/filters";
6
+ import SimpleTextField from "../../simple/forms/SimpleTextField.svelte";
7
+ import DatePickerTextField from "../forms/DatePickerTextField.svelte";
8
+ import Validator from "../../../utils/filters/validator";
9
+ import Autocomplete, { type Item } from "../../simple/forms/Autocomplete.svelte";
10
+ import Checkbox from "../../simple/forms/Checkbox.svelte";
11
+ import type { LabelMapper } from "./Filters.svelte";
12
+ import Icon from "../../simple/media/Icon.svelte";
13
+ import ToggleList from "../forms/ToggleList.svelte";
14
+ import type { KeyboardEventHandler, MouseEventHandler } from "svelte/elements";
15
+ import { tick, type Snippet } from "svelte";
16
+
17
+ interface Props {
18
+ filter?: Filter;
19
+ lang?: 'en' | 'it';
20
+ betweenFromLabel?: string;
21
+ betweenToLabel?: string;
22
+ labelsMapper: LabelMapper;
23
+ forceApplyValid?: boolean;
24
+ editFilterMode?: 'one-edit' | 'multi-edit';
25
+ tmpFilter?: Filter;
26
+ mobile?: boolean;
27
+ onchange?: (event:{
28
+ detail: {
29
+ filter: Filter | undefined,
30
+ tmpFilter: Filter | undefined
31
+ }
32
+ }) => void
33
+ onclick?: MouseEventHandler<HTMLDivElement>
34
+ onkeypress?: KeyboardEventHandler<HTMLDivElement>
35
+ customSnippet?: Snippet<[{
36
+ filter: typeof tmpFilter
37
+ }]>
38
+ filterActionsSnippet?: Snippet<[{
39
+ applyFilterDisabled: typeof applyFilterDisabled,
40
+ filter: typeof tmpFilter
41
+ }]>
42
+ }
43
+
44
+ let {
45
+ filter = $bindable(),
46
+ lang = 'en',
47
+ betweenFromLabel = lang === 'en' ? "From" : "Da",
48
+ betweenToLabel = lang === 'en' ? "To" : "A",
49
+ labelsMapper,
50
+ forceApplyValid = false,
51
+ editFilterMode = 'one-edit',
52
+ tmpFilter = $bindable(),
53
+ mobile = false,
54
+ onchange,
55
+ onclick: onclickInternal,
56
+ onkeypress,
57
+ customSnippet,
58
+ filterActionsSnippet,
59
+ }: Props = $props();
60
+
61
+ let advancedModeOptions: Item[] | undefined = $state(),
62
+ advancedModeSelectedOptions: Item[] = $state([])
63
+
64
+ function closeDropDown() {
65
+ dropdownOpened = false
66
+ }
67
+
68
+ $effect(() => {
69
+ if(!!filter && !tmpFilter) {
70
+ tick().then(() => {
71
+ tmpFilter = filter === undefined ? undefined : {...filter}
72
+ closeDropDown();
73
+ });
22
74
  }
23
- if (!!tmpFilter && ['string', 'number', 'date', 'select'].includes(tmpFilter.type) && Object.keys(tmpFilter).includes('mode')) {
24
- //@ts-ignore
25
- if ((tmpFilter.mode == 'between' && tmpFilter.from !== undefined && tmpFilter.to !== undefined) || tmpFilter.value !== undefined || (tmpFilter.type == 'select' && tmpFilter.values !== undefined && tmpFilter.values.length > 0)) {
26
- advancedModeSelectedOptions = [{
27
- //@ts-ignore
28
- value: tmpFilter.mode, label: labelsMapper[tmpFilter.mode].short || tmpFilter.mode
29
- }];
30
- }
75
+
76
+ if(!!tmpFilter && ['string', 'number', 'date', 'select'].includes(tmpFilter.type) && Object.keys(tmpFilter).includes('mode')) {
77
+ //@ts-ignore
78
+ if((tmpFilter.mode == 'between' && tmpFilter.from !== undefined && tmpFilter.to !== undefined) || tmpFilter.value !== undefined || (tmpFilter.type == 'select' && tmpFilter.values !== undefined && tmpFilter.values.length > 0)) {
79
+ advancedModeSelectedOptions = [{
80
+ //@ts-ignore
81
+ value: tmpFilter.mode, label: labelsMapper[tmpFilter.mode].short || tmpFilter.mode
82
+ }]
83
+ }
31
84
  }
32
- });
33
- $effect(() => {
34
- if (!!tmpFilter) {
35
- let modes;
36
- if (tmpFilter.type == 'string') {
37
- modes = STRING_MODES;
38
- }
39
- else if (tmpFilter.type == 'date') {
40
- modes = GENERIC_MODES;
41
- }
42
- else if (tmpFilter.type == 'number') {
43
- modes = GENERIC_MODES;
44
- }
45
- else if (tmpFilter.type == 'select') {
46
- modes = SELECT_MODES;
47
- }
48
- else if (tmpFilter.type == 'bool') {
49
- modes = undefined;
50
- }
51
- if (!!modes) {
52
- advancedModeOptions = modes.map(mode => {
53
- return {
54
- value: mode,
55
- label: labelsMapper[mode].short || mode
56
- };
57
- });
58
- }
85
+ })
86
+
87
+ $effect(() => {
88
+ if(!!tmpFilter) {
89
+ let modes
90
+ if(tmpFilter.type == 'string') {
91
+ modes = STRING_MODES
92
+ } else if(tmpFilter.type == 'date') {
93
+ modes = GENERIC_MODES
94
+ } else if(tmpFilter.type == 'number') {
95
+ modes = GENERIC_MODES
96
+ } else if(tmpFilter.type == 'select') {
97
+ modes = SELECT_MODES
98
+ } else if(tmpFilter.type == 'bool') {
99
+ modes = undefined
100
+ }
101
+
102
+ if(!!modes) {
103
+ advancedModeOptions = modes.map(mode => {
104
+ return {
105
+ value: mode,
106
+ label: labelsMapper[mode].short || mode
107
+ }
108
+ })
109
+ }
59
110
  }
60
- });
61
- $effect(() => {
62
- if (!tmpFilter?.advanced) {
63
- advancedModeSelectedOptions = [];
111
+ })
112
+
113
+ $effect(() => {
114
+ if(!tmpFilter?.advanced) {
115
+ advancedModeSelectedOptions = []
64
116
  }
65
- });
66
- let dropdownOpened = $state(false), calendarOpened = $state(false), calendarOpened2 = $state(false);
67
- // TODO I don't like that there is a singlo dropdow to handle all filter advance mode.
68
- // In some case would be necessary to handle more than one selection and this code
69
- // could become non sense
70
- function handleAdvancedModeSelection() {
71
- if (advancedModeSelectedOptions.length > 0 && !!tmpFilter) {
72
- if (tmpFilter.type == 'date')
73
- tmpFilter.mode = advancedModeSelectedOptions[0].value;
74
- else if (tmpFilter.type == 'number')
75
- tmpFilter.mode = advancedModeSelectedOptions[0].value;
76
- else if (tmpFilter.type == 'string')
77
- tmpFilter.mode = advancedModeSelectedOptions[0].value;
78
- else if (tmpFilter.type == 'select')
79
- tmpFilter.mode = advancedModeSelectedOptions[0].value;
117
+ })
118
+
119
+ let dropdownOpened: boolean = $state(false),
120
+ calendarOpened: boolean = $state(false),
121
+ calendarOpened2: boolean = $state(false)
122
+
123
+ // TODO I don't like that there is a singlo dropdow to handle all filter advance mode.
124
+ // In some case would be necessary to handle more than one selection and this code
125
+ // could become non sense
126
+ function handleAdvancedModeSelection() {
127
+ if(advancedModeSelectedOptions.length > 0 && !!tmpFilter) {
128
+ if(tmpFilter.type == 'date') tmpFilter.mode = advancedModeSelectedOptions[0].value as DateMode
129
+ else if(tmpFilter.type == 'number') tmpFilter.mode = advancedModeSelectedOptions[0].value as NumberMode
130
+ else if(tmpFilter.type == 'string') tmpFilter.mode = advancedModeSelectedOptions[0].value as StringMode
131
+ else if(tmpFilter.type == 'select') tmpFilter.mode = advancedModeSelectedOptions[0].value as SelectMode
80
132
  }
133
+
81
134
  dropdownOpened = false;
82
- handleChangeValue();
83
- }
84
- let applyFilterDisabled = $derived(!Validator.isValid(tmpFilter) && !forceApplyValid);
85
- $effect.pre(() => {
86
- if (!!tmpFilter && tmpFilter.type == 'bool') {
87
- if (tmpFilter.value === undefined) {
88
- tmpFilter.value = false;
89
- }
135
+ handleChangeValue()
136
+ }
137
+
138
+ let applyFilterDisabled = $derived(!Validator.isValid(tmpFilter) && !forceApplyValid)
139
+
140
+ $effect.pre(() => {
141
+ if(!!tmpFilter && tmpFilter.type == 'bool') {
142
+ if(tmpFilter.value === undefined) {
143
+ tmpFilter.value = false
144
+ }
90
145
  }
91
- });
92
- $effect.pre(() => {
93
- if (!!tmpFilter && tmpFilter.type == 'select') {
94
- if (tmpFilter.values === undefined) {
95
- tmpFilter.values = [];
96
- }
146
+ })
147
+
148
+ $effect.pre(() => {
149
+ if(!!tmpFilter && tmpFilter.type == 'select') {
150
+ if(tmpFilter.values === undefined) {
151
+ tmpFilter.values = []
152
+ }
97
153
  }
98
- });
99
- function handleChangeValue(isCalendarOpened = false) {
100
- calendarOpened = isCalendarOpened;
101
- calendarOpened2 = isCalendarOpened;
102
- if (onchange) {
103
- onchange({
104
- detail: {
105
- filter,
106
- tmpFilter
107
- }
108
- });
154
+ })
155
+
156
+ function handleChangeValue(isCalendarOpened = false) {
157
+ calendarOpened = isCalendarOpened
158
+ calendarOpened2 = isCalendarOpened
159
+ if(onchange) {
160
+ onchange({
161
+ detail: {
162
+ filter,
163
+ tmpFilter
164
+ }
165
+ })
109
166
  }
110
- }
111
- function onclick(event) {
112
- event.stopPropagation();
113
- if (onclickInternal) {
114
- onclickInternal(event);
167
+ }
168
+
169
+ function onclick(event: MouseEvent & {
170
+ currentTarget: EventTarget & HTMLDivElement;
171
+ }) {
172
+ event.stopPropagation()
173
+ if(onclickInternal) {
174
+ onclickInternal(event)
115
175
  }
116
- }
176
+ }
117
177
  </script>
118
178
 
119
179
 
@@ -133,8 +193,8 @@ function onclick(event) {
133
193
  openingId="advanced-filter"
134
194
  mobileDrawer={mobile}
135
195
  {lang}
136
- minWidth={'100px'}
137
- height={'100%'}
196
+ minWidth="100px"
197
+ height="100%"
138
198
  --button-padding="10px 12px"
139
199
  --button-border='var(--dropdown-button-border)'
140
200
  --button-background-color='var(--dropdown-button-background-color)'
@@ -215,7 +275,7 @@ function onclick(event) {
215
275
  mobileDrawer={mobile}
216
276
  onchange={() => handleChangeValue()}
217
277
  placeholder={editFilterMode == 'one-edit' ? tmpFilter?.label : undefined}
218
- minWidth={''}
278
+ minWidth=""
219
279
  ></Autocomplete>
220
280
  </div>
221
281
  {:else if tmpFilter.type === "select" && (tmpFilter.view === 'toggle')}