@adukiorg/anza 0.4.1 → 0.4.3
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/bin/anza/anza-linux-arm64 +0 -0
- package/bin/anza/anza-linux-x64 +0 -0
- package/bin/anza/anza-macos-arm64 +0 -0
- package/bin/anza/anza-macos-x64 +0 -0
- package/bin/anza/anza-windows-x64.exe +0 -0
- package/package.json +1 -1
- package/src/core/api/index.js +2 -2
- package/src/core/offline/sync.js +2 -2
- package/src/core/router/cascade.js +23 -18
- package/src/core/router/container.js +6 -2
- package/src/core/router/graph.js +46 -15
- package/src/core/router/index.js +7 -1
- package/src/core/router/intercept.js +397 -100
- package/src/core/router/match.js +30 -0
- package/src/core/router/transitions.js +4 -3
- package/src/core/ui/define/container.js +3 -13
- package/src/core/ui/define/element.js +58 -8
- package/src/core/ui/define/orchestrator.js +8 -4
- package/src/core/ui/defs/dock.js +27 -14
- package/src/core/ui/defs/page.js +75 -29
- package/src/core/ui/defs/spec.js +81 -11
- package/src/elements/data/list/style.css +1 -1
- package/src/elements/data/table/index.js +2 -1
- package/src/elements/data/table/style.css +1 -1
- package/src/elements/feedback/alert/style.css +1 -1
- package/src/styles/base.css +22 -21
- package/src/styles/reset.css +0 -2
- package/src/tokens/index.css +1 -4
- package/src/tokens/primitives/colors.css +9 -64
- package/src/tokens/primitives/motion.css +6 -18
- package/src/tokens/primitives/spacing.css +7 -12
- package/src/tokens/primitives/typography.css +12 -42
- package/src/tokens/registered/colors.css +5 -96
- package/src/tokens/registered/dimensions.css +6 -19
- package/src/tokens/semantic/contrast.css +8 -36
- package/src/tokens/semantic/dark.css +13 -48
- package/src/tokens/semantic/light.css +13 -44
- package/src/tokens/semantic/transitions.css +26 -13
- package/CHANGELOG.md +0 -360
- package/src/tokens/primitives/radius.css +0 -16
- package/src/tokens/primitives/shadow.css +0 -34
- package/src/tokens/primitives/zindex.css +0 -18
- package/src/tokens/semantic/components.css +0 -123
|
Binary file
|
package/bin/anza/anza-linux-x64
CHANGED
|
Binary file
|
|
Binary file
|
package/bin/anza/anza-macos-x64
CHANGED
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/src/core/api/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import { cache as apiCache } from './caches/index.js';
|
|
|
20
20
|
|
|
21
21
|
let cache = null;
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
function sync() {
|
|
24
24
|
if (typeof document === 'undefined') return;
|
|
25
25
|
const el = document.getElementById('anza-state');
|
|
26
26
|
if (el) {
|
|
@@ -156,7 +156,7 @@ async function request(url, method, body, opts = {}) {
|
|
|
156
156
|
|
|
157
157
|
export const api = {
|
|
158
158
|
get: (url, opts) => request(url, 'GET', null, opts),
|
|
159
|
-
state: () => cache ? JSON.parse(JSON.stringify(cache.__route || {})) :
|
|
159
|
+
state: () => cache ? JSON.parse(JSON.stringify(cache.__route || {})) : {},
|
|
160
160
|
sync,
|
|
161
161
|
post: (url, body, opts) => request(url, 'POST', body, opts),
|
|
162
162
|
put: (url, body, opts) => request(url, 'PUT', body, opts),
|
package/src/core/offline/sync.js
CHANGED
|
@@ -15,7 +15,7 @@ export class SyncManager {
|
|
|
15
15
|
constructor() {
|
|
16
16
|
if (
|
|
17
17
|
typeof navigator !== 'undefined' &&
|
|
18
|
-
|
|
18
|
+
navigator.serviceWorker
|
|
19
19
|
) {
|
|
20
20
|
navigator.serviceWorker.addEventListener('message', async (event) => {
|
|
21
21
|
const data = event.data;
|
|
@@ -38,7 +38,7 @@ export class SyncManager {
|
|
|
38
38
|
async register(tag) {
|
|
39
39
|
if (
|
|
40
40
|
typeof navigator !== 'undefined' &&
|
|
41
|
-
|
|
41
|
+
navigator.serviceWorker
|
|
42
42
|
) {
|
|
43
43
|
try {
|
|
44
44
|
const registration = await navigator.serviceWorker.ready;
|
|
@@ -32,7 +32,16 @@ export async function ensure(target, current = 'main') {
|
|
|
32
32
|
if (live) return live;
|
|
33
33
|
|
|
34
34
|
const segments = path(current, target);
|
|
35
|
-
if (!segments)
|
|
35
|
+
if (!segments) {
|
|
36
|
+
// The container graph has no registered path from `current` to `target`.
|
|
37
|
+
// This almost always means a dock() declaration is missing or was imported
|
|
38
|
+
// after the page() that lists it in `via`.
|
|
39
|
+
throw new Error(
|
|
40
|
+
`[Router] CascadeError: cannot mount '${target}' — no graph path from '${current}'.\n` +
|
|
41
|
+
`Ensure dock('${target}', { parent: '${current}' }) is called and its file is imported\n` +
|
|
42
|
+
`before any page() that lists '${target}' in its via chain.`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
36
45
|
|
|
37
46
|
// Find the deepest node on the path that is currently connected.
|
|
38
47
|
let mounted = null;
|
|
@@ -47,26 +56,22 @@ export async function ensure(target, current = 'main') {
|
|
|
47
56
|
const start = segments.indexOf(mounted) + 1;
|
|
48
57
|
for (let i = start; i < segments.length; i++) {
|
|
49
58
|
const node = segments[i];
|
|
59
|
+
if (resolve(node.name)) continue;
|
|
50
60
|
const parentEl = node.parent?.ref?.deref() ?? null;
|
|
51
|
-
if (!parentEl || !parentEl.isConnected) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const tag = node.name;
|
|
56
|
-
if (tag.includes('-') && typeof customElements !== 'undefined' && !customElements.get(tag)) {
|
|
57
|
-
await customElements.whenDefined(tag);
|
|
58
|
-
}
|
|
59
|
-
|
|
61
|
+
if (!parentEl || !parentEl.isConnected) throw new Error(`CascadeError: parent '${node.parent?.name}' is disconnected while mounting '${node.name}'`);
|
|
62
|
+
const tag = node.tag;
|
|
63
|
+
if (tag.includes('-') && typeof customElements !== 'undefined' && !customElements.get(tag)) await customElements.whenDefined(tag);
|
|
60
64
|
const el = document.createElement(tag);
|
|
61
|
-
|
|
62
|
-
await parentEl.swap(el, { direction: 'push' });
|
|
63
|
-
} else {
|
|
64
|
-
parentEl.replaceChildren(el);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Yield so connectedCallback fires and the dock self-registers in the graph.
|
|
68
|
-
await frame();
|
|
65
|
+
parentEl.replaceChildren(el);
|
|
69
66
|
|
|
67
|
+
// Wait for the element's connectedCallback to complete, including any
|
|
68
|
+
// async resource loading (template/style fetches). A single frame is
|
|
69
|
+
// not sufficient when preloadResources() hits the network.
|
|
70
|
+
let attempts = 0;
|
|
71
|
+
while (!resolve(node.name) && attempts < 50) {
|
|
72
|
+
await frame();
|
|
73
|
+
attempts++;
|
|
74
|
+
}
|
|
70
75
|
if (!resolve(node.name)) {
|
|
71
76
|
throw new Error(`CascadeError: container '${node.name}' failed to register after mount`);
|
|
72
77
|
}
|
|
@@ -62,8 +62,8 @@ function ensureObserver() {
|
|
|
62
62
|
* @param {string|null} [parent='main'] - parent container key in the graph.
|
|
63
63
|
* Pass null explicitly when registering the root (no parent).
|
|
64
64
|
*/
|
|
65
|
-
export function registerContainer(name, element, parent = 'main') {
|
|
66
|
-
add(name, element, parent);
|
|
65
|
+
export function registerContainer(name, element, parent = 'main', tag = null) {
|
|
66
|
+
add(name, element, parent, tag);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/**
|
|
@@ -76,6 +76,10 @@ export function unregisterContainer(name, element) {
|
|
|
76
76
|
remove(name, element);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
export function hasContainer(name) {
|
|
80
|
+
return get(name) !== null;
|
|
81
|
+
}
|
|
82
|
+
|
|
79
83
|
/**
|
|
80
84
|
* Retrieves an active layout container by name.
|
|
81
85
|
*
|
package/src/core/router/graph.js
CHANGED
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
class Node {
|
|
17
|
-
constructor(name, ref, parent) {
|
|
17
|
+
constructor(name, tag, ref, parent) {
|
|
18
18
|
this.name = name; // registry key, e.g. 'main' | 'sidebar'
|
|
19
|
+
this.tag = tag; // custom element tag, e.g. 'dock-docs' | 'main'
|
|
19
20
|
this.ref = ref; // WeakRef<Element> | null (null for virtual root)
|
|
20
21
|
this.parent = parent; // Node | null
|
|
21
22
|
this.children = new Set(); // Set<Node>
|
|
@@ -33,7 +34,7 @@ const nodes = new Map();
|
|
|
33
34
|
// The permanent root node. ref is null at module-evaluation time because
|
|
34
35
|
// modules may be evaluated before the parser reaches <main id="main">.
|
|
35
36
|
// boot.js fills in the WeakRef during anchor().
|
|
36
|
-
const root = new Node('main', null, null);
|
|
37
|
+
const root = new Node('main', 'main', null, null);
|
|
37
38
|
root.depth = 0;
|
|
38
39
|
nodes.set('main', root);
|
|
39
40
|
|
|
@@ -41,15 +42,23 @@ nodes.set('main', root);
|
|
|
41
42
|
// so a just-unmounted container is not confused with a GC'd one (RT bug 8.2).
|
|
42
43
|
const gone = new Set();
|
|
43
44
|
|
|
44
|
-
// Prune stale nodes after their element is collected.
|
|
45
|
+
// Prune stale nodes after their element is collected by GC.
|
|
46
|
+
// This is the ONLY place a node is structurally removed from the graph.
|
|
47
|
+
// Normal DOM disconnects (remove()) only null the ref — they preserve topology.
|
|
45
48
|
const finalizer = typeof FinalizationRegistry !== 'undefined'
|
|
46
49
|
? new FinalizationRegistry((name) => {
|
|
47
50
|
const node = nodes.get(name);
|
|
51
|
+
// Only detach if the node still has no live element (i.e. truly GC'd,
|
|
52
|
+
// not just remounted under a new element instance).
|
|
48
53
|
if (node && !node.alive()) detach(name);
|
|
49
54
|
})
|
|
50
55
|
: { register() {}, unregister() {} };
|
|
51
56
|
|
|
52
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* Structurally removes a node from the tree, reparenting its children to its
|
|
59
|
+
* parent. Called ONLY from the FinalizationRegistry (GC path). DOM disconnects
|
|
60
|
+
* must NOT call this — they use remove() which only nulls the ref.
|
|
61
|
+
*/
|
|
53
62
|
function detach(name) {
|
|
54
63
|
const node = nodes.get(name);
|
|
55
64
|
if (!node || node === root) return;
|
|
@@ -68,9 +77,10 @@ function detach(name) {
|
|
|
68
77
|
* @param {string} name - unique registry key.
|
|
69
78
|
* @param {Element} el - the container element.
|
|
70
79
|
* @param {string} [parent='main'] - parent registry key.
|
|
80
|
+
* @param {string} [tag] - custom element tag; defaults to name.
|
|
71
81
|
* @returns {Node} the inserted node.
|
|
72
82
|
*/
|
|
73
|
-
export function add(name, el, parent = 'main') {
|
|
83
|
+
export function add(name, el, parent = 'main', tag = null) {
|
|
74
84
|
gone.delete(name);
|
|
75
85
|
|
|
76
86
|
const existing = nodes.get(name);
|
|
@@ -78,45 +88,66 @@ export function add(name, el, parent = 'main') {
|
|
|
78
88
|
if (existing === root) {
|
|
79
89
|
// Root re-registration from anchor(): refresh the WeakRef and return.
|
|
80
90
|
// The root cannot be reparented and must not spawn a duplicate node.
|
|
81
|
-
existing.ref = new WeakRef(el);
|
|
91
|
+
if (el) existing.ref = new WeakRef(el);
|
|
82
92
|
return existing;
|
|
83
93
|
}
|
|
84
94
|
const prev = existing.ref?.deref();
|
|
85
|
-
if (prev && prev !== el) {
|
|
95
|
+
if (prev && el && prev !== el) {
|
|
86
96
|
throw new Error(`ContainerError: Singleton violation — '${name}' is already mounted. A second instance cannot register while the first is active.`);
|
|
87
97
|
}
|
|
88
|
-
//
|
|
89
|
-
|
|
98
|
+
// Re-registering after a disconnect (ref was null) or HMR: refresh the ref.
|
|
99
|
+
// Also re-register with the finalizer so the new element instance is tracked.
|
|
100
|
+
if (el) {
|
|
101
|
+
existing.ref = new WeakRef(el);
|
|
102
|
+
finalizer.register(el, name);
|
|
103
|
+
}
|
|
90
104
|
return existing;
|
|
91
105
|
}
|
|
92
106
|
|
|
93
107
|
const parentNode = nodes.get(parent) ?? root;
|
|
94
|
-
const
|
|
108
|
+
const resolvedTag = tag || name;
|
|
109
|
+
const node = new Node(name, resolvedTag, el ? new WeakRef(el) : null, parentNode);
|
|
95
110
|
parentNode.children.add(node);
|
|
96
111
|
nodes.set(name, node);
|
|
97
|
-
finalizer.register(el, name);
|
|
112
|
+
if (el) finalizer.register(el, name);
|
|
98
113
|
return node;
|
|
99
114
|
}
|
|
100
115
|
|
|
101
116
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
117
|
+
* Unregisters the live element of a container node when the element disconnects
|
|
118
|
+
* from the DOM. The node itself stays in `nodes` to preserve graph topology for
|
|
119
|
+
* future ensure()/lca() calls — only its element ref is cleared.
|
|
120
|
+
*
|
|
121
|
+
* The name is marked `gone` for one macrotask so any lookup that races the
|
|
122
|
+
* disconnect (e.g. an in-flight navigation reading the old element) gets
|
|
123
|
+
* `undefined` rather than the stale ref.
|
|
124
|
+
*
|
|
125
|
+
* Structural removal (nodes.delete) is deferred to the FinalizationRegistry so
|
|
126
|
+
* it only happens after the element is truly GC'd and cannot be remounted.
|
|
104
127
|
*
|
|
105
128
|
* @param {string} name - registry key.
|
|
106
|
-
* @param {Element} [el] - element guard; if given, only
|
|
129
|
+
* @param {Element} [el] - element guard; if given, only clears when it matches.
|
|
107
130
|
*/
|
|
108
131
|
export function remove(name, el) {
|
|
109
132
|
const node = nodes.get(name);
|
|
110
133
|
if (!node || node === root) return;
|
|
111
134
|
|
|
112
135
|
const current = node.ref?.deref();
|
|
136
|
+
// Guard: if a specific element is given and it doesn't match the registered
|
|
137
|
+
// one, this is a stale disconnect from a previous instance — ignore.
|
|
113
138
|
if (el && current && current !== el) return;
|
|
114
139
|
|
|
140
|
+
// Unregister from the finalizer (we're clearing the ref manually).
|
|
115
141
|
if (current) {
|
|
116
142
|
try { finalizer.unregister(current); } catch (_) {}
|
|
117
143
|
}
|
|
118
|
-
detach(name);
|
|
119
144
|
|
|
145
|
+
// Clear the element ref but KEEP the node in the graph.
|
|
146
|
+
// This preserves topology: lca() and path() can still traverse the tree
|
|
147
|
+
// on the next navigation that needs to remount this container.
|
|
148
|
+
node.ref = null;
|
|
149
|
+
|
|
150
|
+
// Mark as transiently gone for one macrotask.
|
|
120
151
|
gone.add(name);
|
|
121
152
|
if (typeof setTimeout !== 'undefined') {
|
|
122
153
|
setTimeout(() => gone.delete(name), 0);
|
package/src/core/router/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { register, match, clear, getRoutes, load } from './match.js';
|
|
|
12
12
|
import {
|
|
13
13
|
setup, destroy,
|
|
14
14
|
addGuard, setNotFound,
|
|
15
|
+
addTransformer,
|
|
15
16
|
guardsApi, missApi,
|
|
16
17
|
on, nav, registerNavigator,
|
|
17
18
|
getShell, getWin
|
|
@@ -44,7 +45,8 @@ import {
|
|
|
44
45
|
registerContainer,
|
|
45
46
|
unregisterContainer,
|
|
46
47
|
getContainer,
|
|
47
|
-
clearContainers
|
|
48
|
+
clearContainers,
|
|
49
|
+
hasContainer
|
|
48
50
|
} from './container.js';
|
|
49
51
|
|
|
50
52
|
import { cache, prefetch } from './cache.js';
|
|
@@ -56,6 +58,7 @@ export const router = {
|
|
|
56
58
|
clear,
|
|
57
59
|
guard: addGuard,
|
|
58
60
|
notFound: setNotFound,
|
|
61
|
+
transform: addTransformer,
|
|
59
62
|
|
|
60
63
|
// Grouped APIs
|
|
61
64
|
guards: guardsApi,
|
|
@@ -101,6 +104,7 @@ export const router = {
|
|
|
101
104
|
unregisterContainer,
|
|
102
105
|
getContainer,
|
|
103
106
|
clearContainers,
|
|
107
|
+
hasContainer,
|
|
104
108
|
|
|
105
109
|
// Lifecycle
|
|
106
110
|
setup,
|
|
@@ -151,6 +155,7 @@ export {
|
|
|
151
155
|
// intercept sub-module
|
|
152
156
|
addGuard,
|
|
153
157
|
setNotFound,
|
|
158
|
+
addTransformer as transform,
|
|
154
159
|
setup,
|
|
155
160
|
destroy,
|
|
156
161
|
on,
|
|
@@ -168,6 +173,7 @@ export {
|
|
|
168
173
|
unregisterContainer,
|
|
169
174
|
getContainer,
|
|
170
175
|
clearContainers,
|
|
176
|
+
hasContainer,
|
|
171
177
|
// cache sub-module
|
|
172
178
|
cache,
|
|
173
179
|
prefetch
|