@bouku/modal 0.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.
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" width="1em" height="1em">
2
+ <path
3
+ d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"
4
+ fill="currentColor"
5
+ />
6
+ </svg>
@@ -0,0 +1,3 @@
1
+ export * from "./ui/index.js";
2
+ export { default as ModalProvider } from "./state/provider";
3
+ export { default as useModal } from "./state/context";
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.useModal = exports.ModalProvider = void 0;
21
+ __exportStar(require("./ui/index.js"), exports);
22
+ var provider_1 = require("./state/provider");
23
+ Object.defineProperty(exports, "ModalProvider", { enumerable: true, get: function () { return __importDefault(provider_1).default; } });
24
+ var context_1 = require("./state/context");
25
+ Object.defineProperty(exports, "useModal", { enumerable: true, get: function () { return __importDefault(context_1).default; } });
@@ -0,0 +1,12 @@
1
+ import { JsonMap } from "ts-helper-kit";
2
+ import { ReactNode } from "react";
3
+ export type Props = {
4
+ activeId?: string;
5
+ modal: ReactNode;
6
+ parameters: JsonMap;
7
+ openModal: (modal: string, params?: JsonMap) => void;
8
+ closeModal: () => void;
9
+ };
10
+ export declare const Context: import("react").Context<Props>;
11
+ export declare const useModal: () => Props;
12
+ export default useModal;
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.useModal = exports.Context = void 0;
5
+ const react_1 = require("react");
6
+ exports.Context = (0, react_1.createContext)({
7
+ modal: null,
8
+ parameters: {},
9
+ openModal: () => undefined,
10
+ closeModal: () => undefined
11
+ });
12
+ const useModal = () => (0, react_1.useContext)(exports.Context);
13
+ exports.useModal = useModal;
14
+ exports.default = exports.useModal;
@@ -0,0 +1,29 @@
1
+ import type { ReactElement, ReactNode } from "react";
2
+ /**
3
+ * React Context Provider for Modal component.
4
+ *
5
+ * Supplies modal state and control functions to its children,
6
+ * enabling centralized management of modal configuration, visibility,
7
+ * and parameters throughout the app.
8
+ *
9
+ * Features:
10
+ * - Tracks the currently active modal by its key from the `config` object.
11
+ * - Stores and provides `parameters` for the active modal instance.
12
+ * - Exposes `openModal` and `closeModal` functions for controlling modal state.
13
+ * - Passes modal configuration and state to consumers via context value.
14
+ * - Renders the `RootModal` component for global modal handling.
15
+ *
16
+ * @param {Record<string, ReactElement>} config - A map of modal ID keys to the component itself.
17
+ * @param {ReactNode} children - Child components that will have access to modals.
18
+ **/
19
+ export default function ModalProvider({ config, children }: {
20
+ config: Record<string, ReactElement>;
21
+ children: ReactNode;
22
+ }): import("react/jsx-runtime").JSX.Element;
23
+ /**
24
+ * Problems:
25
+ *
26
+ * - Perfect `Context`.
27
+ * - Perfect `RootModal`.
28
+ * - Perfect `Config`.
29
+ **/
@@ -0,0 +1,47 @@
1
+ "use client";
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.default = ModalProvider;
8
+ const jsx_runtime_1 = require("react/jsx-runtime");
9
+ const react_1 = require("react");
10
+ const context_1 = require("./context");
11
+ const root_1 = __importDefault(require("./root"));
12
+ /**
13
+ * React Context Provider for Modal component.
14
+ *
15
+ * Supplies modal state and control functions to its children,
16
+ * enabling centralized management of modal configuration, visibility,
17
+ * and parameters throughout the app.
18
+ *
19
+ * Features:
20
+ * - Tracks the currently active modal by its key from the `config` object.
21
+ * - Stores and provides `parameters` for the active modal instance.
22
+ * - Exposes `openModal` and `closeModal` functions for controlling modal state.
23
+ * - Passes modal configuration and state to consumers via context value.
24
+ * - Renders the `RootModal` component for global modal handling.
25
+ *
26
+ * @param {Record<string, ReactElement>} config - A map of modal ID keys to the component itself.
27
+ * @param {ReactNode} children - Child components that will have access to modals.
28
+ **/
29
+ function ModalProvider({ config, children }) {
30
+ const [activeModal, setActiveModal] = (0, react_1.useState)();
31
+ const [parameters, setParameters] = (0, react_1.useState)({});
32
+ const openModal = async (modal, params) => {
33
+ setActiveModal(modal);
34
+ setParameters(params || {});
35
+ };
36
+ const closeModal = () => {
37
+ setActiveModal(undefined);
38
+ setParameters({});
39
+ };
40
+ return ((0, jsx_runtime_1.jsxs)(context_1.Context.Provider, { value: {
41
+ activeId: activeModal,
42
+ openModal,
43
+ modal: activeModal ? config[activeModal] : null,
44
+ parameters,
45
+ closeModal
46
+ }, children: [children, (0, jsx_runtime_1.jsx)(root_1.default, {})] }));
47
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Root Modal component
3
+ *
4
+ * Injected into the root layout in a hidden state,
5
+ * then when a modal is opened this is displayed and wraps
6
+ * the new modal with a backdrop.
7
+ **/
8
+ export default function RootModal(): import("react/jsx-runtime").JSX.Element;
9
+ /**
10
+ * Problems:
11
+ *
12
+ * - Perfect `useModal`
13
+ * - Perfect `Animation`
14
+ **/
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.default = RootModal;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const context_1 = require("./context");
7
+ const react_1 = require("@bouko/react");
8
+ /**
9
+ * Root Modal component
10
+ *
11
+ * Injected into the root layout in a hidden state,
12
+ * then when a modal is opened this is displayed and wraps
13
+ * the new modal with a backdrop.
14
+ **/
15
+ function RootModal() {
16
+ const { activeId, modal } = (0, context_1.useModal)();
17
+ return ((0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { mode: "wait", children: modal && ((0, jsx_runtime_1.jsx)(react_1.Animation, { style: styles.backdrop, children: (0, jsx_runtime_1.jsx)("div", { className: styles.content, children: modal }) }, activeId)) }));
18
+ }
19
+ const styles = {
20
+ backdrop: "fixed inset-0 flex justify-center items-center bg-background-light/60 dark:bg-background-dark/60 z-[99]",
21
+ content: "max-w-[80%] max-h-[85%] bg-background border border-border rounded-lg shadow-soft"
22
+ };
@@ -0,0 +1 @@
1
+ export { default as ModalButton } from "./button";
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ModalButton = void 0;
7
+ var button_1 = require("./button");
8
+ Object.defineProperty(exports, "ModalButton", { enumerable: true, get: function () { return __importDefault(button_1).default; } });
@@ -0,0 +1,11 @@
1
+ import type { ReactNode } from "react";
2
+ import type { JsonMap } from "ts-helper-kit";
3
+ type ButtonProps = {
4
+ id: string;
5
+ params?: JsonMap;
6
+ variant?: "surface" | "accent";
7
+ icon?: ReactNode;
8
+ children?: ReactNode;
9
+ };
10
+ export default function ModalButton({ id, params, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.default = ModalButton;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const context_1 = require("../../state/context");
7
+ const core_1 = require("@bouku/core");
8
+ function ModalButton({ id, params, ...props }) {
9
+ const { openModal } = (0, context_1.useModal)();
10
+ return ((0, jsx_runtime_1.jsx)(core_1.Button, { ...props, action: () => openModal(id, params) }));
11
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./layouts/_";
2
+ export * from "./templates/_";
3
+ export * from "./components/_";
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./layouts/_"), exports);
18
+ __exportStar(require("./templates/_"), exports);
19
+ __exportStar(require("./components/_"), exports);
@@ -0,0 +1,2 @@
1
+ export { default as Modal } from "./normal";
2
+ export { default as FormModal } from "./form";
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FormModal = exports.Modal = void 0;
7
+ var normal_1 = require("./normal");
8
+ Object.defineProperty(exports, "Modal", { enumerable: true, get: function () { return __importDefault(normal_1).default; } });
9
+ var form_1 = require("./form");
10
+ Object.defineProperty(exports, "FormModal", { enumerable: true, get: function () { return __importDefault(form_1).default; } });
@@ -0,0 +1,28 @@
1
+ import { ModalProps } from "./normal";
2
+ import { FormBuilderField, FormData, FormSchema, PresetName } from "@bouku/form";
3
+ type Props<T extends FormData = FormData, P extends PresetName | undefined = undefined> = {
4
+ fields: FormBuilderField[][];
5
+ validator?: (data: FormSchema<T, P>) => {
6
+ success: boolean;
7
+ };
8
+ submit: (data: FormSchema<T, P>) => Promise<void | {
9
+ error?: null | Error;
10
+ code?: string;
11
+ message?: string;
12
+ }>;
13
+ } & Omit<ModalProps, "children">;
14
+ /**
15
+ * Form Modal component.
16
+ *
17
+ * Combines a standard modal layout with a form builder.
18
+ * Wraps @bouko/form `FormBuilder` for form handling.
19
+ **/
20
+ export declare function FormModal({ style, fields, submit, ...props }: Props): import("react/jsx-runtime").JSX.Element;
21
+ export default FormModal;
22
+ /**
23
+ * Problems:
24
+ *
25
+ * - Perfect `Modal`
26
+ * - Perfect `ModalProps`
27
+ * - Perfect `FormBuilderProps`
28
+ **/
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FormModal = FormModal;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const normal_1 = require("./normal");
6
+ const form_1 = require("@bouku/form");
7
+ /**
8
+ * Form Modal component.
9
+ *
10
+ * Combines a standard modal layout with a form builder.
11
+ * Wraps @bouko/form `FormBuilder` for form handling.
12
+ **/
13
+ function FormModal({ style, fields, submit, ...props }) {
14
+ return ((0, jsx_runtime_1.jsx)(normal_1.Modal, { ...props, children: (0, jsx_runtime_1.jsx)(form_1.FormBuilder, { style: style, fields: fields, submit: submit }) }));
15
+ }
16
+ exports.default = FormModal;
@@ -0,0 +1,12 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Component } from "@bouko/react";
3
+ export type ModalProps = Component & {
4
+ title: string;
5
+ subtitle?: ReactNode;
6
+ redirect?: {
7
+ label: string;
8
+ to: string;
9
+ };
10
+ };
11
+ export declare function Modal({ style, title, subtitle, redirect, children }: ModalProps): import("react/jsx-runtime").JSX.Element;
12
+ export default Modal;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Modal = Modal;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const context_1 = require("../../state/context");
9
+ const style_1 = require("@bouko/style");
10
+ const x_svg_1 = __importDefault(require("../../assets/icons/x.svg"));
11
+ function Modal({ style, title, subtitle, redirect, children }) {
12
+ const { openModal, closeModal } = (0, context_1.useModal)();
13
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, style_1.cn)(styles.container, style), role: "dialog", "aria-modal": "true", children: [(0, jsx_runtime_1.jsxs)("div", { className: styles.header, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles.heading, children: [(0, jsx_runtime_1.jsx)("span", { className: styles.title, children: title }), (0, jsx_runtime_1.jsxs)("span", { className: styles.subtitle, children: [subtitle, redirect && ((0, jsx_runtime_1.jsx)("button", { className: "p-0 bg-transparent border-none outline-none text-sm text-accent duration-200 hover:text-accent-light cursor-pointer font-semibold", onClick: () => openModal(redirect.to), children: redirect.label }))] })] }), (0, jsx_runtime_1.jsx)(x_svg_1.default, { className: styles.close, onClick: closeModal })] }), children] }));
14
+ }
15
+ const styles = {
16
+ container: "relative flex flex-col gap-4 w-lg p-7 pt-6 select-none overflow-hidden",
17
+ header: "relative flex flex-col gap-px mb-1 w-full",
18
+ heading: "flex flex-col gap-px",
19
+ title: "leading-none text-xl font-semibold",
20
+ subtitle: "flex items-center gap-2 text-sm text-slate-400",
21
+ close: "absolute -right-2 -top-1 text-error hover:text-error text-lg duration-200 cursor-pointer"
22
+ };
23
+ exports.default = Modal;
@@ -0,0 +1,2 @@
1
+ export { default as RegisterModal } from "./register";
2
+ export { default as LoginModal } from "./login";
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LoginModal = exports.RegisterModal = void 0;
7
+ var register_1 = require("./register");
8
+ Object.defineProperty(exports, "RegisterModal", { enumerable: true, get: function () { return __importDefault(register_1).default; } });
9
+ var login_1 = require("./login");
10
+ Object.defineProperty(exports, "LoginModal", { enumerable: true, get: function () { return __importDefault(login_1).default; } });
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Login Modal component
3
+ *
4
+ * Displays a modal for user login with handling for
5
+ * input validation and submission logic for existing users.
6
+ * Uses `nupabase` which is a Supabase wrapper.
7
+ *
8
+ * Form Fields:
9
+ * `email` - User's email address
10
+ * `password` - User's desired password
11
+ **/
12
+ export declare function LoginModal({ login }: {
13
+ login: () => Promise<void>;
14
+ }): import("react/jsx-runtime").JSX.Element;
15
+ export default LoginModal;
16
+ /**
17
+ * Problems:
18
+ *
19
+ * - Perfect `FormModal`.
20
+ * - Perfect `login`.
21
+ * - Perfect `LoginSchema`.
22
+ **/
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoginModal = LoginModal;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const form_1 = require("../layouts/form");
6
+ const form_2 = require("@bouku/form");
7
+ /**
8
+ * Login Modal component
9
+ *
10
+ * Displays a modal for user login with handling for
11
+ * input validation and submission logic for existing users.
12
+ * Uses `nupabase` which is a Supabase wrapper.
13
+ *
14
+ * Form Fields:
15
+ * `email` - User's email address
16
+ * `password` - User's desired password
17
+ **/
18
+ function LoginModal({ login }) {
19
+ return ((0, jsx_runtime_1.jsx)(form_1.FormModal, { title: "Login to your Account", subtitle: "We'll send a verification to your email.", fields: form_2.presets["email-password"], submit: login }));
20
+ }
21
+ exports.default = LoginModal;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Register Modal component
3
+ *
4
+ * Displays a modal for user registration with handling
5
+ * for input validation and submission logic for new users.
6
+ * Uses `nupabase` which is a Supabase wrapper.
7
+ *
8
+ * Form Fields:
9
+ * `email` - User's email address
10
+ * `password` - User's desired password
11
+ **/
12
+ export declare function RegisterModal({ register }: {
13
+ register: () => Promise<void>;
14
+ }): import("react/jsx-runtime").JSX.Element;
15
+ export default RegisterModal;
16
+ /**
17
+ * Problems:
18
+ *
19
+ * - Perfect `FormModal`.
20
+ * - Perfect `register`.
21
+ * - Perfect `RegisterSchema`.
22
+ **/
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RegisterModal = RegisterModal;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const form_1 = require("../layouts/form");
6
+ const form_2 = require("@bouku/form");
7
+ /**
8
+ * Register Modal component
9
+ *
10
+ * Displays a modal for user registration with handling
11
+ * for input validation and submission logic for new users.
12
+ * Uses `nupabase` which is a Supabase wrapper.
13
+ *
14
+ * Form Fields:
15
+ * `email` - User's email address
16
+ * `password` - User's desired password
17
+ **/
18
+ function RegisterModal({ register }) {
19
+ return ((0, jsx_runtime_1.jsx)(form_1.FormModal, { title: "Create an Account", subtitle: "We'll send a verification to your email.", fields: form_2.presets["email-password"], submit: register }));
20
+ }
21
+ exports.default = RegisterModal;
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@bouku/modal",
3
+ "version": "0.0.1",
4
+ "main": "./dist/index.js",
5
+ "types": "./dist/index.d.ts",
6
+ "license": "MIT",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "author": "",
14
+ "description": "",
15
+ "peerDependencies": {
16
+ "react": ">=18.3.1"
17
+ },
18
+ "engines": {},
19
+ "scripts": {
20
+ "build": "tsc"
21
+ },
22
+ "dependencies": {
23
+ "@bouko/style": "^0.1.6",
24
+ "@bouko/ts": "^0.2.0",
25
+ "@bouku/core": "^0.2.4",
26
+ "@bouku/form": "^0.1.4",
27
+ "clsx": "^2.1.1",
28
+ "formeact": "^0.0.3",
29
+ "framer-motion": "^12.16.0",
30
+ "superstruct": "^2.0.2",
31
+ "tailwind-merge": "^3.3.0",
32
+ "tailwind-variants": "^1.0.0",
33
+ "ts-helper-kit": "^0.0.9",
34
+ "zod": "^4.0.17"
35
+ },
36
+ "devDependencies": {
37
+ "@types/react": "^19.1.10",
38
+ "dependency-cruiser": "^17.0.1",
39
+ "nupabase": "^0.2.0",
40
+ "react": "^19.1.1",
41
+ "typescript": "^5.9.2"
42
+ }
43
+ }