@ramesesinc/platform-core 0.1.6 → 0.1.9

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 (90) 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 +3 -0
  6. package/dist/components/index.js +1 -0
  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 +7 -7
  14. package/dist/core/PageContext.js +17 -7
  15. package/dist/core/PageViewContext.d.ts +13 -1
  16. package/dist/core/PageViewContext.js +75 -2
  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 +17 -0
  23. package/dist/core/index.js +1 -0
  24. package/dist/index.css +25 -7
  25. package/dist/lib/utils/BeanUtils.js +7 -7
  26. package/dist/templates/DataListTemplate.js +7 -2
  27. package/dist/templates/ExplorerTemplate.js +1 -1
  28. package/package.json +5 -5
  29. package/dist/components/action/AlertMessage.tsx +0 -38
  30. package/dist/components/action/Button.tsx +0 -230
  31. package/dist/components/action/CancelEdit.tsx +0 -40
  32. package/dist/components/action/DeleteData.tsx +0 -73
  33. package/dist/components/action/Edit.tsx +0 -40
  34. package/dist/components/action/LookupPage.tsx +0 -113
  35. package/dist/components/action/ProcessRunner.tsx +0 -337
  36. package/dist/components/action/Refresh.tsx +0 -35
  37. package/dist/components/action/SaveData.tsx +0 -74
  38. package/dist/components/action/SelectData.tsx +0 -47
  39. package/dist/components/action/Undo.tsx +0 -50
  40. package/dist/components/action/UpdateData.tsx +0 -49
  41. package/dist/components/action/UpdateState.tsx +0 -40
  42. package/dist/components/action/ViewBackPage.tsx +0 -46
  43. package/dist/components/action/ViewPage.tsx +0 -141
  44. package/dist/components/common/UIComponent.tsx +0 -86
  45. package/dist/components/common/UIInput.tsx +0 -49
  46. package/dist/components/common/UIMenu.tsx +0 -91
  47. package/dist/components/index.ts +0 -51
  48. package/dist/components/input/CodeEditor.tsx +0 -188
  49. package/dist/components/input/DateField.tsx +0 -274
  50. package/dist/components/input/DayPicker.tsx +0 -5
  51. package/dist/components/input/HtmlCode.tsx +0 -203
  52. package/dist/components/input/JsonCode.tsx +0 -205
  53. package/dist/components/input/MonthPicker.tsx +0 -5
  54. package/dist/components/input/ScriptCode.tsx +0 -195
  55. package/dist/components/input/Select.tsx +0 -78
  56. package/dist/components/input/SqlCode.tsx +0 -162
  57. package/dist/components/input/StringDecision.tsx +0 -64
  58. package/dist/components/input/Text.tsx +0 -57
  59. package/dist/components/input/YearPicker.tsx +0 -81
  60. package/dist/components/list/IconMenu.tsx +0 -115
  61. package/dist/components/list/TabMenu.tsx +0 -127
  62. package/dist/components/list/TreeMenu.tsx +0 -279
  63. package/dist/components/list/TxnTaskList.tsx +0 -198
  64. package/dist/components/output/Label.tsx +0 -50
  65. package/dist/components/table/DataList.tsx +0 -820
  66. package/dist/components/table/DataTable.tsx +0 -572
  67. package/dist/components/table/ListHandler.ts +0 -276
  68. package/dist/components/table/TableContext.tsx +0 -122
  69. package/dist/components/view/ComponentView.tsx +0 -102
  70. package/dist/components/view/FilterView.tsx +0 -21
  71. package/dist/components/view/HtmlForm.tsx +0 -176
  72. package/dist/components/view/HtmlView.tsx +0 -98
  73. package/dist/components/view/IFrameView.tsx +0 -48
  74. package/dist/components/view/Modal.tsx +0 -72
  75. package/dist/components/view/PageView.tsx +0 -131
  76. package/dist/components/view/PopupView.tsx +0 -160
  77. package/dist/components/view/RootView.tsx +0 -109
  78. package/dist/components/view/WizardView.tsx +0 -48
  79. package/dist/lib/layouts/BorderLayout.tsx +0 -31
  80. package/dist/lib/layouts/CardLayout.tsx +0 -73
  81. package/dist/lib/layouts/CenterLayout.tsx +0 -20
  82. package/dist/lib/layouts/GridLayout.tsx +0 -20
  83. package/dist/lib/layouts/HPanel.tsx +0 -31
  84. package/dist/lib/layouts/HorizontalLayout.tsx +0 -29
  85. package/dist/lib/layouts/MainLayout.tsx +0 -16
  86. package/dist/lib/layouts/PageLayout.tsx +0 -29
  87. package/dist/lib/layouts/VPanel.tsx +0 -27
  88. package/dist/lib/layouts/XLayout.tsx +0 -29
  89. package/dist/lib/layouts/YLayout.tsx +0 -29
  90. package/dist/lib/layouts/index.ts +0 -13
@@ -1,98 +0,0 @@
1
- import { localAPI } from "@ramesesinc/lib/local-api";
2
- import { useEffect, useState } from "react";
3
- import { useApp } from "../../core/AppContext";
4
- import { usePageContext } from "../../core/PageContext";
5
- import useDependHandler from "../../core/UIDependHandler";
6
- import { render } from "../../lib/utils/ExprUtil";
7
- import UIComponent from "../common/UIComponent";
8
-
9
- type HtmlLabelProps = {
10
- label?: string;
11
- depends?: string;
12
- expr?: string;
13
- templateid?: string;
14
- data?: Record<string, any>;
15
- };
16
-
17
- const Html = (props: HtmlLabelProps) => {
18
- const { depends, expr, templateid } = props ?? {};
19
-
20
- const [htmlTemplate, setHtmlTemplate] = useState(""); // raw template
21
- const [renderedHtml, setRenderedHtml] = useState(""); // rendered output
22
- const pageContext = usePageContext();
23
- const binding = pageContext?.binding;
24
- const { tenant, module } = useApp();
25
-
26
- // ← single render function used everywhere
27
- const renderTemplate = (template: string) => {
28
- if (!template) return "";
29
- try {
30
- const data = pageContext?.getAllData() ?? {};
31
- return render(template, data);
32
- } catch (error) {
33
- console.error("Template render error:", error);
34
- return template;
35
- }
36
- };
37
-
38
- // ← single expression render
39
- const renderExpression = (expression: string) => {
40
- if (!expression) return "";
41
- try {
42
- const data = pageContext?.getData() ?? {};
43
- return render(expression, { data });
44
- } catch (error) {
45
- console.error("Expression render error:", error);
46
- return expression;
47
- }
48
- };
49
-
50
- // ← load template only once when templateid changes
51
- useEffect(() => {
52
- if (templateid == null || templateid.trim() === "") return;
53
-
54
- const loadHtmlContent = async () => {
55
- try {
56
- const htmlContent = await localAPI.useMgmt(tenant!, module!).get("html_templates", templateid);
57
- if (htmlContent != null) {
58
- setHtmlTemplate(htmlContent.htmlCode); // ← just store raw template
59
- } else {
60
- setHtmlTemplate("");
61
- }
62
- } catch (error) {
63
- console.error("Error loading HTML template:", error);
64
- setHtmlTemplate("");
65
- }
66
- };
67
-
68
- loadHtmlContent();
69
- }, [templateid]);
70
-
71
- // ← re-render whenever template OR binding data changes
72
- useEffect(() => {
73
- if (htmlTemplate) {
74
- setRenderedHtml(renderTemplate(htmlTemplate));
75
- } else if (expr) {
76
- setRenderedHtml(renderExpression(expr));
77
- }
78
- }, [htmlTemplate, binding?.raw]); // ← binding.raw triggers when data changes
79
-
80
- // ← onRefresh called when depends changes
81
- const onRefresh = () => {
82
- if (htmlTemplate) {
83
- setRenderedHtml(renderTemplate(htmlTemplate));
84
- } else if (expr) {
85
- setRenderedHtml(renderExpression(expr));
86
- }
87
- };
88
-
89
- useDependHandler({ name: depends, onRefresh });
90
-
91
- return (
92
- <UIComponent {...(props ?? {})}>
93
- <div className="h-[calc(100vh-80px)] overflow-y-auto overflow-x-auto" dangerouslySetInnerHTML={{ __html: renderedHtml }} />
94
- </UIComponent>
95
- );
96
- };
97
-
98
- export default Html;
@@ -1,48 +0,0 @@
1
- "use client";
2
-
3
- import { useEffect, useRef, useState } from "react";
4
- import { usePageContext } from "../../core/PageContext";
5
-
6
- const Iframe = (props: Record<string, any>) => {
7
- // console.log(props);
8
- const { url = "", name, depends = "page", width = "100%", height = "100%" } = props ?? {};
9
- const pageContext = usePageContext();
10
- const lastValueRef = useRef<any>();
11
- const [iframeUrl, setIframeUrl] = useState(url);
12
-
13
- const dependHandler = (value: any) => {
14
- if (lastValueRef.current === value) return; // skip if unchanged
15
- lastValueRef.current = value;
16
-
17
- // value is expected to be a URL (string)
18
- if (typeof value === "string") {
19
- setIframeUrl(value);
20
- }
21
- };
22
-
23
- useEffect(() => {
24
- if (!depends) return;
25
- const unsubscribe = pageContext?.dependsTo(depends, dependHandler);
26
- return unsubscribe;
27
- }, [depends]);
28
-
29
- if (!iframeUrl) return null;
30
-
31
- return (
32
- <div className="h-[calc(100vh-60px)]">
33
- <iframe
34
- src={iframeUrl}
35
- name={name}
36
- title={name || "iframe"}
37
- style={{
38
- width,
39
- height,
40
- border: "none",
41
- }}
42
- loading="lazy"
43
- />
44
- </div>
45
- );
46
- };
47
-
48
- export default Iframe;
@@ -1,72 +0,0 @@
1
- "use client";
2
-
3
- import clsx from "clsx";
4
- import { MouseEvent, ReactNode, useEffect } from "react";
5
-
6
- export type ModalRenderFn = (close: () => void) => ReactNode;
7
-
8
- export type ModalProps = {
9
- open: boolean;
10
- onClose: () => void;
11
- children: ReactNode | ModalRenderFn;
12
- title?: string;
13
- className?: string;
14
- width?: string; // e.g. "500px" or "50%"
15
- height?: string; // e.g. "400px" or "80%"
16
- hideCloseButton?: boolean;
17
- };
18
-
19
- const Modal = ({ open, onClose, title, children, className, width = "600px", height, hideCloseButton = false }: ModalProps) => {
20
- useEffect(() => {
21
- const handleKey = (e: KeyboardEvent) => {
22
- if (e.key === "Escape") {
23
- onClose();
24
- }
25
- };
26
-
27
- if (open) {
28
- document.addEventListener("keydown", handleKey);
29
- }
30
-
31
- return () => {
32
- document.removeEventListener("keydown", handleKey);
33
- };
34
- }, [open, onClose]);
35
-
36
- if (!open) return null;
37
-
38
- const handleOverlayClick = (e: MouseEvent<HTMLDivElement>) => {
39
- // if (e.target === e.currentTarget) {
40
- // onClose();
41
- // }
42
- };
43
-
44
- return (
45
- <div className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/40" onClick={handleOverlayClick}>
46
- <div
47
- className={clsx("relative bg-white rounded-lg shadow-lg p-2 w-full max-w-[90vw] transition-all duration-300 ease-in-out", className)}
48
- style={{ width, height }}
49
- role="dialog"
50
- aria-modal="true"
51
- aria-labelledby={title ? "modal-title" : undefined}
52
- >
53
- {title && (
54
- <h2 id="modal-title" className="text-lg font-semibold mb-4 border-b pb-2 text-gray-800">
55
- {title}
56
- </h2>
57
- )}
58
-
59
- {/* Modal Content */}
60
- <div className="overflow-auto">{typeof children === "function" ? children(onClose) : children}</div>
61
-
62
- {!hideCloseButton && (
63
- <button onClick={onClose} aria-label="Close modal" className="absolute top-2 right-2 text-gray-500 hover:text-gray-800 transition-colors">
64
-
65
- </button>
66
- )}
67
- </div>
68
- </div>
69
- );
70
- };
71
-
72
- export default Modal;
@@ -1,131 +0,0 @@
1
- "use client";
2
-
3
- import React, { forwardRef, memo, useEffect, useImperativeHandle, useRef, useState } from "react";
4
- import Page from "../../core/Page";
5
- import { usePageContext } from "../../core/PageContext";
6
- import { PageViewContextValue, PageViewHandle, PageViewProvider, usePageViewContext } from "../../core/PageViewContext";
7
- import useDependHandler from "../../core/UIDependHandler";
8
- import { useUrlParams } from "../../hooks/useUrlParams";
9
- import UIComponent, { UIComponentProps } from "../common/UIComponent";
10
-
11
- type StableShellProps = {
12
- uiProps: Record<string, any>;
13
- handle: PageViewHandle;
14
- slotRef: React.RefObject<PageSlotHandle>;
15
- paths: string[]; // ← new
16
- };
17
-
18
- const StableShell = memo((props: StableShellProps) => {
19
- const { uiProps, slotRef, handle, paths } = props ?? {};
20
- return (
21
- <UIComponent {...uiProps}>
22
- <PageViewProvider handle={handle} paths={paths ?? []}>
23
- <PageSlot ref={slotRef} />
24
- </PageViewProvider>
25
- </UIComponent>
26
- );
27
- });
28
-
29
- interface PageViewProps extends UIComponentProps {
30
- depends?: string;
31
- url?: string;
32
- fallback?: React.ReactNode;
33
- }
34
-
35
- const PageView = memo((props: PageViewProps) => {
36
- const { name = "selectedPage", depends, url } = props ?? {};
37
- const [forceUpdate, setForceUpdate] = useState({});
38
- const providerRef = useRef<PageViewContextValue>({} as PageViewContextValue);
39
- const { setAnchorPath } = useUrlParams();
40
- const slotRef = useRef<PageSlotHandle>(null);
41
- const pageContext = usePageContext();
42
- const [ownPaths, setOwnPaths] = useState<string[]>([]);
43
- const isEmpty = (value: string | null | undefined) => value == null || value.trim() === "";
44
-
45
- const pageView = usePageViewContext();
46
-
47
- let preferredName = isEmpty(name) ? depends : name;
48
- let preferredDepends = isEmpty(depends) ? preferredName : depends;
49
-
50
- const newProps = { ...props, name: preferredName, depends: preferredDepends };
51
-
52
- const propsRef = useRef(newProps);
53
- useEffect(() => {
54
- propsRef.current = newProps;
55
- });
56
-
57
- const getUrl = () => {
58
- if (url != null && url.trim() !== "") return url;
59
- if (newProps.name) return pageContext.get(newProps.name);
60
- return null;
61
- };
62
-
63
- const getUrlRef = useRef(getUrl);
64
- useEffect(() => {
65
- getUrlRef.current = getUrl;
66
- });
67
-
68
- // Stable handle — never recreated
69
- const pageViewHandleRef = useRef({
70
- displayName: "PageView#pageViewHandle",
71
- init: (ref: PageViewContextValue) => {
72
- providerRef.current = ref;
73
- setForceUpdate({});
74
- },
75
- renderPage: (page: string | null) => {
76
- if (page == null || page.trim() === "") {
77
- slotRef.current?.update(null, "null");
78
- return;
79
- }
80
- setOwnPaths([page]); // ← track own paths
81
- const key = "page-" + Math.random().toString(36).slice(2);
82
- const comp = <Page {...propsRef.current} url={page} key={key} />;
83
- slotRef.current?.update(comp, page);
84
- },
85
- isStandalone: () => {
86
- return pageView == null ? true : pageView.isStandalone();
87
- },
88
- });
89
-
90
- const onRefresh = (val?: any) => {
91
- setForceUpdate({ val }); // ← carry the value
92
- };
93
-
94
- useDependHandler({ name: newProps.depends, onRefresh });
95
-
96
- useEffect(() => {
97
- const prov = providerRef.current;
98
- if (prov == null || typeof prov.setPage !== "function") return;
99
-
100
- const url = getUrlRef.current();
101
- // console.log("pageView forceUpdate", url, providerRef.current);
102
- providerRef.current.setPage(url);
103
- }, [forceUpdate]);
104
-
105
- return <StableShell uiProps={newProps} handle={pageViewHandleRef.current} slotRef={slotRef} paths={ownPaths} />;
106
- });
107
-
108
- type PageSlotHandle = {
109
- update: (content: React.ReactNode, opt?: any) => void;
110
- };
111
- const PageSlot = memo(
112
- forwardRef<PageSlotHandle>((_, ref) => {
113
- const [content, setContent] = useState<React.ReactNode>(null);
114
- const [opt, setOpt] = useState<any>(null);
115
-
116
- useImperativeHandle(
117
- ref,
118
- () => ({
119
- update: (content: React.ReactNode, opt?: any) => {
120
- setContent(content);
121
- setOpt(opt);
122
- },
123
- }),
124
- [],
125
- );
126
-
127
- return <>{content == null ? null : content}</>;
128
- }),
129
- );
130
-
131
- export default PageView;
@@ -1,160 +0,0 @@
1
- import { getError } from "@ramesesinc/client";
2
- import clsx from "clsx";
3
- import React, { forwardRef, memo, useEffect, useImperativeHandle, useRef, useState } from "react";
4
- import { twMerge } from "tailwind-merge";
5
- import { EventHandler } from "../../core";
6
- import Page from "../../core/Page";
7
- import { PageViewContextValue, PageViewHandle, PageViewProvider } from "../../core/PageViewContext";
8
-
9
- type PopupViewProps = {
10
- url: string;
11
- popupClassName?: string;
12
- onClose?: () => void;
13
- eventHandler?: EventHandler | null;
14
- };
15
-
16
- const PopupView = (props: PopupViewProps) => {
17
- const { url, popupClassName, onClose = () => {}, eventHandler } = props ?? {};
18
-
19
- const [paths, setPaths] = useState<string[]>([]);
20
-
21
- const providerRef = useRef<PageViewContextValue>({} as PageViewContextValue);
22
- const slotRef = useRef<PopupSlotHandle>(null);
23
-
24
- const [newRootPath, setNewRootPath] = useState<string | null>(null);
25
- const [reInitPage, setReInitPage] = useState(true);
26
-
27
- const mainPath = useRef("");
28
-
29
- const defaultPopupClass = `bg-white rounded-lg shadow-xl w-[90%] h-[90%] flex flex-col`;
30
- const finalPopupClass = twMerge(clsx(defaultPopupClass, popupClassName));
31
-
32
- const loadPage = (path: string | null) => {
33
- // console.log("popupview load page", path);
34
- let comp = null;
35
- try {
36
- const key = "page-" + Math.random().toString(36).slice(2);
37
- comp = <Page url={path} key={key} />;
38
- } catch (error: any) {
39
- const e = getError(error);
40
- comp = <div>{e.message}</div>;
41
- }
42
-
43
- // update the child slot
44
- slotRef.current?.update(comp, finalPopupClass, onClose);
45
- };
46
-
47
- useEffect(() => {
48
- // console.log("popupview change url", url);
49
- const paths = (url == null || url.trim() === "" ? "" : url).split("#");
50
- const [firstPath] = paths;
51
- mainPath.current = firstPath;
52
- setPaths(paths);
53
- }, [url]);
54
-
55
- useEffect(() => {
56
- // this routine is for the initial loading
57
- // console.log("popupview change paths", paths);
58
- loadPage(mainPath.current);
59
- setReInitPage(false);
60
- }, [paths]);
61
-
62
- useEffect(() => {
63
- if (reInitPage) {
64
- // let the initial loading take effect
65
- return;
66
- }
67
-
68
- loadPage(newRootPath);
69
- }, [newRootPath]);
70
-
71
- const pageViewHandle = {
72
- displayName: "PopupView#pageViewHandle",
73
- init: (ref: PageViewContextValue) => {
74
- providerRef.current = ref;
75
- },
76
- renderPage: (page: string) => {
77
- setNewRootPath(page);
78
- },
79
- isStandalone: () => true,
80
- } as PageViewHandle;
81
-
82
- return (
83
- <PageViewProvider prefix="popup" paths={paths} handle={pageViewHandle} eventHandler={eventHandler}>
84
- <ChildrenSlot ref={slotRef} />
85
- </PageViewProvider>
86
- );
87
- };
88
-
89
- export default PopupView;
90
-
91
- type PopupSlotHandle = {
92
- update: (content: React.ReactNode, popupClassName: string, onClose: () => void) => void;
93
- };
94
-
95
- const ChildrenSlot = memo(
96
- forwardRef<PopupSlotHandle>((_, ref) => {
97
- const [content, setContent] = useState<React.ReactNode>(null);
98
-
99
- const optionsRef = useRef<Record<string, any>>({});
100
-
101
- useImperativeHandle(
102
- ref,
103
- () => ({
104
- update: (content: React.ReactNode, popupClassName: string, onClose: () => void) => {
105
- const options = { popupClassName, onClose };
106
- setContent(wrapContent(content, options));
107
- optionsRef.current = options;
108
- },
109
- }),
110
- [],
111
- );
112
-
113
- const handleClose = () => {
114
- setContent(null);
115
-
116
- const { onClose } = optionsRef.current;
117
- if (onClose != null && typeof onClose === "function") {
118
- onClose();
119
- }
120
- };
121
-
122
- const wrapContent = (comp: React.ReactNode, options: Record<string, any>): React.ReactNode => {
123
- if (comp == null) {
124
- return null;
125
- }
126
-
127
- const { popupClassName } = options;
128
- return (
129
- <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
130
- <div className={popupClassName}>
131
- {/* Header */}
132
- <div className="flex items-center justify-between px-4 py-3 border-b">
133
- <h2 className="text-lg font-semibold">Page Viewer</h2>
134
- <button onClick={handleClose} className="w-8 h-8 flex items-center justify-center rounded-md hover:bg-gray-100 transition-colors">
135
- <svg
136
- xmlns="http://www.w3.org/2000/svg"
137
- width="20"
138
- height="20"
139
- viewBox="0 0 24 24"
140
- fill="none"
141
- stroke="currentColor"
142
- strokeWidth="2"
143
- strokeLinecap="round"
144
- strokeLinejoin="round"
145
- >
146
- <line x1="18" y1="6" x2="6" y2="18"></line>
147
- <line x1="6" y1="6" x2="18" y2="18"></line>
148
- </svg>
149
- </button>
150
- </div>
151
- {/* Content */}
152
- <div className="flex-1 overflow-hidden">{comp}</div>
153
- </div>
154
- </div>
155
- );
156
- };
157
-
158
- return <>{content == null ? null : content}</>;
159
- }),
160
- );
@@ -1,109 +0,0 @@
1
- import { getError } from "@ramesesinc/client";
2
- import { forwardRef, memo, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
3
- import { EventHandler } from "../../core";
4
- import Page from "../../core/Page";
5
- import { PageViewContextValue, PageViewHandle, PageViewProvider } from "../../core/PageViewContext";
6
-
7
- type RootViewProps = {
8
- url: string;
9
- eventHandler?: EventHandler | null;
10
- standalone?: boolean;
11
- };
12
-
13
- const RootView = (props: RootViewProps) => {
14
- const { url, eventHandler, standalone = true } = props ?? {};
15
-
16
- const [paths, setPaths] = useState<string[]>([]);
17
-
18
- const mainPath = useRef("");
19
-
20
- const [newRootPath, setNewRootPath] = useState<string | null>(null);
21
- const [reInitPage, setReInitPage] = useState(true);
22
-
23
- const providerRef = useRef<PageViewContextValue>({} as PageViewContextValue);
24
-
25
- const loadPage = (path: string | null) => {
26
- let comp = null;
27
- try {
28
- // console.log("RootView loadPage", path); // main#tasklist
29
- const pageUUID = "page-" + Math.random().toString(36).slice(2);
30
- comp = <Page url={path} key={pageUUID} />;
31
- } catch (error: any) {
32
- const e = getError(error);
33
- // console.log("rootview loadpage error", e);
34
- comp = <div>{e.message}</div>;
35
- }
36
- // update provider paths but maintain the rootPath
37
- // providerRef.current?.updatePaths(newPaths);
38
- // update the child slot
39
- slotRef.current?.update(comp);
40
- };
41
-
42
- useLayoutEffect(() => {
43
- const paths = (url == null || url.trim() === "" ? "" : url).split("#");
44
- // console.log("RootView useLayoutEffect ", url, paths);
45
- const [firstPath] = paths;
46
- mainPath.current = firstPath;
47
- setPaths(paths);
48
- }, [url]);
49
-
50
- useEffect(() => {
51
- // this routine is for the initial loading
52
- // pass the original url
53
- loadPage(url);
54
- setReInitPage(false);
55
- }, [paths]);
56
-
57
- useEffect(() => {
58
- if (reInitPage) {
59
- // let the initial loading take effect
60
- return;
61
- }
62
-
63
- loadPage(newRootPath);
64
- }, [newRootPath]);
65
-
66
- const pageViewHandle = {
67
- displayName: "RootView#pageViewHandle",
68
- init: (ref: PageViewContextValue) => {
69
- providerRef.current = ref;
70
- },
71
- renderPage: (page: string) => {
72
- // console.log("RootView renderPage", page);
73
- setNewRootPath(page);
74
- },
75
- isStandalone: () => standalone,
76
- } as PageViewHandle;
77
-
78
- const slotRef = useRef<ChildrenSlotHandle>(null);
79
-
80
- return (
81
- <PageViewProvider prefix="root" paths={paths} handle={pageViewHandle} eventHandler={eventHandler}>
82
- <ChildrenSlot ref={slotRef} />
83
- </PageViewProvider>
84
- );
85
- };
86
-
87
- export default RootView;
88
-
89
- type ChildrenSlotHandle = {
90
- update: (content: React.ReactNode) => void;
91
- };
92
- const ChildrenSlot = memo(
93
- forwardRef<ChildrenSlotHandle>((_, ref) => {
94
- const [content, setContent] = useState<React.ReactNode>(null);
95
-
96
- useImperativeHandle(
97
- ref,
98
- () => ({
99
- update: (content: React.ReactNode) => {
100
- // console.log("childrenslot update", content);
101
- setContent(content);
102
- },
103
- }),
104
- [],
105
- );
106
-
107
- return <>{content == null ? null : content}</>;
108
- }),
109
- );
@@ -1,48 +0,0 @@
1
- import { useEffect, useRef } from "react";
2
- import { usePageContext } from "../../core/PageContext";
3
- import { StepActionHandler, StepHandler } from "../../core/StepHandler";
4
- import ComponentView from "./ComponentView";
5
-
6
- type WizardViewProps = {
7
- name: string;
8
- items: Record<string, any>[];
9
- };
10
-
11
- const WizardView = (props: WizardViewProps) => {
12
- const { name = "wizard", items = [] } = props ?? {};
13
- const pageContext = usePageContext();
14
- const handlerRef = useRef<StepActionHandler | null>(null);
15
-
16
- if (handlerRef.current == null) {
17
- const callback = (item: Record<string, any>) => {
18
- const onInit = item.events?.onInit;
19
- if (onInit != null && typeof onInit === "function") {
20
- onInit();
21
- }
22
- pageContext?.set(name, item);
23
- };
24
-
25
- const handler = StepHandler(items, callback);
26
-
27
- for (const it of items) {
28
- const item = it as Record<string, any>;
29
- if (item.attr == null) item.attr = {};
30
- item.attr.stepHandler = handler;
31
- item.attr.events = {};
32
- }
33
-
34
- handlerRef.current = handler;
35
- }
36
-
37
- useEffect(() => {
38
- pageContext?.set(name, items[0]);
39
- }, []);
40
-
41
- return (
42
- <div>
43
- <ComponentView name={name} depends={name} />
44
- </div>
45
- );
46
- };
47
-
48
- export default WizardView;
@@ -1,31 +0,0 @@
1
- import { ReactNode } from "react";
2
- import HorizontalLayout from "./HorizontalLayout";
3
- import PageLayout from "./PageLayout";
4
-
5
- type BorderLayoutProps = {
6
- layoutid?: string;
7
- className?: string;
8
- vgap?: number;
9
- hgap?: number;
10
-
11
- north?: ReactNode;
12
- south?: ReactNode;
13
- east?: ReactNode;
14
- west?: ReactNode;
15
-
16
- children?: ReactNode;
17
- };
18
-
19
- const BorderLayout = ({ layoutid, className, vgap = 0, hgap = 0, north, south, east, west, children }: BorderLayoutProps) => {
20
- const preferredLayoutId = layoutid ?? "" ? layoutid : "borderlayout";
21
-
22
- return (
23
- <PageLayout layoutid={`${preferredLayoutId}`} className={className} gap={vgap} header={north} footer={south}>
24
- <HorizontalLayout layoutid={`${preferredLayoutId}-center`} gap={hgap} left={west} right={east}>
25
- {children}
26
- </HorizontalLayout>
27
- </PageLayout>
28
- );
29
- };
30
-
31
- export default BorderLayout;