@ramesesinc/platform-core 0.1.5 → 0.1.8

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 (91) hide show
  1. package/dist/components/action/LookupPage.js +9 -31
  2. package/dist/components/action/ViewPage.d.ts +2 -0
  3. package/dist/components/action/ViewPage.js +25 -31
  4. package/dist/components/common/UIComponent.js +4 -3
  5. package/dist/components/index.d.ts +1 -1
  6. package/dist/components/index.js +1 -1
  7. package/dist/components/table/DataList.js +2 -2
  8. package/dist/components/view/PopupView.d.ts +13 -0
  9. package/dist/components/view/PopupView.js +25 -20
  10. package/dist/core/DataContext.d.ts +7 -4
  11. package/dist/core/DataContext.js +16 -4
  12. package/dist/core/Page.js +25 -26
  13. package/dist/core/PageCache.js +16 -3
  14. package/dist/core/PageContext.js +90 -18
  15. package/dist/core/PageViewContext.d.ts +13 -1
  16. package/dist/core/PageViewContext.js +89 -5
  17. package/dist/core/PopupContext.d.ts +49 -0
  18. package/dist/core/PopupContext.js +380 -0
  19. package/dist/core/RowContext.js +1 -1
  20. package/dist/core/WindowContext.d.ts +15 -0
  21. package/dist/core/WindowContext.js +28 -0
  22. package/dist/core/index.d.ts +16 -0
  23. package/dist/index.css +25 -7
  24. package/dist/lib/utils/BeanUtils.js +7 -7
  25. package/dist/templates/DataListTemplate.js +7 -2
  26. package/dist/templates/ExplorerTemplate.js +1 -1
  27. package/package.json +5 -5
  28. package/dist/components/action/AlertMessage.tsx +0 -38
  29. package/dist/components/action/Button.tsx +0 -230
  30. package/dist/components/action/CancelEdit.tsx +0 -40
  31. package/dist/components/action/DeleteData.tsx +0 -73
  32. package/dist/components/action/Edit.tsx +0 -40
  33. package/dist/components/action/LookupPage.tsx +0 -113
  34. package/dist/components/action/ProcessRunner.tsx +0 -337
  35. package/dist/components/action/Refresh.tsx +0 -35
  36. package/dist/components/action/SaveData.tsx +0 -74
  37. package/dist/components/action/SelectData.tsx +0 -47
  38. package/dist/components/action/Undo.tsx +0 -50
  39. package/dist/components/action/UpdateContext.tsx +0 -40
  40. package/dist/components/action/UpdateData.tsx +0 -49
  41. package/dist/components/action/ViewBackPage.tsx +0 -46
  42. package/dist/components/action/ViewPage.tsx +0 -141
  43. package/dist/components/common/UIComponent.tsx +0 -86
  44. package/dist/components/common/UIInput.tsx +0 -49
  45. package/dist/components/common/UIMenu.tsx +0 -91
  46. package/dist/components/index.ts +0 -51
  47. package/dist/components/input/CodeEditor.tsx +0 -188
  48. package/dist/components/input/DateField.tsx +0 -274
  49. package/dist/components/input/DayPicker.tsx +0 -5
  50. package/dist/components/input/HtmlCode.tsx +0 -203
  51. package/dist/components/input/JsonCode.tsx +0 -205
  52. package/dist/components/input/MonthPicker.tsx +0 -5
  53. package/dist/components/input/ScriptCode.tsx +0 -195
  54. package/dist/components/input/Select.tsx +0 -78
  55. package/dist/components/input/SqlCode.tsx +0 -162
  56. package/dist/components/input/StringDecision.tsx +0 -64
  57. package/dist/components/input/Text.tsx +0 -57
  58. package/dist/components/input/YearPicker.tsx +0 -81
  59. package/dist/components/list/IconMenu.tsx +0 -115
  60. package/dist/components/list/TabMenu.tsx +0 -127
  61. package/dist/components/list/TreeMenu.tsx +0 -279
  62. package/dist/components/list/TxnTaskList.tsx +0 -198
  63. package/dist/components/output/Label.tsx +0 -50
  64. package/dist/components/table/DataList.tsx +0 -820
  65. package/dist/components/table/DataTable.tsx +0 -572
  66. package/dist/components/table/ListHandler.ts +0 -276
  67. package/dist/components/table/TableContext.tsx +0 -122
  68. package/dist/components/view/ComponentView.tsx +0 -102
  69. package/dist/components/view/FilterView.tsx +0 -21
  70. package/dist/components/view/HtmlForm.tsx +0 -176
  71. package/dist/components/view/HtmlView.tsx +0 -98
  72. package/dist/components/view/IFrameView.tsx +0 -48
  73. package/dist/components/view/Modal.tsx +0 -72
  74. package/dist/components/view/PageView.tsx +0 -131
  75. package/dist/components/view/PopupView.tsx +0 -160
  76. package/dist/components/view/RootView.tsx +0 -109
  77. package/dist/components/view/WizardView.tsx +0 -48
  78. package/dist/lib/layouts/BorderLayout.tsx +0 -31
  79. package/dist/lib/layouts/CardLayout.tsx +0 -73
  80. package/dist/lib/layouts/CenterLayout.tsx +0 -20
  81. package/dist/lib/layouts/GridLayout.tsx +0 -20
  82. package/dist/lib/layouts/HPanel.tsx +0 -31
  83. package/dist/lib/layouts/HorizontalLayout.tsx +0 -29
  84. package/dist/lib/layouts/MainLayout.tsx +0 -16
  85. package/dist/lib/layouts/PageLayout.tsx +0 -29
  86. package/dist/lib/layouts/VPanel.tsx +0 -27
  87. package/dist/lib/layouts/XLayout.tsx +0 -29
  88. package/dist/lib/layouts/YLayout.tsx +0 -29
  89. package/dist/lib/layouts/index.ts +0 -13
  90. /package/dist/components/action/{UpdateContext.d.ts → UpdateState.d.ts} +0 -0
  91. /package/dist/components/action/{UpdateContext.js → UpdateState.js} +0 -0
@@ -1,195 +0,0 @@
1
- import Editor from "@monaco-editor/react";
2
- import { useCallback, useEffect, useRef, useState } from "react";
3
- import { usePageContext } from "../../core/PageContext";
4
- import CopyButton from "../../lib/components/CopyButton";
5
- import UIComponent from "../common/UIComponent";
6
- import useUIInput, { UIInputProps } from "../common/UIInput";
7
-
8
- type ScriptCodeProps = UIInputProps & {
9
- height?: number | string;
10
- width?: number | string;
11
- showCopy?: boolean;
12
- };
13
-
14
- const ScriptCode = (props: ScriptCodeProps) => {
15
- const { height = 300, width = "100%", showCopy = true } = props ?? {};
16
-
17
- const pageContext = usePageContext();
18
- const editorRef = useRef<any>(null);
19
- const [fontSize, setFontSize] = useState(14);
20
- const [error, setError] = useState("");
21
- const [readOnly, setReadOnly] = useState(true);
22
-
23
- const onRefresh = () => {
24
- const val = getValue();
25
- setEditorValue(val ?? "");
26
- };
27
-
28
- const { initialValue, getValue, setValue } = useUIInput({ ...props, onRefresh });
29
-
30
- const [editorValue, setEditorValue] = useState(() => initialValue ?? "");
31
-
32
- useEffect(() => {
33
- const unsubscribe = pageContext?.dependsTo("editable", (val: any) => {
34
- const isEditable = val === true || val === "true";
35
- setReadOnly(!isEditable);
36
-
37
- if (!isEditable) {
38
- setEditorValue(getValue() ?? "");
39
- setError("");
40
- }
41
- });
42
- return unsubscribe;
43
- }, []);
44
-
45
- useEffect(() => {
46
- return () => {
47
- editorRef.current = null;
48
- };
49
- }, []);
50
-
51
- const handleKeyDown = useCallback((e: KeyboardEvent) => {
52
- if (e.ctrlKey && e.key === "=") {
53
- e.preventDefault();
54
- setFontSize((prev) => Math.min(prev + 1, 40));
55
- }
56
- if (e.ctrlKey && e.key === "-") {
57
- e.preventDefault();
58
- setFontSize((prev) => Math.max(prev - 1, 8));
59
- }
60
- if (e.ctrlKey && e.key === "0") {
61
- e.preventDefault();
62
- setFontSize(14);
63
- }
64
- }, []);
65
-
66
- useEffect(() => {
67
- window.addEventListener("keydown", handleKeyDown);
68
- return () => window.removeEventListener("keydown", handleKeyDown);
69
- }, [handleKeyDown]);
70
-
71
- useEffect(() => {
72
- editorRef.current?.updateOptions({ fontSize });
73
- }, [fontSize]);
74
-
75
- useEffect(() => {
76
- editorRef.current?.updateOptions({ readOnly, domReadOnly: readOnly });
77
- }, [readOnly]);
78
-
79
- const validateScript = (code: string) => {
80
- if (!code.trim()) {
81
- setError("");
82
- return;
83
- }
84
-
85
- const errors: string[] = [];
86
- const lines = code.split("\n");
87
-
88
- let braceCount = 0;
89
- let parenCount = 0;
90
- let bracketCount = 0;
91
-
92
- for (let i = 0; i < lines.length; i++) {
93
- const line = lines[i];
94
- const lineNum = i + 1;
95
-
96
- for (const char of line) {
97
- if (char === "{") braceCount++;
98
- if (char === "}") braceCount--;
99
- if (char === "(") parenCount++;
100
- if (char === ")") parenCount--;
101
- if (char === "[") bracketCount++;
102
- if (char === "]") bracketCount--;
103
- }
104
-
105
- if (line.trim().match(/^(let|const|var)\s+\w+\s*=.*[^;{}\s]$/)) {
106
- errors.push(`Line ${lineNum}: Possible missing semicolon`);
107
- }
108
-
109
- if (line.includes("console.log") && !line.trim().endsWith(";") && !line.trim().endsWith("{")) {
110
- errors.push(`Line ${lineNum}: Missing semicolon after console.log`);
111
- }
112
- }
113
-
114
- if (braceCount !== 0) errors.push(`Unmatched braces: ${braceCount > 0 ? "missing closing" : "missing opening"} brace(s)`);
115
-
116
- if (parenCount !== 0) errors.push(`Unmatched parentheses: ${parenCount > 0 ? "missing closing" : "missing opening"}`);
117
-
118
- if (bracketCount !== 0) errors.push(`Unmatched brackets: ${bracketCount > 0 ? "missing closing" : "missing opening"}`);
119
-
120
- setError(errors.length > 0 ? errors.join("\n• ") : "");
121
- };
122
-
123
- const handleEditorChange = (value?: string) => {
124
- if (readOnly) return;
125
- const safeValue = value ?? "";
126
- setEditorValue(safeValue);
127
- setValue(safeValue); // JavaScript is always a string, write through immediately
128
- validateScript(safeValue);
129
- };
130
-
131
- const handleEditorDidMount = (editor: any) => {
132
- editorRef.current = editor;
133
-
134
- editor.updateOptions({
135
- minimap: { enabled: false },
136
- fontSize,
137
- lineNumbers: "on",
138
- renderWhitespace: "selection",
139
- folding: true,
140
- bracketPairColorization: { enabled: true },
141
- formatOnPaste: true,
142
- formatOnType: true,
143
- });
144
- };
145
-
146
- return (
147
- <UIComponent {...(props ?? {})}>
148
- <div className="relative w-full bg-white">
149
- {showCopy && (
150
- <div className="absolute top-2 right-4 z-50">
151
- <CopyButton item={editorValue} copySize={15} copiedSize={10} classNameCopied="!px-[15px] !py-[10px]" />
152
- </div>
153
- )}
154
- <Editor
155
- key="script-code-editor"
156
- height={height}
157
- width={width}
158
- language="javascript"
159
- value={editorValue}
160
- onChange={handleEditorChange}
161
- onMount={handleEditorDidMount}
162
- theme="vs-dark"
163
- options={{
164
- readOnly,
165
- domReadOnly: readOnly,
166
- padding: { top: 10 },
167
- selectOnLineNumbers: true,
168
- automaticLayout: true,
169
- minimap: { enabled: false },
170
- fontSize,
171
- wordWrap: "off",
172
- lineNumbers: "on",
173
- renderWhitespace: "selection",
174
- folding: true,
175
- bracketPairColorization: { enabled: true },
176
- formatOnPaste: true,
177
- formatOnType: true,
178
- scrollBeyondLastLine: false,
179
- smoothScrolling: true,
180
- cursorBlinking: "smooth",
181
- renderLineHighlight: "all",
182
- autoIndent: "full",
183
- suggestOnTriggerCharacters: true,
184
- quickSuggestions: true,
185
- parameterHints: { enabled: true },
186
- scrollbar: { vertical: "visible", horizontal: "visible" },
187
- }}
188
- />
189
- {error && !readOnly && <div className="mt-2 text-sm text-red-500 whitespace-pre-wrap">• {error}</div>}
190
- </div>
191
- </UIComponent>
192
- );
193
- };
194
-
195
- export default ScriptCode;
@@ -1,78 +0,0 @@
1
- import { useRef, useState } from "react";
2
- import UIComponent from "../common/UIComponent";
3
- import useUIInput, { UIInputProps } from "../common/UIInput";
4
-
5
- type SelectOption = {
6
- label: string;
7
- value: string;
8
- };
9
-
10
- type SelectFieldProps = UIInputProps & {
11
- required?: boolean;
12
- immediate?: boolean;
13
- options?: SelectOption[];
14
- placeholder?: string;
15
- onChange?: (value: string) => void;
16
- };
17
-
18
- const SelectField = (props: SelectFieldProps) => {
19
- const { immediate = true, options = [], placeholder } = props ?? {};
20
- const [focused, setFocused] = useState(false);
21
- const selectRef = useRef<HTMLSelectElement | null>(null);
22
- const valueRef = useRef<string>("");
23
-
24
- const className = "border rounded px-2 py-1 w-full";
25
-
26
- const handleFocus = () => {
27
- setFocused(true);
28
- };
29
-
30
- const handleBlur = () => {
31
- if (!immediate) {
32
- setValue(selectValue);
33
- }
34
- setFocused(false);
35
- };
36
-
37
- const onRefresh = () => {
38
- setSelectValue(getValue());
39
- };
40
-
41
- const { initialValue, getValue, setValue, binding } = useUIInput({ ...props, onRefresh });
42
- valueRef.current = initialValue ?? "";
43
- const [selectValue, setSelectValue] = useState(valueRef.current);
44
-
45
- const onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
46
- const text = e.target.value ?? "";
47
-
48
- if (text !== selectValue) {
49
- valueRef.current = text;
50
- setSelectValue(valueRef.current);
51
- }
52
-
53
- if (immediate) {
54
- setValue(text);
55
- }
56
-
57
- props.onChange?.(text);
58
- };
59
-
60
- return (
61
- <UIComponent {...(props ?? {})}>
62
- <select ref={selectRef} onChange={onChange} value={selectValue} onFocus={handleFocus} onBlur={handleBlur} className={className}>
63
- {placeholder && (
64
- <option value="" disabled>
65
- {placeholder}
66
- </option>
67
- )}
68
- {options.map((opt) => (
69
- <option key={opt.value} value={opt.value}>
70
- {opt.label}
71
- </option>
72
- ))}
73
- </select>
74
- </UIComponent>
75
- );
76
- };
77
-
78
- export default SelectField;
@@ -1,162 +0,0 @@
1
- import Editor from "@monaco-editor/react";
2
- import { useCallback, useEffect, useRef, useState } from "react";
3
- import { usePageContext } from "../../core/PageContext";
4
- import CopyButton from "../../lib/components/CopyButton";
5
- import UIComponent from "../common/UIComponent";
6
- import useUIInput, { UIInputProps } from "../common/UIInput";
7
-
8
- type SqlCodeProps = UIInputProps & {
9
- height?: number | string;
10
- width?: number | string;
11
- showCopy?: boolean;
12
- };
13
-
14
- const SqlCode = (props: SqlCodeProps) => {
15
- const { height = 300, width = "100%", showCopy = true } = props ?? {};
16
-
17
- const pageContext = usePageContext();
18
- const editorRef = useRef<any>(null);
19
- const [fontSize, setFontSize] = useState(14);
20
- const [error, setError] = useState("");
21
- const [readOnly, setReadOnly] = useState(true);
22
-
23
- const onRefresh = () => {
24
- const val = getValue();
25
- setEditorValue(val ?? "");
26
- };
27
-
28
- const { initialValue, getValue, setValue } = useUIInput({ ...props, onRefresh });
29
-
30
- const [editorValue, setEditorValue] = useState(() => initialValue ?? "");
31
-
32
- useEffect(() => {
33
- const unsubscribe = pageContext?.dependsTo("editable", (val: any) => {
34
- const isEditable = val === true || val === "true";
35
- setReadOnly(!isEditable);
36
-
37
- if (!isEditable) {
38
- setEditorValue(getValue() ?? "");
39
- setError("");
40
- }
41
- });
42
- return unsubscribe;
43
- }, []);
44
-
45
- useEffect(() => {
46
- return () => {
47
- editorRef.current = null;
48
- };
49
- }, []);
50
-
51
- const handleKeyDown = useCallback((e: KeyboardEvent) => {
52
- if (e.ctrlKey && e.key === "=") {
53
- e.preventDefault();
54
- setFontSize((prev) => Math.min(prev + 1, 40));
55
- }
56
- if (e.ctrlKey && e.key === "-") {
57
- e.preventDefault();
58
- setFontSize((prev) => Math.max(prev - 1, 8));
59
- }
60
- if (e.ctrlKey && e.key === "0") {
61
- e.preventDefault();
62
- setFontSize(14);
63
- }
64
- }, []);
65
-
66
- useEffect(() => {
67
- window.addEventListener("keydown", handleKeyDown);
68
- return () => window.removeEventListener("keydown", handleKeyDown);
69
- }, [handleKeyDown]);
70
-
71
- useEffect(() => {
72
- editorRef.current?.updateOptions({ fontSize });
73
- }, [fontSize]);
74
-
75
- useEffect(() => {
76
- editorRef.current?.updateOptions({ readOnly, domReadOnly: readOnly });
77
- }, [readOnly]);
78
-
79
- const validateSql = (value: string) => {
80
- if (!value.trim()) {
81
- setError("");
82
- return;
83
- }
84
- const forbidden = /drop\s+table|delete\s+from/gi;
85
- if (forbidden.test(value)) {
86
- setError("Dangerous SQL statement detected.");
87
- } else {
88
- setError("");
89
- }
90
- };
91
-
92
- const handleEditorChange = (value?: string) => {
93
- if (readOnly) return;
94
- const safeValue = value ?? "";
95
- setEditorValue(safeValue);
96
- setValue(safeValue); // SQL is always a string, write through immediately
97
- validateSql(safeValue);
98
- };
99
-
100
- const handleEditorDidMount = (editor: any, monaco: any) => {
101
- editorRef.current = editor;
102
-
103
- monaco.languages.register({ id: "sql" });
104
-
105
- editor.updateOptions({
106
- minimap: { enabled: false },
107
- fontSize,
108
- lineNumbers: "on",
109
- renderWhitespace: "selection",
110
- folding: true,
111
- bracketPairColorization: { enabled: true },
112
- formatOnPaste: true,
113
- formatOnType: true,
114
- });
115
- };
116
-
117
- return (
118
- <UIComponent {...(props ?? {})}>
119
- <div className="relative w-full bg-white">
120
- {showCopy && (
121
- <div className="absolute top-2 right-4 z-50">
122
- <CopyButton item={editorValue} copySize={15} copiedSize={10} classNameCopied="!px-[15px] !py-[10px]" />
123
- </div>
124
- )}
125
- <Editor
126
- key="sql-code-editor"
127
- height={height}
128
- width={width}
129
- language="sql"
130
- value={editorValue}
131
- onChange={handleEditorChange}
132
- onMount={handleEditorDidMount}
133
- theme="vs-dark"
134
- options={{
135
- readOnly,
136
- domReadOnly: readOnly,
137
- padding: { top: 10 },
138
- selectOnLineNumbers: true,
139
- automaticLayout: true,
140
- minimap: { enabled: false },
141
- fontSize,
142
- wordWrap: "off",
143
- lineNumbers: "on",
144
- renderWhitespace: "selection",
145
- folding: true,
146
- bracketPairColorization: { enabled: true },
147
- formatOnPaste: true,
148
- formatOnType: true,
149
- scrollBeyondLastLine: false,
150
- smoothScrolling: true,
151
- cursorBlinking: "smooth",
152
- renderLineHighlight: "all",
153
- scrollbar: { vertical: "visible", horizontal: "visible" },
154
- }}
155
- />
156
- {error && !readOnly && <p className="text-red-500 text-xs mt-1 px-1">{error}</p>}
157
- </div>
158
- </UIComponent>
159
- );
160
- };
161
-
162
- export default SqlCode;
@@ -1,64 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import { usePageContext } from "../../core/PageContext";
3
- import UIComponent from "../common/UIComponent";
4
-
5
- const operators = [
6
- { label: "Matches", value: "matches" },
7
- { label: "Equals", value: "equals" },
8
- { label: "Not Equals", value: "neq" },
9
- ];
10
-
11
- const StringDecision = (props: Record<string, any>) => {
12
- const { name } = props ?? {};
13
- const [inputOp, setInputOp] = useState("");
14
- const [inputValue, setInputValue] = useState("");
15
- const pageContext = usePageContext();
16
- const binding = pageContext?.binding;
17
-
18
- const inputClassName = "border rounded px-2 py-1 w-full";
19
- const selectClassName =
20
- "px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed";
21
-
22
- const handleChangeOperator = (e: React.ChangeEvent<HTMLSelectElement>) => {
23
- setInputOp(e.target.value);
24
- };
25
-
26
- const handleChangeValue = (e: React.ChangeEvent<HTMLInputElement>) => {
27
- setInputValue(e.target.value);
28
- };
29
-
30
- useEffect(() => {
31
- if (name && inputOp && inputValue) {
32
- pageContext?.set(name, { [inputOp]: inputValue });
33
- } else if (name && (!inputOp || !inputValue)) {
34
- pageContext?.set(name, null);
35
- }
36
- }, [name, inputOp, inputValue, pageContext, binding]);
37
-
38
- return (
39
- <UIComponent {...(props ?? {})}>
40
- <div className="flex gap-4 items-center justify-center">
41
- <select value={inputOp} onChange={handleChangeOperator} className={selectClassName}>
42
- <option value="">Select operator</option>
43
- {operators.map((op) => (
44
- <option key={op.value} value={op.value}>
45
- {op.label}
46
- </option>
47
- ))}
48
- </select>
49
- {/* <Select
50
- options={operators}
51
- placeholder="Select operator"
52
- onChange={(value: string) => setInputOp(value)}
53
- name={""}
54
- onRefresh={function (): void {
55
- throw new Error("Function not implemented.");
56
- }}
57
- /> */}
58
- <input type="text" value={inputValue} onChange={handleChangeValue} className={inputClassName} placeholder="Enter value" />
59
- </div>
60
- </UIComponent>
61
- );
62
- };
63
-
64
- export default StringDecision;
@@ -1,57 +0,0 @@
1
- import { useRef, useState } from "react";
2
- import UIComponent from "../common/UIComponent";
3
- import useUIInput, { UIInputProps } from "../common/UIInput";
4
-
5
- type TextFieldProps = UIInputProps & {
6
- required?: boolean;
7
- immediate?: boolean;
8
- };
9
-
10
- const TextField = (props: TextFieldProps) => {
11
- const { name, immediate = true } = props ?? {};
12
- const [focused, setFocused] = useState(false);
13
- const inputRef = useRef<HTMLInputElement | null>(null);
14
- const valueRef = useRef<string>("");
15
-
16
- const className = "border rounded px-2 py-1 w-full";
17
-
18
- const handleFocus = () => {
19
- setFocused(true);
20
- };
21
-
22
- const handleBlur = () => {
23
- if (!immediate) {
24
- setValue(inputValue);
25
- }
26
- setFocused(false);
27
- };
28
-
29
- const onRefresh = () => {
30
- setInputValue(getValue());
31
- };
32
-
33
- const { initialValue, getValue, setValue, binding } = useUIInput({ ...props, onRefresh });
34
- valueRef.current = initialValue ?? "";
35
- const [inputValue, setInputValue] = useState(valueRef.current);
36
-
37
- const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
38
- const text = e.target.value ?? "";
39
-
40
- if (text !== inputValue) {
41
- valueRef.current = text;
42
- setInputValue(valueRef.current);
43
- }
44
-
45
- if (immediate) {
46
- setValue(text);
47
- }
48
- };
49
-
50
- return (
51
- <UIComponent {...(props ?? {})}>
52
- <input type="text" ref={inputRef} onChange={onChange} value={inputValue} onFocus={handleFocus} onBlur={handleBlur} className={className} />
53
- </UIComponent>
54
- );
55
- };
56
-
57
- export default TextField;
@@ -1,81 +0,0 @@
1
- import { useEffect, useRef, useState } from "react";
2
- import UIComponent from "../common/UIComponent";
3
- import useUIInput, { UIInputProps } from "../common/UIInput";
4
-
5
- type YearPickerProps = UIInputProps & {
6
- min?: number;
7
- max?: number;
8
- immediate?: boolean;
9
- };
10
-
11
- const YearPicker = (props: YearPickerProps) => {
12
- const { min = 1900, max, immediate = true } = props ?? {};
13
- const valueRef = useRef<string>("");
14
- const [focused, setFocused] = useState(false);
15
-
16
- // Set default max to current year if not provided
17
- const currentYear = new Date().getFullYear();
18
- const maxYear = max || currentYear;
19
-
20
- // Generate array of years (descending order)
21
- const years = Array.from({ length: maxYear - min + 1 }, (_, i) => maxYear - i);
22
-
23
- const onRefresh = () => {
24
- setInputValue(getValue());
25
- };
26
-
27
- const { initialValue, getValue, setValue } = useUIInput({ ...props, onRefresh });
28
- valueRef.current = initialValue ?? "";
29
- const [inputValue, setInputValue] = useState(valueRef.current);
30
-
31
- const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
32
- const year = e.target.value;
33
-
34
- if (year !== inputValue) {
35
- valueRef.current = year;
36
- setInputValue(valueRef.current);
37
- }
38
-
39
- if (immediate) {
40
- setValue(year);
41
- }
42
- };
43
-
44
- const handleFocus = () => {
45
- setFocused(true);
46
- };
47
-
48
- const handleBlur = () => {
49
- if (!immediate) {
50
- setValue(inputValue);
51
- }
52
- setFocused(false);
53
- };
54
-
55
- useEffect(() => {
56
- // console.log("inputValue", inputValue);
57
- }, [inputValue]);
58
-
59
- return (
60
- <UIComponent {...(props ?? {})}>
61
- <div className="flex flex-col gap-1">
62
- <select
63
- value={inputValue}
64
- onChange={handleChange}
65
- onFocus={handleFocus}
66
- onBlur={handleBlur}
67
- className="px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
68
- >
69
- <option value="">Select year</option>
70
- {years.map((year) => (
71
- <option key={year} value={year}>
72
- {year}
73
- </option>
74
- ))}
75
- </select>
76
- </div>
77
- </UIComponent>
78
- );
79
- };
80
-
81
- export default YearPicker;