mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-15 10:21:05 +00:00
refactor(modal): simply nested modals logic (#1339)
Cleans up #1331 to reuse shared logic between `Modal`, `ComposedModal`.
This commit is contained in:
parent
95b32937d6
commit
37aa207c85
3 changed files with 44 additions and 44 deletions
|
@ -38,7 +38,7 @@
|
||||||
afterUpdate,
|
afterUpdate,
|
||||||
} from "svelte";
|
} from "svelte";
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import { modalsOpen, addModalId, removeModalId } from "../Modal/modalStore";
|
import { trackModal } from "../Modal/modalStore";
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
const label = writable(undefined);
|
const label = writable(undefined);
|
||||||
|
@ -46,7 +46,6 @@
|
||||||
let buttonRef = null;
|
let buttonRef = null;
|
||||||
let innerModal = null;
|
let innerModal = null;
|
||||||
let didClickInnerModal = false;
|
let didClickInnerModal = false;
|
||||||
let id = "ccs-" + Math.random().toString(36);
|
|
||||||
|
|
||||||
setContext("ComposedModal", {
|
setContext("ComposedModal", {
|
||||||
closeModal: () => {
|
closeModal: () => {
|
||||||
|
@ -74,15 +73,14 @@
|
||||||
let opened = false;
|
let opened = false;
|
||||||
$: didOpen = open;
|
$: didOpen = open;
|
||||||
|
|
||||||
|
const openStore = writable(open);
|
||||||
|
$: $openStore = open;
|
||||||
|
trackModal(openStore);
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
tick().then(() => {
|
tick().then(() => {
|
||||||
focus();
|
focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
|
||||||
removeModalId(id);
|
|
||||||
document.body.classList.remove("bx--body--with-modal-open");
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterUpdate(() => {
|
afterUpdate(() => {
|
||||||
|
@ -95,19 +93,7 @@
|
||||||
opened = true;
|
opened = true;
|
||||||
dispatch("open");
|
dispatch("open");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($modalsOpen.length > 0) {
|
|
||||||
document.body.classList.add("bx--body--with-modal-open");
|
|
||||||
} else {
|
|
||||||
document.body.classList.remove("bx--body--with-modal-open");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$: if (open) {
|
|
||||||
addModalId(id);
|
|
||||||
} else {
|
|
||||||
removeModalId(id);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||||
|
|
|
@ -89,10 +89,11 @@
|
||||||
/** Obtain a reference to the top-level HTML element */
|
/** Obtain a reference to the top-level HTML element */
|
||||||
export let ref = null;
|
export let ref = null;
|
||||||
|
|
||||||
import { createEventDispatcher, onMount, afterUpdate } from "svelte";
|
import { createEventDispatcher, afterUpdate } from "svelte";
|
||||||
import Close from "../icons/Close.svelte";
|
import Close from "../icons/Close.svelte";
|
||||||
import Button from "../Button/Button.svelte";
|
import Button from "../Button/Button.svelte";
|
||||||
import { modalsOpen, addModalId, removeModalId } from "./modalStore";
|
import { trackModal } from "./modalStore";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
@ -107,12 +108,9 @@
|
||||||
node.focus();
|
node.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
const openStore = writable(open);
|
||||||
return () => {
|
$: $openStore = open;
|
||||||
removeModalId(id);
|
trackModal(openStore);
|
||||||
document.body.classList.remove("bx--body--with-modal-open");
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
afterUpdate(() => {
|
afterUpdate(() => {
|
||||||
if (opened) {
|
if (opened) {
|
||||||
|
@ -125,12 +123,6 @@
|
||||||
focus();
|
focus();
|
||||||
dispatch("open");
|
dispatch("open");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($modalsOpen.length > 0) {
|
|
||||||
document.body.classList.add("bx--body--with-modal-open");
|
|
||||||
} else {
|
|
||||||
document.body.classList.remove("bx--body--with-modal-open");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$: modalLabelId = `bx--modal-header__label--modal-${id}`;
|
$: modalLabelId = `bx--modal-header__label--modal-${id}`;
|
||||||
|
@ -138,12 +130,6 @@
|
||||||
$: modalBodyId = `bx--modal-body--${id}`;
|
$: modalBodyId = `bx--modal-body--${id}`;
|
||||||
$: ariaLabel =
|
$: ariaLabel =
|
||||||
modalLabel || $$props["aria-label"] || modalAriaLabel || modalHeading;
|
modalLabel || $$props["aria-label"] || modalAriaLabel || modalHeading;
|
||||||
|
|
||||||
$: if (open) {
|
|
||||||
addModalId(id);
|
|
||||||
} else {
|
|
||||||
removeModalId(id);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||||
|
|
|
@ -1,8 +1,36 @@
|
||||||
import { writable } from "svelte/store";
|
import { onMount } from "svelte";
|
||||||
|
import { get, writable } from "svelte/store";
|
||||||
|
|
||||||
export const modalsOpen = writable([]);
|
/** A set of stores indicating whether a modal is open. */
|
||||||
|
const stores = new Set();
|
||||||
|
|
||||||
export const addModalId = (id) => modalsOpen.update((ids) => [...ids, id]);
|
/** Store for the number of open modals. */
|
||||||
|
const modalsOpen = writable(0);
|
||||||
|
|
||||||
export const removeModalId = (id) =>
|
const updateModalsOpen = () =>
|
||||||
modalsOpen.update((ids) => ids.filter((_id) => _id !== id));
|
modalsOpen.set([...stores].filter((open) => get(open)).length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a modal's store to the open modal tracking.
|
||||||
|
* Has to be called during component initialization.
|
||||||
|
* Modal is automatically removed on destroy.
|
||||||
|
* @param {import('svelte/store').Readable<boolean>} openStore
|
||||||
|
* Store that indicates whether the modal is opened.
|
||||||
|
*/
|
||||||
|
export const trackModal = (openStore) =>
|
||||||
|
onMount(() => {
|
||||||
|
stores.add(openStore);
|
||||||
|
const unsubscribe = openStore.subscribe(updateModalsOpen);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unsubscribe();
|
||||||
|
stores.delete(openStore);
|
||||||
|
|
||||||
|
updateModalsOpen();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
modalsOpen.subscribe((openCount) => {
|
||||||
|
if (typeof document !== "undefined")
|
||||||
|
document.body.classList.toggle("bx--body--with-modal-open", openCount > 0);
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue