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) => {
|
onUpdate={(message, element) => {
|
||||||
return match(message, {
|
return match(message, {
|
||||||
[StackMessage.Add]() {
|
[StackMessage.Add]() {
|
||||||
containers.add(element);
|
containers = new Set([...containers, element]);
|
||||||
},
|
},
|
||||||
[StackMessage.Remove]() {
|
[StackMessage.Remove]() {
|
||||||
containers.delete(element);
|
containers.delete(element);
|
||||||
|
containers = new Set([...containers]);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
FocusResult,
|
FocusResult,
|
||||||
} from "$lib/utils/focus-management";
|
} from "$lib/utils/focus-management";
|
||||||
import { contains } from "$lib/internal/dom-containers";
|
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 containers: Set<HTMLElement>;
|
||||||
export let enabled: boolean = true;
|
export let enabled: boolean = true;
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
// Handle initial focus
|
// Handle initial focus
|
||||||
onMount(handleFocus);
|
onMount(handleFocus);
|
||||||
|
|
||||||
afterUpdate(() => (enabled ? handleFocus() : restore()));
|
$: enabled && containers ? handleFocus() : restore();
|
||||||
|
|
||||||
// When this component is being destroyed, focusElement is called
|
// When this component is being destroyed, focusElement is called
|
||||||
// before handleWindowFocus is removed, so in the svelte port we add this
|
// before handleWindowFocus is removed, so in the svelte port we add this
|
||||||
|
|||||||
@@ -9,24 +9,21 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext, onDestroy, setContext } from "svelte";
|
import { getContext, onDestroy, setContext } from "svelte";
|
||||||
import { Readable, writable, Writable } from "svelte/store";
|
|
||||||
type OnUpdate = (message: StackMessage, element: HTMLElement) => void;
|
type OnUpdate = (message: StackMessage, element: HTMLElement) => void;
|
||||||
|
|
||||||
export let onUpdate: OnUpdate | undefined;
|
export let onUpdate: OnUpdate | undefined;
|
||||||
export let element: HTMLElement | null;
|
export let element: HTMLElement | null;
|
||||||
|
|
||||||
let parentUpdateStore: Readable<OnUpdate> | undefined =
|
function notify(...args: Parameters<OnUpdate>) {
|
||||||
getContext(STACK_CONTEXT_NAME);
|
|
||||||
let notifyStore: Writable<OnUpdate> = writable(() => {});
|
|
||||||
setContext(STACK_CONTEXT_NAME, notifyStore);
|
|
||||||
|
|
||||||
$: notifyStore.set((...args: Parameters<OnUpdate>) => {
|
|
||||||
// Notify our layer
|
// Notify our layer
|
||||||
onUpdate?.(...args);
|
onUpdate?.(...args);
|
||||||
|
|
||||||
// Notify the parent
|
// Notify the parent
|
||||||
$parentUpdateStore?.(...args);
|
parentUpdate?.(...args);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
let parentUpdate: OnUpdate | undefined = getContext(STACK_CONTEXT_NAME);
|
||||||
|
setContext(STACK_CONTEXT_NAME, notify);
|
||||||
|
|
||||||
$: _cleanup = (() => {
|
$: _cleanup = (() => {
|
||||||
if (_cleanup) {
|
if (_cleanup) {
|
||||||
@@ -34,8 +31,8 @@
|
|||||||
}
|
}
|
||||||
if (!element) return null;
|
if (!element) return null;
|
||||||
let savedElement = element;
|
let savedElement = element;
|
||||||
$notifyStore(StackMessage.Add, savedElement);
|
notify(StackMessage.Add, savedElement);
|
||||||
return () => $notifyStore(StackMessage.Remove, savedElement);
|
return () => notify(StackMessage.Remove, savedElement);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user