# use-overlay-state

> Manage your modals/alerts/whatever UI with convenient promise-based interface

Latest version **1.0.1** (published 2023-09-17) · MIT license · 0 weekly downloads

## Install

```sh
npm install use-overlay-state
pnpm add use-overlay-state
yarn add use-overlay-state
bun add use-overlay-state
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.1 |
| Published | 2023-09-17 |
| First published | 2023-09-17 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 11.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 11 |
| Author | Nazar Ilkiv |
| Maintainers | ekscentrysytet |
| Keywords | react-hooks, hooks, popover, overlay, modal |

## Links

- npm: https://www.npmjs.com/package/use-overlay-state
- Repository: https://github.com/ekscentrysytet/use-overlay-state
- Homepage: https://github.com/ekscentrysytet/use-overlay-state#readme
- Issues: https://github.com/ekscentrysytet/use-overlay-state/issues
- npm.io page: https://npm.io/package/use-overlay-state

## Alternatives

- [react-native-root-siblings](https://npm.io/package/react-native-root-siblings.md) — 102.9K weekly downloads
- [post-robot](https://npm.io/package/post-robot.md) — 93.7K weekly downloads
- [@praxisui/dialog](https://npm.io/package/@praxisui/dialog.md) — 2.0K weekly downloads
- [easy-toggle-state](https://npm.io/package/easy-toggle-state.md) — 350 weekly downloads
- [ngx-lightbox-evp](https://npm.io/package/ngx-lightbox-evp.md) — 19 weekly downloads

## Recent versions

- 1.0.1 (latest) — 2023-09-17

## README

# useOverlayState React hook

## Features

- Promise-based interface
- Two-way communication: you can pass params into overlay and get resolved value

## Motivation

The inspiration came from native `window.prompt` which allows you to get user input result in code that invoked it. However `window.prompt` is a blocking call and does not have any customization to your UI, instead this hook utilizes promises and adds more abilities for great experience.
If don't need async communication - it still exposes you convenient methods to control overlay UI open state.

## Usage

**Async communication (mostly applicable to modals/alerts)**:

```tsx
import { useOverlayState } from 'use-overlay-state'

// App.tsx
const App: React.FC = () => {
  const { isOpen, params, open, close, resolve } = useOverlayState<
    User,
    { user: User }
  >()

  const handleEdit = async (user: User) => {
    // user: User is passed to modal params
    // `open` returns a Promise which resolves either with `null` if `close` was called
    // or User if resolve was called
    const updatedUser = await open({ user })

    if (updatedUser != null) {
      alert(`Updated user is ${updatedUser.firstName} ${updatedUser.lastName}`)
    } else {
      console.log('Modal was closed')
    }
  }

  return (
    <>
      <UsersList onEdit={handleEdit} />
      <UserUpdateModal
        isOpen={isOpen}
        user={params?.user}
        onSubmit={resolve}
        onClose={close}
      />
    </>
  )
}

// UserUpdateModal.tsx
import { Modal } from 'antd'
import userService from 'services/user'

const UserUpdateModal: React.FC<{
  user?: User
  isOpen: boolean
  onSubmit: (u: User) => void
  onClose: () => void
}> = ({ user, isOpen, onSubmit, onClose }) => {
  const handleSubmit = async () => {
    const result = await usersService.update(user!.id, {
      firstName: 'Updated',
      lastName: 'User',
      gender: user!.gender,
    })

    setConfirmLoading(false)

    // call `resolve` with user: User here so it resolves Promise created by `open` in App.tsx
    onSubmit(result)
  }

  return (
    <Modal
      title="Update User"
      open={isOpen}
      onOk={handleSubmit}
      onCancel={onClose}
    >
      <p>
        Are you sure you want to update {user?.firstName} {user?.lastName}
      </p>
    </Modal>
  )
}
```

**Simple example - controllable popover (no async communication)**:

```jsx
import { useOverlayState } from 'use-overlay-state'
import Popover from '@material-ui/core/Popover'

const App = () => {
  const [achorEl, setAnchorEl] = useState()
  const { isOpen, open, close } = useOverlayState()

  const handleClick = (e) => {
    setAnchorEl(e.currentTarget)
    open()
  }

  return (
    <>
      <Popover anchorEl={anchorEl} open={isOpen} onClose={close}>
        Some content
      </Popover>
      <button onClick={handleClick}>Open popover</button>
    </>
  )
}
```

See more [examples](https://github.com/ekscentrysytet/use-overlay-state/tree/main/examples)

## API

```ts
useOverlayState<T, P>(
  defaultIsOpen: boolean = false,
): OverlayStateManagerProps<T, P>

interface OverlayStateManagerProps<T, P> {
  isOpen: boolean
  params?: P
  open: (p?: P) => Promise<T | null>
  close: () => void
  resolve: (v: T) => void
  updateParams: React.Dispatch<React.SetStateAction<P | undefined>>
}
```

**Params:**

- `defaultIsOpen: boolean` (optional) - default open state (like in `useState`). Defaults to `false`.

**Returns object with following props:**

- `isOpen: boolean` - open state indicator.
- `params?: P` - params that has been passed when invoked `open`.
- `open: (p?: P) => Promise<T | null>` - function that opens overlay. Returns a promise which resolves to either `null` if `close` was called or `result: T` if `resolve` was called
- `close: () => void` - function that closes overlay. Will resolve returned promise from `open` with null (similar to `window.prompt`)
- `resolve: (v: T) => void` - function that resolves returned promise from `open` with custom value.
- `updateParams: React.Dispatch<React.SetStateAction<P | undefined>>` - `params` updater function

---
_Source: https://npm.io/package/use-overlay-state · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
