# Forma

**High-performance and developer-friendly React form state management library**  
**고성능이며 개발자 친화적인 React 폼 상태 관리 라이브러리**

[![npm version](https://img.shields.io/npm/v/@ehfuse/forma.svg)](https://www.npmjs.com/package/@ehfuse/forma)
[![npm downloads](https://img.shields.io/npm/dm/@ehfuse/forma.svg)](https://www.npmjs.com/package/@ehfuse/forma)
[![GitHub license](https://img.shields.io/github/license/ehfuse/forma.svg)](https://github.com/ehfuse/forma/blob/main/LICENSE)

Forma is a high-performance library that makes form and state management in React applications **simple yet powerful**. **Start immediately with Zero-Config**, and achieve optimal performance through **selective re-rendering** via individual field subscriptions. Easily access production-level advanced features like **global form state sharing**, **Dot Notation nested object access**, and **full MUI compatibility** without complex setup.

Forma는 React 애플리케이션에서 폼과 상태를 **간편하면서도 강력하게** 관리할 수 있는 고성능 라이브러리입니다. **Zero-Config로 바로 시작**할 수 있으며, 개별 필드 구독을 통한 **선택적 리렌더링**으로 최적의 성능을 제공합니다. 복잡한 설정 없이도 **글로벌 폼 상태 공유**, **Dot Notation 중첩 객체 접근**, **MUI 완전 호환** 등 프로덕션 레벨의 고급 기능들을 손쉽게 사용할 수 있습니다.

## Why Forma? | 왜 Forma인가?

Forma는 단순한 폼 라이브러리가 아닙니다. **React 상태 관리의 패러다임을 바꾸는** 혁신적인 솔루션입니다.

### 🚀 The Ultimate State Management Solution | 최강의 상태 관리 솔루션

#### 1. **Watch + Actions = No More useEffect & useState & Context**

**useEffect, useState, Context 지옥에서 탈출하세요**

```tsx
// ❌ Traditional: useEffect + useState + Context + Props Drilling
const AuthContext = createContext(null);

function App() {
    const [logined, setLogined] = useState(false);
    const [syncInterval, setSyncInterval] = useState(null);

    useEffect(() => {
        if (logined) {
            const interval = setInterval(() => syncData(), 5000);
            setSyncInterval(interval);
        } else {
            if (syncInterval) clearInterval(syncInterval);
            setSyncInterval(null);
        }
    }, [logined]);

    // Props drilling or Context Provider needed
    return (
        <AuthContext.Provider value={{ logined, setLogined }}>
            <Header />
            <Main />
            <Footer />
        </AuthContext.Provider>
    );
}

// ✅ Forma: Clean and declarative
const state = useGlobalFormaState({
    stateId: "auth",
    initialValues: {
        logined: false,
        user: { name: "", email: "" },
        syncInterval: null,
    },
    actions: {
        startSync: (ctx) => {
            const interval = setInterval(() => syncData(), 5000);
            ctx.setValue("syncInterval", interval);
        },
        stopSync: (ctx) => {
            const interval = ctx.getValue("syncInterval");
            if (interval) clearInterval(interval);
            ctx.setValue("syncInterval", null);
        },
    },
    watch: {
        logined: (ctx, value) => {
            value ? ctx.actions.startSync(ctx) : ctx.actions.stopSync(ctx);
        },
        "user.email": (ctx, value) => {
            console.log("Email changed:", value);
        },
    },
});
```

**Benefits | 이점:**

-   🧹 **No useEffect clutter** | useEffect 없이 깔끔한 코드
-   � **No Context needed** | Context API 불필요
-   🎯 **No Props Drilling** | Props 전달 지옥 탈출
-   �📦 **Modular logic** | 로직을 별도 파일로 분리 가능
-   🧪 **Easy testing** | actions/watch 단독 테스트 용이
-   🎯 **Better code cohesion** | 높은 코드 응집도

#### 2. **Surgical Re-rendering**

**수술적 정밀도의 리렌더링**

```tsx
// ❌ Redux/Context: Entire component re-renders
const { user, todos, settings } = useStore(); // or useContext(AppContext)
// All fields change = entire component re-renders

// ✅ Forma: Only what you need
const userName = state.useValue("user.name"); // Only this field
const todoCount = state.useValue("todos.length"); // Only array length
const theme = state.useValue("settings.theme"); // Only theme
// Each component subscribes to ONLY what it needs
```

**Performance | 성능:**

-   ⚡ **10-100x faster** than Redux for large forms | 대규모 폼에서 Redux 대비 10-100배 빠름
-   🎯 **Field-level optimization** | 필드 단위 최적화
-   📊 **No selectors needed** | 셀렉터 불필요
-   🔥 **Zero wasted renders** | 불필요한 렌더링 제로

#### 3. **Form + State + Global Access in One**

**폼, 상태, 글로벌 접근을 하나로**

```tsx
// ❌ Traditional: Multiple libraries + Context boilerplate
import { useForm } from "react-hook-form";
import { create } from "zustand";
import { createContext, useContext } from "react";

// Context setup, Provider wrapping, Props drilling...
const FormContext = createContext(null);

function App() {
    const form = useForm();
    return (
        <FormContext.Provider value={form}>
            <Header />
            <MainContent />
        </FormContext.Provider>
    );
}

// ✅ Forma: One library, zero boilerplate
import { useGlobalForm, useGlobalFormaState } from "@ehfuse/forma";

function Header() {
    // Access anywhere, no Provider needed!
    const state = useGlobalFormaState<AuthState>({ stateId: "auth" });
    const userName = state.useValue("user.name");
}

function MainContent() {
    // Same state, no props drilling
    const state = useGlobalFormaState<AuthState>({ stateId: "auth" });
}
```

**All-in-One | 올인원:**

-   📝 **Form management** | 폼 관리
-   🌐 **Global state (no Context!)** | 전역 상태 (Context 불필요!)
-   🚫 **No Props Drilling** | Props 전달 불필요
-   👀 **Reactive watch** | 반응형 감시
-   🎬 **Actions system** | 액션 시스템
-   💾 **localStorage/sessionStorage** | 영속성 저장소 관리
-   🎭 **Modal management** | 모달 관리
-   📱 **Breakpoint detection** | 반응형 감지

## Key Features | 주요 특징

-   🎯 **Zero-Config**: Start immediately | 설정 없이 즉시 시작
-   👀 **Watch System**: Replace useEffect with declarative watchers | useEffect를 선언적 watcher로 대체
-   � **Actions Pattern**: Modular business logic | 모듈화된 비즈니스 로직
-   ✅ **Individual Field Subscription**: Surgical re-rendering | 수술적 리렌더링
-   🌟 **Dot Notation**: Deep nested access `user.profile.name` | 깊은 중첩 접근
-   🌐 **Global State Sharing**: Share across components | 컴포넌트 간 공유
-   💾 **localStorage Persistence**: useLocalStorage hook & persist option | localStorage 영속성 지원
-   🎭 **Modal Stack**: Mobile-friendly with back button | 뒤로가기 지원 모달
-   📱 **Breakpoint Management**: Responsive UI made easy | 반응형 UI 간편화
-   ✅ **Full MUI Compatibility**: Perfect Material-UI integration | MUI 완벽 통합
-   ✅ **TypeScript Native**: Full type safety | 완전한 타입 안전성

## Documentation | 문서

### English

-   **[Getting Started Guide](./docs/en/getting-started.md)** - Step-by-step tutorial and examples
-   **[API Reference](./docs/en/API.md)** - Complete API documentation with examples
-   **[Examples Collection](./docs/en/examples.md)** - Practical usage examples and patterns
-   **[Performance Guide](./docs/en/performance-guide.md)** - Performance optimization techniques
-   **[Performance Warnings](./docs/en/performance-warnings.md)** - Anti-patterns and common pitfalls
-   **[Migration Guide](./docs/en/migration.md)** - Migrate from other form libraries
-   **[useGlobalForm Guide](./docs/en/useGlobalForm-guide.md)** - Global form state management
-   **[Global Hooks Comparison](./docs/en/global-hooks-comparison.md)** - useGlobalForm vs useGlobalFormaState
-   **[Library Comparison](./docs/en/library-comparison.md)** - Forma vs other libraries

### 한국어 (Korean)

-   **[시작 가이드](./docs/ko/getting-started.md)** - 단계별 튜토리얼과 예제
-   **[API 레퍼런스](./docs/ko/API.md)** - 완전한 API 문서와 예제
-   **[예제 모음](./docs/ko/examples.md)** - 실용적인 사용 예제와 패턴
-   **[성능 최적화 가이드](./docs/ko/performance-guide.md)** - 성능 최적화 기법
-   **[성능 최적화 주의사항](./docs/ko/performance-warnings.md)** - 안티패턴과 일반적인 함정
-   **[마이그레이션 가이드](./docs/ko/migration.md)** - 다른 폼 라이브러리에서 이전
-   **[useGlobalForm 가이드](./docs/ko/useGlobalForm-guide.md)** - 글로벌 폼 상태 관리
-   **[글로벌 훅 비교](./docs/ko/global-hooks-comparison.md)** - useGlobalForm vs useGlobalFormaState
-   **[라이브러리 비교](./docs/ko/library-comparison.md)** - Forma vs 다른 라이브러리

### Links | 링크

### 링크

-   🏠 **[GitHub Repository](https://github.com/ehfuse/forma)**
-   📦 **[NPM Package](https://www.npmjs.com/package/@ehfuse/forma)**

---

## Installation | 설치

```bash
npm install @ehfuse/forma
```

```bash
yarn add @ehfuse/forma
```

---

## Quick Start | 빠른 시작

```bash
npm install @ehfuse/forma
```

### Real-World Example: Todo App with Watch | 실전 예제: Watch를 활용한 Todo 앱

```tsx
import { useGlobalFormaState } from "@ehfuse/forma";

// 🎯 Separate actions file for better organization
// 액션을 별도 파일로 분리하여 코드 응집도 향상
const todoActions = {
    addTodo: (ctx, text: string) => {
        const todos = ctx.values.todos;
        ctx.setValue("todos", [
            ...todos,
            {
                id: Date.now(),
                text,
                completed: false,
            },
        ]);
    },

    toggleTodo: (ctx, id: number) => {
        const todos = ctx.values.todos.map((t) =>
            t.id === id ? { ...t, completed: !t.completed } : t
        );
        ctx.setValue("todos", todos);
    },

    // Auto-save to localStorage
    saveToStorage: (ctx) => {
        localStorage.setItem("todos", JSON.stringify(ctx.values.todos));
    },
};

function TodoApp() {
    const state = useGlobalFormaState({
        stateId: "todo-app",
        initialValues: {
            todos: [],
            filter: "all",
            lastSync: null,
        },
        actions: todoActions,
        watch: {
            // 👀 Auto-save when todos change (replaces useEffect!)
            // todos 변경 시 자동 저장 (useEffect 불필요!)
            todos: (ctx, value) => {
                ctx.actions.saveToStorage(ctx);
                ctx.setValue("lastSync", new Date().toISOString());
            },

            // 🎯 Log filter changes
            filter: (ctx, value, prevValue) => {
                console.log(`Filter changed: ${prevValue} → ${value}`);
            },
        },
    });

    // ✅ Surgical re-rendering: Only subscribes to what's needed
    // 수술적 리렌더링: 필요한 것만 구독
    const todosLength = state.useValue("todos.length");
    const filter = state.useValue("filter");
    const lastSync = state.useValue("lastSync");

    return (
        <div>
            <h1>Todos ({todosLength})</h1>
            <p>Last synced: {lastSync}</p>

            <button onClick={() => state.actions.addTodo(state, "New Task")}>
                Add Todo
            </button>

            <select
                value={filter}
                onChange={(e) => state.setValue("filter", e.target.value)}
            >
                <option value="all">All</option>
                <option value="active">Active</option>
                <option value="completed">Completed</option>
            </select>
        </div>
    );
}
```

**What you gain | 얻는 것:**

-   🧹 **No useEffect** - Watch handles all side effects | useEffect 제거 - Watch가 모든 부수효과 처리
-   📦 **Modular actions** - Easy to test and maintain | 모듈화된 액션 - 테스트와 유지보수 용이
-   ⚡ **Optimized rendering** - Only `todosLength`, `filter`, `lastSync` trigger re-renders | 최적화된 렌더링
-   🔄 **Automatic persistence** - Watch auto-saves changes | 자동 저장 - Watch가 변경사항 자동 저장

---

### useLocalStorage: Simple Persistent State | 간단한 영속 상태

```tsx
import { useLocalStorage, GlobalFormaProvider } from "@ehfuse/forma";

// 1. Setup: Add storagePrefix to GlobalFormaProvider
// 1. 설정: GlobalFormaProvider에 storagePrefix 추가
function App() {
    return (
        <GlobalFormaProvider storagePrefix="myapp">
            <ThemeToggle />
        </GlobalFormaProvider>
    );
}

// 2. Use like useState, but persisted!
// 2. useState처럼 사용하면 자동으로 저장!
function ThemeToggle() {
    const { value: theme, setValue: setTheme } = useLocalStorage(
        "theme",
        "light"
    );
    // Stored as "myapp:theme" in localStorage
    // localStorage에 "myapp:theme"으로 저장됨

    return (
        <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
            Current: {theme}
        </button>
    );
}

// 3. Works with complex objects too!
// 3. 복잡한 객체도 지원!
function UserSettings() {
    const { value: settings, setValue: setSettings } = useLocalStorage(
        "settings",
        {
            notifications: true,
            language: "ko",
            fontSize: 14,
        }
    );

    return (
        <div>
            <label>
                <input
                    type="checkbox"
                    checked={settings.notifications}
                    onChange={(e) =>
                        setSettings({
                            ...settings,
                            notifications: e.target.checked,
                        })
                    }
                />
                Enable Notifications
            </label>
        </div>
    );
}
```

**Benefits | 이점:**

-   💾 **Auto-persistence** - Values survive page refresh | 페이지 새로고침 후에도 값 유지
-   🔑 **Centralized prefix** - No key collision between apps | 앱 간 키 충돌 방지
-   📦 **JSON support** - Objects & arrays work seamlessly | 객체와 배열 자동 직렬화
-   🎯 **useState-like API** - Familiar and easy to use | 익숙하고 사용하기 쉬운 API

---

## When to choose Forma?

Forma is **specialized for form state management** and shines in specific scenarios. Here's when Forma is the perfect choice for your project.

### Perfect for these use cases:

**🎨 MUI (Material-UI) Projects**

-   Seamless integration with MUI components
-   No additional wrapper components needed
-   Built-in support for MUI's controlled component patterns

**⚡ Performance-Critical Forms**

-   Large forms with many fields (50+ inputs)
-   Real-time data visualization forms
-   Forms that update frequently during user interaction

**🔄 Multi-Step & Global Forms**

-   Wizard-style multi-step forms
-   Forms shared across multiple components
-   Registration flows with data persistence

**🏗️ Complex Nested Data**

-   User profiles with nested address/contact info
-   Product configurations with multiple layers
-   Settings panels with grouped options

**📊 Dynamic Form Generation**

-   Forms generated from API schemas
-   Conditional field rendering
-   Dynamic validation rules

## 언제 Forma를 선택해야 할까요?

Forma는 **폼 상태 관리에 특화**된 라이브러리로 특정 시나리오에서 빛을 발합니다. 다음은 Forma가 프로젝트에 완벽한 선택이 되는 경우입니다.

### 이런 경우에 완벽합니다:

**🎨 MUI (Material-UI) 프로젝트**

-   MUI 컴포넌트와 완벽한 통합
-   추가 래퍼 컴포넌트 불필요
-   MUI의 제어 컴포넌트 패턴 내장 지원

**⚡ 성능이 중요한 폼**

-   많은 필드가 있는 대규모 폼 (50개 이상 입력)
-   실시간 데이터 시각화 폼
-   사용자 상호작용 중 자주 업데이트되는 폼

**🔄 멀티 스텝 & 글로벌 폼**

-   마법사 스타일의 멀티 스텝 폼
-   여러 컴포넌트에서 공유되는 폼
-   데이터 지속성이 있는 등록 플로우

**🏗️ 복잡한 중첩 데이터**

-   중첩된 주소/연락처 정보가 있는 사용자 프로필
-   다층 구조의 제품 구성
-   그룹화된 옵션이 있는 설정 패널

**📊 동적 폼 생성**

-   API 스키마에서 생성되는 폼
-   조건부 필드 렌더링
-   동적 검증 규칙

---

## Architecture Benefits | 아키텍처 이점

### 📁 Clean Separation of Concerns | 관심사의 명확한 분리

```tsx
// actions.ts - Business logic isolated
// actions.ts - 비즈니스 로직 분리
export const authActions = {
    login: async (ctx, credentials) => {
        const user = await api.login(credentials);
        ctx.setValues({ logined: true, user, token: user.token });
    },
    logout: (ctx) => {
        ctx.setValues({ logined: false, user: null, token: null });
    },
    startSync: (ctx) => {
        /* ... */
    },
    stopSync: (ctx) => {
        /* ... */
    },
};

// watch.ts - Side effects isolated
// watch.ts - 부수효과 분리
export const authWatch = {
    logined: (ctx, value) => {
        value ? ctx.actions.startSync(ctx) : ctx.actions.stopSync(ctx);
    },
    "user.preferences": (ctx, value) => {
        localStorage.setItem("prefs", JSON.stringify(value));
    },
};

// component.tsx - Pure UI
// component.tsx - 순수 UI
function AuthApp() {
    const state = useGlobalFormaState({
        stateId: "auth",
        actions: authActions,
        watch: authWatch,
    });

    // Clean, declarative UI
    // 깔끔한 선언적 UI
    return <LoginForm onSubmit={state.actions.login} />;
}
```

**Benefits | 이점:**

-   🧪 **Testable**: Test actions/watch independently | 독립적 테스트 가능
-   📦 **Reusable**: Share logic across projects | 프로젝트 간 로직 공유
-   🔍 **Maintainable**: Easy to locate and update logic | 로직 위치 파악 및 수정 용이
-   👥 **Team-friendly**: Clear code organization | 명확한 코드 구조

### ⚡ Performance Comparison | 성능 비교

```tsx
// ❌ Redux: Entire component re-renders
const state = useSelector((state) => state); // Everything triggers re-render
// 전체 컴포넌트 리렌더링

// ❌ Context: All consumers re-render
const { user, todos, settings } = useContext(AppContext);
// 모든 컨슈머 리렌더링

// ✅ Forma: Surgical precision
const userName = state.useValue("user.name"); // Only this
const todoCount = state.useValue("todos.length"); // Only this
const theme = state.useValue("settings.theme"); // Only this
// 수술적 정밀도
```

**Real-world impact | 실제 영향:**

-   📊 **50+ fields**: 10-100x faster than Redux | Redux 대비 10-100배 빠름
-   ⚡ **Real-time forms**: Smooth 60fps performance | 부드러운 60fps 성능
-   📱 **Mobile**: Better battery life | 배터리 수명 향상
-   🎯 **Zero wasted renders**: Every render is intentional | 모든 렌더링이 의도적

**[View Detailed Performance Guide](./docs/en/performance-guide.md)** | **[성능 가이드 보기](./docs/ko/performance-guide.md)**

---

## Links | 링크

-   **📦 NPM**: [https://www.npmjs.com/package/@ehfuse/forma](https://www.npmjs.com/package/@ehfuse/forma)
-   **🐙 GitHub**: [https://github.com/ehfuse/forma](https://github.com/ehfuse/forma)
-   **📄 License**: [MIT](https://github.com/ehfuse/forma/blob/main/LICENSE)

---

## Contact | 연락처

-   **Developer**: 김영진 (KIM YOUNG JIN)
-   **Email**: ehfuse@gmail.com
-   **GitHub**: [@ehfuse](https://github.com/ehfuse)

---

Copyright (c) 2025 김영진 (KIM YOUNG JIN) - MIT License
