@blocklet/pages-kit 0.4.16-beta.20250305-2 → 0.4.16-beta.20250306-1
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/lib/cjs/components/CustomComponentRenderer/ErrorComponent.js +40 -0
- package/lib/cjs/components/CustomComponentRenderer/index.js +3 -14
- package/lib/cjs/components/CustomComponentRenderer/state.js +117 -9
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/cjs/utils/inject-es-module-shims-options.js +9 -6
- package/lib/cjs/utils/inject-global-components.js +30 -29
- package/lib/cjs/utils/typescript/builtin-module-transformer.js +9 -9
- package/lib/esm/components/CustomComponentRenderer/ErrorComponent.js +36 -0
- package/lib/esm/components/CustomComponentRenderer/index.js +4 -15
- package/lib/esm/components/CustomComponentRenderer/state.js +119 -11
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/utils/inject-es-module-shims-options.js +7 -7
- package/lib/esm/utils/inject-global-components.js +30 -29
- package/lib/esm/utils/typescript/builtin-module-transformer.js +7 -8
- package/lib/types/components/CustomComponentRenderer/ErrorComponent.d.ts +14 -0
- package/lib/types/tsconfig.tsbuildinfo +1 -1
- package/lib/types/types/preload.d.ts +1 -1
- package/lib/types/utils/inject-es-module-shims-options.d.ts +1 -0
- package/lib/types/utils/typescript/builtin-module-transformer.d.ts +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.ComponentError = void 0;
|
|
15
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
16
|
+
const material_1 = require("@mui/material");
|
|
17
|
+
const ComponentError = (_a) => {
|
|
18
|
+
var { title = 'Component Failed to Load', message, componentId, componentName, blockletId, blockletTitle, showHints = false, error, resetErrorBoundary } = _a, rest = __rest(_a, ["title", "message", "componentId", "componentName", "blockletId", "blockletTitle", "showHints", "error", "resetErrorBoundary"]);
|
|
19
|
+
// 如果提供了error但没有message,使用error.message
|
|
20
|
+
const displayMessage = message || (error ? error.message : 'Unknown error');
|
|
21
|
+
console.warn(rest);
|
|
22
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: {
|
|
23
|
+
p: 3,
|
|
24
|
+
border: '1px dashed #d32f2f',
|
|
25
|
+
borderRadius: 1,
|
|
26
|
+
bgcolor: 'rgba(211, 47, 47, 0.04)',
|
|
27
|
+
display: 'flex',
|
|
28
|
+
flexDirection: 'column',
|
|
29
|
+
gap: 1,
|
|
30
|
+
}, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle1", sx: { color: '#d32f2f', fontWeight: 500 }, children: title }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", sx: { color: 'text.secondary' }, children: displayMessage }), error && error.stack && process.env.NODE_ENV !== 'production' && ((0, jsx_runtime_1.jsx)(material_1.Box, { component: "pre", sx: {
|
|
31
|
+
mt: 2,
|
|
32
|
+
p: 1,
|
|
33
|
+
bgcolor: 'rgba(0,0,0,0.04)',
|
|
34
|
+
borderRadius: 1,
|
|
35
|
+
fontSize: '0.75rem',
|
|
36
|
+
overflow: 'auto',
|
|
37
|
+
maxHeight: '200px',
|
|
38
|
+
}, children: error.stack })), showHints && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", sx: { color: 'text.secondary' }, children: "Please try the following:" }), (0, jsx_runtime_1.jsxs)(material_1.Box, { component: "ul", sx: { m: 0, pl: 2 }, children: [componentId && ((0, jsx_runtime_1.jsxs)(material_1.Typography, { component: "li", variant: "body2", sx: { color: 'text.secondary' }, children: ["Select component", ' ', (0, jsx_runtime_1.jsx)(material_1.Box, { component: "span", sx: { fontWeight: 500 }, children: componentName !== null && componentName !== void 0 ? componentName : componentId }), ' ', "in settings or create this component."] })), (blockletId || blockletTitle) && ((0, jsx_runtime_1.jsxs)(material_1.Typography, { component: "li", variant: "body2", sx: { color: 'text.secondary' }, children: ["Contact administrator to install", ' ', (0, jsx_runtime_1.jsx)(material_1.Box, { component: "span", sx: { fontWeight: 500 }, children: blockletTitle !== null && blockletTitle !== void 0 ? blockletTitle : blockletId }), ' ', "Blocklet"] }))] })] })), resetErrorBoundary && ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: { mt: 2 }, children: (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", color: "error", size: "small", onClick: resetErrorBoundary, children: "Try Again" }) }))] }));
|
|
39
|
+
};
|
|
40
|
+
exports.ComponentError = ComponentError;
|
|
@@ -30,11 +30,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
30
30
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
31
|
exports.default = CustomComponentRenderer;
|
|
32
32
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
33
|
-
const material_1 = require("@mui/material");
|
|
34
33
|
const react_error_boundary_1 = require("react-error-boundary");
|
|
35
34
|
const property_1 = require("../../utils/property");
|
|
36
35
|
const BlockletReactComponentRenderer_1 = __importDefault(require("./BlockletReactComponentRenderer"));
|
|
37
36
|
const DevProvider_1 = require("./DevProvider");
|
|
37
|
+
const ErrorComponent_1 = require("./ErrorComponent");
|
|
38
38
|
const context_1 = require("./context");
|
|
39
39
|
const state_1 = require("./state");
|
|
40
40
|
__exportStar(require("./state"), exports);
|
|
@@ -45,14 +45,11 @@ function CustomComponentRenderer(_a) {
|
|
|
45
45
|
var { dev } = _a, props = __rest(_a, ["dev"]);
|
|
46
46
|
const inheritedDev = (0, DevProvider_1.useDev)();
|
|
47
47
|
const BuiltinComponent = BuiltinComponents[props.componentId];
|
|
48
|
-
return ((0, jsx_runtime_1.jsx)(react_error_boundary_1.ErrorBoundary, { FallbackComponent: (props === null || props === void 0 ? void 0 : props.fallbackRender) ||
|
|
48
|
+
return ((0, jsx_runtime_1.jsx)(react_error_boundary_1.ErrorBoundary, { FallbackComponent: (props === null || props === void 0 ? void 0 : props.fallbackRender) || ErrorComponent_1.ComponentError, resetKeys: [Date.now()], children: (0, jsx_runtime_1.jsx)(DevProvider_1.DevProvider, { dev: dev !== null && dev !== void 0 ? dev : inheritedDev, children: BuiltinComponent ? ((0, jsx_runtime_1.jsx)(BuiltinComponent, Object.assign({}, props))) : ((0, jsx_runtime_1.jsx)(ComponentRenderer, Object.assign({}, props, { instanceId: (_b = props.instanceId) !== null && _b !== void 0 ? _b : props.componentId, renderType: props.renderType }))) }) }));
|
|
49
49
|
}
|
|
50
50
|
const BuiltinComponents = {
|
|
51
51
|
'blocklet-react-component': BlockletReactComponentRenderer_1.default,
|
|
52
52
|
};
|
|
53
|
-
function ErrorView({ error }) {
|
|
54
|
-
return ((0, jsx_runtime_1.jsx)(material_1.Box, { children: (0, jsx_runtime_1.jsx)(material_1.Alert, { severity: "error", children: error.message }) }));
|
|
55
|
-
}
|
|
56
53
|
function ComponentRenderer(_a) {
|
|
57
54
|
var _b;
|
|
58
55
|
var { renderCount = 0, blockletId, blockletTitle, componentName, renderType = 'view' } = _a, props = __rest(_a, ["renderCount", "blockletId", "blockletTitle", "componentName", "renderType"]);
|
|
@@ -77,15 +74,7 @@ function ComponentRenderer(_a) {
|
|
|
77
74
|
}
|
|
78
75
|
// if the component is not in the dev.components, it means the component is not loaded
|
|
79
76
|
if ((dev === null || dev === void 0 ? void 0 : dev.mode) === 'draft' && dev && ((_b = dev.components) === null || _b === void 0 ? void 0 : _b[props.componentId]) === undefined) {
|
|
80
|
-
return ((0, jsx_runtime_1.
|
|
81
|
-
p: 3,
|
|
82
|
-
border: '1px dashed #d32f2f',
|
|
83
|
-
borderRadius: 1,
|
|
84
|
-
bgcolor: 'rgba(211, 47, 47, 0.04)',
|
|
85
|
-
display: 'flex',
|
|
86
|
-
flexDirection: 'column',
|
|
87
|
-
gap: 1,
|
|
88
|
-
}, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle1", sx: { color: '#d32f2f', fontWeight: 500 }, children: "Component Failed to Load" }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", sx: { color: 'text.secondary' }, children: "Please try the following:" }), (0, jsx_runtime_1.jsxs)(material_1.Box, { component: "ul", sx: { m: 0, pl: 2 }, children: [(0, jsx_runtime_1.jsxs)(material_1.Typography, { component: "li", variant: "body2", sx: { color: 'text.secondary' }, children: ["Select component", ' ', (0, jsx_runtime_1.jsx)(material_1.Box, { component: "span", sx: { fontWeight: 500 }, children: componentName !== null && componentName !== void 0 ? componentName : props.componentId }), ' ', "in settings or create this component."] }), (blockletId || blockletTitle) && ((0, jsx_runtime_1.jsxs)(material_1.Typography, { component: "li", variant: "body2", sx: { color: 'text.secondary' }, children: ["Contact administrator to install", ' ', (0, jsx_runtime_1.jsx)(material_1.Box, { component: "span", sx: { fontWeight: 500 }, children: blockletTitle !== null && blockletTitle !== void 0 ? blockletTitle : blockletId }), ' ', "Blocklet"] }))] })] }));
|
|
77
|
+
return ((0, jsx_runtime_1.jsx)(ErrorComponent_1.ComponentError, { componentId: props.componentId, componentName: componentName, blockletId: blockletId, blockletTitle: blockletTitle, message: "Component not found in available components", showHints: true }));
|
|
89
78
|
}
|
|
90
79
|
return null;
|
|
91
80
|
}
|
|
@@ -52,6 +52,7 @@ exports.useComponent = useComponent;
|
|
|
52
52
|
exports.transpileAndLoadScript = transpileAndLoadScript;
|
|
53
53
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
54
54
|
const css_1 = require("@emotion/css");
|
|
55
|
+
const material_1 = require("@mui/material");
|
|
55
56
|
const lodash_1 = require("lodash");
|
|
56
57
|
const set_1 = __importDefault(require("lodash/set"));
|
|
57
58
|
const react_1 = require("react");
|
|
@@ -63,17 +64,109 @@ const api_1 = require("../../api");
|
|
|
63
64
|
const types_1 = require("../../types");
|
|
64
65
|
const preload_1 = require("../../types/preload");
|
|
65
66
|
const property_1 = require("../../utils/property");
|
|
67
|
+
const ErrorComponent_1 = require("./ErrorComponent");
|
|
66
68
|
const PRELOAD_COMPONENTS_STATE = window[preload_1.PreloadComponentsStateGlobalVariableName];
|
|
67
69
|
let states;
|
|
68
70
|
function importCustomComponent(m, { componentId }) {
|
|
71
|
+
// check if m is a Promise
|
|
72
|
+
if (m && typeof m.then === 'function') {
|
|
73
|
+
// handle Promise case
|
|
74
|
+
return (props) => {
|
|
75
|
+
const [loading, setLoading] = (0, react_1.useState)(true);
|
|
76
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
77
|
+
const [ResolvedComponent, setResolvedComponent] = (0, react_1.useState)(null);
|
|
78
|
+
// 只在组件首次加载时执行,避免重复加载
|
|
79
|
+
(0, react_1.useEffect)(() => {
|
|
80
|
+
let isMounted = true;
|
|
81
|
+
const loadComponent = () => __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
try {
|
|
83
|
+
const result = yield m;
|
|
84
|
+
if (!isMounted)
|
|
85
|
+
return;
|
|
86
|
+
if (!result) {
|
|
87
|
+
setError(new Error(`Component ${componentId} resolved to empty value`));
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const Component = importCustomComponent(result, { componentId });
|
|
91
|
+
if (Component) {
|
|
92
|
+
// 存储组件引用而不是渲染结果
|
|
93
|
+
setResolvedComponent(() => Component);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
setError(new Error(`Failed to resolve component ${componentId}`));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
if (!isMounted)
|
|
102
|
+
return;
|
|
103
|
+
console.error(`Component loading error (${componentId}):`, err);
|
|
104
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
if (isMounted) {
|
|
108
|
+
setLoading(false);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
loadComponent();
|
|
113
|
+
return () => {
|
|
114
|
+
isMounted = false;
|
|
115
|
+
};
|
|
116
|
+
}, []); // 仅在组件挂载时执行一次
|
|
117
|
+
// 使用useMemo缓存渲染内容,避免不必要的重计算
|
|
118
|
+
const content = (0, react_1.useMemo)(() => {
|
|
119
|
+
if (loading) {
|
|
120
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { width: '100%', p: 1 }, children: [(0, jsx_runtime_1.jsx)(material_1.Skeleton, { variant: "rectangular", width: "100%", height: 60, animation: "wave" }), (0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { pt: 1 }, children: [(0, jsx_runtime_1.jsx)(material_1.Skeleton, { width: "80%" }), (0, jsx_runtime_1.jsx)(material_1.Skeleton, { width: "60%" }), (0, jsx_runtime_1.jsx)(material_1.Skeleton, { width: "40%" })] })] }));
|
|
121
|
+
}
|
|
122
|
+
if (error) {
|
|
123
|
+
return (0, jsx_runtime_1.jsx)(ErrorComponent_1.ComponentError, { componentId: componentId, message: error.message });
|
|
124
|
+
}
|
|
125
|
+
// 动态渲染组件,但允许props更新传递
|
|
126
|
+
if (ResolvedComponent) {
|
|
127
|
+
return (0, jsx_runtime_1.jsx)(ResolvedComponent, Object.assign({}, props));
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}, [loading, error, ResolvedComponent, props]);
|
|
131
|
+
return ((0, jsx_runtime_1.jsx)(material_1.Fade, { in: !loading, timeout: 500, children: (0, jsx_runtime_1.jsx)(material_1.Box, { children: content }) }));
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// non-Promise case
|
|
135
|
+
// empty value check
|
|
136
|
+
if (!m) {
|
|
137
|
+
console.warn(`Component ${componentId} resolved to empty value`);
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
69
140
|
let Component;
|
|
70
141
|
const css = m.__PagesKit_CSS__;
|
|
71
|
-
|
|
142
|
+
// smart handle component
|
|
143
|
+
if (typeof m === 'function') {
|
|
144
|
+
// the function itself may be a component
|
|
72
145
|
Component = m;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
146
|
+
}
|
|
147
|
+
else if (m.default) {
|
|
148
|
+
// has default export
|
|
149
|
+
if (typeof m.default === 'function') {
|
|
150
|
+
// default is a function may be a component
|
|
151
|
+
Component = m.default;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// default is not a function, maybe a JSX element
|
|
155
|
+
Component = () => m.default;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else if (css) {
|
|
159
|
+
// has CSS but no valid component found
|
|
160
|
+
console.warn(`Component ${componentId} has CSS but no valid component found`);
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
// if a component is found and has CSS, wrap the component with styles
|
|
164
|
+
if (Component && css) {
|
|
165
|
+
const OriginalComponent = Component;
|
|
166
|
+
Component = (props) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_helmet_1.Helmet, { children: (0, jsx_runtime_1.jsx)("style", { children: css }) }), (0, jsx_runtime_1.jsx)(OriginalComponent, Object.assign({}, props, { className: (0, css_1.cx)(props.className, `CustomComponent_${componentId}`) }))] }));
|
|
167
|
+
}
|
|
168
|
+
// keep aigneOutputValueSchema
|
|
169
|
+
if (Component && m.aigneOutputValueSchema) {
|
|
77
170
|
Component.aigneOutputValueSchema = m.aigneOutputValueSchema;
|
|
78
171
|
}
|
|
79
172
|
return Component;
|
|
@@ -105,14 +198,29 @@ const customComponentStates = () => {
|
|
|
105
198
|
states !== null && states !== void 0 ? states : (states = (0, zustand_1.create)()((0, immer_1.immer)((set, get) => ({
|
|
106
199
|
state: {
|
|
107
200
|
config: Object.assign({}, PRELOAD_COMPONENTS_STATE === null || PRELOAD_COMPONENTS_STATE === void 0 ? void 0 : PRELOAD_COMPONENTS_STATE.config),
|
|
108
|
-
components: Object.fromEntries(Object.entries(Object.assign({}, PRELOAD_COMPONENTS_STATE === null || PRELOAD_COMPONENTS_STATE === void 0 ? void 0 : PRELOAD_COMPONENTS_STATE.components))
|
|
201
|
+
components: Object.fromEntries(Object.entries(Object.assign({}, PRELOAD_COMPONENTS_STATE === null || PRELOAD_COMPONENTS_STATE === void 0 ? void 0 : PRELOAD_COMPONENTS_STATE.components))
|
|
202
|
+
.map(([componentId, preload]) => {
|
|
109
203
|
let Component;
|
|
110
204
|
if (preload.componentModuleGlobalVariable) {
|
|
111
205
|
const m = window[preload.componentModuleGlobalVariable];
|
|
112
|
-
|
|
206
|
+
// handle the global variable
|
|
207
|
+
if (typeof m === 'function') {
|
|
208
|
+
try {
|
|
209
|
+
// call m() to get the component module
|
|
210
|
+
const modulePromiseOrObject = m();
|
|
211
|
+
Component = importCustomComponent(modulePromiseOrObject, { componentId });
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
console.error(`Failed to initialize component ${componentId}:`, err);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
console.warn(`Component global variable ${preload.componentModuleGlobalVariable} is not a function`);
|
|
219
|
+
}
|
|
113
220
|
}
|
|
114
221
|
return [componentId, Object.assign(Object.assign({}, preload), { Component })];
|
|
115
|
-
})
|
|
222
|
+
})
|
|
223
|
+
.filter((i) => !!i)),
|
|
116
224
|
instances: Object.assign({}, PRELOAD_COMPONENTS_STATE === null || PRELOAD_COMPONENTS_STATE === void 0 ? void 0 : PRELOAD_COMPONENTS_STATE.instances),
|
|
117
225
|
},
|
|
118
226
|
getComponent({ instanceId, componentId, locale }) {
|
|
@@ -306,7 +414,7 @@ function transpileAndLoadScript(script) {
|
|
|
306
414
|
before: [createBuiltinModuleTransformer(ts)],
|
|
307
415
|
},
|
|
308
416
|
}).outputText;
|
|
309
|
-
//
|
|
417
|
+
// fallback to the original handling
|
|
310
418
|
const url = URL.createObjectURL(new Blob([compiled], { type: 'application/javascript' }));
|
|
311
419
|
try {
|
|
312
420
|
return yield Promise.resolve(`${url}`).then(s => __importStar(require(s)));
|