# Dialog Layer

A global dialog management system that allows you to open dialogs from anywhere in your application without mounting multiple instances.

## Features

- ✅ Stack-based system - Dialogs can open other dialogs
- ✅ Reactive config updates - Dialog config stays in sync with component state
- ✅ Two usage patterns - Simple API and Composition Components
- ✅ Smooth animations - Built-in open/close transitions
- ✅ Flexible - Use simple props or build custom layouts
- ✅ Uses design-system components - All content uses Dialog composition components from design-system

## File Structure

```
src/components/layers/Dialogs/
├── hooks.ts       # useDialogLayer, useDialogLayerItem hooks
├── types.ts       # TypeScript type definitions
├── index.tsx      # DialogLayerProvider and Dialog exports
├── stories.tsx    # Storybook stories
└── README.md      # This file
```

## Setup

Wrap your application with the `DialogLayerProvider`:

```tsx
import { DialogLayerProvider } from '@material-hu/layers/Dialogs';

function App() {
  return (
    <DialogLayerProvider>
      <YourApp />
    </DialogLayerProvider>
  );
}
```

## Usage

**Props:** Use `dialogProps` for the MUI Dialog wrapper (e.g. `maxWidth`, `fullWidth`, `PaperProps`). Content config (title, textBody, or content) stays at top level.

### 1. Simple API

Use the simple API for common dialog patterns. This uses the design-system Dialog component internally.

```tsx
import { useDialogLayer } from '@material-hu/layers/Dialogs';

function MyComponent() {
  const { openDialog, closeDialog } = useDialogLayer();

  const handleConfirm = () => {
    openDialog({
      title: 'Confirm action',
      textBody: 'Are you sure you want to continue?',
      primaryButtonProps: {
        children: 'Continue',
        onClick: () => {
          doSomething();
          closeDialog();
        },
      },
      secondaryButtonProps: {
        children: 'Cancel',
        onClick: closeDialog,
      },
      dialogProps: {
        maxWidth: 'sm',
        fullWidth: true,
      },
    });
  };

  return <button onClick={handleConfirm}>Confirm</button>;
}
```

#### Simple API Props

| Prop | Type | Description |
|------|------|-------------|
| `title` | `string` | Dialog title |
| `textBody` | `string` | Simple text content |
| `body` | `ReactNode` | Custom body component |
| `actionInfo` | `string` | Info text in footer |
| `onClose` | `(reason?: DialogCloseReason) => void` | Close handler (handled by layer) |
| `primaryButtonProps` | `ButtonProps` | Primary action button |
| `secondaryButtonProps` | `ButtonProps` | Secondary action button |
| `footerProps` | `{ hideBorder?: boolean }` | Footer styling |
| `dialogProps` | `Omit<MuiDialogProps, 'open' \| 'onClose'>` | Optional. Props for the MUI Dialog wrapper (`maxWidth`, `fullWidth`, `PaperProps`, etc.). |
| `disableCloseOnBackdropClick` | `boolean` | If true, backdrop click does not close |
| `disableCloseOnEscapeKeyDown` | `boolean` | If true, escape key does not close |

### 2. useDialogLayerItem Hook

Use this hook when you need a dialog with **reactive config updates**. The dialog configuration automatically stays in sync with your component's state.

```tsx
import { useDialogLayerItem } from '@material-hu/layers/Dialogs';

function MyComponent() {
  const [isLoading, setIsLoading] = useState(false);

  const { openDialog, closeDialog } = useDialogLayerItem('confirm-save', {
    title: 'Confirm Save',
    textBody: 'Are you sure you want to save these changes?',
    primaryButtonProps: {
      children: isLoading ? 'Saving...' : 'Save',
      loading: isLoading,
      onClick: async () => {
        setIsLoading(true);
        await saveChanges();
        setIsLoading(false);
        closeDialog();
      },
    },
    secondaryButtonProps: {
      children: 'Cancel',
      onClick: () => closeDialog(),
    },
  });

  return <Button onClick={() => openDialog()}>Save</Button>;
}
```

#### useDialogLayerItem API

| Parameter | Type | Description |
|-----------|------|-------------|
| `id` | `string` | Unique identifier for the dialog |
| `config` | `OpenDialogArgs` | Dialog configuration (same props as `openDialog`) |

**Returns:**

| Method | Type | Description |
|--------|------|-------------|
| `openDialog` | `(config?: OpenDialogArgs) => void` | Opens the dialog (optionally with different config) |
| `closeDialog` | `(immediate?: boolean) => void` | Closes the dialog |
| `updateDialogConfig` | `(setter: (current) => new) => void` | Manually update dialog config |

#### When to use each hook

| Use case | Hook |
|----------|------|
| Simple one-off dialogs | `useDialogLayer` |
| Dialogs with reactive state (loading, form data) | `useDialogLayerItem` |
| Programmatic config updates | `useDialogLayerItem` |

### 3. Composition Components API

Use composition components for complete flexibility in layout and content. Pass **`content`** (your composed JSX) and optionally **`dialogProps`** for the MUI Dialog wrapper.

```tsx
import { useDialogLayer, Dialog } from '@material-hu/layers/Dialogs';

function MyComponent() {
  const { openDialog, closeDialog } = useDialogLayer();

  const handleCustomDialog = () => {
    openDialog({
      content: (
        <>
          <Dialog.Header title="Custom Layout" onClose={closeDialog} />
          <Dialog.Body>
            <YourCustomForm />
          </Dialog.Body>
          <Dialog.Footer>
            <Button variant="tertiary" onClick={closeDialog}>
              Cancel
            </Button>
            <Button variant="primary" onClick={handleSave}>
              Save
            </Button>
          </Dialog.Footer>
        </>
      ),
      dialogProps: {
        maxWidth: 'md',
        fullWidth: true,
      },
    });
  };

  return <button onClick={handleCustomDialog}>Open Dialog</button>;
}
```

#### Composition API props

| Prop | Type | Description |
|------|------|-------------|
| `content` | `ReactNode` | **Required.** Your composed layout (e.g. `Dialog.Header` + `Dialog.Body` + `Dialog.Footer`). |
| `onClose` | `(reason?: DialogCloseReason) => void` | Close handler (handled by layer). |
| `dialogProps` | `Omit<MuiDialogProps, 'open' \| 'onClose'>` | Optional. Props for the MUI Dialog wrapper. |
| `disableCloseOnBackdropClick` | `boolean` | If true, backdrop click does not close |
| `disableCloseOnEscapeKeyDown` | `boolean` | If true, escape key does not close |

#### Available Composition Components

##### `Dialog.Header`

Header section with title and close button.

```tsx
<Dialog.Header
  title="Dialog Title"
  onClose={closeDialog}
/>
```

##### `Dialog.Body`

Content section with automatic scroll support.

```tsx
<Dialog.Body>
  <YourContent />
</Dialog.Body>
```

##### `Dialog.Footer`

Footer section for actions and optional info.

```tsx
<Dialog.Footer actionInfo="Optional info" hideBorder={false}>
  <Button variant="primary" onClick={handleSave}>Save</Button>
</Dialog.Footer>
```

## Examples

### Simple confirmation

```tsx
openDialog({
  title: 'Confirm Action',
  textBody: 'Are you sure you want to proceed?',
  primaryButtonProps: {
    children: 'Yes, proceed',
    onClick: () => {
      doSomething();
      closeDialog();
    },
  },
  secondaryButtonProps: {
    children: 'Cancel',
    onClick: closeDialog,
  },
});
```

### Dialog with custom layout

```tsx
openDialog({
  content: (
    <>
      <Dialog.Header title="Custom" onClose={closeDialog} />
      <Dialog.Body>
        <CustomComponent />
      </Dialog.Body>
      <Dialog.Footer>
        <Button onClick={closeDialog}>Done</Button>
      </Dialog.Footer>
    </>
  ),
});
```

### Minimal dialog (header only)

```tsx
openDialog({
  content: <Dialog.Header title="Just a title" onClose={closeDialog} />,
});
```

## Behavior Notes

- **Stack**: Dialogs can be stacked; opening a new one adds to the stack. Closing removes the topmost.
- **Session Management**: Each dialog can have a unique ID when using `openDialog(args, id)` for targeted close/update.
- **Immediate Close**: Pass `true` to `closeDialog(undefined, true)` to close without animation (useful before navigation).
- **Auto Cleanup**: Dialog state is automatically cleaned up after close animations complete.

## TypeScript Support

Full TypeScript support with exported types:

```tsx
import type {
  OpenDialogArgs,
  SimpleDialogProps,
  CompositionDialogProps,
  DialogLayerContextValue,
  DialogLevel,
  DialogCloseReason,
} from '@material-hu/layers/Dialogs/types';
```

- **`OpenDialogArgs`** – Argument for `openDialog` / `useDialogLayerItem` config. Simple (design-system props) or Composition (`content`). Optional `dialogProps` for the MUI Dialog wrapper.
- **`DialogCloseReason`** – `'backdropClick' | 'escapeKeyDown'`.

### Available Exports

```tsx
// Main exports
import {
  DialogLayerProvider,  // Context provider
  useDialogLayer,       // Basic dialog hook
  useDialogLayerItem,   // Reactive dialog hook
  Dialog,               // Composition components
} from '@material-hu/layers/Dialogs';

// Composition components
Dialog.Header
Dialog.Body
Dialog.Footer
```
