@human-kit/svelte-components 1.0.0-alpha.12 → 1.0.0-alpha.13
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/dist/combobox/input/combobox-input.svelte +1 -0
- package/dist/combobox/list/combobox-listbox.svelte +1 -0
- package/dist/combobox/list/combobox-listbox.svelte.d.ts +1 -0
- package/dist/combobox/root/combobox-test.svelte +8 -2
- package/dist/combobox/root/combobox-test.svelte.d.ts +1 -0
- package/dist/combobox/root/combobox.svelte +15 -9
- package/dist/listbox/item/listbox-item.svelte +11 -2
- package/dist/listbox/root/listbox.svelte +7 -1
- package/dist/listbox/root/listbox.svelte.d.ts +2 -0
- package/package.json +1 -1
|
@@ -14,6 +14,7 @@ declare function $$render<T extends object = object>(): {
|
|
|
14
14
|
id?: string;
|
|
15
15
|
'aria-label'?: string;
|
|
16
16
|
onChange?: ((value: Set<string | number>) => void) | undefined;
|
|
17
|
+
disableFocusHandling?: boolean;
|
|
17
18
|
} & {
|
|
18
19
|
context?: ListBoxContext;
|
|
19
20
|
element?: HTMLElement;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
isPending?: boolean;
|
|
8
8
|
isReadOnly?: boolean;
|
|
9
9
|
trigger?: 'focus' | 'input' | 'press';
|
|
10
|
+
disabledIds?: string[];
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
let {
|
|
@@ -14,7 +15,8 @@
|
|
|
14
15
|
isDisabled = false,
|
|
15
16
|
isPending = false,
|
|
16
17
|
isReadOnly = false,
|
|
17
|
-
trigger = 'press'
|
|
18
|
+
trigger = 'press',
|
|
19
|
+
disabledIds = []
|
|
18
20
|
}: Props = $props();
|
|
19
21
|
|
|
20
22
|
let selectedValue = $state<string | number | undefined>();
|
|
@@ -40,7 +42,11 @@
|
|
|
40
42
|
<ComboBox.Popover>
|
|
41
43
|
<ComboBox.List emptyPlaceholder="No countries found">
|
|
42
44
|
{#each countries as country (country.id)}
|
|
43
|
-
<ComboBox.Item
|
|
45
|
+
<ComboBox.Item
|
|
46
|
+
id={country.id}
|
|
47
|
+
textValue={country.name}
|
|
48
|
+
disabled={disabledIds.includes(country.id)}
|
|
49
|
+
>
|
|
44
50
|
{country.name}
|
|
45
51
|
</ComboBox.Item>
|
|
46
52
|
{/each}
|
|
@@ -211,6 +211,15 @@
|
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
+
function syncInputValue(val: string, options?: { notifyInputChange?: boolean }) {
|
|
215
|
+
inputValueInternal = val;
|
|
216
|
+
inputValue = val;
|
|
217
|
+
|
|
218
|
+
if (options?.notifyInputChange ?? true) {
|
|
219
|
+
onInputChange?.(val);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
214
223
|
function selectItem(id: string | number, label: string) {
|
|
215
224
|
let newSelection: Set<string | number>;
|
|
216
225
|
|
|
@@ -218,10 +227,9 @@
|
|
|
218
227
|
newSelection = new Set([id]);
|
|
219
228
|
// Save the label persistently for restore on blur/escape
|
|
220
229
|
selectedLabel = label;
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
onInputChange?.(label);
|
|
230
|
+
// Keep the selected label visible in the input without re-triggering
|
|
231
|
+
// external filtering during the popover close animation.
|
|
232
|
+
syncInputValue(label, { notifyInputChange: false });
|
|
225
233
|
if (effectiveCloseOnSelect) {
|
|
226
234
|
closePopover(true); // Close and keep focus on input
|
|
227
235
|
}
|
|
@@ -318,6 +326,8 @@
|
|
|
318
326
|
onInputChange?.('');
|
|
319
327
|
}
|
|
320
328
|
// Otherwise user typed, keep their filter
|
|
329
|
+
} else {
|
|
330
|
+
shouldFilter = true;
|
|
321
331
|
}
|
|
322
332
|
setIsOpen(true);
|
|
323
333
|
// Auto-focus the selected item when opening with a selection
|
|
@@ -333,8 +343,6 @@
|
|
|
333
343
|
setIsOpen(false);
|
|
334
344
|
// Reset navigation state
|
|
335
345
|
navigation.reset();
|
|
336
|
-
// Re-enable filtering for next open
|
|
337
|
-
shouldFilter = true;
|
|
338
346
|
// Only refocus input when explicitly requested (e.g., after selection)
|
|
339
347
|
// Never refocus in focus mode to prevent re-opening
|
|
340
348
|
if (refocusInput && trigger !== 'focus') {
|
|
@@ -442,9 +450,7 @@
|
|
|
442
450
|
if (currentSelection.size > 0 && selectedLabel) {
|
|
443
451
|
if (selectedLabel !== currentInputValue) {
|
|
444
452
|
// Restore the selected label
|
|
445
|
-
|
|
446
|
-
inputValue = selectedLabel;
|
|
447
|
-
onInputChange?.(selectedLabel);
|
|
453
|
+
syncInputValue(selectedLabel, { notifyInputChange: false });
|
|
448
454
|
}
|
|
449
455
|
}
|
|
450
456
|
}
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
|
|
146
146
|
// Scroll into view when focused (if enabled)
|
|
147
147
|
$effect(() => {
|
|
148
|
-
if (scrollOnFocus && isFocusedComputed && elementRef) {
|
|
148
|
+
if (scrollOnFocus && isFocusedComputed && isFocusVisibleComputed && elementRef) {
|
|
149
149
|
requestAnimationFrame(() => {
|
|
150
150
|
elementRef?.scrollIntoView({ block: 'nearest' });
|
|
151
151
|
});
|
|
@@ -193,6 +193,15 @@
|
|
|
193
193
|
|
|
194
194
|
const label = getResolvedTextValue();
|
|
195
195
|
|
|
196
|
+
if (!disableFocusHandling && elementRef) {
|
|
197
|
+
suppressNextFocusVisible = true;
|
|
198
|
+
isFocusVisible = false;
|
|
199
|
+
listboxCtx.setFocusVisible(false);
|
|
200
|
+
listboxCtx.setFocusedId(id);
|
|
201
|
+
listboxCtx.keyboardNav.setCurrentId(id);
|
|
202
|
+
focusWithModality(elementRef, 'pointer');
|
|
203
|
+
}
|
|
204
|
+
|
|
196
205
|
// Use custom select handler if provided, otherwise use listbox default
|
|
197
206
|
if (onItemSelect) {
|
|
198
207
|
onItemSelect(id, label);
|
|
@@ -201,7 +210,7 @@
|
|
|
201
210
|
}
|
|
202
211
|
|
|
203
212
|
if (!disableFocusHandling) {
|
|
204
|
-
listboxCtx.keyboardNav.
|
|
213
|
+
listboxCtx.keyboardNav.setCurrentId(id);
|
|
205
214
|
}
|
|
206
215
|
}
|
|
207
216
|
|
|
@@ -32,6 +32,8 @@
|
|
|
32
32
|
'aria-label'?: string;
|
|
33
33
|
/** Callback fired when the selection changes. */
|
|
34
34
|
onChange?: (value: Set<string | number>) => void;
|
|
35
|
+
/** Disable DOM focus handling on the root container for virtual-focus compositions. */
|
|
36
|
+
disableFocusHandling?: boolean;
|
|
35
37
|
};
|
|
36
38
|
|
|
37
39
|
let {
|
|
@@ -47,6 +49,7 @@
|
|
|
47
49
|
id,
|
|
48
50
|
'aria-label': ariaLabel,
|
|
49
51
|
onChange,
|
|
52
|
+
disableFocusHandling = false,
|
|
50
53
|
context = $bindable(),
|
|
51
54
|
element = $bindable()
|
|
52
55
|
}: ListBoxProps & { context?: ListBoxContext; element?: HTMLElement } = $props();
|
|
@@ -136,6 +139,9 @@
|
|
|
136
139
|
function handleMouseDown(event: MouseEvent) {
|
|
137
140
|
trackInteractionModality(event, event.target as HTMLElement | null);
|
|
138
141
|
ctx.setFocusVisible(false);
|
|
142
|
+
if (disableFocusHandling) {
|
|
143
|
+
event.preventDefault();
|
|
144
|
+
}
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
function handleKeyDown(event: KeyboardEvent) {
|
|
@@ -153,7 +159,7 @@
|
|
|
153
159
|
aria-multiselectable={selectionMode === 'multiple'}
|
|
154
160
|
aria-label={ariaLabel}
|
|
155
161
|
class={className}
|
|
156
|
-
tabindex=
|
|
162
|
+
tabindex={disableFocusHandling ? undefined : 0}
|
|
157
163
|
data-focus-within={focusWithin || undefined}
|
|
158
164
|
use:keyboardAction
|
|
159
165
|
onfocusin={handleFocusIn}
|
|
@@ -26,6 +26,8 @@ declare function $$render<T extends object = object>(): {
|
|
|
26
26
|
'aria-label'?: string;
|
|
27
27
|
/** Callback fired when the selection changes. */
|
|
28
28
|
onChange?: (value: Set<string | number>) => void;
|
|
29
|
+
/** Disable DOM focus handling on the root container for virtual-focus compositions. */
|
|
30
|
+
disableFocusHandling?: boolean;
|
|
29
31
|
} & {
|
|
30
32
|
context?: ListBoxContext;
|
|
31
33
|
element?: HTMLElement;
|