sveltacular 0.0.21 → 0.0.23

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.
@@ -5,6 +5,7 @@ import { uniqueId } from "../../helpers/unique-id.js";
5
5
  import Menu from "../../generic/menu/menu.svelte";
6
6
  import AngleUpIcon from "../../icons/angle-up-icon.svelte";
7
7
  import debounce from "../../helpers/debounce.js";
8
+ import { browser } from "$app/environment";
8
9
  export let value = "";
9
10
  export let items = [];
10
11
  export let size = "full";
@@ -12,24 +13,34 @@ export let disabled = false;
12
13
  export let required = false;
13
14
  export let searchable = false;
14
15
  export let search = void 0;
16
+ const id = uniqueId();
17
+ const dispatch = createEventDispatcher();
15
18
  const getText = () => items.find((item) => item.value == value)?.name || "";
19
+ let text = getText();
20
+ let open = false;
21
+ let highlightIndex = -1;
22
+ let filteredItems = [];
16
23
  const onSelect = (e) => {
17
24
  value = e.detail.value;
18
25
  dispatch("change", value);
19
26
  text = getText();
27
+ applyFilter();
20
28
  open = false;
21
29
  };
30
+ const focusOnInput = () => {
31
+ if (browser)
32
+ document.getElementById(id)?.focus();
33
+ };
22
34
  const toggle = () => {
23
35
  open = !open;
24
- if (open)
25
- document.getElementById(id)?.focus();
36
+ focusOnInput();
26
37
  };
27
38
  const onInputKeyPress = (e) => {
28
39
  if (e.key == "Escape") {
29
40
  open = false;
30
41
  return;
31
42
  }
32
- if (e.key == "Enter") {
43
+ if (e.key == "Enter" || e.key == "Tab") {
33
44
  open = false;
34
45
  if (highlightIndex > -1) {
35
46
  onSelect(new CustomEvent("select", { detail: filteredItems[highlightIndex] }));
@@ -47,35 +58,39 @@ const onInputKeyPress = (e) => {
47
58
  open = false;
48
59
  return;
49
60
  }
50
- if (e.key.length == 1) {
61
+ if (e.key.length == 1 || e.key == "Backspace" || e.key == "Delete") {
51
62
  open = true;
52
63
  highlightIndex = 0;
53
64
  triggerSearch();
54
65
  }
55
66
  };
56
67
  const triggerSearch = debounce(async () => {
57
- dispatch("search", searchText);
58
68
  if (search) {
59
- items = await search(searchText);
60
- text = getText();
69
+ items = await search(text);
70
+ console.log(items);
61
71
  }
72
+ updateText();
73
+ applyFilter();
74
+ open = true;
62
75
  }, 300);
63
- const dispatch = createEventDispatcher();
76
+ const applyFilter = () => {
77
+ const searchText = text.trim().toLowerCase();
78
+ filteredItems = searchText ? items.map((item, index) => ({ ...item, index })).filter((item) => item.name.toLowerCase().includes(searchText)) : items.map((item, index) => ({ ...item, index }));
79
+ };
80
+ const clear = () => {
81
+ text = "";
82
+ value = "";
83
+ triggerSearch();
84
+ focusOnInput();
85
+ };
64
86
  const updateText = async () => {
65
- const textBox = document.getElementById(id);
66
- if (document.activeElement != textBox)
67
- text = getText();
87
+ if (browser) {
88
+ const textBox = document.getElementById(id);
89
+ if (document.activeElement != textBox)
90
+ text = getText();
91
+ open = true;
92
+ }
68
93
  };
69
- const id = uniqueId();
70
- let text = getText();
71
- let open = false;
72
- let highlightIndex = -1;
73
- $:
74
- searchText = searchable ? text : "";
75
- $:
76
- filteredItems = searchText ? items.map((item, index) => ({ ...item, index })).filter((item) => item.name.toLowerCase().includes(searchText.toLowerCase())) : items.map((item, index) => ({ ...item, index }));
77
- $:
78
- items && updateText();
79
94
  triggerSearch();
80
95
  </script>
81
96
 
@@ -99,12 +114,13 @@ triggerSearch();
99
114
  <button type="button" class="icon" on:click={toggle} on:keydown={toggle}>
100
115
  <AngleUpIcon />
101
116
  </button>
117
+ <button type="button" class="clear" on:click={clear} on:keydown={clear}> X </button>
102
118
  <div class="dropdown">
103
119
  <Menu
104
120
  items={filteredItems}
105
121
  {open}
106
122
  closeAfterSelect={false}
107
- {searchText}
123
+ searchText={text}
108
124
  on:select={onSelect}
109
125
  size="full"
110
126
  bind:highlightIndex
@@ -131,7 +147,7 @@ div input {
131
147
  user-select: none;
132
148
  white-space: nowrap;
133
149
  }
134
- div button.icon {
150
+ div button {
135
151
  border: 0;
136
152
  appearance: none;
137
153
  background: transparent;
@@ -139,14 +155,19 @@ div button.icon {
139
155
  margin: 0;
140
156
  position: absolute;
141
157
  top: 0.65rem;
142
- right: 1rem;
143
158
  width: 1rem;
144
159
  height: 1rem;
145
- transition: transform 0.3s linear;
146
160
  z-index: 2;
147
161
  color: var(--form-input-fg, black);
162
+ }
163
+ div button.icon {
164
+ right: 1rem;
165
+ transition: transform 0.3s linear;
148
166
  transform: rotate(180deg);
149
167
  }
168
+ div button.clear {
169
+ right: 3rem;
170
+ }
150
171
  div.open .icon {
151
172
  transform: rotate(0deg);
152
173
  }
@@ -12,7 +12,6 @@ declare const __propDef: {
12
12
  };
13
13
  events: {
14
14
  change: CustomEvent<string>;
15
- search: CustomEvent<string>;
16
15
  } & {
17
16
  [evt: string]: CustomEvent<any>;
18
17
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sveltacular",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "scripts": {
5
5
  "watch": "npm run dev -- --open",
6
6
  "dev": "vite dev",