Fixes to issues with Dialog, FocusTrap, and StackContextProvider
* StackContextProvider had some reactivity that didn't make sense and would cause an infinite loop if it ever triggered. * FocusTrap and Dialog did not work together properly all of the time. A top-level <Dialog> with initial state of closed would not have the FocusTrap triggered correctly when it was opened. Needed to make it reactive to changes in `containers`
This commit is contained in:
@@ -253,10 +253,11 @@
|
||||
onUpdate={(message, element) => {
|
||||
return match(message, {
|
||||
[StackMessage.Add]() {
|
||||
containers.add(element);
|
||||
containers = new Set([...containers, element]);
|
||||
},
|
||||
[StackMessage.Remove]() {
|
||||
containers.delete(element);
|
||||
containers = new Set([...containers]);
|
||||
},
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
FocusResult,
|
||||
} from "$lib/utils/focus-management";
|
||||
import { contains } from "$lib/internal/dom-containers";
|
||||
import { afterUpdate, onMount, onDestroy, tick } from "svelte";
|
||||
import { onMount, onDestroy, tick } from "svelte";
|
||||
|
||||
export let containers: Set<HTMLElement>;
|
||||
export let enabled: boolean = true;
|
||||
@@ -74,7 +74,7 @@
|
||||
// Handle initial focus
|
||||
onMount(handleFocus);
|
||||
|
||||
afterUpdate(() => (enabled ? handleFocus() : restore()));
|
||||
$: enabled && containers ? handleFocus() : restore();
|
||||
|
||||
// When this component is being destroyed, focusElement is called
|
||||
// before handleWindowFocus is removed, so in the svelte port we add this
|
||||
|
||||
@@ -9,24 +9,21 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { getContext, onDestroy, setContext } from "svelte";
|
||||
import { Readable, writable, Writable } from "svelte/store";
|
||||
type OnUpdate = (message: StackMessage, element: HTMLElement) => void;
|
||||
|
||||
export let onUpdate: OnUpdate | undefined;
|
||||
export let element: HTMLElement | null;
|
||||
|
||||
let parentUpdateStore: Readable<OnUpdate> | undefined =
|
||||
getContext(STACK_CONTEXT_NAME);
|
||||
let notifyStore: Writable<OnUpdate> = writable(() => {});
|
||||
setContext(STACK_CONTEXT_NAME, notifyStore);
|
||||
|
||||
$: notifyStore.set((...args: Parameters<OnUpdate>) => {
|
||||
function notify(...args: Parameters<OnUpdate>) {
|
||||
// Notify our layer
|
||||
onUpdate?.(...args);
|
||||
|
||||
// Notify the parent
|
||||
$parentUpdateStore?.(...args);
|
||||
});
|
||||
parentUpdate?.(...args);
|
||||
}
|
||||
|
||||
let parentUpdate: OnUpdate | undefined = getContext(STACK_CONTEXT_NAME);
|
||||
setContext(STACK_CONTEXT_NAME, notify);
|
||||
|
||||
$: _cleanup = (() => {
|
||||
if (_cleanup) {
|
||||
@@ -34,8 +31,8 @@
|
||||
}
|
||||
if (!element) return null;
|
||||
let savedElement = element;
|
||||
$notifyStore(StackMessage.Add, savedElement);
|
||||
return () => $notifyStore(StackMessage.Remove, savedElement);
|
||||
notify(StackMessage.Add, savedElement);
|
||||
return () => notify(StackMessage.Remove, savedElement);
|
||||
})();
|
||||
|
||||
onDestroy(() => {
|
||||
|
||||
Reference in New Issue
Block a user