-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathuseExportControlToExtension.ts
More file actions
100 lines (88 loc) · 2.76 KB
/
useExportControlToExtension.ts
File metadata and controls
100 lines (88 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import get from 'es-toolkit/compat/get';
import { useEffect, useState } from 'react';
import { Control, useFormState, useWatch } from 'react-hook-form';
import useDeepCompareEffect from 'use-deep-compare-effect';
import { MessageData, UpdatePayload } from './types';
import { nestToFlat, proxyToObject } from './utils';
export function useExportControlToExtension({
id,
control,
}: {
id: string;
control: Control<any>;
}) {
const nestedFormValues = useWatch({ control });
const formState = useFormState({ control });
const [isExtensionEnabled, setIsExtensionEnabled] = useState(false);
const handleInitMessage = (message: MessageEvent<MessageData>) => {
if (
message.data.source !== 'react-hook-form-bridge' ||
message.data.type !== 'INIT'
) {
return;
}
window.postMessage({
source: 'react-hook-form-bridge',
type: 'WELCOME',
} as MessageData);
setIsExtensionEnabled(true);
};
useEffect(() => {
window.addEventListener('message', handleInitMessage);
return () => window.removeEventListener('message', handleInitMessage);
}, []);
useDeepCompareEffect(() => {
if (!isExtensionEnabled) {
return;
}
const {
errors: nestedErrors,
dirtyFields: nestedDirtyFields,
touchedFields: nestedTouchedFields,
...formStatus
} = proxyToObject(formState);
const flatFieldNames = [...control._names.mount];
const formValues = nestToFlat(flatFieldNames, nestedFormValues, '');
const dirtyFields = nestToFlat(flatFieldNames, nestedDirtyFields, false);
const touchedFields = nestToFlat(
flatFieldNames,
nestedTouchedFields,
false,
);
const flatErrors = nestToFlat<{ type?: string; message?: string }>(
flatFieldNames,
nestedErrors,
);
const errors = Object.entries(flatErrors).reduce((prev, [key, value]) => {
prev[key] = {
type: value?.type as string,
message: value?.message as string,
};
return prev;
}, {} as Record<string, { type?: string; message?: string }>);
const nativeFields = flatFieldNames.reduce((prev, name) => {
const field = get(control._fields, name)?._f;
prev[name] = (get(field, 'ref') as any)?.type;
return prev;
}, {} as Record<string, boolean>);
const updateMessagePayload: UpdatePayload = {
id,
data: {
formValues,
formState: {
errors,
dirtyFields,
touchedFields,
nativeFields,
...formStatus,
},
},
};
window.postMessage({
source: 'react-hook-form-bridge',
type: 'UPDATE',
payload: updateMessagePayload,
} as MessageData);
}, [isExtensionEnabled, nestedFormValues, proxyToObject(formState)]);
return { isExtensionEnabled };
}