@vuu-ui/vuu-ui-controls 2.1.0-alpha.12 → 2.1.0-alpha.14

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.
@@ -24,6 +24,7 @@ const useEditableText = ({
24
24
  }, [value]);
25
25
  const commit = React.useCallback(async () => {
26
26
  const { value: value2 } = editState;
27
+ console.log(`commit ${JSON.stringify(editState)}`);
27
28
  const result = clientSideEditValidationCheck?.(value2, "*");
28
29
  if (result?.ok === false) {
29
30
  setEditState((state) => ({
@@ -32,21 +33,40 @@ const useEditableText = ({
32
33
  }));
33
34
  return false;
34
35
  } else {
35
- setEditState((state) => ({ ...state, message: void 0 }));
36
+ const { current: initialValue } = initialValueRef;
36
37
  const typedValue = vuuUtils.getTypedValue(value2, type, true);
38
+ const previousValue = vuuUtils.getTypedValue(initialValue, type);
37
39
  const response = await onEdit?.(
38
- { editType: "commit", value: typedValue, isValid: true },
40
+ {
41
+ editType: "commit",
42
+ isValid: true,
43
+ previousValue,
44
+ value: typedValue
45
+ },
39
46
  "commit"
40
47
  );
41
48
  if (vuuUtils.isRpcSuccess(response)) {
42
49
  isDirtyRef.current = false;
50
+ setEditState(({ previousValue: previousValue2, value: value3 }) => ({
51
+ previousValue: previousValue2 === value3 ? void 0 : previousValue2 === void 0 ? initialValue : previousValue2,
52
+ value: value3
53
+ }));
43
54
  initialValueRef.current = value2;
44
55
  return true;
45
56
  } else if (vuuUtils.isRpcError(response)) {
46
- setEditState((state) => ({
47
- ...state,
48
- message: response.errorMessage
49
- }));
57
+ if (response.errorMessage === "CHANGE_REVERTED") {
58
+ setEditState(({ value: value3 }) => ({
59
+ previousValue: void 0,
60
+ value: value3
61
+ }));
62
+ initialValueRef.current = value2;
63
+ return true;
64
+ } else {
65
+ setEditState((state) => ({
66
+ ...state,
67
+ message: response.errorMessage
68
+ }));
69
+ }
50
70
  }
51
71
  }
52
72
  return false;
@@ -154,6 +174,10 @@ const useEditableText = ({
154
174
  [clientSideEditValidationCheck, onEdit, type]
155
175
  );
156
176
  return {
177
+ /**
178
+ * has the value been edited during this edit session
179
+ */
180
+ edited: editState.previousValue !== void 0 && editState.previousValue !== editState.value,
157
181
  //TODO why are we detecting commit here, why not use VuuInput ?
158
182
  inputProps: {
159
183
  onBlur: handleBlur,
@@ -1 +1 @@
1
- {"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import type { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type { TableCellEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport {\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 clientSideEditValidationCheck?: DataValueValidationChecker;\n value?: T;\n onEdit?: TableCellEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n message?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n clientSideEditValidationCheck,\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: \"\", value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n const result = clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n return false;\n } else {\n setEditState((state) => ({ ...state, message: undefined }));\n const typedValue = getTypedValue(value, type, true);\n const response = await onEdit?.(\n { editType: \"commit\", value: typedValue, isValid: true },\n \"commit\",\n );\n if (isRpcSuccess(response)) {\n isDirtyRef.current = false;\n initialValueRef.current = value;\n return true;\n } else if (isRpcError(response)) {\n setEditState((state) => ({\n ...state,\n message: response.errorMessage,\n }));\n }\n }\n return false;\n }, [clientSideEditValidationCheck, editState, onEdit, type]);\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n // console.log(`[useEditableText] handleKeyDown`);\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n // console.log(\n // `[useEditableText] ENTER isEditing ? ${isEditingRef.current}, isDirty ${isDirtyRef.current}`,\n // );\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n // console.log(\" ...await commit\");\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 // console.log(\n // `[useEditableText] handleKeydown, arrowkey whilst editing, stop propagation`,\n // );\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 // console.log(\n // `[useEditableText] ESC whilst editing, dirty ? ${isDirtyRef.current}`,\n // );\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 } /* else if (isEditingRef.current === false && isCharacterKey(key)) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }*/\n },\n [commit, editState, onEdit],\n );\n\n const beginEditHandler = useCallback((evt: Event) => {\n // console.log(\"begin edit handler\");\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 const typedValue = getTypedValue(value, type, true);\n // console.log(\n // `[useEditableText] handleChange '${value}' typedValue ${typedValue}\n // initial value ${initialValueRef.current}\n // `,\n // );\n isDirtyRef.current = value !== initialValueRef.current;\n const result = clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n previousValue: initialValueRef.current,\n value: typedValue,\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 [clientSideEditValidationCheck, onEdit, type],\n );\n\n return {\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","isRpcError","dispatchCustomEvent"],"mappings":"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"}
1
+ {"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import type { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type { TableCellEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport {\n dispatchCustomEvent,\n getTypedValue,\n isRpcError,\n isRpcSuccess,\n useEditTracker,\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 clientSideEditValidationCheck?: DataValueValidationChecker;\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 clientSideEditValidationCheck,\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: \"\", value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n console.log(`commit ${JSON.stringify(editState)}`);\n const result = 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 typedValue = getTypedValue(value, type, true);\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 initialValueRef.current = value;\n return true;\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 }\n return false;\n }, [clientSideEditValidationCheck, editState, onEdit, type]);\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n // console.log(`[useEditableText] handleKeyDown`);\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n // console.log(\n // `[useEditableText] ENTER isEditing ? ${isEditingRef.current}, isDirty ${isDirtyRef.current}`,\n // );\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n // console.log(\" ...await commit\");\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 // console.log(\n // `[useEditableText] handleKeydown, arrowkey whilst editing, stop propagation`,\n // );\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 // console.log(\n // `[useEditableText] ESC whilst editing, dirty ? ${isDirtyRef.current}`,\n // );\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 } /* else if (isEditingRef.current === false && isCharacterKey(key)) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }*/\n },\n [commit, editState, onEdit],\n );\n\n const beginEditHandler = useCallback((evt: Event) => {\n // console.log(\"begin edit handler\");\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 const typedValue = getTypedValue(value, type, true);\n // console.log(\n // `[useEditableText] handleChange '${value}' typedValue ${typedValue}\n // initial value ${initialValueRef.current}\n // `,\n // );\n isDirtyRef.current = value !== initialValueRef.current;\n const result = clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n previousValue: initialValueRef.current,\n value: typedValue,\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 [clientSideEditValidationCheck, onEdit, type],\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","dispatchCustomEvent"],"mappings":"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"}
@@ -22,6 +22,7 @@ const useEditableText = ({
22
22
  }, [value]);
23
23
  const commit = useCallback(async () => {
24
24
  const { value: value2 } = editState;
25
+ console.log(`commit ${JSON.stringify(editState)}`);
25
26
  const result = clientSideEditValidationCheck?.(value2, "*");
26
27
  if (result?.ok === false) {
27
28
  setEditState((state) => ({
@@ -30,21 +31,40 @@ const useEditableText = ({
30
31
  }));
31
32
  return false;
32
33
  } else {
33
- setEditState((state) => ({ ...state, message: void 0 }));
34
+ const { current: initialValue } = initialValueRef;
34
35
  const typedValue = getTypedValue(value2, type, true);
36
+ const previousValue = getTypedValue(initialValue, type);
35
37
  const response = await onEdit?.(
36
- { editType: "commit", value: typedValue, isValid: true },
38
+ {
39
+ editType: "commit",
40
+ isValid: true,
41
+ previousValue,
42
+ value: typedValue
43
+ },
37
44
  "commit"
38
45
  );
39
46
  if (isRpcSuccess(response)) {
40
47
  isDirtyRef.current = false;
48
+ setEditState(({ previousValue: previousValue2, value: value3 }) => ({
49
+ previousValue: previousValue2 === value3 ? void 0 : previousValue2 === void 0 ? initialValue : previousValue2,
50
+ value: value3
51
+ }));
41
52
  initialValueRef.current = value2;
42
53
  return true;
43
54
  } else if (isRpcError(response)) {
44
- setEditState((state) => ({
45
- ...state,
46
- message: response.errorMessage
47
- }));
55
+ if (response.errorMessage === "CHANGE_REVERTED") {
56
+ setEditState(({ value: value3 }) => ({
57
+ previousValue: void 0,
58
+ value: value3
59
+ }));
60
+ initialValueRef.current = value2;
61
+ return true;
62
+ } else {
63
+ setEditState((state) => ({
64
+ ...state,
65
+ message: response.errorMessage
66
+ }));
67
+ }
48
68
  }
49
69
  }
50
70
  return false;
@@ -152,6 +172,10 @@ const useEditableText = ({
152
172
  [clientSideEditValidationCheck, onEdit, type]
153
173
  );
154
174
  return {
175
+ /**
176
+ * has the value been edited during this edit session
177
+ */
178
+ edited: editState.previousValue !== void 0 && editState.previousValue !== editState.value,
155
179
  //TODO why are we detecting commit here, why not use VuuInput ?
156
180
  inputProps: {
157
181
  onBlur: handleBlur,
@@ -1 +1 @@
1
- {"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import type { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type { TableCellEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport {\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 clientSideEditValidationCheck?: DataValueValidationChecker;\n value?: T;\n onEdit?: TableCellEditHandler;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\ntype EditState = {\n message?: string;\n value: string;\n};\n\nconst stringValueOf = (value?: VuuRowDataItemType) => value?.toString() ?? \"\";\n\nexport const useEditableText = <T extends string | number | boolean = string>({\n clientSideEditValidationCheck,\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: \"\", value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n const result = clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n return false;\n } else {\n setEditState((state) => ({ ...state, message: undefined }));\n const typedValue = getTypedValue(value, type, true);\n const response = await onEdit?.(\n { editType: \"commit\", value: typedValue, isValid: true },\n \"commit\",\n );\n if (isRpcSuccess(response)) {\n isDirtyRef.current = false;\n initialValueRef.current = value;\n return true;\n } else if (isRpcError(response)) {\n setEditState((state) => ({\n ...state,\n message: response.errorMessage,\n }));\n }\n }\n return false;\n }, [clientSideEditValidationCheck, editState, onEdit, type]);\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n // console.log(`[useEditableText] handleKeyDown`);\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n // console.log(\n // `[useEditableText] ENTER isEditing ? ${isEditingRef.current}, isDirty ${isDirtyRef.current}`,\n // );\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n // console.log(\" ...await commit\");\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 // console.log(\n // `[useEditableText] handleKeydown, arrowkey whilst editing, stop propagation`,\n // );\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 // console.log(\n // `[useEditableText] ESC whilst editing, dirty ? ${isDirtyRef.current}`,\n // );\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 } /* else if (isEditingRef.current === false && isCharacterKey(key)) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }*/\n },\n [commit, editState, onEdit],\n );\n\n const beginEditHandler = useCallback((evt: Event) => {\n // console.log(\"begin edit handler\");\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 const typedValue = getTypedValue(value, type, true);\n // console.log(\n // `[useEditableText] handleChange '${value}' typedValue ${typedValue}\n // initial value ${initialValueRef.current}\n // `,\n // );\n isDirtyRef.current = value !== initialValueRef.current;\n const result = clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n previousValue: initialValueRef.current,\n value: typedValue,\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 [clientSideEditValidationCheck, onEdit, type],\n );\n\n return {\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"],"mappings":"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"}
1
+ {"version":3,"file":"useEditableText.js","sources":["../../../../packages/vuu-ui-controls/src/editable/useEditableText.ts"],"sourcesContent":["import type { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport type { TableCellEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport {\n dispatchCustomEvent,\n getTypedValue,\n isRpcError,\n isRpcSuccess,\n useEditTracker,\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 clientSideEditValidationCheck?: DataValueValidationChecker;\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 clientSideEditValidationCheck,\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: \"\", value: stringValueOf(value) });\n }\n }, [value]);\n\n const commit = useCallback(async () => {\n const { value } = editState;\n console.log(`commit ${JSON.stringify(editState)}`);\n const result = 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 typedValue = getTypedValue(value, type, true);\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 initialValueRef.current = value;\n return true;\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 }\n return false;\n }, [clientSideEditValidationCheck, editState, onEdit, type]);\n\n const handleKeyDown = useCallback(\n async (evt: KeyboardEvent<HTMLElement>) => {\n const { key, target } = evt;\n // console.log(`[useEditableText] handleKeyDown`);\n const input = target as HTMLInputElement;\n if (key === \"Enter\") {\n // console.log(\n // `[useEditableText] ENTER isEditing ? ${isEditingRef.current}, isDirty ${isDirtyRef.current}`,\n // );\n if (isEditingRef.current) {\n if (isDirtyRef.current) {\n // console.log(\" ...await commit\");\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 // console.log(\n // `[useEditableText] handleKeydown, arrowkey whilst editing, stop propagation`,\n // );\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 // console.log(\n // `[useEditableText] ESC whilst editing, dirty ? ${isDirtyRef.current}`,\n // );\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 } /* else if (isEditingRef.current === false && isCharacterKey(key)) {\n isEditingRef.current = true;\n dispatchCustomEvent(evt.target as HTMLElement, \"vuu-enter-edit-mode\");\n }*/\n },\n [commit, editState, onEdit],\n );\n\n const beginEditHandler = useCallback((evt: Event) => {\n // console.log(\"begin edit handler\");\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 const typedValue = getTypedValue(value, type, true);\n // console.log(\n // `[useEditableText] handleChange '${value}' typedValue ${typedValue}\n // initial value ${initialValueRef.current}\n // `,\n // );\n isDirtyRef.current = value !== initialValueRef.current;\n const result = clientSideEditValidationCheck?.(value, \"change\");\n setEditState({ value });\n\n onEdit?.(\n {\n editType: \"change\",\n isValid: result?.ok !== false,\n previousValue: initialValueRef.current,\n value: typedValue,\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 [clientSideEditValidationCheck, onEdit, type],\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"],"mappings":"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"}
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
- "version": "2.1.0-alpha.12",
2
+ "version": "2.1.0-alpha.14",
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.0-alpha.12",
8
- "@vuu-ui/vuu-protocol-types": "2.1.0-alpha.12",
9
- "@vuu-ui/vuu-table-types": "2.1.0-alpha.12"
7
+ "@vuu-ui/vuu-data-types": "2.1.0-alpha.14",
8
+ "@vuu-ui/vuu-protocol-types": "2.1.0-alpha.14",
9
+ "@vuu-ui/vuu-table-types": "2.1.0-alpha.14"
10
10
  },
11
11
  "dependencies": {
12
- "@vuu-ui/vuu-context-menu": "2.1.0-alpha.12",
13
- "@vuu-ui/vuu-data-react": "2.1.0-alpha.12",
14
- "@vuu-ui/vuu-layout": "2.1.0-alpha.12",
15
- "@vuu-ui/vuu-popups": "2.1.0-alpha.12",
16
- "@vuu-ui/vuu-table": "2.1.0-alpha.12",
17
- "@vuu-ui/vuu-utils": "2.1.0-alpha.12",
12
+ "@vuu-ui/vuu-context-menu": "2.1.0-alpha.14",
13
+ "@vuu-ui/vuu-data-react": "2.1.0-alpha.14",
14
+ "@vuu-ui/vuu-layout": "2.1.0-alpha.14",
15
+ "@vuu-ui/vuu-popups": "2.1.0-alpha.14",
16
+ "@vuu-ui/vuu-table": "2.1.0-alpha.14",
17
+ "@vuu-ui/vuu-utils": "2.1.0-alpha.14",
18
18
  "@salt-ds/core": "1.54.1",
19
19
  "@salt-ds/icons": "1.16.0",
20
20
  "@salt-ds/styles": "0.2.1",
@@ -9,6 +9,10 @@ export interface EditableTextHookProps<T extends VuuRowDataItemType = VuuRowData
9
9
  type?: "string" | "number" | "boolean";
10
10
  }
11
11
  export declare const useEditableText: <T extends string | number | boolean = string>({ clientSideEditValidationCheck, value, onEdit, type, }: EditableTextHookProps<T>) => {
12
+ /**
13
+ * has the value been edited during this edit session
14
+ */
15
+ edited: boolean;
12
16
  inputProps: {
13
17
  onBlur: FocusEventHandler<HTMLElement>;
14
18
  onFocus: FocusEventHandler<HTMLElement>;