@linzjs/step-ag-grid 3.0.2 → 4.0.1

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.
Files changed (37) hide show
  1. package/dist/index.js +283 -217
  2. package/dist/index.js.map +1 -1
  3. package/dist/src/components/GridPopoverHook.d.ts +13 -1
  4. package/dist/src/components/gridForm/GridFormSubComponentTextArea.d.ts +11 -0
  5. package/dist/src/components/gridForm/GridFormSubComponentTextInput.d.ts +8 -8
  6. package/dist/src/components/gridForm/GridFormTextArea.d.ts +3 -4
  7. package/dist/src/components/gridForm/GridFormTextInput.d.ts +3 -4
  8. package/dist/src/index.d.ts +1 -1
  9. package/dist/src/lui/TextAreaInput.d.ts +4 -5
  10. package/dist/src/lui/TextInputFormatted.d.ts +4 -10
  11. package/dist/src/utils/textValidator.d.ts +6 -0
  12. package/dist/step-ag-grid.esm.js +283 -217
  13. package/dist/step-ag-grid.esm.js.map +1 -1
  14. package/package.json +1 -1
  15. package/src/components/Grid.tsx +2 -2
  16. package/src/components/GridCell.tsx +5 -0
  17. package/src/components/GridPopoverHook.tsx +79 -1
  18. package/src/components/gridForm/GridFormDropDown.tsx +63 -56
  19. package/src/components/gridForm/GridFormEditBearing.tsx +7 -8
  20. package/src/components/gridForm/GridFormMultiSelect.tsx +6 -10
  21. package/src/components/gridForm/GridFormPopoverMenu.tsx +7 -10
  22. package/src/components/gridForm/GridFormSubComponentTextArea.tsx +58 -0
  23. package/src/components/gridForm/GridFormSubComponentTextInput.tsx +48 -55
  24. package/src/components/gridForm/GridFormTextArea.tsx +10 -18
  25. package/src/components/gridForm/GridFormTextInput.tsx +12 -25
  26. package/src/contexts/GridPopoverContextProvider.tsx +11 -4
  27. package/src/index.ts +1 -1
  28. package/src/lui/TextAreaInput.tsx +34 -18
  29. package/src/lui/TextInputFormatted.tsx +19 -35
  30. package/src/react-menu3/components/MenuItem.tsx +5 -2
  31. package/src/stories/grid/FormTest.tsx +16 -3
  32. package/src/stories/grid/GridPopoutEditDropDown.stories.tsx +20 -17
  33. package/src/stories/grid/GridPopoutEditMultiSelect.stories.tsx +2 -2
  34. package/src/stories/grid/GridReadOnly.stories.tsx +15 -3
  35. package/src/utils/textValidator.ts +24 -0
  36. package/dist/src/components/GridSubComponentTextArea.d.ts +0 -10
  37. package/src/components/GridSubComponentTextArea.tsx +0 -62
@@ -4,37 +4,25 @@ import { useGridPopoverHook } from "../GridPopoverHook";
4
4
  import { GridBaseRow } from "../Grid";
5
5
  import { CellEditorCommon } from "../GridCell";
6
6
  import { useGridPopoverContext } from "../../contexts/GridPopoverContext";
7
+ import { TextInputValidator, TextInputValidatorProps } from "../../utils/textValidator";
7
8
 
8
- export interface GridFormTextInputProps<RowType extends GridBaseRow> extends CellEditorCommon {
9
+ export interface GridFormTextInputProps<RowType extends GridBaseRow> extends TextInputValidatorProps, CellEditorCommon {
9
10
  placeholder?: string;
10
11
  units?: string;
11
- required?: boolean;
12
- maxLength?: number;
13
12
  width?: string | number;
14
- // Return null for ok, otherwise an error string
15
- validate?: (value: string, data: RowType) => string | null;
16
13
  onSave?: (selectedRows: RowType[], value: string) => Promise<boolean>;
14
+ helpText?: string;
17
15
  }
18
16
 
19
17
  export const GridFormTextInput = <RowType extends GridBaseRow>(props: GridFormTextInputProps<RowType>) => {
20
- const { field, data, value: initialVale } = useGridPopoverContext<RowType>();
18
+ const { field, value: initialVale } = useGridPopoverContext<RowType>();
19
+
20
+ const helpText = props.helpText ?? "Press enter or tab to save";
21
21
 
22
22
  const initValue = initialVale == null ? "" : `${initialVale}`;
23
23
  const [value, setValue] = useState(initValue);
24
24
 
25
- const invalid = useCallback(() => {
26
- const trimmedValue = value.trim();
27
- if (props.required && trimmedValue.length == 0) {
28
- return `Some text is required`;
29
- }
30
- if (props.maxLength && trimmedValue.length > props.maxLength) {
31
- return `Text must be no longer than ${props.maxLength} characters`;
32
- }
33
- if (props.validate) {
34
- return props.validate(trimmedValue, data);
35
- }
36
- return null;
37
- }, [data, props, value]);
25
+ const invalid = useCallback(() => TextInputValidator(props, value), [props, value]);
38
26
 
39
27
  const save = useCallback(
40
28
  async (selectedRows: RowType[]): Promise<boolean> => {
@@ -57,7 +45,7 @@ export const GridFormTextInput = <RowType extends GridBaseRow>(props: GridFormTe
57
45
  },
58
46
  [invalid, value, initValue, props, field],
59
47
  );
60
- const { popoverWrapper, triggerSave } = useGridPopoverHook({ className: props.className, save });
48
+ const { popoverWrapper, onlyInputKeyboardEventHandlers } = useGridPopoverHook({ className: props.className, save });
61
49
 
62
50
  return popoverWrapper(
63
51
  <div style={{ display: "flex", flexDirection: "row", width: props.width ?? 240 }} className={"FormTest"}>
@@ -66,11 +54,10 @@ export const GridFormTextInput = <RowType extends GridBaseRow>(props: GridFormTe
66
54
  onChange={(e) => setValue(e.target.value)}
67
55
  error={invalid()}
68
56
  formatted={props.units}
69
- inputProps={{
70
- style: { width: "100%" },
71
- placeholder: props.placeholder,
72
- onKeyDown: async (e) => e.key === "Enter" && triggerSave().then(),
73
- }}
57
+ style={{ width: "100%" }}
58
+ placeholder={props.placeholder}
59
+ {...onlyInputKeyboardEventHandlers}
60
+ helpText={helpText}
74
61
  />
75
62
  </div>,
76
63
  );
@@ -11,7 +11,7 @@ interface GridPopoverContextProps {
11
11
  }
12
12
 
13
13
  export const GridPopoverContextProvider = ({ props, children }: GridPopoverContextProps) => {
14
- const { getSelectedRows, updatingCells } = useContext(GridContext);
14
+ const { getSelectedRows, updatingCells, stopEditing } = useContext(GridContext);
15
15
  const anchorRef = useRef<Element>(props.eGridCell);
16
16
 
17
17
  const [saving, setSaving] = useState(false);
@@ -27,9 +27,16 @@ export const GridPopoverContextProvider = ({ props, children }: GridPopoverConte
27
27
  const field = props.colDef?.field ?? "";
28
28
 
29
29
  const updateValue = useCallback(
30
- async (saveFn: (selectedRows: any[]) => Promise<boolean>): Promise<boolean> =>
31
- !saving && (await updatingCells({ selectedRows, field }, saveFn, setSaving)),
32
- [field, saving, selectedRows, updatingCells],
30
+ async (saveFn: (selectedRows: any[]) => Promise<boolean>): Promise<boolean> => {
31
+ let result = false;
32
+ if (!saving) {
33
+ result = await updatingCells({ selectedRows, field }, saveFn, setSaving);
34
+ if (result) stopEditing();
35
+ }
36
+
37
+ return result;
38
+ },
39
+ [field, saving, selectedRows, stopEditing, updatingCells],
33
40
  );
34
41
 
35
42
  return (
package/src/index.ts CHANGED
@@ -39,7 +39,7 @@ export { GridHeaderSelect } from "./components/gridHeader/GridHeaderSelect";
39
39
 
40
40
  export { TextAreaInput } from "./lui/TextAreaInput";
41
41
  export { TextInputFormatted } from "./lui/TextInputFormatted";
42
- export { GridSubComponentTextArea } from "./components/GridSubComponentTextArea";
42
+ export { GridFormSubComponentTextArea } from "./components/gridForm/GridFormSubComponentTextArea";
43
43
 
44
44
  export * from "./lui/ActionButton";
45
45
 
@@ -1,52 +1,58 @@
1
- import { ChangeEventHandler, InputHTMLAttributes, useState } from "react";
1
+ import { InputHTMLAttributes, useState } from "react";
2
2
  import clsx from "clsx";
3
3
  import { LuiIcon } from "@linzjs/lui";
4
- import { v4 as uuidv4 } from "uuid";
4
+ import { v4 as uuidVersion4 } from "uuid";
5
+ import { omit } from "lodash-es";
5
6
 
6
7
  export const useGenerateOrDefaultId = (idFromProps?: string) => {
7
- const [id] = useState(idFromProps ? idFromProps : uuidv4());
8
+ const [id] = useState(idFromProps ? idFromProps : uuidVersion4());
8
9
  return id;
9
10
  };
10
11
 
11
- export interface LuiTextAreaInputProps {
12
+ export interface LuiTextAreaInputProps extends InputHTMLAttributes<HTMLTextAreaElement> {
13
+ // overrides value in base class to be string type only
14
+ value: string;
15
+
16
+ // Custom fields
12
17
  label?: JSX.Element | string;
13
18
  mandatory?: boolean;
14
- inputProps?: InputHTMLAttributes<HTMLTextAreaElement>;
15
- onChange?: ChangeEventHandler<HTMLTextAreaElement>;
16
- value: string;
19
+ helpText?: string;
17
20
  error?: string | boolean | null;
18
21
  }
19
22
 
20
23
  export const TextAreaInput = (props: LuiTextAreaInputProps) => {
21
- const id = useGenerateOrDefaultId(props.inputProps?.id);
24
+ const id = useGenerateOrDefaultId(props?.id);
22
25
 
23
26
  return (
24
27
  <div
25
28
  className={clsx(
26
29
  "LuiTextAreaInput Grid-popoverContainer",
27
- props.inputProps?.disabled ? "isDisabled" : "",
28
- props?.error ? "hasError" : "",
30
+ props.disabled ? "isDisabled" : "",
31
+ props.error ? "hasError" : "",
32
+ props.className,
29
33
  )}
30
34
  >
31
35
  <label htmlFor={id}>
32
- {props.mandatory && <span className="LuiTextAreaInput-mandatory">*</span>}
33
- {props.label && <span className="LuiTextAreaInput-label">{props.label}</span>}
36
+ {props.mandatory != null && <span className="LuiTextAreaInput-mandatory">*</span>}
37
+ {props.label != null && <span className="LuiTextAreaInput-label">{props.label}</span>}
34
38
  <div className="LuiTextAreaInput-wrapper">
35
- {" "}
36
39
  {/* wrapper div used for error styling */}
37
40
  <textarea
38
- id={id}
39
- value={props.value}
40
- onChange={props.onChange}
41
41
  rows={5}
42
- {...props.inputProps}
42
+ {...omit(props, ["error", "value", "helpText", "formatted", "className"])}
43
+ id={id}
44
+ value={props.value ?? ""}
45
+ spellCheck={true}
43
46
  onMouseEnter={(e) => {
44
47
  if (document.activeElement != e.currentTarget) {
45
48
  e.currentTarget.focus();
46
49
  e.currentTarget.selectionStart = e.currentTarget.value.length;
47
50
  }
51
+ props.onMouseEnter && props.onMouseEnter(e);
48
52
  }}
49
- />
53
+ >
54
+ {props.value}
55
+ </textarea>
50
56
  </div>
51
57
  </label>
52
58
 
@@ -57,6 +63,16 @@ export const TextAreaInput = (props: LuiTextAreaInputProps) => {
57
63
  {props.error}
58
64
  </span>
59
65
  )}
66
+
67
+ {props.helpText && !props.error && (
68
+ <span
69
+ style={{
70
+ fontSize: "0.7rem",
71
+ }}
72
+ >
73
+ {props.helpText}
74
+ </span>
75
+ )}
60
76
  </div>
61
77
  );
62
78
  };
@@ -1,55 +1,36 @@
1
1
  import "./TextInputFormatted.scss";
2
2
 
3
- import {
4
- ChangeEventHandler,
5
- DetailedHTMLProps,
6
- FocusEventHandler,
7
- InputHTMLAttributes,
8
- MouseEventHandler,
9
- } from "react";
3
+ import { DetailedHTMLProps, InputHTMLAttributes } from "react";
10
4
 
11
5
  import clsx from "clsx";
12
6
  import { LuiIcon } from "@linzjs/lui";
7
+ import { omit } from "lodash-es";
13
8
 
14
- export interface LuiTextInputProps {
15
- onChange?: ChangeEventHandler<HTMLInputElement>;
16
- onFocus?: FocusEventHandler<HTMLInputElement>;
17
- onClick?: MouseEventHandler<HTMLInputElement>;
18
- inputProps?: DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
19
- error?: string | boolean | null;
20
- warning?: string | boolean | null;
21
-
22
- className?: string;
9
+ export interface LuiTextInputProps extends DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> {
10
+ // overrides value in base class to be string type only
23
11
  value: string;
24
12
 
25
- placeholder?: string;
13
+ // Custom fields
14
+ helpText?: string;
15
+ error?: string | boolean | null;
26
16
  formatted?: string;
27
17
  }
28
18
 
29
19
  export const TextInputFormatted = (props: LuiTextInputProps): JSX.Element => {
30
20
  return (
31
- <div
32
- className={clsx(
33
- "LuiTextInput Grid-popoverContainer",
34
- props.error && "hasError",
35
- props.warning && "hasWarning",
36
- props.className,
37
- )}
38
- >
21
+ <div className={clsx("LuiTextInput Grid-popoverContainer", props.error && "hasError", props.className)}>
39
22
  <span className="LuiTextInput-inputWrapper">
23
+ {/* wrapper div used for error styling */}
40
24
  <input
41
25
  type={"text"}
42
- className={"LuiTextInput-input"}
43
- min="0"
44
26
  spellCheck={true}
45
27
  defaultValue={props.value}
46
- onChange={props.onChange}
47
- onFocus={props.onFocus}
48
- onClick={props.onClick}
28
+ {...omit(props, ["error", "value", "helpText", "formatted", "className"])}
29
+ className={"LuiTextInput-input"}
49
30
  onMouseEnter={(e) => {
50
31
  e.currentTarget.focus();
32
+ props.onMouseEnter && props.onMouseEnter(e);
51
33
  }}
52
- {...props.inputProps}
53
34
  />
54
35
  <span className={"LuiTextInput-formatted"}>{props.formatted}</span>
55
36
  </span>
@@ -61,10 +42,13 @@ export const TextInputFormatted = (props: LuiTextInputProps): JSX.Element => {
61
42
  </span>
62
43
  )}
63
44
 
64
- {props.warning && (
65
- <span className="LuiTextInput-warning">
66
- <LuiIcon alt="warning" name="ic_warning" className="LuiTextInput-warning-icon" size="sm" status="warning" />
67
- {props.warning}
45
+ {props.helpText && !props.error && (
46
+ <span
47
+ style={{
48
+ fontSize: "0.7rem",
49
+ }}
50
+ >
51
+ {props.helpText}
68
52
  </span>
69
53
  )}
70
54
  </div>
@@ -114,7 +114,10 @@ const MenuItemFr = ({
114
114
  eventHandlers.handleClick(event, isCheckBox || isRadio);
115
115
  };
116
116
 
117
- const handleKeyDown = (e: KeyboardEvent) => {
117
+ /**
118
+ * Keyboard events are triggered on up, otherwise sub-components get spaces and enters typed in them
119
+ */
120
+ const handleKeyUp = (e: KeyboardEvent) => {
118
121
  if (!isHovering) return;
119
122
 
120
123
  switch (e.key) {
@@ -144,7 +147,7 @@ const MenuItemFr = ({
144
147
  {
145
148
  ...restStateProps,
146
149
  onPointerDown: setHover,
147
- onKeyDown: handleKeyDown,
150
+ onKeyUp: handleKeyUp,
148
151
  onClick: handleClick,
149
152
  },
150
153
  restProps,
@@ -39,7 +39,10 @@ export const FormTest = (props: CellEditorCommon): JSX.Element => {
39
39
 
40
40
  const [showModal, setShowModal] = useState<boolean>(false);
41
41
 
42
- const { popoverWrapper } = useGridPopoverHook({ className: props.className, save });
42
+ const { popoverWrapper, firstInputKeyboardEventHandlers, lastInputKeyboardEventHandlers } = useGridPopoverHook({
43
+ className: props.className,
44
+ save,
45
+ });
43
46
 
44
47
  return popoverWrapper(
45
48
  <>
@@ -80,10 +83,20 @@ export const FormTest = (props: CellEditorCommon): JSX.Element => {
80
83
  )}
81
84
  <div style={{ display: "flex", flexDirection: "row" }} className={"FormTest Grid-popoverContainer"}>
82
85
  <div className={"FormTest-textInput"}>
83
- <LuiTextInput label={"Name type"} value={nameType} onChange={(e) => setNameType(e.target.value)} />
86
+ <LuiTextInput
87
+ label={"Name type"}
88
+ value={nameType}
89
+ onChange={(e) => setNameType(e.target.value)}
90
+ inputProps={firstInputKeyboardEventHandlers}
91
+ />
84
92
  </div>
85
93
  <div className={"FormTest-textInput"}>
86
- <LuiTextInput label={"Number"} value={numba} onChange={(e) => setNumba(e.target.value)} />
94
+ <LuiTextInput
95
+ label={"Number"}
96
+ value={numba}
97
+ onChange={(e) => setNumba(e.target.value)}
98
+ inputProps={lastInputKeyboardEventHandlers}
99
+ />
87
100
  </div>
88
101
  <div className={"FormTest-textInput"}>
89
102
  <LuiButton onClick={() => setShowModal(true)}>Show Modal</LuiButton>
@@ -258,26 +258,29 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
258
258
  editorParams: {
259
259
  filtered: "local",
260
260
  filterPlaceholder: "Filter this",
261
- options: [
262
- {
263
- value: "one",
264
- label: "One",
265
- },
266
- {
267
- value: "two",
268
- label: "Two",
269
- },
270
- {
271
- value: "oth",
272
- label: "Other",
273
- subComponent: (props) => (
274
- <GridFormSubComponentTextInput {...props} placeholder={"Subcomponent value"} />
275
- ),
276
- },
277
- ],
261
+ options: () => {
262
+ return [
263
+ {
264
+ value: "one",
265
+ label: "One",
266
+ },
267
+ {
268
+ value: "two",
269
+ label: "Two",
270
+ },
271
+ {
272
+ value: "oth",
273
+ label: "Other",
274
+ subComponent: () => (
275
+ <GridFormSubComponentTextInput placeholder={"Other..."} defaultValue={""} required={true} />
276
+ ),
277
+ },
278
+ ];
279
+ },
278
280
  onSelectedItem: async (selected) => {
279
281
  // eslint-disable-next-line no-console
280
282
  console.log("onSelectedItem", selected);
283
+ selected.selectedRows.forEach((row) => (row.sub = selected.subComponentValue ?? selected.value));
281
284
  },
282
285
  },
283
286
  },
@@ -10,7 +10,7 @@ import { Grid, GridProps } from "../../components/Grid";
10
10
  import { useMemo, useState } from "react";
11
11
  import { MenuSeparator } from "../../components/gridForm/GridFormDropDown";
12
12
  import { wait } from "../../utils/util";
13
- import { GridSubComponentTextArea } from "../../components/GridSubComponentTextArea";
13
+ import { GridFormSubComponentTextArea } from "../../components/gridForm/GridFormSubComponentTextArea";
14
14
  import { ColDefT, GridCell } from "../../components/GridCell";
15
15
  import { GridPopoutEditMultiSelect } from "../../components/gridPopoverEdit/GridPopoutEditMultiSelect";
16
16
  import { partition } from "lodash-es";
@@ -81,7 +81,7 @@ const GridEditMultiSelectTemplate: ComponentStory<typeof Grid> = (props: GridPro
81
81
  {
82
82
  value: "other",
83
83
  label: "Other",
84
- subComponent: () => <GridSubComponentTextArea maxLength={5} defaultValue={""} />,
84
+ subComponent: () => <GridFormSubComponentTextArea maxLength={5} defaultValue={""} />,
85
85
  },
86
86
  ],
87
87
  initialSelectedValues: () => ({
@@ -12,8 +12,9 @@ import { wait } from "../../utils/util";
12
12
  import { GridPopoverMenu } from "../../components/gridPopoverEdit/GridPopoverMenu";
13
13
  import { ColDefT, GridCell } from "../../components/GridCell";
14
14
  import { GridPopoverMessage } from "../../components/gridPopoverEdit/GridPopoverMessage";
15
- import { GridSubComponentTextArea } from "../../components/GridSubComponentTextArea";
16
15
  import { MenuOption } from "../../components/gridForm/GridFormPopoverMenu";
16
+ import { GridFormSubComponentTextInput } from "../../components/gridForm/GridFormSubComponentTextInput";
17
+ import { GridFormSubComponentTextArea } from "../../components/gridForm/GridFormSubComponentTextArea";
17
18
 
18
19
  export default {
19
20
  title: "Components / Grids",
@@ -129,13 +130,23 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
129
130
  supportsMultiEdit: true,
130
131
  },
131
132
  {
132
- label: "Other",
133
+ label: "Other (TextInput)",
133
134
  supportsMultiEdit: true,
134
135
  action: (_, menuOptionResult) => {
135
136
  alert(`Sub selected value was ${JSON.stringify(menuOptionResult.subValue)}`);
136
137
  },
137
138
  subComponent: () => (
138
- <GridSubComponentTextArea placeholder={"Other"} maxLength={2} required defaultValue={""} />
139
+ <GridFormSubComponentTextInput placeholder={"Other"} maxLength={2} required defaultValue={""} />
140
+ ),
141
+ },
142
+ {
143
+ label: "Other (TextArea)",
144
+ supportsMultiEdit: true,
145
+ action: (_, menuOptionResult) => {
146
+ alert(`Sub selected value was ${JSON.stringify(menuOptionResult.subValue)}`);
147
+ },
148
+ subComponent: () => (
149
+ <GridFormSubComponentTextArea placeholder={"Other"} maxLength={2} required defaultValue={""} />
139
150
  ),
140
151
  },
141
152
  ] as MenuOption<ITestRow>[];
@@ -162,6 +173,7 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
162
173
  const [rowData] = useState([
163
174
  { id: 1000, position: "Tester", age: 30, desc: "Tests application", dd: "1" },
164
175
  { id: 1001, position: "Developer", age: 12, desc: "Develops application", dd: "2" },
176
+ { id: 1002, position: "Manager", age: 65, desc: "Manages", dd: "3" },
165
177
  ]);
166
178
 
167
179
  return (
@@ -0,0 +1,24 @@
1
+ export interface TextInputValidatorProps {
2
+ required?: boolean;
3
+ maxLength?: number;
4
+ validate?: (value: string) => string | null;
5
+ }
6
+
7
+ export const TextInputValidator = (props: TextInputValidatorProps, value: string | null) => {
8
+ if (value == null) return null;
9
+
10
+ // This can happen because subcomponent is invoked without type safety
11
+ if (typeof value !== "string") {
12
+ console.error("Value is not a string", value);
13
+ }
14
+ if (props.required && value.length === 0) {
15
+ return `Some text is required`;
16
+ }
17
+ if (props.maxLength && value.length > props.maxLength) {
18
+ return `Text must be no longer than ${props.maxLength} characters`;
19
+ }
20
+ if (props.validate) {
21
+ return props.validate(value);
22
+ }
23
+ return null;
24
+ };
@@ -1,10 +0,0 @@
1
- /// <reference types="react" />
2
- export interface GridSubComponentTextAreaProps {
3
- placeholder?: string;
4
- required?: boolean;
5
- maxLength?: number;
6
- width?: string | number;
7
- validate?: (value: string) => string | null;
8
- defaultValue: string;
9
- }
10
- export declare const GridSubComponentTextArea: (props: GridSubComponentTextAreaProps) => JSX.Element;
@@ -1,62 +0,0 @@
1
- import { useCallback, useContext, useEffect } from "react";
2
- import { TextInputFormatted } from "../lui/TextInputFormatted";
3
- import { GridSubComponentContext } from "../contexts/GridSubComponentContext";
4
-
5
- export interface GridSubComponentTextAreaProps {
6
- placeholder?: string;
7
- required?: boolean;
8
- maxLength?: number;
9
- width?: string | number;
10
- validate?: (value: string) => string | null;
11
- defaultValue: string;
12
- }
13
-
14
- export const GridSubComponentTextArea = (props: GridSubComponentTextAreaProps): JSX.Element => {
15
- const { value, setValue, setValid, triggerSave } = useContext(GridSubComponentContext);
16
-
17
- // If is not initialised yet as it's just been created then set the default value
18
- useEffect(() => {
19
- if (value == null) setValue(props.defaultValue);
20
- }, [props.defaultValue, setValue, value]);
21
-
22
- const validate = useCallback(
23
- (value: string | null) => {
24
- if (value == null) return null;
25
- // This can happen because subcomponent is invoked without type safety
26
- if (typeof value !== "string") {
27
- console.error("Value is not a string", value);
28
- }
29
- if (props.required && value.length === 0) {
30
- return `Some text is required`;
31
- }
32
- if (props.maxLength && value.length > props.maxLength) {
33
- return `Text must be no longer than ${props.maxLength} characters`;
34
- }
35
- if (props.validate) {
36
- return props.validate(value);
37
- }
38
- return null;
39
- },
40
- [props],
41
- );
42
-
43
- useEffect(() => {
44
- setValid(value != null && validate(value) == null);
45
- }, [setValid, validate, value]);
46
-
47
- return (
48
- <div className={"FreeTextInput LuiDeprecatedForms"}>
49
- <TextInputFormatted
50
- className={"free-text-input"}
51
- value={value}
52
- onChange={(e) => setValue(e.target.value)}
53
- error={validate(value)}
54
- inputProps={{
55
- autoFocus: true,
56
- placeholder: props.placeholder,
57
- onKeyDown: async (e) => e.key === "Enter" && triggerSave().then(),
58
- }}
59
- />
60
- </div>
61
- );
62
- };