refac
This commit is contained in:
1 parent
a9a3e5b95c
commit
e8fda1c7a0
1 file changed
+50
-26
@@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
let triggerEl: HTMLElement | null = null;
|
let triggerEl: HTMLElement | null = null;
|
||||||
let contentEl: HTMLElement | null = null;
|
let contentEl: HTMLElement | null = null;
|
||||||
|
let previouslyFocused: HTMLElement | null = null;
|
||||||
|
let shouldFocusContent = false;
|
||||||
let positionFrame: number | undefined;
|
let positionFrame: number | undefined;
|
||||||
let settleTimers: number[] = [];
|
let settleTimers: number[] = [];
|
||||||
let resolvedMaxHeight = maxHeight;
|
let resolvedMaxHeight = maxHeight;
|
||||||
@@ -226,31 +228,57 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleOpen() {
|
async function afterOpen() {
|
||||||
show = !show;
|
await tick();
|
||||||
onOpenChange(show);
|
positionContent();
|
||||||
|
|
||||||
|
// Re-check after transition renders real dimensions
|
||||||
|
if (visualViewportAware) {
|
||||||
|
scheduleSettledPositionUpdates();
|
||||||
|
} else {
|
||||||
|
setTimeout(positionContent, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldFocusContent) {
|
||||||
|
shouldFocusContent = false;
|
||||||
|
contentEl?.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openDropdown(focusContent = false) {
|
||||||
|
if (show) return;
|
||||||
|
if (focusContent) {
|
||||||
|
previouslyFocused =
|
||||||
|
document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
||||||
|
shouldFocusContent = true;
|
||||||
|
}
|
||||||
|
show = true;
|
||||||
|
onOpenChange(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDropdown(restoreFocus = !!contentEl?.contains(document.activeElement)) {
|
||||||
|
if (!show) return;
|
||||||
|
show = false;
|
||||||
|
onOpenChange(false);
|
||||||
|
shouldFocusContent = false;
|
||||||
|
|
||||||
|
if (restoreFocus && previouslyFocused?.isConnected) {
|
||||||
|
previouslyFocused.focus();
|
||||||
|
}
|
||||||
|
previouslyFocused = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleOpen() {
|
||||||
if (show) {
|
if (show) {
|
||||||
await tick();
|
closeDropdown();
|
||||||
positionContent();
|
} else {
|
||||||
// Re-check after transition renders real dimensions
|
openDropdown(true);
|
||||||
if (visualViewportAware) {
|
|
||||||
scheduleSettledPositionUpdates();
|
|
||||||
} else {
|
|
||||||
setTimeout(positionContent, 50);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// React to external show changes (e.g. bind:show toggled by parent component)
|
// React to external show changes (e.g. bind:show toggled by parent component)
|
||||||
$: if (show) {
|
$: if (show) {
|
||||||
tick().then(() => {
|
afterOpen();
|
||||||
positionContent();
|
|
||||||
if (visualViewportAware) {
|
|
||||||
scheduleSettledPositionUpdates();
|
|
||||||
} else {
|
|
||||||
setTimeout(positionContent, 50);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleWindowPointerDown(event: PointerEvent) {
|
function handleWindowPointerDown(event: PointerEvent) {
|
||||||
@@ -258,21 +286,18 @@
|
|||||||
if (!(event.target instanceof Node)) return;
|
if (!(event.target instanceof Node)) return;
|
||||||
if (triggerEl?.contains(event.target)) return;
|
if (triggerEl?.contains(event.target)) return;
|
||||||
if (contentEl?.contains(event.target)) return;
|
if (contentEl?.contains(event.target)) return;
|
||||||
show = false;
|
closeDropdown(false);
|
||||||
onOpenChange(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeydown(event: KeyboardEvent) {
|
function handleKeydown(event: KeyboardEvent) {
|
||||||
if (event.key === 'Escape' && show) {
|
if (event.key === 'Escape' && show) {
|
||||||
show = false;
|
closeDropdown();
|
||||||
onOpenChange(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Close the dropdown programmatically */
|
/** Close the dropdown programmatically */
|
||||||
export function close() {
|
export function close() {
|
||||||
show = false;
|
closeDropdown();
|
||||||
onOpenChange(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
import { onMount, onDestroy } from 'svelte';
|
import { onMount, onDestroy } from 'svelte';
|
||||||
@@ -317,7 +342,6 @@
|
|||||||
|
|
||||||
{#if show}
|
{#if show}
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
||||||
<div
|
<div
|
||||||
use:portal
|
use:portal
|
||||||
bind:this={contentEl}
|
bind:this={contentEl}
|
||||||
|
|||||||
Reference in new issue
Block a user