### Install hiraku Package Source: https://hirotoshioi.github.io/hiraku/guide/getting-started Installs the hiraku package using different package managers (npm, pnpm, bun, yarn). This is the first step to integrate hiraku into your project. ```bash npm install @hirotoshioi/hiraku ``` ```bash pnpm add @hirotoshioi/hiraku ``` ```bash bun add @hirotoshioi/hiraku ``` ```bash yarn add @hirotoshioi/hiraku ``` -------------------------------- ### Install Radix UI Peer Dependencies Source: https://hirotoshioi.github.io/hiraku/guide/getting-started Installs the required Radix UI dialog primitives for hiraku to function correctly. These include `@radix-ui/react-dialog` and `@radix-ui/react-alert-dialog`. ```bash npm install @radix-ui/react-dialog @radix-ui/react-alert-dialog ``` ```bash pnpm add @radix-ui/react-dialog @radix-ui/react-alert-dialog ``` ```bash bun add @radix-ui/react-dialog @radix-ui/react-alert-dialog ``` ```bash yarn add @radix-ui/react-dialog @radix-ui/react-alert-dialog ``` -------------------------------- ### Example Usage and Type Inference Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Demonstrates a complete example of creating and using a dialog, along with how props are inferred for type safety. ```APIDOC ## Example This example shows how to create a `GreetingDialog` and use it. ```tsx import { createDialog } from "@hirotoshioi/hiraku"; import { DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; interface Props { name: string; } function GreetingDialog({ name }: Props) { return ( Hello, {name}! ); } export const greetingDialog = createDialog(GreetingDialog); // Usage await greetingDialog.open({ name: "World" }); ``` ## Type Inference Props are automatically inferred from the component, ensuring type safety. ```tsx // ✅ Type-safe greetingDialog.open({ name: "World" }); // ❌ Type error: missing 'name' greetingDialog.open({}); // ❌ Type error: unknown prop greetingDialog.open({ name: "World", foo: "bar" }); ``` ``` -------------------------------- ### Create a Confirm Dialog Modal Source: https://hirotoshioi.github.io/hiraku/guide/getting-started Defines a reusable confirmation dialog component and its controller using `createDialog`. This example shows how to define the modal's UI and its return type. ```tsx // modals/confirm-dialog.tsx import { createDialog } from "@hirotoshioi/hiraku"; import { DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; interface ConfirmDialogProps { title: string; message: string; } function ConfirmDialog({ title, message }: ConfirmDialogProps) { return ( {title}

{message}

); } export const confirmDialog = createDialog(ConfirmDialog).returns(); ``` -------------------------------- ### Alert Dialog Example with UI Components - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-alert-dialog Provides a comprehensive example of creating and using an alert dialog for a delete confirmation. It integrates with typical UI components for alert dialogs and demonstrates opening, closing, and handling the result. This example showcases a common use case for critical user actions. ```tsx import { createAlertDialog } from "@hirotoshioi/hiraku"; import { AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, } from "@/components/ui/alert-dialog"; interface DeleteConfirmProps { itemName: string; } function DeleteConfirmDialog({ itemName }: DeleteConfirmProps) { return ( Delete {itemName}? This action cannot be undone. This will permanently delete the item. deleteConfirm.close({ role: "cancel" })} > Cancel deleteConfirm.close({ role: "confirm" })} > Delete ); } export const deleteConfirm = createAlertDialog(DeleteConfirmDialog); // Usage await deleteConfirm.open({ itemName: "Project Alpha" }); const result = await deleteConfirm.onDidClose(); if (result.role === "confirm") { await deleteProject(); } ``` -------------------------------- ### Open and Handle Modal Response Source: https://hirotoshioi.github.io/hiraku/guide/getting-started Demonstrates how to open a previously defined modal (`confirmDialog`) and wait for its result. It shows how to pass props to the modal and process the returned data based on the user's interaction. ```tsx import { confirmDialog } from "./modals/confirm-dialog"; // Open the modal await confirmDialog.open({ title: "Delete Item", message: "Are you sure you want to delete this item?", }); // Wait for the result const result = await confirmDialog.onDidClose(); if (result.role === "confirm" && result.data) { // User confirmed deleteItem(); } ``` -------------------------------- ### ModalProvider Integration with Next.js App Router Source: https://hirotoshioi.github.io/hiraku/guide/api/modal-provider Illustrates the setup of the ModalProvider within a Next.js application using the App Router. This example shows placing the ModalProvider in the root layout file (`app/layout.tsx`) to ensure modal functionality is available across all pages and components served by the router. ```tsx // app/layout.tsx import { ModalProvider } from "@hirotoshioi/hiraku"; export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( {children} ); } ``` -------------------------------- ### Full Dialog Example - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog A complete example demonstrating the creation of a dialog component, its controller, and its usage. It includes defining props, rendering content, and closing the dialog. ```tsx import { createDialog } from "@hirotoshioi/hiraku"; import { DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; interface Props { name: string; } function GreetingDialog({ name }: Props) { return ( Hello, {name}! ); } export const greetingDialog = createDialog(GreetingDialog); // Usage await greetingDialog.open({ name: "World" }); ``` -------------------------------- ### Example: Form with Confirmation Flow Source: https://hirotoshioi.github.io/hiraku/guide/api/use-modal A comprehensive example demonstrating a common use case: editing a profile with a confirmation step. It shows opening an edit modal, awaiting its closure, checking the result's role and data, and then performing an update operation with user feedback. ```tsx function EditProfileButton({ userId }: { userId: string }) { const editModal = useModal(editProfileDialog); const handleEdit = async () => { await editModal.open({ userId }); const result = await editProfileDialog.onDidClose(); if (result.role === "confirm" && result.data) { await updateProfile(userId, result.data); toast.success("Profile updated!"); } }; return ( ); } ``` -------------------------------- ### Example: Filter Sheet Implementation - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-sheet Provides a complete example of a filter sheet. It includes the sheet component definition, its integration with `createSheet`, and a usage example demonstrating opening the sheet, handling results, and applying filters. ```tsx import { createSheet } from "@hirotoshioi/hiraku"; import { SheetContent, SheetHeader, SheetTitle, } from "@/components/ui/sheet"; import { useState } from "react"; interface FilterProps { categories: string[]; } function FilterSheet({ categories }: FilterProps) { const [selected, setSelected] = useState([]); return ( Filter
{categories.map((cat) => ( ))}
); } export const filterSheet = createSheet(FilterSheet).returns(); // Usage example: async function applyFiltersToData() { const result = await filterSheet.open({ categories: ["Electronics", "Books", "Clothing"] }); const closedResult = await filterSheet.onDidClose(); if (closedResult.data) { applyFilters(closedResult.data); } } function applyFilters(data: string[]) { console.log("Applying filters:", data); } // To trigger the usage example: // applyFiltersToData(); ``` -------------------------------- ### Add ModalProvider to Application Source: https://hirotoshioi.github.io/hiraku/guide/getting-started Wraps your application with the `ModalProvider` component from hiraku. This component is necessary for managing modal states globally within your React application. ```tsx // app.tsx import { ModalProvider } from "@hirotoshioi/hiraku"; function App() { return ( <> ); } ``` -------------------------------- ### Update Usage Site: Opening Modal with Hiraku Controller (TSX) Source: https://hirotoshioi.github.io/hiraku/guide/migration Demonstrates how to update the usage site of a modal component after migrating to hiraku. It replaces state management for modal visibility with calls to the controller's open and onDidClose methods. Requires importing the created controller. ```tsx import { useState } from "react"; import * as Dialog from "@radix-ui/react-dialog"; function App() { const [isOpen, setIsOpen] = useState(false); return ( <> setIsOpen(false)} onConfirm={() => { console.log("Confirmed"); setIsOpen(false); }} message="Are you sure you want to delete?" /> ); } ``` ```tsx import { confirmDialog } from "./modals/confirm-dialog"; function App() { const handleClick = async () => { await confirmDialog.open({ message: "Are you sure you want to delete?" }); const result = await confirmDialog.onDidClose(); if (result.role === "confirm") { console.log("Confirmed"); } }; return ; } ``` -------------------------------- ### Create a Sheet Modal with Hiraku Source: https://hirotoshioi.github.io/hiraku/guide/creating-modals Illustrates the creation of a sheet modal, a slide-out panel ideal for navigation or filters, using `createSheet` from Hiraku. The example shows how to define props and close the sheet with data. ```tsx import { createSheet } from "@hirotoshioi/hiraku"; import { SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet"; interface FilterSheetProps { categories: string[]; } function FilterSheet({ categories }: FilterSheetProps) { const [selected, setSelected] = useState([]); return ( Filters {categories.map((cat) => ( toggle(cat)} /> ))} ); } export const filterSheet = createSheet(FilterSheet).returns(); ``` -------------------------------- ### Hiraku Modal Type Safety Example Source: https://hirotoshioi.github.io/hiraku/guide/creating-modals Highlights Hiraku's automatic prop type inference for modals. It shows correct usage of `open` with required props for `editUserDialog` and demonstrates that `simpleDialog` can be opened with or without an empty object. ```tsx // Props are required editUserDialog.open({ userId: "1", initialName: "John" }); // ✅ editUserDialog.open({ userId: "1" }); // ❌ Missing initialName // No props needed simpleDialog.open(); // ✅ simpleDialog.open({}); // ✅ ``` -------------------------------- ### Get the topmost modal instance with modalController.getTop() Source: https://hirotoshioi.github.io/hiraku/guide/api/modal-controller This example shows how to get the most recently opened modal instance using the `getTop()` method. If a modal is open, its ID is logged to the console. ```tsx const top = modalController.getTop(); if (top) { console.log("Top modal:", top.id); } ``` -------------------------------- ### Check Modal State with Hiraku Source: https://hirotoshioi.github.io/hiraku/guide/opening-closing Demonstrates how to check the open status of a specific modal using `isOpen()` or any modal using `modalController.isOpen()`. It also shows how to get the total count of currently open modals. ```tsx // Check if a specific modal is open if (confirmDialog.isOpen()) { console.log("Confirm dialog is open"); } // Check if any modal is open import { modalController } from "@hirotoshioi/hiraku"; if (modalController.isOpen()) { console.log("Some modal is open"); } // Get the number of open modals const count = modalController.getCount(); ``` -------------------------------- ### Selection Return Modal Example (TSX) Source: https://hirotoshioi.github.io/hiraku/guide/return-values This example illustrates how to create a dialog that returns a selected string value, such as a color. It shows the definition of the dialog and how to access the selected data upon closing. ```tsx export const colorPicker = createDialog(ColorPickerDialog).returns(); // Usage const { data: selectedColor } = await colorPicker.onDidClose(); if (selectedColor) { applyColor(selectedColor); } ``` -------------------------------- ### Boolean Confirmation Modal Example (TSX) Source: https://hirotoshioi.github.io/hiraku/guide/return-values This example shows how to create a dialog that returns a boolean value upon confirmation. It illustrates defining the dialog with a boolean return type and how to check the result after the dialog is closed. ```tsx export const confirmDialog = createDialog(ConfirmDialog).returns(); // Usage const { data, role } = await confirmDialog.onDidClose(); if (role === "confirm" && data === true) { // Confirmed } ``` -------------------------------- ### Define and Use useModal Hook in React Source: https://hirotoshioi.github.io/hiraku/guide/api/use-modal Demonstrates the basic signature and usage of the useModal hook. It requires a ModalController and returns an object with modal state and control functions. The example shows opening a modal with specific properties and displaying its open state. ```tsx import { useModal } from "@hirotoshioi/hiraku"; import { confirmDialog } from "@/modals/confirm-dialog"; function MyComponent() { const modal = useModal(confirmDialog); return ( ); } ``` -------------------------------- ### Form Data Return Modal Example (TSX) Source: https://hirotoshioi.github.io/hiraku/guide/return-values This example demonstrates creating a dialog that returns structured form data. It defines an interface for the form data and shows how to use the returned data after the dialog is closed. ```tsx interface ContactForm { name: string; email: string; message: string; } export const contactDialog = createDialog(ContactDialog).returns(); // Usage const { data } = await contactDialog.onDidClose(); if (data) { await sendMessage(data); } ``` -------------------------------- ### Migrate Radix UI Dialog to Hiraku Modal (TSX) Source: https://hirotoshioi.github.io/hiraku/guide/migration Converts a Radix UI Dialog component to use hiraku's createDialog function. It removes the need for Dialog.Root and manages state internally via the created controller. Dependencies include @radix-ui/react-dialog and @hirotoshioi/hiraku. ```tsx import * as Dialog from "@radix-ui/react-dialog"; function ConfirmDialog({ isOpen, onClose, onConfirm, message }) { return ( Confirm

{message}

); } ``` ```tsx import { createDialog } from "@hirotoshioi/hiraku"; function ConfirmDialog({ message }: { message: string }) { return ( // Dialog.Root is not needed! hiraku wraps it automatically Confirm

{message}

); } export const confirmDialog = createDialog(ConfirmDialog).returns(); ``` -------------------------------- ### Get the number of open modals with modalController.getCount() Source: https://hirotoshioi.github.io/hiraku/guide/api/modal-controller Illustrates how to retrieve the current number of open modals using the `getCount()` method. The returned count is then logged to the console. ```tsx const count = modalController.getCount(); console.log(`${count} modals open`); ``` -------------------------------- ### Multiple Values Return Sheet Example (TSX) Source: https://hirotoshioi.github.io/hiraku/guide/return-values This example shows how to define a sheet that returns multiple values structured within an interface. It demonstrates specifying a complex return type for a sheet component. ```tsx interface FilterResult { categories: string[]; priceRange: [number, number]; sortBy: "price" | "date" | "name"; } export const filterSheet = createSheet(FilterSheet).returns(); ``` -------------------------------- ### Create Dialog Modal Controller - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Defines the createDialog function signature and provides a basic usage example. It takes a component type and returns a ModalController. ```tsx import { createDialog } from "@hirotoshioi/hiraku"; const myDialog = createDialog(MyDialogComponent); ``` -------------------------------- ### Modal Controller API Source: https://hirotoshioi.github.io/hiraku/guide/api/modal-controller Global utilities for managing all modals, including closing all, checking if any are open, getting the count of open modals, and retrieving the topmost modal. ```APIDOC ## Modal Controller API ### Description Global utilities for managing all modals. ### Methods #### `closeAll()` Closes all open modals. ##### Usage ```tsx import { modalController } from "@hirotoshioi/hiraku"; modalController.closeAll(); ``` **Use cases:** * Route navigation * Logout * Error recovery ```tsx // Close all modals on route change useEffect(() => { return () => modalController.closeAll(); }, [pathname]); ``` #### `isOpen()` Returns whether any modal is currently open. ##### Usage ```tsx import { modalController } from "@hirotoshioi/hiraku"; if (modalController.isOpen()) { console.log("A modal is open"); } ``` **Returns:** `boolean` #### `getCount()` Returns the number of open modals. ##### Usage ```tsx import { modalController } from "@hirotoshioi/hiraku"; const count = modalController.getCount(); console.log(`${count} modals open`); ``` **Returns:** `number` #### `getTop()` Returns the topmost (most recently opened) modal instance. ##### Usage ```tsx import { modalController } from "@hirotoshioi/hiraku"; const top = modalController.getTop(); if (top) { console.log("Top modal:", top.id); } ``` **Returns:** `ModalInstance | undefined` ``` -------------------------------- ### Wait for Dialog Close - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Demonstrates using the `onDidClose` method to get a promise that resolves when the modal is closed. The resolved value contains the modal's result data and role. ```tsx const result = await myDialog.onDidClose(); // result: { data?: T, role?: ModalRole } ``` -------------------------------- ### Get Count of Open Modals using modalController Source: https://hirotoshioi.github.io/hiraku/guide/modal-controller Demonstrates the `getCount` method, which returns the number of modals that are currently open. This information can be used for debugging or for implementing specific UI behaviors that depend on the number of active modals. ```tsx const count = modalController.getCount(); console.log(`${count} modals are open`); ``` -------------------------------- ### Get Topmost Modal Instance with modalController Source: https://hirotoshioi.github.io/hiraku/guide/modal-controller Shows how to retrieve the most recently opened modal instance using the `getTop` method. If a modal is open, this method returns its instance, allowing access to its properties like `id` for targeted interactions or logging. ```tsx const topModal = modalController.getTop(); if (topModal) { console.log("Top modal ID:", topModal.id); } ``` -------------------------------- ### Close Modal from Inside Dialog Source: https://hirotoshioi.github.io/hiraku/guide/opening-closing Provides examples of how to close a modal from within its own component. It shows closing without a role, with a confirm role, and with both data and a confirm role. ```tsx function MyDialog() { return ( ); } ``` -------------------------------- ### Dialog with No Return Value (TSX) Source: https://hirotoshioi.github.io/hiraku/guide/return-values This example demonstrates creating a dialog without a specific return value. It shows how to omit the `.returns()` method and still access the modal's closing role. ```tsx export const infoDialog = createDialog(InfoDialog); // Still get the role const { role } = await infoDialog.onDidClose(); if (role === "dismiss") { // User dismissed the dialog } ``` -------------------------------- ### Getting the Last Close Role with 'role' Source: https://hirotoshioi.github.io/hiraku/guide/api/use-modal Illustrates how to use the `role` property to determine the action taken when the modal was last closed. This is often used within a `useEffect` hook to trigger specific logic based on the user's interaction, such as confirming or canceling an action. ```tsx const { role } = useModal(myDialog); useEffect(() => { if (role === "confirm") { // Handle confirmation } }, [role]); ``` -------------------------------- ### Basic useModal Hook Usage in React Source: https://hirotoshioi.github.io/hiraku/guide/using-hooks Demonstrates the basic integration of the `useModal` hook to manage modal visibility and open it with specific props. It shows how to access the `isOpen` state and the `open` function from the hook. ```tsx import { useModal } from "@hirotoshioi/hiraku"; import { confirmDialog } from "@/modals/confirm-dialog"; function MyComponent() { const modal = useModal(confirmDialog); return (

Modal is {modal.isOpen ? "open" : "closed"}

); } ``` -------------------------------- ### Open Dialog Modal - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Shows how to open a modal using the `open` method of the ModalController. It accepts component props as an argument and returns a Promise that resolves when the modal is presented. ```tsx await myDialog.open({ title: "Hello" }); ``` -------------------------------- ### Create a Simple Dialog Modal Without Props in Hiraku Source: https://hirotoshioi.github.io/hiraku/guide/creating-modals Demonstrates creating a basic dialog modal using `createDialog` that does not require any props. This is useful for simple notifications or messages that don't need dynamic data. The modal can be opened without arguments. ```tsx function SimpleDialog() { return ( Hello! ); } export const simpleDialog = createDialog(SimpleDialog); // Open without arguments await simpleDialog.open(); ``` -------------------------------- ### Managing Reactive Modal State with useModal Source: https://hirotoshioi.github.io/hiraku/guide/using-hooks Illustrates how the `useModal` hook provides reactive `isOpen` state that updates automatically when the modal's visibility changes. This allows components to react to the modal's open/closed status, shown here with conditional rendering and styling. ```tsx function StatusIndicator() { const { isOpen } = useModal(confirmDialog); return (
{isOpen && }
); } ``` -------------------------------- ### Basic Usage of createAlertDialog - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-alert-dialog Demonstrates the basic import and usage of the createAlertDialog function. It shows how to create an alert dialog controller by passing a React component to the function. This is the initial step in setting up an alert dialog. ```tsx import { createAlertDialog } from "@hirotoshioi/hiraku"; const myAlertDialog = createAlertDialog(MyAlertDialogComponent); ``` -------------------------------- ### Open Dialog from Event Handler Source: https://hirotoshioi.github.io/hiraku/guide/opening-closing Shows how to open a dialog from an event handler, such as a button click. It also demonstrates how to wait for the dialog to close and process the result, including performing an action based on the user's role selection. ```tsx function DeleteButton({ itemId }: { itemId: string }) { const handleClick = async () => { await confirmDialog.open({ title: "Delete item", message: "Delete this item?", }); const result = await confirmDialog.onDidClose(); if (result.role === "confirm") { await deleteItem(itemId); } }; return ; } ``` -------------------------------- ### Open Confirm Dialog (Basic Usage) Source: https://hirotoshioi.github.io/hiraku/guide/opening-closing Demonstrates the basic usage of opening a confirmation dialog with a title and message using the `confirmDialog.open` function. This is typically used in React components. ```tsx import { confirmDialog } from "@/modals/confirm-dialog"; // Open with props await confirmDialog.open({ title: "Confirm Action", message: "Are you sure?", }); ``` -------------------------------- ### Import modalController from '@hirotoshioi/hiraku' Source: https://hirotoshioi.github.io/hiraku/guide/api/modal-controller This snippet shows how to import the modalController utility from the '@hirotoshioi/hiraku' package. This is the first step to using any of the modal management functions. ```tsx import { modalController } from "@hirotoshioi/hiraku"; ``` -------------------------------- ### Create a Dialog Modal with Hiraku Source: https://hirotoshioi.github.io/hiraku/guide/creating-modals Demonstrates how to create a common dialog modal using `createDialog` from Hiraku. This modal is suitable for forms, confirmations, and general content. It infers return types and can be opened with specific props. ```tsx import { createDialog } from "@hirotoshioi/hiraku"; import { DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; interface EditUserProps { userId: string; initialName: string; } function EditUserDialog({ userId, initialName }: EditUserProps) { const [name, setName] = useState(initialName); return ( Edit User setName(e.target.value)} /> ); } export const editUserDialog = createDialog(EditUserDialog).returns(); ``` -------------------------------- ### Create an AlertDialog Modal with Hiraku Source: https://hirotoshioi.github.io/hiraku/guide/creating-modals Shows how to create an alert dialog for critical confirmations using `createAlertDialog` from Hiraku. This modal requires explicit user action and cannot be dismissed by clicking outside. It includes cancel and action buttons. ```tsx import { createAlertDialog } from "@hirotoshioi/hiraku"; import { AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, } from "@/components/ui/alert-dialog"; interface DeleteConfirmProps { itemName: string; } function DeleteConfirm({ itemName }: DeleteConfirmProps) { return ( Delete {itemName}? This action cannot be undone. deleteConfirm.close({ role: "cancel" }) }> Cancel deleteConfirm.close({ role: "confirm" }) }> Delete ); } export const deleteConfirm = createAlertDialog(DeleteConfirm); ``` -------------------------------- ### Handling Modal Close Results with useModal Source: https://hirotoshioi.github.io/hiraku/guide/using-hooks Shows how to handle the results returned when a modal is closed after being opened using the `useModal` hook. It demonstrates awaiting the modal's `open` promise and then checking the `result.role` to perform actions based on user interaction. ```tsx function DeleteButton({ itemId }: { itemId: string }) { const confirmModal = useModal(confirmDialog); const handleDelete = async () => { await confirmModal.open({ title: "Delete Item", message: "Are you sure?", }); // Wait for close const result = await confirmDialog.onDidClose(); if (result.role === "confirm") { await deleteItem(itemId); } }; return ( ); } ``` -------------------------------- ### useModal Hook Return Values and Properties Source: https://hirotoshioi.github.io/hiraku/guide/using-hooks Details the properties returned by the `useModal` hook, including `isOpen` for modal state, `open` and `close` functions for control, `data` for props, and `role` for close status. This helps understand how to interact with the modal's state and lifecycle. ```tsx const { isOpen, open, close, data, role, } = useModal(modalController); ``` -------------------------------- ### Basic ModalProvider Usage in React App Source: https://hirotoshioi.github.io/hiraku/guide/api/modal-provider Demonstrates how to integrate the ModalProvider component into the root of a React application. This component is essential for rendering and managing all active modals. It should be placed at the root level to ensure modals are accessible throughout the app. ```tsx import { ModalProvider } from "@hirotoshioi/hiraku"; function App() { return ( <> ); } ``` -------------------------------- ### Opening a Modal with Custom Props Source: https://hirotoshioi.github.io/hiraku/guide/api/use-modal Shows how to trigger the `open` function provided by useModal to display a modal with specific data. The `open` function accepts props that will be available within the modal component. ```tsx const { open } = useModal(myDialog); await open({ title: "Hello" }); ``` -------------------------------- ### Sheet Controller Methods - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-sheet Demonstrates the controller methods available for a sheet, including `open`, `close`, `onDidClose`, and `isOpen`. These methods are identical to those provided by `createDialog`. ```tsx import { createSheet } from "@hirotoshioi/hiraku"; function MySheetComponent() {} const mySheet = createSheet(MySheetComponent); // Open the sheet with props // mySheet.open({ someProp: 'value' }); // Close the sheet with a result // mySheet.close({ data: 'someResult' }); // Get a promise that resolves when the sheet is closed // const result = await mySheet.onDidClose(); // Check if the sheet is currently open // const isOpen = mySheet.isOpen(); ``` -------------------------------- ### ModalController Methods Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Provides an overview of the methods available on a modal controller created by `createDialog`. ```APIDOC ## Controller Methods ### open(props) Opens the modal with the provided props. #### Method `await` #### Endpoint `myDialog.open(props)` #### Parameters - **props** (object) - Required - Component props for the modal. Required if the component has required props. #### Response #### Success Response (Promise) - Resolves when the modal is presented. #### Request Example ```tsx await myDialog.open({ title: "Hello" }); ``` ### close(result?) Closes the modal with an optional result. #### Method (none - synchronous) #### Endpoint `myDialog.close(result?)` #### Parameters - **result.data** (T) - Optional - Return value of the modal, where `T` is the type specified via `.returns()`. - **result.role** (string) - Optional - How the modal was closed (e.g., `"confirm"`, `"cancel"`, `"dismiss"`). #### Request Example ```tsx myDialog.close(); myDialog.close({ role: "confirm" }); myDialog.close({ data: "result", role: "confirm" }); ``` ### onDidClose() Returns a promise that resolves when the modal has been closed. #### Method `await` #### Endpoint `myDialog.onDidClose()` #### Returns - **Promise>** - A promise that resolves with the modal's result. #### Response Example ```tsx const result = await myDialog.onDidClose(); // result: { data?: T, role?: ModalRole } ``` ### isOpen() Returns whether the modal is currently open. #### Method (none - synchronous) #### Endpoint `myDialog.isOpen()` #### Returns - **boolean** - `true` if the modal is open, `false` otherwise. #### Request Example ```tsx if (myDialog.isOpen()) { console.log("Modal is open"); } ``` ``` -------------------------------- ### Typed Return Value for createAlertDialog - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-alert-dialog Illustrates how to specify a return type for the alert dialog using the .returns() method. This allows for type safety when handling the data returned after the dialog is closed. It improves code reliability by enforcing expected data structures. ```tsx const myAlertDialog = createAlertDialog(MyAlertDialogComponent).returns(); ``` -------------------------------- ### Create Dialog with Return Type - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Demonstrates how to specify a return type for the dialog using the `.returns()` method. This is useful for strongly typing the result when the modal is closed. ```tsx const myDialog = createDialog(MyDialogComponent).returns(); ``` -------------------------------- ### Controlling Modal Visibility with isOpen Source: https://hirotoshioi.github.io/hiraku/guide/api/use-modal Illustrates how to use the `isOpen` boolean returned by useModal to conditionally render UI elements or apply styles. This is useful for visual feedback, such as blurring the background when a modal is active. ```tsx const { isOpen } = useModal(myDialog); return (
); ``` -------------------------------- ### Automatic Modal Cleanup on Component Unmount Source: https://hirotoshioi.github.io/hiraku/guide/using-hooks Explains and demonstrates the automatic cleanup feature of the `useModal` hook, where any modal opened by a hook instance is automatically closed when its associated component unmounts. This prevents orphaned modals and memory leaks. ```tsx function TemporaryComponent() { const modal = useModal(formDialog); useEffect(() => { modal.open({ /* ... */ }); // Modal will be closed when component unmounts }, []); return
...
; } ``` -------------------------------- ### React Parent Component with hiraku Modal Integration Source: https://hirotoshioi.github.io/hiraku/guide/why-hiraku This React component illustrates how hiraku simplifies modal opening by using a global modal controller. Instead of managing state locally, it directly calls a modal's open function, delegating state management to hiraku's global store for a cleaner, decoupled approach. ```tsx import { confirmDialog } from "./modals/confirm-dialog"; function Parent() { // This is no longer needed // const [isOpen, setIsOpen] = useState(false); return ( <> ); } ``` -------------------------------- ### Managing Multiple Modals Simultaneously in React Source: https://hirotoshioi.github.io/hiraku/guide/using-hooks Illustrates how to use multiple instances of the `useModal` hook within a single React component to manage different modals independently. Each hook instance controls its own modal's state and lifecycle. ```tsx function Dashboard() { const confirmModal = useModal(confirmDialog); const editModal = useModal(editDialog); const filterSheet = useModal(filterSheet); return (
); } ``` -------------------------------- ### createAlertDialog Source: https://hirotoshioi.github.io/hiraku/guide/api/create-alert-dialog Creates an alert dialog modal controller. Alert dialogs are used for important confirmations and cannot be dismissed by clicking outside. ```APIDOC ## createAlertDialog ### Description Creates an alert dialog modal controller. Alert dialogs are used for important confirmations and cannot be dismissed by clicking outside. ### Method Not Applicable (Function Signature) ### Endpoint Not Applicable (Function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```tsx import { createAlertDialog } from "@hirotoshioi/hiraku"; const myAlertDialog = createAlertDialog(MyAlertDialogComponent); ``` ### Response #### Success Response (200) - **ModalController** (object) - A controller object for the alert dialog. #### Response Example ```json { "open": "function", "close": "function", "onDidClose": "function", "isOpen": "function" } ``` ### Controller Methods - **open(props)**: Opens the alert dialog. - **close(result?)**: Closes the alert dialog. - **onDidClose()**: Promise that resolves on close. - **isOpen()**: Check if alert dialog is open. ### Difference from Dialog | Feature | Dialog | AlertDialog | |------------------------|-----------------|-----------------| | Click outside to close | ✅ | ❌ | | Press Escape to close | ✅ | ❌ | | Use case | General content | Important confirmations | ``` -------------------------------- ### Check if any modal is open with modalController.isOpen() Source: https://hirotoshioi.github.io/hiraku/guide/api/modal-controller This code snippet shows how to check if there are any modals currently open using the `isOpen()` method. It logs a message to the console if a modal is detected. ```tsx if (modalController.isOpen()) { console.log("A modal is open"); } ``` -------------------------------- ### Close all open modals using modalController Source: https://hirotoshioi.github.io/hiraku/guide/api/modal-controller Demonstrates how to close all currently open modals using the `closeAll()` method. This is useful for scenarios like route navigation, logout, or error recovery to ensure a clean state. ```tsx modalController.closeAll(); ``` ```tsx // Close all modals on route change useEffect(() => { return () => modalController.closeAll(); }, [pathname]); ``` -------------------------------- ### Check if Dialog is Open - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Shows how to check if the modal is currently open using the `isOpen` method, which returns a boolean value. ```tsx if (myDialog.isOpen()) { console.log("Modal is open"); } ``` -------------------------------- ### createDialog Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Creates a dialog modal controller for a given React component. This controller provides methods to manage the lifecycle of the modal. ```APIDOC ## createDialog ### Description Creates a dialog modal controller for a specified component. ### Signature ```tsx function createDialog>( component: T ): ModalController; ``` ### Usage ```tsx import { createDialog } from "@hirotoshioi/hiraku"; const myDialog = createDialog(MyDialogComponent); ``` ### With Return Type Specify the expected return type of the modal using `.returns()`. ```tsx const myDialog = createDialog(MyDialogComponent).returns(); ``` ``` -------------------------------- ### Close All Modals using modalController Source: https://hirotoshioi.github.io/hiraku/guide/modal-controller Shows how to close all currently open modal windows using the `closeAll` method of the modalController. This is particularly useful during navigation changes, logout actions, or error recovery scenarios to ensure a clean UI state. ```tsx // Close all modals immediately modalController.closeAll(); ``` ```tsx // Example: Close modals on route change useEffect(() => { return () => { modalController.closeAll(); }; }, [pathname]); ``` -------------------------------- ### Handle Modal Close Results by Role Source: https://hirotoshioi.github.io/hiraku/guide/opening-closing Explains how to interpret the role assigned when a modal is closed, allowing for different actions based on whether the user confirmed, cancelled, dismissed, or provided a custom role. ```tsx const result = await myDialog.onDidClose(); switch (result.role) { case "confirm": // Handle confirmation break; case "cancel": // Handle cancellation break; case "dismiss": // Handle dismissal break; } ``` -------------------------------- ### Accessing Modal Props with 'data' Source: https://hirotoshioi.github.io/hiraku/guide/api/use-modal Explains how to retrieve the data (`props`) that were passed when the modal was opened using the `data` property from the useModal return value. This allows components to access information relevant to the currently displayed modal. ```tsx const { data } = useModal(myDialog); if (data) { console.log("Modal opened with:", data); } ``` -------------------------------- ### Close All Modals with Modal Controller Source: https://hirotoshioi.github.io/hiraku/guide/opening-closing Shows how to close all currently open modals using the `modalController.closeAll()` function from the hiraku library. ```tsx import { modalController } from "@hirotoshioi/hiraku"; // Close all open modals modalController.closeAll(); ``` -------------------------------- ### React Parent Component with Traditional Modal State Source: https://hirotoshioi.github.io/hiraku/guide/why-hiraku This React component demonstrates the conventional pattern for managing modal state using `useState`. The parent component controls the `isOpen` and `onClose` props, which can lead to prop drilling and code bloat as the application grows, especially with multiple modals. ```tsx import { useState } from 'react'; function Parent() { const [isOpen, setIsOpen] = useState(false); return ( <> setIsOpen(false)} /> ); } ``` -------------------------------- ### Type Inference for Dialog Props - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Highlights the type safety provided by `createDialog`. Props passed to `open` are automatically inferred from the dialog component, preventing type errors. ```tsx // ✅ Type-safe greetingDialog.open({ name: "World" }); // ❌ Type error: missing 'name' greetingDialog.open({}); // ❌ Type error: unknown prop greetingDialog.open({ name: "World", foo: "bar" }); ``` -------------------------------- ### Create Sheet Modal Controller - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-sheet Creates a sheet modal controller for a given component. It utilizes a generic type `T` for the component and returns a `ModalController`. ```tsx import { createSheet } from "@hirotoshioi/hiraku"; function MySheetComponent() {} const mySheet = createSheet(MySheetComponent); ``` -------------------------------- ### Create Sheet with Return Type - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-sheet Extends the `createSheet` functionality by allowing a specific return type to be defined using the `.returns()` method. This enhances type safety for modal results. ```tsx interface ResultType {} function MySheetComponent() {} const mySheet = createSheet(MySheetComponent).returns(); ``` -------------------------------- ### Close Dialog Modal - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-dialog Illustrates how to close the modal using the `close` method. It can be called with an optional result object containing `data` and `role` properties. ```tsx myDialog.close(); myDialog.close({ role: "confirm" }); myDialog.close({ data: "result", role: "confirm" }); ``` -------------------------------- ### Open Error Dialog from Utility Function Source: https://hirotoshioi.github.io/hiraku/guide/opening-closing Illustrates opening a modal, specifically an error dialog, from outside a React component, such as within a utility function or API call. This highlights hiraku's flexibility in managing modals from any part of the application. ```tsx // utils/api.ts - Not a React component! import { errorDialog } from "@/modals/error-dialog"; export async function fetchData() { try { const response = await fetch("/api/data"); return response.json(); } catch (error) { // Open modal from utility function await errorDialog.open({ message: "Failed to fetch data", error: error.message, }); } } ``` -------------------------------- ### Create Alert Dialog Function Signature - TSX Source: https://hirotoshioi.github.io/hiraku/guide/api/create-alert-dialog Defines the TypeScript signature for the createAlertDialog function. It takes a ComponentType and returns a ModalController. This function is used to create modal dialogs that require important confirmations. ```tsx function createAlertDialog>( component: T ): ModalController; ```