# react-utils/popup

Overlay popup system with persistent and dismissible modes, built on `StateContext`.

<iframe src="examples/popup/" class="example-frame" title="Popup example"></iframe>

```typescript
import Popup, {
    PopupContextProvider,
    useSetPopup,
    usePopupIsPersistent,
} from '@yaoc1996/js-tools/react-utils'
```

---

## Components

---

### `Popup({ className?, style? })`

Full-coverage overlay that renders the active popup. Invisible (`opacity: 0`, `pointer-events: none`) when no popup is set. Clicking the backdrop dismisses the popup unless it is persistent. Clicking inside the popup content is swallowed via `stopPropagation`.

Must be rendered inside a `<PopupContextProvider>`.

#### Props

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | — | CSS class applied to the overlay div. |
| `style` | `CSSProperties` | — | Extra inline styles merged onto the overlay div. |

#### Example

```tsx
<PopupContextProvider>
    <App />
    <Popup className="popup-overlay" />
</PopupContextProvider>
```

---

### `PopupContextProvider({ children? })`

Provides the `PopupContext` with initial state `{ popup: null, isPersistent: false }`. Wrap your application (or a sub-tree) with this component before using `useSetPopup` or `<Popup>`.

#### Props

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `ReactNode` | — | Sub-tree that can access popup context. |

#### Example

```tsx
<PopupContextProvider>
    <App />
    <Popup />
</PopupContextProvider>
```

---

## Hooks

---

### `useSetPopup()`

Returns a setter function to open a popup. Call the setter with a `ReactNode` and an optional `isPersistent` flag.

#### Returns

`(popup: ReactNode, isPersistent?: boolean) => void`

#### Example

```tsx
const setPopup = useSetPopup();

setPopup(<ConfirmDialog />, true);   // persistent — backdrop click does nothing
setPopup(<Toast />);                  // dismissible — backdrop click closes it
setPopup(null);                       // clear manually
```

---

### `usePopupIsPersistent()`

Returns `true` when the current popup was opened with `isPersistent: true`.

#### Returns

`boolean`

#### Example

```tsx
const isPersistent = usePopupIsPersistent();
```

#### Notes

- Resets to `false` whenever the popup is closed via the backdrop.

---

## Types

```typescript
// PopupContext state shape (internal)
type PopupState = {
    popup: ReactNode;
    isPersistent: boolean;
};
```
