@sveltia/ui 0.10.8 → 0.11.0
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.
- package/package/components/button/button.svelte +1 -0
- package/package/components/button/button.svelte.d.ts +2 -0
- package/package/components/drawer/drawer.svelte +0 -1
- package/package/components/listbox/listbox.svelte +22 -1
- package/package/components/listbox/listbox.svelte.d.ts +4 -0
- package/package/components/listbox/option.svelte +15 -4
- package/package/components/listbox/option.svelte.d.ts +4 -2
- package/package/components/select/combobox.svelte +71 -10
- package/package/components/util/app-shell.svelte +10 -10
- package/package/components/util/modal.svelte +1 -1
- package/package/components/util/popup.svelte +1 -1
- package/package/locales/en.d.ts +2 -0
- package/package/locales/en.js +2 -0
- package/package/locales/ja.d.ts +2 -0
- package/package/locales/ja.js +2 -0
- package/package/services/group.d.ts +1 -1
- package/package/services/group.js +67 -18
- package/package/styles/variables.scss +5 -5
- package/package.json +7 -7
|
@@ -41,6 +41,7 @@ export default class Button extends SvelteComponent<{
|
|
|
41
41
|
keypress: KeyboardEvent;
|
|
42
42
|
focus: FocusEvent;
|
|
43
43
|
blur: FocusEvent;
|
|
44
|
+
toggle: Event;
|
|
44
45
|
select: CustomEvent<any>;
|
|
45
46
|
change: CustomEvent<any>;
|
|
46
47
|
} & {
|
|
@@ -150,6 +151,7 @@ declare const __propDef: {
|
|
|
150
151
|
keypress: KeyboardEvent;
|
|
151
152
|
focus: FocusEvent;
|
|
152
153
|
blur: FocusEvent;
|
|
154
|
+
toggle: Event;
|
|
153
155
|
select: CustomEvent<any>;
|
|
154
156
|
change: CustomEvent<any>;
|
|
155
157
|
} & {
|
|
@@ -46,6 +46,16 @@
|
|
|
46
46
|
* @type {boolean}
|
|
47
47
|
*/
|
|
48
48
|
export let multiple = false;
|
|
49
|
+
/**
|
|
50
|
+
* Search terms to be used to filter the items.
|
|
51
|
+
* @type {string}
|
|
52
|
+
*/
|
|
53
|
+
export let searchTerms = '';
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @type {boolean}
|
|
57
|
+
*/
|
|
58
|
+
let filtered = false;
|
|
49
59
|
|
|
50
60
|
const dispatch = createEventDispatcher();
|
|
51
61
|
</script>
|
|
@@ -53,6 +63,7 @@
|
|
|
53
63
|
<div
|
|
54
64
|
role="listbox"
|
|
55
65
|
class="sui listbox {className}"
|
|
66
|
+
class:filtered
|
|
56
67
|
tabindex={disabled ? -1 : 0}
|
|
57
68
|
hidden={hidden || undefined}
|
|
58
69
|
aria-hidden={hidden}
|
|
@@ -62,11 +73,15 @@
|
|
|
62
73
|
aria-invalid={invalid}
|
|
63
74
|
aria-multiselectable={multiple}
|
|
64
75
|
{...$$restProps}
|
|
65
|
-
use:activateGroup
|
|
76
|
+
use:activateGroup={{ searchTerms }}
|
|
66
77
|
on:click
|
|
67
78
|
on:change={(/** @type {CustomEvent} */ event) => {
|
|
68
79
|
dispatch('change', event.detail);
|
|
69
80
|
}}
|
|
81
|
+
on:filter
|
|
82
|
+
on:filter={(/** @type {CustomEvent} */ { detail: { matched, total } }) => {
|
|
83
|
+
filtered = matched !== total;
|
|
84
|
+
}}
|
|
70
85
|
>
|
|
71
86
|
<div role="none" class="inner" inert={disabled}>
|
|
72
87
|
<slot />
|
|
@@ -113,6 +128,12 @@
|
|
|
113
128
|
[role=listbox]:global(.tabs) :global(.option button[aria-selected="true"]) {
|
|
114
129
|
border-color: var(--sui-primary-accent-color-light);
|
|
115
130
|
}
|
|
131
|
+
[role=listbox].in-combobox:focus-visible {
|
|
132
|
+
outline-color: transparent;
|
|
133
|
+
}
|
|
134
|
+
[role=listbox].filtered :global([role="separator"]) {
|
|
135
|
+
display: none;
|
|
136
|
+
}
|
|
116
137
|
|
|
117
138
|
.inner {
|
|
118
139
|
display: contents;
|
|
@@ -16,8 +16,10 @@ export default class Listbox extends SvelteComponent<{
|
|
|
16
16
|
required?: boolean | undefined;
|
|
17
17
|
hidden?: boolean | undefined;
|
|
18
18
|
readonly?: boolean | undefined;
|
|
19
|
+
searchTerms?: string | undefined;
|
|
19
20
|
}, {
|
|
20
21
|
click: MouseEvent;
|
|
22
|
+
filter: Event | KeyboardEvent | UIEvent | ErrorEvent | AnimationEvent | MouseEvent | InputEvent | FocusEvent | CompositionEvent | ClipboardEvent | DragEvent | FormDataEvent | PointerEvent | ProgressEvent<EventTarget> | SecurityPolicyViolationEvent | SubmitEvent | TouchEvent | TransitionEvent | WheelEvent;
|
|
21
23
|
change: CustomEvent<any>;
|
|
22
24
|
} & {
|
|
23
25
|
[evt: string]: CustomEvent<any>;
|
|
@@ -39,9 +41,11 @@ declare const __propDef: {
|
|
|
39
41
|
required?: boolean | undefined;
|
|
40
42
|
hidden?: boolean | undefined;
|
|
41
43
|
readonly?: boolean | undefined;
|
|
44
|
+
searchTerms?: string | undefined;
|
|
42
45
|
};
|
|
43
46
|
events: {
|
|
44
47
|
click: MouseEvent;
|
|
48
|
+
filter: Event | KeyboardEvent | UIEvent | ErrorEvent | AnimationEvent | MouseEvent | InputEvent | FocusEvent | CompositionEvent | ClipboardEvent | DragEvent | FormDataEvent | PointerEvent | ProgressEvent<EventTarget> | SecurityPolicyViolationEvent | SubmitEvent | TouchEvent | TransitionEvent | WheelEvent;
|
|
45
49
|
change: CustomEvent<any>;
|
|
46
50
|
} & {
|
|
47
51
|
[evt: string]: CustomEvent<any>;
|
|
@@ -31,14 +31,19 @@
|
|
|
31
31
|
export let disabled = false;
|
|
32
32
|
/**
|
|
33
33
|
* Text label displayed on the item.
|
|
34
|
-
* @type {string
|
|
34
|
+
* @type {string}
|
|
35
35
|
*/
|
|
36
|
-
export let label
|
|
36
|
+
export let label;
|
|
37
37
|
/**
|
|
38
38
|
* The `value` attribute on the `<button>` element.
|
|
39
|
-
* @type {string
|
|
39
|
+
* @type {string}
|
|
40
|
+
*/
|
|
41
|
+
export let value = label;
|
|
42
|
+
/**
|
|
43
|
+
* The value to be searched.
|
|
44
|
+
* @type {string}
|
|
40
45
|
*/
|
|
41
|
-
export let
|
|
46
|
+
export let searchValue = label;
|
|
42
47
|
</script>
|
|
43
48
|
|
|
44
49
|
<div role="none" class="sui option {className}" hidden={hidden || undefined}>
|
|
@@ -51,6 +56,8 @@
|
|
|
51
56
|
{hidden}
|
|
52
57
|
{disabled}
|
|
53
58
|
data-type={typeof value}
|
|
59
|
+
data-label={label}
|
|
60
|
+
data-search-value={searchValue}
|
|
54
61
|
{...$$restProps}
|
|
55
62
|
on:click
|
|
56
63
|
on:dblclick
|
|
@@ -65,6 +72,10 @@
|
|
|
65
72
|
on:change={(event) => {
|
|
66
73
|
selected = event.detail.selected;
|
|
67
74
|
}}
|
|
75
|
+
on:toggle={(event) => {
|
|
76
|
+
hidden = /** @type {CustomEvent} */ (event).detail.hidden;
|
|
77
|
+
selected = false;
|
|
78
|
+
}}
|
|
68
79
|
>
|
|
69
80
|
{#if selected}
|
|
70
81
|
<slot name="check-icon">
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export default class Option extends SvelteComponent<{
|
|
10
10
|
[x: string]: any;
|
|
11
|
+
label: string;
|
|
11
12
|
class?: string | undefined;
|
|
12
13
|
disabled?: boolean | undefined;
|
|
13
|
-
label?: string | undefined;
|
|
14
14
|
value?: string | undefined;
|
|
15
15
|
hidden?: boolean | undefined;
|
|
16
16
|
selected?: boolean | undefined;
|
|
17
|
+
searchValue?: string | undefined;
|
|
17
18
|
}, {
|
|
18
19
|
click: MouseEvent;
|
|
19
20
|
dblclick: MouseEvent;
|
|
@@ -45,12 +46,13 @@ import { SvelteComponent } from "svelte";
|
|
|
45
46
|
declare const __propDef: {
|
|
46
47
|
props: {
|
|
47
48
|
[x: string]: any;
|
|
49
|
+
label: string;
|
|
48
50
|
class?: string | undefined;
|
|
49
51
|
disabled?: boolean | undefined;
|
|
50
|
-
label?: string | undefined;
|
|
51
52
|
value?: string | undefined;
|
|
52
53
|
hidden?: boolean | undefined;
|
|
53
54
|
selected?: boolean | undefined;
|
|
55
|
+
searchValue?: string | undefined;
|
|
54
56
|
};
|
|
55
57
|
events: {
|
|
56
58
|
click: MouseEvent;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import Button from '../button/button.svelte';
|
|
14
14
|
import Icon from '../icon/icon.svelte';
|
|
15
15
|
import Listbox from '../listbox/listbox.svelte';
|
|
16
|
+
import SearchBar from '../text-field/search-bar.svelte';
|
|
16
17
|
import TextInput from '../text-field/text-input.svelte';
|
|
17
18
|
import Popup from '../util/popup.svelte';
|
|
18
19
|
|
|
@@ -74,6 +75,12 @@
|
|
|
74
75
|
let isPopupOpen = writable(false);
|
|
75
76
|
/** @type {string} */
|
|
76
77
|
let label = '';
|
|
78
|
+
/** @type {boolean} */
|
|
79
|
+
let showFilter = false;
|
|
80
|
+
/** @type {string} */
|
|
81
|
+
let searchTerms = '';
|
|
82
|
+
/** @type {boolean} */
|
|
83
|
+
let hasMatchingOptions = true;
|
|
77
84
|
|
|
78
85
|
/**
|
|
79
86
|
* Update the {@link label} and selected option when the {@link value} is changed.
|
|
@@ -86,7 +93,7 @@
|
|
|
86
93
|
);
|
|
87
94
|
|
|
88
95
|
if (target) {
|
|
89
|
-
label = target.
|
|
96
|
+
label = target.dataset.label || target.textContent || target.value;
|
|
90
97
|
|
|
91
98
|
if (selected !== target) {
|
|
92
99
|
selected?.setAttribute('aria-selected', 'false');
|
|
@@ -200,16 +207,49 @@
|
|
|
200
207
|
touchOptimized={true}
|
|
201
208
|
bind:open={isPopupOpen}
|
|
202
209
|
bind:this={popupComponent}
|
|
210
|
+
on:open={() => {
|
|
211
|
+
showFilter = (popupComponent?.content?.querySelectorAll('[role="option"]')?.length ?? 0) > 5;
|
|
212
|
+
searchTerms = '';
|
|
213
|
+
}}
|
|
203
214
|
>
|
|
204
|
-
<
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
215
|
+
<div role="none" class="combobox-inner">
|
|
216
|
+
{#if showFilter}
|
|
217
|
+
<SearchBar
|
|
218
|
+
flex
|
|
219
|
+
aria-label={$_('_sui.combobox.filter_options')}
|
|
220
|
+
aria-controls="{id}-listbox"
|
|
221
|
+
bind:value={searchTerms}
|
|
222
|
+
on:keydown={(event) => {
|
|
223
|
+
if (['ArrowUp', 'ArrowDown', 'Enter'].includes(event.key)) {
|
|
224
|
+
event.preventDefault();
|
|
225
|
+
popupComponent?.content
|
|
226
|
+
?.querySelector('.sui.listbox')
|
|
227
|
+
?.dispatchEvent(new KeyboardEvent('keydown', event));
|
|
228
|
+
}
|
|
229
|
+
}}
|
|
230
|
+
/>
|
|
231
|
+
{/if}
|
|
232
|
+
<Listbox
|
|
233
|
+
id="{id}-listbox"
|
|
234
|
+
class="in-combobox"
|
|
235
|
+
{searchTerms}
|
|
236
|
+
on:click={(event) => {
|
|
237
|
+
if (/** @type {HTMLElement} */ (event.target).matches('[role="option"]')) {
|
|
238
|
+
onSelect(/** @type {HTMLButtonElement} */ (event.target));
|
|
239
|
+
}
|
|
240
|
+
}}
|
|
241
|
+
on:filter={(event) => {
|
|
242
|
+
hasMatchingOptions = !!(/** @type {CustomEvent} */ (event).detail.matched);
|
|
243
|
+
}}
|
|
244
|
+
>
|
|
245
|
+
<slot />
|
|
246
|
+
</Listbox>
|
|
247
|
+
{#if !hasMatchingOptions}
|
|
248
|
+
<div role="alert" class="no-options">
|
|
249
|
+
{$_('_sui.combobox.no_matching_options')}
|
|
250
|
+
</div>
|
|
251
|
+
{/if}
|
|
252
|
+
</div>
|
|
213
253
|
</Popup>
|
|
214
254
|
|
|
215
255
|
<style>.combobox {
|
|
@@ -297,4 +337,25 @@
|
|
|
297
337
|
.combobox + :global([role="listbox"]:not(.open)) {
|
|
298
338
|
opacity: 0;
|
|
299
339
|
pointer-events: none;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.combobox-inner {
|
|
343
|
+
display: flex;
|
|
344
|
+
flex-direction: column;
|
|
345
|
+
overflow: hidden;
|
|
346
|
+
}
|
|
347
|
+
.combobox-inner :global(.sui.search-bar) {
|
|
348
|
+
flex: none;
|
|
349
|
+
}
|
|
350
|
+
.combobox-inner :global(.sui.listbox) {
|
|
351
|
+
flex: auto;
|
|
352
|
+
overflow-y: auto;
|
|
353
|
+
}
|
|
354
|
+
.combobox-inner .no-options {
|
|
355
|
+
flex: none;
|
|
356
|
+
display: flex;
|
|
357
|
+
align-items: center;
|
|
358
|
+
padding: var(--sui-option-padding);
|
|
359
|
+
height: var(--sui-option-height);
|
|
360
|
+
color: var(--sui-tertiary-foreground-color);
|
|
300
361
|
}</style>
|
|
@@ -268,10 +268,10 @@
|
|
|
268
268
|
--sui-background-color-2-hsl: var(--sui-base-hue) 5% 98%;
|
|
269
269
|
--sui-background-color-3-hsl: var(--sui-base-hue) 5% 96%;
|
|
270
270
|
--sui-background-color-4-hsl: var(--sui-base-hue) 5% 94%;
|
|
271
|
-
--sui-background-color-5-hsl: var(--sui-base-hue) 5%
|
|
272
|
-
--sui-border-color-1-hsl: var(--sui-base-hue) 5%
|
|
273
|
-
--sui-border-color-2-hsl: var(--sui-base-hue) 5%
|
|
274
|
-
--sui-border-color-3-hsl: var(--sui-base-hue) 5%
|
|
271
|
+
--sui-background-color-5-hsl: var(--sui-base-hue) 5% 84%;
|
|
272
|
+
--sui-border-color-1-hsl: var(--sui-base-hue) 5% 65%;
|
|
273
|
+
--sui-border-color-2-hsl: var(--sui-base-hue) 5% 84%;
|
|
274
|
+
--sui-border-color-3-hsl: var(--sui-base-hue) 5% 88%;
|
|
275
275
|
--sui-shadow-color: var(--sui-base-hue) 10% 0%;
|
|
276
276
|
--sui-primary-accent-color-text: hsl(var(--sui-base-hue) 80% 40%);
|
|
277
277
|
--sui-primary-accent-color-light: hsl(var(--sui-base-hue) 80% 45%);
|
|
@@ -303,7 +303,7 @@
|
|
|
303
303
|
--sui-background-color-3-hsl: var(--sui-base-hue) 10% 14%;
|
|
304
304
|
--sui-background-color-4-hsl: var(--sui-base-hue) 10% 16%;
|
|
305
305
|
--sui-background-color-5-hsl: var(--sui-base-hue) 10% 26%;
|
|
306
|
-
--sui-border-color-1-hsl: var(--sui-base-hue) 10%
|
|
306
|
+
--sui-border-color-1-hsl: var(--sui-base-hue) 10% 45%;
|
|
307
307
|
--sui-border-color-2-hsl: var(--sui-base-hue) 10% 26%;
|
|
308
308
|
--sui-border-color-3-hsl: var(--sui-base-hue) 10% 22%;
|
|
309
309
|
--sui-shadow-color: var(--sui-base-hue) 10% 0%;
|
|
@@ -337,10 +337,10 @@
|
|
|
337
337
|
--sui-background-color-2-hsl: var(--sui-base-hue) 5% 98%;
|
|
338
338
|
--sui-background-color-3-hsl: var(--sui-base-hue) 5% 96%;
|
|
339
339
|
--sui-background-color-4-hsl: var(--sui-base-hue) 5% 94%;
|
|
340
|
-
--sui-background-color-5-hsl: var(--sui-base-hue) 5%
|
|
341
|
-
--sui-border-color-1-hsl: var(--sui-base-hue) 5%
|
|
342
|
-
--sui-border-color-2-hsl: var(--sui-base-hue) 5%
|
|
343
|
-
--sui-border-color-3-hsl: var(--sui-base-hue) 5%
|
|
340
|
+
--sui-background-color-5-hsl: var(--sui-base-hue) 5% 84%;
|
|
341
|
+
--sui-border-color-1-hsl: var(--sui-base-hue) 5% 65%;
|
|
342
|
+
--sui-border-color-2-hsl: var(--sui-base-hue) 5% 84%;
|
|
343
|
+
--sui-border-color-3-hsl: var(--sui-base-hue) 5% 88%;
|
|
344
344
|
--sui-shadow-color: var(--sui-base-hue) 10% 0%;
|
|
345
345
|
--sui-primary-accent-color-text: hsl(var(--sui-base-hue) 80% 40%);
|
|
346
346
|
--sui-primary-accent-color-light: hsl(var(--sui-base-hue) 80% 45%);
|
|
@@ -374,7 +374,7 @@
|
|
|
374
374
|
--sui-background-color-3-hsl: var(--sui-base-hue) 10% 14%;
|
|
375
375
|
--sui-background-color-4-hsl: var(--sui-base-hue) 10% 16%;
|
|
376
376
|
--sui-background-color-5-hsl: var(--sui-base-hue) 10% 26%;
|
|
377
|
-
--sui-border-color-1-hsl: var(--sui-base-hue) 10%
|
|
377
|
+
--sui-border-color-1-hsl: var(--sui-base-hue) 10% 45%;
|
|
378
378
|
--sui-border-color-2-hsl: var(--sui-base-hue) 10% 26%;
|
|
379
379
|
--sui-border-color-3-hsl: var(--sui-base-hue) 10% 22%;
|
|
380
380
|
--sui-shadow-color: var(--sui-base-hue) 10% 0%;
|
package/package/locales/en.d.ts
CHANGED
package/package/locales/en.js
CHANGED
package/package/locales/ja.d.ts
CHANGED
package/package/locales/ja.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function activateGroup(parent: HTMLElement):
|
|
1
|
+
export function activateGroup(parent: HTMLElement, _params?: object | undefined): import('svelte/action').ActionReturn;
|
|
@@ -75,7 +75,18 @@ class Group {
|
|
|
75
75
|
this.childSelectedProp = childSelectedAttr.replace('aria-', '');
|
|
76
76
|
this.focusChild = focusChild;
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
// Wait a bit before the relevant components, including the `aria-controls` target are mounted
|
|
79
|
+
(async () => {
|
|
80
|
+
await sleep(100);
|
|
81
|
+
this.activate();
|
|
82
|
+
})();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Activate the members.
|
|
87
|
+
*/
|
|
88
|
+
activate() {
|
|
89
|
+
const { parent, allMembers, selected: defaultSelected } = this;
|
|
79
90
|
|
|
80
91
|
allMembers.forEach((element, index) => {
|
|
81
92
|
// Select the first one if no member has the `selected` attribute
|
|
@@ -340,9 +351,10 @@ class Group {
|
|
|
340
351
|
const target = /** @type {HTMLElement} */ (event.target);
|
|
341
352
|
const { allMembers, activeMembers } = this;
|
|
342
353
|
|
|
354
|
+
/** @type {HTMLElement | undefined} */
|
|
343
355
|
const currentTarget = (() => {
|
|
344
356
|
if (!this.focusChild) {
|
|
345
|
-
return activeMembers.find((member) => member.matches('.focused'))
|
|
357
|
+
return activeMembers.find((member) => member.matches('.focused'));
|
|
346
358
|
}
|
|
347
359
|
|
|
348
360
|
if (target.matches(this.selector)) {
|
|
@@ -352,22 +364,20 @@ class Group {
|
|
|
352
364
|
return undefined;
|
|
353
365
|
})();
|
|
354
366
|
|
|
355
|
-
if (!currentTarget) {
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
367
|
if (['Enter', ' ', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)) {
|
|
360
368
|
event.preventDefault();
|
|
361
369
|
}
|
|
362
370
|
|
|
363
371
|
if (key === 'Enter') {
|
|
364
|
-
currentTarget
|
|
372
|
+
currentTarget?.click(); // Also close the popup if needed
|
|
365
373
|
|
|
366
374
|
return;
|
|
367
375
|
}
|
|
368
376
|
|
|
369
377
|
if (key === ' ') {
|
|
370
|
-
|
|
378
|
+
if (currentTarget) {
|
|
379
|
+
this.selectTarget(event, currentTarget);
|
|
380
|
+
}
|
|
371
381
|
|
|
372
382
|
return;
|
|
373
383
|
}
|
|
@@ -376,9 +386,9 @@ class Group {
|
|
|
376
386
|
let newTarget;
|
|
377
387
|
|
|
378
388
|
if (this.grid) {
|
|
379
|
-
const colCount = Math.floor(this.parent.clientWidth /
|
|
389
|
+
const colCount = Math.floor(this.parent.clientWidth / activeMembers[0].clientWidth);
|
|
380
390
|
|
|
381
|
-
index = allMembers.indexOf(currentTarget);
|
|
391
|
+
index = currentTarget ? allMembers.indexOf(currentTarget) : -1;
|
|
382
392
|
|
|
383
393
|
if (key === 'ArrowUp' && index > 0) {
|
|
384
394
|
newTarget = allMembers[index - colCount];
|
|
@@ -400,7 +410,7 @@ class Group {
|
|
|
400
410
|
newTarget = undefined;
|
|
401
411
|
}
|
|
402
412
|
} else {
|
|
403
|
-
index = activeMembers.indexOf(currentTarget);
|
|
413
|
+
index = currentTarget ? activeMembers.indexOf(currentTarget) : -1;
|
|
404
414
|
|
|
405
415
|
if (key === (this.orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp')) {
|
|
406
416
|
if (index > 0) {
|
|
@@ -431,17 +441,56 @@ class Group {
|
|
|
431
441
|
this.selectTarget(event, newTarget);
|
|
432
442
|
}
|
|
433
443
|
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Called whenever the params are updated. Filter the items based on the search terms.
|
|
447
|
+
* @param {{ searchTerms: string }} params - Updated params.
|
|
448
|
+
*/
|
|
449
|
+
onUpdate({ searchTerms }) {
|
|
450
|
+
const terms = searchTerms.trim().toLocaleLowerCase();
|
|
451
|
+
const _terms = terms ? terms.split(/\s+/) : [];
|
|
452
|
+
|
|
453
|
+
const matched = this.allMembers
|
|
454
|
+
.map((member) => {
|
|
455
|
+
const searchValue =
|
|
456
|
+
(
|
|
457
|
+
member.dataset.searchValue ??
|
|
458
|
+
member.dataset.label ??
|
|
459
|
+
member.querySelector('.label')?.textContent ??
|
|
460
|
+
member.textContent
|
|
461
|
+
)?.toLocaleLowerCase() ?? '';
|
|
462
|
+
|
|
463
|
+
const hidden = !_terms.every((term) => searchValue.includes(term));
|
|
464
|
+
|
|
465
|
+
member.dispatchEvent(new CustomEvent('toggle', { detail: { hidden } }));
|
|
466
|
+
|
|
467
|
+
return hidden;
|
|
468
|
+
})
|
|
469
|
+
.filter((hidden) => !hidden).length;
|
|
470
|
+
|
|
471
|
+
this.parent.dispatchEvent(
|
|
472
|
+
new CustomEvent('filter', { detail: { matched, total: this.allMembers.length } }),
|
|
473
|
+
);
|
|
474
|
+
}
|
|
434
475
|
}
|
|
435
476
|
|
|
436
477
|
/**
|
|
437
478
|
* Activate a new group.
|
|
438
479
|
* @param {HTMLElement} parent - Parent element.
|
|
480
|
+
* @param {object} [_params] - Action params.
|
|
481
|
+
* @returns {import('svelte/action').ActionReturn} Action.
|
|
439
482
|
*/
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
483
|
+
// eslint-disable-next-line no-unused-vars
|
|
484
|
+
export const activateGroup = (parent, _params) => {
|
|
485
|
+
const group = new Group(parent);
|
|
486
|
+
|
|
487
|
+
return {
|
|
488
|
+
/**
|
|
489
|
+
* Called whenever the params are updated.
|
|
490
|
+
* @param {any} params - Updated params.
|
|
491
|
+
*/
|
|
492
|
+
update(params) {
|
|
493
|
+
group.onUpdate(params);
|
|
494
|
+
},
|
|
495
|
+
};
|
|
447
496
|
};
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
--sui-background-color-2-hsl: var(--sui-base-hue) 5% 98%; // primary
|
|
10
10
|
--sui-background-color-3-hsl: var(--sui-base-hue) 5% 96%; // secondary
|
|
11
11
|
--sui-background-color-4-hsl: var(--sui-base-hue) 5% 94%; // tertiary/disabled
|
|
12
|
-
--sui-background-color-5-hsl: var(--sui-base-hue) 5%
|
|
13
|
-
--sui-border-color-1-hsl: var(--sui-base-hue) 5%
|
|
14
|
-
--sui-border-color-2-hsl: var(--sui-base-hue) 5%
|
|
15
|
-
--sui-border-color-3-hsl: var(--sui-base-hue) 5%
|
|
12
|
+
--sui-background-color-5-hsl: var(--sui-base-hue) 5% 84%; // highlight
|
|
13
|
+
--sui-border-color-1-hsl: var(--sui-base-hue) 5% 65%; // control
|
|
14
|
+
--sui-border-color-2-hsl: var(--sui-base-hue) 5% 84%; // primary
|
|
15
|
+
--sui-border-color-3-hsl: var(--sui-base-hue) 5% 88%; // secondary
|
|
16
16
|
--sui-shadow-color: var(--sui-base-hue) 10% 0%;
|
|
17
17
|
// Accents
|
|
18
18
|
--sui-primary-accent-color-text: hsl(var(--sui-base-hue) 80% 40%);
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
--sui-background-color-3-hsl: var(--sui-base-hue) 10% 14%; // secondary
|
|
47
47
|
--sui-background-color-4-hsl: var(--sui-base-hue) 10% 16%; // tertiary/disabled
|
|
48
48
|
--sui-background-color-5-hsl: var(--sui-base-hue) 10% 26%; // highlight
|
|
49
|
-
--sui-border-color-1-hsl: var(--sui-base-hue) 10%
|
|
49
|
+
--sui-border-color-1-hsl: var(--sui-base-hue) 10% 45%; // control
|
|
50
50
|
--sui-border-color-2-hsl: var(--sui-base-hue) 10% 26%; // primary
|
|
51
51
|
--sui-border-color-3-hsl: var(--sui-base-hue) 10% 22%; // secondary
|
|
52
52
|
--sui-shadow-color: var(--sui-base-hue) 10% 0%;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltia/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -26,32 +26,32 @@
|
|
|
26
26
|
"svelte": "^4.2.12"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@playwright/test": "^1.
|
|
29
|
+
"@playwright/test": "^1.43.0",
|
|
30
30
|
"@sveltejs/adapter-auto": "^3.2.0",
|
|
31
31
|
"@sveltejs/kit": "^2.5.5",
|
|
32
|
-
"@sveltejs/package": "^2.3.
|
|
32
|
+
"@sveltejs/package": "^2.3.1",
|
|
33
33
|
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
|
34
34
|
"cspell": "^8.6.1",
|
|
35
35
|
"eslint": "^8.57.0",
|
|
36
36
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
37
37
|
"eslint-config-prettier": "^9.1.0",
|
|
38
38
|
"eslint-plugin-import": "^2.29.1",
|
|
39
|
-
"eslint-plugin-jsdoc": "^48.2.
|
|
39
|
+
"eslint-plugin-jsdoc": "^48.2.3",
|
|
40
40
|
"eslint-plugin-svelte": "^2.35.1",
|
|
41
41
|
"npm-run-all": "^4.1.5",
|
|
42
42
|
"postcss": "^8.4.38",
|
|
43
43
|
"postcss-html": "^1.6.0",
|
|
44
44
|
"prettier": "^3.2.5",
|
|
45
45
|
"prettier-plugin-svelte": "^3.2.2",
|
|
46
|
-
"sass": "^1.
|
|
46
|
+
"sass": "^1.74.1",
|
|
47
47
|
"stylelint": "^16.3.1",
|
|
48
48
|
"stylelint-config-recommended-scss": "^14.0.0",
|
|
49
49
|
"stylelint-scss": "^6.2.1",
|
|
50
|
-
"svelte-check": "^3.6.
|
|
50
|
+
"svelte-check": "^3.6.9",
|
|
51
51
|
"svelte-i18n": "^4.0.0",
|
|
52
52
|
"svelte-preprocess": "^5.1.3",
|
|
53
53
|
"tslib": "^2.6.2",
|
|
54
|
-
"vite": "^5.2.
|
|
54
|
+
"vite": "^5.2.8",
|
|
55
55
|
"vitest": "^1.4.0"
|
|
56
56
|
},
|
|
57
57
|
"exports": {
|