@likable-hair/svelte 3.0.58 → 3.0.59

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.
@@ -14,7 +14,7 @@ export let headers = [], items = [], sortedBy = void 0, sortDirection = void 0,
14
14
  { label: "20", value: 20 },
15
15
  { label: "50", value: 50 },
16
16
  { label: "100", value: 100 }
17
- ], hideRowsPerPage = false, totalElements = void 0, rowsPerPage = 20, filters = [], searchBarColumns = void 0, searchBarVisible = true, lang = "en";
17
+ ], hideRowsPerPage = false, totalElements = void 0, rowsPerPage = 20, filters = [], searchBarColumns = void 0, searchBarVisible = true, searchBarPlaceholder = "Type something to search...", customFiltersValid = {}, customFiltersValues = void 0, lang = "en";
18
18
  let searchBarInput, searchText = void 0;
19
19
  let dispatch = createEventDispatcher();
20
20
  let rowsPerPageSelection = [];
@@ -39,7 +39,8 @@ function handleSearchChange(searchText2) {
39
39
  let converter = new Converter();
40
40
  let builder;
41
41
  builder = converter.createBuilder({
42
- filters: filters || []
42
+ filters: filters || [],
43
+ customFiltersValues
43
44
  });
44
45
  if (!!searchText2 && !!searchBarColumns && searchBarColumns.length > 0) {
45
46
  builder.where((b) => {
@@ -64,7 +65,7 @@ function handleFiltersChange() {
64
65
  {#if searchBarVisible}
65
66
  <slot name="search-bar" {handleSearchChange}>
66
67
  <SearchBar
67
- placeholder="Type something to search..."
68
+ placeholder={searchBarPlaceholder}
68
69
  bind:input={searchBarInput}
69
70
  bind:value={searchText}
70
71
  >
@@ -78,10 +79,17 @@ function handleFiltersChange() {
78
79
  on:removeFilter={handleFiltersChange}
79
80
  --filters-default-wrapper-width="100%"
80
81
  {lang}
81
- >
82
+ {customFiltersValid}
83
+ >
82
84
  <svelte:fragment slot="append">
83
85
  <slot name="filter-append"></slot>
84
86
  </svelte:fragment>
87
+ <svelte:fragment slot="custom" let:filter>
88
+ <slot name="custom-filter" {filter}></slot>
89
+ </svelte:fragment>
90
+ <svelte:fragment slot="custom-mobile" let:filter>
91
+ <slot name="custom-filter-mobile" {filter}></slot>
92
+ </svelte:fragment>
85
93
  </Filters>
86
94
  </div>
87
95
  <SimpleTable
@@ -24,6 +24,13 @@ declare const __propDef: {
24
24
  filters?: ComponentProps<Filters>['filters'];
25
25
  searchBarColumns?: string[] | undefined;
26
26
  searchBarVisible?: boolean | undefined;
27
+ searchBarPlaceholder?: string | undefined;
28
+ customFiltersValid?: {
29
+ [filterName: string]: boolean;
30
+ } | undefined;
31
+ customFiltersValues?: {
32
+ [filterName: string]: any;
33
+ } | undefined;
27
34
  lang?: "it" | "en" | undefined;
28
35
  };
29
36
  events: {
@@ -44,6 +51,12 @@ declare const __propDef: {
44
51
  handleSearchChange: (searchText: string | undefined) => void;
45
52
  };
46
53
  'filter-append': {};
54
+ 'custom-filter': {
55
+ filter: import("../../../utils/filters/filters").Filter | undefined;
56
+ };
57
+ 'custom-filter-mobile': {
58
+ filter: import("../../../utils/filters/filters").Filter | undefined;
59
+ };
47
60
  header: {
48
61
  head: import("../../simple/lists/SimpleTable.svelte").Header;
49
62
  };
@@ -7,11 +7,11 @@ import { createEventDispatcher } from "svelte";
7
7
  import Validator from "../../../utils/filters/validator";
8
8
  import Autocomplete from "../../simple/forms/Autocomplete.svelte";
9
9
  import Checkbox from "../../simple/forms/Checkbox.svelte";
10
- export let filter = void 0, lang = "en", cancelFilterLabel = lang == "en" ? "Cancel" : "Annulla", applyFilterLabel = lang == "en" ? "Apply filter" : "Applica filter", betweenFromLabel = lang == "en" ? "From" : "Da", betweenToLabel = lang == "en" ? "To" : "A", labelsMapper;
10
+ export let filter = void 0, lang = "en", cancelFilterLabel = lang == "en" ? "Cancel" : "Annulla", applyFilterLabel = lang == "en" ? "Apply filter" : "Applica filter", betweenFromLabel = lang == "en" ? "From" : "Da", betweenToLabel = lang == "en" ? "To" : "A", labelsMapper, forceApplyValid = false;
11
11
  let tmpFilter;
12
12
  let advancedModeOptions, advancedModeSelectedOptions;
13
13
  function initTmpFilter() {
14
- tmpFilter = structuredClone(filter);
14
+ tmpFilter = filter === void 0 ? void 0 : { ...filter };
15
15
  if (!!tmpFilter && ["string", "number", "date", "select"].includes(tmpFilter.type) && Object.keys(tmpFilter).includes("mode")) {
16
16
  if (tmpFilter.mode == "between" && tmpFilter.from !== void 0 && tmpFilter.to !== void 0 || tmpFilter.value !== void 0 || tmpFilter.type == "select" && tmpFilter.values !== void 0 && tmpFilter.values.length > 0) {
17
17
  advancedModeSelectedOptions = [{
@@ -36,7 +36,7 @@ function handleCancelFilterClick(e) {
36
36
  }
37
37
  function handleApplyFilterClick() {
38
38
  if (!!filter && !!tmpFilter) {
39
- filter = structuredClone(tmpFilter);
39
+ filter = { ...tmpFilter };
40
40
  filter.active = true;
41
41
  dispatch("apply");
42
42
  }
@@ -83,7 +83,7 @@ function handleAdvancedModeSelection() {
83
83
  dropdownOpened = false;
84
84
  }
85
85
  $:
86
- applyFilterDisabled = !Validator.isValid(tmpFilter);
86
+ applyFilterDisabled = !Validator.isValid(tmpFilter) && !forceApplyValid;
87
87
  $:
88
88
  if (!!tmpFilter && tmpFilter.type == "bool") {
89
89
  if (tmpFilter.value === void 0) {
@@ -200,6 +200,8 @@ $:
200
200
  {tmpFilter.description}
201
201
  </span>
202
202
  </div>
203
+ {:else if tmpFilter.type == 'custom'}
204
+ <slot name="custom" filter={tmpFilter}></slot>
203
205
  {/if}
204
206
  {/if}
205
207
  </div>
@@ -10,6 +10,7 @@ declare const __propDef: {
10
10
  betweenFromLabel?: string | undefined;
11
11
  betweenToLabel?: string | undefined;
12
12
  labelsMapper: LabelMapper;
13
+ forceApplyValid?: boolean | undefined;
13
14
  };
14
15
  events: {
15
16
  click: MouseEvent;
@@ -19,7 +20,11 @@ declare const __propDef: {
19
20
  } & {
20
21
  [evt: string]: CustomEvent<any>;
21
22
  };
22
- slots: {};
23
+ slots: {
24
+ custom: {
25
+ filter: Filter | undefined;
26
+ };
27
+ };
23
28
  };
24
29
  export type FilterEditorProps = typeof __propDef.props;
25
30
  export type FilterEditorEvents = typeof __propDef.events;
@@ -13,7 +13,7 @@ import Chip from "../../simple/navigation/Chip.svelte";
13
13
  import FilterEditor from "./FilterEditor.svelte";
14
14
  import MobileFilterEditor from "./MobileFilterEditor.svelte";
15
15
  import { fly } from "svelte/transition";
16
- export let filters = [], 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 = "en", betweenSeparator = lang == "en" ? "and" : "e", trueString = lang == "en" ? "true" : "vero", falseString = lang == "en" ? "false" : "falso", labelsMapper = lang == "en" ? {
16
+ export let filters = [], 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 = "en", betweenSeparator = lang == "en" ? "and" : "e", trueString = lang == "en" ? "true" : "vero", falseString = lang == "en" ? "false" : "falso", customFiltersValid = {}, labelsMapper = lang == "en" ? {
17
17
  "equal": {
18
18
  extended: "equal to",
19
19
  short: "equal"
@@ -24,6 +24,9 @@ export let filters = [], lang = "en", addFilterLabel = lang == "en" ? "Filters"
24
24
  "ilike": {
25
25
  short: "includes"
26
26
  },
27
+ "contains": {
28
+ short: "contains"
29
+ },
27
30
  "greater": {
28
31
  short: "greater",
29
32
  extended: "greater than"
@@ -51,6 +54,9 @@ export let filters = [], lang = "en", addFilterLabel = lang == "en" ? "Filters"
51
54
  "ilike": {
52
55
  short: "include"
53
56
  },
57
+ "contains": {
58
+ short: "contiene"
59
+ },
54
60
  "greater": {
55
61
  short: "maggiore",
56
62
  extended: "maggiore di"
@@ -288,10 +294,10 @@ function handleDeleteIconClick(e) {
288
294
  >
289
295
  <div class="drawer-content">
290
296
  {#if !!selectedFilter && singleFilterMenuOpened}
291
- <div
292
- class="drawer-filter-detail"
293
- style:height="100%"
294
- in:fly|local={{delay: 100, duration: 100, x: 200}}
297
+ <div
298
+ class="drawer-filter-detail"
299
+ style:height="100%"
300
+ in:fly|local={{delay: 100, duration: 100, x: 200}}
295
301
  out:fly|local={{duration: 100, x: -200}}
296
302
  >
297
303
  <MobileFilterEditor
@@ -303,20 +309,26 @@ function handleDeleteIconClick(e) {
303
309
  on:cancelClick={() => {mobileOpen = false; closeFilterMenu(200)}}
304
310
  {lang}
305
311
  {labelsMapper}
312
+ forceApplyValid={!!customFiltersValid[selectedFilter.name]}
306
313
  >
307
314
  <div slot="title">
308
315
  <div class="mobile-title">
309
316
  {selectedFilter?.label}
310
317
  </div>
311
318
  </div>
319
+
320
+ <svelte:fragment slot="custom" let:filter>
321
+ <slot name="custom-mobile" {filter}></slot>
322
+ </svelte:fragment>
323
+
312
324
  </MobileFilterEditor>
313
325
  </div>
314
326
  {:else}
315
- <div
316
- class="drawer-filter-list"
317
- style:margin-top="20px"
318
- style:height="100%"
319
- out:fly|local={{duration: 100, x: -200}}
327
+ <div
328
+ class="drawer-filter-list"
329
+ style:margin-top="20px"
330
+ style:height="100%"
331
+ out:fly|local={{duration: 100, x: -200}}
320
332
  in:fly|local={{duration: 100, x: 200, delay: 100}}
321
333
  >
322
334
  <SelectableVerticalList
@@ -401,7 +413,12 @@ function handleDeleteIconClick(e) {
401
413
  on:apply={handleApplyFilterClick}
402
414
  {lang}
403
415
  {labelsMapper}
404
- ></FilterEditor>
416
+ forceApplyValid={!!customFiltersValid[selectedFilter.name]}
417
+ >
418
+ <svelte:fragment slot="custom" let:filter>
419
+ <slot name="custom" {filter}></slot>
420
+ </svelte:fragment>
421
+ </FilterEditor>
405
422
  {/if}
406
423
  </div>
407
424
  </Menu>
@@ -23,6 +23,9 @@ declare const __propDef: {
23
23
  betweenSeparator?: string | undefined;
24
24
  trueString?: string | undefined;
25
25
  falseString?: string | undefined;
26
+ customFiltersValid?: {
27
+ [filterName: string]: boolean;
28
+ } | undefined;
26
29
  labelsMapper?: LabelMapper | undefined;
27
30
  };
28
31
  events: {
@@ -38,6 +41,12 @@ declare const __propDef: {
38
41
  };
39
42
  slots: {
40
43
  append: {};
44
+ 'custom-mobile': {
45
+ filter: Filter | undefined;
46
+ };
47
+ custom: {
48
+ filter: Filter | undefined;
49
+ };
41
50
  };
42
51
  };
43
52
  export type FiltersProps = typeof __propDef.props;
@@ -9,11 +9,11 @@ import Icon from "../../simple/media/Icon.svelte";
9
9
  import { fly } from "svelte/transition";
10
10
  import Autocomplete from "../../simple/forms/Autocomplete.svelte";
11
11
  import Checkbox from "../../simple/forms/Checkbox.svelte";
12
- export let filter = void 0, lang = "en", cancelFilterLabel = lang == "en" ? "Cancel" : "Annulla", applyFilterLabel = lang == "en" ? "Apply filter" : "Applica filtro", backIcon = "mdi-arrow-left", betweenFromLabel = lang == "en" ? "From" : "Da", betweenToLabel = lang == "en" ? "To" : "A", labelsMapper;
12
+ export let filter = void 0, lang = "en", cancelFilterLabel = lang == "en" ? "Cancel" : "Annulla", applyFilterLabel = lang == "en" ? "Apply filter" : "Applica filtro", backIcon = "mdi-arrow-left", betweenFromLabel = lang == "en" ? "From" : "Da", betweenToLabel = lang == "en" ? "To" : "A", labelsMapper, forceApplyValid = false;
13
13
  let dispatch = createEventDispatcher();
14
14
  function handleApplyFilterClick() {
15
15
  if (!!filter && !!tmpFilter) {
16
- filter = structuredClone(tmpFilter);
16
+ filter = { ...tmpFilter };
17
17
  filter.active = true;
18
18
  dispatch("apply");
19
19
  }
@@ -21,7 +21,7 @@ function handleApplyFilterClick() {
21
21
  let step;
22
22
  let tmpFilter;
23
23
  function initTmpFilter() {
24
- tmpFilter = structuredClone(filter);
24
+ tmpFilter = filter === void 0 ? void 0 : { ...filter };
25
25
  if (!!tmpFilter && tmpFilter.advanced) {
26
26
  if (["string", "number", "date", "select"].includes(tmpFilter.type) && Object.keys(tmpFilter).includes("mode")) {
27
27
  if (tmpFilter.mode == "between" && tmpFilter.from !== void 0 && tmpFilter.to !== void 0 || tmpFilter.value !== void 0 || tmpFilter.type == "select" && tmpFilter.values !== void 0 && tmpFilter.values.length > 0) {
@@ -84,7 +84,7 @@ function handleAdvancedModeSelection() {
84
84
  }
85
85
  let canRenderOptions = true;
86
86
  $:
87
- applyFilterDisabled = !Validator.isValid(tmpFilter);
87
+ applyFilterDisabled = !Validator.isValid(tmpFilter) && !forceApplyValid;
88
88
  function handleModeBackClick() {
89
89
  dispatch("backClick");
90
90
  }
@@ -245,6 +245,8 @@ $:
245
245
  {tmpFilter.description}
246
246
  </span>
247
247
  </div>
248
+ {:else if tmpFilter.type == 'custom'}
249
+ <slot name="custom" filter={tmpFilter}></slot>
248
250
  {/if}
249
251
  </div>
250
252
  </div>
@@ -11,6 +11,7 @@ declare const __propDef: {
11
11
  betweenFromLabel?: string | undefined;
12
12
  betweenToLabel?: string | undefined;
13
13
  labelsMapper: LabelMapper;
14
+ forceApplyValid?: boolean | undefined;
14
15
  };
15
16
  events: {
16
17
  keypress: KeyboardEvent;
@@ -24,6 +25,9 @@ declare const __propDef: {
24
25
  };
25
26
  slots: {
26
27
  title: {};
28
+ custom: {
29
+ filter: Filter | undefined;
30
+ };
27
31
  };
28
32
  };
29
33
  export type MobileFilterEditorProps = typeof __propDef.props;
@@ -0,0 +1,128 @@
1
+ <script context="module"></script>
2
+
3
+ <script>import Sortable from "sortablejs";
4
+ import { onMount, createEventDispatcher } from "svelte";
5
+ import TreeEditorItem from "./TreeEditorItem.svelte";
6
+ import { createId } from "@paralleldrive/cuid2";
7
+ import { cloneDeep } from "lodash";
8
+ let dispatch = createEventDispatcher();
9
+ export let items = [], groupName = createId(), cleanItems = convertItemsInClean(items);
10
+ let itemList, sortable = void 0, rerender = true, mounted = false;
11
+ onMount(() => {
12
+ mounted = true;
13
+ initSortable();
14
+ });
15
+ async function initSortable() {
16
+ if (!mounted)
17
+ return;
18
+ sortable = Sortable.create(itemList, {
19
+ handle: ".handle",
20
+ group: groupName,
21
+ animation: 150,
22
+ ghostClass: "ghost-drag-element",
23
+ onEnd(event) {
24
+ sortTree();
25
+ }
26
+ });
27
+ }
28
+ $:
29
+ if (!!items)
30
+ initSortable();
31
+ function handleEnd(event) {
32
+ sortTree();
33
+ }
34
+ async function sortTree() {
35
+ let clonedItems = cloneDeep(items);
36
+ let sortedItems = sortSubTree(clonedItems, items, sortable, "main");
37
+ dispatch("change", {
38
+ items: sortedItems
39
+ });
40
+ items = sortedItems;
41
+ rerender = !rerender;
42
+ }
43
+ function sortSubTree(totalItems, itemsToSort, parentSortable, parentId) {
44
+ if (!parentSortable)
45
+ throw new Error("Parent sortable could not be undefined");
46
+ parentSortable.save();
47
+ for (let i = 0; i < itemsToSort.length; i += 1) {
48
+ let itemToSort = itemsToSort[i];
49
+ if (!!itemToSort.children) {
50
+ itemsToSort[i].children = sortSubTree(totalItems, itemToSort.children, itemToSort.sortable, itemToSort.id);
51
+ }
52
+ }
53
+ let orderedIds = [];
54
+ for (let k = 0; k < parentSortable.el.children.length; k += 1) {
55
+ let id = parentSortable.el.children[k].getAttribute("data-sortable-id")?.toString();
56
+ if (!id)
57
+ throw new Error("All html element must have data-sortbale-id");
58
+ orderedIds.push(id);
59
+ }
60
+ let newItems = [];
61
+ for (let j = 0; j < orderedIds.length; j += 1) {
62
+ let id = orderedIds[j];
63
+ let itemIndex = itemsToSort.findIndex((its) => its.id.toString() == id);
64
+ if (itemIndex === -1) {
65
+ let itemToAdd = findItem(totalItems, id);
66
+ if (!itemToAdd)
67
+ continue;
68
+ newItems.push(itemToAdd);
69
+ } else {
70
+ newItems.push(itemsToSort[itemIndex]);
71
+ }
72
+ }
73
+ return newItems;
74
+ }
75
+ function findItem(itemsToSearch, id) {
76
+ for (let i = 0; i < itemsToSearch.length; i += 1) {
77
+ let item = itemsToSearch[i];
78
+ if (item.id == id)
79
+ return item;
80
+ if (!!item.children) {
81
+ let result = findItem(item.children, id);
82
+ if (!!result)
83
+ return result;
84
+ }
85
+ }
86
+ }
87
+ function convertItemsInClean(items2) {
88
+ return items2.map((i) => {
89
+ return {
90
+ id: i.id,
91
+ title: i.title,
92
+ expanded: i.expanded,
93
+ children: !!i.children ? convertItemsInClean(i.children) : [],
94
+ data: i.data
95
+ };
96
+ });
97
+ }
98
+ $:
99
+ cleanItems = convertItemsInClean(items);
100
+ </script>
101
+
102
+ {#key rerender}
103
+ <ul
104
+ class="main-ul"
105
+ bind:this={itemList}
106
+ >
107
+ {#each items as item (item.id)}
108
+ <TreeEditorItem
109
+ title={item.title}
110
+ id={item.id}
111
+ group={groupName}
112
+ bind:subItems={item.children}
113
+ bind:expanded={item.expanded}
114
+ bind:sortable={item.sortable}
115
+ on:end={handleEnd}
116
+ ></TreeEditorItem>
117
+ {/each}
118
+ </ul>
119
+ {/key}
120
+
121
+ <style>
122
+
123
+ .main-ul {
124
+ padding: 0px;
125
+ padding-bottom: 30px;
126
+ list-style: none;
127
+ }
128
+ </style>
@@ -0,0 +1,38 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ export type Item = {
3
+ id: number | string;
4
+ title: string;
5
+ expanded?: boolean;
6
+ sortable?: Sortable;
7
+ children?: Item[];
8
+ data?: any;
9
+ };
10
+ export type CleanItem = {
11
+ id: number | string;
12
+ title: string;
13
+ expanded?: boolean;
14
+ children?: CleanItem[];
15
+ data?: any;
16
+ };
17
+ import Sortable from 'sortablejs';
18
+ declare const __propDef: {
19
+ props: {
20
+ items?: Item[] | undefined;
21
+ groupName?: string | undefined;
22
+ cleanItems?: CleanItem[] | undefined;
23
+ };
24
+ events: {
25
+ change: CustomEvent<{
26
+ items: Item[];
27
+ }>;
28
+ } & {
29
+ [evt: string]: CustomEvent<any>;
30
+ };
31
+ slots: {};
32
+ };
33
+ export type TreeEditorProps = typeof __propDef.props;
34
+ export type TreeEditorEvents = typeof __propDef.events;
35
+ export type TreeEditorSlots = typeof __propDef.slots;
36
+ export default class TreeEditor extends SvelteComponentTyped<TreeEditorProps, TreeEditorEvents, TreeEditorSlots> {
37
+ }
38
+ export {};
@@ -0,0 +1,120 @@
1
+ <script>import Sortable from "sortablejs";
2
+ import { onMount } from "svelte";
3
+ import Icon from "../media/Icon.svelte";
4
+ import Button from "../buttons/Button.svelte";
5
+ import { slide } from "svelte/transition";
6
+ import { createEventDispatcher } from "svelte";
7
+ let dispatch = createEventDispatcher();
8
+ export let title, id, subtitle = void 0, group, animationDuration = 150, expanded = true, subItems = [], sortable = void 0;
9
+ let subItemList, mounted = false;
10
+ onMount(() => {
11
+ mounted = true;
12
+ initSortable();
13
+ });
14
+ function initSortable() {
15
+ if (!mounted)
16
+ return;
17
+ sortable = Sortable.create(subItemList, {
18
+ group,
19
+ handle: ".handle",
20
+ animation: animationDuration,
21
+ ghostClass: "ghost-drag-element",
22
+ onEnd(ev) {
23
+ dispatch("end", { ev });
24
+ },
25
+ onChange(ev) {
26
+ dispatch("change", { ev });
27
+ },
28
+ onUpdate(ev) {
29
+ }
30
+ });
31
+ }
32
+ $:
33
+ if (!!subItems)
34
+ initSortable();
35
+ </script>
36
+
37
+ <li
38
+ class="tree-editor-item-container"
39
+ data-sortable-title={title}
40
+ data-sortable-id={id}
41
+ >
42
+ <div class="card-container">
43
+ <div class="handle">
44
+ <Icon
45
+ name="mdi-dots-grid"
46
+ ></Icon>
47
+ </div>
48
+ <div class="button-container" class:reversed={expanded}>
49
+ <Button
50
+ buttonType="text"
51
+ on:click={() => expanded = !expanded}
52
+ >
53
+ <Icon
54
+ name="mdi-chevron-down"
55
+ ></Icon>
56
+ </Button>
57
+ </div>
58
+ {title}
59
+ </div>
60
+ <ul
61
+ class="list-container"
62
+ bind:this={subItemList}
63
+ >
64
+ {#if expanded && !!subItems}
65
+ {#each subItems as subItem}
66
+ <svelte:self
67
+ id={subItem.id}
68
+ title={subItem.title}
69
+ group={group}
70
+ animationDuration={animationDuration}
71
+ bind:subItems={subItem.children}
72
+ bind:sortable={subItem.sortable}
73
+ ></svelte:self>
74
+ {/each}
75
+ {/if}
76
+ </ul>
77
+ </li>
78
+
79
+ <style>
80
+ ul {
81
+ min-height: 10px;
82
+ list-style: none;
83
+ }
84
+
85
+ .card-container {
86
+ width: 100%;
87
+ display: flex;
88
+ align-items: center;
89
+ font-size: 1.2rem;
90
+ font-weight: 700;
91
+ border-radius: 12px;
92
+ min-height: 20px;
93
+ padding: 16px;
94
+ box-shadow: rgb(var(--global-color-contrast-200), .3) 0px 4px 6px;;
95
+ }
96
+
97
+ :global(.ghost-drag-element > .card-container) {
98
+ background-color: rgb(var(--global-color-primary-500), .3);
99
+ opacity: 30%;
100
+ }
101
+
102
+ :global(.ghost-drag-element > .list-container) {
103
+ opacity: 30%;
104
+ }
105
+
106
+ .handle {
107
+ margin-right: 8px;
108
+ cursor: grab;
109
+ transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
110
+ }
111
+
112
+ .button-container {
113
+ margin-right: 12px;
114
+ transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
115
+ }
116
+
117
+ .button-container.reversed {
118
+ transform: rotate(-90deg);
119
+ }
120
+ </style>
@@ -0,0 +1,32 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import Sortable from 'sortablejs';
3
+ import type { Item } from './TreeEditor.svelte';
4
+ declare const __propDef: {
5
+ props: {
6
+ title: string;
7
+ id: number | string;
8
+ subtitle?: string | undefined;
9
+ group: string;
10
+ animationDuration?: number | undefined;
11
+ expanded?: boolean | undefined;
12
+ subItems?: Item[] | undefined;
13
+ sortable?: Sortable | undefined;
14
+ };
15
+ events: {
16
+ change: CustomEvent<{
17
+ ev: Sortable.SortableEvent;
18
+ }>;
19
+ end: CustomEvent<{
20
+ ev: Sortable.SortableEvent;
21
+ }>;
22
+ } & {
23
+ [evt: string]: CustomEvent<any>;
24
+ };
25
+ slots: {};
26
+ };
27
+ export type TreeEditorItemProps = typeof __propDef.props;
28
+ export type TreeEditorItemEvents = typeof __propDef.events;
29
+ export type TreeEditorItemSlots = typeof __propDef.slots;
30
+ export default class TreeEditorItem extends SvelteComponentTyped<TreeEditorItemProps, TreeEditorItemEvents, TreeEditorItemSlots> {
31
+ }
32
+ export {};
package/dist/index.d.ts CHANGED
@@ -22,6 +22,7 @@ export { default as Textfield } from './components/simple/forms/Textfield.svelte
22
22
  export { default as SimpleTextField } from './components/simple/forms/SimpleTextField.svelte';
23
23
  export { default as VerticalSwitch } from './components/simple/forms/VerticalSwitch.svelte';
24
24
  export { default as VerticalTextSwitch } from './components/simple/forms/VerticalTextSwitch.svelte';
25
+ export { default as TreeEditor } from './components/simple/forms/TreeEditor.svelte';
25
26
  export { default as ColorInvertedSelector } from './components/simple/lists/ColorInvertedSelector.svelte';
26
27
  export { default as SelectableMenuList } from './components/simple/lists/SelectableMenuList.svelte';
27
28
  export { default as SidebarMenuList } from './components/simple/lists/SidebarMenuList.svelte';
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ export { default as Textfield } from './components/simple/forms/Textfield.svelte
22
22
  export { default as SimpleTextField } from './components/simple/forms/SimpleTextField.svelte';
23
23
  export { default as VerticalSwitch } from './components/simple/forms/VerticalSwitch.svelte';
24
24
  export { default as VerticalTextSwitch } from './components/simple/forms/VerticalTextSwitch.svelte';
25
+ export { default as TreeEditor } from './components/simple/forms/TreeEditor.svelte';
25
26
  export { default as ColorInvertedSelector } from './components/simple/lists/ColorInvertedSelector.svelte';
26
27
  export { default as SelectableMenuList } from './components/simple/lists/SelectableMenuList.svelte';
27
28
  export { default as SidebarMenuList } from './components/simple/lists/SidebarMenuList.svelte';
@@ -1,5 +1,5 @@
1
1
  import Builder from "./builder";
2
- export declare const StringModes: readonly ["equal", "like", "ilike"];
2
+ export declare const StringModes: readonly ["equal", "like", "ilike", "contains"];
3
3
  export type StringMode = typeof StringModes[number];
4
4
  export declare const GenericModes: readonly ["equal", "greater", "lower", "between"];
5
5
  export type DateMode = typeof GenericModes[number];
@@ -73,6 +73,7 @@ type CustomFilter = {
73
73
  modify: (params: {
74
74
  filter: Omit<Filter, 'modifier'>;
75
75
  builder: Builder;
76
+ value: any;
76
77
  }) => Builder;
77
78
  data?: any;
78
79
  };
@@ -87,6 +88,9 @@ export default class Converter {
87
88
  constructor();
88
89
  createBuilder(params: {
89
90
  filters: Filter[];
91
+ customFiltersValues?: {
92
+ [filterName: string]: any;
93
+ };
90
94
  }): Builder;
91
95
  private applyStringFilter;
92
96
  private applyDateFilter;
@@ -1,5 +1,5 @@
1
1
  import Builder from "./builder";
2
- export const StringModes = ['equal', 'like', 'ilike'];
2
+ export const StringModes = ['equal', 'like', 'ilike', 'contains'];
3
3
  export const GenericModes = ['equal', 'greater', 'lower', 'between'];
4
4
  export const SelectModes = ['equal', 'different'];
5
5
  export default class Converter {
@@ -11,8 +11,8 @@ export default class Converter {
11
11
  const filter = params.filters[i];
12
12
  if (!filter.active)
13
13
  continue;
14
- if (filter.type == 'custom' && !!filter.modify) {
15
- builder = filter.modify({ filter, builder });
14
+ if (filter.type == 'custom' && !!filter.modify && !!params.customFiltersValues && params.customFiltersValues[filter.name] !== undefined) {
15
+ builder = filter.modify({ filter, builder, value: params.customFiltersValues[filter.name] });
16
16
  }
17
17
  else if (filter.type == 'string') {
18
18
  this.applyStringFilter({ builder, filter });
@@ -41,6 +41,9 @@ export default class Converter {
41
41
  else if (params.filter.mode == 'ilike') {
42
42
  params.builder.where(params.filter.column, 'ilike', params.filter.value);
43
43
  }
44
+ else if (params.filter.mode == 'contains') {
45
+ params.builder.where(params.filter.column, 'ilike', `%${params.filter.value}%`);
46
+ }
44
47
  else {
45
48
  params.builder.where(params.filter.column, '=', params.filter.value);
46
49
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@likable-hair/svelte",
3
3
  "description": "A Svelte component for likablehair",
4
- "version": "3.0.58",
4
+ "version": "3.0.59",
5
5
  "scripts": {
6
6
  "host": "vite --host",
7
7
  "dev": "vite dev",
@@ -38,6 +38,7 @@
38
38
  "@sveltejs/package": "^2.0.0",
39
39
  "@types/lodash": "^4.14.192",
40
40
  "@types/luxon": "^3.3.0",
41
+ "@types/sortablejs": "^1.15.7",
41
42
  "@typescript-eslint/eslint-plugin": "^5.45.0",
42
43
  "@typescript-eslint/parser": "^5.45.0",
43
44
  "eslint": "^8.28.0",
@@ -65,6 +66,7 @@
65
66
  "imask": "^7.1.0-alpha.0",
66
67
  "lodash": "^4.17.21",
67
68
  "luxon": "^3.3.0",
69
+ "sortablejs": "^1.15.2",
68
70
  "svelte-chartjs": "^3.1.2",
69
71
  "svelte-grid": "^5.1.2"
70
72
  }