modal-system 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -688,7 +688,9 @@ async function main() {
688
688
  message: "Which UI library are you using?",
689
689
  options: [
690
690
  { value: "shadcn", label: "shadcn/ui" },
691
- { value: "daisyui", label: "DaisyUI" }
691
+ { value: "daisyui", label: "DaisyUI" },
692
+ { value: "chakra", label: "Chakra UI" },
693
+ { value: "ark", label: "Ark UI" }
692
694
  ]
693
695
  });
694
696
  if (lD(uiLibrary)) {
@@ -710,7 +712,7 @@ async function main() {
710
712
  }
711
713
  variant = `shadcn-${primitive}`;
712
714
  } else {
713
- variant = "daisyui";
715
+ variant = uiLibrary;
714
716
  }
715
717
  const modalsDir = await te({
716
718
  message: "Where should the modals folder be created?",
@@ -756,7 +758,7 @@ async function main() {
756
758
  le(
757
759
  [
758
760
  `${import_picocolors3.default.bold("1.")} Install dependencies:`,
759
- uiLibrary === "daisyui" ? import_picocolors3.default.cyan(" bun add zustand daisyui") : variant === "shadcn-radix" ? import_picocolors3.default.cyan(" bun add zustand @radix-ui/react-dialog") : import_picocolors3.default.cyan(" bun add zustand @base-ui-components/react"),
761
+ uiLibrary === "daisyui" ? import_picocolors3.default.cyan(" bun add zustand daisyui") : uiLibrary === "chakra" ? import_picocolors3.default.cyan(" bun add zustand @chakra-ui/react @emotion/react") : uiLibrary === "ark" ? import_picocolors3.default.cyan(" bun add zustand @ark-ui/react") : variant === "shadcn-radix" ? import_picocolors3.default.cyan(" bun add zustand @radix-ui/react-dialog") : import_picocolors3.default.cyan(" bun add zustand @base-ui-components/react"),
760
762
  "",
761
763
  `${import_picocolors3.default.bold("2.")} Wrap your app in the provider:`,
762
764
  import_picocolors3.default.cyan(` import { ModalProvider } from "modal-system"`),
@@ -0,0 +1,74 @@
1
+ /**
2
+ * ConfirmModal.tsx (Ark UI)
3
+ *
4
+ * Ark UI is headless — the markup below is styled with Tailwind classes.
5
+ * bun add @ark-ui/react
6
+ */
7
+
8
+ import { Dialog } from "@ark-ui/react/dialog";
9
+ import { Portal } from "@ark-ui/react/portal";
10
+ import type { BaseModalProps } from "modal-system";
11
+ import type { ConfirmModalData } from "./modals";
12
+
13
+ export function ConfirmModal({
14
+ isOpen,
15
+ onClose,
16
+ data,
17
+ }: BaseModalProps<ConfirmModalData>) {
18
+ const handleClose = () => {
19
+ data?.onCancel?.();
20
+ onClose();
21
+ };
22
+
23
+ const handleConfirm = () => {
24
+ data?.onConfirm?.();
25
+ onClose();
26
+ };
27
+
28
+ return (
29
+ <Dialog.Root
30
+ open={isOpen}
31
+ onOpenChange={(e) => !e.open && handleClose()}
32
+ >
33
+ <Portal>
34
+ <Dialog.Backdrop className="fixed inset-0 z-50 bg-black/50 transition-opacity data-[state=closed]:opacity-0 data-[state=open]:opacity-100" />
35
+
36
+ <Dialog.Positioner className="fixed inset-0 z-50 flex items-center justify-center p-4">
37
+ <Dialog.Content className="relative w-full max-w-md min-h-40 rounded-lg bg-white p-6 shadow-lg transition-all data-[state=closed]:opacity-0 data-[state=closed]:scale-95 data-[state=open]:opacity-100 dark:bg-zinc-900">
38
+ <div className="flex flex-col gap-1">
39
+ <Dialog.Title className="text-lg font-semibold">
40
+ {data?.title ?? "Are you sure?"}
41
+ </Dialog.Title>
42
+ {data?.description && (
43
+ <Dialog.Description className="text-xs text-zinc-500 dark:text-zinc-400">
44
+ {data.description}
45
+ </Dialog.Description>
46
+ )}
47
+ </div>
48
+
49
+ <div className="absolute bottom-3 right-3 flex gap-1">
50
+ <Dialog.CloseTrigger
51
+ className="inline-flex h-9 items-center justify-center rounded-md bg-zinc-100 px-4 text-sm font-medium text-zinc-900 shadow-sm transition-colors hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700"
52
+ onClick={handleClose}
53
+ >
54
+ {data?.closeText ?? "Cancel"}
55
+ </Dialog.CloseTrigger>
56
+
57
+ <button
58
+ type="button"
59
+ onClick={handleConfirm}
60
+ className={`inline-flex h-9 items-center justify-center rounded-md px-4 text-sm font-medium text-white shadow transition-colors ${
61
+ data?.isActionButtonDestructive
62
+ ? "bg-red-600 hover:bg-red-700"
63
+ : "bg-blue-600 hover:bg-blue-700"
64
+ }`}
65
+ >
66
+ {data?.actionText ?? "Confirm"}
67
+ </button>
68
+ </div>
69
+ </Dialog.Content>
70
+ </Dialog.Positioner>
71
+ </Portal>
72
+ </Dialog.Root>
73
+ );
74
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * modals/index.ts
3
+ *
4
+ * Register your modal components here.
5
+ * The key you use (e.g. "confirm") becomes the name you pass to openModal().
6
+ */
7
+
8
+ import { defineModals, createModalHook } from "modal-system";
9
+
10
+ import { ConfirmModal } from "./ConfirmModal";
11
+ // import { DeleteUserModal } from "./DeleteUserModal";
12
+
13
+ export const MODALS = defineModals({
14
+ confirm: ConfirmModal,
15
+ // deleteUser: DeleteUserModal,
16
+ });
17
+
18
+ // Import `useModal` from THIS file in your components — it is typed to your registry.
19
+ export const useModal = createModalHook(MODALS);
@@ -0,0 +1,37 @@
1
+ /**
2
+ * modals.ts
3
+ *
4
+ * Define the data interface for each modal here.
5
+ * The key must match the name you register in index.ts.
6
+ *
7
+ * Your component receives these fields via the `data` prop:
8
+ * function ConfirmModal({ data }: BaseModalProps<ConfirmModalData>) {
9
+ * data?.title
10
+ * }
11
+ */
12
+
13
+ import type { ReactNode } from "react";
14
+
15
+ // ── Add your own modals below ────────────────────────────────────────────────
16
+
17
+ export interface ConfirmModalData {
18
+ title?: string;
19
+ description?: string | ReactNode;
20
+ /** Confirm button label. Defaults to "Confirm" */
21
+ actionText?: string;
22
+ /** Cancel button label. Defaults to "Cancel" */
23
+ closeText?: string;
24
+ /** Called when the user clicks the confirm button */
25
+ onConfirm?: () => void;
26
+ /** Called when the user clicks the cancel / X button */
27
+ onCancel?: () => void;
28
+ /** Renders the confirm button with destructive (red) variant */
29
+ isActionButtonDestructive?: boolean;
30
+ }
31
+
32
+ // Example of another modal:
33
+ // export interface DeleteUserModalData {
34
+ // userId: string;
35
+ // userName: string;
36
+ // onDeleted?: () => void;
37
+ // }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * ConfirmModal.tsx (Chakra UI v3)
3
+ *
4
+ * Uses the Chakra UI v3 Dialog component:
5
+ * bun add @chakra-ui/react @emotion/react
6
+ */
7
+
8
+ import {
9
+ Dialog,
10
+ Portal,
11
+ Button,
12
+ CloseButton,
13
+ Text,
14
+ } from "@chakra-ui/react";
15
+ import type { BaseModalProps } from "modal-system";
16
+ import type { ConfirmModalData } from "./modals";
17
+
18
+ export function ConfirmModal({
19
+ isOpen,
20
+ onClose,
21
+ data,
22
+ }: BaseModalProps<ConfirmModalData>) {
23
+ const handleClose = () => {
24
+ data?.onCancel?.();
25
+ onClose();
26
+ };
27
+
28
+ const handleConfirm = () => {
29
+ data?.onConfirm?.();
30
+ onClose();
31
+ };
32
+
33
+ return (
34
+ <Dialog.Root
35
+ open={isOpen}
36
+ onOpenChange={(e) => !e.open && handleClose()}
37
+ placement="center"
38
+ >
39
+ <Portal>
40
+ <Dialog.Backdrop />
41
+ <Dialog.Positioner>
42
+ <Dialog.Content>
43
+ <Dialog.Header>
44
+ <Dialog.Title>{data?.title ?? "Are you sure?"}</Dialog.Title>
45
+ </Dialog.Header>
46
+
47
+ {data?.description && (
48
+ <Dialog.Body>
49
+ <Text fontSize="sm" color="fg.muted">
50
+ {data.description}
51
+ </Text>
52
+ </Dialog.Body>
53
+ )}
54
+
55
+ <Dialog.Footer>
56
+ <Button variant="outline" onClick={handleClose}>
57
+ {data?.closeText ?? "Cancel"}
58
+ </Button>
59
+ <Button
60
+ colorPalette={data?.isActionButtonDestructive ? "red" : "blue"}
61
+ onClick={handleConfirm}
62
+ >
63
+ {data?.actionText ?? "Confirm"}
64
+ </Button>
65
+ </Dialog.Footer>
66
+
67
+ <Dialog.CloseTrigger asChild>
68
+ <CloseButton size="sm" onClick={handleClose} />
69
+ </Dialog.CloseTrigger>
70
+ </Dialog.Content>
71
+ </Dialog.Positioner>
72
+ </Portal>
73
+ </Dialog.Root>
74
+ );
75
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * modals/index.ts
3
+ *
4
+ * Register your modal components here.
5
+ * The key you use (e.g. "confirm") becomes the name you pass to openModal().
6
+ */
7
+
8
+ import { defineModals, createModalHook } from "modal-system";
9
+
10
+ import { ConfirmModal } from "./ConfirmModal";
11
+ // import { DeleteUserModal } from "./DeleteUserModal";
12
+
13
+ export const MODALS = defineModals({
14
+ confirm: ConfirmModal,
15
+ // deleteUser: DeleteUserModal,
16
+ });
17
+
18
+ // Import `useModal` from THIS file in your components — it is typed to your registry.
19
+ export const useModal = createModalHook(MODALS);
@@ -0,0 +1,37 @@
1
+ /**
2
+ * modals.ts
3
+ *
4
+ * Define the data interface for each modal here.
5
+ * The key must match the name you register in index.ts.
6
+ *
7
+ * Your component receives these fields via the `data` prop:
8
+ * function ConfirmModal({ data }: BaseModalProps<ConfirmModalData>) {
9
+ * data?.title
10
+ * }
11
+ */
12
+
13
+ import type { ReactNode } from "react";
14
+
15
+ // ── Add your own modals below ────────────────────────────────────────────────
16
+
17
+ export interface ConfirmModalData {
18
+ title?: string;
19
+ description?: string | ReactNode;
20
+ /** Confirm button label. Defaults to "Confirm" */
21
+ actionText?: string;
22
+ /** Cancel button label. Defaults to "Cancel" */
23
+ closeText?: string;
24
+ /** Called when the user clicks the confirm button */
25
+ onConfirm?: () => void;
26
+ /** Called when the user clicks the cancel / X button */
27
+ onCancel?: () => void;
28
+ /** Renders the confirm button with destructive (red) color palette */
29
+ isActionButtonDestructive?: boolean;
30
+ }
31
+
32
+ // Example of another modal:
33
+ // export interface DeleteUserModalData {
34
+ // userId: string;
35
+ // userName: string;
36
+ // onDeleted?: () => void;
37
+ // }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modal-system",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Type-safe modal management system for React with DaisyUI and shadcn/ui support",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",