@lerx/promise-modal 0.10.4 → 0.11.0
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/docs/claude/commands/guide.md +760 -0
- package/docs/claude/skills/expert/SKILL.md +171 -0
- package/docs/claude/skills/expert/knowledge/advanced-patterns.md +294 -0
- package/docs/claude/skills/expert/knowledge/api-reference.md +175 -0
- package/docs/claude/skills/expert/knowledge/hooks-reference.md +207 -0
- package/docs/claude/skills/expert/knowledge/type-definitions.md +172 -0
- package/docs/en/SPECIFICATION.md +1185 -0
- package/docs/ko/SPECIFICATION.md +1193 -0
- package/package.json +5 -4
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Hooks Reference
|
|
2
|
+
|
|
3
|
+
## useModal
|
|
4
|
+
|
|
5
|
+
Returns modal handlers tied to component lifecycle.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { useModal } from '@lerx/promise-modal';
|
|
9
|
+
|
|
10
|
+
function MyComponent() {
|
|
11
|
+
const modal = useModal({
|
|
12
|
+
ForegroundComponent: CustomForeground, // Hook-level config
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const handleShow = async () => {
|
|
16
|
+
await modal.alert({ title: 'Alert', content: 'Hello!' });
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
return <button onClick={handleShow}>Open Modal</button>;
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Key Feature**: Modals are automatically cleaned up when component unmounts.
|
|
24
|
+
|
|
25
|
+
| Feature | Static Handlers | useModal Hook |
|
|
26
|
+
|------|------------|-------------|
|
|
27
|
+
| Lifecycle | Independent | Tied to component |
|
|
28
|
+
| Cleanup | Manual | Auto on unmount |
|
|
29
|
+
| Usage Location | Anywhere | Inside React components |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## useActiveModalCount
|
|
34
|
+
|
|
35
|
+
Returns the count of currently active modals.
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { useActiveModalCount } from '@lerx/promise-modal';
|
|
39
|
+
|
|
40
|
+
function App() {
|
|
41
|
+
const count = useActiveModalCount();
|
|
42
|
+
// Optional: Filter with condition
|
|
43
|
+
const alertCount = useActiveModalCount(
|
|
44
|
+
(modal) => modal?.type === 'alert' && modal.visible
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return <div>Open modals: {count}</div>;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Parameters**:
|
|
52
|
+
- `filter?: (modal: ModalNode) => boolean` - Optional filter function
|
|
53
|
+
|
|
54
|
+
**Returns**: `number` - Active modal count
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## useModalAnimation
|
|
59
|
+
|
|
60
|
+
Provides animation state callbacks.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { useModalAnimation } from '@lerx/promise-modal';
|
|
64
|
+
|
|
65
|
+
function CustomForeground({ visible, children }) {
|
|
66
|
+
const ref = useRef(null);
|
|
67
|
+
|
|
68
|
+
useModalAnimation(visible, {
|
|
69
|
+
onVisible: () => ref.current?.classList.add('visible'),
|
|
70
|
+
onHidden: () => ref.current?.classList.remove('visible'),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return <div ref={ref}>{children}</div>;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Parameters**:
|
|
78
|
+
- `visible: boolean` - Modal visibility state
|
|
79
|
+
- `callbacks: { onVisible?: () => void; onHidden?: () => void }` - State change callbacks
|
|
80
|
+
|
|
81
|
+
**Timing**:
|
|
82
|
+
- `onVisible`: When modal starts becoming visible
|
|
83
|
+
- `onHidden`: When modal starts becoming hidden
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## useModalDuration
|
|
88
|
+
|
|
89
|
+
Returns modal animation duration.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { useModalDuration } from '@lerx/promise-modal';
|
|
93
|
+
|
|
94
|
+
function Component() {
|
|
95
|
+
const { duration, milliseconds } = useModalDuration();
|
|
96
|
+
// duration: '300ms', milliseconds: 300
|
|
97
|
+
|
|
98
|
+
return <div>Animation duration: {duration}</div>;
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Returns**:
|
|
103
|
+
```typescript
|
|
104
|
+
{
|
|
105
|
+
duration: string; // CSS format (e.g., '300ms')
|
|
106
|
+
milliseconds: number; // Number format (e.g., 300)
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## useDestroyAfter
|
|
113
|
+
|
|
114
|
+
Automatically destroys modal after specified time.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { useDestroyAfter } from '@lerx/promise-modal';
|
|
118
|
+
|
|
119
|
+
function ToastComponent({ id, duration }) {
|
|
120
|
+
useDestroyAfter(id, duration);
|
|
121
|
+
return <div>Toast message</div>;
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Parameters**:
|
|
126
|
+
- `id: number` - Modal ID
|
|
127
|
+
- `duration: number | string` - Wait time before destruction
|
|
128
|
+
|
|
129
|
+
**Use Case**: Auto-removal in toast notification implementation
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## useSubscribeModal
|
|
134
|
+
|
|
135
|
+
Subscribes to modal state changes.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { useSubscribeModal } from '@lerx/promise-modal';
|
|
139
|
+
|
|
140
|
+
function ModalTracker({ modal }) {
|
|
141
|
+
const version = useSubscribeModal(modal);
|
|
142
|
+
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
console.log('Modal state changed');
|
|
145
|
+
}, [version]);
|
|
146
|
+
|
|
147
|
+
return <div>Version: {version}</div>;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Parameters**:
|
|
152
|
+
- `modal: ModalNode` - Modal node to subscribe to
|
|
153
|
+
|
|
154
|
+
**Returns**: `number` - Modal version (increments on state change)
|
|
155
|
+
|
|
156
|
+
**Purpose**: React to modal internal state changes
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## useModalOptions
|
|
161
|
+
|
|
162
|
+
Returns modal option configuration.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import { useModalOptions } from '@lerx/promise-modal';
|
|
166
|
+
|
|
167
|
+
function ModalDebugInfo() {
|
|
168
|
+
const options = useModalOptions();
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div>
|
|
172
|
+
<p>Duration: {options.duration}</p>
|
|
173
|
+
<p>Backdrop: {options.backdrop}</p>
|
|
174
|
+
<p>Manual Destroy: {options.manualDestroy ? 'Yes' : 'No'}</p>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Returns**: `ModalOptions` - Current modal's options object
|
|
181
|
+
|
|
182
|
+
**Included Properties**:
|
|
183
|
+
- `duration` - Animation duration
|
|
184
|
+
- `backdrop` - Background configuration
|
|
185
|
+
- `manualDestroy` - Manual destruction mode
|
|
186
|
+
- `closeOnBackdropClick` - Close on backdrop click
|
|
187
|
+
- Other modal configuration options
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## useModalBackdrop
|
|
192
|
+
|
|
193
|
+
Returns only modal background configuration.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { useModalBackdrop } from '@lerx/promise-modal';
|
|
197
|
+
|
|
198
|
+
function BackdropInfo() {
|
|
199
|
+
const backdrop = useModalBackdrop();
|
|
200
|
+
|
|
201
|
+
return <p>Current backdrop: {backdrop}</p>;
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Returns**: `ModalBackground` - Background configuration value
|
|
206
|
+
|
|
207
|
+
**Purpose**: Lighter alternative to `useModalOptions` when only backdrop configuration is needed
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Type Definitions
|
|
2
|
+
|
|
3
|
+
## ModalFrameProps
|
|
4
|
+
|
|
5
|
+
Props passed to Foreground/Background components.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
interface ModalFrameProps<Context = any, B = any> {
|
|
9
|
+
id: number;
|
|
10
|
+
type: 'alert' | 'confirm' | 'prompt';
|
|
11
|
+
alive: boolean;
|
|
12
|
+
visible: boolean;
|
|
13
|
+
initiator: string;
|
|
14
|
+
manualDestroy: boolean;
|
|
15
|
+
closeOnBackdropClick: boolean;
|
|
16
|
+
background?: ModalBackground<B>;
|
|
17
|
+
onConfirm: () => void;
|
|
18
|
+
onClose: () => void;
|
|
19
|
+
onChange: (value: any) => void;
|
|
20
|
+
onDestroy: () => void;
|
|
21
|
+
onChangeOrder: Function;
|
|
22
|
+
context: Context;
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Property Descriptions**:
|
|
28
|
+
|
|
29
|
+
| Property | Type | Description |
|
|
30
|
+
|------|------|------|
|
|
31
|
+
| `id` | `number` | Unique modal ID |
|
|
32
|
+
| `type` | `'alert' \| 'confirm' \| 'prompt'` | Modal type |
|
|
33
|
+
| `alive` | `boolean` | Whether modal exists in DOM |
|
|
34
|
+
| `visible` | `boolean` | Whether modal is visible on screen |
|
|
35
|
+
| `initiator` | `string` | Identifier of modal creator |
|
|
36
|
+
| `manualDestroy` | `boolean` | Whether manual destruction mode is enabled |
|
|
37
|
+
| `closeOnBackdropClick` | `boolean` | Whether close on backdrop click is enabled |
|
|
38
|
+
| `background` | `ModalBackground<B>` | Background configuration |
|
|
39
|
+
| `onConfirm` | `() => void` | Confirm button click handler |
|
|
40
|
+
| `onClose` | `() => void` | Modal close handler |
|
|
41
|
+
| `onChange` | `(value: any) => void` | Value change handler (for prompt) |
|
|
42
|
+
| `onDestroy` | `() => void` | Modal destruction handler |
|
|
43
|
+
| `onChangeOrder` | `Function` | Modal order change handler |
|
|
44
|
+
| `context` | `Context` | User-defined context data |
|
|
45
|
+
| `children` | `ReactNode` | Modal internal content |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## FooterComponentProps
|
|
50
|
+
|
|
51
|
+
Props for custom footer components.
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
interface FooterComponentProps {
|
|
55
|
+
type: 'alert' | 'confirm' | 'prompt';
|
|
56
|
+
onConfirm: (value?: any) => void;
|
|
57
|
+
onClose: () => void;
|
|
58
|
+
onCancel?: () => void;
|
|
59
|
+
disabled?: boolean;
|
|
60
|
+
footer?: FooterOptions;
|
|
61
|
+
context: any;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Property Descriptions**:
|
|
66
|
+
|
|
67
|
+
| Property | Type | Description |
|
|
68
|
+
|------|------|------|
|
|
69
|
+
| `type` | `'alert' \| 'confirm' \| 'prompt'` | Modal type |
|
|
70
|
+
| `onConfirm` | `(value?: any) => void` | Confirm button click handler |
|
|
71
|
+
| `onClose` | `() => void` | Close button click handler |
|
|
72
|
+
| `onCancel` | `() => void` | Cancel button click handler (optional) |
|
|
73
|
+
| `disabled` | `boolean` | Confirm button disabled state (optional) |
|
|
74
|
+
| `footer` | `FooterOptions` | Footer configuration options (optional) |
|
|
75
|
+
| `context` | `any` | User-defined context data |
|
|
76
|
+
|
|
77
|
+
**Usage Example**:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
const CustomFooter: React.FC<FooterComponentProps> = ({
|
|
81
|
+
type,
|
|
82
|
+
onConfirm,
|
|
83
|
+
onClose,
|
|
84
|
+
disabled,
|
|
85
|
+
footer,
|
|
86
|
+
}) => {
|
|
87
|
+
return (
|
|
88
|
+
<div className="custom-footer">
|
|
89
|
+
{type !== 'alert' && (
|
|
90
|
+
<button onClick={onClose}>
|
|
91
|
+
{footer?.cancel || 'Cancel'}
|
|
92
|
+
</button>
|
|
93
|
+
)}
|
|
94
|
+
<button onClick={() => onConfirm()} disabled={disabled}>
|
|
95
|
+
{footer?.confirm || 'Confirm'}
|
|
96
|
+
</button>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## PromptInputProps<T>
|
|
105
|
+
|
|
106
|
+
Props for prompt input components.
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
interface PromptInputProps<T> {
|
|
110
|
+
value?: T;
|
|
111
|
+
defaultValue?: T;
|
|
112
|
+
onChange: (value: T | undefined) => void;
|
|
113
|
+
onConfirm: () => void;
|
|
114
|
+
onCancel: () => void;
|
|
115
|
+
context: any;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Property Descriptions**:
|
|
120
|
+
|
|
121
|
+
| Property | Type | Description |
|
|
122
|
+
|------|------|------|
|
|
123
|
+
| `value` | `T` | Current input value (optional) |
|
|
124
|
+
| `defaultValue` | `T` | Default input value (optional) |
|
|
125
|
+
| `onChange` | `(value: T \| undefined) => void` | Value change handler |
|
|
126
|
+
| `onConfirm` | `() => void` | Confirm action handler (e.g., Enter key) |
|
|
127
|
+
| `onCancel` | `() => void` | Cancel action handler (e.g., Escape key) |
|
|
128
|
+
| `context` | `any` | User-defined context data |
|
|
129
|
+
|
|
130
|
+
**Usage Examples**:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// Simple text input
|
|
134
|
+
const TextInput: React.FC<PromptInputProps<string>> = ({
|
|
135
|
+
value = '',
|
|
136
|
+
onChange,
|
|
137
|
+
onConfirm,
|
|
138
|
+
}) => {
|
|
139
|
+
return (
|
|
140
|
+
<input
|
|
141
|
+
type="text"
|
|
142
|
+
value={value}
|
|
143
|
+
onChange={(e) => onChange(e.target.value)}
|
|
144
|
+
onKeyPress={(e) => e.key === 'Enter' && onConfirm()}
|
|
145
|
+
/>
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Complex object input
|
|
150
|
+
interface FormData {
|
|
151
|
+
name: string;
|
|
152
|
+
email: string;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const FormInput: React.FC<PromptInputProps<FormData>> = ({
|
|
156
|
+
value = { name: '', email: '' },
|
|
157
|
+
onChange,
|
|
158
|
+
}) => {
|
|
159
|
+
return (
|
|
160
|
+
<div>
|
|
161
|
+
<input
|
|
162
|
+
value={value.name}
|
|
163
|
+
onChange={(e) => onChange({ ...value, name: e.target.value })}
|
|
164
|
+
/>
|
|
165
|
+
<input
|
|
166
|
+
value={value.email}
|
|
167
|
+
onChange={(e) => onChange({ ...value, email: e.target.value })}
|
|
168
|
+
/>
|
|
169
|
+
</div>
|
|
170
|
+
);
|
|
171
|
+
};
|
|
172
|
+
```
|