@djcali570/component-lib 0.0.3 → 0.0.4

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.
@@ -2,7 +2,10 @@
2
2
  import { browser } from '$app/environment';
3
3
  import { fly } from 'svelte/transition';
4
4
 
5
- // Props with runes
5
+ /**
6
+ * Date Picker 5 v0.0.1
7
+ */
8
+
6
9
  let {
7
10
  colorScheme = {
8
11
  labelTextColor: '#989A9A',
@@ -319,18 +322,18 @@
319
322
  readonly
320
323
  bind:value={dateText}
321
324
  />
322
- <div class="flex justify-center items-center p-3">
325
+ <div class="dpicker-closeBtn-container">
323
326
  {#if dateText && !disabled}
324
327
  <button
325
328
  aria-label="Close Date Picker"
326
329
  id="dpicker-CloseBtn-{id}"
327
- class="dpicker-closeBtn w-6 h-6 flex justify-center items-center rounded-full"
330
+ class="dpicker-closeBtn"
328
331
  onclick={(e) => {
329
332
  e.stopPropagation();
330
333
  clearDate();
331
334
  }}
332
335
  >
333
- <div class="h-[14px] w-[14px] close-btn">
336
+ <div class="close-btn">
334
337
  <svg
335
338
  version="1.1"
336
339
  id="Layer_1"
@@ -364,21 +367,18 @@
364
367
  style="box-shadow: 0px 1px 16px 0px rgba(0,0,0,0.12);"
365
368
  transition:fly={{ y: 10 }}
366
369
  >
367
- <div class="h-full">
368
- <div class="grid grid-cols-7 month-block">
370
+ <div style="height:100%;">
371
+ <div class="month-block">
369
372
  <button
370
373
  id="chev-prev-{id}"
371
374
  type="button"
372
375
  aria-label="Previous Month"
373
- class="w-full flex col-span-1 items-center justify-center cursor-pointer"
376
+ class="month-block-btn"
374
377
  disabled={showPrevMonthButton}
375
378
  onclick={prevMonth}
376
379
  >
377
- <div
378
- class="size-8 flex justify-center items-center rounded-full chev"
379
- class:disabled={showPrevMonthButton}
380
- >
381
- <div class="size-5">
380
+ <div class="chev" class:disabled={showPrevMonthButton}>
381
+ <div class="chev-svg">
382
382
  <svg
383
383
  version="1.1"
384
384
  id="Layer_1"
@@ -399,7 +399,7 @@
399
399
  </div>
400
400
  </div>
401
401
  </button>
402
- <div class="col-span-5 flex justify-center items-center">
402
+ <div class="month-block-month">
403
403
  {monthNames[viewDate.getMonth()]}
404
404
  {viewDate.getFullYear()}
405
405
  </div>
@@ -407,15 +407,12 @@
407
407
  id="chev-next-{id}"
408
408
  type="button"
409
409
  aria-label="Next Month"
410
- class="w-full flex col-span-1 items-center justify-center cursor-pointer"
410
+ class="month-block-btn"
411
411
  disabled={showNextMonthButton}
412
412
  onclick={nextMonth}
413
413
  >
414
- <div
415
- class="size-8 flex justify-center items-center rounded-full chev"
416
- class:disabled={showNextMonthButton}
417
- >
418
- <div class="size-5">
414
+ <div class="chev" class:disabled={showNextMonthButton}>
415
+ <div class="chev-svg">
419
416
  <svg
420
417
  version="1.1"
421
418
  id="Layer_1"
@@ -437,21 +434,21 @@
437
434
  </div>
438
435
  </button>
439
436
  </div>
440
- <div class="grid grid-cols-7">
437
+ <div class="week">
441
438
  {#each weekAbv as weekday}
442
- <div class="flex justify-center items-center text-[var(--text-light)] text-sm">
439
+ <div class="week-days">
443
440
  {weekday}
444
441
  </div>
445
442
  {/each}
446
443
  </div>
447
- <div class="grid grid-cols-7 grid-rows-6">
444
+ <div class="calendar-days">
448
445
  {#each calendarDays as date, index (index)}
449
- <div id="day-{index}" class="flex justify-center items-center">
446
+ <div id="day-{index}" class="calendar-days-day">
450
447
  {#if date}
451
448
  <button
452
449
  id="day-btn-{index}"
453
450
  type="button"
454
- class="h-10 w-10 flex justify-center items-center calendar-day"
451
+ class="calendar-day"
455
452
  class:highlighted={(selectedDate &&
456
453
  date.toDateString() === selectedDate.toDateString()) ||
457
454
  (!selectedDate && date.toDateString() === today.toDateString())}
@@ -467,7 +464,7 @@
467
464
  {date.getDate()}
468
465
  </button>
469
466
  {:else}
470
- <div class="h-10 w-10 flex justify-center items-center"></div>
467
+ <div class="calendar-day-else"></div>
471
468
  {/if}
472
469
  </div>
473
470
  {/each}
@@ -483,6 +480,7 @@
483
480
  display: inline-block;
484
481
  width: 100%;
485
482
  color: var(--dpicker-textColor);
483
+ font-family: Arial, sans-serif;
486
484
  }
487
485
  .outer {
488
486
  background-color: var(--dpicker-inputBgColor);
@@ -506,6 +504,10 @@
506
504
  position: relative;
507
505
  box-sizing: border-box;
508
506
  }
507
+ .close-btn {
508
+ height: 14px;
509
+ width: 14px;
510
+ }
509
511
  .dpicker-title {
510
512
  line-height: 20px;
511
513
  color: var(--dpicker-labelTextColor);
@@ -532,6 +534,24 @@
532
534
  appearance: none;
533
535
  -webkit-appearance: none;
534
536
  }
537
+ .dpicker-closeBtn-container {
538
+ display: flex;
539
+ justify-content: center;
540
+ align-items: center;
541
+ padding: 0.75rem;
542
+ }
543
+ .dpicker-closeBtn {
544
+ display: none;
545
+ width: 1.5rem;
546
+ height: 1.5rem;
547
+ justify-content: center;
548
+ align-items: center;
549
+ color: var(--dpicker-clearColor);
550
+ border-radius: calc(infinity * 1px);
551
+ background-color: transparent;
552
+ border: none;
553
+ cursor: pointer;
554
+ }
535
555
  .dpicker-input {
536
556
  display: flex;
537
557
  opacity: 1;
@@ -547,10 +567,6 @@
547
567
  border-top-right-radius: 0.5rem /* 8px */;
548
568
  border-bottom-right-radius: 0.5rem /* 8px */;
549
569
  }
550
- .dpicker-closeBtn {
551
- display: none;
552
- color: var(--dpicker-clearColor);
553
- }
554
570
 
555
571
  .dpicker-closeBtn:hover {
556
572
  background-color: var(--dpicker-clearHoverColor);
@@ -576,19 +592,76 @@
576
592
  background-color: var(--dpicker-bgColor);
577
593
  }
578
594
  .month-block {
595
+ display: grid;
596
+ grid-template-columns: repeat(7, minmax(0, 1fr));
579
597
  width: 100%;
580
598
  background-color: var(--picker-monthBgColor);
581
599
  }
600
+ .month-block-btn {
601
+ display: flex;
602
+ width: 100%;
603
+ justify-content: center;
604
+ align-items: center;
605
+ grid-column: span 1 / span 1;
606
+ cursor: pointer;
607
+ border: none;
608
+ background-color: transparent;
609
+ }
610
+
611
+ .month-block-month {
612
+ grid-column: span 5 / span 5;
613
+ display: flex;
614
+ justify-content: center;
615
+ align-items: center;
616
+ }
617
+
618
+ .chev {
619
+ display: flex;
620
+ align-items: center;
621
+ justify-content: center;
622
+ width: 32px;
623
+ height: 32px;
624
+ border-radius: calc(infinity * 1px);
625
+ }
582
626
  .chev:hover {
583
627
  background-color: var(--dpicker-clearHoverColor);
584
628
  }
585
-
586
629
  .chev.disabled {
587
630
  color: var(--dpicker-inactiveDayColor);
588
631
  }
632
+ .chev-svg {
633
+ width: 1.25rem;
634
+ height: 1.25rem;
635
+ color: var(--dpicker-textColor);
636
+ }
637
+ .calendar-days {
638
+ display: grid;
639
+ grid-template-columns: repeat(7, minmax(0, 1fr));
640
+ grid-template-rows: repeat(6, minmax(0, 1fr));
641
+ }
642
+ .calendar-days-day {
643
+ display: flex;
644
+ justify-content: center;
645
+ align-items: center;
646
+ }
589
647
  .calendar-day {
648
+ display: flex;
649
+ justify-content: center;
650
+ align-items: center;
651
+ height: 2.5rem;
652
+ width: 2.5rem;
590
653
  color: var(--dpicker-textColor);
591
654
  border-radius: 50%;
655
+ background-color: transparent;
656
+ border: none;
657
+ cursor: pointer;
658
+ }
659
+ .calendar-day-else {
660
+ display: flex;
661
+ justify-content: center;
662
+ align-items: center;
663
+ height: 2.5rem;
664
+ width: 2.5rem;
592
665
  }
593
666
  .calendar-day:hover:not(:disabled) {
594
667
  border: 1px solid var(--dpicker-textColor);
@@ -597,9 +670,12 @@
597
670
  background-color: var(--dpicker-selectedDayBgColor);
598
671
  color: var(--dpicker-selectedDayTextColor);
599
672
  opacity: 1 !important; /* Ensure full opacity for highlighted dates */
673
+ border: none;
600
674
  }
601
675
 
602
676
  .other-month:not(.highlighted) {
677
+ background-color: transparent;
678
+ border: none;
603
679
  color: var(--dpicker-textColor);
604
680
  opacity: 0.65;
605
681
  }
@@ -622,4 +698,15 @@
622
698
  opacity: 0.5;
623
699
  cursor: not-allowed;
624
700
  }
701
+ .week {
702
+ display: grid;
703
+ grid-template-columns: repeat(7, minmax(0, 1fr));
704
+ }
705
+ .week-days {
706
+ display: flex;
707
+ justify-content: center;
708
+ align-items: center;
709
+ font-size: 0.875rem;
710
+ color: var(--dpicker-textColor);
711
+ }
625
712
  </style>
@@ -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;