@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.
Files changed (58) hide show
  1. package/dist/config.d.ts +28 -3
  2. package/dist/config.js +23 -12
  3. package/dist/config.js.map +1 -1
  4. package/dist/content.js.map +1 -1
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/island-boundary.d.ts +2 -2
  8. package/dist/island-boundary.js +4 -2
  9. package/dist/island-boundary.js.map +1 -1
  10. package/dist/island.d.ts +8 -4
  11. package/dist/island.js +1 -1
  12. package/dist/island.js.map +1 -1
  13. package/dist/jsx-types.d.ts +1 -1
  14. package/dist/jsx-types.js.map +1 -1
  15. package/dist/runtime.js.map +1 -1
  16. package/dist/slugify.js.map +1 -1
  17. package/dist/zudo-react/description.d.ts +18 -0
  18. package/dist/zudo-react/description.js +41 -0
  19. package/dist/zudo-react/description.js.map +1 -1
  20. package/dist/zudo-react/dom-bindings.d.ts +2 -1
  21. package/dist/zudo-react/dom-bindings.js +16 -22
  22. package/dist/zudo-react/dom-bindings.js.map +1 -1
  23. package/dist/zudo-react/forms.js.map +1 -1
  24. package/dist/zudo-react/hydrate.js +20 -30
  25. package/dist/zudo-react/hydrate.js.map +1 -1
  26. package/dist/zudo-react/index.d.ts +2 -1
  27. package/dist/zudo-react/index.js.map +1 -1
  28. package/dist/zudo-react/jsx-dev-runtime.d.ts +2 -6
  29. package/dist/zudo-react/jsx-dev-runtime.js +3 -3
  30. package/dist/zudo-react/jsx-dev-runtime.js.map +1 -1
  31. package/dist/zudo-react/jsx-runtime.js +2 -2
  32. package/dist/zudo-react/jsx-runtime.js.map +1 -1
  33. package/dist/zudo-react/jsx-types.d.ts +59 -23
  34. package/dist/zudo-react/jsx-types.js.map +1 -1
  35. package/dist/zudo-react/props-transport.d.ts +2 -0
  36. package/dist/zudo-react/props-transport.js +42 -14
  37. package/dist/zudo-react/props-transport.js.map +1 -1
  38. package/dist/zudo-react/raw-html.d.ts +1 -0
  39. package/dist/zudo-react/raw-html.js +120 -0
  40. package/dist/zudo-react/raw-html.js.map +1 -0
  41. package/dist/zudo-react/reactive.js.map +1 -1
  42. package/dist/zudo-react/render-html.d.ts +11 -1
  43. package/dist/zudo-react/render-html.js +83 -56
  44. package/dist/zudo-react/render-html.js.map +1 -1
  45. package/dist/zudo-react/root.js +24 -1
  46. package/dist/zudo-react/root.js.map +1 -1
  47. package/dist/zudo-react/server.d.ts +2 -0
  48. package/dist/zudo-react/server.js.map +1 -1
  49. package/dist/zudo-react/style.d.ts +10 -0
  50. package/dist/zudo-react/style.js +525 -0
  51. package/dist/zudo-react/style.js.map +1 -0
  52. package/dist/zudo-react/testing.d.ts +27 -0
  53. package/dist/zudo-react/testing.js +117 -0
  54. package/dist/zudo-react/testing.js.map +1 -0
  55. package/dist/zudo-react/vocabulary.d.ts +7 -0
  56. package/dist/zudo-react/vocabulary.js +64 -5
  57. package/dist/zudo-react/vocabulary.js.map +1 -1
  58. package/package.json +16 -10
@@ -1,4 +1,6 @@
1
- import type { Child, Component, Key } from "./description.js";
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 | CssStyle | null>;
38
+ style?: Value<string | CSSProperties | null>;
39
39
  hidden?: BooleanAttribute;
40
40
  inert?: BooleanAttribute;
41
- contenteditable?: StringAttribute;
42
- draggable?: StringAttribute;
43
- spellcheck?: StringAttribute;
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 HtmlAttributes<T extends Element = HTMLElement> extends CommonAttributes<T> {
51
+ interface HtmlBaseAttributes<T extends HTMLElement = HTMLElement> extends CommonAttributes<T> {
52
52
  href?: StringAttribute;
53
53
  target?: StringAttribute;
54
54
  rel?: StringAttribute;
55
- download?: StringAttribute;
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 HtmlProps<TRef extends Element = HTMLElement, TEvent extends HTMLElement = HTMLElement> = HtmlAttributes<TRef> & DataAria & EventProps<TEvent, HTMLElementEventMap>;
116
- type RawTextProps<TEvent extends HTMLElement = HTMLElement> = Omit<HtmlAttributes<HTMLElement>, "children" | "rawHtml"> & DataAria & EventProps<TEvent, HTMLElementEventMap> & {
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 InputBase = Omit<HtmlAttributes<HTMLInputElement>, "type"> & DataAria & EventProps<HTMLInputElement, HTMLElementEventMap> & {
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 = HtmlProps<HTMLTextAreaElement, HTMLTextAreaElement> & {
168
+ export type TextareaProps = HTMLAttributes<HTMLTextAreaElement> & {
144
169
  modelValue?: Signal<string> | undefined;
145
170
  defaultValue?: string | undefined;
146
171
  };
147
- type SelectProps = HtmlProps<HTMLSelectElement, HTMLSelectElement> & {
172
+ export type SelectProps = HTMLAttributes<HTMLSelectElement> & {
148
173
  modelValue?: Signal<string> | undefined;
149
174
  defaultValue?: string | undefined;
150
175
  };
151
- interface SvgAttributes extends CommonAttributes<SVGElement> {
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 SvgProps<TEvent extends SVGElement = SVGElement> = SvgAttributes & DataAria & EventProps<TEvent, SVGElementEventMap>;
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 = Child;
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 extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[K] : HTMLElement> : HtmlProps<HTMLElement, K extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[K] : HTMLElement>;
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]: SvgProps<K extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[K] : SVGElement>;
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 validate(value, path, ancestors) {
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) >= record.length))
48
+ if (array && (!/^(0|[1-9]\d*)$/.test(key) || Number(key) >= length))
45
49
  fail("ZR_PROPS_PROPERTY", next);
46
- validate(descriptor.value, next, ancestors);
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 < record.length; 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 serializeProps(props) {
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
- validate(payload, "props", new Map());
73
- return JSON.stringify(payload);
84
+ return normalize(payload, "props", new Map());
74
85
  }
75
- function emptyChildren(value) {
76
- return (value == null ||
77
- typeof value === "boolean" ||
78
- (Array.isArray(value) && value.every(emptyChildren)));
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
- validate(parsed, "props", new Map());
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":"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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 validate(value: unknown, path: string, ancestors: Map<object, string>): void {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return;\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) fail(\"ZR_PROPS_NUMBER\", path);\n return;\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 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 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) >= record.length))\n fail(\"ZR_PROPS_PROPERTY\", next);\n validate(descriptor.value, next, ancestors);\n }\n if (array) {\n for (let index = 0; index < record.length; index++) {\n if (!Object.hasOwn(record, index)) fail(\"ZR_PROPS_UNDEFINED\", `${path}[${index}]`);\n }\n }\n } finally {\n ancestors.delete(record);\n }\n}\n\nexport function serializeProps(props: Record<string, unknown>): string {\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 validate(payload, \"props\", new Map());\n return JSON.stringify(payload);\n}\n\nfunction emptyChildren(value: unknown): boolean {\n return (\n value == null ||\n typeof value === \"boolean\" ||\n (Array.isArray(value) && value.every(emptyChildren))\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 validate(parsed, \"props\", new Map());\n return parsed as Record<string, unknown>;\n}\n"]}
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":"AAAA,OAAO,EAAE,OAAO,EAAwB,MAAM,gBAAgB,CAAC;AAW/D,IAAI,eAAe,GAAoB,IAAI,CAAC;AAC5C,IAAI,UAAU,GAAG,CAAC,CAAC;AACnB,MAAM,eAAe,GAAwB,EAAE,CAAC;AAChD,IAAI,MAAM,GAAG,CAAC,CAAC;AAEf,iEAAiE;AACjE,MAAM,IAAI,GAAG,EAAE,gDAAgD,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;AAEhG,SAAS,KAAK,CAAC,MAAc;IAC3B,IAAI,CAAC,eAAe;QAAE,OAAO;IAC7B,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACxC,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC;AACD,SAAS,MAAM,CAAC,QAAkB;IAChC,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,YAAY;QAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChF,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;AAChC,CAAC;AACD,SAAS,SAAS,CAAI,EAAW;IAC/B,MAAM,QAAQ,GAAG,eAAe,CAAC;IACjC,eAAe,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,eAAe,GAAG,QAAQ,CAAC;IAC7B,CAAC;AACH,CAAC;AACD,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,MAAM,QAAQ;IAIQ;IAHX,cAAc,GAAG,wBAAiC,CAAC;IACnD,cAAc,GAAG,wBAAiC,CAAC;IACnD,WAAW,GAAG,IAAI,GAAG,EAAY,CAAC;IAC3C,YAAoB,OAAU;QAAV,YAAO,GAAP,OAAO,CAAG;QAC5B,IAAI,CAAC,IAAI,CAAC,gDAAgD,CAAC;YACzD,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,KAAK;QACP,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,CAAC,KAAQ;QAChB,IAAI,UAAU,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAC3F,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO;QAC3C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;YAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;IACtE,CAAC;CACF;AAED,MAAM,QAAQ;IAQiB;IAPpB,cAAc,GAAG,wBAAiC,CAAC;IACnD,EAAE,GAAG,YAAY,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;IACjC,WAAW,GAAG,IAAI,GAAG,EAAY,CAAC;IAClC,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,CAAK;IACX,KAAK,GAAG,IAAI,CAAC;IACb,aAAa,GAAG,KAAK,CAAC;IAC9B,YAA6B,IAAa;QAAb,SAAI,GAAJ,IAAI,CAAS;IAAG,CAAC;IAC9C,IAAI,KAAK;QACP,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,sBAAsB,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAC5F,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAChC,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IACO,QAAQ;QACd,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,MAAM,QAAQ,GAAG,eAAe,CAAC;QACjC,eAAe,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,eAAe,CAAC,IAAI,CAAC,IAAyB,CAAC,CAAC;QAChD,UAAU,EAAE,CAAC;QACb,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,UAAU,EAAE,CAAC;YACb,eAAe,CAAC,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,eAAe,GAAG,QAAQ,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,UAAU;QACR,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO;QACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;YAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;IACtE,CAAC;IACD,OAAO;QACL,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAChC,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;CACF;AAED,SAAS,OAAO,CAAC,MAAc;IAC7B,IAAI,MAAM,YAAY,QAAQ;QAAE,MAAM,CAAC,OAAO,EAAE,CAAC;AACnD,CAAC;AACD,SAAS,gBAAgB,CAAC,QAAkB;IAC1C,MAAM,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC3C,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjB,KAAK,MAAM,MAAM,IAAI,OAAO;QAAE,OAAO,CAAC,MAAM,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,MAAM,CAAI,OAAU;IAClC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC;AACD,MAAM,UAAU,QAAQ,CAAI,IAAa;IACvC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AACD,MAAM,UAAU,YAAY,CAAI,KAAwB;IACtD,OAAO,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAOD,MAAM,UAAU,SAAS,CACvB,QAAoB,EACpB,UAA0F,EAAE;IAE5F,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,QAAQ,GAAa;QACzB,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,cAAc,IAAI,CAAC,MAAM,EAAE,EAAE;QAC/C,YAAY,EAAE,IAAI,GAAG,EAAE;QACvB,UAAU;YACR,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;KACF,CAAC;IACF,MAAM,GAAG,GAAQ;QACf,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,QAAQ;QAChC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI,CAAC;QACvD,GAAG,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE;QAC7B,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC;IACF,MAAM,YAAY,GAAiB;QACjC,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,GAAG;YACD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE;gBAAE,OAAO;YAC1B,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAC3B,MAAM,QAAQ,GAAG,eAAe,CAAC;YACjC,eAAe,GAAG,QAAQ,CAAC;YAC3B,IAAI,CAAC;gBACH,QAAQ,EAAE,CAAC;YACb,CAAC;oBAAS,CAAC;gBACT,eAAe,GAAG,QAAQ,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,OAAO;YACL,QAAQ,GAAG,IAAI,CAAC;YAChB,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;IACF,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,KAA8B;IAC5D,OAAO,KAAK,YAAY,QAAQ,IAAI,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7F,CAAC","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"]}