@servlyadmin/runtime-react 0.1.0
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.
- package/dist/index.cjs +235 -0
- package/dist/index.d.cts +44 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +212 -0
- package/package.json +50 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ServlyComponent: () => ServlyComponent,
|
|
24
|
+
clearAllCaches: () => import_runtime_core2.clearAllCaches,
|
|
25
|
+
compareVersions: () => import_runtime_core2.compareVersions,
|
|
26
|
+
default: () => ServlyComponent_default,
|
|
27
|
+
fetchComponent: () => import_runtime_core2.fetchComponent,
|
|
28
|
+
getRegistryUrl: () => import_runtime_core2.getRegistryUrl,
|
|
29
|
+
invalidateCache: () => import_runtime_core2.invalidateCache,
|
|
30
|
+
isComponentAvailable: () => import_runtime_core2.isComponentAvailable,
|
|
31
|
+
parseVersion: () => import_runtime_core2.parseVersion,
|
|
32
|
+
prefetchComponents: () => import_runtime_core2.prefetchComponents,
|
|
33
|
+
resolveVersion: () => import_runtime_core2.resolveVersion,
|
|
34
|
+
satisfiesVersion: () => import_runtime_core2.satisfiesVersion,
|
|
35
|
+
setRegistryUrl: () => import_runtime_core2.setRegistryUrl
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
|
|
39
|
+
// src/ServlyComponent.tsx
|
|
40
|
+
var import_react = require("react");
|
|
41
|
+
var import_runtime_core = require("@servlyadmin/runtime-core");
|
|
42
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
43
|
+
var LoadingSkeleton = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
44
|
+
"div",
|
|
45
|
+
{
|
|
46
|
+
className: `servly-skeleton ${className || ""}`,
|
|
47
|
+
style: {
|
|
48
|
+
backgroundColor: "#f3f4f6",
|
|
49
|
+
borderRadius: "8px",
|
|
50
|
+
minHeight: "100px",
|
|
51
|
+
animation: "servly-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite"
|
|
52
|
+
},
|
|
53
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
|
|
54
|
+
@keyframes servly-pulse {
|
|
55
|
+
0%, 100% { opacity: 1; }
|
|
56
|
+
50% { opacity: 0.5; }
|
|
57
|
+
}
|
|
58
|
+
` })
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
var ErrorDisplay = ({ error, onRetry, className, style }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
62
|
+
"div",
|
|
63
|
+
{
|
|
64
|
+
className: `servly-error ${className || ""}`,
|
|
65
|
+
style: {
|
|
66
|
+
padding: "16px",
|
|
67
|
+
color: "#ef4444",
|
|
68
|
+
backgroundColor: "#fef2f2",
|
|
69
|
+
borderRadius: "8px",
|
|
70
|
+
...style
|
|
71
|
+
},
|
|
72
|
+
children: [
|
|
73
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { margin: 0, fontWeight: 500 }, children: "Failed to load component" }),
|
|
74
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { margin: "8px 0 0", fontSize: "14px", color: "#991b1b" }, children: error.message }),
|
|
75
|
+
onRetry && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
76
|
+
"button",
|
|
77
|
+
{
|
|
78
|
+
onClick: onRetry,
|
|
79
|
+
style: {
|
|
80
|
+
marginTop: "12px",
|
|
81
|
+
padding: "8px 16px",
|
|
82
|
+
backgroundColor: "#ef4444",
|
|
83
|
+
color: "white",
|
|
84
|
+
border: "none",
|
|
85
|
+
borderRadius: "4px",
|
|
86
|
+
cursor: "pointer",
|
|
87
|
+
fontSize: "14px"
|
|
88
|
+
},
|
|
89
|
+
children: "Retry"
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
function ServlyComponent({
|
|
96
|
+
id,
|
|
97
|
+
version = "latest",
|
|
98
|
+
props = {},
|
|
99
|
+
fallback,
|
|
100
|
+
onError,
|
|
101
|
+
onLoad,
|
|
102
|
+
className,
|
|
103
|
+
style,
|
|
104
|
+
showSkeleton = true,
|
|
105
|
+
cacheStrategy = "memory",
|
|
106
|
+
retryConfig,
|
|
107
|
+
eventHandlers
|
|
108
|
+
}) {
|
|
109
|
+
const containerRef = (0, import_react.useRef)(null);
|
|
110
|
+
const renderResultRef = (0, import_react.useRef)(null);
|
|
111
|
+
const abortControllerRef = (0, import_react.useRef)(null);
|
|
112
|
+
const [state, setState] = (0, import_react.useState)({
|
|
113
|
+
loading: true,
|
|
114
|
+
error: null,
|
|
115
|
+
data: null
|
|
116
|
+
});
|
|
117
|
+
const loadComponent = (0, import_react.useCallback)(async () => {
|
|
118
|
+
if (abortControllerRef.current) {
|
|
119
|
+
abortControllerRef.current.abort();
|
|
120
|
+
}
|
|
121
|
+
abortControllerRef.current = new AbortController();
|
|
122
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
123
|
+
const fetchOptions = {
|
|
124
|
+
version,
|
|
125
|
+
cacheStrategy,
|
|
126
|
+
retryConfig,
|
|
127
|
+
signal: abortControllerRef.current.signal
|
|
128
|
+
};
|
|
129
|
+
try {
|
|
130
|
+
const result = await (0, import_runtime_core.fetchComponent)(id, fetchOptions);
|
|
131
|
+
setState({
|
|
132
|
+
loading: false,
|
|
133
|
+
error: null,
|
|
134
|
+
data: result.data
|
|
135
|
+
});
|
|
136
|
+
onLoad?.();
|
|
137
|
+
} catch (error) {
|
|
138
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
139
|
+
if (err.message === "Fetch aborted") return;
|
|
140
|
+
setState({
|
|
141
|
+
loading: false,
|
|
142
|
+
error: err,
|
|
143
|
+
data: null
|
|
144
|
+
});
|
|
145
|
+
onError?.(err);
|
|
146
|
+
}
|
|
147
|
+
}, [id, version, cacheStrategy, retryConfig, onLoad, onError]);
|
|
148
|
+
(0, import_react.useEffect)(() => {
|
|
149
|
+
loadComponent();
|
|
150
|
+
return () => {
|
|
151
|
+
if (abortControllerRef.current) {
|
|
152
|
+
abortControllerRef.current.abort();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}, [loadComponent]);
|
|
156
|
+
(0, import_react.useEffect)(() => {
|
|
157
|
+
if (!state.data || !containerRef.current) return;
|
|
158
|
+
const context = {
|
|
159
|
+
props,
|
|
160
|
+
state: {},
|
|
161
|
+
context: {}
|
|
162
|
+
};
|
|
163
|
+
if (renderResultRef.current) {
|
|
164
|
+
renderResultRef.current.update(context);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
renderResultRef.current = (0, import_runtime_core.render)({
|
|
168
|
+
container: containerRef.current,
|
|
169
|
+
elements: state.data.layout,
|
|
170
|
+
context,
|
|
171
|
+
eventHandlers
|
|
172
|
+
});
|
|
173
|
+
return () => {
|
|
174
|
+
if (renderResultRef.current) {
|
|
175
|
+
renderResultRef.current.destroy();
|
|
176
|
+
renderResultRef.current = null;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}, [state.data, props, eventHandlers]);
|
|
180
|
+
(0, import_react.useEffect)(() => {
|
|
181
|
+
if (!renderResultRef.current || !state.data) return;
|
|
182
|
+
const context = {
|
|
183
|
+
props,
|
|
184
|
+
state: {},
|
|
185
|
+
context: {}
|
|
186
|
+
};
|
|
187
|
+
renderResultRef.current.update(context);
|
|
188
|
+
}, [props, state.data]);
|
|
189
|
+
if (state.loading) {
|
|
190
|
+
if (fallback) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: fallback });
|
|
191
|
+
if (showSkeleton) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoadingSkeleton, { className });
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
if (state.error) {
|
|
195
|
+
if (fallback) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: fallback });
|
|
196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
197
|
+
ErrorDisplay,
|
|
198
|
+
{
|
|
199
|
+
error: state.error,
|
|
200
|
+
onRetry: loadComponent,
|
|
201
|
+
className,
|
|
202
|
+
style
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
207
|
+
"div",
|
|
208
|
+
{
|
|
209
|
+
ref: containerRef,
|
|
210
|
+
className: `servly-component ${className || ""}`,
|
|
211
|
+
style,
|
|
212
|
+
"data-servly-id": id,
|
|
213
|
+
"data-servly-version": state.data?.version
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
var ServlyComponent_default = ServlyComponent;
|
|
218
|
+
|
|
219
|
+
// src/index.ts
|
|
220
|
+
var import_runtime_core2 = require("@servlyadmin/runtime-core");
|
|
221
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
222
|
+
0 && (module.exports = {
|
|
223
|
+
ServlyComponent,
|
|
224
|
+
clearAllCaches,
|
|
225
|
+
compareVersions,
|
|
226
|
+
fetchComponent,
|
|
227
|
+
getRegistryUrl,
|
|
228
|
+
invalidateCache,
|
|
229
|
+
isComponentAvailable,
|
|
230
|
+
parseVersion,
|
|
231
|
+
prefetchComponents,
|
|
232
|
+
resolveVersion,
|
|
233
|
+
satisfiesVersion,
|
|
234
|
+
setRegistryUrl
|
|
235
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CacheStrategy, RetryConfig } from '@servlyadmin/runtime-core';
|
|
3
|
+
export { BindingContext, CacheStrategy, ComponentData, FetchOptions, LayoutElement, PropDefinition, RetryConfig, clearAllCaches, compareVersions, fetchComponent, getRegistryUrl, invalidateCache, isComponentAvailable, parseVersion, prefetchComponents, resolveVersion, satisfiesVersion, setRegistryUrl } from '@servlyadmin/runtime-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ServlyComponent
|
|
7
|
+
* React wrapper for Servly runtime renderer
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Props for ServlyComponent
|
|
12
|
+
*/
|
|
13
|
+
interface ServlyComponentProps<P = Record<string, any>> {
|
|
14
|
+
/** Component ID from the registry */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Version specifier (exact, range, or "latest") */
|
|
17
|
+
version?: string;
|
|
18
|
+
/** Props to pass to the component */
|
|
19
|
+
props?: P;
|
|
20
|
+
/** Fallback UI while loading or on error */
|
|
21
|
+
fallback?: React.ReactNode;
|
|
22
|
+
/** Error callback */
|
|
23
|
+
onError?: (error: Error) => void;
|
|
24
|
+
/** Load complete callback */
|
|
25
|
+
onLoad?: () => void;
|
|
26
|
+
/** Custom className for wrapper */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** Custom styles for wrapper */
|
|
29
|
+
style?: React.CSSProperties;
|
|
30
|
+
/** Show loading skeleton */
|
|
31
|
+
showSkeleton?: boolean;
|
|
32
|
+
/** Cache strategy */
|
|
33
|
+
cacheStrategy?: CacheStrategy;
|
|
34
|
+
/** Retry configuration */
|
|
35
|
+
retryConfig?: Partial<RetryConfig>;
|
|
36
|
+
/** Event handlers keyed by element ID then event name */
|
|
37
|
+
eventHandlers?: Record<string, Record<string, (e: Event) => void>>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* ServlyComponent - React wrapper for Servly runtime
|
|
41
|
+
*/
|
|
42
|
+
declare function ServlyComponent<P = Record<string, any>>({ id, version, props, fallback, onError, onLoad, className, style, showSkeleton, cacheStrategy, retryConfig, eventHandlers, }: ServlyComponentProps<P>): React.ReactElement | null;
|
|
43
|
+
|
|
44
|
+
export { ServlyComponent, type ServlyComponentProps, ServlyComponent as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CacheStrategy, RetryConfig } from '@servlyadmin/runtime-core';
|
|
3
|
+
export { BindingContext, CacheStrategy, ComponentData, FetchOptions, LayoutElement, PropDefinition, RetryConfig, clearAllCaches, compareVersions, fetchComponent, getRegistryUrl, invalidateCache, isComponentAvailable, parseVersion, prefetchComponents, resolveVersion, satisfiesVersion, setRegistryUrl } from '@servlyadmin/runtime-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ServlyComponent
|
|
7
|
+
* React wrapper for Servly runtime renderer
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Props for ServlyComponent
|
|
12
|
+
*/
|
|
13
|
+
interface ServlyComponentProps<P = Record<string, any>> {
|
|
14
|
+
/** Component ID from the registry */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Version specifier (exact, range, or "latest") */
|
|
17
|
+
version?: string;
|
|
18
|
+
/** Props to pass to the component */
|
|
19
|
+
props?: P;
|
|
20
|
+
/** Fallback UI while loading or on error */
|
|
21
|
+
fallback?: React.ReactNode;
|
|
22
|
+
/** Error callback */
|
|
23
|
+
onError?: (error: Error) => void;
|
|
24
|
+
/** Load complete callback */
|
|
25
|
+
onLoad?: () => void;
|
|
26
|
+
/** Custom className for wrapper */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** Custom styles for wrapper */
|
|
29
|
+
style?: React.CSSProperties;
|
|
30
|
+
/** Show loading skeleton */
|
|
31
|
+
showSkeleton?: boolean;
|
|
32
|
+
/** Cache strategy */
|
|
33
|
+
cacheStrategy?: CacheStrategy;
|
|
34
|
+
/** Retry configuration */
|
|
35
|
+
retryConfig?: Partial<RetryConfig>;
|
|
36
|
+
/** Event handlers keyed by element ID then event name */
|
|
37
|
+
eventHandlers?: Record<string, Record<string, (e: Event) => void>>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* ServlyComponent - React wrapper for Servly runtime
|
|
41
|
+
*/
|
|
42
|
+
declare function ServlyComponent<P = Record<string, any>>({ id, version, props, fallback, onError, onLoad, className, style, showSkeleton, cacheStrategy, retryConfig, eventHandlers, }: ServlyComponentProps<P>): React.ReactElement | null;
|
|
43
|
+
|
|
44
|
+
export { ServlyComponent, type ServlyComponentProps, ServlyComponent as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// src/ServlyComponent.tsx
|
|
2
|
+
import { useRef, useEffect, useState, useCallback } from "react";
|
|
3
|
+
import {
|
|
4
|
+
render,
|
|
5
|
+
fetchComponent
|
|
6
|
+
} from "@servlyadmin/runtime-core";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var LoadingSkeleton = ({ className }) => /* @__PURE__ */ jsx(
|
|
9
|
+
"div",
|
|
10
|
+
{
|
|
11
|
+
className: `servly-skeleton ${className || ""}`,
|
|
12
|
+
style: {
|
|
13
|
+
backgroundColor: "#f3f4f6",
|
|
14
|
+
borderRadius: "8px",
|
|
15
|
+
minHeight: "100px",
|
|
16
|
+
animation: "servly-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite"
|
|
17
|
+
},
|
|
18
|
+
children: /* @__PURE__ */ jsx("style", { children: `
|
|
19
|
+
@keyframes servly-pulse {
|
|
20
|
+
0%, 100% { opacity: 1; }
|
|
21
|
+
50% { opacity: 0.5; }
|
|
22
|
+
}
|
|
23
|
+
` })
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
var ErrorDisplay = ({ error, onRetry, className, style }) => /* @__PURE__ */ jsxs(
|
|
27
|
+
"div",
|
|
28
|
+
{
|
|
29
|
+
className: `servly-error ${className || ""}`,
|
|
30
|
+
style: {
|
|
31
|
+
padding: "16px",
|
|
32
|
+
color: "#ef4444",
|
|
33
|
+
backgroundColor: "#fef2f2",
|
|
34
|
+
borderRadius: "8px",
|
|
35
|
+
...style
|
|
36
|
+
},
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ jsx("p", { style: { margin: 0, fontWeight: 500 }, children: "Failed to load component" }),
|
|
39
|
+
/* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0", fontSize: "14px", color: "#991b1b" }, children: error.message }),
|
|
40
|
+
onRetry && /* @__PURE__ */ jsx(
|
|
41
|
+
"button",
|
|
42
|
+
{
|
|
43
|
+
onClick: onRetry,
|
|
44
|
+
style: {
|
|
45
|
+
marginTop: "12px",
|
|
46
|
+
padding: "8px 16px",
|
|
47
|
+
backgroundColor: "#ef4444",
|
|
48
|
+
color: "white",
|
|
49
|
+
border: "none",
|
|
50
|
+
borderRadius: "4px",
|
|
51
|
+
cursor: "pointer",
|
|
52
|
+
fontSize: "14px"
|
|
53
|
+
},
|
|
54
|
+
children: "Retry"
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
function ServlyComponent({
|
|
61
|
+
id,
|
|
62
|
+
version = "latest",
|
|
63
|
+
props = {},
|
|
64
|
+
fallback,
|
|
65
|
+
onError,
|
|
66
|
+
onLoad,
|
|
67
|
+
className,
|
|
68
|
+
style,
|
|
69
|
+
showSkeleton = true,
|
|
70
|
+
cacheStrategy = "memory",
|
|
71
|
+
retryConfig,
|
|
72
|
+
eventHandlers
|
|
73
|
+
}) {
|
|
74
|
+
const containerRef = useRef(null);
|
|
75
|
+
const renderResultRef = useRef(null);
|
|
76
|
+
const abortControllerRef = useRef(null);
|
|
77
|
+
const [state, setState] = useState({
|
|
78
|
+
loading: true,
|
|
79
|
+
error: null,
|
|
80
|
+
data: null
|
|
81
|
+
});
|
|
82
|
+
const loadComponent = useCallback(async () => {
|
|
83
|
+
if (abortControllerRef.current) {
|
|
84
|
+
abortControllerRef.current.abort();
|
|
85
|
+
}
|
|
86
|
+
abortControllerRef.current = new AbortController();
|
|
87
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
88
|
+
const fetchOptions = {
|
|
89
|
+
version,
|
|
90
|
+
cacheStrategy,
|
|
91
|
+
retryConfig,
|
|
92
|
+
signal: abortControllerRef.current.signal
|
|
93
|
+
};
|
|
94
|
+
try {
|
|
95
|
+
const result = await fetchComponent(id, fetchOptions);
|
|
96
|
+
setState({
|
|
97
|
+
loading: false,
|
|
98
|
+
error: null,
|
|
99
|
+
data: result.data
|
|
100
|
+
});
|
|
101
|
+
onLoad?.();
|
|
102
|
+
} catch (error) {
|
|
103
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
104
|
+
if (err.message === "Fetch aborted") return;
|
|
105
|
+
setState({
|
|
106
|
+
loading: false,
|
|
107
|
+
error: err,
|
|
108
|
+
data: null
|
|
109
|
+
});
|
|
110
|
+
onError?.(err);
|
|
111
|
+
}
|
|
112
|
+
}, [id, version, cacheStrategy, retryConfig, onLoad, onError]);
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
loadComponent();
|
|
115
|
+
return () => {
|
|
116
|
+
if (abortControllerRef.current) {
|
|
117
|
+
abortControllerRef.current.abort();
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}, [loadComponent]);
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
if (!state.data || !containerRef.current) return;
|
|
123
|
+
const context = {
|
|
124
|
+
props,
|
|
125
|
+
state: {},
|
|
126
|
+
context: {}
|
|
127
|
+
};
|
|
128
|
+
if (renderResultRef.current) {
|
|
129
|
+
renderResultRef.current.update(context);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
renderResultRef.current = render({
|
|
133
|
+
container: containerRef.current,
|
|
134
|
+
elements: state.data.layout,
|
|
135
|
+
context,
|
|
136
|
+
eventHandlers
|
|
137
|
+
});
|
|
138
|
+
return () => {
|
|
139
|
+
if (renderResultRef.current) {
|
|
140
|
+
renderResultRef.current.destroy();
|
|
141
|
+
renderResultRef.current = null;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}, [state.data, props, eventHandlers]);
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (!renderResultRef.current || !state.data) return;
|
|
147
|
+
const context = {
|
|
148
|
+
props,
|
|
149
|
+
state: {},
|
|
150
|
+
context: {}
|
|
151
|
+
};
|
|
152
|
+
renderResultRef.current.update(context);
|
|
153
|
+
}, [props, state.data]);
|
|
154
|
+
if (state.loading) {
|
|
155
|
+
if (fallback) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
156
|
+
if (showSkeleton) return /* @__PURE__ */ jsx(LoadingSkeleton, { className });
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
if (state.error) {
|
|
160
|
+
if (fallback) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
161
|
+
return /* @__PURE__ */ jsx(
|
|
162
|
+
ErrorDisplay,
|
|
163
|
+
{
|
|
164
|
+
error: state.error,
|
|
165
|
+
onRetry: loadComponent,
|
|
166
|
+
className,
|
|
167
|
+
style
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return /* @__PURE__ */ jsx(
|
|
172
|
+
"div",
|
|
173
|
+
{
|
|
174
|
+
ref: containerRef,
|
|
175
|
+
className: `servly-component ${className || ""}`,
|
|
176
|
+
style,
|
|
177
|
+
"data-servly-id": id,
|
|
178
|
+
"data-servly-version": state.data?.version
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
var ServlyComponent_default = ServlyComponent;
|
|
183
|
+
|
|
184
|
+
// src/index.ts
|
|
185
|
+
import {
|
|
186
|
+
fetchComponent as fetchComponent2,
|
|
187
|
+
prefetchComponents,
|
|
188
|
+
isComponentAvailable,
|
|
189
|
+
setRegistryUrl,
|
|
190
|
+
getRegistryUrl,
|
|
191
|
+
invalidateCache,
|
|
192
|
+
clearAllCaches,
|
|
193
|
+
parseVersion,
|
|
194
|
+
compareVersions,
|
|
195
|
+
satisfiesVersion,
|
|
196
|
+
resolveVersion
|
|
197
|
+
} from "@servlyadmin/runtime-core";
|
|
198
|
+
export {
|
|
199
|
+
ServlyComponent,
|
|
200
|
+
clearAllCaches,
|
|
201
|
+
compareVersions,
|
|
202
|
+
ServlyComponent_default as default,
|
|
203
|
+
fetchComponent2 as fetchComponent,
|
|
204
|
+
getRegistryUrl,
|
|
205
|
+
invalidateCache,
|
|
206
|
+
isComponentAvailable,
|
|
207
|
+
parseVersion,
|
|
208
|
+
prefetchComponents,
|
|
209
|
+
resolveVersion,
|
|
210
|
+
satisfiesVersion,
|
|
211
|
+
setRegistryUrl
|
|
212
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@servlyadmin/runtime-react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React wrapper for Servly runtime renderer",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean --external react",
|
|
22
|
+
"dev": "tsup src/index.ts --format esm,cjs --dts --watch --external react",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"servly",
|
|
28
|
+
"runtime",
|
|
29
|
+
"react",
|
|
30
|
+
"component"
|
|
31
|
+
],
|
|
32
|
+
"author": "Servly",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"react": ">=17.0.0",
|
|
36
|
+
"react-dom": ">=17.0.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@servlyadmin/runtime-core": "^0.1.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/react": "^18.2.0",
|
|
43
|
+
"@types/react-dom": "^18.2.0",
|
|
44
|
+
"react": "^18.2.0",
|
|
45
|
+
"react-dom": "^18.2.0",
|
|
46
|
+
"tsup": "^8.0.0",
|
|
47
|
+
"typescript": "^5.3.0",
|
|
48
|
+
"vitest": "^1.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|