@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.
@@ -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) || ErrorView, 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 }))) }) }));
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.jsxs)(material_1.Box, { sx: {
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
- if (typeof m === 'function')
142
+ // smart handle component
143
+ if (typeof m === 'function') {
144
+ // the function itself may be a component
72
145
  Component = m;
73
- else if (!css)
74
- Component = m.default;
75
- else {
76
- 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)(m.default, Object.assign({}, props, { className: (0, css_1.cx)(props.className, `CustomComponent_${componentId}`) }))] }));
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)).map(([componentId, preload]) => {
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
- Component = typeof m === 'function' ? importCustomComponent(m(), { componentId }) : undefined;
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)));