@djcali570/component-lib 0.0.3 → 0.0.5

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.
@@ -0,0 +1,329 @@
1
+ <script module lang="ts">
2
+ /**
3
+ * Dropdown5 v0.0.1
4
+ */
5
+ export interface DropDownItem<TProps extends Record<string, any> = {}> {
6
+ id?: string;
7
+ value: string;
8
+ extraValue?: string;
9
+ component?: Component<TProps>;
10
+ componentStyles?: string;
11
+ props?: TProps;
12
+ }
13
+ </script>
14
+
15
+ <script lang="ts">
16
+ import { browser } from '$app/environment';
17
+ import { onDestroy, onMount, type Component } from 'svelte';
18
+ import { fly } from 'svelte/transition';
19
+
20
+ let {
21
+ colorScheme = {
22
+ textColor: '#D6D6D6',
23
+ bgColor: '#121212',
24
+ borderColor: '#262626',
25
+ titleColor: '#989A9A',
26
+ dropdownBgColor: '#141414',
27
+ focusedColor: '#4787ac',
28
+ itemTextColor: '#D6D6D6',
29
+ itemHoverBgColor: '#4787ac',
30
+ itemHoverTextColor: '#121212'
31
+ },
32
+ name = 'dropdown',
33
+ title = 'Title',
34
+ value = $bindable(),
35
+ valueKey = $bindable(),
36
+ extraValue = $bindable(),
37
+ onUpdate = (key, v, ev) => {},
38
+ disabled = false,
39
+ dropdownItems = [] as DropDownItem[]
40
+ }: {
41
+ colorScheme?: any;
42
+ name?: string;
43
+ title?: string;
44
+ value: any;
45
+ valueKey?: string | null | undefined;
46
+ extraValue?: string | null | undefined;
47
+ onUpdate?: (valueKey: string, value: string, extraValue: string) => void;
48
+ disabled?: boolean;
49
+ dropdownItems?: DropDownItem[];
50
+ } = $props();
51
+
52
+ const id = generateRandomString();
53
+ let showDropdown = $state(false);
54
+ let dropdownRef: HTMLDivElement | null = $state(null);
55
+ let filteredItems: DropDownItem[] = $state([]);
56
+
57
+ $effect(() => {
58
+ if (!browser || !showDropdown || !dropdownRef) return;
59
+ setTimeout(() => {
60
+ if (!dropdownRef) return;
61
+ const dropdownRect = dropdownRef.getBoundingClientRect();
62
+ const viewportHeight = window.innerHeight;
63
+ if (dropdownRect.bottom > viewportHeight) {
64
+ const scrollY = window.scrollY + (dropdownRect.bottom - viewportHeight) + 10;
65
+ window.scrollTo({ top: scrollY, behavior: 'smooth' });
66
+ }
67
+ }, 0);
68
+ });
69
+
70
+ onMount(() => {
71
+ document.addEventListener('click', closeDropdown);
72
+ });
73
+
74
+ onDestroy(() => {
75
+ try {
76
+ document.removeEventListener('click', closeDropdown);
77
+ } catch (error) {}
78
+ });
79
+
80
+ /**
81
+ * Generate a random string so that each
82
+ * input will have a unique id in the dom
83
+ */
84
+ function generateRandomString() {
85
+ const length = 6;
86
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
87
+
88
+ let result = '';
89
+ for (let i = 0; i < length; i++) {
90
+ const randomIndex = Math.floor(Math.random() * characters.length);
91
+ result += characters.charAt(randomIndex);
92
+ }
93
+
94
+ return result;
95
+ }
96
+
97
+ /**
98
+ * Show the dropdown list
99
+ */
100
+ function showDropdownList() {
101
+ showDropdown = true;
102
+ filteredItems = dropdownItems;
103
+ }
104
+
105
+ function closeDropdown(event: Event) {
106
+ const target = event.target as HTMLElement;
107
+
108
+ if (target.id !== `dropdown-${id}`) {
109
+ showDropdown = false;
110
+ validateInput();
111
+ }
112
+ }
113
+ function filterItems() {
114
+ filteredItems = dropdownItems.filter((item) =>
115
+ item.value.toLowerCase().includes(value.toLowerCase())
116
+ );
117
+ }
118
+ function selectItem(item: DropDownItem) {
119
+ valueKey = item.id ?? '';
120
+ extraValue = item.extraValue ?? '';
121
+ value = item.value;
122
+ onUpdate(valueKey, value, extraValue);
123
+ showDropdown = false;
124
+ }
125
+ function validateInput() {
126
+ const matchedItem = dropdownItems.find((item) => {
127
+ return item.value.toLowerCase() === value.toLowerCase(); // Add return statement
128
+ });
129
+ if (!matchedItem) {
130
+ // Clear input if the entered value is not in the list
131
+ value = '';
132
+ } else if (value !== matchedItem.value) {
133
+ // Set the inputText to the matched item's value if it's different
134
+ value = matchedItem.value;
135
+ }
136
+ }
137
+ </script>
138
+
139
+ <div
140
+ class="dropdown5__container"
141
+ style="
142
+ --dropdown5__textColor: {colorScheme.textColor};
143
+ --dropdown5__mainBgColor: {colorScheme.bgColor};
144
+ --dropdown5__borderColor: {colorScheme.borderColor};
145
+ --dropdown5__titleColor: {colorScheme.titleColor};
146
+ --dropdown5__bgColor: {colorScheme.dropdownBgColor};
147
+ --dropdown5__focusedColor: {colorScheme.focusedColor};
148
+ --dropdown5__itemTextColor: {colorScheme.itemTextColor};
149
+ --dropdown5__itemHoverBgColor: {colorScheme.itemHoverBgColor};
150
+ --dropdown5__itemHoverTextColor: {colorScheme.itemHoverTextColor};
151
+ "
152
+ >
153
+ <div>
154
+ <div class="dropdown5__title">{title}</div>
155
+ <div class="dropdown5__input">
156
+ <input
157
+ id="dropdown-{id}"
158
+ type="text"
159
+ aria-controls="dropdown-{id}-list"
160
+ aria-haspopup="listbox"
161
+ {name}
162
+ bind:value
163
+ oninput={filterItems}
164
+ onfocus={showDropdownList}
165
+ onblur={validateInput}
166
+ autocomplete="off"
167
+ {disabled}
168
+ />
169
+ <input
170
+ id="dropdown-valueKey-{id}"
171
+ name={`${name}-valueKey-${id}`}
172
+ type="hidden"
173
+ bind:value={valueKey}
174
+ />
175
+ </div>
176
+ </div>
177
+
178
+ {#if showDropdown}
179
+ <div
180
+ class="dropdown5__list__container"
181
+ style="box-shadow: 0px 1px 16px 0px rgba(0,0,0,0.12);"
182
+ role="listbox"
183
+ aria-labelledby="dropdown-{id}-title"
184
+ bind:this={dropdownRef}
185
+ oninput={filterItems}
186
+ transition:fly={{
187
+ y: 10
188
+ }}
189
+ >
190
+ <div style="height:100%;">
191
+ {#each filteredItems as item, index}
192
+ <button
193
+ type="button"
194
+ class="dropdown5__list__item"
195
+ role="option"
196
+ aria-selected={item.value === value ? 'true' : 'false'}
197
+ onclick={() => selectItem(item)}
198
+ >
199
+ {#if item.value === value}
200
+ <div class="fic">
201
+ <div style="padding-right: 0.5rem;">
202
+ <div class="fca" style="width: 1rem; height: 1rem;">
203
+ <svg
204
+ viewBox="0 0 12 12"
205
+ xmlns="http://www.w3.org/2000/svg"
206
+ aria-hidden="true"
207
+ role="presentation"
208
+ focusable="false"
209
+ style="display: block; height: 12px; width: 12px; fill: currentcolor;"
210
+ ><path
211
+ d="m10.5 1.939 1.061 1.061-7.061 7.061-.53-.531-3-3-.531-.53 1.061-1.061 3 3 5.47-5.469z"
212
+ ></path></svg
213
+ >
214
+ </div>
215
+ </div>
216
+ {#if item.component}
217
+ {@const Component = item.component}
218
+ <div class="component" style={item.componentStyles}>
219
+ <Component {...item.props} />
220
+ </div>
221
+ {/if}
222
+ <div>{item.value}</div>
223
+ </div>
224
+ {:else}
225
+ <div class="fic">
226
+ <div style="padding-right: 0.5rem;">
227
+ <div style="width: 1rem; height: 1rem;"></div>
228
+ </div>
229
+
230
+ {#if item.component}
231
+ {@const Component = item.component}
232
+ <div class="component" style={item.componentStyles}>
233
+ <Component {...item.props} />
234
+ </div>
235
+ {/if}
236
+
237
+ <div>{item.value}</div>
238
+ </div>
239
+ {/if}
240
+ </button>
241
+ {/each}
242
+ </div>
243
+ </div>
244
+ {/if}
245
+ </div>
246
+
247
+ <style>
248
+ .dropdown5__container {
249
+ position: relative;
250
+ display: flex;
251
+ flex-direction: column;
252
+ width: 100%;
253
+ min-height: 64px;
254
+ font-family: Arial, sans-serif;
255
+ margin: calc(var(--spacing) * 0);
256
+ background-color: var(--dropdown5__mainBgColor);
257
+ box-shadow: inset 0 0 0 1px var(--dropdown5__borderColor);
258
+ border: none;
259
+ border-radius: 0.5rem;
260
+ line-height: 1.25rem;
261
+ }
262
+
263
+ .dropdown5__container:focus-within {
264
+ box-shadow: inset 0 0 0 2px var(--dropdown5__focusedColor);
265
+ }
266
+ .dropdown5__title {
267
+ font-size: 0.75rem;
268
+ font-family: inherit;
269
+ color: var(--dropdown5__titleColor);
270
+ padding-inline: 0.75rem;
271
+ padding-top: 0.5rem;
272
+ }
273
+ .dropdown5__input {
274
+ display: flex;
275
+ padding-inline: 0.75rem;
276
+ color: var(--dropdown5__textColor);
277
+ }
278
+
279
+ input {
280
+ width: 100%;
281
+ color: inherit;
282
+ outline: none;
283
+ font-family: inherit;
284
+ max-height: 24px;
285
+ background-color: var(--dropdown5__mainBgColor);
286
+ border: none;
287
+ }
288
+ .dropdown5__list__container {
289
+ position: absolute;
290
+ top: 110%;
291
+ left: 0;
292
+ display: flex;
293
+ flex-direction: column;
294
+ width: 100%;
295
+ max-height: 10rem;
296
+ overflow-y: auto;
297
+ background-color: var(--dropdown5__bgColor);
298
+ border-radius: 0.75rem;
299
+ z-index: 10;
300
+ }
301
+ .dropdown5__list__item {
302
+ display: flex;
303
+ width: 100%;
304
+ padding: 0.5rem;
305
+ cursor: pointer;
306
+ color: var(--dropdown5__itemTextColor);
307
+ text-align: start;
308
+ background-color: transparent;
309
+ border: none;
310
+ }
311
+ .dropdown5__list__item:hover {
312
+ background-color: var(--dropdown5__itemHoverBgColor);
313
+ color: var(--dropdown5__itemHoverTextColor);
314
+ }
315
+ .fic {
316
+ display: flex;
317
+ align-items: center;
318
+ }
319
+ .fca {
320
+ display: flex;
321
+ align-items: center;
322
+ justify-content: center;
323
+ }
324
+ .component {
325
+ margin-right: 0.5rem;
326
+ width: 2rem;
327
+ height: 2rem;
328
+ }
329
+ </style>
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Dropdown5 v0.0.1
3
+ */
4
+ export interface DropDownItem<TProps extends Record<string, any> = {}> {
5
+ id?: string;
6
+ value: string;
7
+ extraValue?: string;
8
+ component?: Component<TProps>;
9
+ componentStyles?: string;
10
+ props?: TProps;
11
+ }
12
+ import { type Component } from 'svelte';
13
+ type $$ComponentProps = {
14
+ colorScheme?: any;
15
+ name?: string;
16
+ title?: string;
17
+ value: any;
18
+ valueKey?: string | null | undefined;
19
+ extraValue?: string | null | undefined;
20
+ onUpdate?: (valueKey: string, value: string, extraValue: string) => void;
21
+ disabled?: boolean;
22
+ dropdownItems?: DropDownItem[];
23
+ };
24
+ declare const DropDown5: Component<$$ComponentProps, {}, "value" | "valueKey" | "extraValue">;
25
+ type DropDown5 = ReturnType<typeof DropDown5>;
26
+ export default DropDown5;