form-hook-kit 1.2.0 → 1.2.2
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/README.md +28 -372
- package/dist/devtools/FormContext.d.ts +8 -0
- package/dist/devtools/FormContext.d.ts.map +1 -0
- package/dist/devtools/FormDevTools.d.ts.map +1 -1
- package/dist/devtools/FormProvider.d.ts +33 -0
- package/dist/devtools/FormProvider.d.ts.map +1 -0
- package/dist/devtools/devtools/FormDevTools.d.ts +86 -0
- package/dist/devtools/devtools/FormDevTools.d.ts.map +1 -0
- package/dist/devtools/devtools/index.d.ts +3 -0
- package/dist/devtools/devtools/index.d.ts.map +1 -0
- package/dist/devtools/hooks/index.d.ts +4 -0
- package/dist/devtools/hooks/index.d.ts.map +1 -0
- package/dist/devtools/hooks/useForm.d.ts +30 -0
- package/dist/devtools/hooks/useForm.d.ts.map +1 -0
- package/dist/devtools/hooks/useFormField.d.ts +40 -0
- package/dist/devtools/hooks/useFormField.d.ts.map +1 -0
- package/dist/devtools/hooks/useFormPerformance.d.ts +57 -0
- package/dist/devtools/hooks/useFormPerformance.d.ts.map +1 -0
- package/dist/devtools/index.esm.js +203 -0
- package/dist/devtools/index.esm.js.map +1 -0
- package/dist/devtools/index.js +205 -0
- package/dist/devtools/index.js.map +1 -0
- package/dist/devtools/package.json +6 -0
- package/dist/devtools/types/index.d.ts +94 -0
- package/dist/devtools/types/index.d.ts.map +1 -0
- package/dist/devtools/utils/debounce.d.ts +6 -0
- package/dist/devtools/utils/debounce.d.ts.map +1 -0
- package/dist/devtools/utils/errors.d.ts +11 -0
- package/dist/devtools/utils/errors.d.ts.map +1 -0
- package/dist/devtools/utils/formActions.d.ts +57 -0
- package/dist/devtools/utils/formActions.d.ts.map +1 -0
- package/dist/devtools/utils/formReducer.d.ts +7 -0
- package/dist/devtools/utils/formReducer.d.ts.map +1 -0
- package/dist/devtools/utils/index.d.ts +7 -0
- package/dist/devtools/utils/index.d.ts.map +1 -0
- package/dist/devtools/utils/performance.d.ts +7 -0
- package/dist/devtools/utils/performance.d.ts.map +1 -0
- package/dist/devtools/utils/validation.d.ts +25 -0
- package/dist/devtools/utils/validation.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +128 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { FormFieldRef } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Hook for managing a single form field
|
|
4
|
+
*
|
|
5
|
+
* Provides field-specific state and handlers for common field operations.
|
|
6
|
+
*
|
|
7
|
+
* @param name - Field name
|
|
8
|
+
* @returns Field state and handlers
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* function EmailField() {
|
|
13
|
+
* const {value, error, onChange, onBlur} = useFormField('email');
|
|
14
|
+
*
|
|
15
|
+
* return (
|
|
16
|
+
* <div>
|
|
17
|
+
* <input
|
|
18
|
+
* type="email"
|
|
19
|
+
* value={value || ''}
|
|
20
|
+
* onChange={onChange}
|
|
21
|
+
* onBlur={onBlur}
|
|
22
|
+
* />
|
|
23
|
+
* {error && <span className="error">{error}</span>}
|
|
24
|
+
* </div>
|
|
25
|
+
* );
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function useFormField(name: string): {
|
|
30
|
+
value: import("../types").FormFieldValue;
|
|
31
|
+
error: string | null;
|
|
32
|
+
onChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
33
|
+
onChangeValue: (newValue: string | number | boolean | null | undefined) => void;
|
|
34
|
+
onBlur: () => void;
|
|
35
|
+
onFocus: () => void;
|
|
36
|
+
setRef: (ref: FormFieldRef) => void;
|
|
37
|
+
name: string;
|
|
38
|
+
};
|
|
39
|
+
export default useFormField;
|
|
40
|
+
//# sourceMappingURL=useFormField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFormField.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormField.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,YAAY,EAAC,MAAM,UAAU,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM;;;kBAQjC,KAAK,CAAC,WAAW,CAAC,gBAAgB,GAAG,mBAAmB,CAAC;8BAOlD,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS;;;kBAejD,YAAY;;EAkBrB;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { FormFieldValue } from '../types';
|
|
2
|
+
export interface PerformanceMetrics {
|
|
3
|
+
renderCount: number;
|
|
4
|
+
lastRenderTime: number;
|
|
5
|
+
fieldChangeCount: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Hook to monitor form performance metrics
|
|
9
|
+
*
|
|
10
|
+
* Useful for debugging and optimizing form performance.
|
|
11
|
+
*
|
|
12
|
+
* @returns Performance metrics object
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* function MyForm() {
|
|
17
|
+
* const metrics = useFormPerformance();
|
|
18
|
+
*
|
|
19
|
+
* console.log('Render count:', metrics.renderCount);
|
|
20
|
+
* console.log('Avg validation time:', metrics.averageValidationTime);
|
|
21
|
+
*
|
|
22
|
+
* return <div>...</div>;
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function useFormPerformance(): PerformanceMetrics;
|
|
27
|
+
/**
|
|
28
|
+
* Hook to track validation performance
|
|
29
|
+
*
|
|
30
|
+
* Wraps validation calls with timing metrics.
|
|
31
|
+
*
|
|
32
|
+
* @returns Object with tracked validateField and validateForm functions
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* function MyForm() {
|
|
37
|
+
* const {validateField, validateForm, metrics} = useValidationPerformance();
|
|
38
|
+
*
|
|
39
|
+
* const handleSubmit = () => {
|
|
40
|
+
* validateForm();
|
|
41
|
+
* console.log('Validation took:', metrics.lastValidationTime, 'ms');
|
|
42
|
+
* };
|
|
43
|
+
*
|
|
44
|
+
* return <button onClick={handleSubmit}>Submit</button>;
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function useValidationPerformance(): {
|
|
49
|
+
validateField: (name: string, value?: FormFieldValue) => string | null;
|
|
50
|
+
validateForm: () => Record<string, string | null>;
|
|
51
|
+
metrics: {
|
|
52
|
+
lastValidationTime: number;
|
|
53
|
+
totalValidations: number;
|
|
54
|
+
averageValidationTime: number;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=useFormPerformance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFormPerformance.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormPerformance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,cAAc,EAAC,MAAM,UAAU,CAAC;AAGxC,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,IAAI,kBAAkB,CAiCvD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB;0BAST,MAAM,UAAU,cAAc;;;;;;;EA2C5D"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import React, { useState, useRef, useEffect } from 'react';
|
|
2
|
+
import { useForm, useFormPerformance } from 'form-hook-kit';
|
|
3
|
+
|
|
4
|
+
// Detect if we're in React Native environment
|
|
5
|
+
/* istanbul ignore next */
|
|
6
|
+
const isReactNative = typeof navigator !== 'undefined' &&
|
|
7
|
+
navigator.product === 'ReactNative';
|
|
8
|
+
/**
|
|
9
|
+
* FormDevTools Component
|
|
10
|
+
*
|
|
11
|
+
* A cross-platform development tool for inspecting form state in real-time.
|
|
12
|
+
*
|
|
13
|
+
* **Platform Support:**
|
|
14
|
+
* - **Web**: Shows a visual UI panel by default (`mode="ui"`)
|
|
15
|
+
* - **React Native**: Logs to console by default (`mode="console"`)
|
|
16
|
+
* - Use with React Native Debugger, Flipper, or Metro logs
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* // Web - shows UI panel
|
|
21
|
+
* import {FormProvider} from 'form-hook-kit';
|
|
22
|
+
* import {FormDevTools} from 'form-hook-kit/devtools';
|
|
23
|
+
*
|
|
24
|
+
* function App() {
|
|
25
|
+
* return (
|
|
26
|
+
* <FormProvider schema={schema}>
|
|
27
|
+
* <MyForm />
|
|
28
|
+
* {process.env.NODE_ENV === 'development' && <FormDevTools />}
|
|
29
|
+
* </FormProvider>
|
|
30
|
+
* );
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* // React Native - logs to console
|
|
37
|
+
* import {FormProvider} from 'form-hook-kit';
|
|
38
|
+
* import {FormDevTools} from 'form-hook-kit/devtools';
|
|
39
|
+
*
|
|
40
|
+
* function App() {
|
|
41
|
+
* return (
|
|
42
|
+
* <FormProvider schema={schema}>
|
|
43
|
+
* <MyForm />
|
|
44
|
+
* {__DEV__ && <FormDevTools mode="console" autoLog />}
|
|
45
|
+
* </FormProvider>
|
|
46
|
+
* );
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* // Force console mode (works everywhere)
|
|
53
|
+
* <FormDevTools mode="console" autoLog logPrefix="[MyForm]" />
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
// istanbul ignore next - default mode detection is platform-specific and untestable
|
|
57
|
+
function FormDevTools({ mode = isReactNative ? 'console' : 'ui', autoLog = false, logPrefix = '[FormDevTools]', position = 'bottom-right', defaultOpen = true, } = {}) {
|
|
58
|
+
const { values, errors } = useForm();
|
|
59
|
+
const metrics = useFormPerformance();
|
|
60
|
+
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
61
|
+
const [activeTab, setActiveTab] = useState('values');
|
|
62
|
+
const prevValuesRef = useRef(values);
|
|
63
|
+
const prevErrorsRef = useRef(errors);
|
|
64
|
+
// Console logging mode
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (mode === 'console') {
|
|
67
|
+
if (autoLog) {
|
|
68
|
+
// Log when values change
|
|
69
|
+
if (prevValuesRef.current !== values) {
|
|
70
|
+
console.log(`${logPrefix} Values:`, values);
|
|
71
|
+
prevValuesRef.current = values;
|
|
72
|
+
}
|
|
73
|
+
// Log when errors change
|
|
74
|
+
if (prevErrorsRef.current !== errors) {
|
|
75
|
+
console.log(`${logPrefix} Errors:`, errors);
|
|
76
|
+
prevErrorsRef.current = errors;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}, [values, errors, mode, autoLog, logPrefix]);
|
|
81
|
+
// Expose global logging functions for manual inspection
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (mode === 'console') {
|
|
84
|
+
const globalObj = typeof globalThis !== 'undefined' ? globalThis : /* istanbul ignore next */ (typeof window !== 'undefined' ? window : undefined);
|
|
85
|
+
/* istanbul ignore else */
|
|
86
|
+
if (globalObj) {
|
|
87
|
+
// Adding to global for debugging
|
|
88
|
+
globalObj.formDevTools = {
|
|
89
|
+
logValues: () => console.log(`${logPrefix} Values:`, values),
|
|
90
|
+
logErrors: () => console.log(`${logPrefix} Errors:`, errors),
|
|
91
|
+
logMetrics: () => console.log(`${logPrefix} Performance:`, metrics),
|
|
92
|
+
logAll: () => {
|
|
93
|
+
console.log(`${logPrefix} === Form State ===`);
|
|
94
|
+
console.log('Values:', values);
|
|
95
|
+
console.log('Errors:', errors);
|
|
96
|
+
console.log('Performance:', metrics);
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}, [values, errors, metrics, mode, logPrefix]);
|
|
102
|
+
// If mode is 'none' or 'console', don't render UI
|
|
103
|
+
if (mode === 'none' || mode === 'console') {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
// UI mode (web only)
|
|
107
|
+
/* istanbul ignore next */
|
|
108
|
+
if (isReactNative && mode === 'ui') {
|
|
109
|
+
console.warn(`${logPrefix} UI mode is not supported in React Native. Use mode="console" instead.`);
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const positionStyles = {
|
|
113
|
+
'top-left': { top: 10, left: 10 },
|
|
114
|
+
'top-right': { top: 10, right: 10 },
|
|
115
|
+
'bottom-left': { bottom: 10, left: 10 },
|
|
116
|
+
'bottom-right': { bottom: 10, right: 10 },
|
|
117
|
+
};
|
|
118
|
+
const containerStyle = {
|
|
119
|
+
position: 'fixed',
|
|
120
|
+
...positionStyles[position],
|
|
121
|
+
zIndex: 999999,
|
|
122
|
+
fontFamily: 'monospace',
|
|
123
|
+
fontSize: 12,
|
|
124
|
+
};
|
|
125
|
+
const panelStyle = {
|
|
126
|
+
backgroundColor: '#1e1e1e',
|
|
127
|
+
color: '#d4d4d4',
|
|
128
|
+
border: '1px solid #3e3e3e',
|
|
129
|
+
borderRadius: 4,
|
|
130
|
+
padding: 12,
|
|
131
|
+
minWidth: 300,
|
|
132
|
+
maxWidth: 500,
|
|
133
|
+
maxHeight: 400,
|
|
134
|
+
overflow: 'auto',
|
|
135
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
|
|
136
|
+
};
|
|
137
|
+
const toggleButtonStyle = {
|
|
138
|
+
position: 'absolute',
|
|
139
|
+
top: -10,
|
|
140
|
+
right: -10,
|
|
141
|
+
backgroundColor: '#007acc',
|
|
142
|
+
color: 'white',
|
|
143
|
+
border: 'none',
|
|
144
|
+
borderRadius: '50%',
|
|
145
|
+
width: 30,
|
|
146
|
+
height: 30,
|
|
147
|
+
cursor: 'pointer',
|
|
148
|
+
fontSize: 16,
|
|
149
|
+
display: 'flex',
|
|
150
|
+
alignItems: 'center',
|
|
151
|
+
justifyContent: 'center',
|
|
152
|
+
};
|
|
153
|
+
const tabStyle = {
|
|
154
|
+
display: 'inline-block',
|
|
155
|
+
padding: '4px 8px',
|
|
156
|
+
marginRight: 8,
|
|
157
|
+
cursor: 'pointer',
|
|
158
|
+
borderRadius: 3,
|
|
159
|
+
backgroundColor: '#2d2d2d',
|
|
160
|
+
};
|
|
161
|
+
const activeTabStyle = {
|
|
162
|
+
...tabStyle,
|
|
163
|
+
backgroundColor: '#007acc',
|
|
164
|
+
};
|
|
165
|
+
const codeStyle = {
|
|
166
|
+
backgroundColor: '#2d2d2d',
|
|
167
|
+
padding: 8,
|
|
168
|
+
borderRadius: 3,
|
|
169
|
+
overflow: 'auto',
|
|
170
|
+
maxHeight: 250,
|
|
171
|
+
};
|
|
172
|
+
return (React.createElement("div", { style: containerStyle },
|
|
173
|
+
React.createElement("button", { style: toggleButtonStyle, onClick: () => setIsOpen(!isOpen), "aria-label": "Toggle DevTools" }, "\uD83D\uDD27"),
|
|
174
|
+
isOpen && (React.createElement("div", { style: panelStyle },
|
|
175
|
+
React.createElement("div", { style: { marginBottom: 12, fontWeight: 'bold', fontSize: 14 } }, "Form DevTools"),
|
|
176
|
+
React.createElement("div", { style: { marginBottom: 12 } },
|
|
177
|
+
React.createElement("span", { style: activeTab === 'values' ? activeTabStyle : tabStyle, onClick: () => setActiveTab('values') }, "Values"),
|
|
178
|
+
React.createElement("span", { style: activeTab === 'errors' ? activeTabStyle : tabStyle, onClick: () => setActiveTab('errors') }, "Errors"),
|
|
179
|
+
React.createElement("span", { style: activeTab === 'performance' ? activeTabStyle : tabStyle, onClick: () => setActiveTab('performance') }, "Performance")),
|
|
180
|
+
activeTab === 'values' && (React.createElement("div", null,
|
|
181
|
+
React.createElement("div", { style: { marginBottom: 8, color: '#888' } }, "Current Values:"),
|
|
182
|
+
React.createElement("pre", { style: codeStyle }, JSON.stringify(values, null, 2)))),
|
|
183
|
+
activeTab === 'errors' && (React.createElement("div", null,
|
|
184
|
+
React.createElement("div", { style: { marginBottom: 8, color: '#888' } }, "Errors:"),
|
|
185
|
+
React.createElement("pre", { style: codeStyle }, JSON.stringify(errors, null, 2)))),
|
|
186
|
+
activeTab === 'performance' && (React.createElement("div", null,
|
|
187
|
+
React.createElement("div", { style: { marginBottom: 8, color: '#888' } }, "Performance Metrics:"),
|
|
188
|
+
React.createElement("div", { style: codeStyle },
|
|
189
|
+
React.createElement("div", null,
|
|
190
|
+
"Render Count: ",
|
|
191
|
+
metrics.renderCount),
|
|
192
|
+
React.createElement("div", null,
|
|
193
|
+
"Last Render: ",
|
|
194
|
+
metrics.lastRenderTime,
|
|
195
|
+
"ms"),
|
|
196
|
+
React.createElement("div", null,
|
|
197
|
+
"Field Changes: ",
|
|
198
|
+
metrics.fieldChangeCount)),
|
|
199
|
+
React.createElement("div", { style: { marginTop: 12, fontSize: 11, color: '#888' } }, "Note: For validation metrics, use useValidationPerformance hook")))))));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export { FormDevTools };
|
|
203
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../src/src/devtools/FormDevTools.tsx"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var formHookKit = require('form-hook-kit');
|
|
5
|
+
|
|
6
|
+
// Detect if we're in React Native environment
|
|
7
|
+
/* istanbul ignore next */
|
|
8
|
+
const isReactNative = typeof navigator !== 'undefined' &&
|
|
9
|
+
navigator.product === 'ReactNative';
|
|
10
|
+
/**
|
|
11
|
+
* FormDevTools Component
|
|
12
|
+
*
|
|
13
|
+
* A cross-platform development tool for inspecting form state in real-time.
|
|
14
|
+
*
|
|
15
|
+
* **Platform Support:**
|
|
16
|
+
* - **Web**: Shows a visual UI panel by default (`mode="ui"`)
|
|
17
|
+
* - **React Native**: Logs to console by default (`mode="console"`)
|
|
18
|
+
* - Use with React Native Debugger, Flipper, or Metro logs
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* // Web - shows UI panel
|
|
23
|
+
* import {FormProvider} from 'form-hook-kit';
|
|
24
|
+
* import {FormDevTools} from 'form-hook-kit/devtools';
|
|
25
|
+
*
|
|
26
|
+
* function App() {
|
|
27
|
+
* return (
|
|
28
|
+
* <FormProvider schema={schema}>
|
|
29
|
+
* <MyForm />
|
|
30
|
+
* {process.env.NODE_ENV === 'development' && <FormDevTools />}
|
|
31
|
+
* </FormProvider>
|
|
32
|
+
* );
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* // React Native - logs to console
|
|
39
|
+
* import {FormProvider} from 'form-hook-kit';
|
|
40
|
+
* import {FormDevTools} from 'form-hook-kit/devtools';
|
|
41
|
+
*
|
|
42
|
+
* function App() {
|
|
43
|
+
* return (
|
|
44
|
+
* <FormProvider schema={schema}>
|
|
45
|
+
* <MyForm />
|
|
46
|
+
* {__DEV__ && <FormDevTools mode="console" autoLog />}
|
|
47
|
+
* </FormProvider>
|
|
48
|
+
* );
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* // Force console mode (works everywhere)
|
|
55
|
+
* <FormDevTools mode="console" autoLog logPrefix="[MyForm]" />
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
// istanbul ignore next - default mode detection is platform-specific and untestable
|
|
59
|
+
function FormDevTools({ mode = isReactNative ? 'console' : 'ui', autoLog = false, logPrefix = '[FormDevTools]', position = 'bottom-right', defaultOpen = true, } = {}) {
|
|
60
|
+
const { values, errors } = formHookKit.useForm();
|
|
61
|
+
const metrics = formHookKit.useFormPerformance();
|
|
62
|
+
const [isOpen, setIsOpen] = React.useState(defaultOpen);
|
|
63
|
+
const [activeTab, setActiveTab] = React.useState('values');
|
|
64
|
+
const prevValuesRef = React.useRef(values);
|
|
65
|
+
const prevErrorsRef = React.useRef(errors);
|
|
66
|
+
// Console logging mode
|
|
67
|
+
React.useEffect(() => {
|
|
68
|
+
if (mode === 'console') {
|
|
69
|
+
if (autoLog) {
|
|
70
|
+
// Log when values change
|
|
71
|
+
if (prevValuesRef.current !== values) {
|
|
72
|
+
console.log(`${logPrefix} Values:`, values);
|
|
73
|
+
prevValuesRef.current = values;
|
|
74
|
+
}
|
|
75
|
+
// Log when errors change
|
|
76
|
+
if (prevErrorsRef.current !== errors) {
|
|
77
|
+
console.log(`${logPrefix} Errors:`, errors);
|
|
78
|
+
prevErrorsRef.current = errors;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}, [values, errors, mode, autoLog, logPrefix]);
|
|
83
|
+
// Expose global logging functions for manual inspection
|
|
84
|
+
React.useEffect(() => {
|
|
85
|
+
if (mode === 'console') {
|
|
86
|
+
const globalObj = typeof globalThis !== 'undefined' ? globalThis : /* istanbul ignore next */ (typeof window !== 'undefined' ? window : undefined);
|
|
87
|
+
/* istanbul ignore else */
|
|
88
|
+
if (globalObj) {
|
|
89
|
+
// Adding to global for debugging
|
|
90
|
+
globalObj.formDevTools = {
|
|
91
|
+
logValues: () => console.log(`${logPrefix} Values:`, values),
|
|
92
|
+
logErrors: () => console.log(`${logPrefix} Errors:`, errors),
|
|
93
|
+
logMetrics: () => console.log(`${logPrefix} Performance:`, metrics),
|
|
94
|
+
logAll: () => {
|
|
95
|
+
console.log(`${logPrefix} === Form State ===`);
|
|
96
|
+
console.log('Values:', values);
|
|
97
|
+
console.log('Errors:', errors);
|
|
98
|
+
console.log('Performance:', metrics);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}, [values, errors, metrics, mode, logPrefix]);
|
|
104
|
+
// If mode is 'none' or 'console', don't render UI
|
|
105
|
+
if (mode === 'none' || mode === 'console') {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
// UI mode (web only)
|
|
109
|
+
/* istanbul ignore next */
|
|
110
|
+
if (isReactNative && mode === 'ui') {
|
|
111
|
+
console.warn(`${logPrefix} UI mode is not supported in React Native. Use mode="console" instead.`);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
const positionStyles = {
|
|
115
|
+
'top-left': { top: 10, left: 10 },
|
|
116
|
+
'top-right': { top: 10, right: 10 },
|
|
117
|
+
'bottom-left': { bottom: 10, left: 10 },
|
|
118
|
+
'bottom-right': { bottom: 10, right: 10 },
|
|
119
|
+
};
|
|
120
|
+
const containerStyle = {
|
|
121
|
+
position: 'fixed',
|
|
122
|
+
...positionStyles[position],
|
|
123
|
+
zIndex: 999999,
|
|
124
|
+
fontFamily: 'monospace',
|
|
125
|
+
fontSize: 12,
|
|
126
|
+
};
|
|
127
|
+
const panelStyle = {
|
|
128
|
+
backgroundColor: '#1e1e1e',
|
|
129
|
+
color: '#d4d4d4',
|
|
130
|
+
border: '1px solid #3e3e3e',
|
|
131
|
+
borderRadius: 4,
|
|
132
|
+
padding: 12,
|
|
133
|
+
minWidth: 300,
|
|
134
|
+
maxWidth: 500,
|
|
135
|
+
maxHeight: 400,
|
|
136
|
+
overflow: 'auto',
|
|
137
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
|
|
138
|
+
};
|
|
139
|
+
const toggleButtonStyle = {
|
|
140
|
+
position: 'absolute',
|
|
141
|
+
top: -10,
|
|
142
|
+
right: -10,
|
|
143
|
+
backgroundColor: '#007acc',
|
|
144
|
+
color: 'white',
|
|
145
|
+
border: 'none',
|
|
146
|
+
borderRadius: '50%',
|
|
147
|
+
width: 30,
|
|
148
|
+
height: 30,
|
|
149
|
+
cursor: 'pointer',
|
|
150
|
+
fontSize: 16,
|
|
151
|
+
display: 'flex',
|
|
152
|
+
alignItems: 'center',
|
|
153
|
+
justifyContent: 'center',
|
|
154
|
+
};
|
|
155
|
+
const tabStyle = {
|
|
156
|
+
display: 'inline-block',
|
|
157
|
+
padding: '4px 8px',
|
|
158
|
+
marginRight: 8,
|
|
159
|
+
cursor: 'pointer',
|
|
160
|
+
borderRadius: 3,
|
|
161
|
+
backgroundColor: '#2d2d2d',
|
|
162
|
+
};
|
|
163
|
+
const activeTabStyle = {
|
|
164
|
+
...tabStyle,
|
|
165
|
+
backgroundColor: '#007acc',
|
|
166
|
+
};
|
|
167
|
+
const codeStyle = {
|
|
168
|
+
backgroundColor: '#2d2d2d',
|
|
169
|
+
padding: 8,
|
|
170
|
+
borderRadius: 3,
|
|
171
|
+
overflow: 'auto',
|
|
172
|
+
maxHeight: 250,
|
|
173
|
+
};
|
|
174
|
+
return (React.createElement("div", { style: containerStyle },
|
|
175
|
+
React.createElement("button", { style: toggleButtonStyle, onClick: () => setIsOpen(!isOpen), "aria-label": "Toggle DevTools" }, "\uD83D\uDD27"),
|
|
176
|
+
isOpen && (React.createElement("div", { style: panelStyle },
|
|
177
|
+
React.createElement("div", { style: { marginBottom: 12, fontWeight: 'bold', fontSize: 14 } }, "Form DevTools"),
|
|
178
|
+
React.createElement("div", { style: { marginBottom: 12 } },
|
|
179
|
+
React.createElement("span", { style: activeTab === 'values' ? activeTabStyle : tabStyle, onClick: () => setActiveTab('values') }, "Values"),
|
|
180
|
+
React.createElement("span", { style: activeTab === 'errors' ? activeTabStyle : tabStyle, onClick: () => setActiveTab('errors') }, "Errors"),
|
|
181
|
+
React.createElement("span", { style: activeTab === 'performance' ? activeTabStyle : tabStyle, onClick: () => setActiveTab('performance') }, "Performance")),
|
|
182
|
+
activeTab === 'values' && (React.createElement("div", null,
|
|
183
|
+
React.createElement("div", { style: { marginBottom: 8, color: '#888' } }, "Current Values:"),
|
|
184
|
+
React.createElement("pre", { style: codeStyle }, JSON.stringify(values, null, 2)))),
|
|
185
|
+
activeTab === 'errors' && (React.createElement("div", null,
|
|
186
|
+
React.createElement("div", { style: { marginBottom: 8, color: '#888' } }, "Errors:"),
|
|
187
|
+
React.createElement("pre", { style: codeStyle }, JSON.stringify(errors, null, 2)))),
|
|
188
|
+
activeTab === 'performance' && (React.createElement("div", null,
|
|
189
|
+
React.createElement("div", { style: { marginBottom: 8, color: '#888' } }, "Performance Metrics:"),
|
|
190
|
+
React.createElement("div", { style: codeStyle },
|
|
191
|
+
React.createElement("div", null,
|
|
192
|
+
"Render Count: ",
|
|
193
|
+
metrics.renderCount),
|
|
194
|
+
React.createElement("div", null,
|
|
195
|
+
"Last Render: ",
|
|
196
|
+
metrics.lastRenderTime,
|
|
197
|
+
"ms"),
|
|
198
|
+
React.createElement("div", null,
|
|
199
|
+
"Field Changes: ",
|
|
200
|
+
metrics.fieldChangeCount)),
|
|
201
|
+
React.createElement("div", { style: { marginTop: 12, fontSize: 11, color: '#888' } }, "Note: For validation metrics, use useValidationPerformance hook")))))));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
exports.FormDevTools = FormDevTools;
|
|
205
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/src/devtools/FormDevTools.tsx"],"sourcesContent":[null],"names":["useForm","useFormPerformance","useState","useRef","useEffect"],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { AnySchema } from 'yup';
|
|
2
|
+
/**
|
|
3
|
+
* Generic form field value type
|
|
4
|
+
*/
|
|
5
|
+
export type FormFieldValue = string | number | boolean | null | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Form values object
|
|
8
|
+
*/
|
|
9
|
+
export type FormValues = Record<string, FormFieldValue>;
|
|
10
|
+
/**
|
|
11
|
+
* Minimal interface for form field refs
|
|
12
|
+
* Works with both web inputs and React Native TextInput
|
|
13
|
+
*/
|
|
14
|
+
export interface FocusableElement {
|
|
15
|
+
focus: () => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Form field ref type (for React Native TextInput or HTML input elements)
|
|
19
|
+
*
|
|
20
|
+
* Supports both web (HTMLInputElement, HTMLTextAreaElement) and React Native (any object with focus method)
|
|
21
|
+
*/
|
|
22
|
+
export type FormFieldRef = FocusableElement | null;
|
|
23
|
+
/**
|
|
24
|
+
* Form context state
|
|
25
|
+
*/
|
|
26
|
+
export interface FormState {
|
|
27
|
+
errors: Record<string, string | null>;
|
|
28
|
+
values: FormValues;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Form context value interface
|
|
32
|
+
*/
|
|
33
|
+
export interface FormContextValue {
|
|
34
|
+
/** Refs to form fields for focus management */
|
|
35
|
+
fieldRefs: React.MutableRefObject<Record<string, FormFieldRef>>;
|
|
36
|
+
/** Current form errors by field name */
|
|
37
|
+
errors: Record<string, string | null>;
|
|
38
|
+
/** Current form values by field name */
|
|
39
|
+
values: FormValues;
|
|
40
|
+
/** Change a single field value */
|
|
41
|
+
changeValue: (params: {
|
|
42
|
+
name: string;
|
|
43
|
+
value: FormFieldValue;
|
|
44
|
+
}) => void;
|
|
45
|
+
/** Change multiple field values at once */
|
|
46
|
+
changeValues: (values: FormValues) => void;
|
|
47
|
+
/** Clear error for a specific field */
|
|
48
|
+
clearError: (name: string) => void;
|
|
49
|
+
/** Set error for a specific field */
|
|
50
|
+
setError: (params: {
|
|
51
|
+
name: string;
|
|
52
|
+
error: string;
|
|
53
|
+
}) => void;
|
|
54
|
+
/** Validate a single field and return error if any */
|
|
55
|
+
validateField: (name: string, value?: FormFieldValue) => string | null;
|
|
56
|
+
/** Validate entire form and return errors object */
|
|
57
|
+
validateForm: () => Record<string, string | null>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Form provider props
|
|
61
|
+
*/
|
|
62
|
+
export interface FormProviderProps {
|
|
63
|
+
/** Form child components */
|
|
64
|
+
children: React.ReactNode;
|
|
65
|
+
/** Initial error state */
|
|
66
|
+
initialErrors?: Record<string, string>;
|
|
67
|
+
/** Initial form values */
|
|
68
|
+
initialValues?: FormValues;
|
|
69
|
+
/** Yup validation schema */
|
|
70
|
+
schema: AnySchema;
|
|
71
|
+
/**
|
|
72
|
+
* Debounce validation in milliseconds. Useful for performance optimization.
|
|
73
|
+
* @default 0 (no debounce)
|
|
74
|
+
*/
|
|
75
|
+
validationDebounce?: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Form actions
|
|
79
|
+
*/
|
|
80
|
+
export declare enum FormActions {
|
|
81
|
+
UPDATE_ERRORS = "UPDATE_ERRORS",
|
|
82
|
+
UPDATE_VALUES = "UPDATE_VALUES"
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Form action types
|
|
86
|
+
*/
|
|
87
|
+
export type FormAction = {
|
|
88
|
+
type: FormActions.UPDATE_ERRORS;
|
|
89
|
+
payload: Record<string, string | null>;
|
|
90
|
+
} | {
|
|
91
|
+
type: FormActions.UPDATE_VALUES;
|
|
92
|
+
payload: FormValues;
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,KAAK,CAAC;AAE9B;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,IAAI,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACtC,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,SAAS,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAChE,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACtC,wCAAwC;IACxC,MAAM,EAAE,UAAU,CAAC;IACnB,kCAAkC;IAClC,WAAW,EAAE,CAAC,MAAM,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,CAAA;KAAC,KAAK,IAAI,CAAC;IACrE,2CAA2C;IAC3C,YAAY,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,uCAAuC;IACvC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,qCAAqC;IACrC,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,KAAK,IAAI,CAAC;IAC1D,sDAAsD;IACtD,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,cAAc,KAAK,MAAM,GAAG,IAAI,CAAC;IACvE,oDAAoD;IACpD,YAAY,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,4BAA4B;IAC5B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,0BAA0B;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,0BAA0B;IAC1B,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,4BAA4B;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,oBAAY,WAAW;IACrB,aAAa,kBAAkB;IAC/B,aAAa,kBAAkB;CAChC;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAClB;IACE,IAAI,EAAE,WAAW,CAAC,aAAa,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACxC,GACD;IACE,IAAI,EAAE,WAAW,CAAC,aAAa,CAAC;IAChC,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a debounced function that delays invoking func until after wait milliseconds
|
|
3
|
+
* have elapsed since the last time the debounced function was invoked.
|
|
4
|
+
*/
|
|
5
|
+
export declare function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void;
|
|
6
|
+
//# sourceMappingURL=debounce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../../src/utils/debounce.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxD,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAYlC"}
|