mertani-web-toolkit 0.1.49 → 0.1.50
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.
|
@@ -72,6 +72,77 @@
|
|
|
72
72
|
border-color: var(--color-text-error-ti);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
.search-by-wrapper {
|
|
76
|
+
position: relative;
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
border-right: 1px solid var(--color-border-form);
|
|
80
|
+
background: var(--color-bg-disabled);
|
|
81
|
+
flex-shrink: 0;
|
|
82
|
+
border-radius: 6px 0 0 6px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.search-by-trigger {
|
|
86
|
+
border: none;
|
|
87
|
+
outline: none;
|
|
88
|
+
background: transparent;
|
|
89
|
+
font-size: 12px;
|
|
90
|
+
font-weight: 600;
|
|
91
|
+
color: var(--color-text-primary);
|
|
92
|
+
cursor: pointer;
|
|
93
|
+
padding: 0 10px;
|
|
94
|
+
height: 100%;
|
|
95
|
+
display: inline-flex;
|
|
96
|
+
align-items: center;
|
|
97
|
+
gap: 8px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.search-by-trigger:disabled {
|
|
101
|
+
cursor: not-allowed;
|
|
102
|
+
opacity: 0.7;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.search-by-label {
|
|
106
|
+
white-space: nowrap;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.search-by-menu {
|
|
110
|
+
position: absolute;
|
|
111
|
+
top: calc(100% + 4px);
|
|
112
|
+
min-width: 140px;
|
|
113
|
+
background: var(--color-bg-surface);
|
|
114
|
+
border: 1px solid var(--color-border-form);
|
|
115
|
+
border-radius: 4px;
|
|
116
|
+
box-shadow:
|
|
117
|
+
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
|
118
|
+
0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
119
|
+
overflow: hidden;
|
|
120
|
+
z-index: 99999;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.search-by-item {
|
|
124
|
+
width: 100%;
|
|
125
|
+
padding: 10px 12px;
|
|
126
|
+
text-align: left;
|
|
127
|
+
background: transparent;
|
|
128
|
+
border: none;
|
|
129
|
+
font-size: 13px;
|
|
130
|
+
color: var(--color-text-primary);
|
|
131
|
+
cursor: pointer;
|
|
132
|
+
transition:
|
|
133
|
+
background-color 0.15s,
|
|
134
|
+
color 0.15s;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.search-by-item + .search-by-item {
|
|
138
|
+
border-top: 1px solid color-mix(in srgb, var(--color-border-form) 45%, transparent);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.search-by-item:hover,
|
|
142
|
+
.search-by-item.active {
|
|
143
|
+
background: var(--color-bg-disabled);
|
|
144
|
+
}
|
|
145
|
+
|
|
75
146
|
.prefix-wrapper {
|
|
76
147
|
display: flex;
|
|
77
148
|
align-items: center;
|
|
@@ -239,7 +310,7 @@
|
|
|
239
310
|
|
|
240
311
|
.suggestion-item:hover,
|
|
241
312
|
.suggestion-item.active {
|
|
242
|
-
background: var(--color-bg-
|
|
313
|
+
background: var(--color-bg-disabled);
|
|
243
314
|
}
|
|
244
315
|
|
|
245
316
|
.suggestion-empty {
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
value?: string;
|
|
13
13
|
detail?: unknown;
|
|
14
14
|
};
|
|
15
|
+
type SearchByOption = {
|
|
16
|
+
label: string;
|
|
17
|
+
value: string;
|
|
18
|
+
};
|
|
15
19
|
|
|
16
20
|
interface Props extends HTMLInputAttributes {
|
|
17
21
|
// ===Styles===
|
|
@@ -45,6 +49,8 @@
|
|
|
45
49
|
|
|
46
50
|
// Suggestions
|
|
47
51
|
suggestions?: SuggestionOption[];
|
|
52
|
+
searchByOptions?: SearchByOption[];
|
|
53
|
+
searchBy?: string;
|
|
48
54
|
minChars?: number;
|
|
49
55
|
maxSuggestions?: number;
|
|
50
56
|
showSuggestionsOnFocus?: boolean;
|
|
@@ -112,6 +118,8 @@
|
|
|
112
118
|
|
|
113
119
|
// Suggestions
|
|
114
120
|
suggestions = [],
|
|
121
|
+
searchByOptions = [],
|
|
122
|
+
searchBy = $bindable(''),
|
|
115
123
|
minChars = 1,
|
|
116
124
|
maxSuggestions = 8,
|
|
117
125
|
showSuggestionsOnFocus = true,
|
|
@@ -153,11 +161,24 @@
|
|
|
153
161
|
let showList = $state(false);
|
|
154
162
|
let activeIndex = $state(-1);
|
|
155
163
|
let wrapperEl: HTMLDivElement | null = $state(null);
|
|
164
|
+
let searchByValue = $state(searchBy);
|
|
165
|
+
let searchByOpen = $state(false);
|
|
156
166
|
|
|
157
167
|
$effect(() => {
|
|
158
168
|
inputValue = value;
|
|
159
169
|
});
|
|
160
170
|
|
|
171
|
+
$effect(() => {
|
|
172
|
+
searchByValue = searchBy;
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
$effect(() => {
|
|
176
|
+
if (!searchByValue && searchByOptions.length) {
|
|
177
|
+
searchByValue = searchByOptions[0].value;
|
|
178
|
+
searchBy = searchByValue;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
161
182
|
const sizeConfig = $derived(() => {
|
|
162
183
|
switch (size) {
|
|
163
184
|
case 48:
|
|
@@ -365,6 +386,23 @@
|
|
|
365
386
|
oninput?.(e);
|
|
366
387
|
}
|
|
367
388
|
|
|
389
|
+
function handleSearchByChange(e: Event) {
|
|
390
|
+
const target = e.target as HTMLSelectElement;
|
|
391
|
+
searchByValue = target.value;
|
|
392
|
+
searchBy = target.value;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function selectSearchBy(option: SearchByOption) {
|
|
396
|
+
searchByValue = option.value;
|
|
397
|
+
searchBy = option.value;
|
|
398
|
+
searchByOpen = false;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function getSearchByLabel() {
|
|
402
|
+
const current = searchByOptions.find((opt) => opt.value === searchByValue);
|
|
403
|
+
return current?.label || 'Search';
|
|
404
|
+
}
|
|
405
|
+
|
|
368
406
|
function handleChange(e: Event) {
|
|
369
407
|
const target = e.target as HTMLInputElement;
|
|
370
408
|
const value = target.value;
|
|
@@ -426,6 +464,7 @@
|
|
|
426
464
|
function handleClickOutside(e: MouseEvent) {
|
|
427
465
|
if (wrapperEl && !wrapperEl.contains(e.target as Node)) {
|
|
428
466
|
closeSuggestions();
|
|
467
|
+
searchByOpen = false;
|
|
429
468
|
}
|
|
430
469
|
}
|
|
431
470
|
|
|
@@ -459,6 +498,41 @@
|
|
|
459
498
|
</label>
|
|
460
499
|
{/if}
|
|
461
500
|
<div class={wrapperClasses()} style={wrapperStyles()} bind:this={wrapperEl}>
|
|
501
|
+
{#if searchByOptions.length}
|
|
502
|
+
<div class="search-by-wrapper">
|
|
503
|
+
<button
|
|
504
|
+
type="button"
|
|
505
|
+
class="search-by-trigger"
|
|
506
|
+
onclick={() => !disabled && !isLoading && (searchByOpen = !searchByOpen)}
|
|
507
|
+
disabled={disabled || isLoading}
|
|
508
|
+
>
|
|
509
|
+
<span class="search-by-label">{getSearchByLabel()}</span>
|
|
510
|
+
<Icon
|
|
511
|
+
name="bs-chevron-down"
|
|
512
|
+
style="transform-origin: center; transition: transform 0.25s; transform: rotate({searchByOpen
|
|
513
|
+
? '180deg'
|
|
514
|
+
: '0deg'});"
|
|
515
|
+
/>
|
|
516
|
+
</button>
|
|
517
|
+
{#if searchByOpen}
|
|
518
|
+
<div class="search-by-menu">
|
|
519
|
+
{#each searchByOptions as option (option.value)}
|
|
520
|
+
<button
|
|
521
|
+
type="button"
|
|
522
|
+
class="search-by-item"
|
|
523
|
+
class:active={option.value === searchByValue}
|
|
524
|
+
onmousedown={(e) => {
|
|
525
|
+
e.preventDefault();
|
|
526
|
+
selectSearchBy(option);
|
|
527
|
+
}}
|
|
528
|
+
>
|
|
529
|
+
{option.label}
|
|
530
|
+
</button>
|
|
531
|
+
{/each}
|
|
532
|
+
</div>
|
|
533
|
+
{/if}
|
|
534
|
+
</div>
|
|
535
|
+
{/if}
|
|
462
536
|
{#if prefix}
|
|
463
537
|
<div class="prefix-wrapper" style={prefixStyles()}>
|
|
464
538
|
<span class="prefix-text">{prefix}</span>
|
|
@@ -7,6 +7,10 @@ type SuggestionOption = string | {
|
|
|
7
7
|
value?: string;
|
|
8
8
|
detail?: unknown;
|
|
9
9
|
};
|
|
10
|
+
type SearchByOption = {
|
|
11
|
+
label: string;
|
|
12
|
+
value: string;
|
|
13
|
+
};
|
|
10
14
|
interface Props extends HTMLInputAttributes {
|
|
11
15
|
labelColor?: string;
|
|
12
16
|
aligment?: 'side' | 'top';
|
|
@@ -30,6 +34,8 @@ interface Props extends HTMLInputAttributes {
|
|
|
30
34
|
prefix?: string;
|
|
31
35
|
suffix?: string;
|
|
32
36
|
suggestions?: SuggestionOption[];
|
|
37
|
+
searchByOptions?: SearchByOption[];
|
|
38
|
+
searchBy?: string;
|
|
33
39
|
minChars?: number;
|
|
34
40
|
maxSuggestions?: number;
|
|
35
41
|
showSuggestionsOnFocus?: boolean;
|
|
@@ -56,6 +62,6 @@ interface Props extends HTMLInputAttributes {
|
|
|
56
62
|
class?: string;
|
|
57
63
|
style?: string;
|
|
58
64
|
}
|
|
59
|
-
declare const TextInputSuggestion: import("svelte").Component<Props, {}, "value">;
|
|
65
|
+
declare const TextInputSuggestion: import("svelte").Component<Props, {}, "value" | "searchBy">;
|
|
60
66
|
type TextInputSuggestion = ReturnType<typeof TextInputSuggestion>;
|
|
61
67
|
export default TextInputSuggestion;
|