@takazudo/zfb 3.1.0 → 3.2.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/dist/config.d.ts +28 -3
- package/dist/config.js +23 -12
- package/dist/config.js.map +1 -1
- package/dist/content.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js.map +1 -1
- package/dist/island-boundary.d.ts +2 -2
- package/dist/island-boundary.js +4 -2
- package/dist/island-boundary.js.map +1 -1
- package/dist/island.d.ts +8 -4
- package/dist/island.js +1 -1
- package/dist/island.js.map +1 -1
- package/dist/jsx-types.d.ts +1 -1
- package/dist/jsx-types.js.map +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/slugify.js.map +1 -1
- package/dist/zudo-react/description.d.ts +18 -0
- package/dist/zudo-react/description.js +41 -0
- package/dist/zudo-react/description.js.map +1 -1
- package/dist/zudo-react/dom-bindings.d.ts +2 -1
- package/dist/zudo-react/dom-bindings.js +16 -22
- package/dist/zudo-react/dom-bindings.js.map +1 -1
- package/dist/zudo-react/forms.js.map +1 -1
- package/dist/zudo-react/hydrate.js +20 -30
- package/dist/zudo-react/hydrate.js.map +1 -1
- package/dist/zudo-react/index.d.ts +2 -1
- package/dist/zudo-react/index.js.map +1 -1
- package/dist/zudo-react/jsx-dev-runtime.d.ts +2 -6
- package/dist/zudo-react/jsx-dev-runtime.js +3 -3
- package/dist/zudo-react/jsx-dev-runtime.js.map +1 -1
- package/dist/zudo-react/jsx-runtime.js +2 -2
- package/dist/zudo-react/jsx-runtime.js.map +1 -1
- package/dist/zudo-react/jsx-types.d.ts +59 -23
- package/dist/zudo-react/jsx-types.js.map +1 -1
- package/dist/zudo-react/props-transport.d.ts +2 -0
- package/dist/zudo-react/props-transport.js +42 -14
- package/dist/zudo-react/props-transport.js.map +1 -1
- package/dist/zudo-react/raw-html.d.ts +1 -0
- package/dist/zudo-react/raw-html.js +120 -0
- package/dist/zudo-react/raw-html.js.map +1 -0
- package/dist/zudo-react/reactive.js.map +1 -1
- package/dist/zudo-react/render-html.d.ts +11 -1
- package/dist/zudo-react/render-html.js +83 -56
- package/dist/zudo-react/render-html.js.map +1 -1
- package/dist/zudo-react/root.js +24 -1
- package/dist/zudo-react/root.js.map +1 -1
- package/dist/zudo-react/server.d.ts +2 -0
- package/dist/zudo-react/server.js.map +1 -1
- package/dist/zudo-react/style.d.ts +10 -0
- package/dist/zudo-react/style.js +525 -0
- package/dist/zudo-react/style.js.map +1 -0
- package/dist/zudo-react/testing.d.ts +27 -0
- package/dist/zudo-react/testing.js +117 -0
- package/dist/zudo-react/testing.js.map +1 -0
- package/dist/zudo-react/vocabulary.d.ts +7 -0
- package/dist/zudo-react/vocabulary.js +64 -5
- package/dist/zudo-react/vocabulary.js.map +1 -1
- package/package.json +16 -10
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CSSProperties } from "./style.js";
|
|
2
|
+
export type { CSSProperties, CssProperty } from "./style.js";
|
|
3
|
+
import type { Child, Component, Description, Key } from "./description.js";
|
|
2
4
|
import type { Listener, Ref } from "./index.js";
|
|
3
5
|
import type { ReadonlySignal, Signal } from "./reactive-types.js";
|
|
4
6
|
type Value<T> = T | ReadonlySignal<T> | undefined;
|
|
@@ -6,8 +8,6 @@ type ScalarAttribute = Value<string | number | boolean | null>;
|
|
|
6
8
|
type DimensionAttribute = Value<string | number | null>;
|
|
7
9
|
type StringAttribute = Value<string | null>;
|
|
8
10
|
type BooleanAttribute = Value<boolean | null>;
|
|
9
|
-
type CssProperty = `--${string}` | `${string}-${string}` | "color" | "display" | "opacity" | "width" | "height" | "margin" | "padding" | "border" | "background" | "position" | "top" | "right" | "bottom" | "left" | "overflow" | "transform" | "transition" | "animation" | "font" | "flex" | "grid" | "gap";
|
|
10
|
-
type CssStyle = Readonly<Partial<Record<CssProperty, string | number | null | undefined>>>;
|
|
11
11
|
type AnyListener = Listener<any>;
|
|
12
12
|
type EventProps<TEl extends Element, TMap extends Record<keyof TMap, Event>> = {
|
|
13
13
|
[K in keyof TMap & string as `on:${K}` | `on:${K}:capture`]?: Listener<TMap[K] & {
|
|
@@ -35,12 +35,12 @@ interface CommonAttributes<T extends Element = Element> extends ReservedProps<T>
|
|
|
35
35
|
dir?: StringAttribute;
|
|
36
36
|
slot?: StringAttribute;
|
|
37
37
|
role?: StringAttribute;
|
|
38
|
-
style?: Value<string |
|
|
38
|
+
style?: Value<string | CSSProperties | null>;
|
|
39
39
|
hidden?: BooleanAttribute;
|
|
40
40
|
inert?: BooleanAttribute;
|
|
41
|
-
contenteditable?:
|
|
42
|
-
draggable?:
|
|
43
|
-
spellcheck?:
|
|
41
|
+
contenteditable?: Value<string | boolean | null>;
|
|
42
|
+
draggable?: Value<string | boolean | null>;
|
|
43
|
+
spellcheck?: Value<string | boolean | null>;
|
|
44
44
|
tabindex?: Value<number | null>;
|
|
45
45
|
accesskey?: StringAttribute;
|
|
46
46
|
translate?: StringAttribute;
|
|
@@ -48,11 +48,32 @@ interface CommonAttributes<T extends Element = Element> extends ReservedProps<T>
|
|
|
48
48
|
onload?: string | undefined;
|
|
49
49
|
onerror?: string | undefined;
|
|
50
50
|
}
|
|
51
|
-
interface
|
|
51
|
+
interface HtmlBaseAttributes<T extends HTMLElement = HTMLElement> extends CommonAttributes<T> {
|
|
52
52
|
href?: StringAttribute;
|
|
53
53
|
target?: StringAttribute;
|
|
54
54
|
rel?: StringAttribute;
|
|
55
|
-
download?:
|
|
55
|
+
download?: Value<string | boolean | null>;
|
|
56
|
+
property?: StringAttribute;
|
|
57
|
+
itemprop?: StringAttribute;
|
|
58
|
+
hreflang?: StringAttribute;
|
|
59
|
+
as?: StringAttribute;
|
|
60
|
+
integrity?: StringAttribute;
|
|
61
|
+
async?: BooleanAttribute;
|
|
62
|
+
defer?: BooleanAttribute;
|
|
63
|
+
nonce?: StringAttribute;
|
|
64
|
+
popover?: StringAttribute;
|
|
65
|
+
popovertarget?: StringAttribute;
|
|
66
|
+
popovertargetaction?: StringAttribute;
|
|
67
|
+
srcdoc?: StringAttribute;
|
|
68
|
+
fetchpriority?: StringAttribute;
|
|
69
|
+
inputmode?: StringAttribute;
|
|
70
|
+
autocapitalize?: StringAttribute;
|
|
71
|
+
form?: StringAttribute;
|
|
72
|
+
label?: StringAttribute;
|
|
73
|
+
preload?: StringAttribute;
|
|
74
|
+
playsinline?: BooleanAttribute;
|
|
75
|
+
wrap?: StringAttribute;
|
|
76
|
+
closedby?: StringAttribute;
|
|
56
77
|
src?: StringAttribute;
|
|
57
78
|
alt?: StringAttribute;
|
|
58
79
|
width?: Value<string | number | null>;
|
|
@@ -112,16 +133,20 @@ interface HtmlAttributes<T extends Element = HTMLElement> extends CommonAttribut
|
|
|
112
133
|
allow?: StringAttribute;
|
|
113
134
|
allowfullscreen?: BooleanAttribute;
|
|
114
135
|
}
|
|
115
|
-
type
|
|
116
|
-
type RawTextProps<
|
|
136
|
+
export type HTMLAttributes<T extends HTMLElement = HTMLElement> = HtmlBaseAttributes<T> & DataAria & EventProps<T, HTMLElementEventMap>;
|
|
137
|
+
type RawTextProps<T extends HTMLElement = HTMLElement> = Omit<HtmlBaseAttributes<T>, "children" | "rawHtml"> & DataAria & EventProps<T, HTMLElementEventMap> & {
|
|
117
138
|
children?: never;
|
|
118
139
|
rawHtml?: string | undefined;
|
|
119
140
|
};
|
|
120
|
-
type
|
|
141
|
+
type IframeProps = Omit<HtmlBaseAttributes<HTMLIFrameElement>, "children" | "rawHtml"> & DataAria & EventProps<HTMLIFrameElement, HTMLElementEventMap> & {
|
|
142
|
+
children?: never;
|
|
143
|
+
rawHtml?: never;
|
|
144
|
+
};
|
|
145
|
+
type InputBase = Omit<HtmlBaseAttributes<HTMLInputElement>, "type"> & DataAria & EventProps<HTMLInputElement, HTMLElementEventMap> & {
|
|
121
146
|
defaultValue?: string | undefined;
|
|
122
147
|
defaultChecked?: boolean | undefined;
|
|
123
148
|
};
|
|
124
|
-
type InputProps = InputBase & ({
|
|
149
|
+
export type InputProps = InputBase & ({
|
|
125
150
|
type?: "text" | "search" | "email" | "url" | "tel" | "password" | undefined;
|
|
126
151
|
modelValue?: Signal<string> | undefined;
|
|
127
152
|
modelChecked?: never;
|
|
@@ -140,15 +165,15 @@ type InputProps = InputBase & ({
|
|
|
140
165
|
modelValue?: never;
|
|
141
166
|
modelChecked?: never;
|
|
142
167
|
});
|
|
143
|
-
type TextareaProps =
|
|
168
|
+
export type TextareaProps = HTMLAttributes<HTMLTextAreaElement> & {
|
|
144
169
|
modelValue?: Signal<string> | undefined;
|
|
145
170
|
defaultValue?: string | undefined;
|
|
146
171
|
};
|
|
147
|
-
type SelectProps =
|
|
172
|
+
export type SelectProps = HTMLAttributes<HTMLSelectElement> & {
|
|
148
173
|
modelValue?: Signal<string> | undefined;
|
|
149
174
|
defaultValue?: string | undefined;
|
|
150
175
|
};
|
|
151
|
-
interface
|
|
176
|
+
interface SvgBaseAttributes<T extends SVGElement = SVGElement> extends CommonAttributes<T> {
|
|
152
177
|
width?: DimensionAttribute;
|
|
153
178
|
height?: DimensionAttribute;
|
|
154
179
|
viewBox?: StringAttribute;
|
|
@@ -161,6 +186,10 @@ interface SvgAttributes extends CommonAttributes<SVGElement> {
|
|
|
161
186
|
refY?: ScalarAttribute;
|
|
162
187
|
"xlink:href"?: StringAttribute;
|
|
163
188
|
"xml:lang"?: StringAttribute;
|
|
189
|
+
xmlns?: StringAttribute;
|
|
190
|
+
"xmlns:xlink"?: StringAttribute;
|
|
191
|
+
href?: StringAttribute;
|
|
192
|
+
focusable?: StringAttribute;
|
|
164
193
|
"stroke-width"?: ScalarAttribute;
|
|
165
194
|
"fill-rule"?: StringAttribute;
|
|
166
195
|
"clip-rule"?: StringAttribute;
|
|
@@ -168,6 +197,9 @@ interface SvgAttributes extends CommonAttributes<SVGElement> {
|
|
|
168
197
|
"stroke-linejoin"?: StringAttribute;
|
|
169
198
|
"stop-color"?: StringAttribute;
|
|
170
199
|
"stop-opacity"?: ScalarAttribute;
|
|
200
|
+
"fill-opacity"?: ScalarAttribute;
|
|
201
|
+
"stroke-dasharray"?: StringAttribute;
|
|
202
|
+
"text-anchor"?: StringAttribute;
|
|
171
203
|
fill?: StringAttribute;
|
|
172
204
|
stroke?: StringAttribute;
|
|
173
205
|
d?: StringAttribute;
|
|
@@ -188,21 +220,26 @@ interface SvgAttributes extends CommonAttributes<SVGElement> {
|
|
|
188
220
|
offset?: ScalarAttribute;
|
|
189
221
|
id?: StringAttribute;
|
|
190
222
|
}
|
|
191
|
-
type
|
|
223
|
+
export type SVGAttributes<T extends SVGElement = SVGElement> = SvgBaseAttributes<T> & DataAria & EventProps<T, SVGElementEventMap>;
|
|
192
224
|
type CustomProps = ReservedProps & EventProps<HTMLElement, GlobalEventHandlersEventMap> & {
|
|
193
225
|
value?: string | null | undefined;
|
|
194
226
|
checked?: null | undefined;
|
|
195
227
|
[attribute: string]: StringAttribute | Child | Ref<Element> | AnyListener | undefined;
|
|
196
228
|
};
|
|
197
|
-
type HtmlTag = "html" | "head" | "body" | "title" | "base" | "link" | "meta" | "style" | "script" | "div" | "span" | "p" | "a" | "br" | "hr" | "main" | "header" | "footer" | "nav" | "section" | "article" | "aside" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "ul" | "ol" | "li" | "dl" | "dt" | "dd" | "blockquote" | "pre" | "code" | "strong" | "em" | "b" | "i" | "small" | "mark" | "time" | "figure" | "figcaption" | "img" | "picture" | "source" | "video" | "audio" | "track" | "canvas" | "form" | "label" | "input" | "button" | "textarea" | "select" | "option" | "optgroup" | "fieldset" | "legend" | "output" | "progress" | "meter" | "datalist" | "table" | "caption" | "thead" | "tbody" | "tfoot" | "tr" | "th" | "td" | "col" | "colgroup" | "details" | "summary" | "dialog" | "template" | "slot" | "iframe" | "noscript" | "address" | "abbr" | "bdi" | "bdo" | "cite" | "data" | "del" | "dfn" | "ins" | "kbd" | "map" | "area" | "object" | "param" | "q" | "rp" | "rt" | "ruby" | "s" | "samp" | "sub" | "sup" | "u" | "var" | "wbr" | "embed";
|
|
198
|
-
type SvgTag = "svg" | "g" | "path" | "circle" | "ellipse" | "rect" | "line" | "polyline" | "polygon" | "text" | "tspan" | "defs" | "symbol" | "use" | "clipPath" | "mask" | "linearGradient" | "radialGradient" | "stop" | "desc" | "foreignObject";
|
|
229
|
+
type HtmlTag = "html" | "head" | "body" | "title" | "base" | "link" | "meta" | "style" | "script" | "div" | "span" | "p" | "a" | "br" | "hr" | "main" | "header" | "footer" | "nav" | "section" | "article" | "aside" | "search" | "hgroup" | "menu" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "ul" | "ol" | "li" | "dl" | "dt" | "dd" | "blockquote" | "pre" | "code" | "strong" | "em" | "b" | "i" | "small" | "mark" | "time" | "figure" | "figcaption" | "img" | "picture" | "source" | "video" | "audio" | "track" | "canvas" | "form" | "label" | "input" | "button" | "textarea" | "select" | "option" | "optgroup" | "fieldset" | "legend" | "output" | "progress" | "meter" | "datalist" | "table" | "caption" | "thead" | "tbody" | "tfoot" | "tr" | "th" | "td" | "col" | "colgroup" | "details" | "summary" | "dialog" | "template" | "slot" | "iframe" | "noscript" | "address" | "abbr" | "bdi" | "bdo" | "cite" | "data" | "del" | "dfn" | "ins" | "kbd" | "map" | "area" | "object" | "param" | "q" | "rp" | "rt" | "ruby" | "s" | "samp" | "sub" | "sup" | "u" | "var" | "wbr" | "embed";
|
|
230
|
+
type SvgTag = "svg" | "g" | "path" | "circle" | "ellipse" | "rect" | "line" | "polyline" | "polygon" | "text" | "tspan" | "defs" | "symbol" | "use" | "clipPath" | "mask" | "linearGradient" | "radialGradient" | "stop" | "desc" | "foreignObject" | "pattern" | "filter" | "marker" | "image";
|
|
231
|
+
/** DOM element corresponding to an owned intrinsic tag. */
|
|
232
|
+
export type ElementForTag<Tag extends HtmlTag | SvgTag> = Tag extends HtmlTag ? Tag extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[Tag] : HTMLElement : Tag extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[Tag] : SVGElement;
|
|
199
233
|
export declare namespace JSX {
|
|
200
|
-
type Element =
|
|
234
|
+
type Element = Description;
|
|
235
|
+
type HTMLAttributes<T extends HTMLElement = HTMLElement> = import("./jsx-types.js").HTMLAttributes<T>;
|
|
236
|
+
type SVGAttributes<T extends SVGElement = SVGElement> = import("./jsx-types.js").SVGAttributes<T>;
|
|
237
|
+
type CSSProperties = import("./jsx-types.js").CSSProperties;
|
|
201
238
|
type ElementType = string | Component<any> | typeof import("../island.js").Island | typeof import("./description.js").Fragment;
|
|
202
239
|
type IntrinsicElements = {
|
|
203
|
-
[K in HtmlTag]: K extends "input" ? InputProps : K extends "textarea" ? TextareaProps : K extends "select" ? SelectProps : K extends "script" | "style" ? RawTextProps<K
|
|
240
|
+
[K in HtmlTag]: K extends "input" ? InputProps : K extends "textarea" ? TextareaProps : K extends "select" ? SelectProps : K extends "iframe" ? IframeProps : K extends "script" | "style" ? RawTextProps<ElementForTag<K>> : HTMLAttributes<ElementForTag<K>>;
|
|
204
241
|
} & {
|
|
205
|
-
[K in SvgTag]:
|
|
242
|
+
[K in SvgTag]: SVGAttributes<ElementForTag<K>>;
|
|
206
243
|
} & {
|
|
207
244
|
[K in `${string}-${string}`]: CustomProps;
|
|
208
245
|
};
|
|
@@ -213,4 +250,3 @@ export declare namespace JSX {
|
|
|
213
250
|
children: unknown;
|
|
214
251
|
}
|
|
215
252
|
}
|
|
216
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-types.js","sourceRoot":"","sources":["../../src/zudo-react/jsx-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Child, Component, Key } from \"./description.js\";\nimport type { Listener, Ref } from \"./index.js\";\nimport type { ReadonlySignal, Signal } from \"./reactive-types.js\";\n\ntype Value<T> = T | ReadonlySignal<T> | undefined;\ntype ScalarAttribute = Value<string | number | boolean | null>;\ntype DimensionAttribute = Value<string | number | null>;\ntype StringAttribute = Value<string | null>;\ntype BooleanAttribute = Value<boolean | null>;\ntype CssProperty =\n | `--${string}`\n | `${string}-${string}`\n | \"color\"\n | \"display\"\n | \"opacity\"\n | \"width\"\n | \"height\"\n | \"margin\"\n | \"padding\"\n | \"border\"\n | \"background\"\n | \"position\"\n | \"top\"\n | \"right\"\n | \"bottom\"\n | \"left\"\n | \"overflow\"\n | \"transform\"\n | \"transition\"\n | \"animation\"\n | \"font\"\n | \"flex\"\n | \"grid\"\n | \"gap\";\ntype CssStyle = Readonly<Partial<Record<CssProperty, string | number | null | undefined>>>;\n// The custom-name index must also accept every mapped listener under strict function variance.\ntype AnyListener = Listener<any>;\ntype EventProps<TEl extends Element, TMap extends Record<keyof TMap, Event>> = {\n [K in keyof TMap & string as `on:${K}` | `on:${K}:capture`]?: Listener<\n TMap[K] & { currentTarget: TEl }\n >;\n} & {\n [name: `on:${string}`]: AnyListener | undefined;\n};\ntype DataAria = {\n [name: `data-${string}`]: ScalarAttribute;\n} & {\n [name: `aria-${string}`]: ScalarAttribute;\n};\n\ninterface ReservedProps<T extends Element = Element> {\n children?: Child | undefined;\n key?: Key | undefined;\n ref?: Ref<T> | undefined;\n rawHtml?: Value<string | null>;\n}\n\ninterface CommonAttributes<T extends Element = Element> extends ReservedProps<T> {\n id?: StringAttribute;\n class?: StringAttribute;\n title?: StringAttribute;\n lang?: StringAttribute;\n dir?: StringAttribute;\n slot?: StringAttribute;\n role?: StringAttribute;\n style?: Value<string | CssStyle | null>;\n hidden?: BooleanAttribute;\n inert?: BooleanAttribute;\n contenteditable?: StringAttribute;\n draggable?: StringAttribute;\n spellcheck?: StringAttribute;\n tabindex?: Value<number | null>;\n accesskey?: StringAttribute;\n translate?: StringAttribute;\n onclick?: string | undefined;\n onload?: string | undefined;\n onerror?: string | undefined;\n}\n\ninterface HtmlAttributes<T extends Element = HTMLElement> extends CommonAttributes<T> {\n href?: StringAttribute;\n target?: StringAttribute;\n rel?: StringAttribute;\n download?: StringAttribute;\n src?: StringAttribute;\n alt?: StringAttribute;\n width?: Value<string | number | null>;\n height?: Value<string | number | null>;\n type?: StringAttribute;\n name?: StringAttribute;\n value?: string | number | null | undefined;\n placeholder?: StringAttribute;\n for?: StringAttribute;\n charset?: StringAttribute;\n datetime?: StringAttribute;\n readonly?: BooleanAttribute;\n autofocus?: BooleanAttribute;\n required?: BooleanAttribute;\n disabled?: BooleanAttribute;\n checked?: boolean | null | undefined;\n selected?: BooleanAttribute;\n multiple?: BooleanAttribute;\n reversed?: BooleanAttribute;\n open?: BooleanAttribute;\n controls?: BooleanAttribute;\n muted?: BooleanAttribute;\n loop?: BooleanAttribute;\n autoplay?: BooleanAttribute;\n novalidate?: BooleanAttribute;\n formnovalidate?: BooleanAttribute;\n maxlength?: Value<number | null>;\n minlength?: Value<number | null>;\n min?: StringAttribute;\n max?: StringAttribute;\n step?: StringAttribute;\n start?: Value<string | number | null>;\n pattern?: StringAttribute;\n autocomplete?: StringAttribute;\n accept?: StringAttribute;\n \"accept-charset\"?: StringAttribute;\n \"http-equiv\"?: StringAttribute;\n content?: StringAttribute;\n media?: StringAttribute;\n method?: StringAttribute;\n action?: StringAttribute;\n enctype?: StringAttribute;\n rows?: Value<number | null>;\n cols?: Value<number | null>;\n colspan?: Value<number | null>;\n rowspan?: Value<number | null>;\n scope?: StringAttribute;\n cite?: StringAttribute;\n poster?: StringAttribute;\n loading?: StringAttribute;\n decoding?: StringAttribute;\n sizes?: StringAttribute;\n srcset?: StringAttribute;\n crossorigin?: StringAttribute;\n referrerpolicy?: StringAttribute;\n sandbox?: StringAttribute;\n allow?: StringAttribute;\n allowfullscreen?: BooleanAttribute;\n}\n\ntype HtmlProps<\n TRef extends Element = HTMLElement,\n TEvent extends HTMLElement = HTMLElement,\n> = HtmlAttributes<TRef> & DataAria & EventProps<TEvent, HTMLElementEventMap>;\ntype RawTextProps<TEvent extends HTMLElement = HTMLElement> = Omit<\n HtmlAttributes<HTMLElement>,\n \"children\" | \"rawHtml\"\n> &\n DataAria &\n EventProps<TEvent, HTMLElementEventMap> & {\n children?: never;\n rawHtml?: string | undefined;\n };\ntype InputBase = Omit<HtmlAttributes<HTMLInputElement>, \"type\"> &\n DataAria &\n EventProps<HTMLInputElement, HTMLElementEventMap> & {\n defaultValue?: string | undefined;\n defaultChecked?: boolean | undefined;\n };\ntype InputProps = InputBase &\n (\n | {\n type?: \"text\" | \"search\" | \"email\" | \"url\" | \"tel\" | \"password\" | undefined;\n modelValue?: Signal<string> | undefined;\n modelChecked?: never;\n }\n | {\n type: \"checkbox\";\n modelChecked?: Signal<boolean> | undefined;\n modelValue?: never;\n }\n | {\n type: \"radio\";\n name: string;\n value: string;\n modelValue?: Signal<string | null> | undefined;\n modelChecked?: never;\n }\n | {\n type: string;\n modelValue?: never;\n modelChecked?: never;\n }\n );\ntype TextareaProps = HtmlProps<HTMLTextAreaElement, HTMLTextAreaElement> & {\n modelValue?: Signal<string> | undefined;\n defaultValue?: string | undefined;\n};\ntype SelectProps = HtmlProps<HTMLSelectElement, HTMLSelectElement> & {\n modelValue?: Signal<string> | undefined;\n defaultValue?: string | undefined;\n};\n\ninterface SvgAttributes extends CommonAttributes<SVGElement> {\n width?: DimensionAttribute;\n height?: DimensionAttribute;\n viewBox?: StringAttribute;\n preserveAspectRatio?: StringAttribute;\n gradientUnits?: StringAttribute;\n gradientTransform?: StringAttribute;\n markerWidth?: ScalarAttribute;\n markerHeight?: ScalarAttribute;\n refX?: ScalarAttribute;\n refY?: ScalarAttribute;\n \"xlink:href\"?: StringAttribute;\n \"xml:lang\"?: StringAttribute;\n \"stroke-width\"?: ScalarAttribute;\n \"fill-rule\"?: StringAttribute;\n \"clip-rule\"?: StringAttribute;\n \"stroke-linecap\"?: StringAttribute;\n \"stroke-linejoin\"?: StringAttribute;\n \"stop-color\"?: StringAttribute;\n \"stop-opacity\"?: ScalarAttribute;\n fill?: StringAttribute;\n stroke?: StringAttribute;\n d?: StringAttribute;\n x?: ScalarAttribute;\n y?: ScalarAttribute;\n x1?: ScalarAttribute;\n x2?: ScalarAttribute;\n y1?: ScalarAttribute;\n y2?: ScalarAttribute;\n cx?: ScalarAttribute;\n cy?: ScalarAttribute;\n r?: ScalarAttribute;\n rx?: ScalarAttribute;\n ry?: ScalarAttribute;\n points?: StringAttribute;\n transform?: StringAttribute;\n opacity?: ScalarAttribute;\n offset?: ScalarAttribute;\n id?: StringAttribute;\n}\n\ntype SvgProps<TEvent extends SVGElement = SVGElement> = SvgAttributes &\n DataAria &\n EventProps<TEvent, SVGElementEventMap>;\ntype CustomProps = ReservedProps &\n EventProps<HTMLElement, GlobalEventHandlersEventMap> & {\n value?: string | null | undefined;\n checked?: null | undefined;\n [attribute: string]: StringAttribute | Child | Ref<Element> | AnyListener | undefined;\n };\n\ntype HtmlTag =\n | \"html\"\n | \"head\"\n | \"body\"\n | \"title\"\n | \"base\"\n | \"link\"\n | \"meta\"\n | \"style\"\n | \"script\"\n | \"div\"\n | \"span\"\n | \"p\"\n | \"a\"\n | \"br\"\n | \"hr\"\n | \"main\"\n | \"header\"\n | \"footer\"\n | \"nav\"\n | \"section\"\n | \"article\"\n | \"aside\"\n | \"h1\"\n | \"h2\"\n | \"h3\"\n | \"h4\"\n | \"h5\"\n | \"h6\"\n | \"ul\"\n | \"ol\"\n | \"li\"\n | \"dl\"\n | \"dt\"\n | \"dd\"\n | \"blockquote\"\n | \"pre\"\n | \"code\"\n | \"strong\"\n | \"em\"\n | \"b\"\n | \"i\"\n | \"small\"\n | \"mark\"\n | \"time\"\n | \"figure\"\n | \"figcaption\"\n | \"img\"\n | \"picture\"\n | \"source\"\n | \"video\"\n | \"audio\"\n | \"track\"\n | \"canvas\"\n | \"form\"\n | \"label\"\n | \"input\"\n | \"button\"\n | \"textarea\"\n | \"select\"\n | \"option\"\n | \"optgroup\"\n | \"fieldset\"\n | \"legend\"\n | \"output\"\n | \"progress\"\n | \"meter\"\n | \"datalist\"\n | \"table\"\n | \"caption\"\n | \"thead\"\n | \"tbody\"\n | \"tfoot\"\n | \"tr\"\n | \"th\"\n | \"td\"\n | \"col\"\n | \"colgroup\"\n | \"details\"\n | \"summary\"\n | \"dialog\"\n | \"template\"\n | \"slot\"\n | \"iframe\"\n | \"noscript\"\n | \"address\"\n | \"abbr\"\n | \"bdi\"\n | \"bdo\"\n | \"cite\"\n | \"data\"\n | \"del\"\n | \"dfn\"\n | \"ins\"\n | \"kbd\"\n | \"map\"\n | \"area\"\n | \"object\"\n | \"param\"\n | \"q\"\n | \"rp\"\n | \"rt\"\n | \"ruby\"\n | \"s\"\n | \"samp\"\n | \"sub\"\n | \"sup\"\n | \"u\"\n | \"var\"\n | \"wbr\"\n | \"embed\";\n\ntype SvgTag =\n | \"svg\"\n | \"g\"\n | \"path\"\n | \"circle\"\n | \"ellipse\"\n | \"rect\"\n | \"line\"\n | \"polyline\"\n | \"polygon\"\n | \"text\"\n | \"tspan\"\n | \"defs\"\n | \"symbol\"\n | \"use\"\n | \"clipPath\"\n | \"mask\"\n | \"linearGradient\"\n | \"radialGradient\"\n | \"stop\"\n | \"desc\"\n | \"foreignObject\";\n\nexport namespace JSX {\n export type Element = Child;\n export type ElementType =\n | string\n | Component<any>\n | typeof import(\"../island.js\").Island\n | typeof import(\"./description.js\").Fragment;\n export type IntrinsicElements = {\n [K in HtmlTag]: K extends \"input\"\n ? InputProps\n : K extends \"textarea\"\n ? TextareaProps\n : K extends \"select\"\n ? SelectProps\n : K extends \"script\" | \"style\"\n ? RawTextProps<\n K extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[K] : HTMLElement\n >\n : HtmlProps<\n HTMLElement,\n K extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[K] : HTMLElement\n >;\n } & {\n [K in SvgTag]: SvgProps<\n K extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[K] : SVGElement\n >;\n } & {\n [K in `${string}-${string}`]: CustomProps;\n };\n export interface IntrinsicAttributes {\n key?: Key | undefined;\n }\n export interface ElementChildrenAttribute {\n children: unknown;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"jsx-types.js","sourceRoot":"","sources":["../../src/zudo-react/jsx-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CSSProperties } from \"./style.js\";\nexport type { CSSProperties, CssProperty } from \"./style.js\";\nimport type { Child, Component, Description, Key } from \"./description.js\";\nimport type { Listener, Ref } from \"./index.js\";\nimport type { ReadonlySignal, Signal } from \"./reactive-types.js\";\n\ntype Value<T> = T | ReadonlySignal<T> | undefined;\ntype ScalarAttribute = Value<string | number | boolean | null>;\ntype DimensionAttribute = Value<string | number | null>;\ntype StringAttribute = Value<string | null>;\ntype BooleanAttribute = Value<boolean | null>;\n// The custom-name index must also accept every mapped listener under strict function variance.\ntype AnyListener = Listener<any>;\ntype EventProps<TEl extends Element, TMap extends Record<keyof TMap, Event>> = {\n [K in keyof TMap & string as `on:${K}` | `on:${K}:capture`]?: Listener<\n TMap[K] & { currentTarget: TEl }\n >;\n} & {\n [name: `on:${string}`]: AnyListener | undefined;\n};\ntype DataAria = {\n [name: `data-${string}`]: ScalarAttribute;\n} & {\n [name: `aria-${string}`]: ScalarAttribute;\n};\n\ninterface ReservedProps<T extends Element = Element> {\n children?: Child | undefined;\n key?: Key | undefined;\n ref?: Ref<T> | undefined;\n rawHtml?: Value<string | null>;\n}\n\ninterface CommonAttributes<T extends Element = Element> extends ReservedProps<T> {\n id?: StringAttribute;\n class?: StringAttribute;\n title?: StringAttribute;\n lang?: StringAttribute;\n dir?: StringAttribute;\n slot?: StringAttribute;\n role?: StringAttribute;\n style?: Value<string | CSSProperties | null>;\n hidden?: BooleanAttribute;\n inert?: BooleanAttribute;\n contenteditable?: Value<string | boolean | null>;\n draggable?: Value<string | boolean | null>;\n spellcheck?: Value<string | boolean | null>;\n tabindex?: Value<number | null>;\n accesskey?: StringAttribute;\n translate?: StringAttribute;\n onclick?: string | undefined;\n onload?: string | undefined;\n onerror?: string | undefined;\n}\n\ninterface HtmlBaseAttributes<T extends HTMLElement = HTMLElement> extends CommonAttributes<T> {\n href?: StringAttribute;\n target?: StringAttribute;\n rel?: StringAttribute;\n download?: Value<string | boolean | null>;\n property?: StringAttribute;\n itemprop?: StringAttribute;\n hreflang?: StringAttribute;\n as?: StringAttribute;\n integrity?: StringAttribute;\n async?: BooleanAttribute;\n defer?: BooleanAttribute;\n nonce?: StringAttribute;\n popover?: StringAttribute;\n popovertarget?: StringAttribute;\n popovertargetaction?: StringAttribute;\n srcdoc?: StringAttribute;\n fetchpriority?: StringAttribute;\n inputmode?: StringAttribute;\n autocapitalize?: StringAttribute;\n form?: StringAttribute;\n label?: StringAttribute;\n preload?: StringAttribute;\n playsinline?: BooleanAttribute;\n wrap?: StringAttribute;\n closedby?: StringAttribute;\n src?: StringAttribute;\n alt?: StringAttribute;\n width?: Value<string | number | null>;\n height?: Value<string | number | null>;\n type?: StringAttribute;\n name?: StringAttribute;\n value?: string | number | null | undefined;\n placeholder?: StringAttribute;\n for?: StringAttribute;\n charset?: StringAttribute;\n datetime?: StringAttribute;\n readonly?: BooleanAttribute;\n autofocus?: BooleanAttribute;\n required?: BooleanAttribute;\n disabled?: BooleanAttribute;\n checked?: boolean | null | undefined;\n selected?: BooleanAttribute;\n multiple?: BooleanAttribute;\n reversed?: BooleanAttribute;\n open?: BooleanAttribute;\n controls?: BooleanAttribute;\n muted?: BooleanAttribute;\n loop?: BooleanAttribute;\n autoplay?: BooleanAttribute;\n novalidate?: BooleanAttribute;\n formnovalidate?: BooleanAttribute;\n maxlength?: Value<number | null>;\n minlength?: Value<number | null>;\n min?: StringAttribute;\n max?: StringAttribute;\n step?: StringAttribute;\n start?: Value<string | number | null>;\n pattern?: StringAttribute;\n autocomplete?: StringAttribute;\n accept?: StringAttribute;\n \"accept-charset\"?: StringAttribute;\n \"http-equiv\"?: StringAttribute;\n content?: StringAttribute;\n media?: StringAttribute;\n method?: StringAttribute;\n action?: StringAttribute;\n enctype?: StringAttribute;\n rows?: Value<number | null>;\n cols?: Value<number | null>;\n colspan?: Value<number | null>;\n rowspan?: Value<number | null>;\n scope?: StringAttribute;\n cite?: StringAttribute;\n poster?: StringAttribute;\n loading?: StringAttribute;\n decoding?: StringAttribute;\n sizes?: StringAttribute;\n srcset?: StringAttribute;\n crossorigin?: StringAttribute;\n referrerpolicy?: StringAttribute;\n sandbox?: StringAttribute;\n allow?: StringAttribute;\n allowfullscreen?: BooleanAttribute;\n}\n\nexport type HTMLAttributes<T extends HTMLElement = HTMLElement> = HtmlBaseAttributes<T> &\n DataAria &\n EventProps<T, HTMLElementEventMap>;\ntype RawTextProps<T extends HTMLElement = HTMLElement> = Omit<\n HtmlBaseAttributes<T>,\n \"children\" | \"rawHtml\"\n> &\n DataAria &\n EventProps<T, HTMLElementEventMap> & {\n children?: never;\n rawHtml?: string | undefined;\n };\ntype IframeProps = Omit<HtmlBaseAttributes<HTMLIFrameElement>, \"children\" | \"rawHtml\"> &\n DataAria &\n EventProps<HTMLIFrameElement, HTMLElementEventMap> & {\n children?: never;\n rawHtml?: never;\n };\ntype InputBase = Omit<HtmlBaseAttributes<HTMLInputElement>, \"type\"> &\n DataAria &\n EventProps<HTMLInputElement, HTMLElementEventMap> & {\n defaultValue?: string | undefined;\n defaultChecked?: boolean | undefined;\n };\nexport type InputProps = InputBase &\n (\n | {\n type?: \"text\" | \"search\" | \"email\" | \"url\" | \"tel\" | \"password\" | undefined;\n modelValue?: Signal<string> | undefined;\n modelChecked?: never;\n }\n | {\n type: \"checkbox\";\n modelChecked?: Signal<boolean> | undefined;\n modelValue?: never;\n }\n | {\n type: \"radio\";\n name: string;\n value: string;\n modelValue?: Signal<string | null> | undefined;\n modelChecked?: never;\n }\n | {\n type: string;\n modelValue?: never;\n modelChecked?: never;\n }\n );\nexport type TextareaProps = HTMLAttributes<HTMLTextAreaElement> & {\n modelValue?: Signal<string> | undefined;\n defaultValue?: string | undefined;\n};\nexport type SelectProps = HTMLAttributes<HTMLSelectElement> & {\n modelValue?: Signal<string> | undefined;\n defaultValue?: string | undefined;\n};\n\ninterface SvgBaseAttributes<T extends SVGElement = SVGElement> extends CommonAttributes<T> {\n width?: DimensionAttribute;\n height?: DimensionAttribute;\n viewBox?: StringAttribute;\n preserveAspectRatio?: StringAttribute;\n gradientUnits?: StringAttribute;\n gradientTransform?: StringAttribute;\n markerWidth?: ScalarAttribute;\n markerHeight?: ScalarAttribute;\n refX?: ScalarAttribute;\n refY?: ScalarAttribute;\n \"xlink:href\"?: StringAttribute;\n \"xml:lang\"?: StringAttribute;\n xmlns?: StringAttribute;\n \"xmlns:xlink\"?: StringAttribute;\n href?: StringAttribute;\n focusable?: StringAttribute;\n \"stroke-width\"?: ScalarAttribute;\n \"fill-rule\"?: StringAttribute;\n \"clip-rule\"?: StringAttribute;\n \"stroke-linecap\"?: StringAttribute;\n \"stroke-linejoin\"?: StringAttribute;\n \"stop-color\"?: StringAttribute;\n \"stop-opacity\"?: ScalarAttribute;\n \"fill-opacity\"?: ScalarAttribute;\n \"stroke-dasharray\"?: StringAttribute;\n \"text-anchor\"?: StringAttribute;\n fill?: StringAttribute;\n stroke?: StringAttribute;\n d?: StringAttribute;\n x?: ScalarAttribute;\n y?: ScalarAttribute;\n x1?: ScalarAttribute;\n x2?: ScalarAttribute;\n y1?: ScalarAttribute;\n y2?: ScalarAttribute;\n cx?: ScalarAttribute;\n cy?: ScalarAttribute;\n r?: ScalarAttribute;\n rx?: ScalarAttribute;\n ry?: ScalarAttribute;\n points?: StringAttribute;\n transform?: StringAttribute;\n opacity?: ScalarAttribute;\n offset?: ScalarAttribute;\n id?: StringAttribute;\n}\n\nexport type SVGAttributes<T extends SVGElement = SVGElement> = SvgBaseAttributes<T> &\n DataAria &\n EventProps<T, SVGElementEventMap>;\ntype CustomProps = ReservedProps &\n EventProps<HTMLElement, GlobalEventHandlersEventMap> & {\n value?: string | null | undefined;\n checked?: null | undefined;\n [attribute: string]: StringAttribute | Child | Ref<Element> | AnyListener | undefined;\n };\n\ntype HtmlTag =\n | \"html\"\n | \"head\"\n | \"body\"\n | \"title\"\n | \"base\"\n | \"link\"\n | \"meta\"\n | \"style\"\n | \"script\"\n | \"div\"\n | \"span\"\n | \"p\"\n | \"a\"\n | \"br\"\n | \"hr\"\n | \"main\"\n | \"header\"\n | \"footer\"\n | \"nav\"\n | \"section\"\n | \"article\"\n | \"aside\"\n | \"search\"\n | \"hgroup\"\n | \"menu\"\n | \"h1\"\n | \"h2\"\n | \"h3\"\n | \"h4\"\n | \"h5\"\n | \"h6\"\n | \"ul\"\n | \"ol\"\n | \"li\"\n | \"dl\"\n | \"dt\"\n | \"dd\"\n | \"blockquote\"\n | \"pre\"\n | \"code\"\n | \"strong\"\n | \"em\"\n | \"b\"\n | \"i\"\n | \"small\"\n | \"mark\"\n | \"time\"\n | \"figure\"\n | \"figcaption\"\n | \"img\"\n | \"picture\"\n | \"source\"\n | \"video\"\n | \"audio\"\n | \"track\"\n | \"canvas\"\n | \"form\"\n | \"label\"\n | \"input\"\n | \"button\"\n | \"textarea\"\n | \"select\"\n | \"option\"\n | \"optgroup\"\n | \"fieldset\"\n | \"legend\"\n | \"output\"\n | \"progress\"\n | \"meter\"\n | \"datalist\"\n | \"table\"\n | \"caption\"\n | \"thead\"\n | \"tbody\"\n | \"tfoot\"\n | \"tr\"\n | \"th\"\n | \"td\"\n | \"col\"\n | \"colgroup\"\n | \"details\"\n | \"summary\"\n | \"dialog\"\n | \"template\"\n | \"slot\"\n | \"iframe\"\n | \"noscript\"\n | \"address\"\n | \"abbr\"\n | \"bdi\"\n | \"bdo\"\n | \"cite\"\n | \"data\"\n | \"del\"\n | \"dfn\"\n | \"ins\"\n | \"kbd\"\n | \"map\"\n | \"area\"\n | \"object\"\n | \"param\"\n | \"q\"\n | \"rp\"\n | \"rt\"\n | \"ruby\"\n | \"s\"\n | \"samp\"\n | \"sub\"\n | \"sup\"\n | \"u\"\n | \"var\"\n | \"wbr\"\n | \"embed\";\n\ntype SvgTag =\n | \"svg\"\n | \"g\"\n | \"path\"\n | \"circle\"\n | \"ellipse\"\n | \"rect\"\n | \"line\"\n | \"polyline\"\n | \"polygon\"\n | \"text\"\n | \"tspan\"\n | \"defs\"\n | \"symbol\"\n | \"use\"\n | \"clipPath\"\n | \"mask\"\n | \"linearGradient\"\n | \"radialGradient\"\n | \"stop\"\n | \"desc\"\n | \"foreignObject\"\n | \"pattern\"\n | \"filter\"\n | \"marker\"\n | \"image\";\n\n/** DOM element corresponding to an owned intrinsic tag. */\nexport type ElementForTag<Tag extends HtmlTag | SvgTag> = Tag extends HtmlTag\n ? Tag extends keyof HTMLElementTagNameMap\n ? HTMLElementTagNameMap[Tag]\n : HTMLElement\n : Tag extends keyof SVGElementTagNameMap\n ? SVGElementTagNameMap[Tag]\n : SVGElement;\n\nexport namespace JSX {\n export type Element = Description;\n export type HTMLAttributes<T extends HTMLElement = HTMLElement> =\n import(\"./jsx-types.js\").HTMLAttributes<T>;\n export type SVGAttributes<T extends SVGElement = SVGElement> =\n import(\"./jsx-types.js\").SVGAttributes<T>;\n export type CSSProperties = import(\"./jsx-types.js\").CSSProperties;\n export type ElementType =\n | string\n | Component<any>\n | typeof import(\"../island.js\").Island\n | typeof import(\"./description.js\").Fragment;\n export type IntrinsicElements = {\n [K in HtmlTag]: K extends \"input\"\n ? InputProps\n : K extends \"textarea\"\n ? TextareaProps\n : K extends \"select\"\n ? SelectProps\n : K extends \"iframe\"\n ? IframeProps\n : K extends \"script\" | \"style\"\n ? RawTextProps<ElementForTag<K>>\n : HTMLAttributes<ElementForTag<K>>;\n } & {\n [K in SvgTag]: SVGAttributes<ElementForTag<K>>;\n } & {\n [K in `${string}-${string}`]: CustomProps;\n };\n export interface IntrinsicAttributes {\n key?: Key | undefined;\n }\n export interface ElementChildrenAttribute {\n children: unknown;\n }\n}\n"]}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
export declare function normalizeProps(props: Record<string, unknown>): Record<string, unknown>;
|
|
1
2
|
export declare function serializeProps(props: Record<string, unknown>): string;
|
|
3
|
+
export declare function emptyChildren(value: unknown, ancestors?: Set<object>): boolean;
|
|
2
4
|
export declare function parseProps(json: string): Record<string, unknown>;
|
|
@@ -2,13 +2,13 @@ const forbidden = new Set(["__proto__", "prototype", "constructor"]);
|
|
|
2
2
|
function fail(code, path, detail = "") {
|
|
3
3
|
throw new TypeError(`${code} at ${path}${detail ? ` (${detail})` : ""}`);
|
|
4
4
|
}
|
|
5
|
-
function
|
|
5
|
+
function normalize(value, path, ancestors) {
|
|
6
6
|
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
7
|
-
return;
|
|
7
|
+
return value;
|
|
8
8
|
if (typeof value === "number") {
|
|
9
9
|
if (!Number.isFinite(value))
|
|
10
10
|
fail("ZR_PROPS_NUMBER", path);
|
|
11
|
-
return;
|
|
11
|
+
return value;
|
|
12
12
|
}
|
|
13
13
|
if (value === undefined)
|
|
14
14
|
fail("ZR_PROPS_UNDEFINED", path);
|
|
@@ -23,6 +23,7 @@ function validate(value, path, ancestors) {
|
|
|
23
23
|
if (ancestor !== undefined)
|
|
24
24
|
fail("ZR_PROPS_CYCLE", path, `ancestor ${ancestor}`);
|
|
25
25
|
const array = Array.isArray(record);
|
|
26
|
+
const length = array ? record.length : 0;
|
|
26
27
|
if (!array &&
|
|
27
28
|
Object.getPrototypeOf(record) !== Object.prototype &&
|
|
28
29
|
Object.getPrototypeOf(record) !== null)
|
|
@@ -30,6 +31,9 @@ function validate(value, path, ancestors) {
|
|
|
30
31
|
ancestors.set(record, path);
|
|
31
32
|
try {
|
|
32
33
|
const descriptors = Object.getOwnPropertyDescriptors(record);
|
|
34
|
+
const copy = array
|
|
35
|
+
? []
|
|
36
|
+
: Object.create(Object.getPrototypeOf(record));
|
|
33
37
|
for (const key of Reflect.ownKeys(descriptors)) {
|
|
34
38
|
if (typeof key === "symbol")
|
|
35
39
|
fail("ZR_PROPS_PROPERTY", path, "symbol key");
|
|
@@ -41,22 +45,30 @@ function validate(value, path, ancestors) {
|
|
|
41
45
|
const descriptor = descriptors[key];
|
|
42
46
|
if (!descriptor || !descriptor.enumerable || !("value" in descriptor))
|
|
43
47
|
fail("ZR_PROPS_PROPERTY", next);
|
|
44
|
-
if (array && (!/^(0|[1-9]\d*)$/.test(key) || Number(key) >=
|
|
48
|
+
if (array && (!/^(0|[1-9]\d*)$/.test(key) || Number(key) >= length))
|
|
45
49
|
fail("ZR_PROPS_PROPERTY", next);
|
|
46
|
-
|
|
50
|
+
if (!array && descriptor.value === undefined)
|
|
51
|
+
continue;
|
|
52
|
+
Object.defineProperty(copy, key, {
|
|
53
|
+
value: normalize(descriptor.value, next, ancestors),
|
|
54
|
+
enumerable: true,
|
|
55
|
+
writable: true,
|
|
56
|
+
configurable: true,
|
|
57
|
+
});
|
|
47
58
|
}
|
|
48
59
|
if (array) {
|
|
49
|
-
for (let index = 0; index <
|
|
60
|
+
for (let index = 0; index < length; index++) {
|
|
50
61
|
if (!Object.hasOwn(record, index))
|
|
51
62
|
fail("ZR_PROPS_UNDEFINED", `${path}[${index}]`);
|
|
52
63
|
}
|
|
53
64
|
}
|
|
65
|
+
return copy;
|
|
54
66
|
}
|
|
55
67
|
finally {
|
|
56
68
|
ancestors.delete(record);
|
|
57
69
|
}
|
|
58
70
|
}
|
|
59
|
-
export function
|
|
71
|
+
export function normalizeProps(props) {
|
|
60
72
|
if (props === null || Array.isArray(props) || typeof props !== "object")
|
|
61
73
|
fail("ZR_PROPS_OBJECT_KIND", "props");
|
|
62
74
|
const descriptors = Object.getOwnPropertyDescriptors(props);
|
|
@@ -69,13 +81,29 @@ export function serializeProps(props) {
|
|
|
69
81
|
delete descriptors.children;
|
|
70
82
|
}
|
|
71
83
|
const payload = Object.defineProperties(Object.create(Object.getPrototypeOf(props)), descriptors);
|
|
72
|
-
|
|
73
|
-
return JSON.stringify(payload);
|
|
84
|
+
return normalize(payload, "props", new Map());
|
|
74
85
|
}
|
|
75
|
-
function
|
|
76
|
-
return (
|
|
77
|
-
|
|
78
|
-
|
|
86
|
+
export function serializeProps(props) {
|
|
87
|
+
return JSON.stringify(normalizeProps(props));
|
|
88
|
+
}
|
|
89
|
+
export function emptyChildren(value, ancestors = new Set()) {
|
|
90
|
+
if (value == null || typeof value === "boolean")
|
|
91
|
+
return true;
|
|
92
|
+
if (!Array.isArray(value) || ancestors.has(value))
|
|
93
|
+
return false;
|
|
94
|
+
ancestors.add(value);
|
|
95
|
+
try {
|
|
96
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
97
|
+
for (let index = 0; index < value.length; index++) {
|
|
98
|
+
const descriptor = descriptors[index];
|
|
99
|
+
if (descriptor && (!("value" in descriptor) || !emptyChildren(descriptor.value, ancestors)))
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
ancestors.delete(value);
|
|
106
|
+
}
|
|
79
107
|
}
|
|
80
108
|
export function parseProps(json) {
|
|
81
109
|
let parsed;
|
|
@@ -89,7 +117,7 @@ export function parseProps(json) {
|
|
|
89
117
|
fail("ZR_PROPS_OBJECT_KIND", "props");
|
|
90
118
|
if (Object.hasOwn(parsed, "children"))
|
|
91
119
|
fail("ZR_PROPS_CHILDREN", "props.children");
|
|
92
|
-
|
|
120
|
+
normalize(parsed, "props", new Map());
|
|
93
121
|
return parsed;
|
|
94
122
|
}
|
|
95
123
|
//# sourceMappingURL=props-transport.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"props-transport.js","sourceRoot":"","sources":["../../src/zudo-react/props-transport.ts"],"names":[],"mappings":"AAAA,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;AAErE,SAAS,IAAI,CAAC,IAAY,EAAE,IAAY,EAAE,MAAM,GAAG,EAAE;IACnD,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,OAAO,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,
|
|
1
|
+
{"version":3,"file":"props-transport.js","sourceRoot":"","sources":["../../src/zudo-react/props-transport.ts"],"names":[],"mappings":"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","sourcesContent":["const forbidden = new Set([\"__proto__\", \"prototype\", \"constructor\"]);\n\nfunction fail(code: string, path: string, detail = \"\"): never {\n throw new TypeError(`${code} at ${path}${detail ? ` (${detail})` : \"\"}`);\n}\n\nfunction normalize(value: unknown, path: string, ancestors: Map<object, string>): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) fail(\"ZR_PROPS_NUMBER\", path);\n return value;\n }\n if (value === undefined) fail(\"ZR_PROPS_UNDEFINED\", path);\n if (typeof value === \"function\" || typeof value === \"symbol\" || typeof value === \"bigint\")\n fail(`ZR_PROPS_${typeof value}`.toUpperCase(), path);\n if (typeof value !== \"object\") fail(\"ZR_PROPS_VALUE\", path);\n const record = value as object;\n if (\"$$zudo\" in record || \"$$zudoReactive\" in record) fail(\"ZR_PROPS_RUNTIME_VALUE\", path);\n const ancestor = ancestors.get(record);\n if (ancestor !== undefined) fail(\"ZR_PROPS_CYCLE\", path, `ancestor ${ancestor}`);\n const array = Array.isArray(record);\n const length = array ? (record as unknown[]).length : 0;\n if (\n !array &&\n Object.getPrototypeOf(record) !== Object.prototype &&\n Object.getPrototypeOf(record) !== null\n )\n fail(\"ZR_PROPS_OBJECT_KIND\", path);\n ancestors.set(record, path);\n try {\n const descriptors = Object.getOwnPropertyDescriptors(record);\n const copy: Record<string, unknown> | unknown[] = array\n ? []\n : Object.create(Object.getPrototypeOf(record));\n for (const key of Reflect.ownKeys(descriptors)) {\n if (typeof key === \"symbol\") fail(\"ZR_PROPS_PROPERTY\", path, \"symbol key\");\n if (array && key === \"length\") continue;\n const next = array ? `${path}[${key}]` : `${path}.${key}`;\n if (forbidden.has(key)) fail(\"ZR_PROPS_KEY\", next);\n const descriptor = descriptors[key];\n if (!descriptor || !descriptor.enumerable || !(\"value\" in descriptor))\n fail(\"ZR_PROPS_PROPERTY\", next);\n if (array && (!/^(0|[1-9]\\d*)$/.test(key) || Number(key) >= length))\n fail(\"ZR_PROPS_PROPERTY\", next);\n if (!array && descriptor.value === undefined) continue;\n Object.defineProperty(copy, key, {\n value: normalize(descriptor.value, next, ancestors),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n if (array) {\n for (let index = 0; index < length; index++) {\n if (!Object.hasOwn(record, index)) fail(\"ZR_PROPS_UNDEFINED\", `${path}[${index}]`);\n }\n }\n return copy;\n } finally {\n ancestors.delete(record);\n }\n}\n\nexport function normalizeProps(props: Record<string, unknown>): Record<string, unknown> {\n if (props === null || Array.isArray(props) || typeof props !== \"object\")\n fail(\"ZR_PROPS_OBJECT_KIND\", \"props\");\n const descriptors = Object.getOwnPropertyDescriptors(props);\n const child = descriptors.children;\n if (child) {\n if (!child.enumerable || !(\"value\" in child)) fail(\"ZR_PROPS_PROPERTY\", \"props.children\");\n if (!emptyChildren(child.value)) fail(\"ZR_PROPS_CHILDREN\", \"props.children\");\n delete descriptors.children;\n }\n const payload = Object.defineProperties(Object.create(Object.getPrototypeOf(props)), descriptors);\n return normalize(payload, \"props\", new Map()) as Record<string, unknown>;\n}\n\nexport function serializeProps(props: Record<string, unknown>): string {\n return JSON.stringify(normalizeProps(props));\n}\n\nexport function emptyChildren(value: unknown, ancestors = new Set<object>()): boolean {\n if (value == null || typeof value === \"boolean\") return true;\n if (!Array.isArray(value) || ancestors.has(value)) return false;\n ancestors.add(value);\n try {\n const descriptors = Object.getOwnPropertyDescriptors(value);\n for (let index = 0; index < value.length; index++) {\n const descriptor = descriptors[index];\n if (descriptor && (!(\"value\" in descriptor) || !emptyChildren(descriptor.value, ancestors)))\n return false;\n }\n return true;\n } finally {\n ancestors.delete(value);\n }\n}\n\nexport function parseProps(json: string): Record<string, unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n fail(\"ZR_PROPS_JSON\", \"props\");\n }\n if (parsed === null || Array.isArray(parsed) || typeof parsed !== \"object\")\n fail(\"ZR_PROPS_OBJECT_KIND\", \"props\");\n if (Object.hasOwn(parsed, \"children\")) fail(\"ZR_PROPS_CHILDREN\", \"props.children\");\n normalize(parsed, \"props\", new Map());\n return parsed as Record<string, unknown>;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function rawHtmlReserved(payload: string, tag: string): boolean;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Reserved-boundary guard for rawHtml payloads, shared by the server renderer
|
|
2
|
+
// and the client runtime so both accept exactly the same payloads.
|
|
3
|
+
//
|
|
4
|
+
// Rule: a payload is rejected when it can create a reserved boundary, decided
|
|
5
|
+
// by an HTML-tokenizer pass (WHATWG tokenization, data state), not a text regex:
|
|
6
|
+
// - a start or end tag carrying an attribute whose ASCII-lowercased name is
|
|
7
|
+
// `data-zfb-island` or `data-zfb-island-skip-ssr` (any value form, or none);
|
|
8
|
+
// - a comment, including a bogus `<!…>`, `<?…>` or `</…>` comment, whose data
|
|
9
|
+
// contains `zr:1:` (hydration matches `zr:1:` / `/zr:1:` comment prefixes);
|
|
10
|
+
// - a payload that ends inside a tag, comment or `</`, which would absorb the
|
|
11
|
+
// renderer's closing boundary marker.
|
|
12
|
+
// Marker-like text in character data or quoted attribute values is inert and
|
|
13
|
+
// renders as written. The tokenizer models the data state only, so payloads it
|
|
14
|
+
// cannot model take the textual rule, which rejects any `data-zfb-island` or
|
|
15
|
+
// `zr:1:` occurrence: `noscript`/`xmp`/`noembed`/`noframes`/`plaintext` hosts,
|
|
16
|
+
// and payloads naming a RAWTEXT/RCDATA/script/PLAINTEXT element (its end tag may
|
|
17
|
+
// also close a raw-text ancestor) or a CDATA section (foreign content).
|
|
18
|
+
// `script`/`style` hosts are raw text: their payload cannot form markup, and
|
|
19
|
+
// they keep the documented contract (no protocol comment or island attribute
|
|
20
|
+
// text; the callers reject `</script` / `</style`).
|
|
21
|
+
const reservedAttributes = new Set(["data-zfb-island", "data-zfb-island-skip-ssr"]);
|
|
22
|
+
const rawTextHosts = new Set(["noscript", "xmp", "noembed", "noframes", "plaintext"]);
|
|
23
|
+
const unmodeled = /<\/?(?:script|style|textarea|title|xmp|iframe|noembed|noframes|noscript|plaintext)|<!\[cdata\[/i;
|
|
24
|
+
const space = /[\t\n\f\r ]/;
|
|
25
|
+
const nameEnd = /[\t\n\f\r />=]/;
|
|
26
|
+
const unquotedEnd = /[\t\n\f\r >]/;
|
|
27
|
+
export function rawHtmlReserved(payload, tag) {
|
|
28
|
+
if (tag === "script" || tag === "style")
|
|
29
|
+
return /<!--\/?zr:1:|data-zfb-island(?:-skip-ssr)?\s*=/.test(payload);
|
|
30
|
+
if (rawTextHosts.has(tag) || unmodeled.test(payload))
|
|
31
|
+
return /data-zfb-island|zr:1:/i.test(payload);
|
|
32
|
+
let i = 0;
|
|
33
|
+
for (;;) {
|
|
34
|
+
const lt = payload.indexOf("<", i);
|
|
35
|
+
if (lt < 0)
|
|
36
|
+
return false;
|
|
37
|
+
const c = payload[lt + 1];
|
|
38
|
+
let start;
|
|
39
|
+
if (c === undefined)
|
|
40
|
+
return false;
|
|
41
|
+
if (/[a-z]/i.test(c) || (c === "/" && /[a-z]/i.test(payload[lt + 2] ?? ""))) {
|
|
42
|
+
i = tagEnd(payload, c === "/" ? lt + 2 : lt + 1);
|
|
43
|
+
if (i < 0)
|
|
44
|
+
return true;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (c === "!" && payload.startsWith("--", lt + 2)) {
|
|
48
|
+
start = lt + 4;
|
|
49
|
+
if (payload[start] === ">" || payload.startsWith("->", start)) {
|
|
50
|
+
i = start;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const dashes = payload.indexOf("-->", start);
|
|
54
|
+
const bang = payload.indexOf("--!>", start);
|
|
55
|
+
const end = dashes < 0 || (bang >= 0 && bang < dashes) ? bang : dashes;
|
|
56
|
+
if (end < 0 || payload.slice(start, end).includes("zr:1:"))
|
|
57
|
+
return true;
|
|
58
|
+
i = end;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (c === "/") {
|
|
62
|
+
// `</` followed by the closing marker's `<` would open a bogus comment.
|
|
63
|
+
if (lt + 2 >= payload.length)
|
|
64
|
+
return true;
|
|
65
|
+
if (payload[lt + 2] === ">") {
|
|
66
|
+
i = lt + 3;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
start = lt + 2;
|
|
70
|
+
}
|
|
71
|
+
else if (c === "!" || c === "?")
|
|
72
|
+
start = lt + 1;
|
|
73
|
+
else {
|
|
74
|
+
i = lt + 1;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const end = payload.indexOf(">", start);
|
|
78
|
+
if (end < 0 || payload.slice(start, end).includes("zr:1:"))
|
|
79
|
+
return true;
|
|
80
|
+
i = end;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Returns the index just past the tag's `>`, or -1 when the tag is unterminated
|
|
84
|
+
// or carries a reserved attribute.
|
|
85
|
+
function tagEnd(s, j) {
|
|
86
|
+
const n = s.length;
|
|
87
|
+
while (j < n && !space.test(s[j]) && s[j] !== "/" && s[j] !== ">")
|
|
88
|
+
j++;
|
|
89
|
+
for (;;) {
|
|
90
|
+
while (j < n && (space.test(s[j]) || s[j] === "/"))
|
|
91
|
+
j++;
|
|
92
|
+
if (j >= n)
|
|
93
|
+
return -1;
|
|
94
|
+
if (s[j] === ">")
|
|
95
|
+
return j + 1;
|
|
96
|
+
const start = j++;
|
|
97
|
+
while (j < n && !nameEnd.test(s[j]))
|
|
98
|
+
j++;
|
|
99
|
+
if (reservedAttributes.has(s.slice(start, j).toLowerCase()))
|
|
100
|
+
return -1;
|
|
101
|
+
while (j < n && space.test(s[j]))
|
|
102
|
+
j++;
|
|
103
|
+
if (s[j] !== "=")
|
|
104
|
+
continue;
|
|
105
|
+
j++;
|
|
106
|
+
while (j < n && space.test(s[j]))
|
|
107
|
+
j++;
|
|
108
|
+
const quote = s[j];
|
|
109
|
+
if (quote === '"' || quote === "'") {
|
|
110
|
+
const close = s.indexOf(quote, j + 1);
|
|
111
|
+
if (close < 0)
|
|
112
|
+
return -1;
|
|
113
|
+
j = close + 1;
|
|
114
|
+
}
|
|
115
|
+
else
|
|
116
|
+
while (j < n && !unquotedEnd.test(s[j]))
|
|
117
|
+
j++;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=raw-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-html.js","sourceRoot":"","sources":["../../src/zudo-react/raw-html.ts"],"names":[],"mappings":"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","sourcesContent":["// Reserved-boundary guard for rawHtml payloads, shared by the server renderer\n// and the client runtime so both accept exactly the same payloads.\n//\n// Rule: a payload is rejected when it can create a reserved boundary, decided\n// by an HTML-tokenizer pass (WHATWG tokenization, data state), not a text regex:\n// - a start or end tag carrying an attribute whose ASCII-lowercased name is\n// `data-zfb-island` or `data-zfb-island-skip-ssr` (any value form, or none);\n// - a comment, including a bogus `<!…>`, `<?…>` or `</…>` comment, whose data\n// contains `zr:1:` (hydration matches `zr:1:` / `/zr:1:` comment prefixes);\n// - a payload that ends inside a tag, comment or `</`, which would absorb the\n// renderer's closing boundary marker.\n// Marker-like text in character data or quoted attribute values is inert and\n// renders as written. The tokenizer models the data state only, so payloads it\n// cannot model take the textual rule, which rejects any `data-zfb-island` or\n// `zr:1:` occurrence: `noscript`/`xmp`/`noembed`/`noframes`/`plaintext` hosts,\n// and payloads naming a RAWTEXT/RCDATA/script/PLAINTEXT element (its end tag may\n// also close a raw-text ancestor) or a CDATA section (foreign content).\n// `script`/`style` hosts are raw text: their payload cannot form markup, and\n// they keep the documented contract (no protocol comment or island attribute\n// text; the callers reject `</script` / `</style`).\n\nconst reservedAttributes = new Set([\"data-zfb-island\", \"data-zfb-island-skip-ssr\"]);\nconst rawTextHosts = new Set([\"noscript\", \"xmp\", \"noembed\", \"noframes\", \"plaintext\"]);\nconst unmodeled =\n /<\\/?(?:script|style|textarea|title|xmp|iframe|noembed|noframes|noscript|plaintext)|<!\\[cdata\\[/i;\nconst space = /[\\t\\n\\f\\r ]/;\nconst nameEnd = /[\\t\\n\\f\\r />=]/;\nconst unquotedEnd = /[\\t\\n\\f\\r >]/;\n\nexport function rawHtmlReserved(payload: string, tag: string): boolean {\n if (tag === \"script\" || tag === \"style\")\n return /<!--\\/?zr:1:|data-zfb-island(?:-skip-ssr)?\\s*=/.test(payload);\n if (rawTextHosts.has(tag) || unmodeled.test(payload))\n return /data-zfb-island|zr:1:/i.test(payload);\n let i = 0;\n for (;;) {\n const lt = payload.indexOf(\"<\", i);\n if (lt < 0) return false;\n const c = payload[lt + 1];\n let start: number;\n if (c === undefined) return false;\n if (/[a-z]/i.test(c) || (c === \"/\" && /[a-z]/i.test(payload[lt + 2] ?? \"\"))) {\n i = tagEnd(payload, c === \"/\" ? lt + 2 : lt + 1);\n if (i < 0) return true;\n continue;\n }\n if (c === \"!\" && payload.startsWith(\"--\", lt + 2)) {\n start = lt + 4;\n if (payload[start] === \">\" || payload.startsWith(\"->\", start)) {\n i = start;\n continue;\n }\n const dashes = payload.indexOf(\"-->\", start);\n const bang = payload.indexOf(\"--!>\", start);\n const end = dashes < 0 || (bang >= 0 && bang < dashes) ? bang : dashes;\n if (end < 0 || payload.slice(start, end).includes(\"zr:1:\")) return true;\n i = end;\n continue;\n }\n if (c === \"/\") {\n // `</` followed by the closing marker's `<` would open a bogus comment.\n if (lt + 2 >= payload.length) return true;\n if (payload[lt + 2] === \">\") {\n i = lt + 3;\n continue;\n }\n start = lt + 2;\n } else if (c === \"!\" || c === \"?\") start = lt + 1;\n else {\n i = lt + 1;\n continue;\n }\n const end = payload.indexOf(\">\", start);\n if (end < 0 || payload.slice(start, end).includes(\"zr:1:\")) return true;\n i = end;\n }\n}\n\n// Returns the index just past the tag's `>`, or -1 when the tag is unterminated\n// or carries a reserved attribute.\nfunction tagEnd(s: string, j: number): number {\n const n = s.length;\n while (j < n && !space.test(s[j]!) && s[j] !== \"/\" && s[j] !== \">\") j++;\n for (;;) {\n while (j < n && (space.test(s[j]!) || s[j] === \"/\")) j++;\n if (j >= n) return -1;\n if (s[j] === \">\") return j + 1;\n const start = j++;\n while (j < n && !nameEnd.test(s[j]!)) j++;\n if (reservedAttributes.has(s.slice(start, j).toLowerCase())) return -1;\n while (j < n && space.test(s[j]!)) j++;\n if (s[j] !== \"=\") continue;\n j++;\n while (j < n && space.test(s[j]!)) j++;\n const quote = s[j];\n if (quote === '\"' || quote === \"'\") {\n const close = s.indexOf(quote, j + 1);\n if (close < 0) return -1;\n j = close + 1;\n } else while (j < n && !unquotedEnd.test(s[j]!)) j++;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactive.js","sourceRoot":"","sources":["../../src/zudo-react/reactive.ts"],"names":[],"mappings":"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","sourcesContent":["import { enqueue, type Job, type Phase } from \"./scheduler.js\";\nimport type { ReadonlySignal, Signal } from \"./reactive-types.js\";\n\ninterface Source {\n readonly subscribers: Set<Observer>;\n}\ninterface Observer {\n readonly id: string;\n readonly dependencies: Set<Source>;\n invalidate(): void;\n}\nlet currentObserver: Observer | null = null;\nlet evaluating = 0;\nconst evaluationStack: Computed<unknown>[] = [];\nlet nextId = 0;\n\n// The quoted own key is the retained runtime definition witness.\nconst core = { \"@takazudo/zfb/zudo-react/runtime-definition-v1\": true, nextId: () => ++nextId };\n\nfunction track(source: Source): void {\n if (!currentObserver) return;\n source.subscribers.add(currentObserver);\n currentObserver.dependencies.add(source);\n}\nfunction detach(observer: Observer): void {\n for (const source of observer.dependencies) source.subscribers.delete(observer);\n observer.dependencies.clear();\n}\nfunction untracked<T>(fn: () => T): T {\n const previous = currentObserver;\n currentObserver = null;\n try {\n return fn();\n } finally {\n currentObserver = previous;\n }\n}\nexport { untracked };\n\nclass Writable<T> implements Signal<T>, Source {\n readonly $$zudoReactive = \"zudo-react.reactive.v1\" as const;\n readonly $$zudoWritable = \"zudo-react.writable.v1\" as const;\n readonly subscribers = new Set<Observer>();\n constructor(private current: T) {\n if (!core[\"@takazudo/zfb/zudo-react/runtime-definition-v1\"])\n throw new Error(\"ZR_RUNTIME_DEFINITION\");\n }\n get value(): T {\n track(this);\n return this.current;\n }\n set value(value: T) {\n if (evaluating > 0) throw new Error(\"ZR_COMPUTED_WRITE: write during computed evaluation\");\n if (Object.is(value, this.current)) return;\n this.current = value;\n for (const observer of [...this.subscribers]) observer.invalidate();\n }\n}\n\nclass Computed<T> implements ReadonlySignal<T>, Source, Observer {\n readonly $$zudoReactive = \"zudo-react.reactive.v1\" as const;\n readonly id = `computed:${core.nextId()}`;\n readonly subscribers = new Set<Observer>();\n readonly dependencies = new Set<Source>();\n private cached!: T;\n private dirty = true;\n private evaluatingNow = false;\n constructor(private readonly read: () => T) {}\n get value(): T {\n if (this.evaluatingNow) {\n throw new Error(\n `ZR_COMPUTED_CYCLE: ${[...evaluationStack.map((entry) => entry.id), this.id].join(\" -> \")}`,\n );\n }\n if (this.dirty) this.evaluate();\n track(this);\n if (this.subscribers.size === 0) {\n detachAndRelease(this);\n this.dirty = true;\n }\n return this.cached;\n }\n private evaluate(): void {\n detachAndRelease(this);\n const previous = currentObserver;\n currentObserver = this;\n this.evaluatingNow = true;\n evaluationStack.push(this as Computed<unknown>);\n evaluating++;\n try {\n this.cached = this.read();\n this.dirty = false;\n } catch (error) {\n detachAndRelease(this);\n throw error;\n } finally {\n evaluating--;\n evaluationStack.pop();\n this.evaluatingNow = false;\n currentObserver = previous;\n }\n }\n invalidate(): void {\n if (this.dirty) return;\n this.dirty = true;\n for (const observer of [...this.subscribers]) observer.invalidate();\n }\n release(): void {\n if (this.subscribers.size === 0) {\n detachAndRelease(this);\n this.dirty = true;\n }\n }\n}\n\nfunction release(source: Source): void {\n if (source instanceof Computed) source.release();\n}\nfunction detachAndRelease(observer: Observer): void {\n const sources = [...observer.dependencies];\n detach(observer);\n for (const source of sources) release(source);\n}\n\nexport function signal<T>(initial: T): Signal<T> {\n return new Writable(initial);\n}\nexport function computed<T>(read: () => T): ReadonlySignal<T> {\n return new Computed(read);\n}\nexport function readSnapshot<T>(value: ReadonlySignal<T>): T {\n return untracked(() => value.value);\n}\n\nexport interface Subscription {\n readonly id: string;\n run(): void;\n dispose(): void;\n}\nexport function subscribe(\n callback: () => void,\n options: { phase?: Phase; id?: string; active?: () => boolean; report?: Job[\"report\"] } = {},\n): Subscription {\n let disposed = false;\n const observer: Observer = {\n id: options.id ?? `subscriber:${core.nextId()}`,\n dependencies: new Set(),\n invalidate() {\n enqueue(job);\n },\n };\n const job: Job = {\n id: observer.id,\n phase: options.phase ?? \"commit\",\n active: () => !disposed && (options.active?.() ?? true),\n run: () => subscription.run(),\n ...(options.report ? { report: options.report } : {}),\n };\n const subscription: Subscription = {\n id: observer.id,\n run() {\n if (!job.active()) return;\n detachAndRelease(observer);\n const previous = currentObserver;\n currentObserver = observer;\n try {\n callback();\n } finally {\n currentObserver = previous;\n }\n },\n dispose() {\n disposed = true;\n detachAndRelease(observer);\n },\n };\n return subscription;\n}\n\n/** Internal test introspection; absent from every public entry. */\nexport function subscriberCount(value: ReadonlySignal<unknown>): number {\n return value instanceof Writable || value instanceof Computed ? value.subscribers.size : 0;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reactive.js","sourceRoot":"","sources":["../../src/zudo-react/reactive.ts"],"names":[],"mappings":"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","sourcesContent":["import { enqueue, type Job, type Phase } from \"./scheduler.js\";\nimport type { ReadonlySignal, Signal } from \"./reactive-types.js\";\n\ninterface Source {\n readonly subscribers: Set<Observer>;\n}\ninterface Observer {\n readonly id: string;\n readonly dependencies: Set<Source>;\n invalidate(): void;\n}\nlet currentObserver: Observer | null = null;\nlet evaluating = 0;\nconst evaluationStack: Computed<unknown>[] = [];\nlet nextId = 0;\n\n// The quoted own key is the retained runtime definition witness.\nconst core = { \"@takazudo/zfb/zudo-react/runtime-definition-v1\": true, nextId: () => ++nextId };\n\nfunction track(source: Source): void {\n if (!currentObserver) return;\n source.subscribers.add(currentObserver);\n currentObserver.dependencies.add(source);\n}\nfunction detach(observer: Observer): void {\n for (const source of observer.dependencies) source.subscribers.delete(observer);\n observer.dependencies.clear();\n}\nfunction untracked<T>(fn: () => T): T {\n const previous = currentObserver;\n currentObserver = null;\n try {\n return fn();\n } finally {\n currentObserver = previous;\n }\n}\nexport { untracked };\n\nclass Writable<T> implements Signal<T>, Source {\n readonly $$zudoReactive = \"zudo-react.reactive.v1\" as const;\n readonly $$zudoWritable = \"zudo-react.writable.v1\" as const;\n readonly subscribers = new Set<Observer>();\n constructor(private current: T) {\n if (!core[\"@takazudo/zfb/zudo-react/runtime-definition-v1\"])\n throw new Error(\"ZR_RUNTIME_DEFINITION\");\n }\n get value(): T {\n track(this);\n return this.current;\n }\n set value(value: T) {\n if (evaluating > 0) throw new Error(\"ZR_COMPUTED_WRITE: write during computed evaluation\");\n if (Object.is(value, this.current)) return;\n this.current = value;\n for (const observer of [...this.subscribers]) observer.invalidate();\n }\n}\n\nclass Computed<T> implements ReadonlySignal<T>, Source, Observer {\n readonly $$zudoReactive = \"zudo-react.reactive.v1\" as const;\n readonly id = `computed:${core.nextId()}`;\n readonly subscribers = new Set<Observer>();\n readonly dependencies = new Set<Source>();\n private cached!: T;\n private dirty = true;\n private evaluatingNow = false;\n constructor(private readonly read: () => T) {}\n get value(): T {\n if (this.evaluatingNow) {\n throw new Error(\n `ZR_COMPUTED_CYCLE: ${[...evaluationStack.map((entry) => entry.id), this.id].join(\" -> \")}`,\n );\n }\n if (this.dirty) this.evaluate();\n track(this);\n if (this.subscribers.size === 0) {\n detachAndRelease(this);\n this.dirty = true;\n }\n return this.cached;\n }\n private evaluate(): void {\n detachAndRelease(this);\n const previous = currentObserver;\n currentObserver = this;\n this.evaluatingNow = true;\n evaluationStack.push(this as Computed<unknown>);\n evaluating++;\n try {\n this.cached = this.read();\n this.dirty = false;\n } catch (error) {\n detachAndRelease(this);\n throw error;\n } finally {\n evaluating--;\n evaluationStack.pop();\n this.evaluatingNow = false;\n currentObserver = previous;\n }\n }\n invalidate(): void {\n if (this.dirty) return;\n this.dirty = true;\n for (const observer of [...this.subscribers]) observer.invalidate();\n }\n release(): void {\n if (this.subscribers.size === 0) {\n detachAndRelease(this);\n this.dirty = true;\n }\n }\n}\n\nfunction release(source: Source): void {\n if (source instanceof Computed) source.release();\n}\nfunction detachAndRelease(observer: Observer): void {\n const sources = [...observer.dependencies];\n detach(observer);\n for (const source of sources) release(source);\n}\n\nexport function signal<T>(initial: T): Signal<T> {\n return new Writable(initial);\n}\nexport function computed<T>(read: () => T): ReadonlySignal<T> {\n return new Computed(read);\n}\nexport function readSnapshot<T>(value: ReadonlySignal<T>): T {\n return untracked(() => value.value);\n}\n\nexport interface Subscription {\n readonly id: string;\n run(): void;\n dispose(): void;\n}\nexport function subscribe(\n callback: () => void,\n options: { phase?: Phase; id?: string; active?: () => boolean; report?: Job[\"report\"] } = {},\n): Subscription {\n let disposed = false;\n const observer: Observer = {\n id: options.id ?? `subscriber:${core.nextId()}`,\n dependencies: new Set(),\n invalidate() {\n enqueue(job);\n },\n };\n const job: Job = {\n id: observer.id,\n phase: options.phase ?? \"commit\",\n active: () => !disposed && (options.active?.() ?? true),\n run: () => subscription.run(),\n ...(options.report ? { report: options.report } : {}),\n };\n const subscription: Subscription = {\n id: observer.id,\n run() {\n if (!job.active()) return;\n detachAndRelease(observer);\n const previous = currentObserver;\n currentObserver = observer;\n try {\n callback();\n } finally {\n currentObserver = previous;\n }\n },\n dispose() {\n disposed = true;\n detachAndRelease(observer);\n },\n };\n return subscription;\n}\n\n/** Internal test introspection; absent from every public entry. */\nexport function subscriberCount(value: ReadonlySignal<unknown>): number {\n return value instanceof Writable || value instanceof Computed ? value.subscribers.size : 0;\n}\n"]}
|