@lerx/promise-modal 0.2.7 → 0.2.9

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.
@@ -1,12 +1,280 @@
1
+ /**
2
+ * Hook that provides access to the complete modal configuration context.
3
+ *
4
+ * Returns all configuration including component overrides and options.
5
+ * This is the most comprehensive hook for accessing modal configuration,
6
+ * useful when you need multiple configuration values or custom components.
7
+ *
8
+ * @returns Complete configuration context with components and options
9
+ */
1
10
  export declare const useConfigurationContext: () => import("./ConfigurationContext").ConfigurationContextProps;
2
- export declare const useConfigurationOptions: () => {
3
- duration: import("../../@aileron/declare").Duration;
4
- backdrop: import("../../@aileron/declare").Color;
5
- manualDestroy: boolean;
6
- closeOnBackdropClick: boolean;
7
- };
11
+ /**
12
+ * Hook that provides only the modal options from configuration.
13
+ *
14
+ * Convenient when you only need access to options like duration, backdrop,
15
+ * and behavior settings without the component definitions.
16
+ *
17
+ * @returns Modal options object with all settings
18
+ *
19
+ * @example
20
+ * Basic usage:
21
+ * ```tsx
22
+ * function ModalBackdrop() {
23
+ * const options = useConfigurationOptions();
24
+ *
25
+ * return (
26
+ * <div
27
+ * className="modal-backdrop"
28
+ * style={{
29
+ * backgroundColor: options.backdrop,
30
+ * transition: `opacity ${options.duration} ease`
31
+ * }}
32
+ * onClick={options.closeOnBackdropClick ? handleClose : undefined}
33
+ * />
34
+ * );
35
+ * }
36
+ * ```
37
+ *
38
+ * @example
39
+ * Conditional behavior based on options:
40
+ * ```tsx
41
+ * function ModalCloseButton({ onClose }) {
42
+ * const { closeOnBackdropClick, manualDestroy } = useConfigurationOptions();
43
+ * const [isClosing, setIsClosing] = useState(false);
44
+ *
45
+ * const handleClick = () => {
46
+ * if (manualDestroy) {
47
+ * setIsClosing(true);
48
+ * // Trigger close animation
49
+ * setTimeout(onClose, 300);
50
+ * } else {
51
+ * onClose();
52
+ * }
53
+ * };
54
+ *
55
+ * // Hide close button if backdrop click is disabled
56
+ * if (!closeOnBackdropClick) return null;
57
+ *
58
+ * return (
59
+ * <button
60
+ * onClick={handleClick}
61
+ * className={isClosing ? 'closing' : ''}
62
+ * >
63
+ * ×
64
+ * </button>
65
+ * );
66
+ * }
67
+ * ```
68
+ *
69
+ * @example
70
+ * Options-aware animations:
71
+ * ```tsx
72
+ * function AnimatedContent({ visible, children }) {
73
+ * const options = useConfigurationOptions();
74
+ * const contentRef = useRef<HTMLDivElement>(null);
75
+ *
76
+ * useEffect(() => {
77
+ * if (!contentRef.current) return;
78
+ *
79
+ * const element = contentRef.current;
80
+ * element.style.transition = `all ${options.duration} ease`;
81
+ *
82
+ * if (visible) {
83
+ * element.style.opacity = '1';
84
+ * element.style.transform = 'scale(1)';
85
+ * } else {
86
+ * element.style.opacity = '0';
87
+ * element.style.transform = 'scale(0.95)';
88
+ * }
89
+ * }, [visible, options.duration]);
90
+ *
91
+ * return <div ref={contentRef}>{children}</div>;
92
+ * }
93
+ * ```
94
+ */
95
+ export declare const useConfigurationOptions: () => Required<import("../..").ModalOptions>;
96
+ /**
97
+ * Hook that provides modal animation duration in multiple formats.
98
+ *
99
+ * Returns both the original duration string and converted milliseconds,
100
+ * useful for JavaScript animations and timing calculations.
101
+ *
102
+ * @returns Object with duration string and milliseconds number
103
+ *
104
+ * @example
105
+ * Basic animation timing:
106
+ * ```tsx
107
+ * function TimedModal() {
108
+ * const { duration, milliseconds } = useConfigurationDuration();
109
+ * const [phase, setPhase] = useState<'entering' | 'visible' | 'leaving'>();
110
+ *
111
+ * useEffect(() => {
112
+ * if (phase === 'entering') {
113
+ * const timer = setTimeout(() => setPhase('visible'), milliseconds);
114
+ * return () => clearTimeout(timer);
115
+ * }
116
+ * }, [phase, milliseconds]);
117
+ *
118
+ * return (
119
+ * <div
120
+ * className={`modal-${phase}`}
121
+ * style={{ animationDuration: duration }}
122
+ * />
123
+ * );
124
+ * }
125
+ * ```
126
+ *
127
+ * @example
128
+ * Synchronized animations:
129
+ * ```tsx
130
+ * function ModalWithStaggeredElements({ items }) {
131
+ * const { duration, milliseconds } = useConfigurationDuration();
132
+ * const itemDelay = milliseconds / items.length;
133
+ *
134
+ * return (
135
+ * <div className="modal">
136
+ * {items.map((item, index) => (
137
+ * <div
138
+ * key={item.id}
139
+ * className="modal-item"
140
+ * style={{
141
+ * animationDuration: duration,
142
+ * animationDelay: `${index * itemDelay}ms`
143
+ * }}
144
+ * >
145
+ * {item.content}
146
+ * </div>
147
+ * ))}
148
+ * </div>
149
+ * );
150
+ * }
151
+ * ```
152
+ *
153
+ * @example
154
+ * Progress indicators:
155
+ * ```tsx
156
+ * function ModalProgress({ onComplete }) {
157
+ * const { milliseconds } = useConfigurationDuration();
158
+ * const [progress, setProgress] = useState(0);
159
+ *
160
+ * useEffect(() => {
161
+ * const startTime = Date.now();
162
+ * const interval = setInterval(() => {
163
+ * const elapsed = Date.now() - startTime;
164
+ * const percent = Math.min((elapsed / milliseconds) * 100, 100);
165
+ * setProgress(percent);
166
+ *
167
+ * if (percent >= 100) {
168
+ * clearInterval(interval);
169
+ * onComplete();
170
+ * }
171
+ * }, 16); // ~60fps
172
+ *
173
+ * return () => clearInterval(interval);
174
+ * }, [milliseconds, onComplete]);
175
+ *
176
+ * return (
177
+ * <div className="progress-bar">
178
+ * <div
179
+ * className="progress-fill"
180
+ * style={{ width: `${progress}%` }}
181
+ * />
182
+ * </div>
183
+ * );
184
+ * }
185
+ * ```
186
+ *
187
+ * @remarks
188
+ * - Supports various duration formats: '300ms', '0.3s', '1s', etc.
189
+ * - Automatically converts to milliseconds for JavaScript timing
190
+ * - Useful for coordinating CSS and JS animations
191
+ */
8
192
  export declare const useConfigurationDuration: () => {
9
193
  duration: `${number}ms`;
10
194
  milliseconds: number;
11
195
  };
196
+ /**
197
+ * Hook that provides the modal backdrop color configuration.
198
+ *
199
+ * Convenient accessor for backdrop styling, supporting any valid CSS color format.
200
+ *
201
+ * @returns Backdrop color string
202
+ *
203
+ * @example
204
+ * Basic backdrop:
205
+ * ```tsx
206
+ * function ModalOverlay({ visible }) {
207
+ * const backdrop = useConfigurationBackdrop();
208
+ *
209
+ * if (!visible) return null;
210
+ *
211
+ * return (
212
+ * <div
213
+ * className="fixed inset-0"
214
+ * style={{ backgroundColor: backdrop }}
215
+ * />
216
+ * );
217
+ * }
218
+ * ```
219
+ *
220
+ * @example
221
+ * Animated backdrop with opacity:
222
+ * ```tsx
223
+ * function AnimatedBackdrop({ visible }) {
224
+ * const backdrop = useConfigurationBackdrop();
225
+ * const [opacity, setOpacity] = useState(0);
226
+ *
227
+ * // Parse backdrop color and apply custom opacity
228
+ * const backdropWithOpacity = useMemo(() => {
229
+ * if (backdrop.startsWith('rgba')) {
230
+ * return backdrop.replace(/[\d.]+\)$/, `${opacity})`);
231
+ * }
232
+ * return `${backdrop}${Math.round(opacity * 255).toString(16).padStart(2, '0')}`;
233
+ * }, [backdrop, opacity]);
234
+ *
235
+ * useEffect(() => {
236
+ * setOpacity(visible ? 1 : 0);
237
+ * }, [visible]);
238
+ *
239
+ * return (
240
+ * <div
241
+ * className="backdrop"
242
+ * style={{
243
+ * backgroundColor: backdropWithOpacity,
244
+ * transition: 'opacity 300ms ease'
245
+ * }}
246
+ * />
247
+ * );
248
+ * }
249
+ * ```
250
+ *
251
+ * @example
252
+ * Theme-aware backdrop:
253
+ * ```tsx
254
+ * function ThemedBackdrop() {
255
+ * const backdrop = useConfigurationBackdrop();
256
+ * const { theme } = useTheme();
257
+ *
258
+ * const adjustedBackdrop = useMemo(() => {
259
+ * if (theme === 'dark') {
260
+ * // Make backdrop darker in dark mode
261
+ * return backdrop.replace('0.5', '0.8');
262
+ * }
263
+ * return backdrop;
264
+ * }, [backdrop, theme]);
265
+ *
266
+ * return (
267
+ * <div
268
+ * className="modal-backdrop"
269
+ * style={{ backgroundColor: adjustedBackdrop }}
270
+ * />
271
+ * );
272
+ * }
273
+ * ```
274
+ *
275
+ * @remarks
276
+ * - Supports all CSS color formats: hex, rgb, rgba, hsl, etc.
277
+ * - Default backdrop is typically semi-transparent black
278
+ * - Can be overridden at provider level or per-modal
279
+ */
12
280
  export declare const useConfigurationBackdrop: () => import("../../@aileron/declare").Color;
@@ -4,3 +4,4 @@ export * from './confirm';
4
4
  export * from './modal';
5
5
  export * from './prompt';
6
6
  export * from './background';
7
+ export * from './option';
@@ -0,0 +1,11 @@
1
+ import type { Color, Duration } from '../@aileron/declare';
2
+ export interface ModalOptions {
3
+ /** Modal transition time(ms, s) */
4
+ duration?: Duration;
5
+ /** Modal backdrop color */
6
+ backdrop?: Color;
7
+ /** Whether to destroy the modal manually */
8
+ manualDestroy?: boolean;
9
+ /** Whether to close the modal when the backdrop is clicked */
10
+ closeOnBackdropClick?: boolean;
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lerx/promise-modal",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "description": "Universal React modal utility that can be used outside React components with promise-based results for alert, confirm, and prompt modals",
5
5
  "keywords": [
6
6
  "react",
@@ -58,15 +58,15 @@
58
58
  "size-limit": "size-limit",
59
59
  "start": "yarn build && yarn storybook",
60
60
  "storybook": "storybook dev -p 6006",
61
- "storybook:upgrade": "npx storybook@latest upgrade",
61
+ "storybook:upgrade": "npx storybook@latest upgrade --yes",
62
62
  "test": "yarn build:chain && vitest",
63
63
  "version:major": "yarn version major",
64
64
  "version:minor": "yarn version minor",
65
65
  "version:patch": "yarn version patch"
66
66
  },
67
67
  "dependencies": {
68
- "@winglet/common-utils": "^0.2.2",
69
- "@winglet/react-utils": "^0.2.6",
68
+ "@winglet/common-utils": "^0.2.3",
69
+ "@winglet/react-utils": "^0.2.9",
70
70
  "@winglet/style-utils": "^0.2.2"
71
71
  },
72
72
  "devDependencies": {
@@ -78,8 +78,8 @@
78
78
  "@size-limit/preset-app": "^11.1.6",
79
79
  "@size-limit/preset-big-lib": "^11.1.6",
80
80
  "@size-limit/preset-small-lib": "^11.1.6",
81
- "@storybook/addon-docs": "^9.0.14",
82
- "@storybook/react-vite": "^9.0.14",
81
+ "@storybook/addon-docs": "^9.0.18",
82
+ "@storybook/react-vite": "^9.0.18",
83
83
  "@testing-library/dom": "^10.4.0",
84
84
  "@testing-library/jest-dom": "^6.6.3",
85
85
  "@testing-library/react": "^16.1.0",
@@ -98,7 +98,7 @@
98
98
  "rollup-plugin-peer-deps-external": "^2.2.4",
99
99
  "rollup-plugin-visualizer": "^5.12.0",
100
100
  "size-limit": "^11.2.0",
101
- "storybook": "^9.0.14",
101
+ "storybook": "^9.0.18",
102
102
  "tsc-alias": "^1.8.16",
103
103
  "typescript": "^5.7.2",
104
104
  "vite": "^6.3.5",