cajoa 0.3.0 → 0.4.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 +45 -4
- package/dist/index.cjs +111 -10
- package/dist/index.d.cts +29 -2
- package/dist/index.d.ts +29 -2
- package/dist/index.js +102 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
A small, beginner-friendly frontend framework built on **signals** and **JSX**.
|
|
4
4
|
No virtual DOM, no hooks rules, no re-rendering components.
|
|
5
5
|
|
|
6
|
-
> ⚠️ **v0.
|
|
6
|
+
> ⚠️ **v0.4 (early stage).** The API may still change. Not production-ready yet.
|
|
7
7
|
|
|
8
8
|
## Why Cajoa?
|
|
9
9
|
|
|
@@ -80,6 +80,32 @@ const [todos, setTodos] = createSignal([{ id: 1, text: "Learn Cajoa" }]);
|
|
|
80
80
|
</Show>;
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
+
## Routing
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { render, Router, Route, Link, useParams } from "cajoa";
|
|
87
|
+
|
|
88
|
+
const User = () => <h1>User {useParams().id}</h1>;
|
|
89
|
+
|
|
90
|
+
render(
|
|
91
|
+
() => (
|
|
92
|
+
<div>
|
|
93
|
+
<nav>
|
|
94
|
+
<Link href="/">Home</Link> <Link href="/users/7">User 7</Link>
|
|
95
|
+
</nav>
|
|
96
|
+
<Router>
|
|
97
|
+
<Route path="/" component={() => <h1>Home</h1>} />
|
|
98
|
+
<Route path="/users/:id" component={User} />
|
|
99
|
+
<Route path="*" component={() => <h1>Not found</h1>} />
|
|
100
|
+
</Router>
|
|
101
|
+
</div>
|
|
102
|
+
),
|
|
103
|
+
document.getElementById("app")!,
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Routes are matched in order, so put `path="*"` last.
|
|
108
|
+
|
|
83
109
|
## API
|
|
84
110
|
|
|
85
111
|
### Reactivity
|
|
@@ -121,16 +147,31 @@ const [todos, setTodos] = createSignal([{ id: 1, text: "Learn Cajoa" }]);
|
|
|
121
147
|
| `provide(ctx, value, fn)` | Runs `fn`; everything created inside can read `value`. |
|
|
122
148
|
| `useContext(ctx)` | Reads the nearest provided value (or the default). |
|
|
123
149
|
|
|
150
|
+
### Router
|
|
151
|
+
|
|
152
|
+
| Function | What it does |
|
|
153
|
+
| ---------------------------- | ---------------------------------------------------------- |
|
|
154
|
+
| `<Router>` | Renders the first `<Route>` that matches the current path. |
|
|
155
|
+
| `<Route path component>` | Maps a path (`/users/:id`, `*`) to a component. |
|
|
156
|
+
| `<Link href>` | An `<a>` that navigates without reloading the page. |
|
|
157
|
+
| `navigate(to, { replace? })` | Navigates programmatically. |
|
|
158
|
+
| `useParams()` | Reads the route params (`{ id: "7" }`). |
|
|
159
|
+
| `usePath()` | Returns a signal getter for the current pathname. |
|
|
160
|
+
| `untrack(fn)` | Runs `fn` without subscribing to signals. |
|
|
161
|
+
|
|
124
162
|
## Good to know
|
|
125
163
|
|
|
126
164
|
- `For` uses the item itself as the key by default. If you pass `key`, items with the same key are **not** re-rendered when their data changes, so keys must be unique and the item should hold its own signals if it needs to update.
|
|
127
165
|
- `useContext` only works while a component is being created (or inside `onMount` / effects). Read it at the top of your component and use the value later in handlers.
|
|
128
166
|
- Updating an object in place will not trigger effects. Set a new object instead.
|
|
167
|
+
- Fragments (`<>...</>`) work anywhere, but inside `<For>` the child must be a single element, because `For` reuses that node.
|
|
129
168
|
|
|
130
169
|
## Known limitations
|
|
131
170
|
|
|
132
|
-
- No Fragments (`<>...</>`) yet. Wrap siblings in an element.
|
|
133
171
|
- No SSR.
|
|
172
|
+
- Router: pathname only (no query/hash handling), no nested routes, no `base` path.
|
|
173
|
+
- `<Show>` and `<Router>` return a function, so they must sit inside an element, not be the root returned by `render`.
|
|
174
|
+
- Single-page apps need a server fallback to `index.html` for unknown paths.
|
|
134
175
|
- `createMemo` can show a brief inconsistent state when memos depend on each other.
|
|
135
176
|
- `set` calls are not batched automatically inside event handlers. Wrap them in `batch()`.
|
|
136
177
|
|
|
@@ -143,9 +184,9 @@ const [todos, setTodos] = createSignal([{ id: 1, text: "Learn Cajoa" }]);
|
|
|
143
184
|
- [x] `createMemo`, `batch`
|
|
144
185
|
- [x] Context
|
|
145
186
|
- [x] JSX support
|
|
146
|
-
- [
|
|
187
|
+
- [x] Fragments
|
|
147
188
|
- [ ] Vite plugin (removes the two rules above)
|
|
148
|
-
- [
|
|
189
|
+
- [x] Router
|
|
149
190
|
- [ ] SSR
|
|
150
191
|
|
|
151
192
|
## Development
|
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
For: () => For,
|
|
24
|
+
Fragment: () => Fragment,
|
|
25
|
+
Link: () => Link,
|
|
26
|
+
Route: () => Route,
|
|
27
|
+
Router: () => Router,
|
|
24
28
|
Show: () => Show,
|
|
25
29
|
batch: () => batch,
|
|
26
30
|
createContext: () => createContext,
|
|
@@ -32,11 +36,15 @@ __export(index_exports, {
|
|
|
32
36
|
jsx: () => jsx,
|
|
33
37
|
jsxDEV: () => jsxDEV,
|
|
34
38
|
jsxs: () => jsxs,
|
|
39
|
+
navigate: () => navigate,
|
|
35
40
|
onCleanup: () => onCleanup,
|
|
36
41
|
onMount: () => onMount,
|
|
37
42
|
provide: () => provide,
|
|
38
43
|
render: () => render,
|
|
39
|
-
|
|
44
|
+
untrack: () => untrack,
|
|
45
|
+
useContext: () => useContext,
|
|
46
|
+
useParams: () => useParams,
|
|
47
|
+
usePath: () => usePath
|
|
40
48
|
});
|
|
41
49
|
module.exports = __toCommonJS(index_exports);
|
|
42
50
|
|
|
@@ -172,6 +180,15 @@ function useContext(ctx) {
|
|
|
172
180
|
}
|
|
173
181
|
return ctx.defaultValue;
|
|
174
182
|
}
|
|
183
|
+
function untrack(fn) {
|
|
184
|
+
const prev = currentEffect;
|
|
185
|
+
currentEffect = null;
|
|
186
|
+
try {
|
|
187
|
+
return fn();
|
|
188
|
+
} finally {
|
|
189
|
+
currentEffect = prev;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
175
192
|
|
|
176
193
|
// src/dom/h.ts
|
|
177
194
|
function h(tag, props, ...children) {
|
|
@@ -254,9 +271,17 @@ function render(component, container) {
|
|
|
254
271
|
});
|
|
255
272
|
}
|
|
256
273
|
|
|
274
|
+
// src/reactivity/memo.ts
|
|
275
|
+
function createMemo(fn) {
|
|
276
|
+
const [value, setValue] = createSignal(void 0);
|
|
277
|
+
createEffect(() => setValue(() => fn()));
|
|
278
|
+
return value;
|
|
279
|
+
}
|
|
280
|
+
|
|
257
281
|
// src/components/show.ts
|
|
258
282
|
function Show(props) {
|
|
259
|
-
|
|
283
|
+
const visible = createMemo(() => !!props.when());
|
|
284
|
+
return () => visible() ? untrack(() => props.children()) : untrack(() => props.fallback?.() ?? null);
|
|
260
285
|
}
|
|
261
286
|
|
|
262
287
|
// src/components/for.ts
|
|
@@ -290,13 +315,6 @@ function For(props) {
|
|
|
290
315
|
};
|
|
291
316
|
}
|
|
292
317
|
|
|
293
|
-
// src/reactivity/memo.ts
|
|
294
|
-
function createMemo(fn) {
|
|
295
|
-
const [value, setValue] = createSignal(void 0);
|
|
296
|
-
createEffect(() => setValue(() => fn()));
|
|
297
|
-
return value;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
318
|
// src/jsx-runtime.ts
|
|
301
319
|
function jsx(type, props) {
|
|
302
320
|
if (typeof type === "function") return type(props ?? {});
|
|
@@ -306,9 +324,88 @@ function jsx(type, props) {
|
|
|
306
324
|
}
|
|
307
325
|
var jsxs = jsx;
|
|
308
326
|
var jsxDEV = jsx;
|
|
327
|
+
function Fragment(props) {
|
|
328
|
+
const frag = document.createDocumentFragment();
|
|
329
|
+
appendChildren(frag, props.children === void 0 ? [] : [props.children]);
|
|
330
|
+
return frag;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/router.ts
|
|
334
|
+
var read = () => typeof location === "undefined" ? "/" : location.pathname;
|
|
335
|
+
var [path, setPath] = createSignal(read());
|
|
336
|
+
var listening = false;
|
|
337
|
+
function listen() {
|
|
338
|
+
if (listening || typeof window === "undefined") return;
|
|
339
|
+
listening = true;
|
|
340
|
+
window.addEventListener("popstate", () => setPath(read()));
|
|
341
|
+
}
|
|
342
|
+
function navigate(to, options = {}) {
|
|
343
|
+
if (new URL(to, location.href).href === location.href) return;
|
|
344
|
+
history[options.replace ? "replaceState" : "pushState"](null, "", to);
|
|
345
|
+
setPath(read());
|
|
346
|
+
}
|
|
347
|
+
var usePath = () => path;
|
|
348
|
+
var Params = createContext({});
|
|
349
|
+
function useParams() {
|
|
350
|
+
return useContext(Params);
|
|
351
|
+
}
|
|
352
|
+
var split = (s) => s.split("/").filter(Boolean);
|
|
353
|
+
function decode(s) {
|
|
354
|
+
try {
|
|
355
|
+
return decodeURIComponent(s);
|
|
356
|
+
} catch {
|
|
357
|
+
return s;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function match(pattern, pathname) {
|
|
361
|
+
if (pattern === "*") return {};
|
|
362
|
+
const p = split(pattern);
|
|
363
|
+
const u = split(pathname);
|
|
364
|
+
if (p.length !== u.length) return null;
|
|
365
|
+
const params = {};
|
|
366
|
+
for (let i = 0; i < p.length; i++) {
|
|
367
|
+
if (p[i].startsWith(":")) params[p[i].slice(1)] = decode(u[i]);
|
|
368
|
+
else if (p[i] !== u[i]) return null;
|
|
369
|
+
}
|
|
370
|
+
return params;
|
|
371
|
+
}
|
|
372
|
+
function Route(props) {
|
|
373
|
+
return { __route: true, path: props.path, component: props.component };
|
|
374
|
+
}
|
|
375
|
+
function Router(props) {
|
|
376
|
+
listen();
|
|
377
|
+
const routes = [props.children].flat(Infinity).filter(
|
|
378
|
+
(r) => r?.__route === true
|
|
379
|
+
);
|
|
380
|
+
return () => {
|
|
381
|
+
const current = path();
|
|
382
|
+
for (const route of routes) {
|
|
383
|
+
const params = match(route.path, current);
|
|
384
|
+
if (params) {
|
|
385
|
+
return untrack(() => provide(Params, params, () => route.component()));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return null;
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function Link(props) {
|
|
392
|
+
const { href, children, ...rest } = props;
|
|
393
|
+
const onClick = (e) => {
|
|
394
|
+
if (/^[a-z][a-z0-9+.-]*:|^\/\//i.test(href)) return;
|
|
395
|
+
if (e.defaultPrevented || e.button !== 0) return;
|
|
396
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
397
|
+
e.preventDefault();
|
|
398
|
+
navigate(href);
|
|
399
|
+
};
|
|
400
|
+
return h("a", { ...rest, href, onClick }, children);
|
|
401
|
+
}
|
|
309
402
|
// Annotate the CommonJS export names for ESM import in node:
|
|
310
403
|
0 && (module.exports = {
|
|
311
404
|
For,
|
|
405
|
+
Fragment,
|
|
406
|
+
Link,
|
|
407
|
+
Route,
|
|
408
|
+
Router,
|
|
312
409
|
Show,
|
|
313
410
|
batch,
|
|
314
411
|
createContext,
|
|
@@ -320,9 +417,13 @@ var jsxDEV = jsx;
|
|
|
320
417
|
jsx,
|
|
321
418
|
jsxDEV,
|
|
322
419
|
jsxs,
|
|
420
|
+
navigate,
|
|
323
421
|
onCleanup,
|
|
324
422
|
onMount,
|
|
325
423
|
provide,
|
|
326
424
|
render,
|
|
327
|
-
|
|
425
|
+
untrack,
|
|
426
|
+
useContext,
|
|
427
|
+
useParams,
|
|
428
|
+
usePath
|
|
328
429
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -12,6 +12,7 @@ interface Context<T> {
|
|
|
12
12
|
declare function createContext<T>(defaultValue: T): Context<T>;
|
|
13
13
|
declare function provide<T, R>(ctx: Context<T>, value: T, fn: () => R): R;
|
|
14
14
|
declare function useContext<T>(ctx: Context<T>): T;
|
|
15
|
+
declare function untrack<T>(fn: () => T): T;
|
|
15
16
|
|
|
16
17
|
type Child = string | number | boolean | null | undefined | Node | (() => unknown) | Child[];
|
|
17
18
|
declare function h(tag: string, props: Record<string, any> | null, ...children: Child[]): HTMLElement;
|
|
@@ -44,6 +45,32 @@ declare namespace JSX {
|
|
|
44
45
|
children: {};
|
|
45
46
|
}
|
|
46
47
|
}
|
|
48
|
+
declare function Fragment(props: {
|
|
49
|
+
children?: Child;
|
|
50
|
+
}): DocumentFragment;
|
|
47
51
|
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
declare function navigate(to: string, options?: {
|
|
53
|
+
replace?: boolean;
|
|
54
|
+
}): void;
|
|
55
|
+
declare const usePath: () => () => string;
|
|
56
|
+
declare function useParams(): Record<string, string>;
|
|
57
|
+
interface RouteDef {
|
|
58
|
+
__route: true;
|
|
59
|
+
path: string;
|
|
60
|
+
component: () => unknown;
|
|
61
|
+
}
|
|
62
|
+
declare function Route(props: {
|
|
63
|
+
path: string;
|
|
64
|
+
component: () => unknown;
|
|
65
|
+
}): RouteDef;
|
|
66
|
+
declare function Router(props: {
|
|
67
|
+
children?: unknown;
|
|
68
|
+
}): () => unknown;
|
|
69
|
+
declare function Link(props: {
|
|
70
|
+
href: string;
|
|
71
|
+
children?: unknown;
|
|
72
|
+
[key: string]: unknown;
|
|
73
|
+
}): HTMLElement;
|
|
74
|
+
|
|
75
|
+
export { For, Fragment, JSX, Link, Route, Router, Show, batch, createContext, createEffect, createMemo, createRoot, createSignal, h, jsx, jsxDEV, jsxs, navigate, onCleanup, onMount, provide, render, untrack, useContext, useParams, usePath };
|
|
76
|
+
export type { Child, Context, RouteDef };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ interface Context<T> {
|
|
|
12
12
|
declare function createContext<T>(defaultValue: T): Context<T>;
|
|
13
13
|
declare function provide<T, R>(ctx: Context<T>, value: T, fn: () => R): R;
|
|
14
14
|
declare function useContext<T>(ctx: Context<T>): T;
|
|
15
|
+
declare function untrack<T>(fn: () => T): T;
|
|
15
16
|
|
|
16
17
|
type Child = string | number | boolean | null | undefined | Node | (() => unknown) | Child[];
|
|
17
18
|
declare function h(tag: string, props: Record<string, any> | null, ...children: Child[]): HTMLElement;
|
|
@@ -44,6 +45,32 @@ declare namespace JSX {
|
|
|
44
45
|
children: {};
|
|
45
46
|
}
|
|
46
47
|
}
|
|
48
|
+
declare function Fragment(props: {
|
|
49
|
+
children?: Child;
|
|
50
|
+
}): DocumentFragment;
|
|
47
51
|
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
declare function navigate(to: string, options?: {
|
|
53
|
+
replace?: boolean;
|
|
54
|
+
}): void;
|
|
55
|
+
declare const usePath: () => () => string;
|
|
56
|
+
declare function useParams(): Record<string, string>;
|
|
57
|
+
interface RouteDef {
|
|
58
|
+
__route: true;
|
|
59
|
+
path: string;
|
|
60
|
+
component: () => unknown;
|
|
61
|
+
}
|
|
62
|
+
declare function Route(props: {
|
|
63
|
+
path: string;
|
|
64
|
+
component: () => unknown;
|
|
65
|
+
}): RouteDef;
|
|
66
|
+
declare function Router(props: {
|
|
67
|
+
children?: unknown;
|
|
68
|
+
}): () => unknown;
|
|
69
|
+
declare function Link(props: {
|
|
70
|
+
href: string;
|
|
71
|
+
children?: unknown;
|
|
72
|
+
[key: string]: unknown;
|
|
73
|
+
}): HTMLElement;
|
|
74
|
+
|
|
75
|
+
export { For, Fragment, JSX, Link, Route, Router, Show, batch, createContext, createEffect, createMemo, createRoot, createSignal, h, jsx, jsxDEV, jsxs, navigate, onCleanup, onMount, provide, render, untrack, useContext, useParams, usePath };
|
|
76
|
+
export type { Child, Context, RouteDef };
|
package/dist/index.js
CHANGED
|
@@ -130,6 +130,15 @@ function useContext(ctx) {
|
|
|
130
130
|
}
|
|
131
131
|
return ctx.defaultValue;
|
|
132
132
|
}
|
|
133
|
+
function untrack(fn) {
|
|
134
|
+
const prev = currentEffect;
|
|
135
|
+
currentEffect = null;
|
|
136
|
+
try {
|
|
137
|
+
return fn();
|
|
138
|
+
} finally {
|
|
139
|
+
currentEffect = prev;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
133
142
|
|
|
134
143
|
// src/dom/h.ts
|
|
135
144
|
function h(tag, props, ...children) {
|
|
@@ -212,9 +221,17 @@ function render(component, container) {
|
|
|
212
221
|
});
|
|
213
222
|
}
|
|
214
223
|
|
|
224
|
+
// src/reactivity/memo.ts
|
|
225
|
+
function createMemo(fn) {
|
|
226
|
+
const [value, setValue] = createSignal(void 0);
|
|
227
|
+
createEffect(() => setValue(() => fn()));
|
|
228
|
+
return value;
|
|
229
|
+
}
|
|
230
|
+
|
|
215
231
|
// src/components/show.ts
|
|
216
232
|
function Show(props) {
|
|
217
|
-
|
|
233
|
+
const visible = createMemo(() => !!props.when());
|
|
234
|
+
return () => visible() ? untrack(() => props.children()) : untrack(() => props.fallback?.() ?? null);
|
|
218
235
|
}
|
|
219
236
|
|
|
220
237
|
// src/components/for.ts
|
|
@@ -248,13 +265,6 @@ function For(props) {
|
|
|
248
265
|
};
|
|
249
266
|
}
|
|
250
267
|
|
|
251
|
-
// src/reactivity/memo.ts
|
|
252
|
-
function createMemo(fn) {
|
|
253
|
-
const [value, setValue] = createSignal(void 0);
|
|
254
|
-
createEffect(() => setValue(() => fn()));
|
|
255
|
-
return value;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
268
|
// src/jsx-runtime.ts
|
|
259
269
|
function jsx(type, props) {
|
|
260
270
|
if (typeof type === "function") return type(props ?? {});
|
|
@@ -264,8 +274,87 @@ function jsx(type, props) {
|
|
|
264
274
|
}
|
|
265
275
|
var jsxs = jsx;
|
|
266
276
|
var jsxDEV = jsx;
|
|
277
|
+
function Fragment(props) {
|
|
278
|
+
const frag = document.createDocumentFragment();
|
|
279
|
+
appendChildren(frag, props.children === void 0 ? [] : [props.children]);
|
|
280
|
+
return frag;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// src/router.ts
|
|
284
|
+
var read = () => typeof location === "undefined" ? "/" : location.pathname;
|
|
285
|
+
var [path, setPath] = createSignal(read());
|
|
286
|
+
var listening = false;
|
|
287
|
+
function listen() {
|
|
288
|
+
if (listening || typeof window === "undefined") return;
|
|
289
|
+
listening = true;
|
|
290
|
+
window.addEventListener("popstate", () => setPath(read()));
|
|
291
|
+
}
|
|
292
|
+
function navigate(to, options = {}) {
|
|
293
|
+
if (new URL(to, location.href).href === location.href) return;
|
|
294
|
+
history[options.replace ? "replaceState" : "pushState"](null, "", to);
|
|
295
|
+
setPath(read());
|
|
296
|
+
}
|
|
297
|
+
var usePath = () => path;
|
|
298
|
+
var Params = createContext({});
|
|
299
|
+
function useParams() {
|
|
300
|
+
return useContext(Params);
|
|
301
|
+
}
|
|
302
|
+
var split = (s) => s.split("/").filter(Boolean);
|
|
303
|
+
function decode(s) {
|
|
304
|
+
try {
|
|
305
|
+
return decodeURIComponent(s);
|
|
306
|
+
} catch {
|
|
307
|
+
return s;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function match(pattern, pathname) {
|
|
311
|
+
if (pattern === "*") return {};
|
|
312
|
+
const p = split(pattern);
|
|
313
|
+
const u = split(pathname);
|
|
314
|
+
if (p.length !== u.length) return null;
|
|
315
|
+
const params = {};
|
|
316
|
+
for (let i = 0; i < p.length; i++) {
|
|
317
|
+
if (p[i].startsWith(":")) params[p[i].slice(1)] = decode(u[i]);
|
|
318
|
+
else if (p[i] !== u[i]) return null;
|
|
319
|
+
}
|
|
320
|
+
return params;
|
|
321
|
+
}
|
|
322
|
+
function Route(props) {
|
|
323
|
+
return { __route: true, path: props.path, component: props.component };
|
|
324
|
+
}
|
|
325
|
+
function Router(props) {
|
|
326
|
+
listen();
|
|
327
|
+
const routes = [props.children].flat(Infinity).filter(
|
|
328
|
+
(r) => r?.__route === true
|
|
329
|
+
);
|
|
330
|
+
return () => {
|
|
331
|
+
const current = path();
|
|
332
|
+
for (const route of routes) {
|
|
333
|
+
const params = match(route.path, current);
|
|
334
|
+
if (params) {
|
|
335
|
+
return untrack(() => provide(Params, params, () => route.component()));
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return null;
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function Link(props) {
|
|
342
|
+
const { href, children, ...rest } = props;
|
|
343
|
+
const onClick = (e) => {
|
|
344
|
+
if (/^[a-z][a-z0-9+.-]*:|^\/\//i.test(href)) return;
|
|
345
|
+
if (e.defaultPrevented || e.button !== 0) return;
|
|
346
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
347
|
+
e.preventDefault();
|
|
348
|
+
navigate(href);
|
|
349
|
+
};
|
|
350
|
+
return h("a", { ...rest, href, onClick }, children);
|
|
351
|
+
}
|
|
267
352
|
export {
|
|
268
353
|
For,
|
|
354
|
+
Fragment,
|
|
355
|
+
Link,
|
|
356
|
+
Route,
|
|
357
|
+
Router,
|
|
269
358
|
Show,
|
|
270
359
|
batch,
|
|
271
360
|
createContext,
|
|
@@ -277,9 +366,13 @@ export {
|
|
|
277
366
|
jsx,
|
|
278
367
|
jsxDEV,
|
|
279
368
|
jsxs,
|
|
369
|
+
navigate,
|
|
280
370
|
onCleanup,
|
|
281
371
|
onMount,
|
|
282
372
|
provide,
|
|
283
373
|
render,
|
|
284
|
-
|
|
374
|
+
untrack,
|
|
375
|
+
useContext,
|
|
376
|
+
useParams,
|
|
377
|
+
usePath
|
|
285
378
|
};
|