@vuu-ui/vuu-ui-controls 2.1.10 → 2.1.12
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.
|
@@ -11,15 +11,19 @@ const useEditableText = ({
|
|
|
11
11
|
type = "string"
|
|
12
12
|
}) => {
|
|
13
13
|
const [editState, setEditState] = React.useState({
|
|
14
|
+
editing: false,
|
|
14
15
|
value: stringValueOf(value)
|
|
15
16
|
});
|
|
16
17
|
const initialValueRef = React.useRef(value?.toString() ?? "");
|
|
17
18
|
const isDirtyRef = React.useRef(false);
|
|
18
|
-
const isEditingRef = React.useRef(false);
|
|
19
19
|
React.useMemo(() => {
|
|
20
20
|
if (initialValueRef.current !== value?.toString()) {
|
|
21
21
|
initialValueRef.current = stringValueOf(value);
|
|
22
|
-
setEditState(
|
|
22
|
+
setEditState((editState2) => ({
|
|
23
|
+
...editState2,
|
|
24
|
+
message: void 0,
|
|
25
|
+
value: stringValueOf(value)
|
|
26
|
+
}));
|
|
23
27
|
}
|
|
24
28
|
}, [value]);
|
|
25
29
|
const commit = React.useCallback(async () => {
|
|
@@ -33,10 +37,9 @@ const useEditableText = ({
|
|
|
33
37
|
return false;
|
|
34
38
|
} else {
|
|
35
39
|
const { current: initialValue } = initialValueRef;
|
|
40
|
+
const previousValue = vuuUtils.getTypedValue(initialValue, type);
|
|
36
41
|
try {
|
|
37
42
|
const typedValue = vuuUtils.getTypedValue(value2, type, true);
|
|
38
|
-
console.log(`[useEditableText] typedValue = ${typedValue}`);
|
|
39
|
-
const previousValue = vuuUtils.getTypedValue(initialValue, type);
|
|
40
43
|
const response = await onEdit?.(
|
|
41
44
|
{
|
|
42
45
|
editType: "commit",
|
|
@@ -49,23 +52,16 @@ const useEditableText = ({
|
|
|
49
52
|
if (vuuUtils.isRpcSuccess(response)) {
|
|
50
53
|
isDirtyRef.current = false;
|
|
51
54
|
setEditState(({ previousValue: previousValue2, value: value3 }) => ({
|
|
55
|
+
editing: false,
|
|
52
56
|
previousValue: previousValue2 === value3 ? void 0 : previousValue2 === void 0 ? initialValue : previousValue2,
|
|
53
57
|
value: value3
|
|
54
58
|
}));
|
|
55
59
|
} else if (vuuUtils.isRpcError(response)) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
initialValueRef.current = value2;
|
|
62
|
-
return true;
|
|
63
|
-
} else {
|
|
64
|
-
setEditState((state) => ({
|
|
65
|
-
...state,
|
|
66
|
-
message: response.errorMessage
|
|
67
|
-
}));
|
|
68
|
-
}
|
|
60
|
+
setEditState((state) => ({
|
|
61
|
+
...state,
|
|
62
|
+
message: response.errorMessage
|
|
63
|
+
}));
|
|
64
|
+
return false;
|
|
69
65
|
}
|
|
70
66
|
initialValueRef.current = value2;
|
|
71
67
|
return true;
|
|
@@ -79,6 +75,15 @@ const useEditableText = ({
|
|
|
79
75
|
...state,
|
|
80
76
|
message: message2
|
|
81
77
|
}));
|
|
78
|
+
onEdit?.(
|
|
79
|
+
{
|
|
80
|
+
editType: "commit",
|
|
81
|
+
isValid: false,
|
|
82
|
+
previousValue,
|
|
83
|
+
value: value2
|
|
84
|
+
},
|
|
85
|
+
"commit"
|
|
86
|
+
);
|
|
82
87
|
} else {
|
|
83
88
|
setEditState((state) => ({
|
|
84
89
|
...state,
|
|
@@ -90,38 +95,15 @@ const useEditableText = ({
|
|
|
90
95
|
}
|
|
91
96
|
return false;
|
|
92
97
|
}, [column, editState, onEdit, type]);
|
|
93
|
-
const
|
|
94
|
-
async (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (isEditingRef.current) {
|
|
99
|
-
if (isDirtyRef.current) {
|
|
100
|
-
const commitSuccessful = await commit();
|
|
101
|
-
if (commitSuccessful) {
|
|
102
|
-
isEditingRef.current = false;
|
|
103
|
-
vuuUtils.dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
104
|
-
vuuUtils.dispatchCustomEvent(input, "vuu-commit");
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
isEditingRef.current = false;
|
|
108
|
-
vuuUtils.dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
109
|
-
}
|
|
110
|
-
} else {
|
|
111
|
-
isEditingRef.current = true;
|
|
112
|
-
vuuUtils.dispatchCustomEvent(input, "vuu-enter-edit-mode");
|
|
113
|
-
input.select();
|
|
114
|
-
}
|
|
115
|
-
} else if (key === "ArrowRight" || key === "ArrowLeft" || key === "ArrowUp" || key === "ArrowDown") {
|
|
116
|
-
if (isEditingRef.current) {
|
|
117
|
-
evt.stopPropagation();
|
|
118
|
-
}
|
|
119
|
-
} else if (evt.key === "Escape") {
|
|
120
|
-
if (isEditingRef.current) {
|
|
121
|
-
if (isDirtyRef.current) {
|
|
98
|
+
const toggleActivation = React.useCallback(
|
|
99
|
+
async (input, cancel = false) => {
|
|
100
|
+
if (editState.editing) {
|
|
101
|
+
if (isDirtyRef.current) {
|
|
102
|
+
if (cancel) {
|
|
122
103
|
const { value: previousValue } = editState;
|
|
123
104
|
isDirtyRef.current = false;
|
|
124
105
|
setEditState({
|
|
106
|
+
editing: false,
|
|
125
107
|
value: initialValueRef.current,
|
|
126
108
|
message: void 0
|
|
127
109
|
});
|
|
@@ -134,44 +116,64 @@ const useEditableText = ({
|
|
|
134
116
|
},
|
|
135
117
|
"cancel"
|
|
136
118
|
);
|
|
119
|
+
} else {
|
|
120
|
+
const commitSuccessful = await commit();
|
|
121
|
+
if (commitSuccessful) {
|
|
122
|
+
setEditState((editState2) => ({ ...editState2, editing: false }));
|
|
123
|
+
vuuUtils.dispatchCustomEvent(input, "vuu-commit");
|
|
124
|
+
}
|
|
137
125
|
}
|
|
138
|
-
|
|
139
|
-
|
|
126
|
+
} else {
|
|
127
|
+
setEditState((editState2) => ({ ...editState2, editing: false }));
|
|
140
128
|
}
|
|
129
|
+
} else if (!cancel) {
|
|
130
|
+
setEditState((editState2) => ({ ...editState2, editing: true }));
|
|
131
|
+
input.select();
|
|
141
132
|
}
|
|
142
133
|
},
|
|
143
134
|
[commit, editState, onEdit]
|
|
144
135
|
);
|
|
145
|
-
const
|
|
146
|
-
isEditingRef.current = true;
|
|
147
|
-
vuuUtils.dispatchCustomEvent(evt.target, "vuu-enter-edit-mode");
|
|
148
|
-
}, []);
|
|
149
|
-
const handleFocus = React.useCallback(
|
|
150
|
-
(e) => {
|
|
151
|
-
e.target.addEventListener("vuu-begin-edit", beginEditHandler, true);
|
|
152
|
-
},
|
|
153
|
-
[beginEditHandler]
|
|
154
|
-
);
|
|
155
|
-
const handleBlur = React.useCallback(
|
|
136
|
+
const handleKeyDown = React.useCallback(
|
|
156
137
|
async (evt) => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
138
|
+
const { key, target } = evt;
|
|
139
|
+
const input = target;
|
|
140
|
+
if (key === "Enter") {
|
|
141
|
+
toggleActivation(input);
|
|
142
|
+
} else if (key === "ArrowRight" || key === "ArrowLeft" || key === "ArrowUp" || key === "ArrowDown") {
|
|
143
|
+
if (editState.editing) {
|
|
144
|
+
evt.stopPropagation();
|
|
162
145
|
}
|
|
163
|
-
|
|
164
|
-
|
|
146
|
+
} else if (evt.key === "Escape") {
|
|
147
|
+
toggleActivation(input, true);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
[editState, toggleActivation]
|
|
151
|
+
);
|
|
152
|
+
const handleFocus = React.useCallback(
|
|
153
|
+
(e) => {
|
|
154
|
+
const input = e.target;
|
|
155
|
+
const source = e.relatedTarget;
|
|
156
|
+
if (source?.classList.contains("vuuTableCell") && source.contains(input)) {
|
|
157
|
+
toggleActivation(input);
|
|
165
158
|
}
|
|
166
159
|
},
|
|
167
|
-
[
|
|
160
|
+
[toggleActivation]
|
|
168
161
|
);
|
|
162
|
+
const handleBlur = React.useCallback(async () => {
|
|
163
|
+
if (editState.editing) {
|
|
164
|
+
if (isDirtyRef.current) {
|
|
165
|
+
const commitSuccessful = await commit();
|
|
166
|
+
console.log({ commitSuccessful });
|
|
167
|
+
}
|
|
168
|
+
setEditState((editState2) => ({ ...editState2, editing: false }));
|
|
169
|
+
}
|
|
170
|
+
}, [commit, editState]);
|
|
169
171
|
const handleChange = React.useCallback(
|
|
170
172
|
(evt) => {
|
|
171
173
|
const { value: value2 } = evt.target;
|
|
172
174
|
isDirtyRef.current = value2 !== initialValueRef.current;
|
|
173
175
|
const result = column.clientSideEditValidationCheck?.(value2, "change");
|
|
174
|
-
setEditState({ value: value2 });
|
|
176
|
+
setEditState({ editing: true, value: value2 });
|
|
175
177
|
onEdit?.(
|
|
176
178
|
{
|
|
177
179
|
editType: "change",
|
|
@@ -182,11 +184,11 @@ const useEditableText = ({
|
|
|
182
184
|
"change"
|
|
183
185
|
);
|
|
184
186
|
if (result?.ok === false) {
|
|
185
|
-
setEditState({
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
setEditState({
|
|
188
|
+
editing: true,
|
|
189
|
+
value: value2,
|
|
190
|
+
message: result.messages?.join(",")
|
|
191
|
+
});
|
|
190
192
|
}
|
|
191
193
|
},
|
|
192
194
|
[column, onEdit]
|
|
@@ -196,13 +198,14 @@ const useEditableText = ({
|
|
|
196
198
|
* has the value been edited during this edit session
|
|
197
199
|
*/
|
|
198
200
|
edited: editState.previousValue !== void 0 && editState.previousValue !== editState.value,
|
|
199
|
-
|
|
201
|
+
editing: editState.editing,
|
|
200
202
|
inputProps: {
|
|
201
203
|
onBlur: handleBlur,
|
|
202
204
|
onFocus: handleFocus,
|
|
203
205
|
onKeyDown: handleKeyDown
|
|
204
206
|
},
|
|
205
207
|
onChange: handleChange,
|
|
208
|
+
previousValue: editState.previousValue,
|
|
206
209
|
value: editState.value,
|
|
207
210
|
warningMessage: editState.message
|
|
208
211
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type {\n RuntimeColumnDescriptor,\n TableCellEditHandler,\n} from \"@vuu-ui/vuu-table-types\";\nimport {\n DataValidationError,\n dispatchCustomEvent,\n getTypedValue,\n isRpcError,\n isRpcSuccess,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n column: Pick<\n RuntimeColumnDescriptor,\n \"clientSideEditValidationCheck\" | \"label\" | \"name\"\n >;\n value?: T;\n onEdit?: TableCellEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n message?: string;\n // Set once we commit an edit, cleared when edit session is ended.\n previousValue?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n column,\n value,\n onEdit,\n type = \"string\",\n}: EditableTextHookProps<T>) => {\n const [editState, setEditState] = useState<EditState>({\n value: stringValueOf(value),\n });\n const initialValueRef = useRef<string>(value?.toString() ?? \"\");\n const isDirtyRef = useRef(false);\n const isEditingRef = useRef(false);\n\n useMemo(() => {\n if (initialValueRef.current !== value?.toString()) {\n initialValueRef.current = stringValueOf(value);\n setEditState({ message: undefined, value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n const result = column.clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n return false;\n } else {\n //save initial value,it could be reset by time async operation completes\n const { current: initialValue } = initialValueRef;\n try {\n const typedValue = getTypedValue(value, type, true);\n console.log(`[useEditableText] typedValue = ${typedValue}`);\n const previousValue = getTypedValue(initialValue, type);\n const response = await onEdit?.(\n {\n editType: \"commit\",\n isValid: true,\n previousValue,\n value: typedValue,\n },\n \"commit\",\n );\n if (isRpcSuccess(response)) {\n isDirtyRef.current = false;\n setEditState(({ previousValue, value }) => ({\n previousValue:\n previousValue === value\n ? undefined\n : previousValue === undefined\n ? initialValue\n : previousValue,\n value,\n }));\n } else if (isRpcError(response)) {\n if (response.errorMessage === \"CHANGE_REVERTED\") {\n setEditState(({ value }) => ({\n previousValue: undefined,\n value,\n }));\n initialValueRef.current = value;\n return true;\n } else {\n setEditState((state) => ({\n ...state,\n message: response.errorMessage,\n }));\n }\n }\n initialValueRef.current = value;\n return true;\n } catch (e) {\n if (e instanceof DataValidationError) {\n const { actualType, expectedType, message } = e;\n if (column) {\n const { name, label = name } = column;\n const message = `${label} is a ${expectedType} value, data entered is ${actualType} `;\n setEditState((state) => ({\n ...state,\n message,\n }));\n } else {\n setEditState((state) => ({\n ...state,\n message,\n }));\n }\n }\n }\n }\n return false;\n }, [column, editState, onEdit, type]);\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n const commitSuccessful = await commit();\n if (commitSuccessful) {\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n dispatchCustomEvent(input, \"vuu-commit\");\n }\n } else {\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n }\n } else {\n isEditingRef.current = true;\n dispatchCustomEvent(input, \"vuu-enter-edit-mode\");\n input.select();\n }\n } else if (\n key === \"ArrowRight\" ||\n key === \"ArrowLeft\" ||\n key === \"ArrowUp\" ||\n key === \"ArrowDown\"\n ) {\n if (isEditingRef.current) {\n evt.stopPropagation();\n } else {\n // console.log(\n // `[useEditableText] handleKeydown, arrowkey, not editing so let it bubble`,\n // );\n // evt.preventDefault();\n }\n } else if (evt.key === \"Escape\") {\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({\n value: initialValueRef.current,\n message: undefined,\n });\n // this assumes the original value was valid, is that safe ?\n onEdit?.(\n {\n editType: \"cancel\",\n isValid: true,\n previousValue,\n value: initialValueRef.current,\n },\n \"cancel\",\n );\n }\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n }\n }\n },\n [commit, editState, onEdit],\n );\n\n const beginEditHandler = useCallback((evt: Event) => {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }, []);\n\n const handleFocus = useCallback<FocusEventHandler<HTMLElement>>(\n (e) => {\n e.target.addEventListener(\"vuu-begin-edit\", beginEditHandler, true);\n },\n [beginEditHandler],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n async (evt) => {\n evt.target.removeEventListener(\"vuu-begin-edit\", beginEditHandler, true);\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n const commitSuccessful = await commit();\n console.log({ commitSuccessful });\n }\n isEditingRef.current = false;\n dispatchCustomEvent(evt.target, \"vuu-exit-edit-mode\");\n }\n },\n [beginEditHandler, commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n isDirtyRef.current = value !== initialValueRef.current;\n const result = column.clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n previousValue: initialValueRef.current,\n value,\n },\n \"change\",\n );\n if (result?.ok === false) {\n setEditState({ value, message: result.messages?.join(\",\") });\n }\n\n if (!isEditingRef.current) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }\n },\n [column, onEdit],\n );\n\n return {\n /**\n * has the value been edited during this edit session\n */\n edited:\n editState.previousValue !== undefined &&\n editState.previousValue !== editState.value,\n //TODO why are we detecting commit here, why not use VuuInput ?\n inputProps: {\n onBlur: handleBlur,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["useState","useRef","useMemo","useCallback","value","getTypedValue","isRpcSuccess","previousValue","isRpcError","DataValidationError","message","dispatchCustomEvent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type {\n RuntimeColumnDescriptor,\n TableCellEditHandler,\n} from \"@vuu-ui/vuu-table-types\";\nimport {\n DataValidationError,\n dispatchCustomEvent,\n getTypedValue,\n isRpcError,\n isRpcSuccess,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n column: Pick<\n RuntimeColumnDescriptor,\n \"clientSideEditValidationCheck\" | \"label\" | \"name\"\n >;\n value?: T;\n onEdit?: TableCellEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n editing: boolean;\n message?: string;\n // Set once we commit an edit, cleared when edit session is ended.\n previousValue?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n column,\n value,\n onEdit,\n type = \"string\",\n}: EditableTextHookProps<T>) => {\n const [editState, setEditState] = useState<EditState>({\n editing: false,\n value: stringValueOf(value),\n });\n const initialValueRef = useRef<string>(value?.toString() ?? \"\");\n const isDirtyRef = useRef(false);\n\n useMemo(() => {\n if (initialValueRef.current !== value?.toString()) {\n initialValueRef.current = stringValueOf(value);\n setEditState((editState) => ({\n ...editState,\n message: undefined,\n value: stringValueOf(value),\n }));\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n const result = column.clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n return false;\n } else {\n //save initial value,it could be reset by time async operation completes\n const { current: initialValue } = initialValueRef;\n const previousValue = getTypedValue(initialValue, type);\n try {\n const typedValue = getTypedValue(value, type, true);\n const response = await onEdit?.(\n {\n editType: \"commit\",\n isValid: true,\n previousValue,\n value: typedValue,\n },\n \"commit\",\n );\n if (isRpcSuccess(response)) {\n isDirtyRef.current = false;\n setEditState(({ previousValue, value }) => ({\n editing: false,\n previousValue:\n previousValue === value\n ? undefined\n : previousValue === undefined\n ? initialValue\n : previousValue,\n value,\n }));\n } else if (isRpcError(response)) {\n setEditState((state) => ({\n ...state,\n message: response.errorMessage,\n }));\n return false;\n }\n initialValueRef.current = value;\n return true;\n } catch (e) {\n if (e instanceof DataValidationError) {\n const { actualType, expectedType, message } = e;\n if (column) {\n const { name, label = name } = column;\n const message = `${label} is a ${expectedType} value, data entered is ${actualType} `;\n setEditState((state) => ({\n ...state,\n message,\n }));\n onEdit?.(\n {\n editType: \"commit\",\n isValid: false,\n previousValue,\n value,\n },\n \"commit\",\n );\n } else {\n setEditState((state) => ({\n ...state,\n message,\n }));\n }\n }\n }\n }\n return false;\n }, [column, editState, onEdit, type]);\n\n /**\n * Depending on the current state (editing or not, dirty or not) activation will either be\n * entering into edit state, leaving edit state or commiting edited value.\n */\n const toggleActivation = useCallback(\n async (input: HTMLInputElement, cancel = false) => {\n if (editState.editing) {\n if (isDirtyRef.current) {\n if (cancel) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({\n editing: false,\n value: initialValueRef.current,\n message: undefined,\n });\n // this assumes the original value was valid, is that safe ?\n onEdit?.(\n {\n editType: \"cancel\",\n isValid: true,\n previousValue,\n value: initialValueRef.current,\n },\n \"cancel\",\n );\n } else {\n const commitSuccessful = await commit();\n if (commitSuccessful) {\n setEditState((editState) => ({ ...editState, editing: false }));\n dispatchCustomEvent(input, \"vuu-commit\");\n }\n }\n } else {\n setEditState((editState) => ({ ...editState, editing: false }));\n }\n } else if (!cancel) {\n setEditState((editState) => ({ ...editState, editing: true }));\n input.select();\n }\n },\n [commit, editState, onEdit],\n );\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n toggleActivation(input);\n } else if (\n key === \"ArrowRight\" ||\n key === \"ArrowLeft\" ||\n key === \"ArrowUp\" ||\n key === \"ArrowDown\"\n ) {\n if (editState.editing) {\n evt.stopPropagation();\n } else {\n // console.log(\n // `[useEditableText] handleKeydown, arrowkey, not editing so let it bubble`,\n // );\n // evt.preventDefault();\n }\n } else if (evt.key === \"Escape\") {\n toggleActivation(input, true);\n }\n },\n [editState, toggleActivation],\n );\n\n const handleFocus = useCallback<FocusEventHandler<HTMLElement>>(\n (e) => {\n // If focus is transferred from enclosing cell element, we are explicitl entering edit mode\n const input = e.target as HTMLInputElement;\n const source = e.relatedTarget as HTMLElement;\n if (\n source?.classList.contains(\"vuuTableCell\") &&\n source.contains(input)\n ) {\n toggleActivation(input);\n }\n },\n [toggleActivation],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(async () => {\n if (editState.editing) {\n if (isDirtyRef.current) {\n const commitSuccessful = await commit();\n console.log({ commitSuccessful });\n }\n setEditState((editState) => ({ ...editState, editing: false }));\n }\n }, [commit, editState]);\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n isDirtyRef.current = value !== initialValueRef.current;\n const result = column.clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ editing: true, value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n previousValue: initialValueRef.current,\n value,\n },\n \"change\",\n );\n if (result?.ok === false) {\n setEditState({\n editing: true,\n value,\n message: result.messages?.join(\",\"),\n });\n }\n },\n [column, onEdit],\n );\n\n // console.log(\n // `[useEditableText] edited = ${\n // editState.previousValue !== undefined &&\n // editState.previousValue !== editState.value\n // }\n // editState.previousValue ${editState.previousValue}\n // editState.value ${editState.value}\n // `,\n // );\n\n return {\n /**\n * has the value been edited during this edit session\n */\n edited:\n editState.previousValue !== undefined &&\n editState.previousValue !== editState.value,\n editing: editState.editing,\n inputProps: {\n onBlur: handleBlur,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n previousValue: editState.previousValue,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["useState","useRef","useMemo","editState","useCallback","value","getTypedValue","isRpcSuccess","previousValue","isRpcError","DataValidationError","message","dispatchCustomEvent"],"mappings":"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"}
|
|
@@ -9,15 +9,19 @@ const useEditableText = ({
|
|
|
9
9
|
type = "string"
|
|
10
10
|
}) => {
|
|
11
11
|
const [editState, setEditState] = useState({
|
|
12
|
+
editing: false,
|
|
12
13
|
value: stringValueOf(value)
|
|
13
14
|
});
|
|
14
15
|
const initialValueRef = useRef(value?.toString() ?? "");
|
|
15
16
|
const isDirtyRef = useRef(false);
|
|
16
|
-
const isEditingRef = useRef(false);
|
|
17
17
|
useMemo(() => {
|
|
18
18
|
if (initialValueRef.current !== value?.toString()) {
|
|
19
19
|
initialValueRef.current = stringValueOf(value);
|
|
20
|
-
setEditState(
|
|
20
|
+
setEditState((editState2) => ({
|
|
21
|
+
...editState2,
|
|
22
|
+
message: void 0,
|
|
23
|
+
value: stringValueOf(value)
|
|
24
|
+
}));
|
|
21
25
|
}
|
|
22
26
|
}, [value]);
|
|
23
27
|
const commit = useCallback(async () => {
|
|
@@ -31,10 +35,9 @@ const useEditableText = ({
|
|
|
31
35
|
return false;
|
|
32
36
|
} else {
|
|
33
37
|
const { current: initialValue } = initialValueRef;
|
|
38
|
+
const previousValue = getTypedValue(initialValue, type);
|
|
34
39
|
try {
|
|
35
40
|
const typedValue = getTypedValue(value2, type, true);
|
|
36
|
-
console.log(`[useEditableText] typedValue = ${typedValue}`);
|
|
37
|
-
const previousValue = getTypedValue(initialValue, type);
|
|
38
41
|
const response = await onEdit?.(
|
|
39
42
|
{
|
|
40
43
|
editType: "commit",
|
|
@@ -47,23 +50,16 @@ const useEditableText = ({
|
|
|
47
50
|
if (isRpcSuccess(response)) {
|
|
48
51
|
isDirtyRef.current = false;
|
|
49
52
|
setEditState(({ previousValue: previousValue2, value: value3 }) => ({
|
|
53
|
+
editing: false,
|
|
50
54
|
previousValue: previousValue2 === value3 ? void 0 : previousValue2 === void 0 ? initialValue : previousValue2,
|
|
51
55
|
value: value3
|
|
52
56
|
}));
|
|
53
57
|
} else if (isRpcError(response)) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
initialValueRef.current = value2;
|
|
60
|
-
return true;
|
|
61
|
-
} else {
|
|
62
|
-
setEditState((state) => ({
|
|
63
|
-
...state,
|
|
64
|
-
message: response.errorMessage
|
|
65
|
-
}));
|
|
66
|
-
}
|
|
58
|
+
setEditState((state) => ({
|
|
59
|
+
...state,
|
|
60
|
+
message: response.errorMessage
|
|
61
|
+
}));
|
|
62
|
+
return false;
|
|
67
63
|
}
|
|
68
64
|
initialValueRef.current = value2;
|
|
69
65
|
return true;
|
|
@@ -77,6 +73,15 @@ const useEditableText = ({
|
|
|
77
73
|
...state,
|
|
78
74
|
message: message2
|
|
79
75
|
}));
|
|
76
|
+
onEdit?.(
|
|
77
|
+
{
|
|
78
|
+
editType: "commit",
|
|
79
|
+
isValid: false,
|
|
80
|
+
previousValue,
|
|
81
|
+
value: value2
|
|
82
|
+
},
|
|
83
|
+
"commit"
|
|
84
|
+
);
|
|
80
85
|
} else {
|
|
81
86
|
setEditState((state) => ({
|
|
82
87
|
...state,
|
|
@@ -88,38 +93,15 @@ const useEditableText = ({
|
|
|
88
93
|
}
|
|
89
94
|
return false;
|
|
90
95
|
}, [column, editState, onEdit, type]);
|
|
91
|
-
const
|
|
92
|
-
async (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (isEditingRef.current) {
|
|
97
|
-
if (isDirtyRef.current) {
|
|
98
|
-
const commitSuccessful = await commit();
|
|
99
|
-
if (commitSuccessful) {
|
|
100
|
-
isEditingRef.current = false;
|
|
101
|
-
dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
102
|
-
dispatchCustomEvent(input, "vuu-commit");
|
|
103
|
-
}
|
|
104
|
-
} else {
|
|
105
|
-
isEditingRef.current = false;
|
|
106
|
-
dispatchCustomEvent(input, "vuu-exit-edit-mode");
|
|
107
|
-
}
|
|
108
|
-
} else {
|
|
109
|
-
isEditingRef.current = true;
|
|
110
|
-
dispatchCustomEvent(input, "vuu-enter-edit-mode");
|
|
111
|
-
input.select();
|
|
112
|
-
}
|
|
113
|
-
} else if (key === "ArrowRight" || key === "ArrowLeft" || key === "ArrowUp" || key === "ArrowDown") {
|
|
114
|
-
if (isEditingRef.current) {
|
|
115
|
-
evt.stopPropagation();
|
|
116
|
-
}
|
|
117
|
-
} else if (evt.key === "Escape") {
|
|
118
|
-
if (isEditingRef.current) {
|
|
119
|
-
if (isDirtyRef.current) {
|
|
96
|
+
const toggleActivation = useCallback(
|
|
97
|
+
async (input, cancel = false) => {
|
|
98
|
+
if (editState.editing) {
|
|
99
|
+
if (isDirtyRef.current) {
|
|
100
|
+
if (cancel) {
|
|
120
101
|
const { value: previousValue } = editState;
|
|
121
102
|
isDirtyRef.current = false;
|
|
122
103
|
setEditState({
|
|
104
|
+
editing: false,
|
|
123
105
|
value: initialValueRef.current,
|
|
124
106
|
message: void 0
|
|
125
107
|
});
|
|
@@ -132,44 +114,64 @@ const useEditableText = ({
|
|
|
132
114
|
},
|
|
133
115
|
"cancel"
|
|
134
116
|
);
|
|
117
|
+
} else {
|
|
118
|
+
const commitSuccessful = await commit();
|
|
119
|
+
if (commitSuccessful) {
|
|
120
|
+
setEditState((editState2) => ({ ...editState2, editing: false }));
|
|
121
|
+
dispatchCustomEvent(input, "vuu-commit");
|
|
122
|
+
}
|
|
135
123
|
}
|
|
136
|
-
|
|
137
|
-
|
|
124
|
+
} else {
|
|
125
|
+
setEditState((editState2) => ({ ...editState2, editing: false }));
|
|
138
126
|
}
|
|
127
|
+
} else if (!cancel) {
|
|
128
|
+
setEditState((editState2) => ({ ...editState2, editing: true }));
|
|
129
|
+
input.select();
|
|
139
130
|
}
|
|
140
131
|
},
|
|
141
132
|
[commit, editState, onEdit]
|
|
142
133
|
);
|
|
143
|
-
const
|
|
144
|
-
isEditingRef.current = true;
|
|
145
|
-
dispatchCustomEvent(evt.target, "vuu-enter-edit-mode");
|
|
146
|
-
}, []);
|
|
147
|
-
const handleFocus = useCallback(
|
|
148
|
-
(e) => {
|
|
149
|
-
e.target.addEventListener("vuu-begin-edit", beginEditHandler, true);
|
|
150
|
-
},
|
|
151
|
-
[beginEditHandler]
|
|
152
|
-
);
|
|
153
|
-
const handleBlur = useCallback(
|
|
134
|
+
const handleKeyDown = useCallback(
|
|
154
135
|
async (evt) => {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
136
|
+
const { key, target } = evt;
|
|
137
|
+
const input = target;
|
|
138
|
+
if (key === "Enter") {
|
|
139
|
+
toggleActivation(input);
|
|
140
|
+
} else if (key === "ArrowRight" || key === "ArrowLeft" || key === "ArrowUp" || key === "ArrowDown") {
|
|
141
|
+
if (editState.editing) {
|
|
142
|
+
evt.stopPropagation();
|
|
160
143
|
}
|
|
161
|
-
|
|
162
|
-
|
|
144
|
+
} else if (evt.key === "Escape") {
|
|
145
|
+
toggleActivation(input, true);
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
[editState, toggleActivation]
|
|
149
|
+
);
|
|
150
|
+
const handleFocus = useCallback(
|
|
151
|
+
(e) => {
|
|
152
|
+
const input = e.target;
|
|
153
|
+
const source = e.relatedTarget;
|
|
154
|
+
if (source?.classList.contains("vuuTableCell") && source.contains(input)) {
|
|
155
|
+
toggleActivation(input);
|
|
163
156
|
}
|
|
164
157
|
},
|
|
165
|
-
[
|
|
158
|
+
[toggleActivation]
|
|
166
159
|
);
|
|
160
|
+
const handleBlur = useCallback(async () => {
|
|
161
|
+
if (editState.editing) {
|
|
162
|
+
if (isDirtyRef.current) {
|
|
163
|
+
const commitSuccessful = await commit();
|
|
164
|
+
console.log({ commitSuccessful });
|
|
165
|
+
}
|
|
166
|
+
setEditState((editState2) => ({ ...editState2, editing: false }));
|
|
167
|
+
}
|
|
168
|
+
}, [commit, editState]);
|
|
167
169
|
const handleChange = useCallback(
|
|
168
170
|
(evt) => {
|
|
169
171
|
const { value: value2 } = evt.target;
|
|
170
172
|
isDirtyRef.current = value2 !== initialValueRef.current;
|
|
171
173
|
const result = column.clientSideEditValidationCheck?.(value2, "change");
|
|
172
|
-
setEditState({ value: value2 });
|
|
174
|
+
setEditState({ editing: true, value: value2 });
|
|
173
175
|
onEdit?.(
|
|
174
176
|
{
|
|
175
177
|
editType: "change",
|
|
@@ -180,11 +182,11 @@ const useEditableText = ({
|
|
|
180
182
|
"change"
|
|
181
183
|
);
|
|
182
184
|
if (result?.ok === false) {
|
|
183
|
-
setEditState({
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
setEditState({
|
|
186
|
+
editing: true,
|
|
187
|
+
value: value2,
|
|
188
|
+
message: result.messages?.join(",")
|
|
189
|
+
});
|
|
188
190
|
}
|
|
189
191
|
},
|
|
190
192
|
[column, onEdit]
|
|
@@ -194,13 +196,14 @@ const useEditableText = ({
|
|
|
194
196
|
* has the value been edited during this edit session
|
|
195
197
|
*/
|
|
196
198
|
edited: editState.previousValue !== void 0 && editState.previousValue !== editState.value,
|
|
197
|
-
|
|
199
|
+
editing: editState.editing,
|
|
198
200
|
inputProps: {
|
|
199
201
|
onBlur: handleBlur,
|
|
200
202
|
onFocus: handleFocus,
|
|
201
203
|
onKeyDown: handleKeyDown
|
|
202
204
|
},
|
|
203
205
|
onChange: handleChange,
|
|
206
|
+
previousValue: editState.previousValue,
|
|
204
207
|
value: editState.value,
|
|
205
208
|
warningMessage: editState.message
|
|
206
209
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type {\n RuntimeColumnDescriptor,\n TableCellEditHandler,\n} from \"@vuu-ui/vuu-table-types\";\nimport {\n DataValidationError,\n dispatchCustomEvent,\n getTypedValue,\n isRpcError,\n isRpcSuccess,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n column: Pick<\n RuntimeColumnDescriptor,\n \"clientSideEditValidationCheck\" | \"label\" | \"name\"\n >;\n value?: T;\n onEdit?: TableCellEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n message?: string;\n // Set once we commit an edit, cleared when edit session is ended.\n previousValue?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n column,\n value,\n onEdit,\n type = \"string\",\n}: EditableTextHookProps<T>) => {\n const [editState, setEditState] = useState<EditState>({\n value: stringValueOf(value),\n });\n const initialValueRef = useRef<string>(value?.toString() ?? \"\");\n const isDirtyRef = useRef(false);\n const isEditingRef = useRef(false);\n\n useMemo(() => {\n if (initialValueRef.current !== value?.toString()) {\n initialValueRef.current = stringValueOf(value);\n setEditState({ message: undefined, value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n const result = column.clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n return false;\n } else {\n //save initial value,it could be reset by time async operation completes\n const { current: initialValue } = initialValueRef;\n try {\n const typedValue = getTypedValue(value, type, true);\n console.log(`[useEditableText] typedValue = ${typedValue}`);\n const previousValue = getTypedValue(initialValue, type);\n const response = await onEdit?.(\n {\n editType: \"commit\",\n isValid: true,\n previousValue,\n value: typedValue,\n },\n \"commit\",\n );\n if (isRpcSuccess(response)) {\n isDirtyRef.current = false;\n setEditState(({ previousValue, value }) => ({\n previousValue:\n previousValue === value\n ? undefined\n : previousValue === undefined\n ? initialValue\n : previousValue,\n value,\n }));\n } else if (isRpcError(response)) {\n if (response.errorMessage === \"CHANGE_REVERTED\") {\n setEditState(({ value }) => ({\n previousValue: undefined,\n value,\n }));\n initialValueRef.current = value;\n return true;\n } else {\n setEditState((state) => ({\n ...state,\n message: response.errorMessage,\n }));\n }\n }\n initialValueRef.current = value;\n return true;\n } catch (e) {\n if (e instanceof DataValidationError) {\n const { actualType, expectedType, message } = e;\n if (column) {\n const { name, label = name } = column;\n const message = `${label} is a ${expectedType} value, data entered is ${actualType} `;\n setEditState((state) => ({\n ...state,\n message,\n }));\n } else {\n setEditState((state) => ({\n ...state,\n message,\n }));\n }\n }\n }\n }\n return false;\n }, [column, editState, onEdit, type]);\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n const commitSuccessful = await commit();\n if (commitSuccessful) {\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n dispatchCustomEvent(input, \"vuu-commit\");\n }\n } else {\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n }\n } else {\n isEditingRef.current = true;\n dispatchCustomEvent(input, \"vuu-enter-edit-mode\");\n input.select();\n }\n } else if (\n key === \"ArrowRight\" ||\n key === \"ArrowLeft\" ||\n key === \"ArrowUp\" ||\n key === \"ArrowDown\"\n ) {\n if (isEditingRef.current) {\n evt.stopPropagation();\n } else {\n // console.log(\n // `[useEditableText] handleKeydown, arrowkey, not editing so let it bubble`,\n // );\n // evt.preventDefault();\n }\n } else if (evt.key === \"Escape\") {\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({\n value: initialValueRef.current,\n message: undefined,\n });\n // this assumes the original value was valid, is that safe ?\n onEdit?.(\n {\n editType: \"cancel\",\n isValid: true,\n previousValue,\n value: initialValueRef.current,\n },\n \"cancel\",\n );\n }\n isEditingRef.current = false;\n dispatchCustomEvent(input, \"vuu-exit-edit-mode\");\n }\n }\n },\n [commit, editState, onEdit],\n );\n\n const beginEditHandler = useCallback((evt: Event) => {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }, []);\n\n const handleFocus = useCallback<FocusEventHandler<HTMLElement>>(\n (e) => {\n e.target.addEventListener(\"vuu-begin-edit\", beginEditHandler, true);\n },\n [beginEditHandler],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n async (evt) => {\n evt.target.removeEventListener(\"vuu-begin-edit\", beginEditHandler, true);\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n const commitSuccessful = await commit();\n console.log({ commitSuccessful });\n }\n isEditingRef.current = false;\n dispatchCustomEvent(evt.target, \"vuu-exit-edit-mode\");\n }\n },\n [beginEditHandler, commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n isDirtyRef.current = value !== initialValueRef.current;\n const result = column.clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n previousValue: initialValueRef.current,\n value,\n },\n \"change\",\n );\n if (result?.ok === false) {\n setEditState({ value, message: result.messages?.join(\",\") });\n }\n\n if (!isEditingRef.current) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }\n },\n [column, onEdit],\n );\n\n return {\n /**\n * has the value been edited during this edit session\n */\n edited:\n editState.previousValue !== undefined &&\n editState.previousValue !== editState.value,\n //TODO why are we detecting commit here, why not use VuuInput ?\n inputProps: {\n onBlur: handleBlur,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["value","previousValue","message"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type {\n RuntimeColumnDescriptor,\n TableCellEditHandler,\n} from \"@vuu-ui/vuu-table-types\";\nimport {\n DataValidationError,\n dispatchCustomEvent,\n getTypedValue,\n isRpcError,\n isRpcSuccess,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n column: Pick<\n RuntimeColumnDescriptor,\n \"clientSideEditValidationCheck\" | \"label\" | \"name\"\n >;\n value?: T;\n onEdit?: TableCellEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n editing: boolean;\n message?: string;\n // Set once we commit an edit, cleared when edit session is ended.\n previousValue?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n column,\n value,\n onEdit,\n type = \"string\",\n}: EditableTextHookProps<T>) => {\n const [editState, setEditState] = useState<EditState>({\n editing: false,\n value: stringValueOf(value),\n });\n const initialValueRef = useRef<string>(value?.toString() ?? \"\");\n const isDirtyRef = useRef(false);\n\n useMemo(() => {\n if (initialValueRef.current !== value?.toString()) {\n initialValueRef.current = stringValueOf(value);\n setEditState((editState) => ({\n ...editState,\n message: undefined,\n value: stringValueOf(value),\n }));\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n const result = column.clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n return false;\n } else {\n //save initial value,it could be reset by time async operation completes\n const { current: initialValue } = initialValueRef;\n const previousValue = getTypedValue(initialValue, type);\n try {\n const typedValue = getTypedValue(value, type, true);\n const response = await onEdit?.(\n {\n editType: \"commit\",\n isValid: true,\n previousValue,\n value: typedValue,\n },\n \"commit\",\n );\n if (isRpcSuccess(response)) {\n isDirtyRef.current = false;\n setEditState(({ previousValue, value }) => ({\n editing: false,\n previousValue:\n previousValue === value\n ? undefined\n : previousValue === undefined\n ? initialValue\n : previousValue,\n value,\n }));\n } else if (isRpcError(response)) {\n setEditState((state) => ({\n ...state,\n message: response.errorMessage,\n }));\n return false;\n }\n initialValueRef.current = value;\n return true;\n } catch (e) {\n if (e instanceof DataValidationError) {\n const { actualType, expectedType, message } = e;\n if (column) {\n const { name, label = name } = column;\n const message = `${label} is a ${expectedType} value, data entered is ${actualType} `;\n setEditState((state) => ({\n ...state,\n message,\n }));\n onEdit?.(\n {\n editType: \"commit\",\n isValid: false,\n previousValue,\n value,\n },\n \"commit\",\n );\n } else {\n setEditState((state) => ({\n ...state,\n message,\n }));\n }\n }\n }\n }\n return false;\n }, [column, editState, onEdit, type]);\n\n /**\n * Depending on the current state (editing or not, dirty or not) activation will either be\n * entering into edit state, leaving edit state or commiting edited value.\n */\n const toggleActivation = useCallback(\n async (input: HTMLInputElement, cancel = false) => {\n if (editState.editing) {\n if (isDirtyRef.current) {\n if (cancel) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({\n editing: false,\n value: initialValueRef.current,\n message: undefined,\n });\n // this assumes the original value was valid, is that safe ?\n onEdit?.(\n {\n editType: \"cancel\",\n isValid: true,\n previousValue,\n value: initialValueRef.current,\n },\n \"cancel\",\n );\n } else {\n const commitSuccessful = await commit();\n if (commitSuccessful) {\n setEditState((editState) => ({ ...editState, editing: false }));\n dispatchCustomEvent(input, \"vuu-commit\");\n }\n }\n } else {\n setEditState((editState) => ({ ...editState, editing: false }));\n }\n } else if (!cancel) {\n setEditState((editState) => ({ ...editState, editing: true }));\n input.select();\n }\n },\n [commit, editState, onEdit],\n );\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n toggleActivation(input);\n } else if (\n key === \"ArrowRight\" ||\n key === \"ArrowLeft\" ||\n key === \"ArrowUp\" ||\n key === \"ArrowDown\"\n ) {\n if (editState.editing) {\n evt.stopPropagation();\n } else {\n // console.log(\n // `[useEditableText] handleKeydown, arrowkey, not editing so let it bubble`,\n // );\n // evt.preventDefault();\n }\n } else if (evt.key === \"Escape\") {\n toggleActivation(input, true);\n }\n },\n [editState, toggleActivation],\n );\n\n const handleFocus = useCallback<FocusEventHandler<HTMLElement>>(\n (e) => {\n // If focus is transferred from enclosing cell element, we are explicitl entering edit mode\n const input = e.target as HTMLInputElement;\n const source = e.relatedTarget as HTMLElement;\n if (\n source?.classList.contains(\"vuuTableCell\") &&\n source.contains(input)\n ) {\n toggleActivation(input);\n }\n },\n [toggleActivation],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(async () => {\n if (editState.editing) {\n if (isDirtyRef.current) {\n const commitSuccessful = await commit();\n console.log({ commitSuccessful });\n }\n setEditState((editState) => ({ ...editState, editing: false }));\n }\n }, [commit, editState]);\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n isDirtyRef.current = value !== initialValueRef.current;\n const result = column.clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ editing: true, value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n previousValue: initialValueRef.current,\n value,\n },\n \"change\",\n );\n if (result?.ok === false) {\n setEditState({\n editing: true,\n value,\n message: result.messages?.join(\",\"),\n });\n }\n },\n [column, onEdit],\n );\n\n // console.log(\n // `[useEditableText] edited = ${\n // editState.previousValue !== undefined &&\n // editState.previousValue !== editState.value\n // }\n // editState.previousValue ${editState.previousValue}\n // editState.value ${editState.value}\n // `,\n // );\n\n return {\n /**\n * has the value been edited during this edit session\n */\n edited:\n editState.previousValue !== undefined &&\n editState.previousValue !== editState.value,\n editing: editState.editing,\n inputProps: {\n onBlur: handleBlur,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n previousValue: editState.previousValue,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["editState","value","previousValue","message"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.1.
|
|
2
|
+
"version": "2.1.12",
|
|
3
3
|
"description": "VUU UI Controls",
|
|
4
4
|
"author": "heswell",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"devDependencies": {
|
|
7
|
-
"@vuu-ui/vuu-data-types": "2.1.
|
|
8
|
-
"@vuu-ui/vuu-protocol-types": "2.1.
|
|
9
|
-
"@vuu-ui/vuu-table-types": "2.1.
|
|
7
|
+
"@vuu-ui/vuu-data-types": "2.1.12",
|
|
8
|
+
"@vuu-ui/vuu-protocol-types": "2.1.12",
|
|
9
|
+
"@vuu-ui/vuu-table-types": "2.1.12"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@vuu-ui/vuu-context-menu": "2.1.
|
|
13
|
-
"@vuu-ui/vuu-data-react": "2.1.
|
|
14
|
-
"@vuu-ui/vuu-layout": "2.1.
|
|
15
|
-
"@vuu-ui/vuu-popups": "2.1.
|
|
16
|
-
"@vuu-ui/vuu-table": "2.1.
|
|
17
|
-
"@vuu-ui/vuu-utils": "2.1.
|
|
12
|
+
"@vuu-ui/vuu-context-menu": "2.1.12",
|
|
13
|
+
"@vuu-ui/vuu-data-react": "2.1.12",
|
|
14
|
+
"@vuu-ui/vuu-layout": "2.1.12",
|
|
15
|
+
"@vuu-ui/vuu-popups": "2.1.12",
|
|
16
|
+
"@vuu-ui/vuu-table": "2.1.12",
|
|
17
|
+
"@vuu-ui/vuu-utils": "2.1.12",
|
|
18
18
|
"@salt-ds/core": "1.54.1",
|
|
19
19
|
"@salt-ds/icons": "1.16.0",
|
|
20
20
|
"@salt-ds/styles": "0.2.1",
|
|
@@ -12,12 +12,14 @@ export declare const useEditableText: <T extends string | number | boolean = str
|
|
|
12
12
|
* has the value been edited during this edit session
|
|
13
13
|
*/
|
|
14
14
|
edited: boolean;
|
|
15
|
+
editing: boolean;
|
|
15
16
|
inputProps: {
|
|
16
17
|
onBlur: FocusEventHandler<HTMLElement>;
|
|
17
18
|
onFocus: FocusEventHandler<HTMLElement>;
|
|
18
19
|
onKeyDown: (evt: KeyboardEvent<HTMLElement>) => Promise<void>;
|
|
19
20
|
};
|
|
20
21
|
onChange: FormEventHandler;
|
|
22
|
+
previousValue: string | undefined;
|
|
21
23
|
value: string;
|
|
22
24
|
warningMessage: string | undefined;
|
|
23
25
|
};
|