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 🙏

© 2024 – Pkg Stats / Ryan Hefner

async-modal-react

v3.0.3

Published

A React modal that can be used with Promise.

Downloads

127

Readme

async-modal-react

async-modal-react.png

Version

Documentation - livemehere-dev-packs

This is a simple solution to create a modal in React using hooks and async/await.

Really simple, only what you have to do is wrap your root component with ModalProvider and use useModal hook.

Demo

demo.gif

Short Description

  • You can open modal by using promise function.
  • You can open multiple modals at the same time.
  • You can close all modals at the same time.
  • You can close modal by clicking outside of modal.
  • You can customize reject reason and resolve value.
  • Typescript support.
  • No dependencies except React.

Install

npm install async-modal-react

yarn add async-modal-react

Usage

Wrap your Root Component with ModalProvider

  • closeOnOutsideClick props is for close modal when click outside of modal(default: true).
  • disableBodyScrollWhenOpen props is for disable body scroll when modal is opened(default: true).
  • closeOnRouteChange props is for close all modals when route is changed(default: true).
  • errorOnClose props is for throw error when modal is closed by clicking outside of modal or route change(default: false).
import { ModalProvider } from "async-modal-react";

ReactDOM.createRoot(document.getElementById("root")).render(
    <ModalProvider
      closeOnOutsideClick={true}
      disableBodyScrollWhenOpen={true}
      closeOnRouteChange={true}
      errorOnClose={false}
    >
      <App />
    </ModalProvider>,
);

Create Your Modal Component

  • Component that used for modal receive 3 props: close, resolve, reject.
  • resolve function will return value when using open function.
  • close and reject function will reject when using open function.
  • reject reason and resolve value can customize by yourself.

close estimated as reject


const ExampleModal = ({ close, resolve, reject }) => {
  return (
    <div>
      <h2>ExampleModal</h2>
      <button onClick={() => resolve(`resolve!`)}>RESOLVE</button>
      <button onClick={() => reject("reject T-T")}>REJECT</button>
      <button onClick={close}>Close</button>
    </div>
  );
};

export default ExampleModal;

Use Modal with Hooks

  • useModal hook return open and closeAll function.
import ExampleModal from "./components/ExampleModal";
import { useModal } from "async-modal-react";

function App() {
    const { open, closeAll } = useModal();

    const openModal = async () => {
        try {
            // resolve
            const result = await open(ExampleModal);
            console.log(result);
        } catch (e) {
            // reject, close
            console.log(e);
        }
    };

    return (
        <div>
            <button onClick={openModal}>OPEN</button>
        </div>
    );
}

export default App;

Typescript Support

Modal Component Props

  • import ModalProps from async-modal-react and extend your props interface.
export interface ModalProps {
    close: () => void;
    resolve: <Result = any>(v: Result) => void;
    reject: <Reason = any>(reason: Reason) => void;
}
import { ModalProps } from "async-modal-react";

export interface ExampleProps extends ModalProps {
  name: string;
}

const ExampleModal = ({ close, resolve, reject, name }: ExampleProps) => {
  return (
    <div>
      <h2>ExampleModal</h2>
      <button onClick={() => resolve(`resolve! ${name}`)}>RESOLVE</button>
      <button onClick={() => reject("reject T-T")}>REJECT</button>
      <button onClick={close}>Close</button>
    </div>
  );
};

export default ExampleModal;

Hooks

  • resolve type can be set by generic type.
  • second generic type is for modal props. (most case is not necessary)
  • open function return Promise<ReturnType>.
  • options are higher priority than ModalProvider props. You can set individually.
 const result = await open<ReturnType, Props>(
    ExampleModal, // Modal Component
    {}, // ExampleModal props
    { // Individual options
        onClickOutsideClose: true,
        disableScroll: true,
        enableInsideScroll: true, // use this when global disableScroll is true but you want to enable scroll in this modal.
        errorOnClose: true,
    },
);

Customizing

Modal root element

 <div
      id="modal-root"
      style={{
        position: "fixed",
        top: 0,
        left: 0,
        width: "100%",
        height: "100%",
        background: "rgba(0, 0, 0, 0.5)",
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
      }}
    >
  {children}
</div>

customize #modal-root element with global css.

#modal-root {
  background: blue !important;
}

Multiple modals style

By Default modal root element display children with flex and justifyContent: center, alignItems: center. So if there are more than two modal is opened, they will be displayed in just like a flex.
if you want to stack layout, your modal component should have position: absolute style.

// ...
return (
    <div
        style={{
            background: "white",
            position: "absolute",
        }}
    >
        <h2>ExampleModal</h2>
        <button onClick={() => resolve(`resolve! ${name}`)}>RESOLVE</button>
        <button onClick={() => reject("reject T-T")}>REJECT</button>
        <button onClick={close}>Close</button>
        <button onClick={openModal}>OPEN</button>
    </div>
);

If Modal Component not have position: absolute look like.

multi-modal-flex.png

If Modal Component have position: absolute look like.

  • Two modals are stacked

multi-modal-absolute.png