@vuu-ui/vuu-ui-controls 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,14 +23,10 @@ const CycleStateButton = React.forwardRef(function CycleStateButton2({
23
23
  ...buttonProps
24
24
  }, forwardedRef) {
25
25
  const handleClick = React.useCallback(
26
- (evt) => {
26
+ async (evt) => {
27
27
  const nextValue = getNextValue(value, values);
28
28
  onChange?.(nextValue);
29
- onCommit?.(evt, nextValue).then((response) => {
30
- if (response !== true) {
31
- console.error(response);
32
- }
33
- });
29
+ onCommit?.(evt, nextValue);
34
30
  },
35
31
  [onChange, onCommit, value, values]
36
32
  );
@@ -1 +1 @@
1
- {"version":3,"file":"CycleStateButton.js","sources":["../../src/cycle-state-button/CycleStateButton.tsx"],"sourcesContent":["import { Button, ButtonProps } from \"@salt-ds/core\";\nimport cx from \"clsx\";\nimport type { CommitResponse } from \"@vuu-ui/vuu-table-types\";\nimport type {\n VuuColumnDataType,\n VuuRowDataItemType,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport { ForwardedRef, forwardRef, SyntheticEvent, useCallback } from \"react\";\n\nconst classBase = \"vuuCycleStateButton\";\n\nexport type CycleStateCommitHandler = (\n evt: SyntheticEvent,\n value: VuuRowDataItemType,\n) => CommitResponse;\n\nexport interface CycleStateButtonProps extends Omit<ButtonProps, \"onChange\"> {\n onChange?: (value: VuuRowDataItemType) => void;\n onCommit?: CycleStateCommitHandler;\n values: string[];\n value: string;\n}\n\nconst getNextValue = (value: string, valueList: string[]) => {\n const index = valueList\n .map((v) => v.toUpperCase())\n .indexOf(value.toUpperCase());\n if (index === valueList.length - 1) {\n return valueList[0];\n } else {\n return valueList[index + 1];\n }\n};\n\nexport const CycleStateButton = forwardRef(function CycleStateButton(\n {\n className,\n onChange,\n onCommit,\n value = \"\",\n values,\n ...buttonProps\n }: CycleStateButtonProps,\n forwardedRef: ForwardedRef<HTMLButtonElement>,\n) {\n const handleClick = useCallback(\n (evt: SyntheticEvent<HTMLButtonElement>) => {\n const nextValue = getNextValue(value, values);\n onChange?.(nextValue);\n onCommit?.(evt, nextValue as VuuColumnDataType).then((response) => {\n if (response !== true) {\n console.error(response);\n }\n });\n },\n [onChange, onCommit, value, values],\n );\n\n return (\n <Button\n {...buttonProps}\n className={cx(\n classBase,\n className,\n `${classBase}-${value.toLowerCase()}`,\n )}\n onClick={handleClick}\n ref={forwardedRef}\n >\n {value}\n </Button>\n );\n});\n"],"names":["forwardRef","CycleStateButton","useCallback","jsx","Button"],"mappings":";;;;;;;AASA,MAAM,SAAY,GAAA,qBAAA,CAAA;AAclB,MAAM,YAAA,GAAe,CAAC,KAAA,EAAe,SAAwB,KAAA;AAC3D,EAAA,MAAM,KAAQ,GAAA,SAAA,CACX,GAAI,CAAA,CAAC,CAAM,KAAA,CAAA,CAAE,WAAY,EAAC,CAC1B,CAAA,OAAA,CAAQ,KAAM,CAAA,WAAA,EAAa,CAAA,CAAA;AAC9B,EAAI,IAAA,KAAA,KAAU,SAAU,CAAA,MAAA,GAAS,CAAG,EAAA;AAClC,IAAA,OAAO,UAAU,CAAC,CAAA,CAAA;AAAA,GACb,MAAA;AACL,IAAO,OAAA,SAAA,CAAU,QAAQ,CAAC,CAAA,CAAA;AAAA,GAC5B;AACF,CAAA,CAAA;AAEa,MAAA,gBAAA,GAAmBA,gBAAW,CAAA,SAASC,iBAClD,CAAA;AAAA,EACE,SAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAQ,GAAA,EAAA;AAAA,EACR,MAAA;AAAA,EACA,GAAG,WAAA;AACL,CAAA,EACA,YACA,EAAA;AACA,EAAA,MAAM,WAAc,GAAAC,iBAAA;AAAA,IAClB,CAAC,GAA2C,KAAA;AAC1C,MAAM,MAAA,SAAA,GAAY,YAAa,CAAA,KAAA,EAAO,MAAM,CAAA,CAAA;AAC5C,MAAA,QAAA,GAAW,SAAS,CAAA,CAAA;AACpB,MAAA,QAAA,GAAW,GAAK,EAAA,SAA8B,CAAE,CAAA,IAAA,CAAK,CAAC,QAAa,KAAA;AACjE,QAAA,IAAI,aAAa,IAAM,EAAA;AACrB,UAAA,OAAA,CAAQ,MAAM,QAAQ,CAAA,CAAA;AAAA,SACxB;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,IACA,CAAC,QAAA,EAAU,QAAU,EAAA,KAAA,EAAO,MAAM,CAAA;AAAA,GACpC,CAAA;AAEA,EACE,uBAAAC,cAAA;AAAA,IAACC,WAAA;AAAA,IAAA;AAAA,MACE,GAAG,WAAA;AAAA,MACJ,SAAW,EAAA,EAAA;AAAA,QACT,SAAA;AAAA,QACA,SAAA;AAAA,QACA,CAAG,EAAA,SAAS,CAAI,CAAA,EAAA,KAAA,CAAM,aAAa,CAAA,CAAA;AAAA,OACrC;AAAA,MACA,OAAS,EAAA,WAAA;AAAA,MACT,GAAK,EAAA,YAAA;AAAA,MAEJ,QAAA,EAAA,KAAA;AAAA,KAAA;AAAA,GACH,CAAA;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"CycleStateButton.js","sources":["../../src/cycle-state-button/CycleStateButton.tsx"],"sourcesContent":["import { Button, ButtonProps } from \"@salt-ds/core\";\nimport cx from \"clsx\";\nimport type {\n VuuColumnDataType,\n VuuRowDataItemType,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport { ForwardedRef, forwardRef, SyntheticEvent, useCallback } from \"react\";\nimport { CommitHandler } from \"@vuu-ui/vuu-utils\";\n\nconst classBase = \"vuuCycleStateButton\";\n\nexport interface CycleStateButtonProps extends Omit<ButtonProps, \"onChange\"> {\n onChange?: (value: VuuRowDataItemType) => void;\n onCommit?: CommitHandler<HTMLButtonElement>;\n values: string[];\n value: string;\n}\n\nconst getNextValue = (value: string, valueList: string[]) => {\n const index = valueList\n .map((v) => v.toUpperCase())\n .indexOf(value.toUpperCase());\n if (index === valueList.length - 1) {\n return valueList[0];\n } else {\n return valueList[index + 1];\n }\n};\n\nexport const CycleStateButton = forwardRef(function CycleStateButton(\n {\n className,\n onChange,\n onCommit,\n value = \"\",\n values,\n ...buttonProps\n }: CycleStateButtonProps,\n forwardedRef: ForwardedRef<HTMLButtonElement>,\n) {\n const handleClick = useCallback(\n async (evt: SyntheticEvent<HTMLButtonElement>) => {\n const nextValue = getNextValue(value, values);\n onChange?.(nextValue);\n onCommit?.(evt, nextValue as VuuColumnDataType);\n },\n [onChange, onCommit, value, values],\n );\n\n return (\n <Button\n {...buttonProps}\n className={cx(\n classBase,\n className,\n `${classBase}-${value.toLowerCase()}`,\n )}\n onClick={handleClick}\n ref={forwardedRef}\n >\n {value}\n </Button>\n );\n});\n"],"names":["forwardRef","CycleStateButton","useCallback","jsx","Button"],"mappings":";;;;;;;AASA,MAAM,SAAY,GAAA,qBAAA,CAAA;AASlB,MAAM,YAAA,GAAe,CAAC,KAAA,EAAe,SAAwB,KAAA;AAC3D,EAAA,MAAM,KAAQ,GAAA,SAAA,CACX,GAAI,CAAA,CAAC,CAAM,KAAA,CAAA,CAAE,WAAY,EAAC,CAC1B,CAAA,OAAA,CAAQ,KAAM,CAAA,WAAA,EAAa,CAAA,CAAA;AAC9B,EAAI,IAAA,KAAA,KAAU,SAAU,CAAA,MAAA,GAAS,CAAG,EAAA;AAClC,IAAA,OAAO,UAAU,CAAC,CAAA,CAAA;AAAA,GACb,MAAA;AACL,IAAO,OAAA,SAAA,CAAU,QAAQ,CAAC,CAAA,CAAA;AAAA,GAC5B;AACF,CAAA,CAAA;AAEa,MAAA,gBAAA,GAAmBA,gBAAW,CAAA,SAASC,iBAClD,CAAA;AAAA,EACE,SAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAQ,GAAA,EAAA;AAAA,EACR,MAAA;AAAA,EACA,GAAG,WAAA;AACL,CAAA,EACA,YACA,EAAA;AACA,EAAA,MAAM,WAAc,GAAAC,iBAAA;AAAA,IAClB,OAAO,GAA2C,KAAA;AAChD,MAAM,MAAA,SAAA,GAAY,YAAa,CAAA,KAAA,EAAO,MAAM,CAAA,CAAA;AAC5C,MAAA,QAAA,GAAW,SAAS,CAAA,CAAA;AACpB,MAAA,QAAA,GAAW,KAAK,SAA8B,CAAA,CAAA;AAAA,KAChD;AAAA,IACA,CAAC,QAAA,EAAU,QAAU,EAAA,KAAA,EAAO,MAAM,CAAA;AAAA,GACpC,CAAA;AAEA,EACE,uBAAAC,cAAA;AAAA,IAACC,WAAA;AAAA,IAAA;AAAA,MACE,GAAG,WAAA;AAAA,MACJ,SAAW,EAAA,EAAA;AAAA,QACT,SAAA;AAAA,QACA,SAAA;AAAA,QACA,CAAG,EAAA,SAAS,CAAI,CAAA,EAAA,KAAA,CAAM,aAAa,CAAA,CAAA;AAAA,OACrC;AAAA,MACA,OAAS,EAAA,WAAA;AAAA,MACT,GAAK,EAAA,YAAA;AAAA,MAEJ,QAAA,EAAA,KAAA;AAAA,KAAA;AAAA,GACH,CAAA;AAEJ,CAAC;;;;"}
@@ -3,51 +3,54 @@
3
3
  var vuuUtils = require('@vuu-ui/vuu-utils');
4
4
  var React = require('react');
5
5
 
6
- const WarnCommit = () => {
7
- console.warn(
8
- "onCommit handler has not been provided to InputCell cell renderer"
9
- );
10
- return Promise.resolve(true);
11
- };
6
+ const stringValueOf = (value) => value?.toString() ?? "";
12
7
  const useEditableText = ({
13
8
  clientSideEditValidationCheck,
14
- initialValue,
15
- onCommit,
16
- type
9
+ value,
10
+ onEdit,
11
+ type = "string"
17
12
  }) => {
18
- const [message, setMessage] = React.useState();
19
- const [value, setValue] = React.useState(initialValue);
20
- const initialValueRef = React.useRef(initialValue);
13
+ const [editState, setEditState] = React.useState({
14
+ value: stringValueOf(value)
15
+ });
16
+ const initialValueRef = React.useRef(value?.toString() ?? "");
21
17
  const isDirtyRef = React.useRef(false);
22
- const hasCommittedRef = React.useRef(false);
23
- vuuUtils.useLayoutEffectSkipFirst(() => {
24
- setValue(initialValue);
25
- }, [initialValue]);
18
+ React.useMemo(() => {
19
+ if (initialValueRef.current !== value?.toString()) {
20
+ initialValueRef.current = stringValueOf(value);
21
+ setEditState({ message: "", value: stringValueOf(value) });
22
+ console.log("initial value changed to: ", value);
23
+ }
24
+ }, [value]);
26
25
  const commit = React.useCallback(
27
- (target) => {
26
+ async (target) => {
27
+ const { value: value2 } = editState;
28
28
  if (isDirtyRef.current) {
29
- hasCommittedRef.current = true;
30
- const result = clientSideEditValidationCheck?.(value);
29
+ const result = clientSideEditValidationCheck?.(value2, "*");
31
30
  if (result?.ok === false) {
32
- setMessage(result?.messages?.join(","));
31
+ setEditState((state) => ({
32
+ ...state,
33
+ message: result?.messages?.join(",")
34
+ }));
33
35
  } else {
34
- setMessage(void 0);
35
- console.log(`commit value ${value}`);
36
- onCommit(value).then((response) => {
37
- if (response === true) {
38
- isDirtyRef.current = false;
39
- vuuUtils.dispatchCustomEvent(target, "vuu-commit");
40
- } else {
41
- setMessage(response);
42
- }
43
- });
36
+ setEditState((state) => ({ ...state, message: void 0 }));
37
+ const response = await onEdit?.(
38
+ { editType: "commit", value: value2, isValid: true },
39
+ "commit"
40
+ );
41
+ if (response === true) {
42
+ isDirtyRef.current = false;
43
+ initialValueRef.current = value2;
44
+ vuuUtils.dispatchCustomEvent(target, "vuu-commit");
45
+ } else if (typeof response === "string") {
46
+ setEditState((state) => ({ ...state, message: response }));
47
+ }
44
48
  }
45
49
  } else {
46
50
  vuuUtils.dispatchCustomEvent(target, "vuu-commit");
47
- hasCommittedRef.current = false;
48
51
  }
49
52
  },
50
- [clientSideEditValidationCheck, onCommit, value]
53
+ [clientSideEditValidationCheck, editState, onEdit]
51
54
  );
52
55
  const handleKeyDown = React.useCallback(
53
56
  (evt) => {
@@ -57,13 +60,22 @@ const useEditableText = ({
57
60
  evt.stopPropagation();
58
61
  } else if (evt.key === "Escape") {
59
62
  if (isDirtyRef.current) {
63
+ const { value: previousValue } = editState;
60
64
  isDirtyRef.current = false;
61
- setMessage(void 0);
62
- setValue(initialValueRef.current);
65
+ setEditState({ value: initialValueRef.current, message: void 0 });
66
+ onEdit?.(
67
+ {
68
+ editType: "cancel",
69
+ isValid: true,
70
+ previousValue,
71
+ value: initialValueRef.current
72
+ },
73
+ "cancel"
74
+ );
63
75
  }
64
76
  }
65
77
  },
66
- [commit]
78
+ [commit, editState, onEdit]
67
79
  );
68
80
  const handleBlur = React.useCallback(
69
81
  (evt) => {
@@ -75,32 +87,39 @@ const useEditableText = ({
75
87
  );
76
88
  const handleChange = React.useCallback(
77
89
  (evt) => {
78
- let typedValue = evt.target.value;
79
- if (type === "number" && !isNaN(parseFloat(typedValue))) {
80
- typedValue = parseFloat(typedValue);
81
- }
82
- isDirtyRef.current = value !== initialValueRef.current;
83
- setValue(typedValue);
84
- if (hasCommittedRef.current && value !== void 0) {
85
- const result = clientSideEditValidationCheck?.(value);
86
- if (result?.ok === false) {
87
- setMessage(result.messages?.join(","));
88
- }
90
+ const { value: value2 } = evt.target;
91
+ const typedValue = vuuUtils.getTypedValue(value2, type);
92
+ console.log(
93
+ `[useEditableText] handleChange '${value2}' typedValue ${typedValue}
94
+ initial value ${initialValueRef.current}
95
+ `
96
+ );
97
+ isDirtyRef.current = value2 !== initialValueRef.current;
98
+ const result = clientSideEditValidationCheck?.(value2, "change");
99
+ console.log({ result, value: value2 });
100
+ setEditState({ value: value2 });
101
+ onEdit?.(
102
+ { editType: "change", isValid: result?.ok !== false, value: value2 },
103
+ "change"
104
+ );
105
+ if (result?.ok === false) {
106
+ console.log("cell fails validation");
107
+ setEditState({ value: value2, message: result.messages?.join(",") });
89
108
  }
90
109
  },
91
- [clientSideEditValidationCheck, type, value]
110
+ [clientSideEditValidationCheck, onEdit, type]
92
111
  );
93
112
  return {
113
+ //TODO why are we detecting commit here, why not use VuuInput ?
94
114
  inputProps: {
95
115
  onBlur: handleBlur,
96
116
  onKeyDown: handleKeyDown
97
117
  },
98
118
  onChange: handleChange,
99
- value: value ?? "",
100
- warningMessage: message
119
+ value: editState.value,
120
+ warningMessage: editState.message
101
121
  };
102
122
  };
103
123
 
104
- exports.WarnCommit = WarnCommit;
105
124
  exports.useEditableText = useEditableText;
106
125
  //# sourceMappingURL=useEditableText.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEditableText.js","sources":["../../src/editable/useEditableText.ts"],"sourcesContent":["import { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { DataItemCommitHandler } from \"@vuu-ui/vuu-table-types\";\nimport { useLayoutEffectSkipFirst } from \"@vuu-ui/vuu-utils\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport { dispatchCustomEvent } from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport const WarnCommit = (): Promise<true> => {\n console.warn(\n \"onCommit handler has not been provided to InputCell cell renderer\",\n );\n return Promise.resolve(true);\n};\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n clientSideEditValidationCheck?: DataValueValidationChecker;\n initialValue?: T;\n onCommit: DataItemCommitHandler<T>;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\nexport const useEditableText = <T extends string | number = string>({\n clientSideEditValidationCheck,\n initialValue,\n onCommit,\n type,\n}: EditableTextHookProps<T>) => {\n const [message, setMessage] = useState<string | undefined>();\n const [value, setValue] = useState<T | undefined>(initialValue);\n const initialValueRef = useRef<T | undefined>(initialValue);\n const isDirtyRef = useRef(false);\n const hasCommittedRef = useRef(false);\n\n useLayoutEffectSkipFirst(() => {\n //TODO this isn't right, review the state we're using\n setValue(initialValue);\n }, [initialValue]);\n\n const commit = useCallback(\n (target: HTMLElement) => {\n if (isDirtyRef.current) {\n hasCommittedRef.current = true;\n const result = clientSideEditValidationCheck?.(value);\n if (result?.ok === false) {\n setMessage(result?.messages?.join(\",\"));\n } else {\n setMessage(undefined);\n console.log(`commit value ${value}`);\n onCommit(value as T).then((response) => {\n if (response === true) {\n isDirtyRef.current = false;\n dispatchCustomEvent(target, \"vuu-commit\");\n } else {\n setMessage(response);\n }\n });\n }\n } else {\n // why, if not dirty ?\n dispatchCustomEvent(target, \"vuu-commit\");\n hasCommittedRef.current = false;\n }\n },\n [clientSideEditValidationCheck, onCommit, value],\n );\n\n const handleKeyDown = useCallback(\n (evt: KeyboardEvent<HTMLElement>) => {\n if (evt.key === \"Enter\") {\n commit(evt.target as HTMLElement);\n } else if (\n evt.key === \"ArrowRight\" ||\n evt.key === \"ArrowLeft\" ||\n evt.key === \"ArrowUp\" ||\n evt.key === \"ArrowDown\"\n ) {\n evt.stopPropagation();\n } else if (evt.key === \"Escape\") {\n if (isDirtyRef.current) {\n isDirtyRef.current = false;\n setMessage(undefined);\n setValue(initialValueRef.current);\n }\n }\n },\n [commit],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n (evt) => {\n if (isDirtyRef.current) {\n commit(evt.target as HTMLElement);\n }\n },\n [commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n let typedValue: VuuRowDataItemType = (evt.target as HTMLInputElement)\n .value;\n if (type === \"number\" && !isNaN(parseFloat(typedValue))) {\n typedValue = parseFloat(typedValue);\n }\n isDirtyRef.current = value !== initialValueRef.current;\n setValue(typedValue as T);\n if (hasCommittedRef.current && value !== undefined) {\n const result = clientSideEditValidationCheck?.(value);\n if (result?.ok === false) {\n setMessage(result.messages?.join(\",\"));\n }\n }\n },\n [clientSideEditValidationCheck, type, value],\n );\n\n return {\n inputProps: {\n onBlur: handleBlur,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: value ?? \"\",\n warningMessage: message,\n };\n};\n"],"names":["useState","useRef","useLayoutEffectSkipFirst","useCallback","dispatchCustomEvent"],"mappings":"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"}
1
+ {"version":3,"file":"useEditableText.js","sources":["../../src/editable/useEditableText.ts"],"sourcesContent":["import { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport { DataItemEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport { dispatchCustomEvent, getTypedValue } 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?: DataItemEditHandler;\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 // console.log(\"initial value: \", initialValue);\n const [editState, setEditState] = useState<EditState>({\n value: stringValueOf(value),\n });\n // console.log(\"edit state: \", editState);\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({ message: \"\", value: stringValueOf(value) });\n console.log(\"initial value changed to: \", value);\n }\n }, [value]);\n\n const commit = useCallback(\n async (target: HTMLElement) => {\n const { value } = editState;\n if (isDirtyRef.current) {\n const result = clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n } else {\n setEditState((state) => ({ ...state, message: undefined }));\n const response = await onEdit?.(\n { editType: \"commit\", value, isValid: true },\n \"commit\",\n );\n if (response === true) {\n isDirtyRef.current = false;\n initialValueRef.current = value;\n dispatchCustomEvent(target, \"vuu-commit\");\n } else if (typeof response === \"string\") {\n setEditState((state) => ({ ...state, message: response }));\n }\n }\n } else {\n // why, if not dirty ?\n dispatchCustomEvent(target, \"vuu-commit\");\n }\n },\n [clientSideEditValidationCheck, editState, onEdit],\n );\n\n const handleKeyDown = useCallback(\n (evt: KeyboardEvent<HTMLElement>) => {\n if (evt.key === \"Enter\") {\n commit(evt.target as HTMLElement);\n } else if (\n evt.key === \"ArrowRight\" ||\n evt.key === \"ArrowLeft\" ||\n evt.key === \"ArrowUp\" ||\n evt.key === \"ArrowDown\"\n ) {\n evt.stopPropagation();\n } else if (evt.key === \"Escape\") {\n if (isDirtyRef.current) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({ value: initialValueRef.current, message: undefined });\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 }\n },\n [commit, editState, onEdit],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n (evt) => {\n if (isDirtyRef.current) {\n commit(evt.target as HTMLElement);\n }\n },\n [commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n const typedValue = getTypedValue(value, type);\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 console.log({ result, value });\n setEditState({ value });\n\n onEdit?.(\n { editType: \"change\", isValid: result?.ok !== false, value },\n \"change\",\n );\n if (result?.ok === false) {\n console.log(\"cell fails validation\");\n setEditState({ value, message: result.messages?.join(\",\") });\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 onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["useState","useRef","useMemo","useCallback","value","dispatchCustomEvent","getTypedValue"],"mappings":"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"}
package/cjs/index.js CHANGED
@@ -122,7 +122,6 @@ exports.measureElementSizeAndPosition = dropTargetUtils.measureElementSizeAndPos
122
122
  exports.mutateDropTargetsSwitchDropTargetPosition = dropTargetUtils.mutateDropTargetsSwitchDropTargetPosition;
123
123
  exports.removeDraggedItem = dropTargetUtils.removeDraggedItem;
124
124
  exports.useGlobalDragDrop = useGlobalDragDrop.useGlobalDragDrop;
125
- exports.WarnCommit = useEditableText.WarnCommit;
126
125
  exports.useEditableText = useEditableText.useEditableText;
127
126
  exports.EditableLabel = EditableLabel.EditableLabel;
128
127
  exports.NullEditAPI = EditableLabel.NullEditAPI;
package/cjs/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -21,14 +21,10 @@ const CycleStateButton = forwardRef(function CycleStateButton2({
21
21
  ...buttonProps
22
22
  }, forwardedRef) {
23
23
  const handleClick = useCallback(
24
- (evt) => {
24
+ async (evt) => {
25
25
  const nextValue = getNextValue(value, values);
26
26
  onChange?.(nextValue);
27
- onCommit?.(evt, nextValue).then((response) => {
28
- if (response !== true) {
29
- console.error(response);
30
- }
31
- });
27
+ onCommit?.(evt, nextValue);
32
28
  },
33
29
  [onChange, onCommit, value, values]
34
30
  );
@@ -1 +1 @@
1
- {"version":3,"file":"CycleStateButton.js","sources":["../../src/cycle-state-button/CycleStateButton.tsx"],"sourcesContent":["import { Button, ButtonProps } from \"@salt-ds/core\";\nimport cx from \"clsx\";\nimport type { CommitResponse } from \"@vuu-ui/vuu-table-types\";\nimport type {\n VuuColumnDataType,\n VuuRowDataItemType,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport { ForwardedRef, forwardRef, SyntheticEvent, useCallback } from \"react\";\n\nconst classBase = \"vuuCycleStateButton\";\n\nexport type CycleStateCommitHandler = (\n evt: SyntheticEvent,\n value: VuuRowDataItemType,\n) => CommitResponse;\n\nexport interface CycleStateButtonProps extends Omit<ButtonProps, \"onChange\"> {\n onChange?: (value: VuuRowDataItemType) => void;\n onCommit?: CycleStateCommitHandler;\n values: string[];\n value: string;\n}\n\nconst getNextValue = (value: string, valueList: string[]) => {\n const index = valueList\n .map((v) => v.toUpperCase())\n .indexOf(value.toUpperCase());\n if (index === valueList.length - 1) {\n return valueList[0];\n } else {\n return valueList[index + 1];\n }\n};\n\nexport const CycleStateButton = forwardRef(function CycleStateButton(\n {\n className,\n onChange,\n onCommit,\n value = \"\",\n values,\n ...buttonProps\n }: CycleStateButtonProps,\n forwardedRef: ForwardedRef<HTMLButtonElement>,\n) {\n const handleClick = useCallback(\n (evt: SyntheticEvent<HTMLButtonElement>) => {\n const nextValue = getNextValue(value, values);\n onChange?.(nextValue);\n onCommit?.(evt, nextValue as VuuColumnDataType).then((response) => {\n if (response !== true) {\n console.error(response);\n }\n });\n },\n [onChange, onCommit, value, values],\n );\n\n return (\n <Button\n {...buttonProps}\n className={cx(\n classBase,\n className,\n `${classBase}-${value.toLowerCase()}`,\n )}\n onClick={handleClick}\n ref={forwardedRef}\n >\n {value}\n </Button>\n );\n});\n"],"names":["CycleStateButton"],"mappings":";;;;;AASA,MAAM,SAAY,GAAA,qBAAA,CAAA;AAclB,MAAM,YAAA,GAAe,CAAC,KAAA,EAAe,SAAwB,KAAA;AAC3D,EAAA,MAAM,KAAQ,GAAA,SAAA,CACX,GAAI,CAAA,CAAC,CAAM,KAAA,CAAA,CAAE,WAAY,EAAC,CAC1B,CAAA,OAAA,CAAQ,KAAM,CAAA,WAAA,EAAa,CAAA,CAAA;AAC9B,EAAI,IAAA,KAAA,KAAU,SAAU,CAAA,MAAA,GAAS,CAAG,EAAA;AAClC,IAAA,OAAO,UAAU,CAAC,CAAA,CAAA;AAAA,GACb,MAAA;AACL,IAAO,OAAA,SAAA,CAAU,QAAQ,CAAC,CAAA,CAAA;AAAA,GAC5B;AACF,CAAA,CAAA;AAEa,MAAA,gBAAA,GAAmB,UAAW,CAAA,SAASA,iBAClD,CAAA;AAAA,EACE,SAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAQ,GAAA,EAAA;AAAA,EACR,MAAA;AAAA,EACA,GAAG,WAAA;AACL,CAAA,EACA,YACA,EAAA;AACA,EAAA,MAAM,WAAc,GAAA,WAAA;AAAA,IAClB,CAAC,GAA2C,KAAA;AAC1C,MAAM,MAAA,SAAA,GAAY,YAAa,CAAA,KAAA,EAAO,MAAM,CAAA,CAAA;AAC5C,MAAA,QAAA,GAAW,SAAS,CAAA,CAAA;AACpB,MAAA,QAAA,GAAW,GAAK,EAAA,SAA8B,CAAE,CAAA,IAAA,CAAK,CAAC,QAAa,KAAA;AACjE,QAAA,IAAI,aAAa,IAAM,EAAA;AACrB,UAAA,OAAA,CAAQ,MAAM,QAAQ,CAAA,CAAA;AAAA,SACxB;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,IACA,CAAC,QAAA,EAAU,QAAU,EAAA,KAAA,EAAO,MAAM,CAAA;AAAA,GACpC,CAAA;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACE,GAAG,WAAA;AAAA,MACJ,SAAW,EAAA,EAAA;AAAA,QACT,SAAA;AAAA,QACA,SAAA;AAAA,QACA,CAAG,EAAA,SAAS,CAAI,CAAA,EAAA,KAAA,CAAM,aAAa,CAAA,CAAA;AAAA,OACrC;AAAA,MACA,OAAS,EAAA,WAAA;AAAA,MACT,GAAK,EAAA,YAAA;AAAA,MAEJ,QAAA,EAAA,KAAA;AAAA,KAAA;AAAA,GACH,CAAA;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"CycleStateButton.js","sources":["../../src/cycle-state-button/CycleStateButton.tsx"],"sourcesContent":["import { Button, ButtonProps } from \"@salt-ds/core\";\nimport cx from \"clsx\";\nimport type {\n VuuColumnDataType,\n VuuRowDataItemType,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport { ForwardedRef, forwardRef, SyntheticEvent, useCallback } from \"react\";\nimport { CommitHandler } from \"@vuu-ui/vuu-utils\";\n\nconst classBase = \"vuuCycleStateButton\";\n\nexport interface CycleStateButtonProps extends Omit<ButtonProps, \"onChange\"> {\n onChange?: (value: VuuRowDataItemType) => void;\n onCommit?: CommitHandler<HTMLButtonElement>;\n values: string[];\n value: string;\n}\n\nconst getNextValue = (value: string, valueList: string[]) => {\n const index = valueList\n .map((v) => v.toUpperCase())\n .indexOf(value.toUpperCase());\n if (index === valueList.length - 1) {\n return valueList[0];\n } else {\n return valueList[index + 1];\n }\n};\n\nexport const CycleStateButton = forwardRef(function CycleStateButton(\n {\n className,\n onChange,\n onCommit,\n value = \"\",\n values,\n ...buttonProps\n }: CycleStateButtonProps,\n forwardedRef: ForwardedRef<HTMLButtonElement>,\n) {\n const handleClick = useCallback(\n async (evt: SyntheticEvent<HTMLButtonElement>) => {\n const nextValue = getNextValue(value, values);\n onChange?.(nextValue);\n onCommit?.(evt, nextValue as VuuColumnDataType);\n },\n [onChange, onCommit, value, values],\n );\n\n return (\n <Button\n {...buttonProps}\n className={cx(\n classBase,\n className,\n `${classBase}-${value.toLowerCase()}`,\n )}\n onClick={handleClick}\n ref={forwardedRef}\n >\n {value}\n </Button>\n );\n});\n"],"names":["CycleStateButton"],"mappings":";;;;;AASA,MAAM,SAAY,GAAA,qBAAA,CAAA;AASlB,MAAM,YAAA,GAAe,CAAC,KAAA,EAAe,SAAwB,KAAA;AAC3D,EAAA,MAAM,KAAQ,GAAA,SAAA,CACX,GAAI,CAAA,CAAC,CAAM,KAAA,CAAA,CAAE,WAAY,EAAC,CAC1B,CAAA,OAAA,CAAQ,KAAM,CAAA,WAAA,EAAa,CAAA,CAAA;AAC9B,EAAI,IAAA,KAAA,KAAU,SAAU,CAAA,MAAA,GAAS,CAAG,EAAA;AAClC,IAAA,OAAO,UAAU,CAAC,CAAA,CAAA;AAAA,GACb,MAAA;AACL,IAAO,OAAA,SAAA,CAAU,QAAQ,CAAC,CAAA,CAAA;AAAA,GAC5B;AACF,CAAA,CAAA;AAEa,MAAA,gBAAA,GAAmB,UAAW,CAAA,SAASA,iBAClD,CAAA;AAAA,EACE,SAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAQ,GAAA,EAAA;AAAA,EACR,MAAA;AAAA,EACA,GAAG,WAAA;AACL,CAAA,EACA,YACA,EAAA;AACA,EAAA,MAAM,WAAc,GAAA,WAAA;AAAA,IAClB,OAAO,GAA2C,KAAA;AAChD,MAAM,MAAA,SAAA,GAAY,YAAa,CAAA,KAAA,EAAO,MAAM,CAAA,CAAA;AAC5C,MAAA,QAAA,GAAW,SAAS,CAAA,CAAA;AACpB,MAAA,QAAA,GAAW,KAAK,SAA8B,CAAA,CAAA;AAAA,KAChD;AAAA,IACA,CAAC,QAAA,EAAU,QAAU,EAAA,KAAA,EAAO,MAAM,CAAA;AAAA,GACpC,CAAA;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACE,GAAG,WAAA;AAAA,MACJ,SAAW,EAAA,EAAA;AAAA,QACT,SAAA;AAAA,QACA,SAAA;AAAA,QACA,CAAG,EAAA,SAAS,CAAI,CAAA,EAAA,KAAA,CAAM,aAAa,CAAA,CAAA;AAAA,OACrC;AAAA,MACA,OAAS,EAAA,WAAA;AAAA,MACT,GAAK,EAAA,YAAA;AAAA,MAEJ,QAAA,EAAA,KAAA;AAAA,KAAA;AAAA,GACH,CAAA;AAEJ,CAAC;;;;"}
@@ -1,51 +1,54 @@
1
- import { useLayoutEffectSkipFirst, dispatchCustomEvent } from '@vuu-ui/vuu-utils';
2
- import { useState, useRef, useCallback } from 'react';
1
+ import { dispatchCustomEvent, getTypedValue } from '@vuu-ui/vuu-utils';
2
+ import { useState, useRef, useMemo, useCallback } from 'react';
3
3
 
4
- const WarnCommit = () => {
5
- console.warn(
6
- "onCommit handler has not been provided to InputCell cell renderer"
7
- );
8
- return Promise.resolve(true);
9
- };
4
+ const stringValueOf = (value) => value?.toString() ?? "";
10
5
  const useEditableText = ({
11
6
  clientSideEditValidationCheck,
12
- initialValue,
13
- onCommit,
14
- type
7
+ value,
8
+ onEdit,
9
+ type = "string"
15
10
  }) => {
16
- const [message, setMessage] = useState();
17
- const [value, setValue] = useState(initialValue);
18
- const initialValueRef = useRef(initialValue);
11
+ const [editState, setEditState] = useState({
12
+ value: stringValueOf(value)
13
+ });
14
+ const initialValueRef = useRef(value?.toString() ?? "");
19
15
  const isDirtyRef = useRef(false);
20
- const hasCommittedRef = useRef(false);
21
- useLayoutEffectSkipFirst(() => {
22
- setValue(initialValue);
23
- }, [initialValue]);
16
+ useMemo(() => {
17
+ if (initialValueRef.current !== value?.toString()) {
18
+ initialValueRef.current = stringValueOf(value);
19
+ setEditState({ message: "", value: stringValueOf(value) });
20
+ console.log("initial value changed to: ", value);
21
+ }
22
+ }, [value]);
24
23
  const commit = useCallback(
25
- (target) => {
24
+ async (target) => {
25
+ const { value: value2 } = editState;
26
26
  if (isDirtyRef.current) {
27
- hasCommittedRef.current = true;
28
- const result = clientSideEditValidationCheck?.(value);
27
+ const result = clientSideEditValidationCheck?.(value2, "*");
29
28
  if (result?.ok === false) {
30
- setMessage(result?.messages?.join(","));
29
+ setEditState((state) => ({
30
+ ...state,
31
+ message: result?.messages?.join(",")
32
+ }));
31
33
  } else {
32
- setMessage(void 0);
33
- console.log(`commit value ${value}`);
34
- onCommit(value).then((response) => {
35
- if (response === true) {
36
- isDirtyRef.current = false;
37
- dispatchCustomEvent(target, "vuu-commit");
38
- } else {
39
- setMessage(response);
40
- }
41
- });
34
+ setEditState((state) => ({ ...state, message: void 0 }));
35
+ const response = await onEdit?.(
36
+ { editType: "commit", value: value2, isValid: true },
37
+ "commit"
38
+ );
39
+ if (response === true) {
40
+ isDirtyRef.current = false;
41
+ initialValueRef.current = value2;
42
+ dispatchCustomEvent(target, "vuu-commit");
43
+ } else if (typeof response === "string") {
44
+ setEditState((state) => ({ ...state, message: response }));
45
+ }
42
46
  }
43
47
  } else {
44
48
  dispatchCustomEvent(target, "vuu-commit");
45
- hasCommittedRef.current = false;
46
49
  }
47
50
  },
48
- [clientSideEditValidationCheck, onCommit, value]
51
+ [clientSideEditValidationCheck, editState, onEdit]
49
52
  );
50
53
  const handleKeyDown = useCallback(
51
54
  (evt) => {
@@ -55,13 +58,22 @@ const useEditableText = ({
55
58
  evt.stopPropagation();
56
59
  } else if (evt.key === "Escape") {
57
60
  if (isDirtyRef.current) {
61
+ const { value: previousValue } = editState;
58
62
  isDirtyRef.current = false;
59
- setMessage(void 0);
60
- setValue(initialValueRef.current);
63
+ setEditState({ value: initialValueRef.current, message: void 0 });
64
+ onEdit?.(
65
+ {
66
+ editType: "cancel",
67
+ isValid: true,
68
+ previousValue,
69
+ value: initialValueRef.current
70
+ },
71
+ "cancel"
72
+ );
61
73
  }
62
74
  }
63
75
  },
64
- [commit]
76
+ [commit, editState, onEdit]
65
77
  );
66
78
  const handleBlur = useCallback(
67
79
  (evt) => {
@@ -73,31 +85,39 @@ const useEditableText = ({
73
85
  );
74
86
  const handleChange = useCallback(
75
87
  (evt) => {
76
- let typedValue = evt.target.value;
77
- if (type === "number" && !isNaN(parseFloat(typedValue))) {
78
- typedValue = parseFloat(typedValue);
79
- }
80
- isDirtyRef.current = value !== initialValueRef.current;
81
- setValue(typedValue);
82
- if (hasCommittedRef.current && value !== void 0) {
83
- const result = clientSideEditValidationCheck?.(value);
84
- if (result?.ok === false) {
85
- setMessage(result.messages?.join(","));
86
- }
88
+ const { value: value2 } = evt.target;
89
+ const typedValue = getTypedValue(value2, type);
90
+ console.log(
91
+ `[useEditableText] handleChange '${value2}' typedValue ${typedValue}
92
+ initial value ${initialValueRef.current}
93
+ `
94
+ );
95
+ isDirtyRef.current = value2 !== initialValueRef.current;
96
+ const result = clientSideEditValidationCheck?.(value2, "change");
97
+ console.log({ result, value: value2 });
98
+ setEditState({ value: value2 });
99
+ onEdit?.(
100
+ { editType: "change", isValid: result?.ok !== false, value: value2 },
101
+ "change"
102
+ );
103
+ if (result?.ok === false) {
104
+ console.log("cell fails validation");
105
+ setEditState({ value: value2, message: result.messages?.join(",") });
87
106
  }
88
107
  },
89
- [clientSideEditValidationCheck, type, value]
108
+ [clientSideEditValidationCheck, onEdit, type]
90
109
  );
91
110
  return {
111
+ //TODO why are we detecting commit here, why not use VuuInput ?
92
112
  inputProps: {
93
113
  onBlur: handleBlur,
94
114
  onKeyDown: handleKeyDown
95
115
  },
96
116
  onChange: handleChange,
97
- value: value ?? "",
98
- warningMessage: message
117
+ value: editState.value,
118
+ warningMessage: editState.message
99
119
  };
100
120
  };
101
121
 
102
- export { WarnCommit, useEditableText };
122
+ export { useEditableText };
103
123
  //# sourceMappingURL=useEditableText.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEditableText.js","sources":["../../src/editable/useEditableText.ts"],"sourcesContent":["import { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { DataItemCommitHandler } from \"@vuu-ui/vuu-table-types\";\nimport { useLayoutEffectSkipFirst } from \"@vuu-ui/vuu-utils\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport { dispatchCustomEvent } from \"@vuu-ui/vuu-utils\";\nimport {\n FocusEventHandler,\n FormEventHandler,\n KeyboardEvent,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport const WarnCommit = (): Promise<true> => {\n console.warn(\n \"onCommit handler has not been provided to InputCell cell renderer\",\n );\n return Promise.resolve(true);\n};\n\nexport interface EditableTextHookProps<\n T extends VuuRowDataItemType = VuuRowDataItemType,\n> {\n clientSideEditValidationCheck?: DataValueValidationChecker;\n initialValue?: T;\n onCommit: DataItemCommitHandler<T>;\n type?: \"string\" | \"number\" | \"boolean\";\n}\n\nexport const useEditableText = <T extends string | number = string>({\n clientSideEditValidationCheck,\n initialValue,\n onCommit,\n type,\n}: EditableTextHookProps<T>) => {\n const [message, setMessage] = useState<string | undefined>();\n const [value, setValue] = useState<T | undefined>(initialValue);\n const initialValueRef = useRef<T | undefined>(initialValue);\n const isDirtyRef = useRef(false);\n const hasCommittedRef = useRef(false);\n\n useLayoutEffectSkipFirst(() => {\n //TODO this isn't right, review the state we're using\n setValue(initialValue);\n }, [initialValue]);\n\n const commit = useCallback(\n (target: HTMLElement) => {\n if (isDirtyRef.current) {\n hasCommittedRef.current = true;\n const result = clientSideEditValidationCheck?.(value);\n if (result?.ok === false) {\n setMessage(result?.messages?.join(\",\"));\n } else {\n setMessage(undefined);\n console.log(`commit value ${value}`);\n onCommit(value as T).then((response) => {\n if (response === true) {\n isDirtyRef.current = false;\n dispatchCustomEvent(target, \"vuu-commit\");\n } else {\n setMessage(response);\n }\n });\n }\n } else {\n // why, if not dirty ?\n dispatchCustomEvent(target, \"vuu-commit\");\n hasCommittedRef.current = false;\n }\n },\n [clientSideEditValidationCheck, onCommit, value],\n );\n\n const handleKeyDown = useCallback(\n (evt: KeyboardEvent<HTMLElement>) => {\n if (evt.key === \"Enter\") {\n commit(evt.target as HTMLElement);\n } else if (\n evt.key === \"ArrowRight\" ||\n evt.key === \"ArrowLeft\" ||\n evt.key === \"ArrowUp\" ||\n evt.key === \"ArrowDown\"\n ) {\n evt.stopPropagation();\n } else if (evt.key === \"Escape\") {\n if (isDirtyRef.current) {\n isDirtyRef.current = false;\n setMessage(undefined);\n setValue(initialValueRef.current);\n }\n }\n },\n [commit],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n (evt) => {\n if (isDirtyRef.current) {\n commit(evt.target as HTMLElement);\n }\n },\n [commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n let typedValue: VuuRowDataItemType = (evt.target as HTMLInputElement)\n .value;\n if (type === \"number\" && !isNaN(parseFloat(typedValue))) {\n typedValue = parseFloat(typedValue);\n }\n isDirtyRef.current = value !== initialValueRef.current;\n setValue(typedValue as T);\n if (hasCommittedRef.current && value !== undefined) {\n const result = clientSideEditValidationCheck?.(value);\n if (result?.ok === false) {\n setMessage(result.messages?.join(\",\"));\n }\n }\n },\n [clientSideEditValidationCheck, type, value],\n );\n\n return {\n inputProps: {\n onBlur: handleBlur,\n onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: value ?? \"\",\n warningMessage: message,\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useEditableText.js","sources":["../../src/editable/useEditableText.ts"],"sourcesContent":["import { DataValueValidationChecker } from \"@vuu-ui/vuu-data-types\";\nimport { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport { DataItemEditHandler } from \"@vuu-ui/vuu-table-types\";\nimport { dispatchCustomEvent, getTypedValue } 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?: DataItemEditHandler;\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 // console.log(\"initial value: \", initialValue);\n const [editState, setEditState] = useState<EditState>({\n value: stringValueOf(value),\n });\n // console.log(\"edit state: \", editState);\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({ message: \"\", value: stringValueOf(value) });\n console.log(\"initial value changed to: \", value);\n }\n }, [value]);\n\n const commit = useCallback(\n async (target: HTMLElement) => {\n const { value } = editState;\n if (isDirtyRef.current) {\n const result = clientSideEditValidationCheck?.(value, \"*\");\n if (result?.ok === false) {\n setEditState((state) => ({\n ...state,\n message: result?.messages?.join(\",\"),\n }));\n } else {\n setEditState((state) => ({ ...state, message: undefined }));\n const response = await onEdit?.(\n { editType: \"commit\", value, isValid: true },\n \"commit\",\n );\n if (response === true) {\n isDirtyRef.current = false;\n initialValueRef.current = value;\n dispatchCustomEvent(target, \"vuu-commit\");\n } else if (typeof response === \"string\") {\n setEditState((state) => ({ ...state, message: response }));\n }\n }\n } else {\n // why, if not dirty ?\n dispatchCustomEvent(target, \"vuu-commit\");\n }\n },\n [clientSideEditValidationCheck, editState, onEdit],\n );\n\n const handleKeyDown = useCallback(\n (evt: KeyboardEvent<HTMLElement>) => {\n if (evt.key === \"Enter\") {\n commit(evt.target as HTMLElement);\n } else if (\n evt.key === \"ArrowRight\" ||\n evt.key === \"ArrowLeft\" ||\n evt.key === \"ArrowUp\" ||\n evt.key === \"ArrowDown\"\n ) {\n evt.stopPropagation();\n } else if (evt.key === \"Escape\") {\n if (isDirtyRef.current) {\n const { value: previousValue } = editState;\n isDirtyRef.current = false;\n setEditState({ value: initialValueRef.current, message: undefined });\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 }\n },\n [commit, editState, onEdit],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLElement>>(\n (evt) => {\n if (isDirtyRef.current) {\n commit(evt.target as HTMLElement);\n }\n },\n [commit],\n );\n\n const handleChange = useCallback<FormEventHandler>(\n (evt) => {\n const { value } = evt.target as HTMLInputElement;\n const typedValue = getTypedValue(value, type);\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 console.log({ result, value });\n setEditState({ value });\n\n onEdit?.(\n { editType: \"change\", isValid: result?.ok !== false, value },\n \"change\",\n );\n if (result?.ok === false) {\n console.log(\"cell fails validation\");\n setEditState({ value, message: result.messages?.join(\",\") });\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 onKeyDown: handleKeyDown,\n },\n onChange: handleChange,\n value: editState.value,\n warningMessage: editState.message,\n };\n};\n"],"names":["value"],"mappings":"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"}
package/esm/index.js CHANGED
@@ -19,7 +19,7 @@ export { DragDropState } from './drag-drop/DragDropState.js';
19
19
  export { useDragDrop } from './drag-drop/useDragDrop.js';
20
20
  export { NOT_HIDDEN, NOT_OVERFLOWED, cloneElement, constrainRect, dimensions, dropTargetsDebugString, getIndexOfDraggedItem, getItemById, getItemParentContainer, getNextDropTarget, getScrollableContainer, isContainerScrollable, measureDropTargets, measureElementSizeAndPosition, mutateDropTargetsSwitchDropTargetPosition, removeDraggedItem } from './drag-drop/drop-target-utils.js';
21
21
  export { useGlobalDragDrop } from './drag-drop/useGlobalDragDrop.js';
22
- export { WarnCommit, useEditableText } from './editable/useEditableText.js';
22
+ export { useEditableText } from './editable/useEditableText.js';
23
23
  export { EditableLabel, NullEditAPI } from './editable-label/EditableLabel.js';
24
24
  export { ExpandoInput } from './expando-input/ExpandoInput.js';
25
25
  export { Icon } from './icon-button/Icon.js';
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
- "version": "0.9.1",
2
+ "version": "0.9.2",
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": "0.9.1",
8
- "@vuu-ui/vuu-table-types": "0.9.1"
7
+ "@vuu-ui/vuu-data-types": "0.9.2",
8
+ "@vuu-ui/vuu-table-types": "0.9.2"
9
9
  },
10
10
  "dependencies": {
11
- "@vuu-ui/vuu-data-react": "0.9.1",
12
- "@vuu-ui/vuu-layout": "0.9.1",
13
- "@vuu-ui/vuu-popups": "0.9.1",
14
- "@vuu-ui/vuu-table": "0.9.1",
15
- "@vuu-ui/vuu-utils": "0.9.1",
11
+ "@vuu-ui/vuu-data-react": "0.9.2",
12
+ "@vuu-ui/vuu-layout": "0.9.2",
13
+ "@vuu-ui/vuu-popups": "0.9.2",
14
+ "@vuu-ui/vuu-table": "0.9.2",
15
+ "@vuu-ui/vuu-utils": "0.9.2",
16
16
  "@floating-ui/react": "^0.26.5",
17
17
  "@salt-ds/core": "1.34.0",
18
18
  "@salt-ds/icons": "1.12.1",
@@ -1,11 +1,10 @@
1
+ /// <reference types="react" />
1
2
  import { ButtonProps } from "@salt-ds/core";
2
- import type { CommitResponse } from "@vuu-ui/vuu-table-types";
3
3
  import type { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
4
- import { SyntheticEvent } from "react";
5
- export type CycleStateCommitHandler = (evt: SyntheticEvent, value: VuuRowDataItemType) => CommitResponse;
4
+ import { CommitHandler } from "@vuu-ui/vuu-utils";
6
5
  export interface CycleStateButtonProps extends Omit<ButtonProps, "onChange"> {
7
6
  onChange?: (value: VuuRowDataItemType) => void;
8
- onCommit?: CycleStateCommitHandler;
7
+ onCommit?: CommitHandler<HTMLButtonElement>;
9
8
  values: string[];
10
9
  value: string;
11
10
  }
@@ -1,20 +1,19 @@
1
1
  import { DataValueValidationChecker } from "@vuu-ui/vuu-data-types";
2
- import { DataItemCommitHandler } from "@vuu-ui/vuu-table-types";
3
2
  import { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
3
+ import { DataItemEditHandler } from "@vuu-ui/vuu-table-types";
4
4
  import { FocusEventHandler, FormEventHandler, KeyboardEvent } from "react";
5
- export declare const WarnCommit: () => Promise<true>;
6
5
  export interface EditableTextHookProps<T extends VuuRowDataItemType = VuuRowDataItemType> {
7
6
  clientSideEditValidationCheck?: DataValueValidationChecker;
8
- initialValue?: T;
9
- onCommit: DataItemCommitHandler<T>;
7
+ value?: T;
8
+ onEdit?: DataItemEditHandler;
10
9
  type?: "string" | "number" | "boolean";
11
10
  }
12
- export declare const useEditableText: <T extends string | number = string>({ clientSideEditValidationCheck, initialValue, onCommit, type, }: EditableTextHookProps<T>) => {
11
+ export declare const useEditableText: <T extends string | number | boolean = string>({ clientSideEditValidationCheck, value, onEdit, type, }: EditableTextHookProps<T>) => {
13
12
  inputProps: {
14
13
  onBlur: FocusEventHandler<HTMLElement>;
15
14
  onKeyDown: (evt: KeyboardEvent<HTMLElement>) => void;
16
15
  };
17
16
  onChange: FormEventHandler;
18
- value: string | T;
17
+ value: string;
19
18
  warningMessage: string | undefined;
20
19
  };