@vanijs/vani 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanijs/vani",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Web-standards-first UI runtime with explicit updates, fine-grained DOM ownership, and zero dependencies. JS-first, transpiler-free, with an optional JSX adapter. Built for SPA, SSR, and SSG.",
5
5
  "keywords": [
6
6
  "ui",
@@ -35,16 +35,22 @@
35
35
  "type": "module",
36
36
  "exports": {
37
37
  ".": {
38
- "types": "./dist/lib/index.d.mts",
39
- "default": "./dist/lib/index.mjs"
38
+ "import": {
39
+ "types": "./dist/lib/index.d.mts",
40
+ "default": "./dist/lib/index.mjs"
41
+ }
40
42
  },
41
43
  "./jsx-runtime": {
42
- "types": "./dist/lib/jsx-runtime.d.mts",
43
- "default": "./dist/lib/jsx-runtime.mjs"
44
+ "import": {
45
+ "types": "./dist/lib/jsx-runtime.d.mts",
46
+ "default": "./dist/lib/jsx-runtime.mjs"
47
+ }
44
48
  },
45
49
  "./jsx-dev-runtime": {
46
- "types": "./dist/lib/jsx-dev-runtime.d.mts",
47
- "default": "./dist/lib/jsx-dev-runtime.mjs"
50
+ "import": {
51
+ "types": "./dist/lib/jsx-dev-runtime.d.mts",
52
+ "default": "./dist/lib/jsx-dev-runtime.mjs"
53
+ }
48
54
  }
49
55
  },
50
56
  "module": "./dist/lib/index.mjs",
@@ -57,7 +63,33 @@
57
63
  "README.md",
58
64
  "LICENSE"
59
65
  ],
60
- "dependencies": {},
66
+ "scripts": {
67
+ "bench": "pnpm cleanup && pnpm run --filter benchmarks bench",
68
+ "bench:build": "pnpm run --filter benchmarks build:prod",
69
+ "bench:dev": "pnpm run --filter benchmarks dev",
70
+ "bench:wide": "BENCH_VIEWPORT_WIDTH=1280 BENCH_VIEWPORT_HEIGHT=740 pnpm run --filter benchmarks bench",
71
+ "build": "vite build && pnpm run build:lib",
72
+ "build:all": "pnpm run build && pnpm run build:pages",
73
+ "postbuild:all": "./tests/postbuild.sh dist",
74
+ "build:lib": "pnpm tsdown src/vani/index.ts src/vani/jsx-runtime.ts src/vani/jsx-dev-runtime.ts --minify --out-dir dist/lib --dts --sourcemap",
75
+ "build:pages": "vite build && pnpm run bench:build && cp -r bench/dist ./dist/client/benchmarks && cp -r bench/results ./dist/client/benchmarks/data",
76
+ "cleanup": "rm -rf dist node_modules/.vite node_modules/.vite-temp bench/dist bench/frameworks/*/dist",
77
+ "dev": "vite",
78
+ "format": "prettier --write . && pnpm run format:pkg",
79
+ "format:pkg": "pnpm sort-package-json package.json bench/package.json",
80
+ "lint": "pnpm run typecheck && pnpm run lint:eslint && pnpm run lint:circular",
81
+ "lint:circular": "pnpm madge --circular --extensions ts src/",
82
+ "lint:eslint": "eslint .",
83
+ "lint:unused": "pnpm knip --exclude exports",
84
+ "prepublishOnly": "pnpm format && pnpm lint && pnpm run build:lib && pnpm publint",
85
+ "preview": "pnpm run build:pages && vite preview",
86
+ "serve": "sirv ./dist/client",
87
+ "test": "./tests/postbuild.sh dist",
88
+ "typecheck": "tsc --noEmit && cd bench && pnpm run typecheck"
89
+ },
90
+ "dependencies": {
91
+ "sirv-cli": "^3.0.1"
92
+ },
61
93
  "devDependencies": {
62
94
  "@babel/runtime": "^7.28.6",
63
95
  "@codemirror/commands": "^6.10.1",
@@ -69,48 +101,45 @@
69
101
  "@shikijs/langs": "^3.21.0",
70
102
  "@shikijs/themes": "^3.21.0",
71
103
  "@tailwindcss/vite": "^4.1.18",
72
- "@types/bun": "^1.3.6",
73
- "@types/node": "^25.0.10",
74
- "@typescript/native-preview": "7.0.0-dev.20260122.3",
104
+ "@types/bun": "catalog:",
105
+ "@types/node": "catalog:",
106
+ "@typescript/native-preview": "catalog:",
75
107
  "@uiw/codemirror-theme-vscode": "^4.25.4",
76
108
  "eslint": "^9.39.2",
77
- "globals": "^17.0.0",
109
+ "globals": "^17.1.0",
110
+ "husky": "^9.1.7",
78
111
  "knip": "^5.82.1",
79
- "lucide-static": "^0.562.0",
112
+ "lucide-static": "^0.563.0",
80
113
  "madge": "^8.0.0",
81
- "playwright": "^1.57.0",
114
+ "playwright": "catalog:",
82
115
  "prettier": "^3.8.1",
83
116
  "prettier-plugin-tailwindcss": "^0.7.2",
84
117
  "publint": "^0.3.17",
85
118
  "shiki": "^3.21.0",
86
- "sort-package-json": "^3.6.0",
119
+ "sort-package-json": "^3.6.1",
87
120
  "tailwind-merge": "^3.4.0",
88
121
  "tailwindcss": "^4.1.18",
89
- "tsdown": "0.20.0-beta.4",
122
+ "tsdown": "0.20.1",
90
123
  "tw-animate-css": "^1.4.0",
91
- "typescript": "^5.9.3",
124
+ "typescript": "catalog:",
92
125
  "typescript-eslint": "^8.53.1",
93
- "vite": "8.0.0-beta.8"
126
+ "vite": "catalog:"
94
127
  },
95
128
  "publishConfig": {
96
- "access": "public"
97
- },
98
- "scripts": {
99
- "bench": "pnpm run --filter benchmarks bench",
100
- "bench:build": "pnpm run --filter benchmarks build --base '/benchmarks/{dir}'",
101
- "bench:dev": "pnpm run --filter benchmarks dev",
102
- "build": "pnpm run cleanup && vite build && pnpm run build:lib",
103
- "build:lib": "pnpm tsdown src/vani/index.ts src/vani/jsx-runtime.ts src/vani/jsx-dev-runtime.ts --minify --out-dir dist/lib --dts",
104
- "build:pages": "pnpm run cleanup && vite build && pnpm run bench:build && cp -r bench/dist ./dist/client/benchmarks && cp -r bench/snapshot/results ./dist/client/benchmarks/data",
105
- "cleanup": "rm -rf dist node_modules/.vite node_modules/.vite-temp bench/dist bench/frameworks/*/dist",
106
- "dev": "vite",
107
- "format": "prettier --write . && pnpm run format:pkg",
108
- "format:pkg": "pnpm sort-package-json package.json bench/package.json bench/frameworks/**/package.json",
109
- "lint": "pnpm run typecheck && pnpm run lint:eslint && pnpm run lint:circular",
110
- "lint:circular": "pnpm madge --circular --extensions ts src/",
111
- "lint:eslint": "eslint .",
112
- "lint:unused": "pnpm knip --exclude exports",
113
- "preview": "pnpm run build:pages && vite preview",
114
- "typecheck": "tsc --noEmit"
129
+ "access": "public",
130
+ "exports": {
131
+ ".": {
132
+ "types": "./dist/lib/index.d.mts",
133
+ "default": "./dist/lib/index.mjs"
134
+ },
135
+ "./jsx-runtime": {
136
+ "types": "./dist/lib/jsx-runtime.d.mts",
137
+ "default": "./dist/lib/jsx-runtime.mjs"
138
+ },
139
+ "./jsx-dev-runtime": {
140
+ "types": "./dist/lib/jsx-dev-runtime.d.mts",
141
+ "default": "./dist/lib/jsx-dev-runtime.mjs"
142
+ }
143
+ }
115
144
  }
116
- }
145
+ }
@@ -1,190 +0,0 @@
1
- //#region src/vani/signals.d.ts
2
- type SignalGetter<T> = () => T;
3
- type SignalSetter<T> = (value: T | ((prev: T) => T)) => void;
4
- type Signal<T> = [SignalGetter<T>, SignalSetter<T>];
5
- type ClassName$1 = string | undefined | null | {
6
- [key: string]: boolean | undefined | null;
7
- } | ClassName$1[];
8
- type AttrValue = ClassName$1 | string | number | boolean | null | undefined;
9
- type TextNode = Node | {
10
- type: 'text';
11
- text: string;
12
- };
13
- declare function text(value: SignalGetter<unknown> | (() => unknown) | unknown): TextNode;
14
- declare function attr(el: Element, name: string, value: SignalGetter<AttrValue> | (() => AttrValue) | AttrValue): () => void;
15
- //#endregion
16
- //#region src/vani/runtime.d.ts
17
- type SSRNode = {
18
- type: 'element';
19
- tag: string;
20
- props: Record<string, any>;
21
- children: SSRNode[];
22
- } | {
23
- type: 'text';
24
- text: string;
25
- } | {
26
- type: 'comment';
27
- text: string;
28
- } | {
29
- type: 'fragment';
30
- children: SSRNode[];
31
- } | {
32
- type: 'component';
33
- instance: ComponentInstance<any>;
34
- };
35
- type VNode = Node | SSRNode;
36
- interface Handle {
37
- /**
38
- * Schedules a render for the component.
39
- * This triggers a re-render on the next microtask.
40
- */
41
- update(options?: UpdateOptions): void;
42
- /**
43
- * Flushes the component render.
44
- * This triggers a re-render immediately.
45
- */
46
- updateSync(options?: UpdateOptions): void;
47
- /**
48
- * Disposes the component: removes the component from the DOM and runs all cleanup functions.
49
- */
50
- dispose(): void;
51
- /**
52
- * Adds a cleanup function that is called when the component is disposed.
53
- */
54
- onCleanup(fn: () => void): void;
55
- /**
56
- * This is purely syntatic sugar, as it is basically the same as running the function
57
- * on the setup phase and calling onCleanup to add a cleanup function.
58
- *
59
- * Using effects is necessary in SSR mode, for side effects to not run on the server
60
- * (e.g. timers, subscriptions, DOM usage, etc.)
61
- *
62
- * Runs a side effect function when the component is mounted.
63
- * The returning function may be a cleanup function that is called when the component is disposed.
64
- *
65
- */
66
- effect(fn: () => void | (() => void)): void;
67
- }
68
- type RenderFn = () => VChild;
69
- type Component<Props = any> = (props: Props, handle: Handle) => RenderFn | Promise<RenderFn>;
70
- type ComponentInstance<Props = any> = {
71
- $$vani: 'component';
72
- component: Component<Props>;
73
- props: Props;
74
- /**
75
- * A key is used to identify the component when it is re-rendered.
76
- * If a key is provided, the component will be re-rendered only if the key changes.
77
- */
78
- key?: string | number;
79
- /**
80
- * A ref is used to get a reference to the component instance.
81
- * The ref is set to the component instance when the component is mounted.
82
- * The ref is set to null when the component is disposed.
83
- */
84
- ref?: ComponentRef;
85
- clientOnly?: boolean;
86
- };
87
- type ComponentInput<Props> = Props & {
88
- key?: string | number;
89
- ref?: ComponentRef;
90
- };
91
- type ComponentMetaProps = {
92
- key?: string | number;
93
- ref?: ComponentRef;
94
- fallback?: RenderFn;
95
- clientOnly?: boolean;
96
- };
97
- type VChild = VNode | ComponentInstance<any> | string | number | null | undefined | false;
98
- type DataAttribute = `data-${string}` | `data${Capitalize<string>}`;
99
- type HtmlTagName = keyof HTMLElementTagNameMap;
100
- type SvgTagName = keyof SVGElementTagNameMap;
101
- type ElementTagName = HtmlTagName | SvgTagName;
102
- type ElementByTag<T extends ElementTagName> = T extends HtmlTagName ? HTMLElementTagNameMap[T] : T extends SvgTagName ? SVGElementTagNameMap[T] : Element;
103
- type SvgProps<T extends SvgTagName = SvgTagName> = BaseProps<T> & {
104
- [key: string]: string | number | boolean | undefined | null | ((...args: any[]) => any);
105
- };
106
- type BaseProps<T extends ElementTagName> = {
107
- className?: ClassName;
108
- style?: string;
109
- ref?: DomRef<ElementByTag<T>>;
110
- } & {
111
- [key: DataAttribute]: string | number | boolean | undefined | null;
112
- };
113
- type HtmlProps<T extends HtmlTagName = HtmlTagName> = BaseProps<T> & Partial<Omit<ElementByTag<T>, 'children' | 'className' | 'style'>>;
114
- type ElementProps<T extends ElementTagName> = T extends SvgTagName ? SvgProps<T> : HtmlProps<Extract<T, HtmlTagName>>;
115
- type ClassName = string | undefined | null | {
116
- [key: string]: boolean | undefined | null;
117
- } | ClassName[];
118
- type ComponentRef = {
119
- current: Handle | null;
120
- };
121
- type DomRef<T extends Element = Element> = {
122
- current: T | null;
123
- };
124
- type UpdateOptions = {
125
- onlyAttributes?: boolean;
126
- };
127
- type RenderMode = 'dom' | 'ssr';
128
- declare function component(fn: Component<void>): (props?: ComponentMetaProps) => ComponentInstance<void>;
129
- declare function component<Props>(fn: Component<Props>): (props: Props & ComponentMetaProps) => ComponentInstance<Props>;
130
- declare function withRenderMode<T>(mode: RenderMode, fn: () => T): T;
131
- declare function getRenderMode(): RenderMode;
132
- declare function signal<T>(value: T): Signal<T>;
133
- declare function derive<T>(fn: () => T): SignalGetter<T>;
134
- declare function effect(fn: () => void | (() => void)): () => void;
135
- type Renderable = Component<any> | ComponentInstance<any>;
136
- declare function renderToDOM(components: Renderable | Renderable[], root: HTMLElement): Handle[];
137
- declare function isComponentInstance(child: VChild): child is ComponentInstance<any>;
138
- declare function renderKeyedChildren(parent: Node, children: Array<ComponentInstance<any>>): void;
139
- declare function classNames(...classes: ClassName[]): string;
140
- declare function el<E extends ElementTagName>(tag: E, props?: ElementProps<E> | VChild | null, ...children: VChild[]): VNode;
141
- declare const fragment: (...children: VChild[]) => {
142
- type: "fragment";
143
- children: SSRNode[];
144
- } | DocumentFragment;
145
- declare function mount<Props>(component: Component<Props>, props: Props): VNode;
146
- /**
147
- * Marks all updates triggered inside the callback as a "transition".
148
- *
149
- * A transition represents non-urgent UI work that can be deferred
150
- * to keep the application responsive.
151
- *
152
- * Updates scheduled inside `startTransition`:
153
- * - do NOT block user interactions
154
- * - are batched separately from urgent updates
155
- * - may be flushed later (e.g. after the current event or during idle time)
156
- *
157
- * Transitions are NOT animations.
158
- * They do not control how updates look, only *when* they are applied.
159
- *
160
- * Typical use cases:
161
- * - Filtering or sorting large lists
162
- * - Rendering expensive subtrees
163
- * - Applying async results that are not immediately visible
164
- *
165
- * Example:
166
- * ```ts
167
- * button({
168
- * onclick: () => {
169
- * // urgent update
170
- * setOpen(true)
171
- * handle.update()
172
- *
173
- * // non-urgent update
174
- * startTransition(() => {
175
- * setItems(filter(items))
176
- * handle.update()
177
- * })
178
- * },
179
- * })
180
- * ```
181
- *
182
- * If multiple transitions are triggered, they are automatically batched.
183
- * Transition updates never interrupt urgent updates.
184
- */
185
- declare function startTransition(fn: () => void): void;
186
- declare function batch(fn: () => void): void;
187
- declare function hydrateToDOM(components: Renderable | Renderable[], root: HTMLElement): Handle[];
188
- declare function isDevMode(): boolean;
189
- //#endregion
190
- export { renderToDOM as A, fragment as C, isDevMode as D, isComponentInstance as E, SignalGetter as F, SignalSetter as I, attr as L, startTransition as M, withRenderMode as N, mount as O, Signal as P, text as R, el as S, hydrateToDOM as T, batch as _, ComponentRef as a, derive as b, ElementProps as c, RenderFn as d, SSRNode as f, VNode as g, VChild as h, ComponentInstance as i, signal as j, renderKeyedChildren as k, Handle as l, UpdateOptions as m, Component as n, DataAttribute as o, SvgProps as p, ComponentInput as r, DomRef as s, ClassName as t, HtmlProps as u, classNames as v, getRenderMode as w, effect as x, component as y };
@@ -1 +0,0 @@
1
- let e=null;const t=new Set;let n=!1;function r(t){!e||e.disposed||e.deps.has(t)||(e.deps.add(t),t.observers.add(e))}function i(e){for(let t of e.deps)t.observers.delete(e);e.deps.clear(),e.cleanup&&=(e.cleanup(),void 0)}function a(t){if(t.disposed)return;i(t);let n=e;e=t;let r=t.fn();e=n,typeof r==`function`&&(t.cleanup=r)}function o(e){e.disposed||(t.add(e),!n&&(n=!0,queueMicrotask(()=>{n=!1;let e=Array.from(t);t.clear();for(let t of e)a(t)})))}function s(e){let t={value:e,observers:new Set};return[()=>(r(t),t.value),e=>{let n=typeof e==`function`?e(t.value):e;if(!Object.is(n,t.value)){t.value=n;for(let e of t.observers)o(e)}}]}function c(e){let t={fn:e,deps:new Set,disposed:!1};return a(t),()=>{t.disposed||(t.disposed=!0,i(t))}}function l(e){let[t,n]=s(e());return c(()=>{n(e())}),t}let u=null;function d(e){u=e}function f(e){let t=()=>typeof e==`function`?e():e,n=String(t()??``);if(!u)return typeof document<`u`?document.createTextNode(n):{type:`text`,text:n};let r=u.createTextNode(n);if(u.getRenderMode()===`ssr`)return r;if(typeof e==`function`){let e=r,n=c(()=>{e.textContent=String(t()??``)});u.addNodeCleanup(e,n)}return r}function ee(e,t,n){if(!u)return()=>{};let r=u;if(r.getRenderMode()===`ssr`||t.startsWith(`on`))return()=>{};let i=e instanceof SVGElement,a=t===`className`?`class`:r.normalizeAttrKey(t,i),o=t=>{if(a===`class`){let n=r.classNames(t);if(!n){e.removeAttribute(`class`);return}e.setAttribute(`class`,n);return}if(t===!0){e.setAttribute(a,``);return}if(t===!1||t==null){e.removeAttribute(a);return}e.setAttribute(a,String(t))};if(typeof n==`function`){let t=c(()=>{o(n())});return r.addNodeCleanup(e,t),t}return o(n),()=>{}}function p(e){let t=e;return t.__vaniKeyed||=new Map,t.__vaniKeyed}function m(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 h=`dom`;function te(e,t){let n=h;h=e;let r=t();return r&&typeof r.finally==`function`?r.finally(()=>{h=n}):(h=n,r)}function g(){return h}function ne(e){return s(e)}function re(e){if(h===`ssr`){let t=e();return()=>t}return l(e)}function ie(e){return h===`ssr`?(e(),()=>{}):c(e)}function _(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 v(e){return _(e)&&e.type===`element`}function ae(e){return _(e)&&e.type===`fragment`}const y=new Set([`svg`,`g`,`path`,`circle`,`rect`,`line`,`polyline`,`polygon`,`ellipse`,`defs`,`clipPath`,`mask`,`pattern`,`linearGradient`,`radialGradient`,`stop`,`use`]);function oe(e){return h===`dom`?y.has(e)?document.createElementNS(`http://www.w3.org/2000/svg`,e):document.createElement(e):{type:`element`,tag:e,props:{},children:[]}}function b(e){return h===`dom`?document.createTextNode(e):{type:`text`,text:e}}function x(e,t){if(h===`dom`){e.appendChild(t);return}(v(e)||ae(e))&&e.children.push(t)}function se(e,t){let n=e;if(!n.__vaniCleanup){n.__vaniCleanup=[t];return}n.__vaniCleanup.push(t)}function ce(e){let t=e,n=t.__vaniCleanup;if(Array.isArray(n)){t.__vaniCleanup=null;for(let e of n)e()}}function S(e,t){let n=e.nextSibling;for(;n&&n!==t;){let e=n.nextSibling;if(n.nodeType===Node.COMMENT_NODE&&n.nodeValue===`vani:start`){let t=n.__vaniHandle;if(t){let r=t.__vaniEnd?.nextSibling??e;t.dispose(),n=r;continue}}ce(n);let t=n;t.__vaniDomRef&&(t.__vaniDomRef.current=null),n.remove(),n=e}}function le(e){if(e==null||e===!1)return document.createComment(`vani:empty`);if(T(e)){let t=document.createDocumentFragment(),n=C(e.component,E(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 C(e,t,n,r){let i=[],a=!1,o,s,c=null,l=t?.clientOnly===!0;if(Y){let e=Z;Z+=1,o=ye(n,e),s=be(o,e)}else o=document.createComment(`vani:start`),s=document.createComment(`vani:end`),n.appendChild(o),n.appendChild(s);let u,d={update(e){if(a)return;let t=d.__vaniUpdateOptions,n=e?.onlyAttributes?{onlyAttributes:!0}:{onlyAttributes:!1};(!t||!t.onlyAttributes||!n.onlyAttributes)&&(d.__vaniUpdateOptions=n),B?G.has(d)||(K.add(d),H>0?W=!0:q()):(K.delete(d),G.add(d),H>0?U=!0:J())},updateSync(e){if(a||!o.parentNode)return;let t=e??d.__vaniUpdateOptions;if(d.__vaniUpdateOptions=void 0,t?.onlyAttributes&&c){let e=F;F=!0;let t;try{t=u()}finally{F=e}if(t instanceof Node){let e=k(t);if(e&&e.tagName===c.tagName){fe(c,e);return}}}S(o,s);let n=le(u()),r=k(n);s.before(n,s),c=r},onCleanup(e){i.push(e)},dispose(){if(!a){a=!0,o.__vaniHandle=null,d.__vaniStart=null,d.__vaniEnd=null,G.delete(d),K.delete(d);for(let e of i)e();i.length=0,S(o,s),o.remove(),s.remove(),u=(()=>document.createComment(`disposed`))}},effect(e){let t=e();typeof t==`function`&&i.push(t)}};if(d.__vaniStart=o,d.__vaniEnd=s,o.__vaniHandle=d,Y&&!l){let n=!1;return u=()=>{if(!n){n=!0;let r=e(t,d);u=r instanceof Promise?()=>document.createComment(`async`):r}return u()},d}let f=e(t,d);return f instanceof Promise?(u=t?.fallback||(()=>document.createComment(`vani:async`)),(!Y||l)&&(r?.initialRender===`sync`?d.updateSync():d.update()),f.then(e=>{a||(u=e,d.update())}),d):(u=f,(!Y||l)&&(r?.initialRender===`sync`?d.updateSync():d.update()),d)}function ue(e){return Array.isArray(e)?e:[e]}function w(e,t){if(!t)throw Error(`[vani] root element not found`);let n=[],r=ue(e);for(let e of r){if(typeof e==`function`){let r=C(e,{},t);n.push(r);continue}let r=C(e.component,E(e),t);n.push(r)}return n}function T(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 de(e){let t=typeof Node<`u`&&e instanceof Node;return typeof e==`object`&&!!e&&!t&&!T(e)&&!_(e)}function E(e){return e.clientOnly?{...e.props??{},clientOnly:!0}:e.props}function D(e){let t=e.__vaniStart,n=e.__vaniEnd;return!t||!n?null:{start:t,end:n}}function O(e,t,n,r=null){let i=document.createDocumentFragment(),a=t;for(;a;){let e=a.nextSibling;if(i.appendChild(a),a===n)break;a=e}e.insertBefore(i,r)}function k(e){if(e.nodeType===Node.ELEMENT_NODE)return e;if(e.nodeType===Node.DOCUMENT_FRAGMENT_NODE){let t=e.firstChild;if(t&&t.nodeType===Node.ELEMENT_NODE&&t.nextSibling===null)return t}return null}function fe(e,t){let n=new Set(t.getAttributeNames());for(let t of e.getAttributeNames())n.has(t)||e.removeAttribute(t);for(let r of n){let n=t.getAttribute(r);e.getAttribute(r)!==n&&(n===null?e.removeAttribute(r):e.setAttribute(r,n))}}function A(e,t){if(e.props===t)return!1;if(!e.props||typeof e.props!=`object`||!t||typeof t!=`object`)return e.props=t,!0;let n=!1,r=e.props,i=t;for(let e in r)e in i||(delete r[e],n=!0);for(let e in i)r[e]!==i[e]&&(r[e]=i[e],n=!0);return n}function j(e,t,n=null){let r=document.createDocumentFragment(),i=C(t.component,E(t),r,{initialRender:`sync`});t.ref&&(t.ref.current=i);let a=D(i)??void 0,o={component:t.component,handle:i,fragment:r,ref:t.ref,props:t.props,start:a?.start,end:a?.end};return e.insertBefore(r,n),o}function M(e,t){if(h===`ssr`){for(let n of t)if(!(n==null||n===!1||n===void 0)){if(T(n)){x(e,{type:`component`,instance:n});continue}if(typeof n==`string`||typeof n==`number`){x(e,b(String(n)));continue}if(_(n)){x(e,n);continue}}return}let n=e;for(let e of t)if(!(e==null||e===!1||e===void 0)){if(T(e)){if(e.key!=null){let t=p(n),r=n.__vaniUsedKeys??=new Set,i=t.get(e.key);i&&i.component!==e.component&&(i.handle.dispose(),i.ref&&(i.ref.current=null),t.delete(e.key),i=void 0),i?(i.ref!==e.ref&&(i.ref&&(i.ref.current=null),i.ref=e.ref),i.ref&&(i.ref.current=i.handle),A(i,e.props)&&i.handle.update(),i.start&&i.end&&O(n,i.start,i.end)):(i=j(n,e,null),t.set(e.key,i)),r.add(e.key);continue}let t=document.createDocumentFragment(),r=C(e.component,E(e),t);e.ref&&(e.ref.current=r),n.appendChild(t);continue}if(typeof e==`string`||typeof e==`number`){n.appendChild(document.createTextNode(String(e)));continue}n.appendChild(e)}let r=n.__vaniKeyed,i=n.__vaniUsedKeys;if(r&&i){for(let[e,t]of r)i.has(e)||(t.handle.dispose(),t.ref&&(t.ref.current=null),r.delete(e));i.clear()}}function pe(e,t){if(h===`ssr`)throw Error(`[vani] renderKeyedChildren is not supported in SSR mode`);let n=e,r=p(n),i=n.__vaniUsedKeys??=new Set,a=n.firstChild;for(let e of t){if(!T(e)||e.key==null)continue;let t=r.get(e.key);t&&t.component!==e.component&&(t.handle.dispose(),t.ref&&(t.ref.current=null),r.delete(e.key),t=void 0);let o=t==null;if(o)t=j(n,e,a),r.set(e.key,t);else{let n=t;n.ref!==e.ref&&(n.ref&&(n.ref.current=null),n.ref=e.ref),n.ref&&(n.ref.current=n.handle),A(n,e.props)&&n.handle.update(),t=n}let s=t;s.start&&s.end&&(!o&&a&&s.start!==a&&O(n,s.start,s.end,a),a=s.end.nextSibling),i.add(e.key)}for(let[e,t]of r)i.has(e)||(t.handle.dispose(),t.ref&&(t.ref.current=null),r.delete(e));i.clear()}function me(e){return typeof SVGElement<`u`&&e instanceof SVGElement}function N(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()}d({getRenderMode:g,createTextNode:e=>b(e),addNodeCleanup:se,classNames:P,normalizeAttrKey:N});function he(e,t){let n=v(e)?y.has(e.tag):me(e);for(let r in t){let i=t[r];if(![`key`,`ref`].includes(r)){if(r===`className`){let t=P(i);v(e)?e.props.class=t:n?e.setAttribute(`class`,t):e.className=t;continue}if(r.startsWith(`on`)&&typeof i==`function`)v(e)||(e[r.toLowerCase()]=i);else if(i===!0)v(e)?e.props[r]=!0:e.setAttribute(r,``);else if(i===!1||i==null)continue;else{let t=N(r,n);v(e)?e.props[t]=String(i):e.setAttribute(t,String(i))}}}}function P(...e){return e.map(e=>{if(!(e==null||e===``))return typeof e==`string`?e.trim():Array.isArray(e)?P(...e):Object.entries(e).filter(([e,t])=>t).map(([e])=>e.trim()).join(` `).trim()}).filter(Boolean).join(` `)}let F=!1;function I(e,t,...n){let r=oe(e);return de(t)?(t.ref&&(!v(r)&&!F?(t.ref.current=r,r.__vaniDomRef=t.ref):t.ref.current=null),he(r,t),F||M(r,n),r):(M(r,[t,...n]),r)}const L=(...e)=>{if(h===`ssr`){let t={type:`fragment`,children:[]};return M(t,e),t}let t=document.createDocumentFragment();return M(t,e),t};function R(e,t){if(h===`ssr`)return{type:`component`,instance:{$$vani:`component`,component:e,props:t}};let n=document.createDocumentFragment();return C(e,t,n),n}let z=!1,B=!1,V=!1,H=0,U=!1,W=!1;const G=new Set,K=new Set;function ge(e){let t=B;B=!0;try{e()}finally{B=t,H>0?W=!0:q()}}function _e(e){H+=1;try{e()}finally{--H,H===0&&(U&&(U=!1,J()),W&&(W=!1,q()))}}function q(){V||(V=!0,setTimeout(()=>{V=!1,ve()},0))}function J(){z||(z=!0,queueMicrotask(()=>{z=!1;for(let e of G)e.updateSync(e.__vaniUpdateOptions);G.clear()}))}function ve(){for(let e of K)e.updateSync(e.__vaniUpdateOptions);K.clear(),K.size>0&&q()}let Y=!1,X=null,Z=0;function Q(e){$()&&console.warn(`[vani] hydration warning: ${e}`)}function ye(e,t){let n=X;(!n||!e.contains(n))&&(n=e.firstChild);let r=!1;for(;n;){if(n.nodeType===Node.COMMENT_NODE&&n.nodeValue===`vani:start`)return r&&Q(`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 Q(`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 be(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 X=n.nextSibling,n;--r}}n=n.nextSibling}throw Q(`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 xe(e,t){let n=[];Y=!0,X=t.firstChild,Z=0;try{n=w(e,t)}catch(e){console.error(`[vani] hydration failed:`,e)}finally{if($()&&X){let e=X,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&&Q(`Unused SSR anchors detected after hydration. Some server-rendered DOM was not claimed by the client runtime.`)}Y=!1,X=null,Z=0}return n}function $(){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{te as _,ie as a,g as c,$ as d,R as f,ge as g,ne as h,re as i,xe as l,w as m,P as n,I as o,pe as p,m as r,L as s,_e as t,T as u,ee as v,f as y};