Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
90891c8
feat(.changeset, packages/vanjs) robust types for better DOM property…
michTheBrandofficial Apr 10, 2026
a12cbd7
feat(packages/vanjs) added svg and mathml tags function directly to v…
michTheBrandofficial Apr 10, 2026
daabfa0
feat(packages/vite-plugin-vanjs) better hmr error message container
michTheBrandofficial Apr 10, 2026
a916ab5
feat(packages/vite-plugin-vanjs) add support for svgTags and mathml t…
michTheBrandofficial Apr 11, 2026
3df3a23
fix(packages/vite-plugin-vanjs, examples/plugin-test) fix comment lin…
michTheBrandofficial Apr 11, 2026
6f992e0
fix(packages/vite-plugin-vanjs, examples/plugin-test) adding support …
michTheBrandofficial Apr 12, 2026
1df36df
fix(packages/vite-plugin-vanjs, examples/plugin-test) adding support …
michTheBrandofficial Apr 12, 2026
f9249d1
fix(packages/vite-plugin-vanjs, examples/plugin-test) adding support …
michTheBrandofficial Apr 12, 2026
36ce0ee
fix(packages/vite-plugin-vanjs, examples/plugin-test) adding support …
michTheBrandofficial Apr 12, 2026
e32c20f
fix(packages/vite-plugin-vanjs, examples/plugin-test) adding support …
michTheBrandofficial Apr 12, 2026
2806423
fix(packages/vite-plugin-vanjs, examples/plugin-test) adding support …
michTheBrandofficial Apr 12, 2026
e593c95
fix(packages/vite-plugin-vanjs/src/plugin.ts) stray debug log removed
michTheBrandofficial Apr 12, 2026
858ccba
fix(packages/create-van-app) bump deps version in create-van-app
michTheBrandofficial Apr 12, 2026
99fa633
fix(.changeset/*.md) added `bump deps version in create-van-app chang…
michTheBrandofficial Apr 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .changeset/deep-brooms-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
"@michthemaker/vanjs": minor
---

Added dedicated SVG and MathML element support

VanJS now provides specialized tag creation for SVG and MathML elements through `van.svgTags` and `van.mathmlTags`, giving you proper type safety and element creation for graphics and mathematical markup alongside regular HTML elements.

```typescript
const { svg, path, circle } = van.svgTags;
const { div, h1, button } = van.tags;
const { math, mi, mo } = van.mathmlTags;

// Create SVG graphics
svg({
viewBox: "0 0 24 24",
width: "24",
height: "24"
},
path({ d: "M12 2L2 7v10c0 5.55 3.84 10 9 10s9-4.45 9-10V7l-10-5z" })
);

// Create mathematical notation
math(mi("x"), mo("+"), mi("y"));
```
43 changes: 0 additions & 43 deletions .changeset/eager-lies-behave.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/funky-humans-open.md

This file was deleted.

7 changes: 7 additions & 0 deletions .changeset/pink-frogs-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@michthemaker/vite-plugin-vanjs": patch
---

Fixed duplicate export statements during hot reload

The Vite plugin was incorrectly duplicating export statements like `export { App }` when processing components for hot module replacement. This has been resolved, ensuring clean exports without duplication.
68 changes: 68 additions & 0 deletions .changeset/small-moles-arrive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
"create-van-app": major
---

Scaffold Your First Van Project using `create-van-app`

> **Compatibility Note:**
> Create Van App requires [Node.js](https://nodejs.org/en/) version 20.19+, 22.12+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.

With NPM:

```bash
npm create van-app@latest
```

With Yarn:

```bash
yarn create van-app
```

With PNPM:

```bash
pnpm create van-app
```

With Bun:

```bash
bun create van-app
```

With Deno:

```bash
deno init --npm van-app
```

Then follow the prompts!

You can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a VanJS + Tailwind project, run:

```bash
# npm 7+, extra double-dash is needed:
npm create van-app@latest my-van-app -- --template vanjs-ts-tailwind

# yarn
yarn create van-app my-van-app --template vanjs-ts-tailwind

# pnpm
pnpm create van-app my-van-app --template vanjs-ts-tailwind

# Bun
bun create van-app my-van-app --template vanjs-ts-tailwind

# Deno
deno init --npm van-app my-van-app --template vanjs-ts-tailwind
```

Currently supported template presets include:

- `vanjs-ts` + `tailwind` ← default
- `vanjs-ts` + `css`
- `vanjs` + `tailwind`
- `vanjs` + `css`

You can use `.` for the project name to scaffold in the current directory.
7 changes: 7 additions & 0 deletions .changeset/ten-moles-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@michthemaker/vite-plugin-vanjs": minor
---

Improved error display during hot module replacement

Error messages during development now display in a better-styled container during hot module replacement, making debugging issues easier to spot and read.
7 changes: 7 additions & 0 deletions .changeset/twelve-trams-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@michthemaker/vanjs": minor
---

Improved type definitions for DOM element properties

Rewrote the VanJS type system to provide better type resolution when setting attributes and properties on DOM elements. This gives you more accurate autocompletion and compile-time checks when using `van.tags`.
8 changes: 8 additions & 0 deletions .changeset/wet-masks-slide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@michthemaker/vite-plugin-vanjs": minor
---

Improved context support during Hot Module Replacement (HMR)

- **Stable contexts across reloads**: `createContext()` is intercepted and keyed by `hmrId`, so the same context object is reused between HMR updates.
- **Context snapshot + replay**: active context stacks are captured on `registerRender` and replayed on `rerender`, allowing `useContext` to keep working even when called outside the original render call tree.
8 changes: 8 additions & 0 deletions .changeset/wicked-meteors-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@michthemaker/vite-plugin-vanjs": minor
---

Better handling for multiple and aliased exports

- Multiple named exports like `export { Foo, Bar }` are now correctly preserved during transformation.
- Aliased exports such as `export { Foo as Bar }` now generate the correct wrapper and transform logic.
2 changes: 1 addition & 1 deletion .zed/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
// settings for all languages
"languages": {
"TypeScript": {
"language_servers": ["tsgo"]
"language_servers": ["vtsls", "oxfmt"]
},
"JavaScript": {
"language_servers": ["tsgo", "vtsls"],
Expand Down
16 changes: 14 additions & 2 deletions apps/examples/plugin-test/index.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
<!doctype html>
<html lang="en">
<html lang="en" class="no-scrollbar">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Example Repository VanJS</title>
<style>
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>
</head>
<body style="overflow-y: auto; height: 100dvh; width: 100dvw">
<body
class="no-scrollbar"
style="overflow-y: auto; height: 100dvh; width: 100dvw"
>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
68 changes: 68 additions & 0 deletions apps/examples/plugin-test/src/App.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import van, { type Ref } from "@michthemaker/vanjs";
import {
QueryContextProvider,
ThemeContextProvider,
useQueryFt,
useTheme,
} from "./context-test";
import { GifModal } from "./GifModal";
import { UserProfile } from "./UserProfile";

const { div, h1, p, span, button } = van.tags;

// Edge case 1: nested providers (ThemeContext inside QueryContext)
// Expected: both contexts available to deep children on rerender
export const App = (props: { name: string }) => {
const myName = van.state("Mich");
const ref: Ref<HTMLHeadingElement> = { current: null };

return QueryContextProvider(() =>
ThemeContextProvider(() =>
div(
{
style:
"padding-inline: 4px; font-family: sans-serif; margin: 0; overflow: auto;",
class: "no-scrollbar",
},
h1(
{
style:
"width: 90%; color: #333; border-bottom: 2px solid #eee; padding-bottom: 10px;",
ref: ref,
},
"VanJS HMR Context Edge Cases — ",
props.name,
" ",
myName
),

// Edge case 1: child component using ONE context (QueryContext)
// Save GifModal.ts → should rerender fine with QueryContext snapshot
GifModal(),

// Edge case 2: inline fn using BOTH contexts simultaneously
// Save App.ts → should have both QueryContext + ThemeContext in snapshot
() => {
const query = useQueryFt();
const theme = useTheme();
return span(
{ style: `color: ${theme.color};` },
`query=${query.name} dark=${theme.dark}`
);
},

// Edge case 3: same context used twice in same tree
() => {
const a = useQueryFt();
const b = useQueryFt();
return p(`same context twice: ${a.name} === ${b.name}`);
},

// Edge case 4: component that owns its OWN Provider internally
// UserBadge inside UserProfile uses UserContext
// Save UserProfile.ts → UserBadge should rerender with UserContext snapshot
UserProfile()
)
)
);
};
13 changes: 13 additions & 0 deletions apps/examples/plugin-test/src/GifModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// just a file using dummy context to test context with hmr

import van from "@michthemaker/vanjs";
import { useQueryFt } from "./context-test";

const { p } = van.tags;

const GifModal = () => {
const queryContext = useQueryFt();
return p(queryContext.name, "name is usss and them eight");
};

export { GifModal };
34 changes: 34 additions & 0 deletions apps/examples/plugin-test/src/UserProfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Edge case: component that owns its own Context.Provider
// and has a deeply nested consumer in same file

import van from "@michthemaker/vanjs";
import { UserContext, useUser } from "./context-test";

const { div, p, span, strong } = van.tags;

// Deep consumer — no Provider above it in its own file
// relies on snapshot replay during HMR rerender
const UserBadge = () => {
const user = useUser();
return span(
{ style: "background: #eee; padding: 4px 8px; border-radius: 4px;" },
strong(user.role + "me and you"),
" — ",
user.username
);
};

// Owns the Provider + renders UserBadge inside it
const UserProfile = () => {
const userState = van.state({ username: "michthemaker", role: "admin" });
return UserContext.Provider(userState, () =>
div(
{ style: "border: 1px solid #ccc; padding: 12px; margin-top: 12px;" },
p("UserProfile component owns this Provider"),
UserBadge(),
p(() => `role is: ${userState.val.role}`)
)
);
};

export { UserProfile, UserBadge };
1 change: 0 additions & 1 deletion apps/examples/plugin-test/src/barrel-export.ts

This file was deleted.

Loading
Loading