@takazudo/zfb 4.3.3 → 4.5.0
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 +14 -0
- package/dist/css.d.ts +45 -0
- package/dist/css.js +137 -0
- package/dist/css.js.map +1 -0
- package/dist/zudo-react/dom-bindings.js +11 -5
- package/dist/zudo-react/dom-bindings.js.map +1 -1
- package/dist/zudo-react/error-boundary-client.d.ts +3 -0
- package/dist/zudo-react/error-boundary-client.js +232 -0
- package/dist/zudo-react/error-boundary-client.js.map +1 -0
- package/dist/zudo-react/error-boundary-type.d.ts +8 -0
- package/dist/zudo-react/error-boundary-type.js +25 -0
- package/dist/zudo-react/error-boundary-type.js.map +1 -0
- package/dist/zudo-react/error-boundary.d.ts +8 -0
- package/dist/zudo-react/error-boundary.js +13 -0
- package/dist/zudo-react/error-boundary.js.map +1 -0
- package/dist/zudo-react/form-recovery.d.ts +2 -0
- package/dist/zudo-react/form-recovery.js +116 -0
- package/dist/zudo-react/form-recovery.js.map +1 -0
- package/dist/zudo-react/forms.d.ts +38 -4
- package/dist/zudo-react/forms.js +143 -172
- package/dist/zudo-react/forms.js.map +1 -1
- package/dist/zudo-react/hydrate.d.ts +68 -0
- package/dist/zudo-react/hydrate.js +177 -89
- package/dist/zudo-react/hydrate.js.map +1 -1
- package/dist/zudo-react/index.d.ts +1 -0
- package/dist/zudo-react/index.js +1 -0
- package/dist/zudo-react/index.js.map +1 -1
- package/dist/zudo-react/render-html.js +55 -10
- package/dist/zudo-react/render-html.js.map +1 -1
- package/dist/zudo-react/scope.d.ts +21 -13
- package/dist/zudo-react/scope.js +141 -113
- package/dist/zudo-react/scope.js.map +1 -1
- package/dist/zudo-react/style.d.ts +0 -1
- package/dist/zudo-react/style.js +11 -503
- package/dist/zudo-react/style.js.map +1 -1
- package/dist/zudo-react/vocabulary.js +12 -49
- package/dist/zudo-react/vocabulary.js.map +1 -1
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -24,6 +24,20 @@ npm install @takazudo/zfb
|
|
|
24
24
|
# or: yarn add @takazudo/zfb
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
## Compile CSS in Node.js
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { compileCss } from "@takazudo/zfb/css";
|
|
31
|
+
|
|
32
|
+
const { css, diagnostics, warnings } = await compileCss({
|
|
33
|
+
input: "styles/main.css",
|
|
34
|
+
sources: ["components/**/*.tsx"],
|
|
35
|
+
noAutoSource: true,
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Requires Node.js ≥22 and the matching native platform package installed through optional dependencies. This ESM entry compiles in-process, accepts already-evaluated CSS configuration, and never discovers config files. `output` is optional; every successful call returns CSS. The addon is isolated from root/runtime imports. See the [CSS API reference](https://takazudomodular.com/pj/zudo-front-builder/docs/api/compile-css/) for path anchors, presets, diagnostics, and supported platforms.
|
|
40
|
+
|
|
27
41
|
## What lives here
|
|
28
42
|
|
|
29
43
|
This package is the canonical TypeScript source for the `zfb` SDK
|
package/dist/css.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { CodeHighlightMode, ZfbConfig } from "./config.js";
|
|
2
|
+
export type CssCompileConfig = Pick<ZfbConfig, "wind" | "codeHighlight" | "outDir" | "presets">;
|
|
3
|
+
export interface CompileCssOptions {
|
|
4
|
+
input: string;
|
|
5
|
+
cwd?: string;
|
|
6
|
+
projectRoot?: string;
|
|
7
|
+
configDir?: string;
|
|
8
|
+
config?: CssCompileConfig;
|
|
9
|
+
sources?: string[];
|
|
10
|
+
noAutoSource?: boolean;
|
|
11
|
+
codeHighlightMode?: CodeHighlightMode;
|
|
12
|
+
noDefaultHighlightStyles?: boolean;
|
|
13
|
+
output?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface CssDiagnosticOrigin {
|
|
16
|
+
sourceId: string | null;
|
|
17
|
+
path: string | null;
|
|
18
|
+
line: number | null;
|
|
19
|
+
/** One-based byte column. */
|
|
20
|
+
column: number | null;
|
|
21
|
+
byteOffset: number | null;
|
|
22
|
+
label: string | null;
|
|
23
|
+
}
|
|
24
|
+
export interface CssDiagnostic {
|
|
25
|
+
code: string;
|
|
26
|
+
severity: "warning" | "error";
|
|
27
|
+
message: string;
|
|
28
|
+
candidate: string | null;
|
|
29
|
+
origin: CssDiagnosticOrigin;
|
|
30
|
+
}
|
|
31
|
+
export interface CompileCssResult {
|
|
32
|
+
css: string;
|
|
33
|
+
diagnostics: CssDiagnostic[];
|
|
34
|
+
/** Source planning and configuration warnings, preserved verbatim. */
|
|
35
|
+
warnings: string[];
|
|
36
|
+
}
|
|
37
|
+
export declare class CssCompileError extends Error {
|
|
38
|
+
readonly diagnostics: CssDiagnostic[];
|
|
39
|
+
readonly code: string | undefined;
|
|
40
|
+
readonly severity: "warning" | "error" | undefined;
|
|
41
|
+
readonly origin: CssDiagnosticOrigin | undefined;
|
|
42
|
+
constructor(message: string, diagnostics?: CssDiagnostic[], options?: ErrorOptions);
|
|
43
|
+
}
|
|
44
|
+
/** Compile a CSS file in-process. Configuration files are never discovered or evaluated. */
|
|
45
|
+
export declare function compileCss(options: CompileCssOptions): Promise<CompileCssResult>;
|
package/dist/css.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { isAbsolute, sep } from "node:path";
|
|
3
|
+
import { readdirSync } from "node:fs";
|
|
4
|
+
export class CssCompileError extends Error {
|
|
5
|
+
diagnostics;
|
|
6
|
+
code;
|
|
7
|
+
severity;
|
|
8
|
+
origin;
|
|
9
|
+
constructor(message, diagnostics = [], options) {
|
|
10
|
+
super(message, options);
|
|
11
|
+
this.name = "CssCompileError";
|
|
12
|
+
this.diagnostics = diagnostics;
|
|
13
|
+
const primary = diagnostics.find((item) => item.severity === "error") ?? diagnostics[0];
|
|
14
|
+
this.code = primary?.code;
|
|
15
|
+
this.severity = primary?.severity;
|
|
16
|
+
this.origin = primary?.origin;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
let binding;
|
|
20
|
+
const require = createRequire(import.meta.url);
|
|
21
|
+
function loadBinding() {
|
|
22
|
+
if (binding)
|
|
23
|
+
return binding;
|
|
24
|
+
const platform = process.platform;
|
|
25
|
+
const arch = process.arch;
|
|
26
|
+
if (platform === "linux") {
|
|
27
|
+
const report = process.report?.getReport();
|
|
28
|
+
let musl = false;
|
|
29
|
+
try {
|
|
30
|
+
musl = readdirSync("/lib").some((name) => name.startsWith("ld-musl-"));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* The report remains authoritative when /lib is inaccessible. */
|
|
34
|
+
}
|
|
35
|
+
if (!report.header?.glibcVersionRuntime && musl) {
|
|
36
|
+
throw new CssCompileError("@takazudo/zfb/css requires glibc on Linux; musl is not supported");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const carrier = platform === "darwin" && (arch === "arm64" || arch === "x64")
|
|
40
|
+
? `darwin-${arch}`
|
|
41
|
+
: platform === "linux" && (arch === "arm64" || arch === "x64")
|
|
42
|
+
? `linux-${arch}-gnu`
|
|
43
|
+
: platform === "win32" && arch === "x64"
|
|
44
|
+
? "win32-x64-msvc"
|
|
45
|
+
: undefined;
|
|
46
|
+
if (!carrier)
|
|
47
|
+
throw new CssCompileError(`Unsupported CSS compiler platform: ${platform}/${arch}`);
|
|
48
|
+
const name = `@takazudo/zfb-${carrier}`;
|
|
49
|
+
try {
|
|
50
|
+
const sdk = require("../package.json");
|
|
51
|
+
const installed = require(`${name}/package.json`);
|
|
52
|
+
if (installed.version !== sdk.version) {
|
|
53
|
+
throw new Error(`Expected ${name}@${sdk.version}, found ${installed.version}`);
|
|
54
|
+
}
|
|
55
|
+
const loaded = require(`${name}/zfb-css.node`);
|
|
56
|
+
if (typeof loaded.compileCssNative !== "function")
|
|
57
|
+
throw new Error("Native CSS entry is missing");
|
|
58
|
+
binding = loaded;
|
|
59
|
+
return loaded;
|
|
60
|
+
}
|
|
61
|
+
catch (cause) {
|
|
62
|
+
throw new CssCompileError(`Cannot load the packaged CSS compiler from ${name}/zfb-css.node. Install the matching platform package with optional dependencies enabled.`, [], { cause });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function jsonValue(value, path, parents = new Set()) {
|
|
66
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
67
|
+
return value;
|
|
68
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
69
|
+
return value;
|
|
70
|
+
if (typeof value !== "object")
|
|
71
|
+
throw new CssCompileError(`${path}: expected a JSON-compatible value`);
|
|
72
|
+
if (parents.has(value))
|
|
73
|
+
throw new CssCompileError(`${path}: circular configuration`);
|
|
74
|
+
if (!Array.isArray(value) &&
|
|
75
|
+
Object.getPrototypeOf(value) !== Object.prototype &&
|
|
76
|
+
Object.getPrototypeOf(value) !== null) {
|
|
77
|
+
throw new CssCompileError(`${path}: expected a plain object`);
|
|
78
|
+
}
|
|
79
|
+
parents.add(value);
|
|
80
|
+
const result = Array.isArray(value)
|
|
81
|
+
? Array.from(value, (item, index) => jsonValue(item, `${path}[${index}]`, parents))
|
|
82
|
+
: Object.fromEntries(Object.entries(value)
|
|
83
|
+
.filter(([, item]) => item !== undefined)
|
|
84
|
+
.map(([key, item]) => [key, jsonValue(item, `${path}.${key}`, parents)]));
|
|
85
|
+
parents.delete(value);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function projectConfig(value, path = "config", parents = new Set()) {
|
|
89
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
90
|
+
throw new CssCompileError(`${path}: expected an object`);
|
|
91
|
+
if (parents.has(value))
|
|
92
|
+
throw new CssCompileError(`${path}: circular configuration`);
|
|
93
|
+
parents.add(value);
|
|
94
|
+
const projected = {};
|
|
95
|
+
for (const key of ["wind", "codeHighlight", "outDir"]) {
|
|
96
|
+
if (value[key] !== undefined)
|
|
97
|
+
projected[key] = jsonValue(value[key], `${path}.${key}`);
|
|
98
|
+
}
|
|
99
|
+
if (value.presets !== undefined) {
|
|
100
|
+
if (!Array.isArray(value.presets))
|
|
101
|
+
throw new CssCompileError(`${path}.presets: expected an array`);
|
|
102
|
+
projected.presets = value.presets.map((preset, index) => projectConfig(preset, `${path}.presets[${index}]`, parents));
|
|
103
|
+
}
|
|
104
|
+
parents.delete(value);
|
|
105
|
+
return projected;
|
|
106
|
+
}
|
|
107
|
+
/** Compile a CSS file in-process. Configuration files are never discovered or evaluated. */
|
|
108
|
+
export async function compileCss(options) {
|
|
109
|
+
try {
|
|
110
|
+
const invocationCwd = process.cwd();
|
|
111
|
+
const cwd = options.cwd === undefined
|
|
112
|
+
? invocationCwd
|
|
113
|
+
: isAbsolute(options.cwd)
|
|
114
|
+
? options.cwd
|
|
115
|
+
: `${invocationCwd}${sep}${options.cwd}`;
|
|
116
|
+
// Rust preserves symlink/parent semantics; path.resolve would collapse them here.
|
|
117
|
+
const request = {
|
|
118
|
+
...options,
|
|
119
|
+
cwd,
|
|
120
|
+
...(options.config === undefined ? {} : { config: projectConfig(options.config) }),
|
|
121
|
+
};
|
|
122
|
+
const response = JSON.parse(await loadBinding().compileCssNative(JSON.stringify(request)));
|
|
123
|
+
if (response.error)
|
|
124
|
+
throw new CssCompileError(response.error.message, response.error.diagnostics);
|
|
125
|
+
if (!response.result)
|
|
126
|
+
throw new CssCompileError("Native CSS compiler returned an invalid response");
|
|
127
|
+
return response.result;
|
|
128
|
+
}
|
|
129
|
+
catch (cause) {
|
|
130
|
+
if (cause instanceof CssCompileError)
|
|
131
|
+
throw cause;
|
|
132
|
+
throw new CssCompileError(cause instanceof Error ? cause.message : String(cause), [], {
|
|
133
|
+
cause,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=css.js.map
|
package/dist/css.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css.js","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AA2CtC,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,WAAW,CAAkB;IAC7B,IAAI,CAAqB;IACzB,QAAQ,CAAkC;IAC1C,MAAM,CAAkC;IAEjD,YAAY,OAAe,EAAE,WAAW,GAAoB,EAAE,EAAE,OAAsB;QACpF,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,IAAI,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;IAChC,CAAC;CACF;AAKD,IAAI,OAA4B,CAAC;AACjC,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,SAAS,WAAW;IAClB,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1B,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,EAAmD,CAAC;QAC5F,IAAI,IAAI,GAAG,KAAK,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QACzE,CAAC;QAAC,MAAM,CAAC;YACP,iEAAiE;QACnE,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,IAAI,IAAI,EAAE,CAAC;YAChD,MAAM,IAAI,eAAe,CAAC,kEAAkE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GACX,QAAQ,KAAK,QAAQ,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK,CAAC;QAC3D,CAAC,CAAC,UAAU,IAAI,EAAE;QAClB,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK,CAAC;YAC5D,CAAC,CAAC,SAAS,IAAI,MAAM;YACrB,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK;gBACtC,CAAC,CAAC,gBAAgB;gBAClB,CAAC,CAAC,SAAS,CAAC;IACpB,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,eAAe,CAAC,sCAAsC,QAAQ,IAAI,IAAI,EAAE,CAAC,CAAC;IAClG,MAAM,IAAI,GAAG,iBAAiB,OAAO,EAAE,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;QAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,IAAI,eAAe,CAAwB,CAAC;QACzE,IAAI,SAAS,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,IAAI,GAAG,CAAC,OAAO,WAAW,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,eAAe,CAAY,CAAC;QAC1D,IAAI,OAAO,MAAM,CAAC,gBAAgB,KAAK,UAAU;YAC/C,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,OAAO,GAAG,MAAM,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,eAAe,CACvB,8CAA8C,IAAI,0FAA0F,EAC5I,EAAE,EACF,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAc,EAAE,IAAY,EAAE,OAAO,GAAG,IAAI,GAAG,EAAU;IAC1E,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC5F,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAC3B,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,oCAAoC,CAAC,CAAC;IACzE,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,0BAA0B,CAAC,CAAC;IACrF,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACrB,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,SAAS;QACjD,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,IAAI,EACrC,CAAC;QACD,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,2BAA2B,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACjC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,OAAO,CAAC,CAAC;QACnF,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC;aACxC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAC3E,CAAC;IACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CACpB,KAAuB,EACvB,IAAI,GAAG,QAAQ,EACf,OAAO,GAAG,IAAI,GAAG,EAAU;IAE3B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAC7D,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,sBAAsB,CAAC,CAAC;IAC3D,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,0BAA0B,CAAC,CAAC;IACrF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnB,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,EAAE,QAAQ,CAAU,EAAE,CAAC;QAC/D,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,SAAS;YAAE,SAAS,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;IACzF,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;YAC/B,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,6BAA6B,CAAC,CAAC;QAClE,SAAS,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACtD,aAAa,CAAC,MAAM,EAAE,GAAG,IAAI,YAAY,KAAK,GAAG,EAAE,OAAO,CAAC,CAC5D,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAA0B;IACzD,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,GAAG,GACP,OAAO,CAAC,GAAG,KAAK,SAAS;YACvB,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC;gBACvB,CAAC,CAAC,OAAO,CAAC,GAAG;gBACb,CAAC,CAAC,GAAG,aAAa,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC/C,kFAAkF;QAClF,MAAM,OAAO,GAAG;YACd,GAAG,OAAO;YACV,GAAG;YACH,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;SACnF,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,WAAW,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAGxF,CAAC;QACF,IAAI,QAAQ,CAAC,KAAK;YAChB,MAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAChF,IAAI,CAAC,QAAQ,CAAC,MAAM;YAClB,MAAM,IAAI,eAAe,CAAC,kDAAkD,CAAC,CAAC;QAChF,OAAO,QAAQ,CAAC,MAAM,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,eAAe;YAAE,MAAM,KAAK,CAAC;QAClD,MAAM,IAAI,eAAe,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE;YACpF,KAAK;SACN,CAAC,CAAC;IACL,CAAC;AACH,CAAC","sourcesContent":["import { createRequire } from \"node:module\";\nimport { isAbsolute, sep } from \"node:path\";\nimport { readdirSync } from \"node:fs\";\nimport type { CodeHighlightMode, ZfbConfig } from \"./config.js\";\n\nexport type CssCompileConfig = Pick<ZfbConfig, \"wind\" | \"codeHighlight\" | \"outDir\" | \"presets\">;\n\nexport interface CompileCssOptions {\n input: string;\n cwd?: string;\n projectRoot?: string;\n configDir?: string;\n config?: CssCompileConfig;\n sources?: string[];\n noAutoSource?: boolean;\n codeHighlightMode?: CodeHighlightMode;\n noDefaultHighlightStyles?: boolean;\n output?: string;\n}\n\nexport interface CssDiagnosticOrigin {\n sourceId: string | null;\n path: string | null;\n line: number | null;\n /** One-based byte column. */\n column: number | null;\n byteOffset: number | null;\n label: string | null;\n}\n\nexport interface CssDiagnostic {\n code: string;\n severity: \"warning\" | \"error\";\n message: string;\n candidate: string | null;\n origin: CssDiagnosticOrigin;\n}\n\nexport interface CompileCssResult {\n css: string;\n diagnostics: CssDiagnostic[];\n /** Source planning and configuration warnings, preserved verbatim. */\n warnings: string[];\n}\n\nexport class CssCompileError extends Error {\n readonly diagnostics: CssDiagnostic[];\n readonly code: string | undefined;\n readonly severity: \"warning\" | \"error\" | undefined;\n readonly origin: CssDiagnosticOrigin | undefined;\n\n constructor(message: string, diagnostics: CssDiagnostic[] = [], options?: ErrorOptions) {\n super(message, options);\n this.name = \"CssCompileError\";\n this.diagnostics = diagnostics;\n const primary = diagnostics.find((item) => item.severity === \"error\") ?? diagnostics[0];\n this.code = primary?.code;\n this.severity = primary?.severity;\n this.origin = primary?.origin;\n }\n}\n\ninterface Binding {\n compileCssNative(request: string): Promise<string>;\n}\nlet binding: Binding | undefined;\nconst require = createRequire(import.meta.url);\n\nfunction loadBinding(): Binding {\n if (binding) return binding;\n const platform = process.platform;\n const arch = process.arch;\n if (platform === \"linux\") {\n const report = process.report?.getReport() as { header?: { glibcVersionRuntime?: string } };\n let musl = false;\n try {\n musl = readdirSync(\"/lib\").some((name) => name.startsWith(\"ld-musl-\"));\n } catch {\n /* The report remains authoritative when /lib is inaccessible. */\n }\n if (!report.header?.glibcVersionRuntime && musl) {\n throw new CssCompileError(\"@takazudo/zfb/css requires glibc on Linux; musl is not supported\");\n }\n }\n const carrier =\n platform === \"darwin\" && (arch === \"arm64\" || arch === \"x64\")\n ? `darwin-${arch}`\n : platform === \"linux\" && (arch === \"arm64\" || arch === \"x64\")\n ? `linux-${arch}-gnu`\n : platform === \"win32\" && arch === \"x64\"\n ? \"win32-x64-msvc\"\n : undefined;\n if (!carrier) throw new CssCompileError(`Unsupported CSS compiler platform: ${platform}/${arch}`);\n const name = `@takazudo/zfb-${carrier}`;\n try {\n const sdk = require(\"../package.json\") as { version: string };\n const installed = require(`${name}/package.json`) as { version: string };\n if (installed.version !== sdk.version) {\n throw new Error(`Expected ${name}@${sdk.version}, found ${installed.version}`);\n }\n const loaded = require(`${name}/zfb-css.node`) as Binding;\n if (typeof loaded.compileCssNative !== \"function\")\n throw new Error(\"Native CSS entry is missing\");\n binding = loaded;\n return loaded;\n } catch (cause) {\n throw new CssCompileError(\n `Cannot load the packaged CSS compiler from ${name}/zfb-css.node. Install the matching platform package with optional dependencies enabled.`,\n [],\n { cause },\n );\n }\n}\n\nfunction jsonValue(value: unknown, path: string, parents = new Set<object>()): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"object\")\n throw new CssCompileError(`${path}: expected a JSON-compatible value`);\n if (parents.has(value)) throw new CssCompileError(`${path}: circular configuration`);\n if (\n !Array.isArray(value) &&\n Object.getPrototypeOf(value) !== Object.prototype &&\n Object.getPrototypeOf(value) !== null\n ) {\n throw new CssCompileError(`${path}: expected a plain object`);\n }\n parents.add(value);\n const result = Array.isArray(value)\n ? Array.from(value, (item, index) => jsonValue(item, `${path}[${index}]`, parents))\n : Object.fromEntries(\n Object.entries(value)\n .filter(([, item]) => item !== undefined)\n .map(([key, item]) => [key, jsonValue(item, `${path}.${key}`, parents)]),\n );\n parents.delete(value);\n return result;\n}\n\nfunction projectConfig(\n value: CssCompileConfig,\n path = \"config\",\n parents = new Set<object>(),\n): unknown {\n if (!value || typeof value !== \"object\" || Array.isArray(value))\n throw new CssCompileError(`${path}: expected an object`);\n if (parents.has(value)) throw new CssCompileError(`${path}: circular configuration`);\n parents.add(value);\n const projected: Record<string, unknown> = {};\n for (const key of [\"wind\", \"codeHighlight\", \"outDir\"] as const) {\n if (value[key] !== undefined) projected[key] = jsonValue(value[key], `${path}.${key}`);\n }\n if (value.presets !== undefined) {\n if (!Array.isArray(value.presets))\n throw new CssCompileError(`${path}.presets: expected an array`);\n projected.presets = value.presets.map((preset, index) =>\n projectConfig(preset, `${path}.presets[${index}]`, parents),\n );\n }\n parents.delete(value);\n return projected;\n}\n\n/** Compile a CSS file in-process. Configuration files are never discovered or evaluated. */\nexport async function compileCss(options: CompileCssOptions): Promise<CompileCssResult> {\n try {\n const invocationCwd = process.cwd();\n const cwd =\n options.cwd === undefined\n ? invocationCwd\n : isAbsolute(options.cwd)\n ? options.cwd\n : `${invocationCwd}${sep}${options.cwd}`;\n // Rust preserves symlink/parent semantics; path.resolve would collapse them here.\n const request = {\n ...options,\n cwd,\n ...(options.config === undefined ? {} : { config: projectConfig(options.config) }),\n };\n const response = JSON.parse(await loadBinding().compileCssNative(JSON.stringify(request))) as {\n result?: CompileCssResult;\n error?: { message: string; diagnostics: CssDiagnostic[] };\n };\n if (response.error)\n throw new CssCompileError(response.error.message, response.error.diagnostics);\n if (!response.result)\n throw new CssCompileError(\"Native CSS compiler returned an invalid response\");\n return response.result;\n } catch (cause) {\n if (cause instanceof CssCompileError) throw cause;\n throw new CssCompileError(cause instanceof Error ? cause.message : String(cause), [], {\n cause,\n });\n }\n}\n"]}
|
|
@@ -33,11 +33,17 @@ export function setAttribute(element, name, value) {
|
|
|
33
33
|
export function bind(source, scope, options, container, path, apply, initial) {
|
|
34
34
|
let previous = initial;
|
|
35
35
|
const subscription = subscribe(() => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
try {
|
|
37
|
+
const next = source.value;
|
|
38
|
+
if (Object.is(previous, next))
|
|
39
|
+
return;
|
|
40
|
+
previous = next;
|
|
41
|
+
apply(next);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (!scope.recoverRender(error))
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
41
47
|
}, {
|
|
42
48
|
active: () => scope.active,
|
|
43
49
|
report: (code, actual) => report(options, diagnostic(options, code, "update", `${rootPath(container)}${path}`, "binding update", actual)),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-bindings.js","sourceRoot":"","sources":["../../src/zudo-react/dom-bindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAqB,MAAM,eAAe,CAAC;AAI3E,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEpE,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,gBAAgB,IAAI,KAAK;QACzB,KAAK,CAAC,cAAc,KAAK,wBAAwB,CAClD,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,IAAI,CAAC,KAAc;IACjC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC;AACD,MAAM,CAAC,MAAM,SAAS,GAAG,cAAc,CAAC;AACxC,MAAM,UAAU,YAAY,CAAC,OAAgB,EAAE,IAAY,EAAE,KAAc;IACzE,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,MAAM,IAAI,GAAG,IAAI,KAAK,OAAO,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/F,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,IAAI,SAAS;YAAE,OAAO,CAAC,iBAAiB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;;YAC1D,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IACD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,KAAK,IAAI;YACvD,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;SAAM,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACnF,CAAC;AACD,MAAM,UAAU,IAAI,CAClB,MAAyB,EACzB,KAAmB,EACnB,OAAoB,EACpB,SAAkB,EAClB,IAAY,EACZ,KAAyB,EACzB,OAAU;IAEV,IAAI,QAAQ,GAAG,OAAO,CAAC;IACvB,MAAM,YAAY,GAAG,SAAS,CAC5B,GAAG,EAAE;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"dom-bindings.js","sourceRoot":"","sources":["../../src/zudo-react/dom-bindings.ts"],"names":[],"mappings":"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","sourcesContent":["import { serializeStyle } from \"./style.js\";\nimport { subscribe, readSnapshot, type Subscription } from \"./reactive.js\";\nimport type { ReadonlySignal } from \"./reactive-types.js\";\nimport type { RuntimeScope } from \"./scope.js\";\nimport type { RootOptions } from \"./root.js\";\nimport { diagnostic, report, rootPath } from \"./root.js\";\nimport { attributeNamespace, attributeText } from \"./vocabulary.js\";\n\nexport function isReactive(value: unknown): value is ReadonlySignal<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"$$zudoReactive\" in value &&\n value.$$zudoReactive === \"zudo-react.reactive.v1\"\n );\n}\nexport function read(value: unknown): unknown {\n return isReactive(value) ? readSnapshot(value) : value;\n}\nexport const styleText = serializeStyle;\nexport function setAttribute(element: Element, name: string, value: unknown): void {\n const namespace = attributeNamespace(name);\n const localName = namespace && name.includes(\":\") ? name.split(\":\")[1]! : name;\n const text = name === \"style\" && value != null ? styleText(value) : attributeText(name, value);\n if (text === null) {\n if (namespace) element.removeAttributeNS(namespace, localName);\n else element.removeAttribute(name);\n return;\n }\n if (namespace) {\n if (element.getAttributeNS(namespace, localName) !== text)\n element.setAttributeNS(namespace, name, text);\n } else if (element.getAttribute(name) !== text) element.setAttribute(name, text);\n}\nexport function bind<T>(\n source: ReadonlySignal<T>,\n scope: RuntimeScope,\n options: RootOptions,\n container: Element,\n path: string,\n apply: (value: T) => void,\n initial: T,\n): Subscription {\n let previous = initial;\n const subscription = subscribe(\n () => {\n try {\n const next = source.value;\n if (Object.is(previous, next)) return;\n previous = next;\n apply(next);\n } catch (error) {\n if (!scope.recoverRender(error)) throw error;\n }\n },\n {\n active: () => scope.active,\n report: (code, actual) =>\n report(\n options,\n diagnostic(\n options,\n code,\n \"update\",\n `${rootPath(container)}${path}`,\n \"binding update\",\n actual,\n ),\n ),\n },\n );\n subscription.run();\n return subscription;\n}\nexport function listener(name: string): { name: string; capture: boolean } | null {\n const match = /^on:([A-Za-z][A-Za-z0-9_-]*)(:capture)?$/.exec(name);\n return match ? { name: match[1]!, capture: Boolean(match[2]) } : null;\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Description } from "./description.js";
|
|
2
|
+
import type { BoundaryHost, BuildContext } from "./hydrate.js";
|
|
3
|
+
export declare function renderErrorBoundary(value: Description, parent: Node, context: BuildContext, namespace: string, parentTag: string, path: string, host: BoundaryHost): void;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { boundaryProps } from "./error-boundary-type.js";
|
|
2
|
+
import { createFormRecovery } from "./form-recovery.js";
|
|
3
|
+
// Each attempt has its own collection lifetime. Failed descriptions, markers,
|
|
4
|
+
// provisional forms and operations cannot remain reachable through the root.
|
|
5
|
+
export function renderErrorBoundary(value, parent, context, namespace, parentTag, path, host) {
|
|
6
|
+
// Use the owning renderer's scope/reactivity/form state, including when the
|
|
7
|
+
// boundary function came from another package copy with the shared type token.
|
|
8
|
+
const { owned, installOwned, selfMap, marker, range, fail, openMarker, matchingClose, recoverable, prepareForms, read, subscribe, untracked, enqueue, } = host;
|
|
9
|
+
context.root.recovery ??= (scope, error) => {
|
|
10
|
+
let attempted = false;
|
|
11
|
+
for (let owner = scope; owner; owner = owner.parent) {
|
|
12
|
+
if (!recoverable(error))
|
|
13
|
+
throw error;
|
|
14
|
+
if (!owner.active || !owner.renderRecovery)
|
|
15
|
+
continue;
|
|
16
|
+
attempted = true;
|
|
17
|
+
try {
|
|
18
|
+
const commit = untracked(() => owner.renderRecovery(error));
|
|
19
|
+
return () => untracked(commit);
|
|
20
|
+
}
|
|
21
|
+
catch (next) {
|
|
22
|
+
error = next;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (attempted)
|
|
26
|
+
throw error;
|
|
27
|
+
return undefined;
|
|
28
|
+
};
|
|
29
|
+
const { recoveries } = host.formHost;
|
|
30
|
+
if (!recoveries.has(context.container)) {
|
|
31
|
+
recoveries.set(context.container, createFormRecovery(context.container, host.formHost));
|
|
32
|
+
context.root.cleanups.push(() => recoveries.delete(context.container));
|
|
33
|
+
}
|
|
34
|
+
const props = boundaryProps(value);
|
|
35
|
+
const owner = context.scope.child("ErrorBoundary");
|
|
36
|
+
const prefix = `${context.prefix ?? ""}${context.next}.`;
|
|
37
|
+
let current;
|
|
38
|
+
let installed = false;
|
|
39
|
+
let requested = false;
|
|
40
|
+
let start;
|
|
41
|
+
let end;
|
|
42
|
+
let lastKey = props.resetKey && read(props.resetKey);
|
|
43
|
+
const clear = () => {
|
|
44
|
+
for (const node of range(start, end).slice(1, -1))
|
|
45
|
+
node.parentNode.removeChild(node);
|
|
46
|
+
};
|
|
47
|
+
const attempt = (factory, initial) => {
|
|
48
|
+
const local = {
|
|
49
|
+
...context,
|
|
50
|
+
scope: owner,
|
|
51
|
+
next: 0,
|
|
52
|
+
prefix,
|
|
53
|
+
operations: [],
|
|
54
|
+
forms: [],
|
|
55
|
+
formOwners: new WeakMap(),
|
|
56
|
+
opaque: new WeakSet(),
|
|
57
|
+
textSlots: new WeakSet(),
|
|
58
|
+
displayOnlyTextareas: new WeakSet(),
|
|
59
|
+
dynamicRanges: [],
|
|
60
|
+
collectRootRanges: false,
|
|
61
|
+
errorRanges: new WeakMap(),
|
|
62
|
+
replacements: [],
|
|
63
|
+
};
|
|
64
|
+
const instance = owned(local, "ErrorBoundary attempt", namespace, parentTag, path, factory, true);
|
|
65
|
+
if (initial) {
|
|
66
|
+
context.forms.push(...instance.forms);
|
|
67
|
+
for (const form of instance.forms)
|
|
68
|
+
context.formOwners.set(form, local.formOwners.get(form) ?? instance);
|
|
69
|
+
}
|
|
70
|
+
local.forms.length = 0;
|
|
71
|
+
return instance;
|
|
72
|
+
};
|
|
73
|
+
const fallback = (error, initial) => {
|
|
74
|
+
if (!recoverable(error))
|
|
75
|
+
throw error;
|
|
76
|
+
return attempt(() => props.fallback(error, reset), initial);
|
|
77
|
+
};
|
|
78
|
+
const prepare = (initial) => {
|
|
79
|
+
let replacement;
|
|
80
|
+
try {
|
|
81
|
+
replacement = attempt(props.children, initial);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
return fallback(error, initial);
|
|
85
|
+
}
|
|
86
|
+
replacement.scope.renderRecovery = (error) => {
|
|
87
|
+
// Disposal makes all work from this attempt inert in the current pass.
|
|
88
|
+
current.scope.dispose();
|
|
89
|
+
const next = fallback(error, false);
|
|
90
|
+
return () => commit(next);
|
|
91
|
+
};
|
|
92
|
+
return replacement;
|
|
93
|
+
};
|
|
94
|
+
const commit = (replacement) => {
|
|
95
|
+
const map = selfMap(replacement.fragment);
|
|
96
|
+
try {
|
|
97
|
+
prepareForms(replacement.forms, map, "mount", context.container, [current.scope], start.parentNode);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
replacement.scope.dispose();
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
current.scope.dispose();
|
|
104
|
+
clear();
|
|
105
|
+
end.parentNode.insertBefore(replacement.fragment, end);
|
|
106
|
+
current = replacement;
|
|
107
|
+
installOwned(current, map, context, "mount");
|
|
108
|
+
if (owner.isActivated)
|
|
109
|
+
current.scope.activate();
|
|
110
|
+
};
|
|
111
|
+
const job = {
|
|
112
|
+
id: `ErrorBoundary:${owner.id}`,
|
|
113
|
+
phase: "commit",
|
|
114
|
+
active: () => owner.active && installed,
|
|
115
|
+
run: () => {
|
|
116
|
+
requested = false;
|
|
117
|
+
if (props.resetKey)
|
|
118
|
+
lastKey = read(props.resetKey);
|
|
119
|
+
let replacement;
|
|
120
|
+
try {
|
|
121
|
+
replacement = untracked(() => prepare(false));
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (!owner.recoverRender(error))
|
|
125
|
+
throw error;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
commit(replacement);
|
|
129
|
+
},
|
|
130
|
+
report: (code, actual) => owner.report(code, "update", actual),
|
|
131
|
+
};
|
|
132
|
+
function reset() {
|
|
133
|
+
if (requested || !job.active())
|
|
134
|
+
return;
|
|
135
|
+
requested = true;
|
|
136
|
+
enqueue(job);
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const ends = marker(context, parent, "e", () => {
|
|
140
|
+
current = untracked(() => prepare(true));
|
|
141
|
+
parent.appendChild(current.fragment);
|
|
142
|
+
});
|
|
143
|
+
context.errorRanges.set(ends[0], (wants, has, i, j, map, childPath) => {
|
|
144
|
+
const wanted = wants[i];
|
|
145
|
+
const found = has[j];
|
|
146
|
+
const wantedEnd = matchingClose(wants, i);
|
|
147
|
+
const foundEnd = matchingClose(has, j);
|
|
148
|
+
if (wantedEnd < 0 || foundEnd < 0)
|
|
149
|
+
fail("ZR_HYDRATION_MISMATCH", "preflight", "balanced boundary", "missing marker", childPath);
|
|
150
|
+
validateBoundaryMarkers(has.slice(j + 1, foundEnd), `${openMarker(found)[1]}.`, childPath, host);
|
|
151
|
+
const close = has[foundEnd];
|
|
152
|
+
map.set(wants[wantedEnd], close);
|
|
153
|
+
const mapFresh = (node) => {
|
|
154
|
+
map.set(node, node);
|
|
155
|
+
for (const child of node.childNodes)
|
|
156
|
+
mapFresh(child);
|
|
157
|
+
};
|
|
158
|
+
// Include whitespace nodes too: significant() is only a comparison view.
|
|
159
|
+
const allFresh = range(wanted, wants[wantedEnd]).slice(1, -1);
|
|
160
|
+
for (const node of allFresh)
|
|
161
|
+
mapFresh(node);
|
|
162
|
+
context.replacements.push(() => {
|
|
163
|
+
for (const node of range(found, close).slice(1, -1))
|
|
164
|
+
node.parentNode.removeChild(node);
|
|
165
|
+
for (const node of allFresh)
|
|
166
|
+
close.parentNode.insertBefore(node, close);
|
|
167
|
+
});
|
|
168
|
+
return [wantedEnd + 1, foundEnd + 1];
|
|
169
|
+
});
|
|
170
|
+
context.operations.push((map, cleanups) => {
|
|
171
|
+
start = map.get(ends[0]);
|
|
172
|
+
end = map.get(ends[1]);
|
|
173
|
+
installOwned(current, map, context, "hydrate");
|
|
174
|
+
installed = true;
|
|
175
|
+
if (props.resetKey) {
|
|
176
|
+
const key = props.resetKey;
|
|
177
|
+
const subscription = subscribe(() => {
|
|
178
|
+
const next = key.value;
|
|
179
|
+
if (Object.is(lastKey, next))
|
|
180
|
+
return;
|
|
181
|
+
lastKey = next;
|
|
182
|
+
reset();
|
|
183
|
+
}, { active: () => owner.active, report: job.report });
|
|
184
|
+
subscription.run();
|
|
185
|
+
owner.cleanups.push(() => subscription.dispose());
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
owner.dispose();
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function validateBoundaryMarkers(nodes, prefix, path, host) {
|
|
195
|
+
const { fail, openMarker } = host;
|
|
196
|
+
const seen = new Set();
|
|
197
|
+
const invalid = () => fail("ZR_HYDRATION_MISMATCH", "preflight", "balanced boundary markers", "invalid marker", path);
|
|
198
|
+
const visit = (children, namespace) => {
|
|
199
|
+
const stack = [];
|
|
200
|
+
for (const node of children) {
|
|
201
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
202
|
+
visit([...node.childNodes], namespace);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (node.nodeType !== Node.COMMENT_NODE)
|
|
206
|
+
continue;
|
|
207
|
+
const value = node.textContent ?? "";
|
|
208
|
+
const open = openMarker(node);
|
|
209
|
+
if (open) {
|
|
210
|
+
const id = open[1];
|
|
211
|
+
if (!id.startsWith(namespace) || id.slice(namespace.length).includes(".") || seen.has(id))
|
|
212
|
+
invalid();
|
|
213
|
+
seen.add(id);
|
|
214
|
+
stack.push({ id, namespace });
|
|
215
|
+
if (open[2] === "e")
|
|
216
|
+
namespace = `${id}.`;
|
|
217
|
+
}
|
|
218
|
+
else if (value.startsWith("/zr:1:")) {
|
|
219
|
+
const frame = stack.pop();
|
|
220
|
+
if (!frame || value !== `/zr:1:${frame.id}`)
|
|
221
|
+
invalid();
|
|
222
|
+
namespace = frame.namespace;
|
|
223
|
+
}
|
|
224
|
+
else if (value.includes("zr:1:"))
|
|
225
|
+
invalid();
|
|
226
|
+
}
|
|
227
|
+
if (stack.length)
|
|
228
|
+
invalid();
|
|
229
|
+
};
|
|
230
|
+
visit(nodes, prefix);
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=error-boundary-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-boundary-client.js","sourceRoot":"","sources":["../../src/zudo-react/error-boundary-client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Child, Description } from \"./description.js\";\nimport type { BoundaryHost, BuildContext, Owned } from \"./hydrate.js\";\nimport { boundaryProps } from \"./error-boundary-type.js\";\nimport { createFormRecovery } from \"./form-recovery.js\";\nimport type { RuntimeScope } from \"./scope.js\";\nimport type { Job } from \"./scheduler.js\";\n\n// Each attempt has its own collection lifetime. Failed descriptions, markers,\n// provisional forms and operations cannot remain reachable through the root.\nexport function renderErrorBoundary(\n value: Description,\n parent: Node,\n context: BuildContext,\n namespace: string,\n parentTag: string,\n path: string,\n host: BoundaryHost,\n): void {\n // Use the owning renderer's scope/reactivity/form state, including when the\n // boundary function came from another package copy with the shared type token.\n const {\n owned,\n installOwned,\n selfMap,\n marker,\n range,\n fail,\n openMarker,\n matchingClose,\n recoverable,\n prepareForms,\n read,\n subscribe,\n untracked,\n enqueue,\n } = host;\n context.root.recovery ??= (scope, error) => {\n let attempted = false;\n for (let owner: RuntimeScope | undefined = scope; owner; owner = owner.parent) {\n if (!recoverable(error)) throw error;\n if (!owner.active || !owner.renderRecovery) continue;\n attempted = true;\n try {\n const commit = untracked(() => owner.renderRecovery!(error));\n return () => untracked(commit);\n } catch (next) {\n error = next;\n }\n }\n if (attempted) throw error;\n return undefined;\n };\n const { recoveries } = host.formHost;\n if (!recoveries.has(context.container)) {\n recoveries.set(context.container, createFormRecovery(context.container, host.formHost));\n context.root.cleanups.push(() => recoveries.delete(context.container));\n }\n const props = boundaryProps(value);\n const owner = context.scope.child(\"ErrorBoundary\");\n const prefix = `${context.prefix ?? \"\"}${context.next}.`;\n let current: Owned;\n let installed = false;\n let requested = false;\n let start: Node;\n let end: Node;\n let lastKey = props.resetKey && read(props.resetKey);\n const clear = (): void => {\n for (const node of range(start, end).slice(1, -1)) node.parentNode!.removeChild(node);\n };\n const attempt = (factory: () => Child, initial: boolean): Owned => {\n const local: BuildContext = {\n ...context,\n scope: owner,\n next: 0,\n prefix,\n operations: [],\n forms: [],\n formOwners: new WeakMap(),\n opaque: new WeakSet(),\n textSlots: new WeakSet(),\n displayOnlyTextareas: new WeakSet(),\n dynamicRanges: [],\n collectRootRanges: false,\n errorRanges: new WeakMap(),\n replacements: [],\n };\n const instance = owned(\n local,\n \"ErrorBoundary attempt\",\n namespace,\n parentTag,\n path,\n factory,\n true,\n );\n if (initial) {\n context.forms.push(...instance.forms);\n for (const form of instance.forms)\n context.formOwners.set(form, local.formOwners.get(form) ?? instance);\n }\n local.forms.length = 0;\n return instance;\n };\n const fallback = (error: unknown, initial: boolean): Owned => {\n if (!recoverable(error)) throw error;\n return attempt(() => props.fallback(error, reset), initial);\n };\n const prepare = (initial: boolean): Owned => {\n let replacement: Owned;\n try {\n replacement = attempt(props.children, initial);\n } catch (error) {\n return fallback(error, initial);\n }\n replacement.scope.renderRecovery = (error) => {\n // Disposal makes all work from this attempt inert in the current pass.\n current.scope.dispose();\n const next = fallback(error, false);\n return () => commit(next);\n };\n return replacement;\n };\n const commit = (replacement: Owned): void => {\n const map = selfMap(replacement.fragment);\n try {\n prepareForms(\n replacement.forms,\n map,\n \"mount\",\n context.container,\n [current.scope],\n start.parentNode,\n );\n } catch (error) {\n replacement.scope.dispose();\n throw error;\n }\n current.scope.dispose();\n clear();\n end.parentNode!.insertBefore(replacement.fragment, end);\n current = replacement;\n installOwned(current, map, context, \"mount\");\n if (owner.isActivated) current.scope.activate();\n };\n const job: Job = {\n id: `ErrorBoundary:${owner.id}`,\n phase: \"commit\",\n active: () => owner.active && installed,\n run: () => {\n requested = false;\n if (props.resetKey) lastKey = read(props.resetKey);\n let replacement: Owned;\n try {\n replacement = untracked(() => prepare(false));\n } catch (error) {\n if (!owner.recoverRender(error)) throw error;\n return;\n }\n commit(replacement);\n },\n report: (code, actual) => owner.report(code, \"update\", actual),\n };\n function reset(): void {\n if (requested || !job.active()) return;\n requested = true;\n enqueue(job);\n }\n try {\n const ends = marker(context, parent, \"e\", () => {\n current = untracked(() => prepare(true));\n parent.appendChild(current.fragment);\n });\n context.errorRanges.set(ends[0], (wants, has, i, j, map, childPath) => {\n const wanted = wants[i]!;\n const found = has[j]!;\n const wantedEnd = matchingClose(wants, i);\n const foundEnd = matchingClose(has, j);\n if (wantedEnd < 0 || foundEnd < 0)\n fail(\n \"ZR_HYDRATION_MISMATCH\",\n \"preflight\",\n \"balanced boundary\",\n \"missing marker\",\n childPath,\n );\n validateBoundaryMarkers(\n has.slice(j + 1, foundEnd),\n `${openMarker(found)![1]}.`,\n childPath,\n host,\n );\n const close = has[foundEnd]!;\n map.set(wants[wantedEnd]!, close);\n const mapFresh = (node: Node): void => {\n map.set(node, node);\n for (const child of node.childNodes) mapFresh(child);\n };\n // Include whitespace nodes too: significant() is only a comparison view.\n const allFresh = range(wanted, wants[wantedEnd]!).slice(1, -1);\n for (const node of allFresh) mapFresh(node);\n context.replacements.push(() => {\n for (const node of range(found, close).slice(1, -1)) node.parentNode!.removeChild(node);\n for (const node of allFresh) close.parentNode!.insertBefore(node, close);\n });\n return [wantedEnd + 1, foundEnd + 1];\n });\n context.operations.push((map, cleanups) => {\n start = map.get(ends[0])!;\n end = map.get(ends[1])!;\n installOwned(current, map, context, \"hydrate\");\n installed = true;\n if (props.resetKey) {\n const key = props.resetKey;\n const subscription = subscribe(\n () => {\n const next = key.value;\n if (Object.is(lastKey, next)) return;\n lastKey = next;\n reset();\n },\n { active: () => owner.active, report: job.report },\n );\n subscription.run();\n owner.cleanups.push(() => subscription.dispose());\n }\n });\n } catch (error) {\n owner.dispose();\n throw error;\n }\n}\n\nfunction validateBoundaryMarkers(\n nodes: Node[],\n prefix: string,\n path: string,\n host: BoundaryHost,\n): void {\n const { fail, openMarker } = host;\n const seen = new Set<string>();\n const invalid = (): never =>\n fail(\"ZR_HYDRATION_MISMATCH\", \"preflight\", \"balanced boundary markers\", \"invalid marker\", path);\n const visit = (children: Node[], namespace: string): void => {\n const stack: Array<{ id: string; namespace: string }> = [];\n for (const node of children) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n visit([...node.childNodes], namespace);\n continue;\n }\n if (node.nodeType !== Node.COMMENT_NODE) continue;\n const value = node.textContent ?? \"\";\n const open = openMarker(node);\n if (open) {\n const id = open[1]!;\n if (!id.startsWith(namespace) || id.slice(namespace.length).includes(\".\") || seen.has(id))\n invalid();\n seen.add(id);\n stack.push({ id, namespace });\n if (open[2] === \"e\") namespace = `${id}.`;\n } else if (value.startsWith(\"/zr:1:\")) {\n const frame = stack.pop();\n if (!frame || value !== `/zr:1:${frame.id}`) invalid();\n namespace = frame!.namespace;\n } else if (value.includes(\"zr:1:\")) invalid();\n }\n if (stack.length) invalid();\n };\n visit(nodes, prefix);\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Description } from "./description.js";
|
|
2
|
+
import type { ErrorBoundaryProps } from "./error-boundary.js";
|
|
3
|
+
import type { renderErrorBoundary } from "./error-boundary-client.js";
|
|
4
|
+
export declare const boundaryType: unique symbol;
|
|
5
|
+
export declare function boundaryRenderer(type: unknown): typeof renderErrorBoundary | undefined;
|
|
6
|
+
export declare function boundaryProps(description: Description): ErrorBoundaryProps;
|
|
7
|
+
export declare function integrity<T extends object>(error: T): T;
|
|
8
|
+
export declare function recoverable(error: unknown): boolean;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const boundaryType = Symbol.for("@takazudo/zfb/zudo-react/ErrorBoundary");
|
|
2
|
+
export function boundaryRenderer(type) {
|
|
3
|
+
return typeof type === "function"
|
|
4
|
+
? type[boundaryType]
|
|
5
|
+
: undefined;
|
|
6
|
+
}
|
|
7
|
+
export function boundaryProps(description) {
|
|
8
|
+
const props = description.props;
|
|
9
|
+
if (typeof props.children !== "function" || typeof props.fallback !== "function")
|
|
10
|
+
throw new TypeError("ZR_CHILD: ErrorBoundary requires children and fallback factories");
|
|
11
|
+
if (props.resetKey !== undefined && props.resetKey?.$$zudoReactive !== "zudo-react.reactive.v1")
|
|
12
|
+
throw new TypeError("ZR_CHILD: ErrorBoundary.resetKey requires a readable signal");
|
|
13
|
+
return props;
|
|
14
|
+
}
|
|
15
|
+
// Only engine-created integrity failures bypass recovery. User error messages are
|
|
16
|
+
// never interpreted as protocol or ownership failures.
|
|
17
|
+
const integrityErrors = new WeakSet();
|
|
18
|
+
export function integrity(error) {
|
|
19
|
+
integrityErrors.add(error);
|
|
20
|
+
return error;
|
|
21
|
+
}
|
|
22
|
+
export function recoverable(error) {
|
|
23
|
+
return !(typeof error === "object" && error !== null && integrityErrors.has(error));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=error-boundary-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-boundary-type.js","sourceRoot":"","sources":["../../src/zudo-react/error-boundary-type.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AACjF,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,OAAO,OAAO,IAAI,KAAK,UAAU;QAC/B,CAAC,CAAE,IAAwD,CAAC,YAAY,CAAC;QACzE,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,WAAwB;IACpD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAsC,CAAC;IACjE,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,UAAU;QAC9E,MAAM,IAAI,SAAS,CAAC,kEAAkE,CAAC,CAAC;IAC1F,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,EAAE,cAAc,KAAK,wBAAwB;QAC7F,MAAM,IAAI,SAAS,CAAC,6DAA6D,CAAC,CAAC;IACrF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kFAAkF;AAClF,uDAAuD;AACvD,MAAM,eAAe,GAAG,IAAI,OAAO,EAAU,CAAC;AAC9C,MAAM,UAAU,SAAS,CAAmB,KAAQ;IAClD,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,KAAK,CAAC;AACf,CAAC;AACD,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AACtF,CAAC","sourcesContent":["import type { Description } from \"./description.js\";\nimport type { ErrorBoundaryProps } from \"./error-boundary.js\";\nimport type { renderErrorBoundary } from \"./error-boundary-client.js\";\n\nexport const boundaryType = Symbol.for(\"@takazudo/zfb/zudo-react/ErrorBoundary\");\nexport function boundaryRenderer(type: unknown): typeof renderErrorBoundary | undefined {\n return typeof type === \"function\"\n ? (type as { [boundaryType]?: typeof renderErrorBoundary })[boundaryType]\n : undefined;\n}\nexport function boundaryProps(description: Description): ErrorBoundaryProps {\n const props = description.props as unknown as ErrorBoundaryProps;\n if (typeof props.children !== \"function\" || typeof props.fallback !== \"function\")\n throw new TypeError(\"ZR_CHILD: ErrorBoundary requires children and fallback factories\");\n if (props.resetKey !== undefined && props.resetKey?.$$zudoReactive !== \"zudo-react.reactive.v1\")\n throw new TypeError(\"ZR_CHILD: ErrorBoundary.resetKey requires a readable signal\");\n return props;\n}\n\n// Only engine-created integrity failures bypass recovery. User error messages are\n// never interpreted as protocol or ownership failures.\nconst integrityErrors = new WeakSet<object>();\nexport function integrity<T extends object>(error: T): T {\n integrityErrors.add(error);\n return error;\n}\nexport function recoverable(error: unknown): boolean {\n return !(typeof error === \"object\" && error !== null && integrityErrors.has(error));\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Child, type Description } from "./description.js";
|
|
2
|
+
import type { ReadonlySignal } from "./reactive-types.js";
|
|
3
|
+
export interface ErrorBoundaryProps {
|
|
4
|
+
children: () => Child;
|
|
5
|
+
fallback: (error: unknown, reset: () => void) => Child;
|
|
6
|
+
resetKey?: ReadonlySignal<unknown> | undefined;
|
|
7
|
+
}
|
|
8
|
+
export declare const ErrorBoundary: (props: ErrorBoundaryProps) => Description;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createDescription } from "./description.js";
|
|
2
|
+
import { boundaryType } from "./error-boundary-type.js";
|
|
3
|
+
import { renderErrorBoundary } from "./error-boundary-client.js";
|
|
4
|
+
// The renderer hook belongs to the opt-in value. A barrel re-export alone must
|
|
5
|
+
// not retain boundary attempts, resets, or local hydration replacement code.
|
|
6
|
+
export const ErrorBoundary = /* @__PURE__ */ (() => {
|
|
7
|
+
function ErrorBoundary(props) {
|
|
8
|
+
return createDescription(ErrorBoundary, props);
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(ErrorBoundary, boundaryType, { value: renderErrorBoundary });
|
|
11
|
+
return ErrorBoundary;
|
|
12
|
+
})();
|
|
13
|
+
//# sourceMappingURL=error-boundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-boundary.js","sourceRoot":"","sources":["../../src/zudo-react/error-boundary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAgC,MAAM,kBAAkB,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AASjE,+EAA+E;AAC/E,6EAA6E;AAC7E,MAAM,CAAC,MAAM,aAAa,GAA+C,eAAe,CAAC,CAAC,GAAG,EAAE;IAC7F,SAAS,aAAa,CAAC,KAAyB;QAC9C,OAAO,iBAAiB,CAAC,aAAa,EAAE,KAA2C,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACnF,OAAO,aAAa,CAAC;AACvB,CAAC,CAAC,EAAE,CAAC","sourcesContent":["import { createDescription, type Child, type Description } from \"./description.js\";\nimport { boundaryType } from \"./error-boundary-type.js\";\nimport { renderErrorBoundary } from \"./error-boundary-client.js\";\nimport type { ReadonlySignal } from \"./reactive-types.js\";\n\nexport interface ErrorBoundaryProps {\n children: () => Child;\n fallback: (error: unknown, reset: () => void) => Child;\n resetKey?: ReadonlySignal<unknown> | undefined;\n}\n\n// The renderer hook belongs to the opt-in value. A barrel re-export alone must\n// not retain boundary attempts, resets, or local hydration replacement code.\nexport const ErrorBoundary: (props: ErrorBoundaryProps) => Description = /* @__PURE__ */ (() => {\n function ErrorBoundary(props: ErrorBoundaryProps): Description {\n return createDescription(ErrorBoundary, props as unknown as Record<string, unknown>);\n }\n Object.defineProperty(ErrorBoundary, boundaryType, { value: renderErrorBoundary });\n return ErrorBoundary;\n})();\n"]}
|