zenith 1.0.0-beta.13 → 1.0.0-beta.15
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 +27 -20
- package/dist/zenith.global.js +2 -2
- package/dist/zenith.js +2 -2
- 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 | null) => 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: number;
|
|
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.15 | 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.15 | 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.15 | 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.15 | MIT License | © 2022-2025 Daniel Barber */
|
|
2
2
|
const VNODE_ELEM = 1;
|
|
3
3
|
const VNODE_TEXT = 2;
|
|
4
4
|
const VNODE_COMP = 3;
|
|
@@ -45,7 +45,7 @@ const sync = () => {
|
|
|
45
45
|
if (!--remaining) break;
|
|
46
46
|
}
|
|
47
47
|
if (redrawQueue.size) Promise.resolve().then(sync);
|
|
48
|
-
if (active &&
|
|
48
|
+
if (active && document.activeElement === document.body) {
|
|
49
49
|
active.focus();
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -74,7 +74,7 @@ const draw = (vNode, surgical) => {
|
|
|
74
74
|
const _flattenReusableArray = [];
|
|
75
75
|
const _flatten = (nodes, offset = 0, arr = []) => {
|
|
76
76
|
let node2;
|
|
77
|
-
if (!
|
|
77
|
+
if (!nodes || nodes.length == null) {
|
|
78
78
|
_flattenReusableArray[0] = nodes;
|
|
79
79
|
nodes = _flattenReusableArray;
|
|
80
80
|
}
|
|
@@ -131,7 +131,7 @@ const _place = (vNode, parentEl, next) => {
|
|
|
131
131
|
}
|
|
132
132
|
return next;
|
|
133
133
|
};
|
|
134
|
-
const _updateNode = (parentNode, parentEl, newNode, oldNode, xmlns
|
|
134
|
+
const _updateNode = (parentNode, parentEl, newNode, oldNode, xmlns) => {
|
|
135
135
|
if (oldNode.el) {
|
|
136
136
|
const newNodeType = newNode.is;
|
|
137
137
|
if (newNodeType === oldNode.is) {
|
|
@@ -166,7 +166,7 @@ const _updateNode = (parentNode, parentEl, newNode, oldNode, xmlns, skipMemo) =>
|
|
|
166
166
|
newNode.el = oldNode.el;
|
|
167
167
|
newNode.$h = oldNode.$h;
|
|
168
168
|
newNode.nodes = oldNode.nodes;
|
|
169
|
-
if (
|
|
169
|
+
if (oldNode.$tag & FLAG_IS_STALE || !(newNode.$def.$memo && (newNode.$def.$memo === true ? newNode.attrs === oldNode.attrs : newNode.$def.$memo(newNode.attrs, oldNode.attrs)))) {
|
|
170
170
|
newNode.$tag &= ~FLAG_IS_STALE;
|
|
171
171
|
_redrawComponent(newNode, parentEl, xmlns);
|
|
172
172
|
}
|
|
@@ -188,7 +188,7 @@ const _updateNode = (parentNode, parentEl, newNode, oldNode, xmlns, skipMemo) =>
|
|
|
188
188
|
_create(parentNode, parentEl, newNode, xmlns);
|
|
189
189
|
}
|
|
190
190
|
};
|
|
191
|
-
const _updateNodes = (parentNode, parentEl, newNodes, oldNodes, xmlns
|
|
191
|
+
const _updateNodes = (parentNode, parentEl, newNodes, oldNodes, xmlns) => {
|
|
192
192
|
const newNodesLength = newNodes.length;
|
|
193
193
|
const oldNodesLength = oldNodes.length;
|
|
194
194
|
if (newNodesLength) {
|
|
@@ -376,23 +376,24 @@ 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];
|
|
382
|
+
redrawQueue.delete(node2);
|
|
381
383
|
if (node2.is === VNODE_COMP) {
|
|
382
|
-
if (node2.$tag & FLAG_HAS_REMOVE
|
|
384
|
+
if (node2.$tag & FLAG_HAS_REMOVE) {
|
|
383
385
|
if (!(node2.$tag & FLAG_REMOVE_CALLED)) {
|
|
384
386
|
node2.$def.remove(node2);
|
|
385
387
|
}
|
|
386
388
|
}
|
|
387
|
-
if (node2.$tag & FLAG_HAS_REMOVED
|
|
389
|
+
if (node2.$tag & FLAG_HAS_REMOVED) {
|
|
388
390
|
node2.$def.removed(node2);
|
|
389
391
|
}
|
|
390
392
|
}
|
|
391
|
-
if (node2.$h && node2.nodes.length) {
|
|
393
|
+
if ((node2.$h || redrawQueue.size) && node2.nodes && node2.nodes.length) {
|
|
392
394
|
_unmount(node2.nodes);
|
|
393
|
-
node2.nodes = null;
|
|
394
395
|
}
|
|
395
|
-
node2
|
|
396
|
+
node2.$tag = 0;
|
|
396
397
|
}
|
|
397
398
|
};
|
|
398
399
|
const _detach = (vNode) => {
|
|
@@ -411,7 +412,7 @@ const _destroy = (vNode) => {
|
|
|
411
412
|
};
|
|
412
413
|
const _remove = (vNode) => {
|
|
413
414
|
if (vNode.is === VNODE_COMP) {
|
|
414
|
-
if (vNode.$tag & FLAG_HAS_REMOVE
|
|
415
|
+
if (vNode.$tag & FLAG_HAS_REMOVE) {
|
|
415
416
|
if (vNode.$tag & FLAG_IS_REMOVING) {
|
|
416
417
|
return false;
|
|
417
418
|
}
|
|
@@ -510,10 +511,8 @@ const comp = (componentDefinition, attrs = ALWAYS_EMPTY_OBJECT) => {
|
|
|
510
511
|
const node = (el) => {
|
|
511
512
|
return {
|
|
512
513
|
is: VNODE_NODE,
|
|
513
|
-
$tag:
|
|
514
|
-
// string: element name
|
|
514
|
+
$tag: 0,
|
|
515
515
|
$def: null,
|
|
516
|
-
// always null for node
|
|
517
516
|
attrs: null,
|
|
518
517
|
nodes: null,
|
|
519
518
|
up: null,
|
|
@@ -525,12 +524,20 @@ const RootWrapper = compDef({
|
|
|
525
524
|
});
|
|
526
525
|
const bind = (el, vNodeAnyOrArray) => {
|
|
527
526
|
if (el == null) throw new Error("mount");
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
527
|
+
let root = boundNodes.get(el);
|
|
528
|
+
if (vNodeAnyOrArray === null) {
|
|
529
|
+
if (root) {
|
|
530
|
+
_destroy(root);
|
|
531
|
+
boundNodes.delete(el);
|
|
532
|
+
}
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
root = root || comp(RootWrapper);
|
|
536
|
+
root.attrs = { $nodes: vNodeAnyOrArray };
|
|
537
|
+
boundNodes.set(root.el = el, root);
|
|
538
|
+
draw(root);
|
|
532
539
|
sync();
|
|
533
|
-
return
|
|
540
|
+
return root;
|
|
534
541
|
};
|
|
535
542
|
|
|
536
543
|
export { bind, comp, compDef, diff, draw, elem, node, ns, sync };
|
package/dist/zenith.global.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! Zenith v1.0.0-beta.
|
|
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&&
|
|
1
|
+
/*! Zenith v1.0.0-beta.15 | MIT License | © 2022-2025 Daniel Barber */
|
|
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&&document.activeElement===document.body&&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&&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)=>{if(l.el){const r=s.is;if(r===l.is)if(1===r)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===r?(s.el=l.el,s.$tag!==l.$tag&&(s.el.textContent=s.$tag)):3===r?(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,(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===r&&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)=>{const r=s.length,o=l.length;if(r){let d,$,g=0;if(o)if(s.$keys&&l.$keys){for(;r>g&&o>g&&s[g].attrs.$key===l[g].attrs.$key;)f(e,t,s[g],l[g],n),g++;if(r>g||o>g){const c=new Map;for(let e=g;o>e;e++)c.set(l[e].attrs.$key,l[e]);const m=i(l[o-1]);let p=m?m.nextSibling:null;for(let l=r-1;l>=g;l--){if($=s[l],d=c.get($.attrs.$key),d)if(c.delete($.attrs.$key),3===$.is&&$.attrs.$remove){if(!(4&d.$tag)&&h(d)){s.splice(l,1);continue}d.up=e,s[l]=d}else f(e,t,$,d,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=r;o>e;e++)h(l[e]);for(let o=0;r>o;o++)d=l[o],$=s[o],d&&d.el?f(e,t,$,d,n):u(e,t,$,n)}else for(;r>g;g++)u(e,t,s[g],n)}else if(1===e.is)t.textContent="",m(l);else for(let e=0;o>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 s=0;e.length>s;s++){const l=e[s];t.delete(l),3===l.is&&(16&l.$tag&&(64&l.$tag||l.$def.remove(l)),32&l.$tag&&l.$def.removed(l)),(l.$h||t.size)&&l.nodes&&l.nodes.length&&m(l.nodes),l.$tag=0}},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){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:0,$def:null,attrs:null,nodes:null,up:null,el:e}),compDef:compDef,bind:(t,s)=>{let l=e.get(t);return null===s?(l&&(y(l),e.delete(t)),null):(l=l||comp(v),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.
|
|
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&&
|
|
1
|
+
/*! Zenith v1.0.0-beta.15 | MIT License | © 2022-2025 Daniel Barber */
|
|
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&&document.activeElement===document.body&&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&&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)=>{if(l.el){const r=s.is;if(r===l.is)if(1===r)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===r?(s.el=l.el,s.$tag!==l.$tag&&(s.el.textContent=s.$tag)):3===r?(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,(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===r&&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)=>{const r=s.length,o=l.length;if(r){let $,d,g=0;if(o)if(s.$keys&&l.$keys){for(;r>g&&o>g&&s[g].attrs.$key===l[g].attrs.$key;)f(e,t,s[g],l[g],n),g++;if(r>g||o>g){const c=new Map;for(let e=g;o>e;e++)c.set(l[e].attrs.$key,l[e]);const p=i(l[o-1]);let m=p?p.nextSibling:null;for(let l=r-1;l>=g;l--){if(d=s[l],$=c.get(d.attrs.$key),$)if(c.delete(d.attrs.$key),3===d.is&&d.attrs.$remove){if(!(4&$.$tag)&&h($)){s.splice(l,1);continue}$.up=e,s[l]=$}else f(e,t,d,$,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=r;o>e;e++)h(l[e]);for(let o=0;r>o;o++)$=l[o],d=s[o],$&&$.el?f(e,t,d,$,n):u(e,t,d,n)}else for(;r>g;g++)u(e,t,s[g],n)}else if(1===e.is)t.textContent="",p(l);else for(let e=0;o>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 s=0;e.length>s;s++){const l=e[s];t.delete(l),3===l.is&&(16&l.$tag&&(64&l.$tag||l.$def.remove(l)),32&l.$tag&&l.$def.removed(l)),(l.$h||t.size)&&l.nodes&&l.nodes.length&&p(l.nodes),l.$tag=0}},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){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:0,$def:null,attrs:null,nodes:null,up:null,el:e}),v=compDef({draw:e=>e.attrs.$nodes}),bind=(t,s)=>{let l=e.get(t);return null===s?(l&&(y(l),e.delete(t)),null):(l=l||comp(v),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.15",
|
|
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",
|