@web-widget/react 0.0.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/dist/babel-plugin.d.ts +14 -0
- package/dist/babel-plugin.js +127 -0
- package/dist/react.client.d.ts +21 -0
- package/dist/react.client.js +208 -0
- package/dist/react.server.d.ts +9 -0
- package/dist/react.server.js +200 -0
- package/dist/vite-plugin.d.ts +6 -0
- package/dist/vite-plugin.js +57 -0
- package/dist/web-widget-ec342172.d.ts +60 -0
- package/globals.d.ts +9 -0
- package/package.json +65 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PluginPass } from '@babel/core';
|
|
2
|
+
import { Visitor } from '@babel/traverse';
|
|
3
|
+
|
|
4
|
+
type Config = {
|
|
5
|
+
base: string;
|
|
6
|
+
root: string;
|
|
7
|
+
isServer: boolean;
|
|
8
|
+
};
|
|
9
|
+
declare const _default: (api: object, options: Record<string, any> | null | undefined, dirname: string) => {
|
|
10
|
+
name: string;
|
|
11
|
+
visitor: Visitor<PluginPass>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export { Config, _default as default };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// src/babel-plugin.ts
|
|
2
|
+
import { addNamed } from "@babel/helper-module-imports";
|
|
3
|
+
import { declare } from "@babel/helper-plugin-utils";
|
|
4
|
+
import { types as t } from "@babel/core";
|
|
5
|
+
function createWebWidgetVariableDeclaration(definer, component, source, base, options) {
|
|
6
|
+
const getType = (object) => Object.prototype.toString.call(object).slice(8, -1).toLocaleLowerCase();
|
|
7
|
+
return t.variableDeclaration("const", [
|
|
8
|
+
t.variableDeclarator(
|
|
9
|
+
t.identifier(component),
|
|
10
|
+
t.callExpression(t.identifier(definer), [
|
|
11
|
+
t.arrowFunctionExpression(
|
|
12
|
+
[],
|
|
13
|
+
t.callExpression(t.import(), [t.stringLiteral(source)])
|
|
14
|
+
),
|
|
15
|
+
t.stringLiteral(base),
|
|
16
|
+
t.objectExpression(
|
|
17
|
+
Object.keys(options).map((key) => {
|
|
18
|
+
const value = options[key];
|
|
19
|
+
const type = getType(value);
|
|
20
|
+
switch (type) {
|
|
21
|
+
case "string":
|
|
22
|
+
return t.objectProperty(
|
|
23
|
+
t.identifier(key),
|
|
24
|
+
t.stringLiteral(value)
|
|
25
|
+
);
|
|
26
|
+
case "number":
|
|
27
|
+
return t.objectProperty(
|
|
28
|
+
t.identifier(key),
|
|
29
|
+
t.numericLiteral(value)
|
|
30
|
+
);
|
|
31
|
+
case "boolean":
|
|
32
|
+
return t.objectProperty(
|
|
33
|
+
t.identifier(key),
|
|
34
|
+
t.booleanLiteral(value)
|
|
35
|
+
);
|
|
36
|
+
case "null":
|
|
37
|
+
return t.objectProperty(t.identifier(key), t.nullLiteral());
|
|
38
|
+
}
|
|
39
|
+
throw new Error(`Type not supported: ${key}=${value}`);
|
|
40
|
+
})
|
|
41
|
+
)
|
|
42
|
+
])
|
|
43
|
+
)
|
|
44
|
+
]);
|
|
45
|
+
}
|
|
46
|
+
var babel_plugin_default = declare((api) => {
|
|
47
|
+
api.assertVersion(7);
|
|
48
|
+
let config;
|
|
49
|
+
const visitor = {
|
|
50
|
+
Program: {
|
|
51
|
+
enter(path, { opts }) {
|
|
52
|
+
config = opts;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
JSXOpeningElement(path, state) {
|
|
56
|
+
if (!state.filename) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const name = path.node.name;
|
|
60
|
+
let bindingName;
|
|
61
|
+
if (t.isJSXIdentifier(name)) {
|
|
62
|
+
bindingName = name.name;
|
|
63
|
+
} else if (t.isJSXMemberExpression(name)) {
|
|
64
|
+
let object = name.object;
|
|
65
|
+
while (t.isJSXMemberExpression(object)) {
|
|
66
|
+
object = object.object;
|
|
67
|
+
}
|
|
68
|
+
bindingName = object.name;
|
|
69
|
+
} else if (t.isJSXNamespacedName(name)) {
|
|
70
|
+
bindingName = name.namespace.name;
|
|
71
|
+
} else {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const binding = path.scope.getBinding(bindingName);
|
|
75
|
+
if (binding && t.isImportDeclaration(binding.path.parent)) {
|
|
76
|
+
const container = path.container;
|
|
77
|
+
if (!t.isJSXElement(container)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (!t.isJSXIdentifier(container.openingElement.name)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const attributes = container.openingElement.attributes;
|
|
84
|
+
const clientAttr = attributes.find(
|
|
85
|
+
(attr) => t.isJSXAttribute(attr) && (attr.name.name === "client" || attr.name.name === "clientOnly")
|
|
86
|
+
);
|
|
87
|
+
if (!clientAttr) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
container.openingElement.attributes = container.openingElement.attributes.filter(
|
|
91
|
+
(attr) => attr !== clientAttr
|
|
92
|
+
);
|
|
93
|
+
const options = {
|
|
94
|
+
name: container.openingElement.name.name,
|
|
95
|
+
recovering: config.isServer && clientAttr.name.name !== "clientOnly"
|
|
96
|
+
};
|
|
97
|
+
if (t.isStringLiteral(clientAttr.value) && clientAttr.value.value) {
|
|
98
|
+
options.loading = clientAttr.value.value;
|
|
99
|
+
}
|
|
100
|
+
const importDeclaration = binding.path.parent;
|
|
101
|
+
const source = importDeclaration.source.value;
|
|
102
|
+
const importName = addNamed(
|
|
103
|
+
path,
|
|
104
|
+
"defineWebWidget",
|
|
105
|
+
"@web-widget/react"
|
|
106
|
+
);
|
|
107
|
+
const base = config.base;
|
|
108
|
+
binding.path.parentPath?.replaceWith(
|
|
109
|
+
createWebWidgetVariableDeclaration(
|
|
110
|
+
importName.name,
|
|
111
|
+
container.openingElement.name.name,
|
|
112
|
+
source,
|
|
113
|
+
base,
|
|
114
|
+
options
|
|
115
|
+
)
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
return {
|
|
121
|
+
name: "@web-widget/react:web-widget",
|
|
122
|
+
visitor
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
export {
|
|
126
|
+
babel_plugin_default as default
|
|
127
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as _web_widget_schema from '@web-widget/schema';
|
|
2
|
+
export * from '@web-widget/schema/client';
|
|
3
|
+
export { C as ClientOptions, D as DefineWebWidgetOptions, W as WebWidget, b as WebWidgetClient, a as WebWidgetClientProps, c as WebWidgetProps, _ as __ENV__, W as default, e as defineClient, f as defineClientOnly, d as defineWebWidget, r as renderServerWidget } from './web-widget-ec342172.js';
|
|
4
|
+
import 'react/jsx-runtime';
|
|
5
|
+
import 'react';
|
|
6
|
+
|
|
7
|
+
declare const render: (context: _web_widget_schema.ClientWidgetRenderContext<unknown> | _web_widget_schema.ClientRouteRenderContext<unknown, Record<string, string>>) => Promise<void | {
|
|
8
|
+
mount?: (() => void | Promise<void>) | undefined;
|
|
9
|
+
unmount?: (() => void | Promise<void>) | undefined;
|
|
10
|
+
update?: (({ data }: {
|
|
11
|
+
data: Record<string, any>;
|
|
12
|
+
}) => void | Promise<void>) | undefined;
|
|
13
|
+
} | {
|
|
14
|
+
mount?: (() => void | Promise<void>) | undefined;
|
|
15
|
+
unmount?: (() => void | Promise<void>) | undefined;
|
|
16
|
+
update?: (({ data }: {
|
|
17
|
+
data: Record<string, any>;
|
|
18
|
+
}) => void | Promise<void>) | undefined;
|
|
19
|
+
}>;
|
|
20
|
+
|
|
21
|
+
export { render };
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
// src/web-widget.tsx
|
|
2
|
+
import { Suspense, createElement, lazy } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
var __ENV__ = {
|
|
5
|
+
server: true
|
|
6
|
+
};
|
|
7
|
+
var MODULE_REG = /\b(?:import|__vite_ssr_dynamic_import__)\(["']([^"']*?)["']\)/;
|
|
8
|
+
function getFilename(loader) {
|
|
9
|
+
const match = String(loader).match(MODULE_REG);
|
|
10
|
+
const id = match?.[1];
|
|
11
|
+
if (!id) {
|
|
12
|
+
throw new Error(`The url for the module was not found: ${loader}`);
|
|
13
|
+
}
|
|
14
|
+
return id;
|
|
15
|
+
}
|
|
16
|
+
async function readableStreamToString(stream) {
|
|
17
|
+
const decoder = new TextDecoder();
|
|
18
|
+
const reader = stream.getReader();
|
|
19
|
+
let result = "";
|
|
20
|
+
try {
|
|
21
|
+
while (true) {
|
|
22
|
+
const { done, value } = await reader.read();
|
|
23
|
+
if (done)
|
|
24
|
+
break;
|
|
25
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
26
|
+
result += chunk;
|
|
27
|
+
}
|
|
28
|
+
} finally {
|
|
29
|
+
reader.releaseLock();
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
function WebWidgetClient({
|
|
34
|
+
base,
|
|
35
|
+
data,
|
|
36
|
+
import: url,
|
|
37
|
+
innerHTML = "",
|
|
38
|
+
loading,
|
|
39
|
+
name,
|
|
40
|
+
recovering
|
|
41
|
+
}) {
|
|
42
|
+
const attrs = {
|
|
43
|
+
base,
|
|
44
|
+
data: JSON.stringify(data),
|
|
45
|
+
import: url,
|
|
46
|
+
loading,
|
|
47
|
+
name,
|
|
48
|
+
rendertarget: "light"
|
|
49
|
+
};
|
|
50
|
+
if (recovering && typeof recovering !== "string") {
|
|
51
|
+
Object.assign(attrs, {
|
|
52
|
+
recovering: ""
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return createElement("web-widget", {
|
|
56
|
+
...attrs,
|
|
57
|
+
dangerouslySetInnerHTML: { __html: innerHTML }
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async function renderServerWidget(loader, data) {
|
|
61
|
+
const module = await loader();
|
|
62
|
+
if (typeof module.render !== "function") {
|
|
63
|
+
const url = getFilename(loader);
|
|
64
|
+
throw new Error(`The module does not export a 'render' method: ${url}`);
|
|
65
|
+
}
|
|
66
|
+
const result = await module.render({
|
|
67
|
+
meta: module.meta ?? {},
|
|
68
|
+
// TODO 处理 Meta 中的相对路径资产
|
|
69
|
+
module,
|
|
70
|
+
data
|
|
71
|
+
});
|
|
72
|
+
if (result instanceof ReadableStream) {
|
|
73
|
+
return await readableStreamToString(result);
|
|
74
|
+
} else if (typeof result === "string") {
|
|
75
|
+
return result;
|
|
76
|
+
} else {
|
|
77
|
+
const url = getFilename(loader);
|
|
78
|
+
throw new Error(`Render results in an unknown format: ${url}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function WebWidget({
|
|
82
|
+
base,
|
|
83
|
+
children,
|
|
84
|
+
data,
|
|
85
|
+
fallback,
|
|
86
|
+
import: url,
|
|
87
|
+
loader,
|
|
88
|
+
loading,
|
|
89
|
+
name,
|
|
90
|
+
recovering
|
|
91
|
+
}) {
|
|
92
|
+
if (!base) {
|
|
93
|
+
throw new Error(`Missing base`);
|
|
94
|
+
}
|
|
95
|
+
if (children) {
|
|
96
|
+
throw new Error(`No support for 'children'`);
|
|
97
|
+
}
|
|
98
|
+
if (recovering && !loader) {
|
|
99
|
+
throw new Error(`Missing loader`);
|
|
100
|
+
}
|
|
101
|
+
const WebWidgetClientFactory = lazy(async () => {
|
|
102
|
+
let innerHTML = "";
|
|
103
|
+
if (__ENV__.server && recovering && loader) {
|
|
104
|
+
innerHTML = await renderServerWidget(loader, data);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
default: function WebWidgetClientFactory2() {
|
|
108
|
+
return /* @__PURE__ */ jsx(
|
|
109
|
+
WebWidgetClient,
|
|
110
|
+
{
|
|
111
|
+
...{
|
|
112
|
+
base,
|
|
113
|
+
data,
|
|
114
|
+
import: url,
|
|
115
|
+
loading,
|
|
116
|
+
name,
|
|
117
|
+
innerHTML,
|
|
118
|
+
recovering
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback, children: /* @__PURE__ */ jsx(WebWidgetClientFactory, {}) });
|
|
126
|
+
}
|
|
127
|
+
function defineWebWidget(loader, base, { loading, name, recovering = true } = {}) {
|
|
128
|
+
const url = getFilename(loader);
|
|
129
|
+
return function WebWidgetFactory({
|
|
130
|
+
children,
|
|
131
|
+
fallback,
|
|
132
|
+
...data
|
|
133
|
+
}) {
|
|
134
|
+
return /* @__PURE__ */ jsx(
|
|
135
|
+
WebWidget,
|
|
136
|
+
{
|
|
137
|
+
...{
|
|
138
|
+
base,
|
|
139
|
+
data,
|
|
140
|
+
fallback,
|
|
141
|
+
import: url,
|
|
142
|
+
loader,
|
|
143
|
+
loading,
|
|
144
|
+
name,
|
|
145
|
+
recovering
|
|
146
|
+
},
|
|
147
|
+
children
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function defineClient(loader, base, { loading, name } = {}) {
|
|
153
|
+
return defineWebWidget(loader, base, {
|
|
154
|
+
loading,
|
|
155
|
+
name,
|
|
156
|
+
recovering: true
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function defineClientOnly(loader, base, { loading, name } = {}) {
|
|
160
|
+
return defineWebWidget(loader, base, {
|
|
161
|
+
loading,
|
|
162
|
+
name,
|
|
163
|
+
recovering: false
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/client.ts
|
|
168
|
+
import { createElement as createElement2 } from "react";
|
|
169
|
+
import { createRoot, hydrateRoot } from "react-dom/client";
|
|
170
|
+
import { defineRender, isRouteRenderContext } from "@web-widget/schema/client";
|
|
171
|
+
export * from "@web-widget/schema/client";
|
|
172
|
+
Reflect.defineProperty(__ENV__, "server", {
|
|
173
|
+
value: false
|
|
174
|
+
});
|
|
175
|
+
var render = defineRender(
|
|
176
|
+
async (context, component, props) => {
|
|
177
|
+
const { recovering, container } = context;
|
|
178
|
+
if (!container) {
|
|
179
|
+
throw new Error(`Container required.`);
|
|
180
|
+
}
|
|
181
|
+
let vnode;
|
|
182
|
+
if (typeof component === "function" && component.constructor.name === "AsyncFunction") {
|
|
183
|
+
if (isRouteRenderContext(context)) {
|
|
184
|
+
vnode = await component(props);
|
|
185
|
+
} else {
|
|
186
|
+
throw new Error("Async widget components are not supported.");
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
vnode = createElement2(component, props);
|
|
190
|
+
}
|
|
191
|
+
if (recovering) {
|
|
192
|
+
hydrateRoot(container, vnode);
|
|
193
|
+
} else {
|
|
194
|
+
createRoot(container).render(vnode);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
export {
|
|
199
|
+
WebWidget,
|
|
200
|
+
WebWidgetClient,
|
|
201
|
+
__ENV__,
|
|
202
|
+
WebWidget as default,
|
|
203
|
+
defineClient,
|
|
204
|
+
defineClientOnly,
|
|
205
|
+
defineWebWidget,
|
|
206
|
+
render,
|
|
207
|
+
renderServerWidget
|
|
208
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as _web_widget_schema from '@web-widget/schema';
|
|
2
|
+
export * from '@web-widget/schema/server';
|
|
3
|
+
export { C as ClientOptions, D as DefineWebWidgetOptions, W as WebWidget, b as WebWidgetClient, a as WebWidgetClientProps, c as WebWidgetProps, _ as __ENV__, W as default, e as defineClient, f as defineClientOnly, d as defineWebWidget, r as renderServerWidget } from './web-widget-ec342172.js';
|
|
4
|
+
import 'react/jsx-runtime';
|
|
5
|
+
import 'react';
|
|
6
|
+
|
|
7
|
+
declare const render: (context: _web_widget_schema.ServerWidgetRenderContext<unknown> | _web_widget_schema.ServerRouteRenderContext<unknown, Record<string, string>>) => Promise<string | ReadableStream<any>>;
|
|
8
|
+
|
|
9
|
+
export { render };
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// src/web-widget.tsx
|
|
2
|
+
import { Suspense, createElement, lazy } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
var __ENV__ = {
|
|
5
|
+
server: true
|
|
6
|
+
};
|
|
7
|
+
var MODULE_REG = /\b(?:import|__vite_ssr_dynamic_import__)\(["']([^"']*?)["']\)/;
|
|
8
|
+
function getFilename(loader) {
|
|
9
|
+
const match = String(loader).match(MODULE_REG);
|
|
10
|
+
const id = match?.[1];
|
|
11
|
+
if (!id) {
|
|
12
|
+
throw new Error(`The url for the module was not found: ${loader}`);
|
|
13
|
+
}
|
|
14
|
+
return id;
|
|
15
|
+
}
|
|
16
|
+
async function readableStreamToString(stream) {
|
|
17
|
+
const decoder = new TextDecoder();
|
|
18
|
+
const reader = stream.getReader();
|
|
19
|
+
let result = "";
|
|
20
|
+
try {
|
|
21
|
+
while (true) {
|
|
22
|
+
const { done, value } = await reader.read();
|
|
23
|
+
if (done)
|
|
24
|
+
break;
|
|
25
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
26
|
+
result += chunk;
|
|
27
|
+
}
|
|
28
|
+
} finally {
|
|
29
|
+
reader.releaseLock();
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
function WebWidgetClient({
|
|
34
|
+
base,
|
|
35
|
+
data,
|
|
36
|
+
import: url,
|
|
37
|
+
innerHTML = "",
|
|
38
|
+
loading,
|
|
39
|
+
name,
|
|
40
|
+
recovering
|
|
41
|
+
}) {
|
|
42
|
+
const attrs = {
|
|
43
|
+
base,
|
|
44
|
+
data: JSON.stringify(data),
|
|
45
|
+
import: url,
|
|
46
|
+
loading,
|
|
47
|
+
name,
|
|
48
|
+
rendertarget: "light"
|
|
49
|
+
};
|
|
50
|
+
if (recovering && typeof recovering !== "string") {
|
|
51
|
+
Object.assign(attrs, {
|
|
52
|
+
recovering: ""
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return createElement("web-widget", {
|
|
56
|
+
...attrs,
|
|
57
|
+
dangerouslySetInnerHTML: { __html: innerHTML }
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async function renderServerWidget(loader, data) {
|
|
61
|
+
const module = await loader();
|
|
62
|
+
if (typeof module.render !== "function") {
|
|
63
|
+
const url = getFilename(loader);
|
|
64
|
+
throw new Error(`The module does not export a 'render' method: ${url}`);
|
|
65
|
+
}
|
|
66
|
+
const result = await module.render({
|
|
67
|
+
meta: module.meta ?? {},
|
|
68
|
+
// TODO 处理 Meta 中的相对路径资产
|
|
69
|
+
module,
|
|
70
|
+
data
|
|
71
|
+
});
|
|
72
|
+
if (result instanceof ReadableStream) {
|
|
73
|
+
return await readableStreamToString(result);
|
|
74
|
+
} else if (typeof result === "string") {
|
|
75
|
+
return result;
|
|
76
|
+
} else {
|
|
77
|
+
const url = getFilename(loader);
|
|
78
|
+
throw new Error(`Render results in an unknown format: ${url}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function WebWidget({
|
|
82
|
+
base,
|
|
83
|
+
children,
|
|
84
|
+
data,
|
|
85
|
+
fallback,
|
|
86
|
+
import: url,
|
|
87
|
+
loader,
|
|
88
|
+
loading,
|
|
89
|
+
name,
|
|
90
|
+
recovering
|
|
91
|
+
}) {
|
|
92
|
+
if (!base) {
|
|
93
|
+
throw new Error(`Missing base`);
|
|
94
|
+
}
|
|
95
|
+
if (children) {
|
|
96
|
+
throw new Error(`No support for 'children'`);
|
|
97
|
+
}
|
|
98
|
+
if (recovering && !loader) {
|
|
99
|
+
throw new Error(`Missing loader`);
|
|
100
|
+
}
|
|
101
|
+
const WebWidgetClientFactory = lazy(async () => {
|
|
102
|
+
let innerHTML = "";
|
|
103
|
+
if (__ENV__.server && recovering && loader) {
|
|
104
|
+
innerHTML = await renderServerWidget(loader, data);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
default: function WebWidgetClientFactory2() {
|
|
108
|
+
return /* @__PURE__ */ jsx(
|
|
109
|
+
WebWidgetClient,
|
|
110
|
+
{
|
|
111
|
+
...{
|
|
112
|
+
base,
|
|
113
|
+
data,
|
|
114
|
+
import: url,
|
|
115
|
+
loading,
|
|
116
|
+
name,
|
|
117
|
+
innerHTML,
|
|
118
|
+
recovering
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback, children: /* @__PURE__ */ jsx(WebWidgetClientFactory, {}) });
|
|
126
|
+
}
|
|
127
|
+
function defineWebWidget(loader, base, { loading, name, recovering = true } = {}) {
|
|
128
|
+
const url = getFilename(loader);
|
|
129
|
+
return function WebWidgetFactory({
|
|
130
|
+
children,
|
|
131
|
+
fallback,
|
|
132
|
+
...data
|
|
133
|
+
}) {
|
|
134
|
+
return /* @__PURE__ */ jsx(
|
|
135
|
+
WebWidget,
|
|
136
|
+
{
|
|
137
|
+
...{
|
|
138
|
+
base,
|
|
139
|
+
data,
|
|
140
|
+
fallback,
|
|
141
|
+
import: url,
|
|
142
|
+
loader,
|
|
143
|
+
loading,
|
|
144
|
+
name,
|
|
145
|
+
recovering
|
|
146
|
+
},
|
|
147
|
+
children
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function defineClient(loader, base, { loading, name } = {}) {
|
|
153
|
+
return defineWebWidget(loader, base, {
|
|
154
|
+
loading,
|
|
155
|
+
name,
|
|
156
|
+
recovering: true
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function defineClientOnly(loader, base, { loading, name } = {}) {
|
|
160
|
+
return defineWebWidget(loader, base, {
|
|
161
|
+
loading,
|
|
162
|
+
name,
|
|
163
|
+
recovering: false
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/server.ts
|
|
168
|
+
import { createElement as createElement2 } from "react";
|
|
169
|
+
import * as ReactDOMServer from "react-dom/server.browser";
|
|
170
|
+
import { defineRender, isRouteRenderContext } from "@web-widget/schema/server";
|
|
171
|
+
export * from "@web-widget/schema/server";
|
|
172
|
+
Reflect.defineProperty(__ENV__, "server", {
|
|
173
|
+
value: true
|
|
174
|
+
});
|
|
175
|
+
var render = defineRender(
|
|
176
|
+
async (context, component, props) => {
|
|
177
|
+
let vnode;
|
|
178
|
+
if (typeof component === "function" && component.constructor.name === "AsyncFunction") {
|
|
179
|
+
if (isRouteRenderContext(context)) {
|
|
180
|
+
vnode = await component(props);
|
|
181
|
+
} else {
|
|
182
|
+
throw new Error("Async widget components are not supported.");
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
vnode = createElement2(component, props);
|
|
186
|
+
}
|
|
187
|
+
return ReactDOMServer.renderToReadableStream(vnode);
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
export {
|
|
191
|
+
WebWidget,
|
|
192
|
+
WebWidgetClient,
|
|
193
|
+
__ENV__,
|
|
194
|
+
WebWidget as default,
|
|
195
|
+
defineClient,
|
|
196
|
+
defineClientOnly,
|
|
197
|
+
defineWebWidget,
|
|
198
|
+
render,
|
|
199
|
+
renderServerWidget
|
|
200
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// src/vite-plugin.ts
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
function ReactWebWidgetVitePlugin(options = {}) {
|
|
4
|
+
let config;
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
name: "@web-widget/react:get-config",
|
|
8
|
+
enforce: "pre",
|
|
9
|
+
config(config2) {
|
|
10
|
+
var _a;
|
|
11
|
+
config2.resolve || (config2.resolve = {});
|
|
12
|
+
(_a = config2.resolve).alias || (_a.alias = {});
|
|
13
|
+
const aliases = [
|
|
14
|
+
{ find: "react-dom/server", replacement: "react-dom/server.browser" }
|
|
15
|
+
];
|
|
16
|
+
if (Array.isArray(config2.resolve.alias)) {
|
|
17
|
+
config2.resolve.alias = [...config2.resolve.alias, ...aliases];
|
|
18
|
+
} else {
|
|
19
|
+
for (const alias of aliases) {
|
|
20
|
+
config2.resolve.alias[alias.find] = alias.replacement;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
configResolved(resolvedConfig) {
|
|
25
|
+
config = resolvedConfig;
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
...react({
|
|
29
|
+
...options,
|
|
30
|
+
babel: {
|
|
31
|
+
...options?.babel,
|
|
32
|
+
plugins: [
|
|
33
|
+
// @ts-expect-error
|
|
34
|
+
...options?.babel?.plugins || [],
|
|
35
|
+
[
|
|
36
|
+
"@web-widget/react/babel-plugin",
|
|
37
|
+
{
|
|
38
|
+
get base() {
|
|
39
|
+
const isServer = !!config.build.ssr;
|
|
40
|
+
return isServer ? config.base + config.build.assetsDir + "/" : config.base;
|
|
41
|
+
},
|
|
42
|
+
get root() {
|
|
43
|
+
return config.root;
|
|
44
|
+
},
|
|
45
|
+
get isServer() {
|
|
46
|
+
return !!config.build.ssr || config.command === "serve";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
ReactWebWidgetVitePlugin as default
|
|
57
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
import { WidgetModule } from '@web-widget/schema';
|
|
5
|
+
|
|
6
|
+
declare const __ENV__: {
|
|
7
|
+
server: boolean;
|
|
8
|
+
};
|
|
9
|
+
type JSONValue = string | number | boolean | {
|
|
10
|
+
[x: string]: JSONValue;
|
|
11
|
+
} | Array<JSONValue>;
|
|
12
|
+
type JSONProps = {
|
|
13
|
+
[x: string]: JSONValue;
|
|
14
|
+
};
|
|
15
|
+
type Loader = () => Promise<WidgetModule>;
|
|
16
|
+
interface WebWidgetClientProps {
|
|
17
|
+
base: string;
|
|
18
|
+
data: JSONProps;
|
|
19
|
+
import: string;
|
|
20
|
+
innerHTML?: string;
|
|
21
|
+
loading?: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
recovering: boolean;
|
|
24
|
+
}
|
|
25
|
+
declare function WebWidgetClient({ base, data, import: url, innerHTML, loading, name, recovering, }: WebWidgetClientProps): react.DOMElement<{
|
|
26
|
+
dangerouslySetInnerHTML: {
|
|
27
|
+
__html: string;
|
|
28
|
+
};
|
|
29
|
+
base: string;
|
|
30
|
+
data: string;
|
|
31
|
+
import: string;
|
|
32
|
+
loading: string | undefined;
|
|
33
|
+
name: string | undefined;
|
|
34
|
+
rendertarget: string;
|
|
35
|
+
}, Element>;
|
|
36
|
+
declare function renderServerWidget(loader: Loader, data: any): Promise<string>;
|
|
37
|
+
interface WebWidgetProps extends WebWidgetClientProps {
|
|
38
|
+
fallback?: ReactNode;
|
|
39
|
+
children?: ReactNode | undefined;
|
|
40
|
+
loader?: Loader;
|
|
41
|
+
}
|
|
42
|
+
declare function WebWidget({ base, children, data, fallback, import: url, loader, loading, name, recovering, }: WebWidgetProps): react_jsx_runtime.JSX.Element;
|
|
43
|
+
type WebWidgetFactoryProps = JSONProps & {
|
|
44
|
+
children?: ReactNode;
|
|
45
|
+
fallback?: ReactNode;
|
|
46
|
+
};
|
|
47
|
+
interface DefineWebWidgetOptions {
|
|
48
|
+
loading?: string;
|
|
49
|
+
name?: string;
|
|
50
|
+
recovering?: boolean;
|
|
51
|
+
}
|
|
52
|
+
declare function defineWebWidget(loader: Loader, base: string, { loading, name, recovering }?: DefineWebWidgetOptions): ({ children, fallback, ...data }: WebWidgetFactoryProps) => react_jsx_runtime.JSX.Element;
|
|
53
|
+
interface ClientOptions {
|
|
54
|
+
loading?: "lazy";
|
|
55
|
+
name?: string;
|
|
56
|
+
}
|
|
57
|
+
declare function defineClient(loader: Loader, base: string, { loading, name }?: ClientOptions): ({ children, fallback, ...data }: WebWidgetFactoryProps) => react_jsx_runtime.JSX.Element;
|
|
58
|
+
declare function defineClientOnly(loader: Loader, base: string, { loading, name }?: ClientOptions): ({ children, fallback, ...data }: WebWidgetFactoryProps) => react_jsx_runtime.JSX.Element;
|
|
59
|
+
|
|
60
|
+
export { ClientOptions as C, DefineWebWidgetOptions as D, WebWidget as W, __ENV__ as _, WebWidgetClientProps as a, WebWidgetClient as b, WebWidgetProps as c, defineWebWidget as d, defineClient as e, defineClientOnly as f, renderServerWidget as r };
|
package/globals.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@web-widget/react",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"worker": {
|
|
8
|
+
"types": "./dist/react.server.d.ts",
|
|
9
|
+
"default": "./dist/react.server.js"
|
|
10
|
+
},
|
|
11
|
+
"browser": {
|
|
12
|
+
"types": "./dist/react.client.d.ts",
|
|
13
|
+
"default": "./dist/react.client.js"
|
|
14
|
+
},
|
|
15
|
+
"default": {
|
|
16
|
+
"types": "./dist/react.server.d.ts",
|
|
17
|
+
"default": "./dist/react.server.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"./babel-plugin": {
|
|
21
|
+
"types": "./dist/babel-plugin.d.ts",
|
|
22
|
+
"default": "./dist/babel-plugin.js"
|
|
23
|
+
},
|
|
24
|
+
"./vite-plugin": {
|
|
25
|
+
"types": "./dist/vite-plugin.d.ts",
|
|
26
|
+
"default": "./dist/vite-plugin.js"
|
|
27
|
+
},
|
|
28
|
+
"./globals": "./globals.d.ts"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"globals.d.ts"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@babel/core": "^7.22.5",
|
|
36
|
+
"@babel/helper-module-imports": "^7.22.5",
|
|
37
|
+
"@babel/helper-plugin-utils": "^7.22.5",
|
|
38
|
+
"@babel/traverse": "^7.22.5",
|
|
39
|
+
"@web-widget/schema": "0.0.1"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@vitejs/plugin-react": "^4.0.2",
|
|
43
|
+
"react": "^18.2.0",
|
|
44
|
+
"react-dom": "^18.2.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/babel__core": "^7.20.1",
|
|
48
|
+
"@types/babel__helper-module-imports": "^7.18.0",
|
|
49
|
+
"@types/babel__helper-plugin-utils": "^7.10.0",
|
|
50
|
+
"@types/babel__traverse": "^7.20.1",
|
|
51
|
+
"@types/node": "^20.3.1",
|
|
52
|
+
"@types/react": "^18.2.9",
|
|
53
|
+
"@types/react-dom": "^18.0.6",
|
|
54
|
+
"tsup": "^7.0.0",
|
|
55
|
+
"typescript": "^5.0.4",
|
|
56
|
+
"vite": "^4.3.9"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "pnpm exec tsup",
|
|
63
|
+
"dev": "pnpm exec tsup --watch"
|
|
64
|
+
}
|
|
65
|
+
}
|