zenith 1.0.0-beta.13 → 1.0.0-beta.14
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 +71 -23
- package/dist/types/helpers/closest.d.ts +14 -0
- package/dist/types/helpers/cls.d.ts +8 -0
- package/dist/types/helpers/derived.d.ts +19 -0
- package/dist/types/helpers/html.d.ts +20 -0
- package/dist/types/helpers/index.d.ts +13 -0
- package/dist/types/helpers/index.iife.d.ts +1 -0
- package/dist/types/helpers/inject.d.ts +11 -0
- package/dist/types/helpers/is.d.ts +14 -0
- package/dist/types/helpers/keep.d.ts +11 -0
- package/dist/types/helpers/portal.d.ts +21 -0
- package/dist/types/helpers/router.d.ts +28 -0
- package/dist/types/helpers/signal.d.ts +21 -0
- package/dist/types/helpers/slot.d.ts +29 -0
- package/dist/types/index.d.ts +28 -0
- package/dist/types/index.iife.d.ts +1 -0
- package/dist/types/vnode.defs.d.ts +82 -0
- package/dist/zenith-helpers.development.js +18 -13
- package/dist/zenith-helpers.global.js +2 -2
- package/dist/zenith-helpers.js +2 -2
- package/dist/zenith.development.js +2 -1
- package/dist/zenith.global.js +1 -1
- package/dist/zenith.js +1 -1
- package/package.json +13 -6
package/README.md
CHANGED
|
@@ -1,50 +1,98 @@
|
|
|
1
1
|
# Zenith
|
|
2
2
|
|
|
3
|
-
Zenith is a tiny
|
|
3
|
+
Zenith is a tiny reactive JavaScript framework with a virtual DOM, keyed reconciliation, and targeted component redraws. Its rendering model can update an entire application or a specific component, which is useful when parts of a page manage their own content, such as canvas, WebGL, and SVG interfaces.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Zenith supports component lifecycle hooks, memoization, DOM events, SVG and MathML, and optional helpers. It is inspired by [Mithril.js](https://github.com/MithrilJS/mithril.js).
|
|
6
6
|
|
|
7
|
-
Zenith is
|
|
8
|
-
|
|
9
|
-
**The current release release is alpha. It is used in production, but is still rapidly evolving. Consider the API relatively safe.**
|
|
7
|
+
**Status:** Zenith is currently in beta. We aim to keep the API stable through 1.0.0, but breaking changes may still occur during the beta period.
|
|
10
8
|
|
|
11
9
|
## Installation
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
Install the beta package:
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
```sh
|
|
14
|
+
npm install zenith@beta
|
|
15
|
+
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Import the functions you need:
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
```js
|
|
20
|
+
import { bind, comp, compDef, elem } from 'zenith';
|
|
21
|
+
```
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
Prebuilt browser files are also included in `dist/`. The `zenith.global.js` build is intended for direct browser use; the `zenith.js` build is an ES module.
|
|
22
24
|
|
|
23
|
-
##
|
|
25
|
+
## Example: counter
|
|
24
26
|
|
|
25
27
|
```html
|
|
26
|
-
<!
|
|
28
|
+
<!doctype html>
|
|
27
29
|
<html lang="en">
|
|
28
30
|
<head>
|
|
31
|
+
<meta charset="utf-8">
|
|
32
|
+
<title>Zenith counter</title>
|
|
29
33
|
</head>
|
|
30
34
|
<body>
|
|
31
35
|
<main id="app"></main>
|
|
32
|
-
<script
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
36
|
+
<script type="module">
|
|
37
|
+
import { bind, comp, compDef, elem } from 'zenith';
|
|
38
|
+
|
|
39
|
+
let count = 0;
|
|
40
|
+
|
|
41
|
+
const Counter = compDef({
|
|
42
|
+
draw: () => elem('button', {
|
|
43
|
+
onclick: () => { count++; }
|
|
44
|
+
}, `Count: ${count}`)
|
|
41
45
|
});
|
|
42
|
-
|
|
46
|
+
|
|
47
|
+
bind(document.querySelector('#app'), comp(Counter));
|
|
43
48
|
</script>
|
|
44
49
|
</body>
|
|
45
50
|
</html>
|
|
46
51
|
```
|
|
47
52
|
|
|
53
|
+
The example assumes an environment that resolves npm package imports, such as a bundler or development server. Event handlers automatically schedule a redraw unless the event's `draw` property is set to `false`.
|
|
54
|
+
|
|
55
|
+
## Components and redraws
|
|
56
|
+
|
|
57
|
+
Create components with `compDef()` and `comp()`, then mount them using `bind()`. Call `draw()` when external state changes outside an event handler:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
import { bind, comp, compDef, draw, elem } from 'zenith';
|
|
61
|
+
|
|
62
|
+
let message = 'Hello';
|
|
63
|
+
|
|
64
|
+
const Message = compDef({
|
|
65
|
+
draw: () => elem('p', message)
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const view = comp(Message);
|
|
69
|
+
bind(document.querySelector('#app'), view);
|
|
70
|
+
|
|
71
|
+
message = 'Updated';
|
|
72
|
+
draw(view);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Redraws are scheduled in a microtask. Call `sync()` if you need to apply queued redraws immediately. `draw(view, true)` requests a targeted redraw of a component.
|
|
76
|
+
|
|
77
|
+
Component definitions can use `init`, `draw`, `drawn`, `remove`, and `removed` lifecycle hooks. `remove` may return a Promise to defer removal. Components also support optional memoization through `$memo`.
|
|
78
|
+
|
|
79
|
+
## Package builds
|
|
80
|
+
|
|
81
|
+
The npm package includes prebuilt files under `dist/`, including:
|
|
82
|
+
|
|
83
|
+
- `zenith.js` — ES module
|
|
84
|
+
- `zenith.global.js` — global browser build
|
|
85
|
+
- `zenith.development.js` — development build
|
|
86
|
+
- `zenith-helpers.js` — optional helpers (import from `zenith/helpers`)
|
|
87
|
+
|
|
88
|
+
The library is designed for a very small compressed footprint; actual size depends on the build and compression settings.
|
|
89
|
+
|
|
90
|
+
## Documentation
|
|
91
|
+
|
|
92
|
+
Additional information: [Zenith website](https://aleph-1.com/zenith) (work in progress).
|
|
93
|
+
|
|
94
|
+
Report bugs and request features through [GitHub Issues](https://github.com/aleph1/Zenith/issues).
|
|
95
|
+
|
|
48
96
|
## License
|
|
49
97
|
|
|
50
|
-
[MIT](LICENSE
|
|
98
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { VNode } from '../vnode.defs';
|
|
2
|
+
/**
|
|
3
|
+
* Finds the closest ancestor vNode matching the predicate.
|
|
4
|
+
* Walks up the tree from the given vNode's parent.
|
|
5
|
+
* Returns undefined if no match is found.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // Find the closest list component ancestor
|
|
9
|
+
* const list = closest(vNode, n => n.is === is.comp && n.$def === List);
|
|
10
|
+
*
|
|
11
|
+
* // Find the closest ancestor with a specific attribute
|
|
12
|
+
* const themed = closest(vNode, n => n.attrs?.theme);
|
|
13
|
+
*/
|
|
14
|
+
export declare const closest: (vNode: VNode, predicate: (vNode: VNode) => boolean) => VNode | undefined;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Combines class names, filtering out falsy values.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* cls('btn', isActive && 'btn-active', hasError && 'btn-error')
|
|
6
|
+
* // => 'btn btn-active' (if isActive, not hasError)
|
|
7
|
+
*/
|
|
8
|
+
export declare const cls: (...args: (string | false | null | undefined | 0)[]) => string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Signal } from './signal';
|
|
2
|
+
export interface DerivedSignal<T> extends Signal<T> {
|
|
3
|
+
destroy(): void;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Creates a computed signal that updates when any dependency changes.
|
|
7
|
+
* Call destroy() in component cleanup to prevent memory leaks.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const firstName = signal('John');
|
|
11
|
+
* const lastName = signal('Smith');
|
|
12
|
+
* const fullName = derived(
|
|
13
|
+
* () => `${firstName.val} ${lastName.val}`,
|
|
14
|
+
* [firstName, lastName]
|
|
15
|
+
* );
|
|
16
|
+
* // In component cleanup:
|
|
17
|
+
* removed: () => fullName.destroy()
|
|
18
|
+
*/
|
|
19
|
+
export declare const derived: <T>(fn: () => T, deps: Signal<any>[]) => DerivedSignal<T>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { VNodeNode } from '../vnode.defs';
|
|
2
|
+
/**
|
|
3
|
+
* Converts an HTML string to DOM nodes wrapped in node() vnodes.
|
|
4
|
+
*
|
|
5
|
+
* XSS WARNING: Only use with trusted, sanitized HTML.
|
|
6
|
+
* Never pass user-generated content without sanitization.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Safe static content
|
|
10
|
+
* html('<div class="card"><h2>Title</h2></div>')
|
|
11
|
+
*
|
|
12
|
+
* // Unsafe user input
|
|
13
|
+
* html(`<div>${userInput}</div>`)
|
|
14
|
+
*
|
|
15
|
+
* // Safe alternative
|
|
16
|
+
* elem('div', userInput)
|
|
17
|
+
*
|
|
18
|
+
* @see https://owasp.org/www-community/attacks/xss/
|
|
19
|
+
*/
|
|
20
|
+
export declare const html: (value: string | number | bigint) => VNodeNode | VNodeNode[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { keep } from './keep';
|
|
2
|
+
export { is } from './is';
|
|
3
|
+
export { cls } from './cls';
|
|
4
|
+
export { slot } from './slot';
|
|
5
|
+
export { html } from './html';
|
|
6
|
+
export { closest } from './closest';
|
|
7
|
+
export { inject } from './inject';
|
|
8
|
+
export { signal } from './signal';
|
|
9
|
+
export type { Signal } from './signal';
|
|
10
|
+
export { derived } from './derived';
|
|
11
|
+
export type { DerivedSignal } from './derived';
|
|
12
|
+
export { router } from './router';
|
|
13
|
+
export { Portal } from './portal';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { VNode } from '../vnode.defs';
|
|
2
|
+
/**
|
|
3
|
+
* Retrieves values provided by ancestor components.
|
|
4
|
+
* Walks up the tree collecting requested keys, with closer
|
|
5
|
+
* ancestors taking priority (shadowing).
|
|
6
|
+
* Returns an object with only the keys that were found.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const { theme, locale } = inject(vNode, 'theme', 'locale');
|
|
10
|
+
*/
|
|
11
|
+
export declare const inject: (vNode: VNode, ...keys: string[]) => Record<string, any>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vNode type constants for use with predicate checks.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* if (vNode.is === is.elem) // is a DOM element
|
|
6
|
+
* if (vNode.is === is.comp) // is a component
|
|
7
|
+
*/
|
|
8
|
+
export declare const is: {
|
|
9
|
+
elem: number;
|
|
10
|
+
text: number;
|
|
11
|
+
comp: number;
|
|
12
|
+
node: number;
|
|
13
|
+
compDef: number;
|
|
14
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A memoization predicate that prevents all re-renders.
|
|
3
|
+
* Pass to a component's $memo property to make it fully static.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const Static = compDef({
|
|
7
|
+
* $memo: keep,
|
|
8
|
+
* draw: () => elem('div', 'I never re-render')
|
|
9
|
+
* });
|
|
10
|
+
*/
|
|
11
|
+
export declare const keep: () => boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { VNodeComp, VNodeCompDefinition, VNodeAnyOrArray } from '../vnode.defs';
|
|
2
|
+
interface PortalAttrs {
|
|
3
|
+
to: string | Element;
|
|
4
|
+
children: VNodeAnyOrArray;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Renders children to a different DOM location.
|
|
8
|
+
* Useful for modals, tooltips, and overlays that need
|
|
9
|
+
* to escape their parent's stacking context or overflow.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* comp(Portal, {
|
|
13
|
+
* to: '#modals', // CSS selector
|
|
14
|
+
* to: document.body, // or Element reference
|
|
15
|
+
* children: comp(Modal)
|
|
16
|
+
* })
|
|
17
|
+
*/
|
|
18
|
+
export declare const Portal: VNodeCompDefinition<PortalAttrs> & {
|
|
19
|
+
to: (vNode: VNodeComp<PortalAttrs>) => Element | null;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { VNodeCompDefinition, VNodeAnyOrArray } from '../vnode.defs';
|
|
2
|
+
interface RouterOptions {
|
|
3
|
+
mode?: 'hash' | 'history';
|
|
4
|
+
}
|
|
5
|
+
type RouteComponent = (params: Record<string, string>) => VNodeAnyOrArray;
|
|
6
|
+
interface RouterRoutes {
|
|
7
|
+
[pattern: string]: RouteComponent;
|
|
8
|
+
'*'?: RouteComponent;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Creates a hash or history-based router as a component definition.
|
|
12
|
+
* Supports dynamic params (:id) and wildcard routes (*).
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const App = router({
|
|
16
|
+
* '/': () => comp(Home),
|
|
17
|
+
* '/users/:id': ({ id }) => comp(User, { id }),
|
|
18
|
+
* '*': () => comp(NotFound)
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Hash mode (default)
|
|
22
|
+
* draw(comp(App), document.body);
|
|
23
|
+
*
|
|
24
|
+
* // History mode
|
|
25
|
+
* draw(comp(router(routes, { mode: 'history' })), document.body);
|
|
26
|
+
*/
|
|
27
|
+
export declare const router: (routes: RouterRoutes, options?: RouterOptions) => VNodeCompDefinition;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type SignalSubscriber<T> = (val: T) => void;
|
|
2
|
+
export interface Signal<T> {
|
|
3
|
+
get val(): T;
|
|
4
|
+
set val(newVal: T);
|
|
5
|
+
sub(fn: SignalSubscriber<T>): () => void;
|
|
6
|
+
notify(): void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a reactive value that notifies subscribers on change.
|
|
10
|
+
* Uses strict inequality (!==) to detect changes, so object
|
|
11
|
+
* mutations won't trigger notifications — use immutable updates
|
|
12
|
+
* or call notify() manually.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const count = signal(0);
|
|
16
|
+
* const unsub = count.sub(val => console.log(val));
|
|
17
|
+
* count.val = 1; // logs 1
|
|
18
|
+
* unsub(); // stop listening
|
|
19
|
+
*/
|
|
20
|
+
export declare const signal: <T>(val: T) => Signal<T>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { VNode, VNodeAttrs } from '../vnode.defs';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a content slot to a renderable vNode.
|
|
4
|
+
* Supports multiple content formats for flexible component APIs.
|
|
5
|
+
*
|
|
6
|
+
* - string → returned as-is
|
|
7
|
+
* - function → called with attrs, returns result
|
|
8
|
+
* - array → each item recursively resolved
|
|
9
|
+
* - vNode → returned as-is
|
|
10
|
+
* - null / undefined → returns nothing
|
|
11
|
+
*
|
|
12
|
+
* Note: component definitions must be wrapped in comp() by the caller.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const Card = compDef({
|
|
16
|
+
* draw: (vNode) => elem('div', { class: 'card' },
|
|
17
|
+
* slot(vNode.attrs.header, vNode.attrs),
|
|
18
|
+
* slot(vNode.attrs.children, vNode.attrs)
|
|
19
|
+
* )
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Usage
|
|
23
|
+
* comp(Card, {
|
|
24
|
+
* header: elem('h2', 'Title'), // vNode
|
|
25
|
+
* children: (attrs) => elem('p', 'Hi'), // function
|
|
26
|
+
* children: comp(Modal, { ... }), // wrap in comp() explicitly
|
|
27
|
+
* })
|
|
28
|
+
*/
|
|
29
|
+
export declare const slot: (content: VNode | VNode[] | string | ((attrs: VNodeAttrs) => VNode | VNode[] | string) | null | undefined, attrs: VNodeAttrs) => VNode | VNode[] | string | undefined;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface Window {
|
|
3
|
+
DEBUG?: boolean;
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
import { VNodeElem, VNodeComp, VNodeNode, VNodeAny, VNodeArray, VNodeElemAttributes, VNodeCompAttributes, VNodeCompDefinition, VNodeContainer } from './vnode.defs';
|
|
7
|
+
declare const ns: {
|
|
8
|
+
math: string;
|
|
9
|
+
svg: string;
|
|
10
|
+
};
|
|
11
|
+
export declare const diff: {
|
|
12
|
+
none: number;
|
|
13
|
+
self: number;
|
|
14
|
+
nodes: number;
|
|
15
|
+
all: number;
|
|
16
|
+
};
|
|
17
|
+
export declare const sync: () => void;
|
|
18
|
+
export declare const draw: (vNode: VNodeContainer, surgical?: boolean) => void;
|
|
19
|
+
export declare const elem: {
|
|
20
|
+
(tag: string): VNodeElem;
|
|
21
|
+
(tag: string, attrs: VNodeElemAttributes, ...args: VNodeArray): VNodeElem;
|
|
22
|
+
(tag: string, ...args: VNodeArray): VNodeElem;
|
|
23
|
+
};
|
|
24
|
+
export declare const compDef: (componentDefinition: VNodeCompDefinition) => VNodeCompDefinition;
|
|
25
|
+
export declare const comp: (componentDefinition: VNodeCompDefinition, attrs?: VNodeCompAttributes) => VNodeComp;
|
|
26
|
+
export declare const node: (el: Element) => VNodeNode;
|
|
27
|
+
export declare const bind: (el: Element, vNodeAnyOrArray: VNodeAny | VNodeArray) => VNodeComp;
|
|
28
|
+
export { ns };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export declare const VNODE_ELEM = 1;
|
|
2
|
+
export declare const VNODE_TEXT = 2;
|
|
3
|
+
export declare const VNODE_COMP = 3;
|
|
4
|
+
export declare const VNODE_NODE = 4;
|
|
5
|
+
export declare const VNODE_COMPDEF = 5;
|
|
6
|
+
export interface VNodeElemAttributes {
|
|
7
|
+
class?: string | string[];
|
|
8
|
+
style?: string | Record<string, string | number | null | undefined>;
|
|
9
|
+
$key?: string | number;
|
|
10
|
+
$diff?: number;
|
|
11
|
+
$remove?: boolean;
|
|
12
|
+
is?: string;
|
|
13
|
+
xmlns?: string;
|
|
14
|
+
[property: string]: any;
|
|
15
|
+
}
|
|
16
|
+
export interface VNodeCompAttributes {
|
|
17
|
+
$key?: string | number;
|
|
18
|
+
$remove?: boolean;
|
|
19
|
+
to?: string | Element;
|
|
20
|
+
[property: string]: any;
|
|
21
|
+
}
|
|
22
|
+
export type VNodeAttrs = VNodeElemAttributes | VNodeCompAttributes;
|
|
23
|
+
export interface VNodeNodeAttributes {
|
|
24
|
+
[property: string]: any;
|
|
25
|
+
}
|
|
26
|
+
export interface VNodeCompDefinition<A extends VNodeCompAttributes = VNodeCompAttributes> {
|
|
27
|
+
$tag?: number;
|
|
28
|
+
init?: (vNode: VNodeComp<A>) => void;
|
|
29
|
+
draw: (vNode: VNodeComp<A>, oldChildren?: VNodeFlatArray) => VNodeAnyOrArray;
|
|
30
|
+
drawn?: (vNode: VNodeComp<A>, isFirstDraw?: boolean) => void;
|
|
31
|
+
remove?: (vNode: VNodeComp<A>) => Promise<void> | void;
|
|
32
|
+
removed?: (vNode: VNodeComp<A>) => void;
|
|
33
|
+
$memo?: boolean | ((newAttrs: A, oldAttrs: A) => boolean);
|
|
34
|
+
}
|
|
35
|
+
interface VNodeBase {
|
|
36
|
+
$h?: boolean;
|
|
37
|
+
up: VNodeContainer | null;
|
|
38
|
+
nodes: VNodeFlatArray | null;
|
|
39
|
+
el: any;
|
|
40
|
+
}
|
|
41
|
+
export interface VNodeElem extends VNodeBase {
|
|
42
|
+
is: typeof VNODE_ELEM;
|
|
43
|
+
$tag: string;
|
|
44
|
+
$def: null;
|
|
45
|
+
attrs: VNodeElemAttributes;
|
|
46
|
+
nodes: VNodeFlatArray;
|
|
47
|
+
}
|
|
48
|
+
export interface VNodeText extends VNodeBase {
|
|
49
|
+
is: typeof VNODE_TEXT;
|
|
50
|
+
$tag: string;
|
|
51
|
+
$def: null;
|
|
52
|
+
attrs: null;
|
|
53
|
+
nodes: null;
|
|
54
|
+
}
|
|
55
|
+
export interface VNodeComp<A extends VNodeCompAttributes = VNodeCompAttributes> extends VNodeBase {
|
|
56
|
+
is: typeof VNODE_COMP;
|
|
57
|
+
$tag: number;
|
|
58
|
+
$def: VNodeCompDefinition;
|
|
59
|
+
attrs: A;
|
|
60
|
+
nodes: VNodeFlatArray;
|
|
61
|
+
provide?: Record<string, any>;
|
|
62
|
+
}
|
|
63
|
+
export interface VNodeNode extends VNodeBase {
|
|
64
|
+
is: typeof VNODE_NODE;
|
|
65
|
+
$tag: string;
|
|
66
|
+
$def: null;
|
|
67
|
+
attrs: null;
|
|
68
|
+
nodes: null;
|
|
69
|
+
}
|
|
70
|
+
export type VNode = VNodeElem | VNodeText | VNodeComp | VNodeNode;
|
|
71
|
+
export type VNodeAny = VNode;
|
|
72
|
+
export type VNodeContainer = VNodeComp | VNodeElem;
|
|
73
|
+
export type VNodeDrawable = VNodeComp;
|
|
74
|
+
export type VNodeHTML = VNodeElem;
|
|
75
|
+
export type VNodeDom = Node | Node[];
|
|
76
|
+
export type VNodeChild = VNodeAny | string | number | boolean | null | undefined;
|
|
77
|
+
export type VNodeArray = Array<VNodeChild | VNodeArray>;
|
|
78
|
+
export type VNodeAnyOrArray = VNodeChild | VNodeArray;
|
|
79
|
+
export interface VNodeFlatArray extends Array<VNodeAny> {
|
|
80
|
+
$keys?: Map<any, any> | null;
|
|
81
|
+
}
|
|
82
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Zenith Helpers v1.0.0-beta.
|
|
1
|
+
/*! Zenith Helpers v1.0.0-beta.14 | MIT License | © 2022-2025 Daniel Barber */
|
|
2
2
|
import { node, draw } from './zenith.js';
|
|
3
3
|
|
|
4
4
|
const keep = () => true;
|
|
@@ -43,7 +43,7 @@ const inject = (vNode, ...keys) => {
|
|
|
43
43
|
const result = {};
|
|
44
44
|
const needed = new Set(keys);
|
|
45
45
|
for (let current = vNode.up; current && needed.size > 0; current = current.up) {
|
|
46
|
-
if (current.is ===
|
|
46
|
+
if (current.is === VNODE_COMP && current.provide) {
|
|
47
47
|
for (const key of needed) {
|
|
48
48
|
if (current.provide[key] !== void 0) {
|
|
49
49
|
result[key] = current.provide[key];
|
|
@@ -122,24 +122,29 @@ const router = (routes, options = {}) => {
|
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
124
|
return {
|
|
125
|
-
init(vNode) {
|
|
125
|
+
init: (vNode) => {
|
|
126
|
+
const node = vNode;
|
|
126
127
|
const matched = matchRoute(getPath());
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
node.route = matched.component;
|
|
129
|
+
node.params = matched.params;
|
|
130
|
+
node.onroute = () => {
|
|
130
131
|
const matched2 = matchRoute(getPath());
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
draw(
|
|
132
|
+
node.route = matched2.component;
|
|
133
|
+
node.params = matched2.params;
|
|
134
|
+
draw(node, true);
|
|
134
135
|
};
|
|
135
|
-
window.addEventListener(eventType,
|
|
136
|
+
window.addEventListener(eventType, node.onroute);
|
|
136
137
|
},
|
|
137
138
|
draw: (vNode) => {
|
|
138
139
|
var _a;
|
|
139
|
-
|
|
140
|
+
const node = vNode;
|
|
141
|
+
return (_a = node.route) == null ? void 0 : _a.call(node, node.params);
|
|
140
142
|
},
|
|
141
|
-
removed(vNode) {
|
|
142
|
-
|
|
143
|
+
removed: (vNode) => {
|
|
144
|
+
const node = vNode;
|
|
145
|
+
if (node.onroute) {
|
|
146
|
+
window.removeEventListener(eventType, node.onroute);
|
|
147
|
+
}
|
|
143
148
|
}
|
|
144
149
|
};
|
|
145
150
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! Zenith Helpers v1.0.0-beta.
|
|
2
|
-
!function(e){"use strict";const
|
|
1
|
+
/*! Zenith Helpers v1.0.0-beta.14 | MIT License | © 2022-2025 Daniel Barber */
|
|
2
|
+
!function(e){"use strict";const signal=e=>{let t=e;const o=new Set,n=()=>{for(const e of o)e(t)};return{get val(){return t},set val(e){t!==e&&(t=e,n())},sub:e=>(o.add(e),()=>o.delete(e)),notify:n}},t={keep:()=>!0,is:{elem:1,text:2,comp:3,node:4,compDef:5},cls:(...e)=>e.filter(Boolean).join(" "),slot:(e,t)=>{if(e)return"function"==typeof e?e(t):e},html:t=>{const o=document.createElement("div");o.innerHTML=t+"";const n=[...o.childNodes].map(t=>e.node(t));return 1===n.length?n[0]:n},closest:(e,t)=>{for(let o=e.up;o;o=o.up)if(t(o))return o},inject:(e,...t)=>{const o={},n=new Set(t);for(let t=e.up;t&&n.size>0;t=t.up)if(3===t.is&&t.provide)for(const e of n)void 0!==t.provide[e]&&(o[e]=t.provide[e],n.delete(e));return o},signal:signal,derived:(e,t)=>{const o=signal(e()),n=t.map(t=>t.sub(()=>{o.val=e()}));return o.destroy=()=>{for(const e of n)e();n.length=0},o},router:(t,o={})=>{const n="history"===o.mode,r=n?"popstate":"hashchange",s=()=>n?location.pathname:location.hash.slice(1)||"/",c=[],a=e=>{for(const t of c){const o=e.match(t.regex);if(o){const e={};for(let n=0;t.keys.length>n;n++)e[t.keys[n]]=o[n+1];return{component:t.component,params:e}}}return{component:t["*"]||null,params:{}}};for(const e in t){const o=[],n=e.replace(/:[^/]+/g,e=>(o.push(e.slice(1)),"([^/]+)")).replace(/\*/g,"(.*)");c.push({regex:RegExp(`^${n}$`),keys:o,component:t[e]})}return{init:t=>{const o=t,n=a(s());o.route=n.component,o.params=n.params,o.onroute=()=>{const t=a(s());o.route=t.component,o.params=t.params,e.draw(o,!0)},window.addEventListener(r,o.onroute)},draw:e=>{var t;return null==(t=e.route)?void 0:t.call(e,e.params)},removed:e=>{e.onroute&&window.removeEventListener(r,e.onroute)}}},Portal:{to:e=>"string"==typeof e.attrs.to?document.querySelector(e.attrs.to):e.attrs.to,draw:e=>e.attrs.children}};window.zh=t}(z);
|
package/dist/zenith-helpers.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! Zenith Helpers v1.0.0-beta.
|
|
2
|
-
import{node as e,draw as t}from"./zenith.js";const keep=()=>!0,is={elem:1,text:2,comp:3,node:4,compDef:5},cls=(...e)=>e.filter(Boolean).join(" "),slot=(e,t)=>{if(e)return"function"==typeof e?e(t):e},html=t=>{const o=document.createElement("div");o.innerHTML=t+"";const n=[...o.childNodes].map(t=>e(t));return 1===n.length?n[0]:n},closest=(e,t)=>{for(let o=e.up;o;o=o.up)if(t(o))return o},inject=(e,...t)=>{const o={},n=new Set(t);for(let t=e.up;t&&n.size>0;t=t.up)if(3===t.is&&t.provide)for(const e of n)void 0!==t.provide[e]&&(o[e]=t.provide[e],n.delete(e));return o},signal=e=>{let t=e;const o=new Set,n=()=>{for(const e of o)e(t)};return{get val(){return t},set val(e){t!==e&&(t=e,n())},sub:e=>(o.add(e),()=>o.delete(e)),notify:n}},derived=(e,t)=>{const o=signal(e()),n=t.map(t=>t.sub(()=>{o.val=e()}));return o.destroy=()=>{for(const e of n)e();n.length=0},o},router=(e,o={})=>{const n="history"===o.mode,r=n?"popstate":"hashchange",s=()=>n?location.pathname:location.hash.slice(1)||"/",a=[],c=t=>{for(const e of a){const o=t.match(e.regex);if(o){const t={};for(let n=0;e.keys.length>n;n++)t[e.keys[n]]=o[n+1];return{component:e.component,params:t}}}return{component:e["*"]||null,params:{}}};for(const t in e){const o=[],n=t.replace(/:[^/]+/g,e=>(o.push(e.slice(1)),"([^/]+)")).replace(/\*/g,"(.*)");a.push({regex:RegExp(`^${n}$`),keys:o,component:e[t]})}return{init
|
|
1
|
+
/*! Zenith Helpers v1.0.0-beta.14 | MIT License | © 2022-2025 Daniel Barber */
|
|
2
|
+
import{node as e,draw as t}from"./zenith.js";const keep=()=>!0,is={elem:1,text:2,comp:3,node:4,compDef:5},cls=(...e)=>e.filter(Boolean).join(" "),slot=(e,t)=>{if(e)return"function"==typeof e?e(t):e},html=t=>{const o=document.createElement("div");o.innerHTML=t+"";const n=[...o.childNodes].map(t=>e(t));return 1===n.length?n[0]:n},closest=(e,t)=>{for(let o=e.up;o;o=o.up)if(t(o))return o},inject=(e,...t)=>{const o={},n=new Set(t);for(let t=e.up;t&&n.size>0;t=t.up)if(3===t.is&&t.provide)for(const e of n)void 0!==t.provide[e]&&(o[e]=t.provide[e],n.delete(e));return o},signal=e=>{let t=e;const o=new Set,n=()=>{for(const e of o)e(t)};return{get val(){return t},set val(e){t!==e&&(t=e,n())},sub:e=>(o.add(e),()=>o.delete(e)),notify:n}},derived=(e,t)=>{const o=signal(e()),n=t.map(t=>t.sub(()=>{o.val=e()}));return o.destroy=()=>{for(const e of n)e();n.length=0},o},router=(e,o={})=>{const n="history"===o.mode,r=n?"popstate":"hashchange",s=()=>n?location.pathname:location.hash.slice(1)||"/",a=[],c=t=>{for(const e of a){const o=t.match(e.regex);if(o){const t={};for(let n=0;e.keys.length>n;n++)t[e.keys[n]]=o[n+1];return{component:e.component,params:t}}}return{component:e["*"]||null,params:{}}};for(const t in e){const o=[],n=t.replace(/:[^/]+/g,e=>(o.push(e.slice(1)),"([^/]+)")).replace(/\*/g,"(.*)");a.push({regex:RegExp(`^${n}$`),keys:o,component:e[t]})}return{init:e=>{const o=e,n=c(s());o.route=n.component,o.params=n.params,o.onroute=()=>{const e=c(s());o.route=e.component,o.params=e.params,t(o,!0)},window.addEventListener(r,o.onroute)},draw:e=>{var t;return null==(t=e.route)?void 0:t.call(e,e.params)},removed:e=>{e.onroute&&window.removeEventListener(r,e.onroute)}}},Portal={to:e=>"string"==typeof e.attrs.to?document.querySelector(e.attrs.to):e.attrs.to,draw:e=>e.attrs.children};export{Portal,closest,cls,derived,html,inject,is,keep,router,signal,slot};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Zenith v1.0.0-beta.
|
|
1
|
+
/*! Zenith v1.0.0-beta.14 | MIT License | © 2022-2025 Daniel Barber */
|
|
2
2
|
const VNODE_ELEM = 1;
|
|
3
3
|
const VNODE_TEXT = 2;
|
|
4
4
|
const VNODE_COMP = 3;
|
|
@@ -376,6 +376,7 @@ const _unmount = (nodes) => {
|
|
|
376
376
|
_unmountReusableArray[0] = nodes;
|
|
377
377
|
nodes = _unmountReusableArray;
|
|
378
378
|
}
|
|
379
|
+
nodes = nodes;
|
|
379
380
|
for (let i = 0; i < nodes.length; i++) {
|
|
380
381
|
const node2 = nodes[i];
|
|
381
382
|
if (node2.is === VNODE_COMP) {
|
package/dist/zenith.global.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! Zenith v1.0.0-beta.
|
|
1
|
+
/*! Zenith v1.0.0-beta.14 | MIT License | © 2022-2025 Daniel Barber */
|
|
2
2
|
const e=new Map,t=new Set,ns={math:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg"},s=[],l={},n=new Map,sync=()=>{let s,l=t.size;if(l){const n=document.activeElement;for(const n of t)if(s=e.has(n.el)?n.el:n.attrs&&n.attrs.to||n.el&&n.el.parentNode||n.up&&n.up.el,t.delete(n),s&&g(n,s),! --l)break;t.size&&Promise.resolve().then(sync),n&&n!==document.activeElement&&"function"==typeof n.focus&&n.focus()}},draw=(e,s)=>{if(s)3===e.is&&(e.$tag|=2),t.add(e);else{let s;for(s=e;s.up;s=s.up);for(t.add(s),s=e;s.up;s=s.up)if(3===s.is){if(2&s.$tag)break;s.$tag|=2}}1===t.size&&Promise.resolve().then(sync)},r=[],o=(e,t=0,s=[])=>{let l;for(e&&"object"==typeof e&&null!=e.length||(r[0]=e,e=r);e.length>t;t++)if(l=e[t],Array.isArray(l))o(l,0,s);else if(null!=l)if(l.is){if(void 0===s.$keys)s.$keys=l.attrs&&"$key"in l.attrs?n:null;else if(!s.$keys!=!(l.attrs&&"$key"in l.attrs))throw Error("$keys");s.push(l)}else if(!0!==l&&!1!==l){if(void 0===s.$keys)s.$keys=null;else if(s.$keys)throw Error("$keys");s.push({is:2,$tag:l+"",$def:null,attrs:null,nodes:null,up:null,el:null})}return s},i=e=>{if(3===e.is&&!e.attrs.to){for(let t=e.nodes.length-1;t>=0;t--){const s=i(e.nodes[t]);if(s)return s}return null}return e.el},a=(e,t,s)=>{if(3!==e.is||e.attrs.to)e.el&&(e.el.nextSibling!==s&&t.insertBefore(e.el,s),s=e.el);else for(let l=e.nodes.length-1;l>=0;l--)s=a(e.nodes[l],t,s);return s},f=(e,t,s,l,n,r)=>{if(l.el){const o=s.is;if(o===l.is)if(1===o)if(s.up=e,s.$tag===l.$tag){s.el=l.el,s.$h=l.$h;const e=s.attrs.$diff||6;2&e&&$(s,l.attrs),4&e?d(s,s.el,s.nodes,l.nodes,s.attrs.xmlns||ns[s.$tag]||n):s.nodes=l.nodes}else u(e,t,s,n),t.insertBefore(s.el,l.el),h(l);else 2===o?(s.el=l.el,s.$tag!==l.$tag&&(s.el.textContent=s.$tag)):3===o?(4&l.$tag&&(l.$tag&=-5),s.up=e,s.$def===l.$def?(s.el=l.el,s.$h=l.$h,s.nodes=l.nodes,(r||2&l.$tag||!s.$def.$memo||(!0===s.$def.$memo?s.attrs!==l.attrs:!s.$def.$memo(s.attrs,l.attrs)))&&(s.$tag&=-3,g(s,t,n))):(u(e,t,s,n),h(l))):4===o&&s.el!==l.el&&(t.insertBefore(s.el,null),l.el.remove());else u(e,t,s,n),h(l)}else u(e,t,s,n)},d=(e,t,s,l,n,r=0)=>{const o=s.length,d=l.length;if(o){let r,$,g=0;if(d)if(s.$keys&&l.$keys){for(;o>g&&d>g&&s[g].attrs.$key===l[g].attrs.$key;)f(e,t,s[g],l[g],n),g++;if(o>g||d>g){const c=new Map;for(let e=g;d>e;e++)c.set(l[e].attrs.$key,l[e]);const m=i(l[d-1]);let p=m?m.nextSibling:null;for(let l=o-1;l>=g;l--){if($=s[l],r=c.get($.attrs.$key),r)if(c.delete($.attrs.$key),3===$.is&&$.attrs.$remove){if(!(4&r.$tag)&&h(r)){s.splice(l,1);continue}r.up=e,s[l]=r}else f(e,t,$,r,n);else{if($.attrs.$remove){s.splice(l,1);continue}u(e,t,$,n)}p=a(s[l],t,p)}for(const e of c.values())h(e)}}else{for(let e=o;d>e;e++)h(l[e]);for(let i=0;o>i;i++)r=l[i],$=s[i],r&&r.el?f(e,t,$,r,n):u(e,t,$,n)}else for(;o>g;g++)u(e,t,s[g],n)}else if(1===e.is)t.textContent="",m(l);else for(let e=0;d>e;e++)h(l[e]);e.nodes=s},$=(e,t=l)=>{let s,n;const r=e.el,o=e.attrs;for(s in"input"===e.$tag&&o.type&&r.setAttribute("type",o.type),o){const i=o[s];if("o"===s[0]&&"n"===s[1])i!==t[s]&&(r[s]="function"==typeof i?t=>{!1===i.call(t.currentTarget,t)&&(t.preventDefault(),t.stopPropagation()),!1!==t.draw&&draw(e)}:null);else if("$"!==s[0]&&("type"!==s||"input"!==e.$tag)&&"is"!==s&&"xmlns"!==s)if(n=typeof i,"string"===n||"number"===n)"value"===s?i!==t[s]&&(r.value=i):i!==t[s]&&r.setAttribute(s,i+"");else if(!0===i)!0!==t[s]&&r.setAttribute(s,s);else if(i){if("style"===s){if("string"==typeof t.style)r.removeAttribute("style");else for(const e in t.style||l)e in i||(r.style[e]="");Object.assign(r.style,i)}}else t[s]&&r.removeAttribute(s)}for(s in t)s in o||("o"===s[0]&&"n"===s[1]?r[s]=null:r.removeAttribute(s))},u=(e,t,s,l)=>{if(1===s.is){s.up=e,s.el=(l=s.attrs&&s.attrs.xmlns||ns[s.$tag]||l)?document.createElementNS(l,s.$tag,s.attrs.is?{is:s.attrs.is}:null):document.createElement(s.$tag,s.attrs.is?{is:s.attrs.is}:null),$(s);for(let e=0;s.nodes.length>e;e++)u(s,s.el,s.nodes[e],l);t.insertBefore(s.el,null)}else if(2===s.is)s.el=document.createTextNode(s.$tag),t.insertBefore(s.el,null);else if(3===s.is){if(s.up=e,s.$def.init&&s.$def.init(s),s.nodes=o(s.$def.draw(s)),8&s.$tag)for(let e=s;e&&!e.$h;e=e.up)e.$h=!0;s.attrs.to&&(s.el=document.createComment(""),t.insertBefore(s.el,null));for(let e=0;s.nodes.length>e;e++)u(s,s.attrs.to||t,s.nodes[e],l);s.el||(s.el=s.nodes[0]&&s.nodes[0].el),s.$def.drawn&&s.$def.drawn(s,!0)}else 4===s.is&&t.insertBefore(s.el,null)},g=(e,t,s)=>{const l=e.nodes,n=e.$def.draw(e,l);e.$tag&=-3,n!==l&&(d(e,e.attrs.to||t,o(n),l,s),e.el||(e.el=e.nodes[0]&&e.nodes[0].el)),e.$def.drawn&&e.$def.drawn(e)},c=[],m=e=>{Array.isArray(e)||(c[0]=e,e=c);for(let t=0;e.length>t;t++){const s=e[t];3===s.is&&((16&s.$tag||s.$def.remove)&&(64&s.$tag||s.$def.remove(s)),(32&s.$tag||s.$def.removed)&&s.$def.removed(s)),s.$h&&s.nodes.length&&(m(s.nodes),s.nodes=null),s.attrs=s.nodes=s.$tag=s.$def=s.el=s.up=null}},p=e=>{if(3===e.is){for(let t=0;e.nodes.length>t;t++)p(e.nodes[t]);e.attrs.to&&e.el&&e.el.remove()}else e.el&&e.el.remove()},y=e=>{p(e),m(e)},h=e=>{if(3===e.is&&(16&e.$tag||e.$def.remove)){if(4&e.$tag)return!1;e.$tag|=68;const t=e.$def.remove(e);if(t&&t.then){const s=()=>{if(4&e.$tag){const t=e.up;if(t){const s=t.nodes.indexOf(e);-1!==s&&t.nodes.splice(s,1)}y(e),draw(t)}};return t.then(s,s),!1}}return y(e),!0},compDef=e=>Object.freeze({is:5,$tag:1|(e.remove?16:0)|(e.removed?32:0)|(e.remove||e.removed?8:0),...e}),comp=(e,t=l)=>({is:3,$tag:e.$tag||0,$def:e,attrs:t,nodes:s,up:null,el:null}),v=compDef({draw:e=>e.attrs.$nodes});window.z={elem:function(e){const t=arguments[1],n=t&&"object"==typeof t&&!Array.isArray(t)&&!("$tag"in t);return{is:1,$tag:e,$def:null,attrs:n?t:l,nodes:arguments.length>(n?2:1)?o(arguments,n?2:1):s,up:null,el:null}},comp:comp,node:e=>({is:4,$tag:e.nodeName.toLowerCase(),$def:null,attrs:null,nodes:null,up:null,el:e}),compDef:compDef,bind:(t,s)=>{const l=e.get(t)||comp(v);return l.attrs={$nodes:s},e.set(l.el=t,l),draw(l),sync(),l},draw:draw,ns:ns,diff:{none:1,self:2,nodes:4,all:6}};
|
package/dist/zenith.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! Zenith v1.0.0-beta.
|
|
1
|
+
/*! Zenith v1.0.0-beta.14 | MIT License | © 2022-2025 Daniel Barber */
|
|
2
2
|
const e=new Map,t=new Set,ns={math:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg"},diff={none:1,self:2,nodes:4,all:6},s=[],l={},n=new Map,sync=()=>{let s,l=t.size;if(l){const n=document.activeElement;for(const n of t)if(s=e.has(n.el)?n.el:n.attrs&&n.attrs.to||n.el&&n.el.parentNode||n.up&&n.up.el,t.delete(n),s&&g(n,s),! --l)break;t.size&&Promise.resolve().then(sync),n&&n!==document.activeElement&&"function"==typeof n.focus&&n.focus()}},draw=(e,s)=>{if(s)3===e.is&&(e.$tag|=2),t.add(e);else{let s;for(s=e;s.up;s=s.up);for(t.add(s),s=e;s.up;s=s.up)if(3===s.is){if(2&s.$tag)break;s.$tag|=2}}1===t.size&&Promise.resolve().then(sync)},r=[],o=(e,t=0,s=[])=>{let l;for(e&&"object"==typeof e&&null!=e.length||(r[0]=e,e=r);e.length>t;t++)if(l=e[t],Array.isArray(l))o(l,0,s);else if(null!=l)if(l.is){if(void 0===s.$keys)s.$keys=l.attrs&&"$key"in l.attrs?n:null;else if(!s.$keys!=!(l.attrs&&"$key"in l.attrs))throw Error("$keys");s.push(l)}else if(!0!==l&&!1!==l){if(void 0===s.$keys)s.$keys=null;else if(s.$keys)throw Error("$keys");s.push({is:2,$tag:l+"",$def:null,attrs:null,nodes:null,up:null,el:null})}return s},i=e=>{if(3===e.is&&!e.attrs.to){for(let t=e.nodes.length-1;t>=0;t--){const s=i(e.nodes[t]);if(s)return s}return null}return e.el},a=(e,t,s)=>{if(3!==e.is||e.attrs.to)e.el&&(e.el.nextSibling!==s&&t.insertBefore(e.el,s),s=e.el);else for(let l=e.nodes.length-1;l>=0;l--)s=a(e.nodes[l],t,s);return s},f=(e,t,s,l,n,r)=>{if(l.el){const o=s.is;if(o===l.is)if(1===o)if(s.up=e,s.$tag===l.$tag){s.el=l.el,s.$h=l.$h;const e=s.attrs.$diff||6;2&e&&d(s,l.attrs),4&e?$(s,s.el,s.nodes,l.nodes,s.attrs.xmlns||ns[s.$tag]||n):s.nodes=l.nodes}else u(e,t,s,n),t.insertBefore(s.el,l.el),h(l);else 2===o?(s.el=l.el,s.$tag!==l.$tag&&(s.el.textContent=s.$tag)):3===o?(4&l.$tag&&(l.$tag&=-5),s.up=e,s.$def===l.$def?(s.el=l.el,s.$h=l.$h,s.nodes=l.nodes,(r||2&l.$tag||!s.$def.$memo||(!0===s.$def.$memo?s.attrs!==l.attrs:!s.$def.$memo(s.attrs,l.attrs)))&&(s.$tag&=-3,g(s,t,n))):(u(e,t,s,n),h(l))):4===o&&s.el!==l.el&&(t.insertBefore(s.el,null),l.el.remove());else u(e,t,s,n),h(l)}else u(e,t,s,n)},$=(e,t,s,l,n,r=0)=>{const o=s.length,$=l.length;if(o){let r,d,g=0;if($)if(s.$keys&&l.$keys){for(;o>g&&$>g&&s[g].attrs.$key===l[g].attrs.$key;)f(e,t,s[g],l[g],n),g++;if(o>g||$>g){const c=new Map;for(let e=g;$>e;e++)c.set(l[e].attrs.$key,l[e]);const p=i(l[$-1]);let m=p?p.nextSibling:null;for(let l=o-1;l>=g;l--){if(d=s[l],r=c.get(d.attrs.$key),r)if(c.delete(d.attrs.$key),3===d.is&&d.attrs.$remove){if(!(4&r.$tag)&&h(r)){s.splice(l,1);continue}r.up=e,s[l]=r}else f(e,t,d,r,n);else{if(d.attrs.$remove){s.splice(l,1);continue}u(e,t,d,n)}m=a(s[l],t,m)}for(const e of c.values())h(e)}}else{for(let e=o;$>e;e++)h(l[e]);for(let i=0;o>i;i++)r=l[i],d=s[i],r&&r.el?f(e,t,d,r,n):u(e,t,d,n)}else for(;o>g;g++)u(e,t,s[g],n)}else if(1===e.is)t.textContent="",p(l);else for(let e=0;$>e;e++)h(l[e]);e.nodes=s},d=(e,t=l)=>{let s,n;const r=e.el,o=e.attrs;for(s in"input"===e.$tag&&o.type&&r.setAttribute("type",o.type),o){const i=o[s];if("o"===s[0]&&"n"===s[1])i!==t[s]&&(r[s]="function"==typeof i?t=>{!1===i.call(t.currentTarget,t)&&(t.preventDefault(),t.stopPropagation()),!1!==t.draw&&draw(e)}:null);else if("$"!==s[0]&&("type"!==s||"input"!==e.$tag)&&"is"!==s&&"xmlns"!==s)if(n=typeof i,"string"===n||"number"===n)"value"===s?i!==t[s]&&(r.value=i):i!==t[s]&&r.setAttribute(s,i+"");else if(!0===i)!0!==t[s]&&r.setAttribute(s,s);else if(i){if("style"===s){if("string"==typeof t.style)r.removeAttribute("style");else for(const e in t.style||l)e in i||(r.style[e]="");Object.assign(r.style,i)}}else t[s]&&r.removeAttribute(s)}for(s in t)s in o||("o"===s[0]&&"n"===s[1]?r[s]=null:r.removeAttribute(s))},u=(e,t,s,l)=>{if(1===s.is){s.up=e,s.el=(l=s.attrs&&s.attrs.xmlns||ns[s.$tag]||l)?document.createElementNS(l,s.$tag,s.attrs.is?{is:s.attrs.is}:null):document.createElement(s.$tag,s.attrs.is?{is:s.attrs.is}:null),d(s);for(let e=0;s.nodes.length>e;e++)u(s,s.el,s.nodes[e],l);t.insertBefore(s.el,null)}else if(2===s.is)s.el=document.createTextNode(s.$tag),t.insertBefore(s.el,null);else if(3===s.is){if(s.up=e,s.$def.init&&s.$def.init(s),s.nodes=o(s.$def.draw(s)),8&s.$tag)for(let e=s;e&&!e.$h;e=e.up)e.$h=!0;s.attrs.to&&(s.el=document.createComment(""),t.insertBefore(s.el,null));for(let e=0;s.nodes.length>e;e++)u(s,s.attrs.to||t,s.nodes[e],l);s.el||(s.el=s.nodes[0]&&s.nodes[0].el),s.$def.drawn&&s.$def.drawn(s,!0)}else 4===s.is&&t.insertBefore(s.el,null)},g=(e,t,s)=>{const l=e.nodes,n=e.$def.draw(e,l);e.$tag&=-3,n!==l&&($(e,e.attrs.to||t,o(n),l,s),e.el||(e.el=e.nodes[0]&&e.nodes[0].el)),e.$def.drawn&&e.$def.drawn(e)},c=[],p=e=>{Array.isArray(e)||(c[0]=e,e=c);for(let t=0;e.length>t;t++){const s=e[t];3===s.is&&((16&s.$tag||s.$def.remove)&&(64&s.$tag||s.$def.remove(s)),(32&s.$tag||s.$def.removed)&&s.$def.removed(s)),s.$h&&s.nodes.length&&(p(s.nodes),s.nodes=null),s.attrs=s.nodes=s.$tag=s.$def=s.el=s.up=null}},m=e=>{if(3===e.is){for(let t=0;e.nodes.length>t;t++)m(e.nodes[t]);e.attrs.to&&e.el&&e.el.remove()}else e.el&&e.el.remove()},y=e=>{m(e),p(e)},h=e=>{if(3===e.is&&(16&e.$tag||e.$def.remove)){if(4&e.$tag)return!1;e.$tag|=68;const t=e.$def.remove(e);if(t&&t.then){const s=()=>{if(4&e.$tag){const t=e.up;if(t){const s=t.nodes.indexOf(e);-1!==s&&t.nodes.splice(s,1)}y(e),draw(t)}};return t.then(s,s),!1}}return y(e),!0},elem=function(e){const t=arguments[1],n=t&&"object"==typeof t&&!Array.isArray(t)&&!("$tag"in t);return{is:1,$tag:e,$def:null,attrs:n?t:l,nodes:arguments.length>(n?2:1)?o(arguments,n?2:1):s,up:null,el:null}},compDef=e=>Object.freeze({is:5,$tag:1|(e.remove?16:0)|(e.removed?32:0)|(e.remove||e.removed?8:0),...e}),comp=(e,t=l)=>({is:3,$tag:e.$tag||0,$def:e,attrs:t,nodes:s,up:null,el:null}),node=e=>({is:4,$tag:e.nodeName.toLowerCase(),$def:null,attrs:null,nodes:null,up:null,el:e}),v=compDef({draw:e=>e.attrs.$nodes}),bind=(t,s)=>{const l=e.get(t)||comp(v);return l.attrs={$nodes:s},e.set(l.el=t,l),draw(l),sync(),l};export{bind,comp,compDef,diff,draw,elem,node,ns,sync};
|
package/package.json
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zenith",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.14",
|
|
4
4
|
"description": "Another front-end framework.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "dist/zenith.
|
|
7
|
-
"module": "dist/zenith.js",
|
|
6
|
+
"main": "./dist/zenith.js",
|
|
7
|
+
"module": "./dist/zenith.js",
|
|
8
|
+
"types": "./dist/types/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
|
-
".":
|
|
10
|
-
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/types/index.d.ts",
|
|
12
|
+
"default": "./dist/zenith.js"
|
|
13
|
+
},
|
|
14
|
+
"./helpers": {
|
|
15
|
+
"types": "./dist/types/helpers/index.d.ts",
|
|
16
|
+
"default": "./dist/zenith-helpers.js"
|
|
17
|
+
}
|
|
11
18
|
},
|
|
12
19
|
"files": [
|
|
13
20
|
"dist/"
|
|
14
21
|
],
|
|
15
22
|
"sideEffects": false,
|
|
16
23
|
"scripts": {
|
|
17
|
-
"build": "rollup --config && node scripts/after-build.mjs",
|
|
24
|
+
"build": "rollup --config && tsc && node scripts/after-build.mjs",
|
|
18
25
|
"lint": "eslint . --ext .ts",
|
|
19
26
|
"test": "vitest --run --coverage --reporter verbose",
|
|
20
27
|
"test:ui": "vitest --ui",
|