@monstermann/signals-modal 0.2.1 → 0.3.1

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.
@@ -5,6 +5,7 @@ import { MaybeDispose } from "@monstermann/signals";
5
5
  interface ModalContext {
6
6
  key: string;
7
7
  dispose: () => void;
8
+ isDisposed: () => boolean;
8
9
  onDispose: (dispose: MaybeDispose) => void;
9
10
  }
10
11
  declare const onModalDisposed: _monstermann_signals0.Emitter<string>;
@@ -1,12 +1,12 @@
1
1
  import { onModalClosed } from "./status/onModalClosed.js";
2
2
  import { closeModal } from "./status/closeModal.js";
3
3
  import { isModalClosed } from "./status/isModalClosed.js";
4
- import { SILENT, context, disposer, emitter } from "@monstermann/signals";
4
+ import { SILENT, context, disposer, emitter, isDisposed } from "@monstermann/signals";
5
5
 
6
6
  //#region src/createModal.ts
7
7
  const meta = {
8
8
  path: "@signals-modal/createModal.ts",
9
- line: 15,
9
+ line: 16,
10
10
  name: "onModalDisposed"
11
11
  };
12
12
  const modalCtx = context();
@@ -21,6 +21,7 @@ function createModal(key, setup) {
21
21
  const nextCtx = {
22
22
  key,
23
23
  onDispose: dispose,
24
+ isDisposed: () => isDisposed(dispose),
24
25
  dispose() {
25
26
  if (isModalClosed(key)) {
26
27
  dispose();
package/dist/index.d.ts CHANGED
@@ -27,6 +27,7 @@ import { getModalPlacement } from "./position/getModalPlacement.js";
27
27
  import { ModalPosition, withPosition } from "./position/withPosition.js";
28
28
  import { getModalPosition } from "./position/getModalPosition.js";
29
29
  import { withBoundary } from "./position/withBoundary.js";
30
+ import { withCloseOnScroll } from "./scroll/withCloseOnScroll.js";
30
31
  import { closeAllModals } from "./status/closeAllModals.js";
31
32
  import { closeLastModal } from "./status/closeLastModal.js";
32
33
  import { closeModal } from "./status/closeModal.js";
@@ -59,4 +60,4 @@ import { withModalStatus } from "./status/withModalStatus.js";
59
60
  import { closeLastModalOnClickOutside } from "./utils/closeLastModalOnClickOutside.js";
60
61
  import { closeLastModalOnEsc } from "./utils/closeLastModalOnEsc.js";
61
62
  import { syncModalGroupsToBody } from "./utils/syncModalGroupsToBody.js";
62
- export { ModalContext, ModalPlacement, ModalPlacementOption, ModalPosition, ModalStatus, closeAllModals, closeLastModal, closeLastModalOnClickOutside, closeLastModalOnEsc, closeModal, createModal, currentModal, getAnchorElement, getAnchorMeasurement, getClosedModals, getClosingModals, getDialogs, getFloatingElement, getFloatingMeasurement, getGroupsForModal, getModalPlacement, getModalPosition, getModalStatus, getModalsForGroup, getOpenModals, getOpenedModals, getOpeningModals, getPopovers, getTooltips, getVisibleModals, isAnyModalClosed, isAnyModalClosing, isAnyModalOpen, isAnyModalOpened, isAnyModalOpening, isAnyModalVisible, isDialog, isModalClosed, isModalClosing, isModalInGroup, isModalOpen, isModalOpened, isModalOpening, isModalVisible, isPopover, isTooltip, modalGroups, onModalClosed, onModalClosing, onModalDisposed, onModalOpened, onModalOpening, openModal, setAnchorElement, setFloatingElement, setModalStatus, syncModalGroupsToBody, withAnchorElement, withAnchorMeasurement, withBoundary, withFloatingElement, withFloatingMeasurement, withModalGroups, withModalStatus, withMouseAnchor, withPlacement, withPosition };
63
+ export { ModalContext, ModalPlacement, ModalPlacementOption, ModalPosition, ModalStatus, closeAllModals, closeLastModal, closeLastModalOnClickOutside, closeLastModalOnEsc, closeModal, createModal, currentModal, getAnchorElement, getAnchorMeasurement, getClosedModals, getClosingModals, getDialogs, getFloatingElement, getFloatingMeasurement, getGroupsForModal, getModalPlacement, getModalPosition, getModalStatus, getModalsForGroup, getOpenModals, getOpenedModals, getOpeningModals, getPopovers, getTooltips, getVisibleModals, isAnyModalClosed, isAnyModalClosing, isAnyModalOpen, isAnyModalOpened, isAnyModalOpening, isAnyModalVisible, isDialog, isModalClosed, isModalClosing, isModalInGroup, isModalOpen, isModalOpened, isModalOpening, isModalVisible, isPopover, isTooltip, modalGroups, onModalClosed, onModalClosing, onModalDisposed, onModalOpened, onModalOpening, openModal, setAnchorElement, setFloatingElement, setModalStatus, syncModalGroupsToBody, withAnchorElement, withAnchorMeasurement, withBoundary, withCloseOnScroll, withFloatingElement, withFloatingMeasurement, withModalGroups, withModalStatus, withMouseAnchor, withPlacement, withPosition };
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ import { getModalPosition } from "./position/getModalPosition.js";
31
31
  import { withBoundary } from "./position/withBoundary.js";
32
32
  import { withPlacement } from "./position/withPlacement.js";
33
33
  import { withPosition } from "./position/withPosition.js";
34
+ import { withCloseOnScroll } from "./scroll/withCloseOnScroll.js";
34
35
  import { closeAllModals } from "./status/closeAllModals.js";
35
36
  import { closeLastModal } from "./status/closeLastModal.js";
36
37
  import { getClosedModals } from "./status/getClosedModals.js";
@@ -59,4 +60,4 @@ import { closeLastModalOnClickOutside } from "./utils/closeLastModalOnClickOutsi
59
60
  import { closeLastModalOnEsc } from "./utils/closeLastModalOnEsc.js";
60
61
  import { syncModalGroupsToBody } from "./utils/syncModalGroupsToBody.js";
61
62
 
62
- export { closeAllModals, closeLastModal, closeLastModalOnClickOutside, closeLastModalOnEsc, closeModal, createModal, currentModal, getAnchorElement, getAnchorMeasurement, getClosedModals, getClosingModals, getDialogs, getFloatingElement, getFloatingMeasurement, getGroupsForModal, getModalPlacement, getModalPosition, getModalStatus, getModalsForGroup, getOpenModals, getOpenedModals, getOpeningModals, getPopovers, getTooltips, getVisibleModals, isAnyModalClosed, isAnyModalClosing, isAnyModalOpen, isAnyModalOpened, isAnyModalOpening, isAnyModalVisible, isDialog, isModalClosed, isModalClosing, isModalInGroup, isModalOpen, isModalOpened, isModalOpening, isModalVisible, isPopover, isTooltip, modalGroups, onModalClosed, onModalClosing, onModalDisposed, onModalOpened, onModalOpening, openModal, setAnchorElement, setFloatingElement, setModalStatus, syncModalGroupsToBody, withAnchorElement, withAnchorMeasurement, withBoundary, withFloatingElement, withFloatingMeasurement, withModalGroups, withModalStatus, withMouseAnchor, withPlacement, withPosition };
63
+ export { closeAllModals, closeLastModal, closeLastModalOnClickOutside, closeLastModalOnEsc, closeModal, createModal, currentModal, getAnchorElement, getAnchorMeasurement, getClosedModals, getClosingModals, getDialogs, getFloatingElement, getFloatingMeasurement, getGroupsForModal, getModalPlacement, getModalPosition, getModalStatus, getModalsForGroup, getOpenModals, getOpenedModals, getOpeningModals, getPopovers, getTooltips, getVisibleModals, isAnyModalClosed, isAnyModalClosing, isAnyModalOpen, isAnyModalOpened, isAnyModalOpening, isAnyModalVisible, isDialog, isModalClosed, isModalClosing, isModalInGroup, isModalOpen, isModalOpened, isModalOpening, isModalVisible, isPopover, isTooltip, modalGroups, onModalClosed, onModalClosing, onModalDisposed, onModalOpened, onModalOpening, openModal, setAnchorElement, setFloatingElement, setModalStatus, syncModalGroupsToBody, withAnchorElement, withAnchorMeasurement, withBoundary, withCloseOnScroll, withFloatingElement, withFloatingMeasurement, withModalGroups, withModalStatus, withMouseAnchor, withPlacement, withPosition };
@@ -0,0 +1,10 @@
1
+ import { ModalStatus } from "../status/types.js";
2
+ import { Reactive } from "@monstermann/signals";
3
+
4
+ //#region src/scroll/withCloseOnScroll.d.ts
5
+ declare function withCloseOnScroll(options: {
6
+ $anchorElement: Reactive<HTMLElement | null>;
7
+ $status: Reactive<ModalStatus>;
8
+ }): void;
9
+ //#endregion
10
+ export { withCloseOnScroll };
@@ -0,0 +1,41 @@
1
+ import { closeModal } from "../status/closeModal.js";
2
+ import { currentModal } from "../createModal.js";
3
+ import { INTERNAL, effect } from "@monstermann/signals";
4
+
5
+ //#region src/scroll/withCloseOnScroll.ts
6
+ const meta = {
7
+ path: "@signals-modal/scroll/withCloseOnScroll.ts",
8
+ line: 13,
9
+ name: "withCloseOnScroll"
10
+ };
11
+ function withCloseOnScroll(options) {
12
+ const modal = currentModal();
13
+ const onScroll = () => closeModal(modal.key);
14
+ modal.onDispose(effect(() => {
15
+ const element = options.$anchorElement();
16
+ const status = options.$status();
17
+ if (!element) return;
18
+ if (status === "closing" || status === "closed") return;
19
+ const overflowElements = getScrollableAncestors(element);
20
+ for (const element$1 of overflowElements) element$1.addEventListener("scroll", onScroll, { passive: true });
21
+ return () => {
22
+ for (const element$1 of overflowElements) element$1.removeEventListener("scroll", onScroll);
23
+ };
24
+ }, INTERNAL, meta));
25
+ }
26
+ function isOverflowElement(element) {
27
+ const { display, overflow, overflowX, overflowY } = getComputedStyle(element);
28
+ return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !["inline", "contents"].includes(display);
29
+ }
30
+ function getScrollableAncestors(element) {
31
+ const scrollableAncestors = [];
32
+ let pivot = element.parentElement;
33
+ while (pivot) {
34
+ if (isOverflowElement(pivot)) scrollableAncestors.push(pivot);
35
+ pivot = pivot.parentElement;
36
+ }
37
+ return scrollableAncestors;
38
+ }
39
+
40
+ //#endregion
41
+ export { withCloseOnScroll };
@@ -1,23 +1,33 @@
1
1
  import { getGroupsForModal } from "../groups/getGroupsForModal.js";
2
2
  import { getVisibleModals } from "../status/getVisibleModals.js";
3
- import { INTERNAL, effect } from "@monstermann/signals";
3
+ import { INTERNAL, effect, memo } from "@monstermann/signals";
4
4
 
5
5
  //#region src/utils/syncModalGroupsToBody.ts
6
+ const path = "@signals-modal/utils/syncModalGroupsToBody.ts";
6
7
  const meta = {
7
- path: "@signals-modal/utils/syncModalGroupsToBody.ts",
8
- line: 6,
8
+ path,
9
+ line: 5,
10
+ name: "$classes"
11
+ };
12
+ const meta1 = {
13
+ path,
14
+ line: 17,
9
15
  name: "syncModalGroupsToBody"
10
16
  };
17
+ const $classes = memo(() => {
18
+ const modals = getVisibleModals();
19
+ const clx = /* @__PURE__ */ new Set();
20
+ for (const modal of modals) for (const group of getGroupsForModal(modal)) clx.add(`has-${group}`);
21
+ return Array.from(clx).sort().join(" ");
22
+ }, INTERNAL, meta);
11
23
  function syncModalGroupsToBody() {
12
24
  effect(() => {
13
- const modals = getVisibleModals();
14
- const clx = /* @__PURE__ */ new Set();
15
- for (const modal of modals) for (const group of getGroupsForModal(modal)) clx.add(`has-${group}`);
16
- document.body.classList.add(...clx);
25
+ const classes = $classes().split(" ");
26
+ document.body.classList.add(...classes);
17
27
  return () => {
18
- document.body.classList.remove(...clx);
28
+ document.body.classList.remove(...classes);
19
29
  };
20
- }, INTERNAL, meta);
30
+ }, INTERNAL, meta1);
21
31
  }
22
32
 
23
33
  //#endregion
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@monstermann/signals-modal",
3
3
  "type": "module",
4
- "version": "0.2.1",
4
+ "version": "0.3.1",
5
5
  "description": "Composable modal management.",
6
6
  "author": "Michael Ostermann <michaelostermann@me.com>",
7
7
  "license": "MIT",