@vanijs/vani 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -59,7 +59,7 @@ This guarantees:
59
59
 
60
60
  Vani requires:
61
61
 
62
- - no JSX
62
+ - JS-first by default (optional JSX adapter)
63
63
  - no compiler
64
64
  - no build-time transforms
65
65
  - no generated code
@@ -154,6 +154,24 @@ This separates:
154
154
 
155
155
  ---
156
156
 
157
+ ## JSX (optional)
158
+
159
+ Vani is JS-first and transpiler-free, but it also ships a JSX adapter that maps JSX syntax to the
160
+ same runtime behavior (CSR + SSR).
161
+
162
+ TypeScript config example:
163
+
164
+ ```json
165
+ {
166
+ "compilerOptions": {
167
+ "jsx": "react-jsx",
168
+ "jsxImportSource": "@vanijs/vani"
169
+ }
170
+ }
171
+ ```
172
+
173
+ ---
174
+
157
175
  ## SSR (experimental)
158
176
 
159
177
  Vani SSR is explicit and anchor-based. You call `renderToString`, and the output includes the same
@@ -185,11 +203,17 @@ Notes:
185
203
 
186
204
  - ❌ Not a Virtual DOM
187
205
  - ❌ Not reactive-by-default
188
- - ❌ Not JSX-based
206
+ - ❌ Not JSX-mandatory (optional adapter)
189
207
  - ❌ Not compiler-driven
190
208
  - ❌ Not a template language
191
209
  - ❌ Not a framework that guesses intent
192
210
 
211
+ ### Why not Web Components (yet)
212
+
213
+ Vani does not use Web Components today because the developer ergonomics are still rough and SSR
214
+ support is a key goal. We may revisit this if Web Components bring clear benefits without harming
215
+ productivity and cross-browser compatibility.
216
+
193
217
  ---
194
218
 
195
219
  ## Comparison with Popular Frameworks
@@ -206,7 +230,31 @@ Notes:
206
230
  | SSR without heuristics | ✅ | ❌ | ❌ | ❌ | ❌ |
207
231
  | Dependency-free core | ✅ | ❌ | ❌ | ❌ | ❌ |
208
232
 
209
- ⚠️ = partially / indirectly supported
233
+ ⚠️ = partially / indirectly supported / average
234
+
235
+ The strength of Vani is its predictability and simplicity, while other frameworks focus on developer
236
+ productivity and ease of use, handling a lot of complexity behind the scenes automatically.
237
+
238
+ ### Vani's Sweet Spot
239
+
240
+ ✅ Perfect for:
241
+
242
+ - Dashboard widgets
243
+ - Micro-frontends
244
+ - Live-coding in the browser
245
+ - Embeddable components in other frameworks
246
+ - Performance-critical UIs where you need exact control
247
+ - Server-rendered sites
248
+ - Learning UI fundamentals (no magic, direct DOM)
249
+ - Lightweight SPAs or small Multi-Page Applications
250
+
251
+ ❌ Not ideal for:
252
+
253
+ - Large, complex web applications with many interrelated states
254
+ - Teams that want framework conventions to handle complexity
255
+ - Projects needing a mature ecosystem
256
+
257
+ (at least not yet)
210
258
 
211
259
  ---
212
260
 
@@ -1,157 +1,5 @@
1
- //#region src/vani/runtime.d.ts
2
- type SSRNode = {
3
- type: 'element';
4
- tag: string;
5
- props: Record<string, any>;
6
- children: SSRNode[];
7
- } | {
8
- type: 'text';
9
- text: string;
10
- } | {
11
- type: 'comment';
12
- text: string;
13
- } | {
14
- type: 'fragment';
15
- children: SSRNode[];
16
- } | {
17
- type: 'component';
18
- instance: ComponentInstance<any>;
19
- };
20
- type VNode = Node | SSRNode;
21
- interface Handle {
22
- /**
23
- * Schedules a render for the component.
24
- * This triggers a re-render on the next microtask.
25
- */
26
- update(): void;
27
- /**
28
- * Flushes the component render.
29
- * This triggers a re-render immediately.
30
- */
31
- updateSync(): void;
32
- /**
33
- * Disposes the component: removes the component from the DOM and runs all cleanup functions.
34
- */
35
- dispose(): void;
36
- /**
37
- * Adds a cleanup function that is called when the component is disposed.
38
- */
39
- onCleanup(fn: () => void): void;
40
- /**
41
- * This is purely syntatic sugar, as it is basically the same as running the function
42
- * on the setup phase and calling onCleanup to add a cleanup function.
43
- *
44
- * Using effects is necessary in SSR mode, for side effects to not run on the server
45
- * (e.g. timers, subscriptions, DOM usage, etc.)
46
- *
47
- * Runs a side effect function when the component is mounted.
48
- * The returning function may be a cleanup function that is called when the component is disposed.
49
- *
50
- */
51
- effect(fn: () => void | (() => void)): void;
52
- }
53
- type RenderFn = () => VChild;
54
- type Component<Props = any> = (props: Props, handle: Handle) => RenderFn | Promise<RenderFn>;
55
- type ComponentInstance<Props = any> = {
56
- $$vani: 'component';
57
- component: Component<Props>;
58
- props: Props;
59
- /**
60
- * A key is used to identify the component when it is re-rendered.
61
- * If a key is provided, the component will be re-rendered only if the key changes.
62
- */
63
- key?: string | number;
64
- /**
65
- * A ref is used to get a reference to the component instance.
66
- * The ref is set to the component instance when the component is mounted.
67
- * The ref is set to null when the component is disposed.
68
- */
69
- ref?: ComponentRef;
70
- clientOnly?: boolean;
71
- };
72
- type ComponentInput<Props> = Props & {
73
- key?: string | number;
74
- ref?: ComponentRef;
75
- };
76
- type ComponentMetaProps = {
77
- key?: string | number;
78
- ref?: ComponentRef;
79
- fallback?: RenderFn;
80
- clientOnly?: boolean;
81
- };
82
- type VChild = VNode | ComponentInstance<any> | string | number | null | undefined | false;
83
- type DataAttribute = `data-${string}`;
84
- type HtmlProps<T extends keyof HTMLElementTagNameMap> = Partial<Omit<HTMLElementTagNameMap[T], 'children' | 'className' | 'style'>> & {
85
- className?: ClassName;
86
- style?: string;
87
- ref?: DomRef<HTMLElementTagNameMap[T]>;
88
- } & { [key in DataAttribute]?: string | number | boolean | undefined | null };
89
- type ClassName = string | undefined | null | {
90
- [key: string]: boolean | undefined | null;
91
- } | ClassName[];
92
- type ComponentRef = {
93
- current: Handle | null;
94
- };
95
- type DomRef<T extends HTMLElement = HTMLElement> = {
96
- current: T | null;
97
- };
98
- type RenderMode = 'dom' | 'ssr';
99
- declare function component(fn: Component<void>): (props?: ComponentMetaProps) => ComponentInstance<void>;
100
- declare function component<Props>(fn: Component<Props>): (props: Props & ComponentMetaProps) => ComponentInstance<Props>;
101
- declare function withRenderMode<T>(mode: RenderMode, fn: () => T): T;
102
- declare function getRenderMode(): RenderMode;
103
- declare function renderToDOM(components: Array<Component<any> | ComponentInstance<any>>, root: HTMLElement): Handle[];
104
- declare function isComponentInstance(child: VChild): child is ComponentInstance<any>;
105
- declare function classNames(...classes: ClassName[]): string;
106
- declare function el<E extends keyof HTMLElementTagNameMap>(tag: E, props?: HtmlProps<E> | VChild | null, ...children: VChild[]): VNode;
107
- declare const fragment: (...children: VChild[]) => {
108
- type: "fragment";
109
- children: SSRNode[];
110
- } | DocumentFragment;
111
- declare function mount<Props>(component: Component<Props>, props: Props): VNode;
112
- /**
113
- * Marks all updates triggered inside the callback as a "transition".
114
- *
115
- * A transition represents non-urgent UI work that can be deferred
116
- * to keep the application responsive.
117
- *
118
- * Updates scheduled inside `startTransition`:
119
- * - do NOT block user interactions
120
- * - are batched separately from urgent updates
121
- * - may be flushed later (e.g. after the current event or during idle time)
122
- *
123
- * Transitions are NOT animations.
124
- * They do not control how updates look, only *when* they are applied.
125
- *
126
- * Typical use cases:
127
- * - Filtering or sorting large lists
128
- * - Rendering expensive subtrees
129
- * - Applying async results that are not immediately visible
130
- *
131
- * Example:
132
- * ```ts
133
- * button({
134
- * onclick: () => {
135
- * // urgent update
136
- * setOpen(true)
137
- * handle.update()
138
- *
139
- * // non-urgent update
140
- * startTransition(() => {
141
- * setItems(filter(items))
142
- * handle.update()
143
- * })
144
- * },
145
- * })
146
- * ```
147
- *
148
- * If multiple transitions are triggered, they are automatically batched.
149
- * Transition updates never interrupt urgent updates.
150
- */
151
- declare function startTransition(fn: () => void): void;
152
- declare function hydrateToDOM(components: Array<Component<any> | ComponentInstance<any>>, root: HTMLElement): Handle[];
153
- declare function isDevMode(): boolean;
154
- //#endregion
1
+ import { C as isDevMode, D as withRenderMode, E as startTransition, S as isComponentInstance, T as renderToDOM, _ as component, a as ComponentRef, b as getRenderMode, c as ElementProps, d as RenderFn, f as SSRNode, g as classNames, h as VNode, i as ComponentInstance, l as Handle, m as VChild, n as Component, o as DataAttribute, p as SvgProps, r as ComponentInput, s as DomRef, t as ClassName, u as HtmlProps, v as el, w as mount, x as hydrateToDOM, y as fragment } from "./runtime-Dp-nlil7.mjs";
2
+
155
3
  //#region src/vani/html.d.ts
156
4
  declare const div: (propsOrChild?: VChild | HtmlProps<"div">, ...children: VChild[]) => VNode;
157
5
  declare const span: (propsOrChild?: VChild | HtmlProps<"span">, ...children: VChild[]) => VNode;
@@ -170,7 +18,7 @@ declare const aside: (propsOrChild?: VChild | HtmlProps<"aside">, ...children: V
170
18
  declare const nav: (propsOrChild?: VChild | HtmlProps<"nav">, ...children: VChild[]) => VNode;
171
19
  declare const details: (propsOrChild?: VChild | HtmlProps<"details">, ...children: VChild[]) => VNode;
172
20
  declare const summary: (propsOrChild?: VChild | HtmlProps<"summary">, ...children: VChild[]) => VNode;
173
- declare const a: (propsOrChild?: VChild | HtmlProps<"a">, ...children: VChild[]) => VNode;
21
+ declare const a: (propsOrChild?: VChild | SvgProps<"a">, ...children: VChild[]) => VNode;
174
22
  declare const button: (propsOrChild?: VChild | HtmlProps<"button">, ...children: VChild[]) => VNode;
175
23
  declare const input: (propsOrChild?: VChild | HtmlProps<"input">, ...children: VChild[]) => VNode;
176
24
  declare const output: (propsOrChild?: VChild | HtmlProps<"output">, ...children: VChild[]) => VNode;
@@ -227,14 +75,39 @@ declare const tfoot: (propsOrChild?: VChild | HtmlProps<"tfoot">, ...children: V
227
75
  declare const tr: (propsOrChild?: VChild | HtmlProps<"tr">, ...children: VChild[]) => VNode;
228
76
  declare const td: (propsOrChild?: VChild | HtmlProps<"td">, ...children: VChild[]) => VNode;
229
77
  declare const th: (propsOrChild?: VChild | HtmlProps<"th">, ...children: VChild[]) => VNode;
230
- declare const style: (propsOrChild?: VChild | HtmlProps<"style">, ...children: VChild[]) => VNode;
231
- declare const script: (propsOrChild?: VChild | HtmlProps<"script">, ...children: VChild[]) => VNode;
78
+ declare const style: (propsOrChild?: VChild | SvgProps<"style">, ...children: VChild[]) => VNode;
79
+ declare const script: (propsOrChild?: VChild | SvgProps<"script">, ...children: VChild[]) => VNode;
232
80
  declare const noscript: (propsOrChild?: VChild | HtmlProps<"noscript">, ...children: VChild[]) => VNode;
233
81
  declare const template: (propsOrChild?: VChild | HtmlProps<"template">, ...children: VChild[]) => VNode;
234
82
  declare const slot: (propsOrChild?: VChild | HtmlProps<"slot">, ...children: VChild[]) => VNode;
83
+ declare const svg: (propsOrChild?: VChild | SvgProps<"svg">, ...children: VChild[]) => VNode;
84
+ declare const g: (propsOrChild?: VChild | SvgProps<"g">, ...children: VChild[]) => VNode;
85
+ declare const path: (propsOrChild?: VChild | SvgProps<"path">, ...children: VChild[]) => VNode;
86
+ declare const circle: (propsOrChild?: VChild | SvgProps<"circle">, ...children: VChild[]) => VNode;
87
+ declare const rect: (propsOrChild?: VChild | SvgProps<"rect">, ...children: VChild[]) => VNode;
88
+ declare const line: (propsOrChild?: VChild | SvgProps<"line">, ...children: VChild[]) => VNode;
89
+ declare const polyline: (propsOrChild?: VChild | SvgProps<"polyline">, ...children: VChild[]) => VNode;
90
+ declare const polygon: (propsOrChild?: VChild | SvgProps<"polygon">, ...children: VChild[]) => VNode;
91
+ declare const ellipse: (propsOrChild?: VChild | SvgProps<"ellipse">, ...children: VChild[]) => VNode;
92
+ declare const defs: (propsOrChild?: VChild | SvgProps<"defs">, ...children: VChild[]) => VNode;
93
+ declare const clipPath: (propsOrChild?: VChild | SvgProps<"clipPath">, ...children: VChild[]) => VNode;
94
+ declare const mask: (propsOrChild?: VChild | SvgProps<"mask">, ...children: VChild[]) => VNode;
95
+ declare const pattern: (propsOrChild?: VChild | SvgProps<"pattern">, ...children: VChild[]) => VNode;
96
+ declare const linearGradient: (propsOrChild?: VChild | SvgProps<"linearGradient">, ...children: VChild[]) => VNode;
97
+ declare const radialGradient: (propsOrChild?: VChild | SvgProps<"radialGradient">, ...children: VChild[]) => VNode;
98
+ declare const stop: (propsOrChild?: VChild | SvgProps<"stop">, ...children: VChild[]) => VNode;
99
+ declare const use: (propsOrChild?: VChild | SvgProps<"use">, ...children: VChild[]) => VNode;
235
100
  //#endregion
236
101
  //#region src/vani/ssr.d.ts
237
102
  type Renderable = Component<any> | ComponentInstance<any>;
238
103
  declare function renderToString(components: Renderable[]): Promise<string>;
239
104
  //#endregion
240
- export { ClassName, Component, ComponentInput, ComponentInstance, ComponentRef, DataAttribute, DomRef, Handle, HtmlProps, RenderFn, SSRNode, VChild, VNode, a, abbr, article, aside, audio, blockquote, br, button, caption, cite, classNames, code, col, colgroup, component, datalist, dd, details, dfn, div, dl, dt, el, em, embed, fieldset, figcaption, figure, footer, form, fragment, getRenderMode, h1, h2, h3, h4, h5, h6, header, hr, hydrateToDOM, iframe, img, input, isComponentInstance, isDevMode, kbd, label, legend, li, main, mark, meter, mount, nav, noscript, ol, optgroup, option, output, p, picture, pre, progress, renderToDOM, renderToString, samp, script, section, select, slot, small, source, span, startTransition, strong, style, summary, table, tbody, td, template, textarea, tfoot, th, thead, time, tr, ul, var_, video, withRenderMode };
105
+ //#region src/vani/svg.d.ts
106
+ type SvgRenderOptions = {
107
+ size?: number;
108
+ className?: string;
109
+ attributes?: SvgProps;
110
+ };
111
+ declare const renderSvgString: (svg: string, options?: SvgRenderOptions) => VNode;
112
+ //#endregion
113
+ export { ClassName, Component, ComponentInput, ComponentInstance, ComponentRef, DataAttribute, DomRef, ElementProps, Handle, HtmlProps, RenderFn, SSRNode, SvgProps, SvgRenderOptions, VChild, VNode, a, abbr, article, aside, audio, blockquote, br, button, caption, circle, cite, classNames, clipPath, code, col, colgroup, component, datalist, dd, defs, details, dfn, div, dl, dt, el, ellipse, em, embed, fieldset, figcaption, figure, footer, form, fragment, g, getRenderMode, h1, h2, h3, h4, h5, h6, header, hr, hydrateToDOM, iframe, img, input, isComponentInstance, isDevMode, kbd, label, legend, li, line, linearGradient, main, mark, mask, meter, mount, nav, noscript, ol, optgroup, option, output, p, path, pattern, picture, polygon, polyline, pre, progress, radialGradient, rect, renderSvgString, renderToDOM, renderToString, samp, script, section, select, slot, small, source, span, startTransition, stop, strong, style, summary, svg, table, tbody, td, template, textarea, tfoot, th, thead, time, tr, ul, use, var_, video, withRenderMode };
@@ -1 +1 @@
1
- function e(e){let t=e;return t.__vaniKeyed||=new Map,t.__vaniKeyed}function t(e){return t=>{let n,r,i=!1,a=t;if(t&&typeof t==`object`){let e=t;if(n=e.key,r=e.ref,i=e.clientOnly,`key`in e||`ref`in e){let{key:t,ref:n,clientOnly:r,...i}=e;a=i}}return{$$vani:`component`,component:e,props:a,key:n,ref:r,clientOnly:i}}}let n=`dom`;function r(e,t){let r=n;n=e;let i=t();return i&&typeof i.finally==`function`?i.finally(()=>{n=r}):(n=r,i)}function i(){return n}function a(e){return typeof e==`object`&&!!e&&`type`in e}function o(e){return a(e)&&e.type===`element`}function s(e){return a(e)&&e.type===`fragment`}function c(e){return n===`dom`?document.createElement(e):{type:`element`,tag:e,props:{},children:[]}}function l(e){return n===`dom`?document.createTextNode(e):{type:`text`,text:e}}function u(e,t){if(n===`dom`){e.appendChild(t);return}(o(e)||s(e))&&e.children.push(t)}function d(e,t){let n=e.nextSibling;for(;n&&n!==t;){let e=n.nextSibling,t=n;t.__vaniDomRef&&(t.__vaniDomRef.current=null),n.remove(),n=e}}function ee(e){if(e==null||e===!1)return document.createComment(`vani:empty`);if(m(e)){let t=document.createDocumentFragment(),n=f(e.component,h(e),t);return e.ref&&(e.ref.current=n),t}if(typeof e==`string`||typeof e==`number`)return document.createTextNode(String(e));if(e instanceof Node)return e;throw Error(`[vani] render returned an unsupported node type in DOM mode`)}function f(e,t,n){let r=[],i=!1,a,o,s=t?.clientOnly===!0;if(O){let e=A;A+=1,a=M(n,e),o=N(a,e)}else a=document.createComment(`vani:start`),o=document.createComment(`vani:end`),n.appendChild(a),n.appendChild(o);let c,l={update(){i||(S?w.has(l)||(T.add(l),D()):(T.delete(l),w.add(l),re()))},updateSync(){if(i)return;let e=a.parentNode;if(!e)return;d(a,o);let t=ee(c());e.insertBefore(t,o)},onCleanup(e){r.push(e)},dispose(){if(!i){i=!0,w.delete(l),T.delete(l);for(let e of r)e();r.length=0,d(a,o),a.remove(),o.remove(),c=(()=>document.createComment(`disposed`))}},effect(e){let t=e();typeof t==`function`&&r.push(t)}};if(O&&!s){let n=!1;return c=()=>{if(!n){n=!0;let r=e(t,l);c=r instanceof Promise?()=>document.createComment(`async`):r}return c()},l}let u=e(t,l);return u instanceof Promise?(c=t?.fallback||(()=>document.createComment(`vani:async`)),(!O||s)&&l.update(),u.then(e=>{i||(c=e,l.update())}),l):(c=u,(!O||s)&&l.update(),l)}function p(e,t){if(!t)throw Error(`[vani] root element not found`);let n=[];for(let r of e){if(typeof r==`function`){let e=f(r,{},t);n.push(e);continue}let e=f(r.component,h(r),t);n.push(e)}return n}function m(e){let t=typeof Node<`u`&&e instanceof Node;if(typeof e!=`object`||t)return!1;let n=e;return n.$$vani===`component`&&typeof n.component==`function`}function te(e){let t=typeof Node<`u`&&e instanceof Node;return typeof e==`object`&&!!e&&!t&&!m(e)}function h(e){return e.clientOnly?{...e.props??{},clientOnly:!0}:e.props}function g(t,r){if(n===`ssr`){for(let e of r)if(!(e==null||e===!1||e===void 0)){if(m(e)){u(t,{type:`component`,instance:e});continue}if(typeof e==`string`||typeof e==`number`){u(t,l(String(e)));continue}if(a(e)){u(t,e);continue}}return}let i=t;for(let t of r)if(!(t==null||t===!1||t===void 0)){if(m(t)){if(t.key!=null){let n=e(i),r=i.__vaniUsedKeys??=new Set,a=n.get(t.key);if(!a){let e=document.createDocumentFragment(),r=f(t.component,h(t),e);t.ref&&(t.ref.current=r),a={fragment:e,handle:r,ref:t.ref},n.set(t.key,a),t.ref&&(t.ref.current=r)}r.add(t.key),i.appendChild(a.fragment);continue}let n=document.createDocumentFragment(),r=f(t.component,h(t),n);t.ref&&(t.ref.current=r),i.appendChild(n);continue}if(typeof t==`string`||typeof t==`number`){i.appendChild(document.createTextNode(String(t)));continue}i.appendChild(t)}let o=i.__vaniKeyed,s=i.__vaniUsedKeys;if(o&&s){for(let[e,t]of o)s.has(e)||(t.handle.dispose(),t.ref&&(t.ref.current=null),o.delete(e));s.clear()}}function _(e,t){for(let n in t){let r=t[n];if(![`key`,`ref`].includes(n)){if(n===`className`){let t=v(r);o(e)?e.props.class=t:e.className=t;continue}if(n.startsWith(`on`)&&typeof r==`function`)o(e)||(e[n.toLowerCase()]=r);else if(r===!0)o(e)?e.props[n]=!0:e.setAttribute(n,``);else if(r===!1||r==null)continue;else o(e)?e.props[n]=String(r):e.setAttribute(n,String(r))}}}function v(...e){return e.map(e=>{if(!(e==null||e===``))return typeof e==`string`?e.trim():Array.isArray(e)?v(...e):Object.entries(e).filter(([e,t])=>t).map(([e])=>e.trim()).join(` `).trim()}).filter(Boolean).join(` `)}function y(e,t,...n){let r=c(e);return te(t)?(t.ref&&(o(r)?t.ref.current=null:(t.ref.current=r,r.__vaniDomRef=t.ref)),_(r,t),g(r,n),r):(g(r,[t,...n]),r)}const ne=(...e)=>{if(n===`ssr`){let t={type:`fragment`,children:[]};return g(t,e),t}let t=document.createDocumentFragment();return g(t,e),t};function b(e,t){if(n===`ssr`)return{type:`component`,instance:{$$vani:`component`,component:e,props:t}};let r=document.createDocumentFragment();return f(e,t,r),r}let x=!1,S=!1,C=!1;const w=new Set,T=new Set;function E(e){let t=S;S=!0;try{e()}finally{S=t,D()}}function D(){C||(C=!0,setTimeout(()=>{C=!1,ie()},0))}function re(){x||(x=!0,queueMicrotask(()=>{x=!1;for(let e of w)e.updateSync();w.clear()}))}function ie(){for(let e of T)e.updateSync();T.clear(),T.size>0&&D()}let O=!1,k=null,A=0;function j(e){F()&&console.warn(`[vani] hydration warning: ${e}`)}function M(e,t){let n=k;(!n||!e.contains(n))&&(n=e.firstChild);let r=!1;for(;n;){if(n.nodeType===Node.COMMENT_NODE&&n.nodeValue===`vani:start`)return r&&j(`Found <!--vani:end--> before <!--vani:start--> for component #${t}. This usually means the server HTML anchor order is incorrect.`),n;n.nodeType===Node.COMMENT_NODE&&n.nodeValue===`vani:end`&&(r=!0),n=n.nextSibling}throw j(`Expected <!--vani:start--> for component #${t}, but none was found. This usually means the server HTML does not match the client component tree.`),Error(`[vani] hydration failed: start anchor not found`)}function N(e,t){let n=e.nextSibling,r=0;for(;n;){if(n.nodeType===Node.COMMENT_NODE){if(n.nodeValue===`vani:start`)r+=1;else if(n.nodeValue===`vani:end`){if(r===0)return k=n.nextSibling,n;--r}}n=n.nextSibling}throw j(`Expected <!--vani:end--> for component #${t}, but none was found. This usually means the server HTML does not match the client component tree.`),Error(`[vani] hydration failed: end anchor not found`)}function P(e,t){let n=[];O=!0,k=t.firstChild,A=0;try{n=p(e,t)}catch(e){console.error(`[vani] hydration failed:`,e)}finally{if(F()&&k){let e=k,t=!1;for(;e;){if(e.nodeType===Node.COMMENT_NODE){let n=e.nodeValue;if(n===`vani:start`||n===`vani:end`){t=!0;break}}e=e.nextSibling}t&&j(`Unused SSR anchors detected after hydration. Some server-rendered DOM was not claimed by the client runtime.`)}O=!1,k=null,A=0}return n}function F(){return`__vaniDevMode`in globalThis?globalThis.__vaniDevMode===!0:import.meta.env?import.meta.env.DEV:typeof process<`u`&&process.env!==void 0?process.env.NODE_ENV===`development`:!1}function I(e){return(t,...n)=>y(e,t,...n)}const L=I(`div`),R=I(`span`),z=I(`ul`),B=I(`li`),V=I(`ol`),H=I(`dl`),U=I(`dt`),W=I(`dd`),G=I(`main`),K=I(`header`),q=I(`footer`),J=I(`section`),Y=I(`article`),ae=I(`aside`),oe=I(`nav`),se=I(`details`),ce=I(`summary`),le=I(`a`),ue=I(`button`),de=I(`input`),fe=I(`output`),pe=I(`textarea`),me=I(`select`),he=I(`option`),ge=I(`optgroup`),_e=I(`label`),ve=I(`form`),ye=I(`progress`),be=I(`meter`),xe=I(`fieldset`),Se=I(`legend`),Ce=I(`datalist`),we=I(`figure`),Te=I(`figcaption`),Ee=I(`img`),De=I(`picture`),Oe=I(`source`),ke=I(`video`),Ae=I(`audio`),je=I(`iframe`),Me=I(`embed`),Ne=I(`time`),Pe=I(`mark`),Fe=I(`p`),Ie=I(`h1`),Le=I(`h2`),Re=I(`h3`),ze=I(`h4`),Be=I(`h5`),Ve=I(`h6`),He=I(`code`),Ue=I(`pre`),We=I(`blockquote`),Ge=I(`var`),Ke=I(`kbd`),qe=I(`samp`),Je=I(`cite`),Ye=I(`dfn`),Xe=I(`abbr`),Ze=I(`small`),Qe=I(`strong`),$e=I(`em`),et=I(`br`),tt=I(`hr`),nt=I(`table`),rt=I(`caption`),it=I(`colgroup`),at=I(`col`),ot=I(`tbody`),st=I(`thead`),ct=I(`tfoot`),lt=I(`tr`),ut=I(`td`),dt=I(`th`),ft=I(`style`),pt=I(`script`),mt=I(`noscript`),ht=I(`template`),X=I(`slot`),gt=new Set([`area`,`base`,`br`,`col`,`embed`,`hr`,`img`,`input`,`link`,`meta`,`param`,`source`,`track`,`wbr`]);function _t(){return{update(){},updateSync(){},dispose(){},onCleanup(){},effect(){}}}function vt(e){return typeof e==`function`?{$$vani:`component`,component:e,props:{}}:e}function Z(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}function yt(e){let t=[];for(let n of Object.keys(e)){let r=e[n];r==null||r===!1||n.startsWith(`on`)&&typeof r==`function`||(r===!0?t.push(n):t.push(`${n}="${Z(String(r))}"`))}return t.length>0?` ${t.join(` `)}`:``}function Q(e){if(e==null||e===!1)return{type:`fragment`,children:[]};if(typeof e==`string`||typeof e==`number`)return{type:`text`,text:String(e)};if(m(e))return{type:`component`,instance:e};if(typeof e==`object`&&`type`in e)return e;throw Error(`[vani] SSR received a DOM node. This is not supported.`)}async function bt(e){let t=`<!--vani:start-->`,n=`<!--vani:end-->`;if(e.clientOnly){let r=e.props?.fallback;return r?`${t}${await $(Q(r()))}${n}`:`${t}${n}`}let r=e.component(e.props,_t());return`${t}${await $(Q((r instanceof Promise?await r:r)()))}${n}`}async function $(e){switch(e.type){case`text`:return Z(e.text);case`comment`:return`<!--${e.text}-->`;case`fragment`:return(await Promise.all(e.children.map($))).join(``);case`component`:return bt(e.instance);case`element`:{let t=yt(e.props);if(gt.has(e.tag))return`<${e.tag}${t}>`;let n=(await Promise.all(e.children.map($))).join(``);return`<${e.tag}${t}>${n}</${e.tag}>`}}}async function xt(e){return r(`ssr`,async()=>{if(i()!==`ssr`)throw Error(`[vani] renderToString failed to set SSR render mode.`);let t=e.map(e=>({type:`component`,instance:vt(e)}));return(await Promise.all(t.map($))).join(``)})}export{le as a,Xe as abbr,Y as article,ae as aside,Ae as audio,We as blockquote,et as br,ue as button,rt as caption,Je as cite,v as classNames,He as code,at as col,it as colgroup,t as component,Ce as datalist,W as dd,se as details,Ye as dfn,L as div,H as dl,U as dt,y as el,$e as em,Me as embed,xe as fieldset,Te as figcaption,we as figure,q as footer,ve as form,ne as fragment,i as getRenderMode,Ie as h1,Le as h2,Re as h3,ze as h4,Be as h5,Ve as h6,K as header,tt as hr,P as hydrateToDOM,je as iframe,Ee as img,de as input,m as isComponentInstance,F as isDevMode,Ke as kbd,_e as label,Se as legend,B as li,G as main,Pe as mark,be as meter,b as mount,oe as nav,mt as noscript,V as ol,ge as optgroup,he as option,fe as output,Fe as p,De as picture,Ue as pre,ye as progress,p as renderToDOM,xt as renderToString,qe as samp,pt as script,J as section,me as select,X as slot,Ze as small,Oe as source,R as span,E as startTransition,Qe as strong,ft as style,ce as summary,nt as table,ot as tbody,ut as td,ht as template,pe as textarea,ct as tfoot,dt as th,st as thead,Ne as time,lt as tr,z as ul,Ge as var_,ke as video,r as withRenderMode};
1
+ import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,r as c,s as l,t as ee,u as te}from"./runtime-BIk4OH1t.mjs";function u(e){return(t,...n)=>c(e,t,...n)}const ne=u(`div`),re=u(`span`),ie=u(`ul`),ae=u(`li`),oe=u(`ol`),se=u(`dl`),d=u(`dt`),f=u(`dd`),p=u(`main`),m=u(`header`),h=u(`footer`),g=u(`section`),_=u(`article`),v=u(`aside`),y=u(`nav`),b=u(`details`),x=u(`summary`),S=u(`a`),C=u(`button`),w=u(`input`),T=u(`output`),E=u(`textarea`),D=u(`select`),O=u(`option`),k=u(`optgroup`),A=u(`label`),j=u(`form`),M=u(`progress`),N=u(`meter`),P=u(`fieldset`),F=u(`legend`),I=u(`datalist`),L=u(`figure`),R=u(`figcaption`),z=u(`img`),B=u(`picture`),V=u(`source`),H=u(`video`),U=u(`audio`),W=u(`iframe`),G=u(`embed`),K=u(`time`),ce=u(`mark`),le=u(`p`),ue=u(`h1`),de=u(`h2`),fe=u(`h3`),pe=u(`h4`),me=u(`h5`),he=u(`h6`),ge=u(`code`),_e=u(`pre`),ve=u(`blockquote`),ye=u(`var`),be=u(`kbd`),xe=u(`samp`),Se=u(`cite`),Ce=u(`dfn`),we=u(`abbr`),Te=u(`small`),Ee=u(`strong`),De=u(`em`),Oe=u(`br`),ke=u(`hr`),Ae=u(`table`),je=u(`caption`),Me=u(`colgroup`),Ne=u(`col`),Pe=u(`tbody`),Fe=u(`thead`),Ie=u(`tfoot`),Le=u(`tr`),Re=u(`td`),ze=u(`th`),Be=u(`style`),Ve=u(`script`),He=u(`noscript`),Ue=u(`template`),We=u(`slot`),Ge=u(`svg`),Ke=u(`g`),qe=u(`path`),Je=u(`circle`),Ye=u(`rect`),Xe=u(`line`),Ze=u(`polyline`),Qe=u(`polygon`),$e=u(`ellipse`),et=u(`defs`),tt=u(`clipPath`),nt=u(`mask`),rt=u(`pattern`),it=u(`linearGradient`),at=u(`radialGradient`),ot=u(`stop`),st=u(`use`),q=new Set([`area`,`base`,`br`,`col`,`embed`,`hr`,`img`,`input`,`link`,`meta`,`param`,`source`,`track`,`wbr`]);function ct(){return{update(){},updateSync(){},dispose(){},onCleanup(){},effect(){}}}function lt(e){return typeof e==`function`?{$$vani:`component`,component:e,props:{}}:e}function J(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}function ut(e){let t=[];for(let n of Object.keys(e)){let r=e[n];r==null||r===!1||n.startsWith(`on`)&&typeof r==`function`||(r===!0?t.push(n):t.push(`${n}="${J(String(r))}"`))}return t.length>0?` ${t.join(` `)}`:``}function Y(e){if(e==null||e===!1)return{type:`fragment`,children:[]};if(typeof e==`string`||typeof e==`number`)return{type:`text`,text:String(e)};if(l(e))return{type:`component`,instance:e};if(typeof e==`object`&&`type`in e)return e;throw Error(`[vani] SSR received a DOM node. This is not supported.`)}async function dt(e){let t=`<!--vani:start-->`,n=`<!--vani:end-->`;if(e.clientOnly){let r=e.props?.fallback;return r?`${t}${await X(Y(r()))}${n}`:`${t}${n}`}let r=e.component(e.props,ct());return`${t}${await X(Y((r instanceof Promise?await r:r)()))}${n}`}async function X(e){switch(e.type){case`text`:return J(e.text);case`comment`:return`<!--${e.text}-->`;case`fragment`:return(await Promise.all(e.children.map(X))).join(``);case`component`:return dt(e.instance);case`element`:{let t=ut(e.props);if(q.has(e.tag))return`<${e.tag}${t}>`;let n=(await Promise.all(e.children.map(X))).join(``);return`<${e.tag}${t}>${n}</${e.tag}>`}}}async function ft(t){return r(`ssr`,async()=>{if(e()!==`ssr`)throw Error(`[vani] renderToString failed to set SSR render mode.`);let n=t.map(e=>({type:`component`,instance:lt(e)}));return(await Promise.all(n.map(X))).join(``)})}const Z=new Map,Q=(e,t)=>{if(!t)return e;let n=`${e??``} ${t}`.trim();return n.length>0?n:void 0},pt=(e,t)=>{if(!t)return;let n=t.size;if(n!=null&&(e.setAttribute(`width`,String(n)),e.setAttribute(`height`,String(n))),t.className){let n=Q(e.getAttribute(`class`)??void 0,t.className);n&&e.setAttribute(`class`,n)}if(t.attributes){for(let[n,r]of Object.entries(t.attributes))if(!(r==null||r===!1)){if(r===!0){e.setAttribute(n,``);continue}e.setAttribute(n,String(r))}}},mt=e=>{let t={},n=/([^\s=]+)(?:=(?:"([^"]*)"|'([^']*)'|([^\s"'>]+)))?/g,r;for(;r=n.exec(e);){let e=r[1],n=r[2]??r[3]??r[4];t[e]=n===void 0?!0:n}return t},ht=e=>{let t=e.replace(/<!--[\s\S]*?-->/g,``).trim(),n=/<\/?[^>]+>/g,r=[],i=null,a=0,o,s=e=>{let t=r[r.length-1];t&&(t.type===`element`||t.type===`fragment`)&&t.children.push(e)};for(;o=n.exec(t);){let e=t.slice(a,o.index);e.trim().length>0&&s({type:`text`,text:e});let c=o[0];if(c.startsWith(`</`))r.pop();else{let e=c.endsWith(`/>`),t=c.slice(1,e?-2:-1).trim(),n=t.search(/\s/),a={type:`element`,tag:n===-1?t:t.slice(0,n),props:mt(n===-1?``:t.slice(n+1)),children:[]};i?s(a):i=a,e||r.push(a)}a=n.lastIndex}return i??{type:`fragment`,children:[]}},$=e=>e.type===`text`?{type:`text`,text:e.text}:e.type===`comment`?{type:`comment`,text:e.text}:e.type===`fragment`?{type:`fragment`,children:e.children.map($)}:e.type===`component`?{type:`component`,instance:e.instance}:{type:`element`,tag:e.tag,props:{...e.props},children:e.children.map($)},gt=(e,t)=>{if(!t||e.type!==`element`||e.tag!==`svg`)return;let n=e.props;if(t.size!=null&&(n.width=String(t.size),n.height=String(t.size)),t.className){let e=Q(n.class,t.className);e&&(n.class=e)}if(t.attributes){for(let[e,r]of Object.entries(t.attributes))if(!(r==null||r===!1)){if(r===!0){n[e]=!0;continue}n[e]=String(r)}}},_t=(t,n)=>{if(e()===`ssr`){let e=$(ht(t));return gt(e,n),e}let r=Z.get(t);r||(r=new DOMParser().parseFromString(t,`image/svg+xml`).documentElement,Z.set(t,r));let i=r.cloneNode(!0);return pt(i,n),i};export{S as a,we as abbr,_ as article,v as aside,U as audio,ve as blockquote,Oe as br,C as button,je as caption,Je as circle,Se as cite,ee as classNames,tt as clipPath,ge as code,Ne as col,Me as colgroup,o as component,I as datalist,f as dd,et as defs,b as details,Ce as dfn,ne as div,se as dl,d as dt,c as el,$e as ellipse,De as em,G as embed,P as fieldset,R as figcaption,L as figure,h as footer,j as form,i as fragment,Ke as g,e as getRenderMode,ue as h1,de as h2,fe as h3,pe as h4,me as h5,he as h6,m as header,ke as hr,s as hydrateToDOM,W as iframe,z as img,w as input,l as isComponentInstance,t as isDevMode,be as kbd,A as label,F as legend,ae as li,Xe as line,it as linearGradient,p as main,ce as mark,nt as mask,N as meter,a as mount,y as nav,He as noscript,oe as ol,k as optgroup,O as option,T as output,le as p,qe as path,rt as pattern,B as picture,Qe as polygon,Ze as polyline,_e as pre,M as progress,at as radialGradient,Ye as rect,_t as renderSvgString,te as renderToDOM,ft as renderToString,xe as samp,Ve as script,g as section,D as select,We as slot,Te as small,V as source,re as span,n as startTransition,ot as stop,Ee as strong,Be as style,x as summary,Ge as svg,Ae as table,Pe as tbody,Re as td,Ue as template,E as textarea,Ie as tfoot,ze as th,Fe as thead,K as time,Le as tr,ie as ul,st as use,ye as var_,H as video,r as withRenderMode};
@@ -0,0 +1,2 @@
1
+ import { Fragment, jsx, jsxDEV, jsxs } from "./jsx-runtime.mjs";
2
+ export { Fragment, jsx, jsxDEV, jsxs };
@@ -0,0 +1 @@
1
+ import{Fragment as e,jsx as t,jsxDEV as n,jsxs as r}from"./jsx-runtime.mjs";export{e as Fragment,t as jsx,n as jsxDEV,r as jsxs};
@@ -0,0 +1,27 @@
1
+ import { a as ComponentRef, c as ElementProps, h as VNode, i as ComponentInstance, m as VChild, n as Component, s as DomRef } from "./runtime-Dp-nlil7.mjs";
2
+
3
+ //#region src/vani/jsx-runtime.d.ts
4
+ type ElementTagName = Extract<keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap, string>;
5
+ type IntrinsicElementProps<Tag extends ElementTagName> = ElementProps<Tag> & {
6
+ children?: VChild | VChild[];
7
+ };
8
+ type Key = string | number | null | undefined;
9
+ declare const Fragment: unique symbol;
10
+ type JsxElementType = string | Component<any> | typeof Fragment;
11
+ declare function jsx(type: JsxElementType, props: Record<string, any> | null, key?: Key): VNode | ComponentInstance<void>;
12
+ declare const jsxs: typeof jsx;
13
+ declare function jsxDEV(type: JsxElementType, props: Record<string, any> | null, key?: Key, _isStaticChildren?: boolean, _source?: unknown, _self?: unknown): VNode | ComponentInstance<void>;
14
+ declare namespace JSX {
15
+ type Element = VNode | ComponentInstance<any>;
16
+ type ElementType = JsxElementType;
17
+ interface ElementChildrenAttribute {
18
+ children: {};
19
+ }
20
+ interface IntrinsicAttributes {
21
+ key?: string | number;
22
+ ref?: DomRef<globalThis.Element> | ComponentRef;
23
+ }
24
+ type IntrinsicElements = { [K in ElementTagName]: IntrinsicElementProps<K> };
25
+ }
26
+ //#endregion
27
+ export { Fragment, JSX, jsx, jsxDEV, jsxs };
@@ -0,0 +1 @@
1
+ import{i as e,n as t,r as n}from"./runtime-BIk4OH1t.mjs";const r=Symbol.for(`vani.fragment`);function i(e){return e==null||e===!1?[]:Array.isArray(e)?e:[e]}function a(e,t){if(!e||typeof e!=`object`)return{props:null,children:[],key:t,ref:void 0,hasChildrenProp:!1};let n=Object.prototype.hasOwnProperty.call(e,`children`),r=n?i(e.children):[],a=t??e.key,o=e.ref,{key:s,ref:c,children:l,...u}=e;return{props:Object.keys(u).length>0?u:null,children:r,key:a,ref:o,hasChildrenProp:n}}function o(i,o,s){let{props:c,children:l,key:u,ref:d,hasChildrenProp:f}=a(o,s);if(i===r)return e(...l);if(typeof i==`string`)return c?n(i,c,...l):n(i,null,...l);if(typeof i==`function`){let e={...c??{}};return(l.length>0||f)&&(e.children=l.length<=1?l[0]:l),u!=null&&(e.key=u),d&&(e.ref=d),t(i)(e)}throw Error(`[vani] jsx runtime received an unsupported element type.`)}const s=o;function c(e,t,n,r,i,a){return o(e,t,n)}export{r as Fragment,o as jsx,c as jsxDEV,s as jsxs};
@@ -0,0 +1 @@
1
+ function e(e){let t=e;return t.__vaniKeyed||=new Map,t.__vaniKeyed}function t(e){return t=>{let n,r,i=!1,a=t;if(t&&typeof t==`object`){let e=t;if(n=e.key,r=e.ref,i=e.clientOnly,`key`in e||`ref`in e){let{key:t,ref:n,clientOnly:r,...i}=e;a=i}}return{$$vani:`component`,component:e,props:a,key:n,ref:r,clientOnly:i}}}let n=`dom`;function r(e,t){let r=n;n=e;let i=t();return i&&typeof i.finally==`function`?i.finally(()=>{n=r}):(n=r,i)}function i(){return n}function a(e){if(typeof e!=`object`||!e||!(`type`in e))return!1;let t=e;switch(t.type){case`element`:return typeof t.tag==`string`&&typeof t.props==`object`&&Array.isArray(t.children);case`text`:case`comment`:return typeof t.text==`string`;case`fragment`:return Array.isArray(t.children);case`component`:return typeof t.instance==`object`&&t.instance!=null;default:return!1}}function o(e){return a(e)&&e.type===`element`}function s(e){return a(e)&&e.type===`fragment`}const c=new Set([`svg`,`g`,`path`,`circle`,`rect`,`line`,`polyline`,`polygon`,`ellipse`,`defs`,`clipPath`,`mask`,`pattern`,`linearGradient`,`radialGradient`,`stop`,`use`]);function l(e){return n===`dom`?c.has(e)?document.createElementNS(`http://www.w3.org/2000/svg`,e):document.createElement(e):{type:`element`,tag:e,props:{},children:[]}}function u(e){return n===`dom`?document.createTextNode(e):{type:`text`,text:e}}function d(e,t){if(n===`dom`){e.appendChild(t);return}(o(e)||s(e))&&e.children.push(t)}function f(e,t){let n=e.nextSibling;for(;n&&n!==t;){let e=n.nextSibling,t=n;t.__vaniDomRef&&(t.__vaniDomRef.current=null),n.remove(),n=e}}function p(e){if(e==null||e===!1)return document.createComment(`vani:empty`);if(g(e)){let t=document.createDocumentFragment(),n=m(e.component,v(e),t);return e.ref&&(e.ref.current=n),t}if(typeof e==`string`||typeof e==`number`)return document.createTextNode(String(e));if(e instanceof Node)return e;throw Error(`[vani] render returned an unsupported node type in DOM mode`)}function m(e,t,n){let r=[],i=!1,a,o,s=t?.clientOnly===!0;if(I){let e=R;R+=1,a=B(n,e),o=V(a,e)}else a=document.createComment(`vani:start`),o=document.createComment(`vani:end`),n.appendChild(a),n.appendChild(o);let c,l={update(){i||(O?A.has(l)||(j.add(l),N()):(j.delete(l),A.add(l),P()))},updateSync(){if(i)return;let e=a.parentNode;if(!e)return;f(a,o);let t=p(c());e.insertBefore(t,o)},onCleanup(e){r.push(e)},dispose(){if(!i){i=!0,A.delete(l),j.delete(l);for(let e of r)e();r.length=0,f(a,o),a.remove(),o.remove(),c=(()=>document.createComment(`disposed`))}},effect(e){let t=e();typeof t==`function`&&r.push(t)}};if(I&&!s){let n=!1;return c=()=>{if(!n){n=!0;let r=e(t,l);c=r instanceof Promise?()=>document.createComment(`async`):r}return c()},l}let u=e(t,l);return u instanceof Promise?(c=t?.fallback||(()=>document.createComment(`vani:async`)),(!I||s)&&l.update(),u.then(e=>{i||(c=e,l.update())}),l):(c=u,(!I||s)&&l.update(),l)}function h(e,t){if(!t)throw Error(`[vani] root element not found`);let n=[];for(let r of e){if(typeof r==`function`){let e=m(r,{},t);n.push(e);continue}let e=m(r.component,v(r),t);n.push(e)}return n}function g(e){let t=typeof Node<`u`&&e instanceof Node;if(typeof e!=`object`||t)return!1;let n=e;return n.$$vani===`component`&&typeof n.component==`function`}function _(e){let t=typeof Node<`u`&&e instanceof Node;return typeof e==`object`&&!!e&&!t&&!g(e)&&!a(e)}function v(e){return e.clientOnly?{...e.props??{},clientOnly:!0}:e.props}function y(t,r){if(n===`ssr`){for(let e of r)if(!(e==null||e===!1||e===void 0)){if(g(e)){d(t,{type:`component`,instance:e});continue}if(typeof e==`string`||typeof e==`number`){d(t,u(String(e)));continue}if(a(e)){d(t,e);continue}}return}let i=t;for(let t of r)if(!(t==null||t===!1||t===void 0)){if(g(t)){if(t.key!=null){let n=e(i),r=i.__vaniUsedKeys??=new Set,a=n.get(t.key);if(!a){let e=document.createDocumentFragment(),r=m(t.component,v(t),e);t.ref&&(t.ref.current=r),a={fragment:e,handle:r,ref:t.ref},n.set(t.key,a),t.ref&&(t.ref.current=r)}r.add(t.key),i.appendChild(a.fragment);continue}let n=document.createDocumentFragment(),r=m(t.component,v(t),n);t.ref&&(t.ref.current=r),i.appendChild(n);continue}if(typeof t==`string`||typeof t==`number`){i.appendChild(document.createTextNode(String(t)));continue}i.appendChild(t)}let o=i.__vaniKeyed,s=i.__vaniUsedKeys;if(o&&s){for(let[e,t]of o)s.has(e)||(t.handle.dispose(),t.ref&&(t.ref.current=null),o.delete(e));s.clear()}}function b(e){return typeof SVGElement<`u`&&e instanceof SVGElement}function x(e,t){return e.startsWith(`aria`)?`aria-`+e.replace(`aria-`,``).replace(`aria`,``).toLowerCase():e.startsWith(`data`)?`data-`+e.replace(`data-`,``).replace(`data`,``):e.toLowerCase()===`htmlfor`?`for`:t?e:e.toLowerCase()}function S(e,t){let n=o(e)?c.has(e.tag):b(e);for(let r in t){let i=t[r];if(![`key`,`ref`].includes(r)){if(r===`className`){let t=C(i);o(e)?e.props.class=t:n?e.setAttribute(`class`,t):e.className=t;continue}if(r.startsWith(`on`)&&typeof i==`function`)o(e)||(e[r.toLowerCase()]=i);else if(i===!0)o(e)?e.props[r]=!0:e.setAttribute(r,``);else if(i===!1||i==null)continue;else{let t=x(r,n);o(e)?e.props[t]=String(i):e.setAttribute(t,String(i))}}}}function C(...e){return e.map(e=>{if(!(e==null||e===``))return typeof e==`string`?e.trim():Array.isArray(e)?C(...e):Object.entries(e).filter(([e,t])=>t).map(([e])=>e.trim()).join(` `).trim()}).filter(Boolean).join(` `)}function w(e,t,...n){let r=l(e);return _(t)?(t.ref&&(o(r)?t.ref.current=null:(t.ref.current=r,r.__vaniDomRef=t.ref)),S(r,t),y(r,n),r):(y(r,[t,...n]),r)}const T=(...e)=>{if(n===`ssr`){let t={type:`fragment`,children:[]};return y(t,e),t}let t=document.createDocumentFragment();return y(t,e),t};function E(e,t){if(n===`ssr`)return{type:`component`,instance:{$$vani:`component`,component:e,props:t}};let r=document.createDocumentFragment();return m(e,t,r),r}let D=!1,O=!1,k=!1;const A=new Set,j=new Set;function M(e){let t=O;O=!0;try{e()}finally{O=t,N()}}function N(){k||(k=!0,setTimeout(()=>{k=!1,F()},0))}function P(){D||(D=!0,queueMicrotask(()=>{D=!1;for(let e of A)e.updateSync();A.clear()}))}function F(){for(let e of j)e.updateSync();j.clear(),j.size>0&&N()}let I=!1,L=null,R=0;function z(e){U()&&console.warn(`[vani] hydration warning: ${e}`)}function B(e,t){let n=L;(!n||!e.contains(n))&&(n=e.firstChild);let r=!1;for(;n;){if(n.nodeType===Node.COMMENT_NODE&&n.nodeValue===`vani:start`)return r&&z(`Found <!--vani:end--> before <!--vani:start--> for component #${t}. This usually means the server HTML anchor order is incorrect.`),n;n.nodeType===Node.COMMENT_NODE&&n.nodeValue===`vani:end`&&(r=!0),n=n.nextSibling}throw z(`Expected <!--vani:start--> for component #${t}, but none was found. This usually means the server HTML does not match the client component tree.`),Error(`[vani] hydration failed: start anchor not found`)}function V(e,t){let n=e.nextSibling,r=0;for(;n;){if(n.nodeType===Node.COMMENT_NODE){if(n.nodeValue===`vani:start`)r+=1;else if(n.nodeValue===`vani:end`){if(r===0)return L=n.nextSibling,n;--r}}n=n.nextSibling}throw z(`Expected <!--vani:end--> for component #${t}, but none was found. This usually means the server HTML does not match the client component tree.`),Error(`[vani] hydration failed: end anchor not found`)}function H(e,t){let n=[];I=!0,L=t.firstChild,R=0;try{n=h(e,t)}catch(e){console.error(`[vani] hydration failed:`,e)}finally{if(U()&&L){let e=L,t=!1;for(;e;){if(e.nodeType===Node.COMMENT_NODE){let n=e.nodeValue;if(n===`vani:start`||n===`vani:end`){t=!0;break}}e=e.nextSibling}t&&z(`Unused SSR anchors detected after hydration. Some server-rendered DOM was not claimed by the client runtime.`)}I=!1,L=null,R=0}return n}function U(){return`__vaniDevMode`in globalThis?globalThis.__vaniDevMode===!0:import.meta.env?import.meta.env.DEV:typeof process<`u`&&process.env!==void 0?process.env.NODE_ENV===`development`:!1}export{i as a,U as c,M as d,r as f,T as i,E as l,t as n,H as o,w as r,g as s,C as t,h as u};
@@ -0,0 +1,166 @@
1
+ //#region src/vani/runtime.d.ts
2
+ type SSRNode = {
3
+ type: 'element';
4
+ tag: string;
5
+ props: Record<string, any>;
6
+ children: SSRNode[];
7
+ } | {
8
+ type: 'text';
9
+ text: string;
10
+ } | {
11
+ type: 'comment';
12
+ text: string;
13
+ } | {
14
+ type: 'fragment';
15
+ children: SSRNode[];
16
+ } | {
17
+ type: 'component';
18
+ instance: ComponentInstance<any>;
19
+ };
20
+ type VNode = Node | SSRNode;
21
+ interface Handle {
22
+ /**
23
+ * Schedules a render for the component.
24
+ * This triggers a re-render on the next microtask.
25
+ */
26
+ update(): void;
27
+ /**
28
+ * Flushes the component render.
29
+ * This triggers a re-render immediately.
30
+ */
31
+ updateSync(): void;
32
+ /**
33
+ * Disposes the component: removes the component from the DOM and runs all cleanup functions.
34
+ */
35
+ dispose(): void;
36
+ /**
37
+ * Adds a cleanup function that is called when the component is disposed.
38
+ */
39
+ onCleanup(fn: () => void): void;
40
+ /**
41
+ * This is purely syntatic sugar, as it is basically the same as running the function
42
+ * on the setup phase and calling onCleanup to add a cleanup function.
43
+ *
44
+ * Using effects is necessary in SSR mode, for side effects to not run on the server
45
+ * (e.g. timers, subscriptions, DOM usage, etc.)
46
+ *
47
+ * Runs a side effect function when the component is mounted.
48
+ * The returning function may be a cleanup function that is called when the component is disposed.
49
+ *
50
+ */
51
+ effect(fn: () => void | (() => void)): void;
52
+ }
53
+ type RenderFn = () => VChild;
54
+ type Component<Props = any> = (props: Props, handle: Handle) => RenderFn | Promise<RenderFn>;
55
+ type ComponentInstance<Props = any> = {
56
+ $$vani: 'component';
57
+ component: Component<Props>;
58
+ props: Props;
59
+ /**
60
+ * A key is used to identify the component when it is re-rendered.
61
+ * If a key is provided, the component will be re-rendered only if the key changes.
62
+ */
63
+ key?: string | number;
64
+ /**
65
+ * A ref is used to get a reference to the component instance.
66
+ * The ref is set to the component instance when the component is mounted.
67
+ * The ref is set to null when the component is disposed.
68
+ */
69
+ ref?: ComponentRef;
70
+ clientOnly?: boolean;
71
+ };
72
+ type ComponentInput<Props> = Props & {
73
+ key?: string | number;
74
+ ref?: ComponentRef;
75
+ };
76
+ type ComponentMetaProps = {
77
+ key?: string | number;
78
+ ref?: ComponentRef;
79
+ fallback?: RenderFn;
80
+ clientOnly?: boolean;
81
+ };
82
+ type VChild = VNode | ComponentInstance<any> | string | number | null | undefined | false;
83
+ type DataAttribute = `data-${string}` | `data${Capitalize<string>}`;
84
+ type HtmlTagName = keyof HTMLElementTagNameMap;
85
+ type SvgTagName = keyof SVGElementTagNameMap;
86
+ type ElementTagName = HtmlTagName | SvgTagName;
87
+ type ElementByTag<T extends ElementTagName> = T extends HtmlTagName ? HTMLElementTagNameMap[T] : T extends SvgTagName ? SVGElementTagNameMap[T] : Element;
88
+ type SvgProps<T extends SvgTagName = SvgTagName> = BaseProps<T> & {
89
+ [key: string]: string | number | boolean | undefined | null | ((...args: any[]) => any);
90
+ };
91
+ type BaseProps<T extends ElementTagName> = {
92
+ className?: ClassName;
93
+ style?: string;
94
+ ref?: DomRef<ElementByTag<T>>;
95
+ } & {
96
+ [key: DataAttribute]: string | number | boolean | undefined | null;
97
+ };
98
+ type HtmlProps<T extends HtmlTagName = HtmlTagName> = BaseProps<T> & Partial<Omit<ElementByTag<T>, 'children' | 'className' | 'style'>>;
99
+ type ElementProps<T extends ElementTagName> = T extends SvgTagName ? SvgProps<T> : HtmlProps<Extract<T, HtmlTagName>>;
100
+ type ClassName = string | undefined | null | {
101
+ [key: string]: boolean | undefined | null;
102
+ } | ClassName[];
103
+ type ComponentRef = {
104
+ current: Handle | null;
105
+ };
106
+ type DomRef<T extends Element = Element> = {
107
+ current: T | null;
108
+ };
109
+ type RenderMode = 'dom' | 'ssr';
110
+ declare function component(fn: Component<void>): (props?: ComponentMetaProps) => ComponentInstance<void>;
111
+ declare function component<Props>(fn: Component<Props>): (props: Props & ComponentMetaProps) => ComponentInstance<Props>;
112
+ declare function withRenderMode<T>(mode: RenderMode, fn: () => T): T;
113
+ declare function getRenderMode(): RenderMode;
114
+ declare function renderToDOM(components: Array<Component<any> | ComponentInstance<any>>, root: HTMLElement): Handle[];
115
+ declare function isComponentInstance(child: VChild): child is ComponentInstance<any>;
116
+ declare function classNames(...classes: ClassName[]): string;
117
+ declare function el<E extends ElementTagName>(tag: E, props?: ElementProps<E> | VChild | null, ...children: VChild[]): VNode;
118
+ declare const fragment: (...children: VChild[]) => {
119
+ type: "fragment";
120
+ children: SSRNode[];
121
+ } | DocumentFragment;
122
+ declare function mount<Props>(component: Component<Props>, props: Props): VNode;
123
+ /**
124
+ * Marks all updates triggered inside the callback as a "transition".
125
+ *
126
+ * A transition represents non-urgent UI work that can be deferred
127
+ * to keep the application responsive.
128
+ *
129
+ * Updates scheduled inside `startTransition`:
130
+ * - do NOT block user interactions
131
+ * - are batched separately from urgent updates
132
+ * - may be flushed later (e.g. after the current event or during idle time)
133
+ *
134
+ * Transitions are NOT animations.
135
+ * They do not control how updates look, only *when* they are applied.
136
+ *
137
+ * Typical use cases:
138
+ * - Filtering or sorting large lists
139
+ * - Rendering expensive subtrees
140
+ * - Applying async results that are not immediately visible
141
+ *
142
+ * Example:
143
+ * ```ts
144
+ * button({
145
+ * onclick: () => {
146
+ * // urgent update
147
+ * setOpen(true)
148
+ * handle.update()
149
+ *
150
+ * // non-urgent update
151
+ * startTransition(() => {
152
+ * setItems(filter(items))
153
+ * handle.update()
154
+ * })
155
+ * },
156
+ * })
157
+ * ```
158
+ *
159
+ * If multiple transitions are triggered, they are automatically batched.
160
+ * Transition updates never interrupt urgent updates.
161
+ */
162
+ declare function startTransition(fn: () => void): void;
163
+ declare function hydrateToDOM(components: Array<Component<any> | ComponentInstance<any>>, root: HTMLElement): Handle[];
164
+ declare function isDevMode(): boolean;
165
+ //#endregion
166
+ export { isDevMode as C, withRenderMode as D, startTransition as E, isComponentInstance as S, renderToDOM as T, component as _, ComponentRef as a, getRenderMode as b, ElementProps as c, RenderFn as d, SSRNode as f, classNames as g, VNode as h, ComponentInstance as i, Handle as l, VChild as m, Component as n, DataAttribute as o, SvgProps as p, ComponentInput as r, DomRef as s, ClassName as t, HtmlProps as u, el as v, mount as w, hydrateToDOM as x, fragment as y };
package/llms.txt CHANGED
@@ -1,8 +1,3 @@
1
1
  # Vani project agent guide
2
2
 
3
- Vani (from Vanilla) is a Web Standards-first framework for building web applications.
4
-
5
- A fine-grained reactive open source framework for building lightning-fast apps — no virtual DOM, no
6
- compiler, no JSX, no transpilation, zero dependencies, SSR support, imperative reactivity.
7
-
8
- Check the DOCS.md and README.md files for more information.
3
+ Check the DOCS.md and README.md files for more information.