0.9.2 • Published 6 months ago

overlay-manager-rc v0.9.2

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

Overlay-manager-rc

English | 한국어

Inspired by angular cdk overlay

React overlay component manager

Feature

  • (alert-dialog, dialog, sheet...) open, close state no more management.
  • You don't need to worry about declaring overlay component. It's okay to have multiple overlays.
  • Delivering data to overlay component props.
  • Detect when an overlay component is closed; the resulting data is received on close.
  • Prevent closing with beforeClose logic. Asynchronous result handling with await.
  • Simplified API with automatic ID management.
  • No unnecessary renders when opening or closing overlay components.
  • React 19 support

Install

npm

npm install overlay-manager-rc

yarn

yarn add overlay-manager-rc

pnpm

pnpm add overlay-manager-rc

Setting

ex) nextjs(app router) + shadcn-ui(radix-ui)

already install

  • alert-dialog

Step1

make file overlay-manager-provider.tsx;

'use client';

import type { ReactNode } from 'react';
import { OverlayContainer } from "overlay-manager-rc";

export function OverlayContainerNext({ children }: { children?: ReactNode }) {
  return <OverlayContainer/>;
}

Step2

set provider in layout.tsx component

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className={cn('min-h-screen font-sans antialiased dark')}>
        {children}
        <OverlayContainerNext />
      </body>
    </html>
  );
}

Usage

Create overlay component

import type {OverlayContentProps} from 'overlay-manager-rc';
import {useBeforeClose} from 'overlay-manager-rc'; // Import useBeforeClose

export function TestContent({
  open,
  data,
  close,
  id // add id prop
}: OverlayContentProps<string>) {

  return (
    <AlertDialog
      onOpenChange={(v) => {
        !v && close();
      }}
      open={open}
    >
      <AlertDialogContent>
        <AlertDialogHeader>
          <AlertDialogTitle>Alert title</AlertDialogTitle>
          <AlertDialogDescription>Get Data: {data}</AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogCancel>Cancel</AlertDialogCancel>
          <AlertDialogAction>Continue</AlertDialogAction>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>
  );
}

Open overlay

'use client';

import { useOverlayManager } from 'overlay-manager-rc';

export function AlertSection() {
  const { openOverlay } = useOverlayManager();
  
  const handleOpenAlert = async () => {
    const result = await openOverlay({ 
      content: TestContent,
      data: 'hello!!!!',
      onClose: (result) => {
        console.log('Dialog closed with result:', result);
      },
      onOpen: (id) => {
        console.log('Overlay opened with id:', id);
      },
    });
    console.log('Result from openOverlay:', result); // Same value as onClose result
  };

  return (
    <section className="md:h-screen">
      <div className="flex flex-col gap-10">
        <Button onClick={handleOpenAlert}>
          show alert
        </Button>
      </div>
    </section>
  );
}

Manual ID Management

When you specify a manual ID and an overlay with the same ID is already open, the existing overlay will automatically close before opening the new one.

'use client';

import { useOverlayManager } from 'overlay-manager-rc';

export function AlertSection() {
  const { openOverlay } = useOverlayManager();
  
  const handleOpenAlert = async () => {
    // This will close any existing overlay with ID 'custom-alert' 
    // before opening the new one
    await openOverlay({ 
      id: 'custom-alert',
      content: TestContent,
      data: 'first alert!',
    });
  };

  const handleOpenAnotherAlert = async () => {
    // If 'custom-alert' is already open, it will close first
    await openOverlay({ 
      id: 'custom-alert',
      content: TestContent,
      data: 'second alert!',
    });
  };

  return (
    <section className="md:h-screen">
      <div className="flex flex-col gap-10">
        <Button onClick={handleOpenAlert}>First Alert</Button>
        <Button onClick={handleOpenAnotherAlert}>Second Alert</Button>
      </div>
    </section>
  );
}

API

useOverlayManager

returns

namedescriptionparameter
openOverlayOpens an overlay component. Returns a Promise.OverlayOptions
closeAllOverlaysCloses all overlay components.-
closeOverlayByIdCloses an overlay component by ID.id: string

OverlayOptions<TData, TResult>

PropTypeDefaultRequired
idstring-No
contentOverlayContent<TData, TResult>-Yes
dataTData-No
onClose(result?: TResult) => void | Promise-No
onOpen(id: string) => void | Promise-No
beforeClose() => boolean | Promise-No

OverlayContentProps<TData, TResult>

PropTypeDefaultRequired
dataTData-Yes
close(result?: TResult) => void-Yes
openboolean-Yes
idstring-Yes

useBeforeClose

When the manager tries to run an overlay with the same id function that executes before closing the overlay

import { useBeforeClose } from 'overlay-manager-rc/useBeforeClose';

// ... inside your overlay component
useBeforeClose(async () => {
  // Your logic to determine whether to prevent closing.
  // For example, check if a form is dirty.
  const canClose = window.confirm('Are you sure you want to close?');
  return canClose; // Return true to allow closing, false to prevent it.
}, id); // Pass the overlay's ID
0.8.4

7 months ago

0.7.5

7 months ago

0.9.0

7 months ago

0.8.1

7 months ago

0.7.2

7 months ago

0.8.0

7 months ago

0.7.1

7 months ago

0.9.2

6 months ago

0.8.3

7 months ago

0.7.4

7 months ago

0.9.1

7 months ago

0.8.2

7 months ago

0.7.0

7 months ago

0.6.0

7 months ago

0.5.0

12 months ago

0.4.0

12 months ago

0.3.3

1 year ago

0.3.1

1 year ago

0.3.0

1 year ago

0.2.2

1 year ago

0.2.1

1 year ago

0.2.0

1 year ago