npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@monstermann/signals-modal

v0.8.0

Published

Composable modal management.

Readme

Minified Minzipped

Composable modal management.

Documentation

Example

const modal = createModal("key", () => {
    const { $status } = withModalStatus();

    const $anchorElement = withAnchorElement();
    const $anchorMeasurement = withAnchorMeasurement({
        $anchorElement,
        $status,
    });

    const $floatingElement = withFloatingElement();
    const $floatingMeasurement = withFloatingMeasurement({
        $floatingElement,
        $status,
    });

    const $boundary = withBoundary({
        $status,
        transform: (rect) => rect,
    });

    const $placement = withPlacement({
        placement: "down-center",
        $anchorMeasurement,
        $boundary,
        $floatingMeasurement,
    });

    const $position = withPosition({
        $anchorMeasurement,
        $boundary,
        $floatingMeasurement,
        $placement,
    });

    return {
        $anchorElement,
        $floatingElement,
        $position,
        $status,
    };
});

Installation

npm install @monstermann/signals-modal
pnpm add @monstermann/signals-modal
yarn add @monstermann/signals-modal
bun add @monstermann/signals-modal

Anchor

withAnchorElement

function withAnchorElement(
    anchorElement?: HTMLElement,
): Signal<HTMLElement | null>;

Assigns an anchor element to the current modal. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withAnchorElement,
    setAnchorElement,
    getAnchorElement,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withAnchorElement();
});

setAnchorElement("key", document.querySelector(".anchor"));
getAnchorElement("key"); // HTMLElement

withAnchorMeasurement

function withAnchorMeasurement(options: {
    $anchorElement: Reactive<HTMLElement | null>;
    $status: Reactive<ModalStatus>;
    transform?: (rect: Rect) => Rect;
}): Memo<Rect>;

Takes an anchor element and continuously measures its position while the modal is visible, to be used to position eg. a popover next to an element. This function must be called inside a createModal callback.

The optional transform option can be used to eg. make the anchor bigger, resulting with a margin between the anchor and floating popover.

Example

import {
    createModal,
    withAnchorElement,
    withModalStatus,
    withAnchorMeasurement,
    setAnchorElement,
    setModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $anchorElement = withAnchorElement();
    // Memo({ top: number, left: number, width: number, height: number })
    const $anchorMeasurement = withAnchorMeasurement({
        $status,
        $anchorElement,
    });
});

setAnchorElement("key", document.querySelector(".anchor"));
setModalStatus("key", "opened");

withMouseAnchor

function withMouseAnchor(options: {
    $status: Reactive<ModalStatus>;
    transform?: (rect: Rect) => Rect;
}): Memo<Rect>;

This can be used to make the mouse cursor the anchor, instead of an element. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withModalStatus,
    withMouseAnchor,
    setModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    // Memo({ top: number, left: number, width: number, height: number })
    const $anchorMeasurement = withMouseAnchor({ $status });
});

// Updates $anchorMeasurement to the current mouse coordinates (once).
setModalStatus("key", "opened");

Core

createModal

function createModal(
    key: string,
    setup: () => T,
): T & {
    key: string;
    dispose: () => void;
    isDisposed: () => boolean;
    onDispose: (dispose: MaybeDispose) => void;
};

Creates a new modal.

Example

import { createModal } from "@monstermann/signals-modal";

const modal = createModal("key", () => ({}));
modal.key;
modal.dispose();
modal.onDispose(callback);

currentModal

function currentModal(): {
    key: string;
    dispose: () => void;
    onDispose: (dispose: MaybeDispose) => void;
};

Retrieves the current modal.

Example

import { createModal, currentModal } from "@monstermann/signals-modal";

createModal(() => {
    const modal = currentModal();
});

onModalDisposed

const onModalDisposed: Emitter<string>;

An emitter that fires when a modal gets disposed. The emitted value is the modal key.

Example

import { createModal, onModalDisposed } from "@monstermann/signals-modal";

const modal = createModal("key", () => {});

const stopListening = onModalDisposed((key) => {
    console.log(`Modal ${key} disposed`);
});

modal.dispose();

stopListening();

Floating

withFloatingElement

function withFloatingElement(
    floatingElement?: HTMLElement,
): Signal<HTMLElement | null>;

Assigns an floating element to the current modal. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withFloatingElement,
    setFloatingElement,
    getFloatingElement,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withFloatingElement();
});

setFloatingElement("key", document.querySelector(".floating"));
getFloatingElement("key"); // HTMLElement

withFloatingMeasurement

function withFloatingMeasurement(options: {
    $floatingElement: Reactive<HTMLElement | null>;
    $status: Reactive<ModalStatus>;
    transform?: (rect: Rect) => Rect;
}): Memo<Rect>;

Takes an floating element and continuously measures its position while the modal is visible, to be used to position eg. a popover next to an element. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withFloatingElement,
    withModalStatus,
    withFloatingMeasurement,
    setFloatingElement,
    setModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $floatingElement = withFloatingElement();
    // Memo({ top: number, left: number, width: number, height: number })
    const $floatingMeasurement = withFloatingMeasurement({
        $status,
        $floatingElement,
    });
});

setFloatingElement("key", document.querySelector(".floating"));
setModalStatus("key", "opened");

Groups

getDialogs

Reactive

function getDialogs(): ReadonlySet<string>;

Returns all dialog keys from the modalGroups.dialog group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getDialogs,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.dialog]);
});

getDialogs(); // Set(["key"])

getGroupsForModal

Reactive

function getGroupsForModal(key: string): ReadonlySet<string>;

Returns all groups the given key belongs to.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getGroupsForModal,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.dialog]);
});

getGroupsForModal("key"); // Set(["dialog"])

getModalsForGroup

Reactive

function getModalsForGroup(group: string): ReadonlySet<string>;

Returns all keys the given group belongs to.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getModalsForGroup,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.dialog]);
});

getModalsForGroup(modalGroups.dialog); // Set(["key"])

getPopovers

Reactive

function getPopovers(): ReadonlySet<string>;

Returns all popover keys from the modalGroups.popover group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getPopovers,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

getPopovers(); // Set(["key"])

getTooltips

Reactive

function getTooltips(): ReadonlySet<string>;

Returns all tooltip keys from the modalGroups.tooltip group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getTooltips,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.tooltip]);
});

getTooltips(); // Set(["key"])

isDialog

Reactive

function isDialog(key: string): boolean;

Returns a boolean indicating whether the given key belongs to the modalGroups.dialog group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    isDialog,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

isDialog("key"); // true

isModalInGroup

Reactive

function isModalInGroup(key: string, group: string): boolean;

Returns a boolean indicating whether the given key belongs to the group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    isModalInGroup,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

isModalInGroup("key", modalGroups.popover); // true

isPopover

Reactive

function isPopover(key: string): boolean;

Returns a boolean indicating whether the given key belongs to the modalGroups.popover group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    isPopover,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

isPopover("key"); // true

isTooltip

Reactive

function isTooltip(key: string): boolean;

Returns a boolean indicating whether the given key belongs to the modalGroups.tooltip group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    isTooltip,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

isTooltip("key"); // true

modalGroups

const modalGroups = {
    dialog: "dialog",
    popover: "popover",
    tooltip: "tooltip",
};

A record containing common modal groups.

withModalGroups

function withModalGroups(groups: Iterable<string>): Memo<ReadonlySet<string>>;

Assigns the current modal to a list of groups. Can be used to for example mark the modal as a dialog/popover/tooltip. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withModalGroups,
    getDialogs,
    getGroupsForModal,
    getModalsForGroup,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups(["dialog"]);
});

getGroupsForModal("key"); // Set(["dialog"])
getModalsForGroup("dialog"); // Set(["key"])

Position

withBoundary

function withBoundary(options: {
    $status: Reactive<ModalStatus>;
    transform?: (rect: Rect) => Rect;
}): Memo<Rect>;

Constructs a Rect resembling the window dimensions, to be fed into withPlacement and withPosition, used to constrain the floating element to be within the window boundary. This function must be called inside a createModal callback.

The optional transform option can be used to eg. make the Rect smaller, increasing the distance between the floating element and the edges of the window.

Example

import {
    createModal,
    withModalStatus,
    withBoundary,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $boundary = withBoundary({ $status });
});

withPlacement

function withPlacement(options: {
    placement: ModalPlacementOption;
    $boundary: () => Rect;
    $anchorMeasurement: () => Rect;
    $floatingMeasurement: () => Rect;
}): Memo<ModalPlacement>;

type ModalPlacementOption =
    | "vertical-center"
    | "vertical-left"
    | "vertical-right"
    | "horizontal-center"
    | "horizontal-up"
    | "horizontal-down"
    | "up-center"
    | "down-center"
    | "left-down"
    | "right-down";

type ModalPlacement =
    | "down-center"
    | "down-left"
    | "down-right"
    | "left-center"
    | "left-down"
    | "left-up"
    | "right-center"
    | "right-down"
    | "right-up"
    | "up-center"
    | "up-left"
    | "up-right";

Takes a ModalPlacementOption and resolves it to ModalPlacement, picking whichever side has more space. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withModalStatus,
    withAnchorElement,
    withAnchorMeasurement,
    withFloatingElement,
    withFloatingMeasurement,
    withBoundary,
    withPlacement,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $anchorElement = withAnchorElement();
    const $floatingElement = withFloatingElement();
    const $anchorMeasurement = withAnchorMeasurement({
        $status,
        $anchorElement,
    });
    const $floatingMeasurement = withFloatingMeasurement({
        $status,
        $floatingElement,
    });
    const $boundary = withBoundary({ $status });
    const $placement = withPlacement({
        placement: "vertical-center",
        $boundary,
        $anchorMeasurement,
        $floatingMeasurement,
    });
});

withPosition

function withPosition(options: {
    $boundary: () => Rect;
    $placement: () => ModalPlacement;
    $anchorMeasurement: () => Rect;
    $floatingMeasurement: () => Rect;
    transform?: (rect: Rect) => Rect;
}): Memo<{
    floatingX: number;
    floatingY: number;
    maxHeight: number;
    maxWidth: number;
    originX: number;
    originY: number;
}>;

Consumes a range of measurements and calculates the final position for the floating element. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withModalStatus,
    withAnchorElement,
    withAnchorMeasurement,
    withFloatingElement,
    withFloatingMeasurement,
    withBoundary,
    withPlacement,
    withPosition,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $anchorElement = withAnchorElement();
    const $floatingElement = withFloatingElement();
    const $anchorMeasurement = withAnchorMeasurement({
        $status,
        $anchorElement,
    });
    const $floatingMeasurement = withFloatingMeasurement({
        $status,
        $floatingElement,
    });
    const $boundary = withBoundary({ $status });
    const $placement = withPlacement({
        placement: "vertical-center",
        $boundary,
        $anchorMeasurement,
        $floatingMeasurement,
    });
    const $position = withPosition({
        $boundary,
        $placement,
        $anchorMeasurement,
        $floatingMeasurement,
    });
});

Scroll

withCloseOnScroll

function withCloseOnScroll(options: {
    $anchorElement: Reactive<HTMLElement | null>;
    $status: Reactive<ModalStatus>;
}): void;

Automatically closes the modal when any scrollable ancestor of the anchor element is scrolled. This function must be called inside a createModal callback.

The function listens for scroll events on all scrollable parent elements of the anchor element and triggers a close when scrolling occurs. Scroll listeners are only active when the modal is opening or opened (not when closing or closed).

Example

import {
    createModal,
    withModalStatus,
    withAnchorElement,
    withCloseOnScroll,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $anchorElement = withAnchorElement();

    withCloseOnScroll({
        $status,
        $anchorElement,
    });
});

Status

closeAllModals

function closeAllModals(): void;

Closes all modals by setting their status to "closing". Skips modals that are already "closing" or "closed".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    closeAllModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

openModal("modal1");
openModal("modal2");
closeAllModals();

closeModal

function closeModal(key: string): void;

Closes a modal by setting its status to "closing". Does nothing if the modal is already "closing" or "closed", or if the modal doesn't exist.

Example

import {
    createModal,
    withModalStatus,
    openModal,
    closeModal,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

openModal("key");
closeModal("key");

getClosedModals

Reactive

function getClosedModals(): string[];

Returns an array of all modal keys with status "closed".

Example

import {
    createModal,
    withModalStatus,
    getClosedModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

getClosedModals(); // ["modal1", "modal2"]

getClosingModals

Reactive

function getClosingModals(): string[];

Returns an array of all modal keys with status "closing".

Example

import {
    createModal,
    withModalStatus,
    closeModal,
    getClosingModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus("opened");
});

createModal("modal2", () => {
    withModalStatus("opened");
});

closeModal("modal1");
closeModal("modal2");

getClosingModals(); // ["modal1", "modal2"]

getModalStatus

Reactive

function getModalStatus(key: string): ModalStatus;

Retrieves the current status of a modal. Returns "closed" if the modal doesn't exist.

ModalStatus can be one of: "closed", "opening", "opened", or "closing".

Example

import {
    createModal,
    withModalStatus,
    getModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

getModalStatus("key"); // "closed"

getOpenedModals

Reactive

function getOpenedModals(): string[];

Returns an array of all modal keys with status "opened".

Example

import {
    createModal,
    withModalStatus,
    getOpenedModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus("opened");
});

createModal("modal2", () => {
    withModalStatus("opened");
});

getOpenedModals(); // ["modal1", "modal2"]

getOpeningModals

Reactive

function getOpeningModals(): string[];

Returns an array of all modal keys with status "opening".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    getOpeningModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

openModal("modal1");
openModal("modal2");

getOpeningModals(); // ["modal1", "modal2"]

getOpenModals

Reactive

function getOpenModals(): string[];

Returns an array of all modal keys with status "opening" or "opened".

Example

import {
    createModal,
    withModalStatus,
    getOpenModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus("opening");
});

createModal("modal2", () => {
    withModalStatus("opened");
});

createModal("modal3", () => {
    withModalStatus("closed");
});

getOpenModals(); // ["modal1", "modal2"]

getVisibleModals

Reactive

function getVisibleModals(): string[];

Returns an array of all modal keys that are visible (not "closed"). This includes "opening", "opened", and "closing" statuses.

Example

import {
    createModal,
    withModalStatus,
    openModal,
    getVisibleModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

openModal("modal1");
openModal("modal2");

getVisibleModals(); // ["modal1", "modal2"]

isAnyModalClosed

Reactive

function isAnyModalClosed(): boolean;

Returns true if any modal has status "closed".

Example

import {
    createModal,
    withModalStatus,
    isAnyModalClosed,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus("opened");
});

isAnyModalClosed(); // true

isAnyModalClosing

Reactive

function isAnyModalClosing(): boolean;

Returns true if any modal has status "closing".

Example

import {
    createModal,
    withModalStatus,
    closeModal,
    isAnyModalClosing,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus("opened");
});

createModal("modal2", () => {
    withModalStatus();
});

closeModal("modal1");

isAnyModalClosing(); // true

isAnyModalOpen

Reactive

function isAnyModalOpen(): boolean;

Returns true if any modal has status "opening" or "opened".

Example

import {
    createModal,
    withModalStatus,
    isAnyModalOpen,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus("opened");
});

isAnyModalOpen(); // true

isAnyModalOpened

Reactive

function isAnyModalOpened(): boolean;

Returns true if any modal has status "opened".

Example

import {
    createModal,
    withModalStatus,
    isAnyModalOpened,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus("opened");
});

isAnyModalOpened(); // true

isAnyModalOpening

Reactive

function isAnyModalOpening(): boolean;

Returns true if any modal has status "opening".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    isAnyModalOpening,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

openModal("modal1");

isAnyModalOpening(); // true

isAnyModalVisible

Reactive

function isAnyModalVisible(): boolean;

Returns true if any modal is visible (not "closed"). This includes "opening", "opened", and "closing" statuses.

Example

import {
    createModal,
    withModalStatus,
    isAnyModalVisible,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus("opened");
});

isAnyModalVisible(); // true

isModalClosed

Reactive

function isModalClosed(key: string): boolean;

Returns true if the modal's status is "closed" or if the modal doesn't exist.

Example

import {
    createModal,
    withModalStatus,
    isModalClosed,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

isModalClosed("key"); // true

isModalClosing

Reactive

function isModalClosing(key: string): boolean;

Returns true if the modal's status is "closing".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    closeModal,
    isModalClosing,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    $status("opened");
});

closeModal("key");
isModalClosing("key"); // true

isModalOpen

Reactive

function isModalOpen(key: string): boolean;

Returns true if the modal's status is "opening" or "opened".

Example

import {
    createModal,
    withModalStatus,
    isModalOpen,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus("opening");
});

isModalOpen("key"); // true

isModalOpened

Reactive

function isModalOpened(key: string): boolean;

Returns true if the modal's status is "opened".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    isModalOpened,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    $status("opened");
});

isModalOpened("key"); // true

isModalOpening

Reactive

function isModalOpening(key: string): boolean;

Returns true if the modal's status is "opening".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    isModalOpening,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

openModal("key");
isModalOpening("key"); // true

isModalVisible

Reactive

function isModalVisible(key: string): boolean;

Returns true if the modal is visible (not "closed"). This includes "opening", "opened", and "closing" statuses.

Example

import {
    createModal,
    withModalStatus,
    openModal,
    isModalVisible,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

openModal("key");
isModalVisible("key"); // true

onModalClosed

const onModalClosed: Emitter<string>;

An emitter that fires when a modal transitions to the "closed" status. The emitted value is the modal key.

Example

import {
    createModal,
    withModalStatus,
    onModalClosed,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

const stopListening = onModalClosed((key) => {
    console.log(`Modal ${key} closed`);
});

stopListening();

onModalClosing

const onModalClosing: Emitter<string>;

An emitter that fires when a modal transitions to the "closing" status. The emitted value is the modal key.

Example

import {
    createModal,
    withModalStatus,
    onModalClosing,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

const stopListening = onModalClosing((key) => {
    console.log(`Modal ${key} closing`);
});

stopListening();

onModalOpened

const onModalOpened: Emitter<string>;

An emitter that fires when a modal transitions to the "opened" status. The emitted value is the modal key.

Example

import {
    createModal,
    withModalStatus,
    onModalOpened,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

const stopListening = onModalOpened((key) => {
    console.log(`Modal ${key} opened`);
});

stopListening();

onModalOpening

const onModalOpening: Emitter<string>;

An emitter that fires when a modal transitions to the "opening" status. The emitted value is the modal key.

Example

import {
    createModal,
    withModalStatus,
    onModalOpening,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

const stopListening = onModalOpening((key) => {
    console.log(`Modal ${key} opening`);
});

stopListening();

openModal

function openModal(key: string): void;

Opens a modal by setting its status to "opening". Does nothing if the modal is already "opening" or "opened", or if the modal doesn't exist.

Example

import {
    createModal,
    withModalStatus,
    openModal,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

openModal("key");

setModalStatus

function setModalStatus(key: string, status: ModalStatus): void;

Sets the status of a modal. Does nothing if the modal doesn't exist.

ModalStatus can be one of: "closed", "opening", "opened", or "closing".

Example

import {
    createModal,
    withModalStatus,
    setModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

setModalStatus("key", "opened");

withModalStatus

function withModalStatus(status: ModalStatus = "closed"): {
    $isOpen: Memo<boolean>;
    $mounted: Memo<boolean>;
    $status: Signal<ModalStatus>;
    close: () => void;
    open: () => void;
    toggle: () => void;
};

Creates and returns a status signal for the current modal. This function must be called inside a createModal callback.

The optional status parameter sets the initial status of the modal (defaults to "closed").

ModalStatus can be one of: "closed", "opening", "opened", or "closing".

Example

import { createModal, withModalStatus } from "@monstermann/signals-modal";

// Default to "closed"
createModal("modal1", () => {
    const { $status } = withModalStatus();
    console.log($status()); // "closed"
});

// Start with a different initial status
createModal("modal2", () => {
    const { $status } = withModalStatus("opened");
    console.log($status()); // "opened"

    // Update the status
    $status("closing");
});