@vuu-ui/vuu-ui-controls 2.1.8 → 2.1.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.
@@ -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({ message: void 0, value: stringValueOf(value) });
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,12 +52,14 @@ 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
60
  if (response.errorMessage === "CHANGE_REVERTED") {
57
61
  setEditState(({ value: value3 }) => ({
62
+ editing: true,
58
63
  previousValue: void 0,
59
64
  value: value3
60
65
  }));
@@ -79,6 +84,15 @@ const useEditableText = ({
79
84
  ...state,
80
85
  message: message2
81
86
  }));
87
+ onEdit?.(
88
+ {
89
+ editType: "commit",
90
+ isValid: false,
91
+ previousValue,
92
+ value: value2
93
+ },
94
+ "commit"
95
+ );
82
96
  } else {
83
97
  setEditState((state) => ({
84
98
  ...state,
@@ -90,38 +104,15 @@ const useEditableText = ({
90
104
  }
91
105
  return false;
92
106
  }, [column, editState, onEdit, type]);
93
- const handleKeyDown = React.useCallback(
94
- async (evt) => {
95
- const { key, target } = evt;
96
- const input = target;
97
- if (key === "Enter") {
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) {
107
+ const toggleActivation = React.useCallback(
108
+ async (input, cancel = false) => {
109
+ if (editState.editing) {
110
+ if (isDirtyRef.current) {
111
+ if (cancel) {
122
112
  const { value: previousValue } = editState;
123
113
  isDirtyRef.current = false;
124
114
  setEditState({
115
+ editing: false,
125
116
  value: initialValueRef.current,
126
117
  message: void 0
127
118
  });
@@ -134,44 +125,64 @@ const useEditableText = ({
134
125
  },
135
126
  "cancel"
136
127
  );
128
+ } else {
129
+ const commitSuccessful = await commit();
130
+ if (commitSuccessful) {
131
+ setEditState((editState2) => ({ ...editState2, editing: false }));
132
+ vuuUtils.dispatchCustomEvent(input, "vuu-commit");
133
+ }
137
134
  }
138
- isEditingRef.current = false;
139
- vuuUtils.dispatchCustomEvent(input, "vuu-exit-edit-mode");
135
+ } else {
136
+ setEditState((editState2) => ({ ...editState2, editing: false }));
140
137
  }
138
+ } else if (!cancel) {
139
+ setEditState((editState2) => ({ ...editState2, editing: true }));
140
+ input.select();
141
141
  }
142
142
  },
143
143
  [commit, editState, onEdit]
144
144
  );
145
- const beginEditHandler = React.useCallback((evt) => {
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(
145
+ const handleKeyDown = React.useCallback(
156
146
  async (evt) => {
157
- evt.target.removeEventListener("vuu-begin-edit", beginEditHandler, true);
158
- if (isEditingRef.current) {
159
- if (isDirtyRef.current) {
160
- const commitSuccessful = await commit();
161
- console.log({ commitSuccessful });
147
+ const { key, target } = evt;
148
+ const input = target;
149
+ if (key === "Enter") {
150
+ toggleActivation(input);
151
+ } else if (key === "ArrowRight" || key === "ArrowLeft" || key === "ArrowUp" || key === "ArrowDown") {
152
+ if (editState.editing) {
153
+ evt.stopPropagation();
162
154
  }
163
- isEditingRef.current = false;
164
- vuuUtils.dispatchCustomEvent(evt.target, "vuu-exit-edit-mode");
155
+ } else if (evt.key === "Escape") {
156
+ toggleActivation(input, true);
157
+ }
158
+ },
159
+ [editState, toggleActivation]
160
+ );
161
+ const handleFocus = React.useCallback(
162
+ (e) => {
163
+ const input = e.target;
164
+ const source = e.relatedTarget;
165
+ if (source?.classList.contains("vuuTableCell") && source.contains(input)) {
166
+ toggleActivation(input);
165
167
  }
166
168
  },
167
- [beginEditHandler, commit]
169
+ [toggleActivation]
168
170
  );
171
+ const handleBlur = React.useCallback(async () => {
172
+ if (editState.editing) {
173
+ if (isDirtyRef.current) {
174
+ const commitSuccessful = await commit();
175
+ console.log({ commitSuccessful });
176
+ }
177
+ setEditState((editState2) => ({ ...editState2, editing: false }));
178
+ }
179
+ }, [commit, editState]);
169
180
  const handleChange = React.useCallback(
170
181
  (evt) => {
171
182
  const { value: value2 } = evt.target;
172
183
  isDirtyRef.current = value2 !== initialValueRef.current;
173
184
  const result = column.clientSideEditValidationCheck?.(value2, "change");
174
- setEditState({ value: value2 });
185
+ setEditState({ editing: true, value: value2 });
175
186
  onEdit?.(
176
187
  {
177
188
  editType: "change",
@@ -182,11 +193,11 @@ const useEditableText = ({
182
193
  "change"
183
194
  );
184
195
  if (result?.ok === false) {
185
- setEditState({ value: value2, message: result.messages?.join(",") });
186
- }
187
- if (!isEditingRef.current) {
188
- isEditingRef.current = true;
189
- vuuUtils.dispatchCustomEvent(evt.target, "vuu-enter-edit-mode");
196
+ setEditState({
197
+ editing: true,
198
+ value: value2,
199
+ message: result.messages?.join(",")
200
+ });
190
201
  }
191
202
  },
192
203
  [column, onEdit]
@@ -196,13 +207,14 @@ const useEditableText = ({
196
207
  * has the value been edited during this edit session
197
208
  */
198
209
  edited: editState.previousValue !== void 0 && editState.previousValue !== editState.value,
199
- //TODO why are we detecting commit here, why not use VuuInput ?
210
+ editing: editState.editing,
200
211
  inputProps: {
201
212
  onBlur: handleBlur,
202
213
  onFocus: handleFocus,
203
214
  onKeyDown: handleKeyDown
204
215
  },
205
216
  onChange: handleChange,
217
+ previousValue: editState.previousValue,
206
218
  value: editState.value,
207
219
  warningMessage: editState.message
208
220
  };
@@ -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 if (response.errorMessage === \"CHANGE_REVERTED\") {\n setEditState(({ value }) => ({\n editing: true,\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 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 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({ message: void 0, value: stringValueOf(value) });
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,12 +50,14 @@ 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
58
  if (response.errorMessage === "CHANGE_REVERTED") {
55
59
  setEditState(({ value: value3 }) => ({
60
+ editing: true,
56
61
  previousValue: void 0,
57
62
  value: value3
58
63
  }));
@@ -77,6 +82,15 @@ const useEditableText = ({
77
82
  ...state,
78
83
  message: message2
79
84
  }));
85
+ onEdit?.(
86
+ {
87
+ editType: "commit",
88
+ isValid: false,
89
+ previousValue,
90
+ value: value2
91
+ },
92
+ "commit"
93
+ );
80
94
  } else {
81
95
  setEditState((state) => ({
82
96
  ...state,
@@ -88,38 +102,15 @@ const useEditableText = ({
88
102
  }
89
103
  return false;
90
104
  }, [column, editState, onEdit, type]);
91
- const handleKeyDown = useCallback(
92
- async (evt) => {
93
- const { key, target } = evt;
94
- const input = target;
95
- if (key === "Enter") {
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) {
105
+ const toggleActivation = useCallback(
106
+ async (input, cancel = false) => {
107
+ if (editState.editing) {
108
+ if (isDirtyRef.current) {
109
+ if (cancel) {
120
110
  const { value: previousValue } = editState;
121
111
  isDirtyRef.current = false;
122
112
  setEditState({
113
+ editing: false,
123
114
  value: initialValueRef.current,
124
115
  message: void 0
125
116
  });
@@ -132,44 +123,64 @@ const useEditableText = ({
132
123
  },
133
124
  "cancel"
134
125
  );
126
+ } else {
127
+ const commitSuccessful = await commit();
128
+ if (commitSuccessful) {
129
+ setEditState((editState2) => ({ ...editState2, editing: false }));
130
+ dispatchCustomEvent(input, "vuu-commit");
131
+ }
135
132
  }
136
- isEditingRef.current = false;
137
- dispatchCustomEvent(input, "vuu-exit-edit-mode");
133
+ } else {
134
+ setEditState((editState2) => ({ ...editState2, editing: false }));
138
135
  }
136
+ } else if (!cancel) {
137
+ setEditState((editState2) => ({ ...editState2, editing: true }));
138
+ input.select();
139
139
  }
140
140
  },
141
141
  [commit, editState, onEdit]
142
142
  );
143
- const beginEditHandler = useCallback((evt) => {
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(
143
+ const handleKeyDown = useCallback(
154
144
  async (evt) => {
155
- evt.target.removeEventListener("vuu-begin-edit", beginEditHandler, true);
156
- if (isEditingRef.current) {
157
- if (isDirtyRef.current) {
158
- const commitSuccessful = await commit();
159
- console.log({ commitSuccessful });
145
+ const { key, target } = evt;
146
+ const input = target;
147
+ if (key === "Enter") {
148
+ toggleActivation(input);
149
+ } else if (key === "ArrowRight" || key === "ArrowLeft" || key === "ArrowUp" || key === "ArrowDown") {
150
+ if (editState.editing) {
151
+ evt.stopPropagation();
160
152
  }
161
- isEditingRef.current = false;
162
- dispatchCustomEvent(evt.target, "vuu-exit-edit-mode");
153
+ } else if (evt.key === "Escape") {
154
+ toggleActivation(input, true);
155
+ }
156
+ },
157
+ [editState, toggleActivation]
158
+ );
159
+ const handleFocus = useCallback(
160
+ (e) => {
161
+ const input = e.target;
162
+ const source = e.relatedTarget;
163
+ if (source?.classList.contains("vuuTableCell") && source.contains(input)) {
164
+ toggleActivation(input);
163
165
  }
164
166
  },
165
- [beginEditHandler, commit]
167
+ [toggleActivation]
166
168
  );
169
+ const handleBlur = useCallback(async () => {
170
+ if (editState.editing) {
171
+ if (isDirtyRef.current) {
172
+ const commitSuccessful = await commit();
173
+ console.log({ commitSuccessful });
174
+ }
175
+ setEditState((editState2) => ({ ...editState2, editing: false }));
176
+ }
177
+ }, [commit, editState]);
167
178
  const handleChange = useCallback(
168
179
  (evt) => {
169
180
  const { value: value2 } = evt.target;
170
181
  isDirtyRef.current = value2 !== initialValueRef.current;
171
182
  const result = column.clientSideEditValidationCheck?.(value2, "change");
172
- setEditState({ value: value2 });
183
+ setEditState({ editing: true, value: value2 });
173
184
  onEdit?.(
174
185
  {
175
186
  editType: "change",
@@ -180,11 +191,11 @@ const useEditableText = ({
180
191
  "change"
181
192
  );
182
193
  if (result?.ok === false) {
183
- setEditState({ value: value2, message: result.messages?.join(",") });
184
- }
185
- if (!isEditingRef.current) {
186
- isEditingRef.current = true;
187
- dispatchCustomEvent(evt.target, "vuu-enter-edit-mode");
194
+ setEditState({
195
+ editing: true,
196
+ value: value2,
197
+ message: result.messages?.join(",")
198
+ });
188
199
  }
189
200
  },
190
201
  [column, onEdit]
@@ -194,13 +205,14 @@ const useEditableText = ({
194
205
  * has the value been edited during this edit session
195
206
  */
196
207
  edited: editState.previousValue !== void 0 && editState.previousValue !== editState.value,
197
- //TODO why are we detecting commit here, why not use VuuInput ?
208
+ editing: editState.editing,
198
209
  inputProps: {
199
210
  onBlur: handleBlur,
200
211
  onFocus: handleFocus,
201
212
  onKeyDown: handleKeyDown
202
213
  },
203
214
  onChange: handleChange,
215
+ previousValue: editState.previousValue,
204
216
  value: editState.value,
205
217
  warningMessage: editState.message
206
218
  };
@@ -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":";;;AAyCA,MAAM,aAAgB,GAAA,CAAC,KAA+B,KAAA,KAAA,EAAO,UAAc,IAAA,EAAA;AAEpE,MAAM,kBAAkB,CAA+C;AAAA,EAC5E,MAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAO,GAAA;AACT,CAAgC,KAAA;AAC9B,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,QAAoB,CAAA;AAAA,IACpD,KAAA,EAAO,cAAc,KAAK;AAAA,GAC3B,CAAA;AACD,EAAA,MAAM,eAAkB,GAAA,MAAA,CAAe,KAAO,EAAA,QAAA,MAAc,EAAE,CAAA;AAC9D,EAAM,MAAA,UAAA,GAAa,OAAO,KAAK,CAAA;AAC/B,EAAM,MAAA,YAAA,GAAe,OAAO,KAAK,CAAA;AAEjC,EAAA,OAAA,CAAQ,MAAM;AACZ,IAAA,IAAI,eAAgB,CAAA,OAAA,KAAY,KAAO,EAAA,QAAA,EAAY,EAAA;AACjD,MAAgB,eAAA,CAAA,OAAA,GAAU,cAAc,KAAK,CAAA;AAC7C,MAAA,YAAA,CAAa,EAAE,OAAS,EAAA,KAAA,CAAA,EAAW,OAAO,aAAc,CAAA,KAAK,GAAG,CAAA;AAAA;AAClE,GACF,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAM,MAAA,MAAA,GAAS,YAAY,YAAY;AACrC,IAAM,MAAA,EAAE,KAAAA,EAAAA,MAAAA,EAAU,GAAA,SAAA;AAClB,IAAA,MAAM,MAAS,GAAA,MAAA,CAAO,6BAAgCA,GAAAA,MAAAA,EAAO,GAAG,CAAA;AAChE,IAAI,IAAA,MAAA,EAAQ,OAAO,KAAO,EAAA;AACxB,MAAA,YAAA,CAAa,CAAC,KAAW,MAAA;AAAA,QACvB,GAAG,KAAA;AAAA,QACH,OAAS,EAAA,MAAA,EAAQ,QAAU,EAAA,IAAA,CAAK,GAAG;AAAA,OACnC,CAAA,CAAA;AACF,MAAO,OAAA,KAAA;AAAA,KACF,MAAA;AAEL,MAAM,MAAA,EAAE,OAAS,EAAA,YAAA,EAAiB,GAAA,eAAA;AAClC,MAAI,IAAA;AACF,QAAA,MAAM,UAAa,GAAA,aAAA,CAAcA,MAAO,EAAA,IAAA,EAAM,IAAI,CAAA;AAClD,QAAQ,OAAA,CAAA,GAAA,CAAI,CAAkC,+BAAA,EAAA,UAAU,CAAE,CAAA,CAAA;AAC1D,QAAM,MAAA,aAAA,GAAgB,aAAc,CAAA,YAAA,EAAc,IAAI,CAAA;AACtD,QAAA,MAAM,WAAW,MAAM,MAAA;AAAA,UACrB;AAAA,YACE,QAAU,EAAA,QAAA;AAAA,YACV,OAAS,EAAA,IAAA;AAAA,YACT,aAAA;AAAA,YACA,KAAO,EAAA;AAAA,WACT;AAAA,UACA;AAAA,SACF;AACA,QAAI,IAAA,YAAA,CAAa,QAAQ,CAAG,EAAA;AAC1B,UAAA,UAAA,CAAW,OAAU,GAAA,KAAA;AACrB,UAAA,YAAA,CAAa,CAAC,EAAE,aAAA,EAAAC,cAAe,EAAA,KAAA,EAAAD,QAAa,MAAA;AAAA,YAC1C,eACEC,cAAkBD,KAAAA,MAAAA,GACd,KACAC,CAAAA,GAAAA,cAAAA,KAAkB,SAChB,YACAA,GAAAA,cAAAA;AAAA,YACR,KAAAD,EAAAA;AAAA,WACA,CAAA,CAAA;AAAA,SACJ,MAAA,IAAW,UAAW,CAAA,QAAQ,CAAG,EAAA;AAC/B,UAAI,IAAA,QAAA,CAAS,iBAAiB,iBAAmB,EAAA;AAC/C,YAAA,YAAA,CAAa,CAAC,EAAE,KAAAA,EAAAA,MAAAA,EAAa,MAAA;AAAA,cAC3B,aAAe,EAAA,KAAA,CAAA;AAAA,cACf,KAAAA,EAAAA;AAAA,aACA,CAAA,CAAA;AACF,YAAA,eAAA,CAAgB,OAAUA,GAAAA,MAAAA;AAC1B,YAAO,OAAA,IAAA;AAAA,WACF,MAAA;AACL,YAAA,YAAA,CAAa,CAAC,KAAW,MAAA;AAAA,cACvB,GAAG,KAAA;AAAA,cACH,SAAS,QAAS,CAAA;AAAA,aAClB,CAAA,CAAA;AAAA;AACJ;AAEF,QAAA,eAAA,CAAgB,OAAUA,GAAAA,MAAAA;AAC1B,QAAO,OAAA,IAAA;AAAA,eACA,CAAG,EAAA;AACV,QAAA,IAAI,aAAa,mBAAqB,EAAA;AACpC,UAAA,MAAM,EAAE,UAAA,EAAY,YAAc,EAAA,OAAA,EAAY,GAAA,CAAA;AAC9C,UAAA,IAAI,MAAQ,EAAA;AACV,YAAA,MAAM,EAAE,IAAA,EAAM,KAAQ,GAAA,IAAA,EAAS,GAAA,MAAA;AAC/B,YAAA,MAAME,WAAU,CAAG,EAAA,KAAK,CAAS,MAAA,EAAA,YAAY,2BAA2B,UAAU,CAAA,CAAA,CAAA;AAClF,YAAA,YAAA,CAAa,CAAC,KAAW,MAAA;AAAA,cACvB,GAAG,KAAA;AAAA,cACH,OAAAA,EAAAA;AAAA,aACA,CAAA,CAAA;AAAA,WACG,MAAA;AACL,YAAA,YAAA,CAAa,CAAC,KAAW,MAAA;AAAA,cACvB,GAAG,KAAA;AAAA,cACH;AAAA,aACA,CAAA,CAAA;AAAA;AACJ;AACF;AACF;AAEF,IAAO,OAAA,KAAA;AAAA,KACN,CAAC,MAAA,EAAQ,SAAW,EAAA,MAAA,EAAQ,IAAI,CAAC,CAAA;AAEpC,EAAA,MAAM,aAAgB,GAAA,WAAA;AAAA,IACpB,OAAO,GAAoC,KAAA;AACzC,MAAM,MAAA,EAAE,GAAK,EAAA,MAAA,EAAW,GAAA,GAAA;AACxB,MAAA,MAAM,KAAQ,GAAA,MAAA;AACd,MAAA,IAAI,QAAQ,OAAS,EAAA;AACnB,QAAA,IAAI,aAAa,OAAS,EAAA;AACxB,UAAA,IAAI,WAAW,OAAS,EAAA;AACtB,YAAM,MAAA,gBAAA,GAAmB,MAAM,MAAO,EAAA;AACtC,YAAA,IAAI,gBAAkB,EAAA;AACpB,cAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,cAAA,mBAAA,CAAoB,OAAO,oBAAoB,CAAA;AAC/C,cAAA,mBAAA,CAAoB,OAAO,YAAY,CAAA;AAAA;AACzC,WACK,MAAA;AACL,YAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,YAAA,mBAAA,CAAoB,OAAO,oBAAoB,CAAA;AAAA;AACjD,SACK,MAAA;AACL,UAAA,YAAA,CAAa,OAAU,GAAA,IAAA;AACvB,UAAA,mBAAA,CAAoB,OAAO,qBAAqB,CAAA;AAChD,UAAA,KAAA,CAAM,MAAO,EAAA;AAAA;AACf,OACF,MAAA,IACE,QAAQ,YACR,IAAA,GAAA,KAAQ,eACR,GAAQ,KAAA,SAAA,IACR,QAAQ,WACR,EAAA;AACA,QAAA,IAAI,aAAa,OAAS,EAAA;AACxB,UAAA,GAAA,CAAI,eAAgB,EAAA;AAAA;AAMtB,OACF,MAAA,IAAW,GAAI,CAAA,GAAA,KAAQ,QAAU,EAAA;AAC/B,QAAA,IAAI,aAAa,OAAS,EAAA;AACxB,UAAA,IAAI,WAAW,OAAS,EAAA;AACtB,YAAM,MAAA,EAAE,KAAO,EAAA,aAAA,EAAkB,GAAA,SAAA;AACjC,YAAA,UAAA,CAAW,OAAU,GAAA,KAAA;AACrB,YAAa,YAAA,CAAA;AAAA,cACX,OAAO,eAAgB,CAAA,OAAA;AAAA,cACvB,OAAS,EAAA,KAAA;AAAA,aACV,CAAA;AAED,YAAA,MAAA;AAAA,cACE;AAAA,gBACE,QAAU,EAAA,QAAA;AAAA,gBACV,OAAS,EAAA,IAAA;AAAA,gBACT,aAAA;AAAA,gBACA,OAAO,eAAgB,CAAA;AAAA,eACzB;AAAA,cACA;AAAA,aACF;AAAA;AAEF,UAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,UAAA,mBAAA,CAAoB,OAAO,oBAAoB,CAAA;AAAA;AACjD;AACF,KACF;AAAA,IACA,CAAC,MAAQ,EAAA,SAAA,EAAW,MAAM;AAAA,GAC5B;AAEA,EAAM,MAAA,gBAAA,GAAmB,WAAY,CAAA,CAAC,GAAe,KAAA;AACnD,IAAA,YAAA,CAAa,OAAU,GAAA,IAAA;AACvB,IAAoB,mBAAA,CAAA,GAAA,CAAI,QAAuB,qBAAqB,CAAA;AAAA,GACtE,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAc,GAAA,WAAA;AAAA,IAClB,CAAC,CAAM,KAAA;AACL,MAAA,CAAA,CAAE,MAAO,CAAA,gBAAA,CAAiB,gBAAkB,EAAA,gBAAA,EAAkB,IAAI,CAAA;AAAA,KACpE;AAAA,IACA,CAAC,gBAAgB;AAAA,GACnB;AAEA,EAAA,MAAM,UAAa,GAAA,WAAA;AAAA,IACjB,OAAO,GAAQ,KAAA;AACb,MAAA,GAAA,CAAI,MAAO,CAAA,mBAAA,CAAoB,gBAAkB,EAAA,gBAAA,EAAkB,IAAI,CAAA;AACvE,MAAA,IAAI,aAAa,OAAS,EAAA;AACxB,QAAA,IAAI,WAAW,OAAS,EAAA;AACtB,UAAM,MAAA,gBAAA,GAAmB,MAAM,MAAO,EAAA;AACtC,UAAQ,OAAA,CAAA,GAAA,CAAI,EAAE,gBAAA,EAAkB,CAAA;AAAA;AAElC,QAAA,YAAA,CAAa,OAAU,GAAA,KAAA;AACvB,QAAoB,mBAAA,CAAA,GAAA,CAAI,QAAQ,oBAAoB,CAAA;AAAA;AACtD,KACF;AAAA,IACA,CAAC,kBAAkB,MAAM;AAAA,GAC3B;AAEA,EAAA,MAAM,YAAe,GAAA,WAAA;AAAA,IACnB,CAAC,GAAQ,KAAA;AACP,MAAA,MAAM,EAAE,KAAA,EAAAF,MAAM,EAAA,GAAI,GAAI,CAAA,MAAA;AACtB,MAAW,UAAA,CAAA,OAAA,GAAUA,WAAU,eAAgB,CAAA,OAAA;AAC/C,MAAA,MAAM,MAAS,GAAA,MAAA,CAAO,6BAAgCA,GAAAA,MAAAA,EAAO,QAAQ,CAAA;AACrE,MAAa,YAAA,CAAA,EAAE,KAAAA,EAAAA,MAAAA,EAAO,CAAA;AAEtB,MAAA,MAAA;AAAA,QACE;AAAA,UACE,QAAU,EAAA,QAAA;AAAA,UACV,OAAA,EAAS,QAAQ,EAAO,KAAA,KAAA;AAAA,UACxB,eAAe,eAAgB,CAAA,OAAA;AAAA,UAC/B,KAAAA,EAAAA;AAAA,SACF;AAAA,QACA;AAAA,OACF;AACA,MAAI,IAAA,MAAA,EAAQ,OAAO,KAAO,EAAA;AACxB,QAAa,YAAA,CAAA,EAAE,OAAAA,MAAO,EAAA,OAAA,EAAS,OAAO,QAAU,EAAA,IAAA,CAAK,GAAG,CAAA,EAAG,CAAA;AAAA;AAG7D,MAAI,IAAA,CAAC,aAAa,OAAS,EAAA;AACzB,QAAA,YAAA,CAAa,OAAU,GAAA,IAAA;AACvB,QAAoB,mBAAA,CAAA,GAAA,CAAI,QAAuB,qBAAqB,CAAA;AAAA;AACtE,KACF;AAAA,IACA,CAAC,QAAQ,MAAM;AAAA,GACjB;AAEA,EAAO,OAAA;AAAA;AAAA;AAAA;AAAA,IAIL,QACE,SAAU,CAAA,aAAA,KAAkB,KAC5B,CAAA,IAAA,SAAA,CAAU,kBAAkB,SAAU,CAAA,KAAA;AAAA;AAAA,IAExC,UAAY,EAAA;AAAA,MACV,MAAQ,EAAA,UAAA;AAAA,MACR,OAAS,EAAA,WAAA;AAAA,MACT,SAAW,EAAA;AAAA,KACb;AAAA,IACA,QAAU,EAAA,YAAA;AAAA,IACV,OAAO,SAAU,CAAA,KAAA;AAAA,IACjB,gBAAgB,SAAU,CAAA;AAAA,GAC5B;AACF;;;;"}
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 if (response.errorMessage === \"CHANGE_REVERTED\") {\n setEditState(({ value }) => ({\n editing: true,\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 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 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.8",
2
+ "version": "2.1.9",
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",
8
- "@vuu-ui/vuu-protocol-types": "2.1.8",
9
- "@vuu-ui/vuu-table-types": "2.1.8"
7
+ "@vuu-ui/vuu-data-types": "2.1.9",
8
+ "@vuu-ui/vuu-protocol-types": "2.1.9",
9
+ "@vuu-ui/vuu-table-types": "2.1.9"
10
10
  },
11
11
  "dependencies": {
12
- "@vuu-ui/vuu-context-menu": "2.1.8",
13
- "@vuu-ui/vuu-data-react": "2.1.8",
14
- "@vuu-ui/vuu-layout": "2.1.8",
15
- "@vuu-ui/vuu-popups": "2.1.8",
16
- "@vuu-ui/vuu-table": "2.1.8",
17
- "@vuu-ui/vuu-utils": "2.1.8",
12
+ "@vuu-ui/vuu-context-menu": "2.1.9",
13
+ "@vuu-ui/vuu-data-react": "2.1.9",
14
+ "@vuu-ui/vuu-layout": "2.1.9",
15
+ "@vuu-ui/vuu-popups": "2.1.9",
16
+ "@vuu-ui/vuu-table": "2.1.9",
17
+ "@vuu-ui/vuu-utils": "2.1.9",
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
  };