@ramesesinc/platform-core 0.1.6 → 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 (87) 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/table/DataList.js +2 -2
  6. package/dist/components/view/PopupView.d.ts +13 -0
  7. package/dist/components/view/PopupView.js +25 -20
  8. package/dist/core/DataContext.d.ts +7 -4
  9. package/dist/core/DataContext.js +16 -4
  10. package/dist/core/Page.js +25 -26
  11. package/dist/core/PageCache.js +7 -7
  12. package/dist/core/PageContext.js +17 -7
  13. package/dist/core/PageViewContext.d.ts +13 -1
  14. package/dist/core/PageViewContext.js +75 -2
  15. package/dist/core/PopupContext.d.ts +49 -0
  16. package/dist/core/PopupContext.js +380 -0
  17. package/dist/core/RowContext.js +1 -1
  18. package/dist/core/WindowContext.d.ts +15 -0
  19. package/dist/core/WindowContext.js +28 -0
  20. package/dist/core/index.d.ts +16 -0
  21. package/dist/index.css +25 -7
  22. package/dist/lib/utils/BeanUtils.js +7 -7
  23. package/dist/templates/DataListTemplate.js +7 -2
  24. package/dist/templates/ExplorerTemplate.js +1 -1
  25. package/package.json +5 -5
  26. package/dist/components/action/AlertMessage.tsx +0 -38
  27. package/dist/components/action/Button.tsx +0 -230
  28. package/dist/components/action/CancelEdit.tsx +0 -40
  29. package/dist/components/action/DeleteData.tsx +0 -73
  30. package/dist/components/action/Edit.tsx +0 -40
  31. package/dist/components/action/LookupPage.tsx +0 -113
  32. package/dist/components/action/ProcessRunner.tsx +0 -337
  33. package/dist/components/action/Refresh.tsx +0 -35
  34. package/dist/components/action/SaveData.tsx +0 -74
  35. package/dist/components/action/SelectData.tsx +0 -47
  36. package/dist/components/action/Undo.tsx +0 -50
  37. package/dist/components/action/UpdateData.tsx +0 -49
  38. package/dist/components/action/UpdateState.tsx +0 -40
  39. package/dist/components/action/ViewBackPage.tsx +0 -46
  40. package/dist/components/action/ViewPage.tsx +0 -141
  41. package/dist/components/common/UIComponent.tsx +0 -86
  42. package/dist/components/common/UIInput.tsx +0 -49
  43. package/dist/components/common/UIMenu.tsx +0 -91
  44. package/dist/components/index.ts +0 -51
  45. package/dist/components/input/CodeEditor.tsx +0 -188
  46. package/dist/components/input/DateField.tsx +0 -274
  47. package/dist/components/input/DayPicker.tsx +0 -5
  48. package/dist/components/input/HtmlCode.tsx +0 -203
  49. package/dist/components/input/JsonCode.tsx +0 -205
  50. package/dist/components/input/MonthPicker.tsx +0 -5
  51. package/dist/components/input/ScriptCode.tsx +0 -195
  52. package/dist/components/input/Select.tsx +0 -78
  53. package/dist/components/input/SqlCode.tsx +0 -162
  54. package/dist/components/input/StringDecision.tsx +0 -64
  55. package/dist/components/input/Text.tsx +0 -57
  56. package/dist/components/input/YearPicker.tsx +0 -81
  57. package/dist/components/list/IconMenu.tsx +0 -115
  58. package/dist/components/list/TabMenu.tsx +0 -127
  59. package/dist/components/list/TreeMenu.tsx +0 -279
  60. package/dist/components/list/TxnTaskList.tsx +0 -198
  61. package/dist/components/output/Label.tsx +0 -50
  62. package/dist/components/table/DataList.tsx +0 -820
  63. package/dist/components/table/DataTable.tsx +0 -572
  64. package/dist/components/table/ListHandler.ts +0 -276
  65. package/dist/components/table/TableContext.tsx +0 -122
  66. package/dist/components/view/ComponentView.tsx +0 -102
  67. package/dist/components/view/FilterView.tsx +0 -21
  68. package/dist/components/view/HtmlForm.tsx +0 -176
  69. package/dist/components/view/HtmlView.tsx +0 -98
  70. package/dist/components/view/IFrameView.tsx +0 -48
  71. package/dist/components/view/Modal.tsx +0 -72
  72. package/dist/components/view/PageView.tsx +0 -131
  73. package/dist/components/view/PopupView.tsx +0 -160
  74. package/dist/components/view/RootView.tsx +0 -109
  75. package/dist/components/view/WizardView.tsx +0 -48
  76. package/dist/lib/layouts/BorderLayout.tsx +0 -31
  77. package/dist/lib/layouts/CardLayout.tsx +0 -73
  78. package/dist/lib/layouts/CenterLayout.tsx +0 -20
  79. package/dist/lib/layouts/GridLayout.tsx +0 -20
  80. package/dist/lib/layouts/HPanel.tsx +0 -31
  81. package/dist/lib/layouts/HorizontalLayout.tsx +0 -29
  82. package/dist/lib/layouts/MainLayout.tsx +0 -16
  83. package/dist/lib/layouts/PageLayout.tsx +0 -29
  84. package/dist/lib/layouts/VPanel.tsx +0 -27
  85. package/dist/lib/layouts/XLayout.tsx +0 -29
  86. package/dist/lib/layouts/YLayout.tsx +0 -29
  87. package/dist/lib/layouts/index.ts +0 -13
@@ -1,49 +0,0 @@
1
- "use client";
2
-
3
- import { usePageContext } from "../../core/PageContext";
4
- import { getValue } from "../../lib/utils/BeanUtils";
5
- import { AbstractComponent } from "../../types/component";
6
-
7
- /* ------------------------------------------------------------------ */
8
- /* Types */
9
-
10
- interface UpdateDataProps extends AbstractComponent {
11
- className?: string;
12
- title?: string;
13
- api: string;
14
- data?: string;
15
- }
16
-
17
- /* ------------------------------------------------------------------ */
18
- /* Component */
19
-
20
- const UpdateData = (props: UpdateDataProps) => {
21
- const { className = "", title, api, data } = props ?? {};
22
- const pageContext = usePageContext();
23
-
24
- /* ---------------------- Events ---------------------- */
25
- const handleClick = async () => {
26
- try {
27
- if (!api) throw new Error("api not defined");
28
- if (data) {
29
- const allData = pageContext?.getAllData() ?? {};
30
- const d = getValue(data, allData);
31
- await pageContext?.execService(api, d);
32
- } else {
33
- const vdata = pageContext?.getData() ?? {};
34
- await pageContext?.execService(api, vdata);
35
- }
36
- } catch (err: any) {
37
- alert(err.message);
38
- }
39
- };
40
-
41
- /* ---------------------- Render ---------------------- */
42
- return (
43
- <button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
44
- {title || "Update Context"}
45
- </button>
46
- );
47
- };
48
-
49
- export default UpdateData;
@@ -1,40 +0,0 @@
1
- "use client";
2
-
3
- import { usePageContext } from "../../core/PageContext";
4
- import { AbstractComponent } from "../../types/component";
5
-
6
- /* ------------------------------------------------------------------ */
7
- /* Types */
8
-
9
- interface UpdateContextProps extends AbstractComponent {
10
- source: string;
11
- target: string;
12
- className?: string;
13
- title?: string;
14
- }
15
-
16
- /* ------------------------------------------------------------------ */
17
- /* Component */
18
-
19
- const UpdateContext = (props: UpdateContextProps) => {
20
- const { source, target, className = "", title } = props ?? {};
21
-
22
- const pageContext = usePageContext();
23
-
24
- /* ---------------------- Events ---------------------- */
25
- const handleClick = () => {
26
- if (!source || !target) return;
27
- const allData = pageContext?.getAllData() ?? {};
28
- const value = allData[source];
29
- pageContext?.set(target, value);
30
- };
31
-
32
- /* ---------------------- Render ---------------------- */
33
- return (
34
- <button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
35
- {title || "Update Context"}
36
- </button>
37
- );
38
- };
39
-
40
- export default UpdateContext;
@@ -1,46 +0,0 @@
1
- "use client";
2
-
3
- import { usePageViewContext } from "../../core/PageViewContext";
4
- import { AbstractComponent } from "../../types/component";
5
-
6
- /* ------------------------------------------------------------------ */
7
- /* Types */
8
-
9
- interface ViewBackPageProps extends AbstractComponent {
10
- className?: string;
11
- title?: string;
12
- icon?: string;
13
- opt?: Record<string, any>;
14
- }
15
-
16
- /* ------------------------------------------------------------------ */
17
- /* Component */
18
-
19
- const ViewBackPage = (props: ViewBackPageProps) => {
20
- const { className = "", title, icon, opt = {} } = props ?? {};
21
-
22
- const pageView = usePageViewContext();
23
-
24
- /* ---------------------- Events ---------------------- */
25
- const handleClick = () => {
26
- pageView?.popPage();
27
- };
28
-
29
- const hasBackPage = () => {
30
- return pageView == null ? false : pageView.hasBackPage();
31
- };
32
-
33
- /* ---------------------- Render ---------------------- */
34
- return (
35
- <>
36
- {hasBackPage() && (
37
- <button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
38
- {icon && <span className="dl-action-icon">{icon}</span>}
39
- {title || "Back"}
40
- </button>
41
- )}
42
- </>
43
- );
44
- };
45
-
46
- export default ViewBackPage;
@@ -1,141 +0,0 @@
1
- "use client";
2
-
3
- import React, { forwardRef, memo, useImperativeHandle, useRef, useState } from "react";
4
- import { useDataContext } from "../../core/DataContext";
5
- import { usePageContext } from "../../core/PageContext";
6
- import { usePageViewContext } from "../../core/PageViewContext";
7
- import { substituteExpr } from "../../lib/utils/BeanUtils";
8
- import { getUrlPageParams, parseHashUrl } from "../../lib/utils/PageUtils";
9
- import { AbstractComponent } from "../../types/component";
10
- import PopupView from "../view/PopupView";
11
-
12
- /* ------------------------------------------------------------------ */
13
- /* Types */
14
-
15
- interface ViewPageProps extends AbstractComponent {
16
- url: string;
17
- mode?: "popup" | "window";
18
- className?: string;
19
- title?: string;
20
- icon?: string | React.ReactNode;
21
- opt?: Record<string, any>;
22
- iconOnly?: boolean;
23
- popupClassName?: string;
24
- }
25
-
26
- /* ------------------------------------------------------------------ */
27
- /* Component */
28
-
29
- const ViewPage = (props: ViewPageProps) => {
30
- const { url, mode, className = "", title, icon, opt = {}, popupClassName = "", iconOnly = false } = props ?? {};
31
- const { data = {} } = opt;
32
-
33
- const dataContext = useDataContext();
34
- const pageView = usePageViewContext();
35
- const pageContext = usePageContext();
36
- const slotRef = useRef<ChildrenSlotHandle>(null);
37
-
38
- /* ---------------------- Events ---------------------- */
39
-
40
- const onClose = () => {
41
- slotRef.current?.update(null);
42
- };
43
-
44
- const handleClick = (e: React.MouseEvent) => {
45
- e.preventDefault();
46
-
47
- if (!url) return;
48
-
49
- const getUrlParams = () => {
50
- let result = null;
51
- if (pageView.isStandalone()) {
52
- const { params } = parseHashUrl(url);
53
- result = params;
54
- } else {
55
- const { params } = getUrlPageParams();
56
- result = params;
57
- }
58
- return result ?? {};
59
- };
60
-
61
- const getUrlData = () => {
62
- let result = null;
63
- if (dataContext == null) {
64
- // use data received from props
65
- const fullData = {
66
- ...pageContext.getAllData(),
67
- ...data,
68
- };
69
- result = fullData;
70
- } else {
71
- result = dataContext.getData();
72
- }
73
- return result ?? {};
74
- };
75
-
76
- const urlParams = getUrlParams();
77
- const urlData = getUrlData();
78
- const surl = substituteExpr(url, { ...urlParams, ...urlData });
79
-
80
- if (mode === "popup") {
81
- const handler = {
82
- onSave: (itm: any) => {
83
- onClose();
84
- pageContext.notifyDepends();
85
- },
86
- refresh: () => {
87
- pageContext.notifyDepends();
88
- },
89
- };
90
-
91
- slotRef.current?.update(<PopupView url={surl} onClose={onClose} eventHandler={handler} />);
92
- } else if (mode === "window") {
93
- pageView.setPage(surl, { mode });
94
- } else {
95
- pageView.pushPage(surl);
96
- }
97
- };
98
-
99
- /* ---------------------- Render ---------------------- */
100
- return (
101
- <>
102
- {iconOnly ? (
103
- <span onClick={handleClick} className={`cursor-pointer ${className}`}>
104
- {icon}
105
- </span>
106
- ) : (
107
- <button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
108
- {icon && <span className="dl-action-icon">{icon}</span>}
109
- {title || "View Page"}
110
- </button>
111
- )}
112
-
113
- <ChildrenSlot ref={slotRef} />
114
- </>
115
- );
116
- };
117
-
118
- export default ViewPage;
119
-
120
- type ChildrenSlotHandle = {
121
- update: (content: React.ReactNode) => void;
122
- };
123
-
124
- const ChildrenSlot = memo(
125
- forwardRef<ChildrenSlotHandle>((_, ref) => {
126
- const [content, setContent] = useState<React.ReactNode>(null);
127
-
128
- useImperativeHandle(
129
- ref,
130
- () => ({
131
- update: (content: React.ReactNode) => {
132
- // console.log("view page children slot", content);
133
- setContent(content);
134
- },
135
- }),
136
- [],
137
- );
138
-
139
- return <>{content == null ? null : content}</>;
140
- }),
141
- );
@@ -1,86 +0,0 @@
1
- import { compile } from "expression-eval";
2
- import { useEffect, useState } from "react";
3
- import { usePageContext } from "../../core/PageContext";
4
-
5
- export type UIComponentProps = {
6
- name?: string;
7
- title?: string;
8
- depends?: string;
9
- visibleWhen?: string;
10
- children?: React.ReactNode;
11
- labelPosition?: "top" | "left";
12
- style?: string;
13
- };
14
-
15
- const UIComponent = (props: UIComponentProps) => {
16
- const { name, title, depends, children, visibleWhen, labelPosition = "top", style } = props ?? {};
17
- const pageContext = usePageContext();
18
-
19
- const evaluateVisible = (): boolean => {
20
- if (!visibleWhen) return true;
21
- try {
22
- const context = pageContext?.getAllData() ?? {};
23
- const stripped = visibleWhen.replace(/^\s*\{([\s\S]*)\}\s*$/, "$1").trim();
24
- const jsExpr = stripped.replace(/\{\{([\s\S]+?)\}\}/g, (_, path) => {
25
- const val = path
26
- .trim()
27
- .split(".")
28
- .reduce((obj: any, key: string) => obj?.[key], context);
29
- return JSON.stringify(val ?? null);
30
- });
31
- // eslint-disable-next-line no-new-func
32
- // return Boolean(new Function(`return (${jsExpr})`)());
33
- return Boolean(compile(jsExpr)(context));
34
- } catch (e) {
35
- console.warn("visibleWhen eval error:", e);
36
- return true;
37
- }
38
- };
39
-
40
- const [visible, setVisible] = useState(() => evaluateVisible());
41
-
42
- const dependHandler = (val: any) => {
43
- // for visibleWhen
44
- setVisible(evaluateVisible());
45
- };
46
-
47
- useEffect(() => {
48
- const unsubscribe = pageContext?.dependsTo(depends || "", dependHandler);
49
- return unsubscribe;
50
- }, [depends]);
51
-
52
- // Re-evaluate when binding changes (same pattern as Label)
53
- useEffect(() => {
54
- setVisible(evaluateVisible());
55
- }, [pageContext?.binding?.raw, visibleWhen]);
56
-
57
- if (!visible) return null;
58
-
59
- // Top layout (default)
60
- if (labelPosition === "top") {
61
- return (
62
- <div className="flex flex-col gap-1 mb-4">
63
- {title && (
64
- <label htmlFor={name} className="text-sm font-medium text-gray-700">
65
- {title}
66
- </label>
67
- )}
68
- {children}
69
- </div>
70
- );
71
- }
72
-
73
- // Left layout
74
- return (
75
- <div className="flex items-center gap-2 mb-4">
76
- {title && (
77
- <label htmlFor={name} className="text-sm font-medium text-gray-700 min-w-[50px]">
78
- {title}
79
- </label>
80
- )}
81
- <div className="flex-1">{children}</div>
82
- </div>
83
- );
84
- };
85
-
86
- export default UIComponent;
@@ -1,49 +0,0 @@
1
- import { useEffect } from "react";
2
- import { usePageContext } from "../../core/PageContext";
3
-
4
- export type UIInputProps = {
5
- name: string;
6
- depends?: string;
7
- onRefresh: () => void;
8
- };
9
-
10
- const useUIInput = (props: UIInputProps) => {
11
- const { name, depends, onRefresh } = props ?? {};
12
- const pageContext = usePageContext();
13
- // console.log("useIUInput re-render", name, depends, onRefresh);
14
- const binding = pageContext?.binding;
15
-
16
- const getValue = () => {
17
- const val = pageContext?.get(name) ?? "";
18
- // console.log("ui input, get value", name, val, pageContext.getData());
19
- return val;
20
- };
21
-
22
- const setValue = (value: any) => {
23
- pageContext?.set(name, value);
24
- // console.log("after set value", name, pageContext?.get(name));
25
- };
26
-
27
- const initialValue = pageContext?.get(name) ?? "";
28
- // console.log("ui input init", name, initialValue);
29
- useEffect(() => {
30
- if (onRefresh) {
31
- onRefresh();
32
- }
33
- }, [binding?.raw, initialValue]);
34
-
35
- const dependHandler = (val: any) => {
36
- if (onRefresh) {
37
- onRefresh();
38
- }
39
- };
40
-
41
- useEffect(() => {
42
- const unsubscribe = pageContext?.dependsTo(depends || "", dependHandler);
43
- return unsubscribe;
44
- }, [depends]);
45
-
46
- return { initialValue, setValue, getValue, binding };
47
- };
48
-
49
- export default useUIInput;
@@ -1,91 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import { usePageContext } from "../../core/PageContext";
3
-
4
- export type MenuItem = {
5
- title: string;
6
- page?: string;
7
- icon?: React.ReactNode | string;
8
- mode?: string;
9
- };
10
-
11
- export type MenuGroup = {
12
- title: string;
13
- icon?: React.ReactNode | string;
14
- items: MenuItem[];
15
- };
16
-
17
- export type UIMenuProps = {
18
- items?: Record<string, any>[];
19
- data?: Record<string, any>;
20
- menugroup?: string;
21
- opt?: Record<string, any>;
22
- };
23
-
24
- const useUIMenu = (props: UIMenuProps) => {
25
- const { items: itemMenus, data, menugroup, opt = {} } = props ?? {};
26
-
27
- const pageContext = usePageContext();
28
-
29
- const [menus, setMenus] = useState<MenuGroup[]>([]);
30
- const [loading, setLoading] = useState(false);
31
- const [error, setError] = useState<string | null>(null);
32
-
33
- useEffect(() => {
34
- // 1️⃣ Static items
35
- if (Array.isArray(itemMenus) && itemMenus.length > 0) {
36
- // Check if already grouped (has items array) or flat
37
- const isGrouped = itemMenus.every((item) => Array.isArray(item.items));
38
- if (isGrouped) {
39
- setMenus(itemMenus as MenuGroup[]);
40
- } else {
41
- setMenus([{ title: "", items: itemMenus as MenuItem[] }]); // ✅ wrap in single group
42
- }
43
- return;
44
- }
45
-
46
- const fetchMenus = async () => {
47
- setLoading(true);
48
- setError(null);
49
-
50
- try {
51
- // 2️⃣ Custom API
52
- if (data?.api) {
53
- const res = await pageContext?.execService(data.api, data.params ?? {});
54
- setMenus(Array.isArray(res) ? (res as MenuGroup[]) : []);
55
- return;
56
- }
57
-
58
- // 3️⃣ Menugroup — fetch categories + items, map to MenuGroup[]
59
- if (menugroup != null) {
60
- const menuGroup = await pageContext?.getMgmt("menugroups", menugroup);
61
- const { categories = [] } = menuGroup || {};
62
-
63
- const menusRes = await pageContext?.postMgmt("menus", "list", {
64
- filter: { menugroup },
65
- sort: { sortorder: 1 },
66
- });
67
-
68
- const sorted = Array.isArray(menusRes) ? [...menusRes].sort((a, b) => (a.sortorder ?? 0) - (b.sortorder ?? 0)) : [];
69
-
70
- const mappedItems: MenuGroup[] = categories.map((cat: any) => ({
71
- title: cat.title,
72
- icon: cat.icon,
73
- items: sorted.filter((m: any) => m.category === cat.id),
74
- }));
75
-
76
- setMenus(mappedItems);
77
- }
78
- } catch (err: any) {
79
- setError(err?.message ?? "Failed to load menus");
80
- } finally {
81
- setLoading(false);
82
- }
83
- };
84
-
85
- fetchMenus();
86
- }, [itemMenus, data, menugroup]);
87
-
88
- return { items: menus, loading, error };
89
- };
90
-
91
- export default useUIMenu;
@@ -1,51 +0,0 @@
1
- export { default as Button } from "./action/Button";
2
- //inputs
3
- export { default as DateField } from "./input/DateField";
4
- export { default as DayPicker } from "./input/DayPicker";
5
-
6
- export { default as MonthPicker } from "./input/MonthPicker";
7
- export { default as Select } from "./input/Select";
8
- export { default as Text } from "./input/Text";
9
- export { default as YearPicker } from "./input/YearPicker";
10
-
11
- //codes
12
- export { default as HtmlCode } from "./input/HtmlCode";
13
- export { default as JsonCode } from "./input/JsonCode";
14
- export { default as ScriptCode } from "./input/ScriptCode";
15
- export { default as SqlCode } from "./input/SqlCode";
16
-
17
- //conditions
18
- export { default as StringDecision } from "./input/StringDecision";
19
-
20
- //export { default as YearPicker } from "./input/YearPicker";
21
- export { default as TabMenu } from "./list/TabMenu";
22
- export { default as TreeMenu } from "./list/TreeMenu";
23
- export { default as Label } from "./output/Label";
24
- export { default as DataList } from "./table/DataList";
25
-
26
- //views
27
- export { default as ComponentView } from "./view/ComponentView";
28
- export { default as FilterView } from "./view/FilterView";
29
- export { default as HtmlForm } from "./view/HtmlForm";
30
- export { default as HtmlView } from "./view/HtmlView";
31
- export { default as IFrameView } from "./view/IFrameView";
32
- export { default as RootView } from "./view/RootView";
33
- export { default as WizardView } from "./view/WizardView";
34
- //actions
35
- export { default as AlertMessage } from "./action/AlertMessage";
36
- export { default as DeleteData } from "./action/DeleteData";
37
- export { default as Edit } from "./action/Edit";
38
- export { default as ProcessRunner } from "./action/ProcessRunner";
39
- export { default as Refresh } from "./action/Refresh";
40
- export { default as SaveData } from "./action/SaveData";
41
- export { default as SelectData } from "./action/SelectData";
42
-
43
- export { default as LookupPage } from "./action/LookupPage";
44
- export { default as UpdateState } from "./action/UpdateState";
45
- export { default as ViewBackPage } from "./action/ViewBackPage";
46
- export { default as ViewPage } from "./action/ViewPage";
47
- export { default as PageView } from "./view/PageView";
48
-
49
- //lists
50
- export { default as IconMenu } from "./list/IconMenu";
51
- export { default as TxnTaskList } from "./list/TxnTaskList";