vite-plugin-vanjs
Version:
A mini meta-framework for VanJS powered by Vite
224 lines (202 loc) • 5.84 kB
TypeScript
/// <reference path="global.d.ts" />
import type {
Element as VElement,
TagFunc as IsoTagFunc,
} from "mini-van-plate/van-plate";
import van from "vanjs-core";
import type {
ChildDom,
Primitive,
Props,
PropsWithKnownKeys,
PropValueOrDerived,
State,
} from "vanjs-core";
// type VanElement = VElement | Exclude<Primitive, boolean | undefined>;
type DOMElement = globalThis.Element;
type PrimitiveChild = Primitive | State<Primitive | undefined | null>;
type VanElement =
| SVGElement
| HTMLElement
| DOMElement
| Node
| VElement
| PrimitiveChild;
export type VanNode =
| VanElement
| VanNode[]
| (() => VanNode)
| null
| undefined;
type ComponentProps1<T> =
& Props
& PropsWithKnownKeys<T>;
type ComponentProps<K extends keyof HTMLElementTagNameMap> =
& Props
& PropsWithKnownKeys<HTMLElementTagNameMap[K]>;
export type VanComponent<
K extends keyof HTMLElementTagNameMap = "div",
O extends (Record<string, PropValueOrDerived> | undefined) = undefined,
> = {
(
props?: O extends object ? ComponentProps<K> & Partial<O>
: ComponentProps<K>,
...children: ChildDom[]
): HTMLElementTagNameMap[K];
};
// router.mjs
/**
* A virtual component that renders the current route
* in your VanJS application. It must be used in your main component.
*
* @example
* import { Router } from '@vanjs/router';
*
* export const App = () => {
* return Router(); // or <Router /> for JSX
* }
*/
// export const Router: JSX.Component<HTMLElement> & VanComponent<HTMLElement>;
// export function Router(props?: ComponentProps<HTMLElement>): HTMLElement;
// export function Router(
// props?: JSX.IntrinsicElements["main"] & { children: null },
// ): HTMLElement;
export const Router:
& VanComponent<"main">
& JSX.Component<"main">;
// a.mjs
/**
* A virtual component that creates an anchor element
* that navigates to the specified href when clicked.
*
* @example
* import { A } from '@vanjs/router';
* import van from 'vanjs-core';
*
* export const Navigation = () => {
* const { nav } = van.tags
* return nav(
* A({ href="/" }, "Home"), // or <A href="/">Home</A> with JSX
* A({ href="/about" }, "About"), // or <A href="/about">About</A> with JSX
* // ...other children
* );
* }
*/
export const A:
& VanComponent<"a">
& JSX.Component<"a">;
// helpers.mjs
/**
* Navigates to the specified href in the client and sets the router state.
* Keep in mind that the router handles the search params and hash.
*
* @param href the URL to navigate to
* @param options when true, will replace the current history entry
*/
export const navigate: (
href: string,
options?: { replace?: boolean },
) => void;
/**
* A client only helper function that reloads the current page.
*/
export const reload: () => void;
/**
* A helper function that redirects the user to the specified href.
* When called in the server, it will return a function that will redirect the user
* to the specified href when called.
* @param {string | undefined} href the URL to redirect to
*/
export const redirect: (href?: string) => void | (() => void);
// routes.mjs
export type RouteEntry = {
path: string;
component: Promise<ComponentModule>;
preload?: (params?: Record<string, string>) => void;
load?: (params?: Record<string, string>) => void;
};
export type RouteProps = {
path: string;
component:
| (() => HTMLElementTagNameMap[unknown] | HTMLElementTagNameMap[unknown][])
| VanComponent
| (() => ComponentModule);
preload?: (params?: Record<string, string>) => void;
load?: (params?: Record<string, string>) => void;
};
export const routes: RouteEntry[];
/**
* Registers a new route in the router state.
* @param route the route to register
*
* @example
* import { Route, lazy } from '@vanjs/router';
* import Home from './pages/Home';
* import NotFound from './pages/NotFound';
*
* Route({ path: '/', component: Home });
* Route({ path: '/about', component: lazy(() => import("./pages/About.ts")) });
* Route({ path: '*', component: NotFound });
*/
export const Route: (route: RouteProps) => void;
// state.mjs
export type RouterState = {
pathname: string;
searchParams: URLSearchParams;
params: Record<string, string>;
};
/**
* A reactive object that holds the current router state.
* This state is maintained by both server and client.
*/
export const routerState: {
pathname: van.state<RouterState.pathname>;
searchParams: van.state<RouterState.searchParams>;
params?: van.state<RouterState.params>;
};
/**
* Sets the router state to the specified href.
* @param href the URL to navigate to
* @param search the search string
* @param params the route params object
*/
export const setRouterState: (
href: string,
search?: string,
params?: Record<string, string>,
) => void;
/**
* Merge the children of an Element or an array of elements with an optional array of children
* into the childen of a single HTMLFragmentElement element.
* @param source
* @param {...VanNode[]} children
*/
export const unwrap: (
source:
| VanNode
| IsoTagFunc
| VanNode[]
| IsoTagFunc[]
| (() => IsoTagFunc | IsoTagFunc[] | VanNode | VanNode[]),
...children: VanNode[]
) => VanNode;
export type ComponentModule = {
component: VanComponent | JSX.Element;
route: Pick<RouteEntry, "load" | "preload">;
};
export type DynamicModule = {
Page: VanComponent | JSX.Element;
default?: VanComponent | JSX.Element;
route?: Pick<RouteEntry, "load" | "preload">;
};
export type LazyComponent = Promise<DynamicModule>;
/**
* Registers a lazy component.
* @param importFn
*/
export const lazy: (importFn: () => LazyComponent) => () => ComponentModule;
/**
* Fixes the URL of a route.
* @param url
*/
export const fixRouteUrl: (url: string) => string;