@servlyadmin/runtime-react 0.1.31 → 0.1.34
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 +46 -26
- package/dist/index.js +50 -27
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -41,6 +41,11 @@ var import_react = require("react");
|
|
|
41
41
|
var import_react_dom = require("react-dom");
|
|
42
42
|
var import_runtime_core = require("@servlyadmin/runtime-core");
|
|
43
43
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
44
|
+
if (typeof document !== "undefined") {
|
|
45
|
+
(0, import_runtime_core.injectTailwind)({ usePlayCdn: true }).catch((err) => {
|
|
46
|
+
console.warn("[ServlyComponent React] Failed to inject Tailwind:", err);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
44
49
|
var LoadingSkeleton = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
45
50
|
"div",
|
|
46
51
|
{
|
|
@@ -126,7 +131,8 @@ function ServlyComponent({
|
|
|
126
131
|
cacheStrategy = "memory",
|
|
127
132
|
retryConfig,
|
|
128
133
|
eventHandlers,
|
|
129
|
-
children
|
|
134
|
+
children,
|
|
135
|
+
waitForStyles = true
|
|
130
136
|
}) {
|
|
131
137
|
const containerRef = (0, import_react.useRef)(null);
|
|
132
138
|
const renderResultRef = (0, import_react.useRef)(null);
|
|
@@ -135,7 +141,9 @@ function ServlyComponent({
|
|
|
135
141
|
const [state, setState] = (0, import_react.useState)({
|
|
136
142
|
loading: true,
|
|
137
143
|
error: null,
|
|
138
|
-
data: null
|
|
144
|
+
data: null,
|
|
145
|
+
stylesReady: !waitForStyles
|
|
146
|
+
// If not waiting, styles are "ready"
|
|
139
147
|
});
|
|
140
148
|
const slotElements = useSlotElements(containerRef, isRendered);
|
|
141
149
|
const effectiveSlots = (0, import_react.useMemo)(() => {
|
|
@@ -160,24 +168,26 @@ function ServlyComponent({
|
|
|
160
168
|
};
|
|
161
169
|
try {
|
|
162
170
|
const result = await (0, import_runtime_core.fetchComponent)(id, fetchOptions);
|
|
163
|
-
setState({
|
|
171
|
+
setState((prev) => ({
|
|
172
|
+
...prev,
|
|
164
173
|
loading: false,
|
|
165
174
|
error: null,
|
|
166
175
|
data: result.data,
|
|
167
176
|
views: result.views,
|
|
168
177
|
registry: result.registry
|
|
169
|
-
});
|
|
178
|
+
}));
|
|
170
179
|
onLoad?.();
|
|
171
180
|
} catch (error) {
|
|
172
181
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
173
182
|
if (err.message === "Fetch aborted") return;
|
|
174
|
-
setState({
|
|
183
|
+
setState((prev) => ({
|
|
184
|
+
...prev,
|
|
175
185
|
loading: false,
|
|
176
186
|
error: err,
|
|
177
187
|
data: null,
|
|
178
188
|
views: void 0,
|
|
179
189
|
registry: void 0
|
|
180
|
-
});
|
|
190
|
+
}));
|
|
181
191
|
onError?.(err);
|
|
182
192
|
}
|
|
183
193
|
}, [id, version, cacheStrategy, retryConfig, onLoad, onError]);
|
|
@@ -191,24 +201,34 @@ function ServlyComponent({
|
|
|
191
201
|
}, [loadComponent]);
|
|
192
202
|
(0, import_react.useEffect)(() => {
|
|
193
203
|
if (!state.data || !containerRef.current) return;
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
204
|
+
const doRender = async () => {
|
|
205
|
+
if (waitForStyles) {
|
|
206
|
+
await (0, import_runtime_core.waitForTailwind)();
|
|
207
|
+
setState((prev) => ({ ...prev, stylesReady: true }));
|
|
208
|
+
}
|
|
209
|
+
const context = {
|
|
210
|
+
props,
|
|
211
|
+
state: {},
|
|
212
|
+
context: {}
|
|
213
|
+
};
|
|
214
|
+
if (renderResultRef.current) {
|
|
215
|
+
renderResultRef.current.update(context);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
renderResultRef.current = (0, import_runtime_core.render)({
|
|
219
|
+
container: containerRef.current,
|
|
220
|
+
elements: state.data.layout,
|
|
221
|
+
context,
|
|
222
|
+
eventHandlers,
|
|
223
|
+
views: state.views,
|
|
224
|
+
componentRegistry: state.registry
|
|
225
|
+
});
|
|
226
|
+
if (containerRef.current) {
|
|
227
|
+
(0, import_runtime_core.markElementReady)(containerRef.current);
|
|
228
|
+
}
|
|
229
|
+
setIsRendered(true);
|
|
198
230
|
};
|
|
199
|
-
|
|
200
|
-
renderResultRef.current.update(context);
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
renderResultRef.current = (0, import_runtime_core.render)({
|
|
204
|
-
container: containerRef.current,
|
|
205
|
-
elements: state.data.layout,
|
|
206
|
-
context,
|
|
207
|
-
eventHandlers,
|
|
208
|
-
views: state.views,
|
|
209
|
-
componentRegistry: state.registry
|
|
210
|
-
});
|
|
211
|
-
setIsRendered(true);
|
|
231
|
+
doRender();
|
|
212
232
|
return () => {
|
|
213
233
|
if (renderResultRef.current) {
|
|
214
234
|
renderResultRef.current.destroy();
|
|
@@ -216,7 +236,7 @@ function ServlyComponent({
|
|
|
216
236
|
setIsRendered(false);
|
|
217
237
|
}
|
|
218
238
|
};
|
|
219
|
-
}, [state.data, eventHandlers]);
|
|
239
|
+
}, [state.data, eventHandlers, waitForStyles]);
|
|
220
240
|
(0, import_react.useEffect)(() => {
|
|
221
241
|
if (!renderResultRef.current || !state.data) return;
|
|
222
242
|
const context = {
|
|
@@ -226,7 +246,7 @@ function ServlyComponent({
|
|
|
226
246
|
};
|
|
227
247
|
renderResultRef.current.update(context);
|
|
228
248
|
}, [props, state.data]);
|
|
229
|
-
if (state.loading) {
|
|
249
|
+
if (state.loading || waitForStyles && !state.stylesReady) {
|
|
230
250
|
if (fallback) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: fallback });
|
|
231
251
|
if (showSkeleton) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoadingSkeleton, { className });
|
|
232
252
|
return null;
|
|
@@ -248,7 +268,7 @@ function ServlyComponent({
|
|
|
248
268
|
"div",
|
|
249
269
|
{
|
|
250
270
|
ref: containerRef,
|
|
251
|
-
className: `servly-component ${className || ""}`,
|
|
271
|
+
className: `servly-component servly-ready ${className || ""}`,
|
|
252
272
|
style,
|
|
253
273
|
"data-servly-id": id,
|
|
254
274
|
"data-servly-version": state.data?.version
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,17 @@ import { useRef, useEffect, useState, useCallback, useMemo } from "react";
|
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
4
|
import {
|
|
5
5
|
render,
|
|
6
|
-
fetchComponent
|
|
6
|
+
fetchComponent,
|
|
7
|
+
waitForTailwind,
|
|
8
|
+
markElementReady,
|
|
9
|
+
injectTailwind
|
|
7
10
|
} from "@servlyadmin/runtime-core";
|
|
8
11
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
if (typeof document !== "undefined") {
|
|
13
|
+
injectTailwind({ usePlayCdn: true }).catch((err) => {
|
|
14
|
+
console.warn("[ServlyComponent React] Failed to inject Tailwind:", err);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
9
17
|
var LoadingSkeleton = ({ className }) => /* @__PURE__ */ jsx(
|
|
10
18
|
"div",
|
|
11
19
|
{
|
|
@@ -91,7 +99,8 @@ function ServlyComponent({
|
|
|
91
99
|
cacheStrategy = "memory",
|
|
92
100
|
retryConfig,
|
|
93
101
|
eventHandlers,
|
|
94
|
-
children
|
|
102
|
+
children,
|
|
103
|
+
waitForStyles = true
|
|
95
104
|
}) {
|
|
96
105
|
const containerRef = useRef(null);
|
|
97
106
|
const renderResultRef = useRef(null);
|
|
@@ -100,7 +109,9 @@ function ServlyComponent({
|
|
|
100
109
|
const [state, setState] = useState({
|
|
101
110
|
loading: true,
|
|
102
111
|
error: null,
|
|
103
|
-
data: null
|
|
112
|
+
data: null,
|
|
113
|
+
stylesReady: !waitForStyles
|
|
114
|
+
// If not waiting, styles are "ready"
|
|
104
115
|
});
|
|
105
116
|
const slotElements = useSlotElements(containerRef, isRendered);
|
|
106
117
|
const effectiveSlots = useMemo(() => {
|
|
@@ -125,24 +136,26 @@ function ServlyComponent({
|
|
|
125
136
|
};
|
|
126
137
|
try {
|
|
127
138
|
const result = await fetchComponent(id, fetchOptions);
|
|
128
|
-
setState({
|
|
139
|
+
setState((prev) => ({
|
|
140
|
+
...prev,
|
|
129
141
|
loading: false,
|
|
130
142
|
error: null,
|
|
131
143
|
data: result.data,
|
|
132
144
|
views: result.views,
|
|
133
145
|
registry: result.registry
|
|
134
|
-
});
|
|
146
|
+
}));
|
|
135
147
|
onLoad?.();
|
|
136
148
|
} catch (error) {
|
|
137
149
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
138
150
|
if (err.message === "Fetch aborted") return;
|
|
139
|
-
setState({
|
|
151
|
+
setState((prev) => ({
|
|
152
|
+
...prev,
|
|
140
153
|
loading: false,
|
|
141
154
|
error: err,
|
|
142
155
|
data: null,
|
|
143
156
|
views: void 0,
|
|
144
157
|
registry: void 0
|
|
145
|
-
});
|
|
158
|
+
}));
|
|
146
159
|
onError?.(err);
|
|
147
160
|
}
|
|
148
161
|
}, [id, version, cacheStrategy, retryConfig, onLoad, onError]);
|
|
@@ -156,24 +169,34 @@ function ServlyComponent({
|
|
|
156
169
|
}, [loadComponent]);
|
|
157
170
|
useEffect(() => {
|
|
158
171
|
if (!state.data || !containerRef.current) return;
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
172
|
+
const doRender = async () => {
|
|
173
|
+
if (waitForStyles) {
|
|
174
|
+
await waitForTailwind();
|
|
175
|
+
setState((prev) => ({ ...prev, stylesReady: true }));
|
|
176
|
+
}
|
|
177
|
+
const context = {
|
|
178
|
+
props,
|
|
179
|
+
state: {},
|
|
180
|
+
context: {}
|
|
181
|
+
};
|
|
182
|
+
if (renderResultRef.current) {
|
|
183
|
+
renderResultRef.current.update(context);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
renderResultRef.current = render({
|
|
187
|
+
container: containerRef.current,
|
|
188
|
+
elements: state.data.layout,
|
|
189
|
+
context,
|
|
190
|
+
eventHandlers,
|
|
191
|
+
views: state.views,
|
|
192
|
+
componentRegistry: state.registry
|
|
193
|
+
});
|
|
194
|
+
if (containerRef.current) {
|
|
195
|
+
markElementReady(containerRef.current);
|
|
196
|
+
}
|
|
197
|
+
setIsRendered(true);
|
|
163
198
|
};
|
|
164
|
-
|
|
165
|
-
renderResultRef.current.update(context);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
renderResultRef.current = render({
|
|
169
|
-
container: containerRef.current,
|
|
170
|
-
elements: state.data.layout,
|
|
171
|
-
context,
|
|
172
|
-
eventHandlers,
|
|
173
|
-
views: state.views,
|
|
174
|
-
componentRegistry: state.registry
|
|
175
|
-
});
|
|
176
|
-
setIsRendered(true);
|
|
199
|
+
doRender();
|
|
177
200
|
return () => {
|
|
178
201
|
if (renderResultRef.current) {
|
|
179
202
|
renderResultRef.current.destroy();
|
|
@@ -181,7 +204,7 @@ function ServlyComponent({
|
|
|
181
204
|
setIsRendered(false);
|
|
182
205
|
}
|
|
183
206
|
};
|
|
184
|
-
}, [state.data, eventHandlers]);
|
|
207
|
+
}, [state.data, eventHandlers, waitForStyles]);
|
|
185
208
|
useEffect(() => {
|
|
186
209
|
if (!renderResultRef.current || !state.data) return;
|
|
187
210
|
const context = {
|
|
@@ -191,7 +214,7 @@ function ServlyComponent({
|
|
|
191
214
|
};
|
|
192
215
|
renderResultRef.current.update(context);
|
|
193
216
|
}, [props, state.data]);
|
|
194
|
-
if (state.loading) {
|
|
217
|
+
if (state.loading || waitForStyles && !state.stylesReady) {
|
|
195
218
|
if (fallback) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
196
219
|
if (showSkeleton) return /* @__PURE__ */ jsx(LoadingSkeleton, { className });
|
|
197
220
|
return null;
|
|
@@ -213,7 +236,7 @@ function ServlyComponent({
|
|
|
213
236
|
"div",
|
|
214
237
|
{
|
|
215
238
|
ref: containerRef,
|
|
216
|
-
className: `servly-component ${className || ""}`,
|
|
239
|
+
className: `servly-component servly-ready ${className || ""}`,
|
|
217
240
|
style,
|
|
218
241
|
"data-servly-id": id,
|
|
219
242
|
"data-servly-version": state.data?.version
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servlyadmin/runtime-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
4
4
|
"description": "React wrapper for Servly runtime renderer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"react-dom": ">=17.0.0"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@servlyadmin/runtime-core": "^0.1.
|
|
39
|
+
"@servlyadmin/runtime-core": "^0.1.44"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/react": "^18.2.0",
|