@web-widget/solid 3.0.0-beta.2 → 3.0.0-beta.5

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/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @web-widget/solid
2
+
3
+ Solid adapter.
@@ -0,0 +1,111 @@
1
+ // src/components.ts
2
+ import {
3
+ ErrorBoundary,
4
+ Suspense,
5
+ createComponent,
6
+ createResource,
7
+ splitProps
8
+ } from "solid-js";
9
+ import { Dynamic } from "solid-js/web";
10
+ import { WebWidgetRenderer } from "@web-widget/web-widget";
11
+ function resolveFallback(fallback) {
12
+ var _a;
13
+ if (fallback !== null && typeof fallback === "object" && ("pending" in fallback || "error" in fallback)) {
14
+ return {
15
+ pending: fallback.pending,
16
+ error: (_a = fallback.error) != null ? _a : fallback.pending
17
+ };
18
+ }
19
+ return { pending: fallback, error: fallback };
20
+ }
21
+ function createWidgetAdapter(renderChildren, renderHost, renderInnerHTML) {
22
+ return (loader, options = {}) => (props) => {
23
+ var _a, _b;
24
+ const hasChildren = "children" in props;
25
+ const [local, data] = splitProps(props, ["children", "slot", "widget"]);
26
+ const widget = (_a = local.widget) != null ? _a : {};
27
+ if (hasChildren && options.root !== "shadow") {
28
+ throw new Error(
29
+ `Rendering content in a slot requires "options.root = 'shadow'".`
30
+ );
31
+ }
32
+ const fallback = resolveFallback(widget.fallback);
33
+ const renderOptions = {
34
+ ...options,
35
+ clientOnly: widget.clientOnly,
36
+ id: widget.id,
37
+ loading: (_b = widget.loading) != null ? _b : options.loading,
38
+ serverOnly: widget.serverOnly
39
+ };
40
+ const renderer = new WebWidgetRenderer(loader, {
41
+ ...renderOptions,
42
+ data,
43
+ root: options.root,
44
+ slot: local.slot
45
+ });
46
+ const widgetProps = {
47
+ component: renderer.localName,
48
+ ...renderer.attributes
49
+ };
50
+ if (!renderChildren && !renderHost && hasChildren) {
51
+ return createComponent(Dynamic, {
52
+ ...widgetProps,
53
+ get children() {
54
+ return local.children;
55
+ }
56
+ });
57
+ }
58
+ if (widget.clientOnly && typeof window === "undefined" && fallback.pending != null) {
59
+ return createComponent(Dynamic, {
60
+ ...widgetProps,
61
+ get children() {
62
+ return createComponent(Dynamic, {
63
+ component: renderer.pendingBoundary.localName,
64
+ "aria-busy": renderer.pendingBoundary.ariaBusy,
65
+ slot: renderer.pendingBoundary.slot,
66
+ style: `display: ${renderer.pendingBoundary.display}`,
67
+ children: fallback.pending
68
+ });
69
+ }
70
+ });
71
+ }
72
+ const [html] = createResource(async () => {
73
+ const children = local.children && renderChildren ? await renderChildren(local.children) : "";
74
+ return renderer.renderInnerHTMLToString({
75
+ children
76
+ }).catch(
77
+ (error) => error instanceof Error ? error : new Error(String(error))
78
+ );
79
+ });
80
+ const renderServerHost = (children) => renderHost && !hasChildren ? renderHost(renderer.localName, renderer.attributes, children) : children;
81
+ const content = () => {
82
+ const result = html();
83
+ if (result instanceof Error) return fallback.error;
84
+ if (result === void 0) return result;
85
+ if (renderInnerHTML) {
86
+ return renderServerHost(renderInnerHTML(result));
87
+ }
88
+ return createComponent(Dynamic, {
89
+ ...widgetProps,
90
+ innerHTML: result
91
+ });
92
+ };
93
+ const boundary = createComponent(ErrorBoundary, {
94
+ fallback: () => fallback.error,
95
+ get children() {
96
+ return createComponent(Suspense, {
97
+ fallback: fallback.pending == null ? fallback.pending : renderServerHost(fallback.pending),
98
+ get children() {
99
+ return content();
100
+ }
101
+ });
102
+ }
103
+ });
104
+ const hostChildren = hasChildren ? [boundary, local.children] : boundary;
105
+ return renderHost && hasChildren ? renderHost(renderer.localName, renderer.attributes, hostChildren) : boundary;
106
+ };
107
+ }
108
+
109
+ export {
110
+ createWidgetAdapter
111
+ };
@@ -0,0 +1,14 @@
1
+ import { Component, JSX } from 'solid-js';
2
+ import { WidgetHostProps, WidgetContainerProps, WidgetContainerOptions, ExtractWidgetProps, WidgetModuleLoader } from '@web-widget/schema';
3
+
4
+ type SolidWidgetContainerProps = WidgetContainerProps<JSX.Element>;
5
+ type SolidWidgetComponent<T = unknown> = Component<T & WidgetHostProps & {
6
+ children?: JSX.Element;
7
+ widget?: SolidWidgetContainerProps;
8
+ }>;
9
+ interface SolidWidgetFactory {
10
+ <M>(loader: () => Promise<M>, options?: WidgetContainerOptions): SolidWidgetComponent<ExtractWidgetProps<M>>;
11
+ <Props>(loader: WidgetModuleLoader, options?: WidgetContainerOptions): SolidWidgetComponent<Props>;
12
+ }
13
+
14
+ export type { SolidWidgetFactory as S, SolidWidgetComponent as a, SolidWidgetContainerProps as b };
@@ -1,8 +1,10 @@
1
1
  import * as _web_widget_schema from '@web-widget/schema';
2
+ export { WidgetContainerOptions } from '@web-widget/schema';
3
+ import { S as SolidWidgetFactory } from './components-WgHeqrQg.js';
4
+ export { a as SolidWidgetComponent, b as SolidWidgetContainerProps } from './components-WgHeqrQg.js';
2
5
  import { Component } from 'solid-js';
3
- export { D as DefineWebWidgetOptions, S as SolidWidgetComponent, W as WidgetContainerConfig, c as container } from './components-BfyNPS03.js';
4
- import '@web-widget/web-widget';
5
6
 
7
+ declare const widget: SolidWidgetFactory;
6
8
  declare const render: _web_widget_schema.ClientRender<Component<any>, unknown, _web_widget_schema.ClientRenderOptions, void | _web_widget_schema.ClientRenderResult<unknown>>;
7
9
 
8
- export { render };
10
+ export { SolidWidgetFactory, render, widget };
@@ -1,26 +1,52 @@
1
1
  import {
2
- container
3
- } from "./chunk-35N5BM2J.js";
2
+ createWidgetAdapter
3
+ } from "./chunk-UU3ACCGF.js";
4
4
 
5
5
  // src/adapter.client.ts
6
6
  import { defineClientRender } from "@web-widget/helpers";
7
- import { createComponent } from "solid-js";
7
+ import { createComponent, sharedConfig } from "solid-js";
8
8
  import { hydrate, render as renderComponent } from "solid-js/web";
9
+ var widget = createWidgetAdapter();
10
+ function ensureHydrationRuntime() {
11
+ var _a, _b, _c, _d, _e, _f, _g, _h;
12
+ const runtime = globalThis;
13
+ if (!runtime._$HY) {
14
+ runtime._$HY = {
15
+ completed: /* @__PURE__ */ new WeakSet(),
16
+ events: [],
17
+ fe: () => void 0,
18
+ r: {}
19
+ };
20
+ return;
21
+ }
22
+ (_b = (_a = runtime._$HY).completed) != null ? _b : _a.completed = /* @__PURE__ */ new WeakSet();
23
+ (_d = (_c = runtime._$HY).events) != null ? _d : _c.events = [];
24
+ (_f = (_e = runtime._$HY).fe) != null ? _f : _e.fe = () => void 0;
25
+ (_h = (_g = runtime._$HY).r) != null ? _h : _g.r = {};
26
+ }
9
27
  var render = defineClientRender(
10
- async (component, data, { container: container2, recovering }) => {
28
+ async (component, data, { container, id, recovering }) => {
11
29
  if (!component) throw new TypeError("Missing component.");
12
- if (!container2) throw new Error("Missing container.");
30
+ if (!container) throw new Error("Missing container.");
13
31
  let dispose;
14
32
  return {
15
33
  mount() {
16
34
  const view = () => createComponent(component, data != null ? data : {});
17
- const isIsolatedWidget = container2 instanceof Element && container2.hasAttribute("recovering") && container2.hasAttribute("import");
18
- const canHydrate = recovering && !isIsolatedWidget && Reflect.has(globalThis, "_$HY");
19
- if (canHydrate) {
20
- dispose = hydrate(view, container2);
35
+ const canHydrate = recovering && container.querySelector("[data-hk]") !== null;
36
+ if (recovering && !canHydrate) {
37
+ throw new Error(
38
+ "Cannot hydrate Solid widget: SSR hydration markers are missing."
39
+ );
40
+ }
41
+ if (recovering) {
42
+ ensureHydrationRuntime();
43
+ const runtime = globalThis;
44
+ runtime._$HY.done = false;
45
+ sharedConfig.done = false;
46
+ dispose = hydrate(view, container, { renderId: id });
21
47
  } else {
22
- container2.replaceChildren();
23
- dispose = renderComponent(view, container2);
48
+ container.replaceChildren();
49
+ dispose = renderComponent(view, container);
24
50
  }
25
51
  },
26
52
  unmount() {
@@ -31,6 +57,6 @@ var render = defineClientRender(
31
57
  }
32
58
  );
33
59
  export {
34
- container,
35
- render
60
+ render,
61
+ widget
36
62
  };
@@ -1,8 +1,10 @@
1
1
  import * as _web_widget_schema from '@web-widget/schema';
2
+ export { WidgetContainerOptions } from '@web-widget/schema';
3
+ import { S as SolidWidgetFactory } from './components-WgHeqrQg.js';
4
+ export { a as SolidWidgetComponent, b as SolidWidgetContainerProps } from './components-WgHeqrQg.js';
2
5
  import { Component } from 'solid-js';
3
- export { D as DefineWebWidgetOptions, S as SolidWidgetComponent, W as WidgetContainerConfig, c as container } from './components-BfyNPS03.js';
4
- import '@web-widget/web-widget';
5
6
 
7
+ declare const widget: SolidWidgetFactory;
6
8
  declare const render: _web_widget_schema.ServerRender<Component<any>, unknown, _web_widget_schema.ServerRenderOptions, _web_widget_schema.ServerRenderResult>;
7
9
 
8
- export { render };
10
+ export { SolidWidgetFactory, render, widget };
@@ -1,45 +1,85 @@
1
1
  import {
2
- container
3
- } from "./chunk-35N5BM2J.js";
2
+ createWidgetAdapter
3
+ } from "./chunk-UU3ACCGF.js";
4
4
 
5
5
  // src/adapter.server.ts
6
6
  import { defineServerRender } from "@web-widget/helpers";
7
7
  import { createComponent } from "solid-js";
8
- import { renderToStream, renderToStringAsync } from "solid-js/web";
9
- var HYDRATION_SCRIPT_FALLBACK = [
10
- "<script>",
11
- 'window._$HY||(e=>{let t=e=>e&&e.hasAttribute&&(e.hasAttribute("data-hk")?e:t(e.host&&e.host.nodeType?e.host:e.parentNode));',
12
- '["click","input"].forEach(o=>document.addEventListener(o,o=>{if(!e.events)return;let s=t(o.composedPath&&o.composedPath()[0]||o.target);',
13
- "s&&!e.completed.has(s)&&e.events.push([s,o])}))})(_$HY={events:[],completed:new WeakSet,r:{},fe(){}});",
14
- "</script><!--xs-->"
15
- ].join("");
8
+ import {
9
+ generateHydrationScript,
10
+ renderToStream,
11
+ renderToStringAsync,
12
+ ssr,
13
+ ssrElement
14
+ } from "solid-js/web";
15
+ var widget = createWidgetAdapter(
16
+ void 0,
17
+ (localName, attributes, children) => ssrElement(localName, attributes, children, true),
18
+ (html) => ssr(html)
19
+ );
20
+ var HYDRATION_SCRIPT = generateHydrationScript();
16
21
  var render = defineServerRender(
17
- async (component, data, { progressive }) => {
22
+ async (component, data, { id, progressive }) => {
18
23
  if (!component) throw new TypeError("Missing component.");
19
24
  const view = () => createComponent(component, data != null ? data : {});
20
25
  if (!progressive) {
21
- return HYDRATION_SCRIPT_FALLBACK + await renderToStringAsync(view);
26
+ return HYDRATION_SCRIPT + await renderToStringAsync(view, { renderId: id });
22
27
  }
23
- return new ReadableStream({
28
+ let resolveShell;
29
+ let rejectShell;
30
+ const shellReady = new Promise((resolve, reject) => {
31
+ resolveShell = resolve;
32
+ rejectShell = reject;
33
+ });
34
+ let active = true;
35
+ const stream = new ReadableStream({
24
36
  start(controller) {
25
37
  let shellPending = true;
26
38
  const writable = {
27
39
  write(chunk) {
28
- controller.enqueue(
29
- shellPending ? HYDRATION_SCRIPT_FALLBACK + chunk : chunk
30
- );
40
+ if (!active) return;
41
+ const shell = shellPending;
31
42
  shellPending = false;
43
+ controller.enqueue(shell ? HYDRATION_SCRIPT + chunk : chunk);
44
+ if (shell) resolveShell();
32
45
  },
33
46
  end() {
47
+ if (!active) return;
48
+ active = false;
34
49
  controller.close();
50
+ if (shellPending) resolveShell();
35
51
  }
36
52
  };
37
- renderToStream(view).pipe(writable);
53
+ try {
54
+ const streamOptions = {
55
+ renderId: id,
56
+ onError(error) {
57
+ if (!active) return;
58
+ if (shellPending) {
59
+ active = false;
60
+ rejectShell(error);
61
+ controller.error(error);
62
+ } else {
63
+ console.error(error);
64
+ }
65
+ }
66
+ };
67
+ renderToStream(view, streamOptions).pipe(writable);
68
+ } catch (error) {
69
+ active = false;
70
+ rejectShell(error);
71
+ controller.error(error);
72
+ }
73
+ },
74
+ cancel() {
75
+ active = false;
38
76
  }
39
77
  });
78
+ await shellReady;
79
+ return stream;
40
80
  }
41
81
  );
42
82
  export {
43
- container,
44
- render
83
+ render,
84
+ widget
45
85
  };
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ name: string;
3
+ extensions: string[];
4
+ adapter: string;
5
+ };
6
+
7
+ export { _default as default };
@@ -0,0 +1,9 @@
1
+ // src/transform.ts
2
+ var transform_default = {
3
+ name: "solid",
4
+ extensions: [".tsx", ".jsx"],
5
+ adapter: "@web-widget/solid/adapter"
6
+ };
7
+ export {
8
+ transform_default as default
9
+ };
package/package.json CHANGED
@@ -1,22 +1,33 @@
1
1
  {
2
2
  "name": "@web-widget/solid",
3
3
  "description": "Solid adapter",
4
- "version": "3.0.0-beta.2",
4
+ "version": "3.0.0-beta.5",
5
+ "homepage": "https://github.com/web-widget/web-widget#readme",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/web-widget/web-widget.git",
9
+ "directory": "packages/solid"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/web-widget/web-widget/issues"
13
+ },
5
14
  "license": "MIT",
6
15
  "type": "module",
7
16
  "sideEffects": false,
8
17
  "dependencies": {
9
- "@web-widget/schema": "3.0.0-beta.2",
10
- "@web-widget/web-widget": "3.0.0-beta.2",
11
- "@web-widget/helpers": "3.0.0-beta.2"
18
+ "@web-widget/helpers": "workspace:*",
19
+ "@web-widget/schema": "workspace:*",
20
+ "@web-widget/web-widget": "workspace:*"
12
21
  },
13
22
  "peerDependencies": {
14
23
  "solid-js": "^1.9.0"
15
24
  },
16
25
  "devDependencies": {
17
- "solid-js": "^1.9.14",
18
- "tsup": "^8.3.4",
19
- "typescript": "^5.9.3"
26
+ "happy-dom": "14.12.3",
27
+ "solid-js": "catalog:",
28
+ "tsup": "catalog:",
29
+ "typescript": "catalog:",
30
+ "vitest": "catalog:"
20
31
  },
21
32
  "exports": {
22
33
  ".": {
@@ -24,6 +35,11 @@
24
35
  "development": "./src/index.ts",
25
36
  "default": "./dist/solid.js"
26
37
  },
38
+ "./transform": {
39
+ "types": "./dist/solid.transform.d.ts",
40
+ "development": "./src/transform.ts",
41
+ "default": "./dist/solid.transform.js"
42
+ },
27
43
  "./adapter": {
28
44
  "worker": {
29
45
  "types": "./dist/solid.adapter.server.d.ts",
@@ -42,15 +58,6 @@
42
58
  }
43
59
  }
44
60
  },
45
- "webWidgetAdapter": {
46
- "version": "1.0.0",
47
- "name": "solid",
48
- "extensions": [
49
- ".tsx",
50
- ".jsx"
51
- ],
52
- "adapter": "./adapter"
53
- },
54
61
  "files": [
55
62
  "dist"
56
63
  ],
@@ -58,6 +65,7 @@
58
65
  "build": "pnpm exec tsup",
59
66
  "clean:build": "rm -rf dist",
60
67
  "clean:node": "rm -rf node_modules",
61
- "lint": "eslint src"
68
+ "lint": "eslint src",
69
+ "test": "vitest run"
62
70
  }
63
- }
71
+ }
@@ -1,61 +0,0 @@
1
- // src/components.ts
2
- import {
3
- ErrorBoundary,
4
- Suspense,
5
- createComponent,
6
- createResource,
7
- splitProps
8
- } from "solid-js";
9
- import { Dynamic } from "solid-js/web";
10
- import { WebWidgetRenderer } from "@web-widget/web-widget";
11
- function resolveFallback(fallback) {
12
- var _a;
13
- if (fallback !== null && typeof fallback === "object" && ("pending" in fallback || "error" in fallback)) {
14
- return {
15
- pending: fallback.pending,
16
- error: (_a = fallback.error) != null ? _a : fallback.pending
17
- };
18
- }
19
- return { pending: fallback, error: fallback };
20
- }
21
- function container(loader, options = {}) {
22
- return (props) => {
23
- var _a, _b, _c, _d;
24
- const [local, data] = splitProps(props, ["children", "widget"]);
25
- if (local.children) throw new TypeError("Children not supported.");
26
- const widget = (_a = local.widget) != null ? _a : {};
27
- const fallback = resolveFallback(widget.fallback);
28
- const renderStage = widget.serverOnly ? "server" : widget.clientOnly ? "client" : options.renderStage;
29
- const renderer = new WebWidgetRenderer(loader, {
30
- ...options,
31
- children: "",
32
- data,
33
- loading: (_c = (_b = widget.loading) != null ? _b : options.loading) != null ? _c : "lazy",
34
- renderStage,
35
- renderTarget: (_d = options.renderTarget) != null ? _d : "light"
36
- });
37
- const [html] = createResource(() => renderer.renderInnerHTMLToString());
38
- const content = () => createComponent(Dynamic, {
39
- component: renderer.localName,
40
- ...renderer.attributes,
41
- get innerHTML() {
42
- return html();
43
- }
44
- });
45
- return createComponent(ErrorBoundary, {
46
- fallback: () => fallback.error,
47
- get children() {
48
- return createComponent(Suspense, {
49
- fallback: fallback.pending,
50
- get children() {
51
- return content();
52
- }
53
- });
54
- }
55
- });
56
- };
57
- }
58
-
59
- export {
60
- container
61
- };
@@ -1,22 +0,0 @@
1
- import { Component, JSX } from 'solid-js';
2
- import { WebWidgetRendererOptions, Loader } from '@web-widget/web-widget';
3
- import { ExtractWidgetProps } from '@web-widget/schema';
4
-
5
- type DefineWebWidgetOptions = Partial<Pick<WebWidgetRendererOptions, 'base' | 'import' | 'loading' | 'name' | 'renderStage' | 'renderTarget'>>;
6
- interface WidgetContainerConfig {
7
- fallback?: JSX.Element | {
8
- pending?: JSX.Element;
9
- error?: JSX.Element;
10
- };
11
- loading?: WebWidgetRendererOptions['loading'];
12
- serverOnly?: true;
13
- clientOnly?: true;
14
- }
15
- type SolidWidgetComponent<T = unknown> = Component<T & {
16
- children?: JSX.Element;
17
- widget?: WidgetContainerConfig;
18
- }>;
19
- declare function container<M>(loader: () => Promise<M>, options?: DefineWebWidgetOptions): SolidWidgetComponent<ExtractWidgetProps<M>>;
20
- declare function container<Props>(loader: Loader, options?: DefineWebWidgetOptions): SolidWidgetComponent<Props>;
21
-
22
- export { type DefineWebWidgetOptions as D, type SolidWidgetComponent as S, type WidgetContainerConfig as W, container as c };