@zeus-js/web-c-runtime 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/web-c-runtime.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface ZeusPropMeta {
|
|
|
5
5
|
type: ZeusPropType;
|
|
6
6
|
reflect?: boolean;
|
|
7
7
|
default?: unknown;
|
|
8
|
+
serialize?: boolean;
|
|
9
|
+
deserialize?: boolean;
|
|
8
10
|
}
|
|
9
11
|
export interface ZeusLazyComponentMeta {
|
|
10
12
|
tagName: string;
|
|
@@ -17,22 +19,32 @@ export interface ZeusLazyComponentMeta {
|
|
|
17
19
|
default: ZeusComponentModule;
|
|
18
20
|
}>;
|
|
19
21
|
props: ZeusPropMeta[];
|
|
22
|
+
methods?: string[];
|
|
20
23
|
/**
|
|
21
24
|
* Whether to render into a ShadowRoot.
|
|
22
25
|
*
|
|
23
26
|
* @default false
|
|
24
27
|
*/
|
|
25
28
|
shadow?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Whether the proxy class participates in browser form association.
|
|
31
|
+
*
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
formAssociated?: boolean;
|
|
26
35
|
}
|
|
27
36
|
export interface HostRef {
|
|
28
37
|
host: HTMLElement;
|
|
29
38
|
meta: ZeusLazyComponentMeta;
|
|
39
|
+
internals?: ElementInternals;
|
|
30
40
|
connected: boolean;
|
|
31
41
|
loaded: boolean;
|
|
32
42
|
loading?: Promise<void>;
|
|
33
43
|
instance?: ZeusComponentInstance;
|
|
34
44
|
values: Map<string, unknown>;
|
|
45
|
+
attributeProps: Set<string>;
|
|
35
46
|
reflectingAttrs: Set<string>;
|
|
47
|
+
pendingFormCallbacks: ZeusFormCallback[];
|
|
36
48
|
readyWaiters: Array<{
|
|
37
49
|
resolve(host: HTMLElement): void;
|
|
38
50
|
reject(error: unknown): void;
|
|
@@ -42,6 +54,10 @@ export interface ZeusComponentInstance {
|
|
|
42
54
|
connected?(): void;
|
|
43
55
|
disconnected?(): void;
|
|
44
56
|
propertyChanged?(name: string, oldValue: unknown, newValue: unknown): void;
|
|
57
|
+
formAssociated?(form: HTMLFormElement | null): void;
|
|
58
|
+
formDisabled?(disabled: boolean): void;
|
|
59
|
+
formReset?(): void;
|
|
60
|
+
formStateRestore?(state: File | FormData | string | null, mode: 'restore' | 'autocomplete'): void;
|
|
45
61
|
/**
|
|
46
62
|
* Can return Node / Node[] / string.
|
|
47
63
|
* If the component completes rendering itself, it can also return void.
|
|
@@ -49,6 +65,19 @@ export interface ZeusComponentInstance {
|
|
|
49
65
|
render?(): void | string | Node | Node[];
|
|
50
66
|
dispose?(): void;
|
|
51
67
|
}
|
|
68
|
+
type ZeusFormCallback = {
|
|
69
|
+
type: 'associated';
|
|
70
|
+
form: HTMLFormElement | null;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'disabled';
|
|
73
|
+
disabled: boolean;
|
|
74
|
+
} | {
|
|
75
|
+
type: 'reset';
|
|
76
|
+
} | {
|
|
77
|
+
type: 'stateRestore';
|
|
78
|
+
state: File | FormData | string | null;
|
|
79
|
+
mode: 'restore' | 'autocomplete';
|
|
80
|
+
};
|
|
52
81
|
export interface ZeusComponentModule {
|
|
53
82
|
createComponent(hostRef: HostRef): ZeusComponentInstance;
|
|
54
83
|
}
|
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* web-c-runtime v0.
|
|
2
|
+
* web-c-runtime v0.2.0
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
6
|
+
//#region packages/web-c/web-c-runtime/src/form-callbacks.ts
|
|
7
|
+
function invokeFormCallback(hostRef, callback) {
|
|
8
|
+
switch (callback.type) {
|
|
9
|
+
case "associated":
|
|
10
|
+
var _hostRef$instance, _hostRef$instance$for;
|
|
11
|
+
(_hostRef$instance = hostRef.instance) === null || _hostRef$instance === void 0 || (_hostRef$instance$for = _hostRef$instance.formAssociated) === null || _hostRef$instance$for === void 0 || _hostRef$instance$for.call(_hostRef$instance, callback.form);
|
|
12
|
+
return;
|
|
13
|
+
case "disabled":
|
|
14
|
+
var _hostRef$instance2, _hostRef$instance2$fo;
|
|
15
|
+
(_hostRef$instance2 = hostRef.instance) === null || _hostRef$instance2 === void 0 || (_hostRef$instance2$fo = _hostRef$instance2.formDisabled) === null || _hostRef$instance2$fo === void 0 || _hostRef$instance2$fo.call(_hostRef$instance2, callback.disabled);
|
|
16
|
+
return;
|
|
17
|
+
case "reset":
|
|
18
|
+
var _hostRef$instance3, _hostRef$instance3$fo;
|
|
19
|
+
(_hostRef$instance3 = hostRef.instance) === null || _hostRef$instance3 === void 0 || (_hostRef$instance3$fo = _hostRef$instance3.formReset) === null || _hostRef$instance3$fo === void 0 || _hostRef$instance3$fo.call(_hostRef$instance3);
|
|
20
|
+
return;
|
|
21
|
+
case "stateRestore":
|
|
22
|
+
var _hostRef$instance4, _hostRef$instance4$fo;
|
|
23
|
+
(_hostRef$instance4 = hostRef.instance) === null || _hostRef$instance4 === void 0 || (_hostRef$instance4$fo = _hostRef$instance4.formStateRestore) === null || _hostRef$instance4$fo === void 0 || _hostRef$instance4$fo.call(_hostRef$instance4, callback.state, callback.mode);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
6
27
|
//#region packages/web-c/web-c-runtime/src/host-ref.ts
|
|
7
28
|
const hostRefs = /* @__PURE__ */ new WeakMap();
|
|
8
29
|
function registerHost(host, meta) {
|
|
@@ -11,15 +32,27 @@ function registerHost(host, meta) {
|
|
|
11
32
|
const hostRef = {
|
|
12
33
|
host,
|
|
13
34
|
meta,
|
|
35
|
+
internals: meta.formAssociated ? attachElementInternals(host) : void 0,
|
|
14
36
|
connected: false,
|
|
15
37
|
loaded: false,
|
|
16
38
|
values: /* @__PURE__ */ new Map(),
|
|
39
|
+
attributeProps: /* @__PURE__ */ new Set(),
|
|
17
40
|
reflectingAttrs: /* @__PURE__ */ new Set(),
|
|
41
|
+
pendingFormCallbacks: [],
|
|
18
42
|
readyWaiters: []
|
|
19
43
|
};
|
|
20
44
|
hostRefs.set(host, hostRef);
|
|
21
45
|
return hostRef;
|
|
22
46
|
}
|
|
47
|
+
function attachElementInternals(host) {
|
|
48
|
+
if (typeof host.attachInternals !== "function") return;
|
|
49
|
+
try {
|
|
50
|
+
return host.attachInternals();
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.warn("[zeus:web-c] Failed to attach ElementInternals.", error);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
23
56
|
function getHostRef(host) {
|
|
24
57
|
return hostRefs.get(host);
|
|
25
58
|
}
|
|
@@ -53,7 +86,8 @@ function setPropValue(hostRef, prop, value) {
|
|
|
53
86
|
const oldValue = getPropValue(hostRef, prop);
|
|
54
87
|
if (Object.is(oldValue, value)) return;
|
|
55
88
|
hostRef.values.set(prop.name, value);
|
|
56
|
-
|
|
89
|
+
hostRef.attributeProps.delete(prop.name);
|
|
90
|
+
if (prop.reflect && !prop.serialize) reflectPropertyToAttribute(hostRef, prop, value);
|
|
57
91
|
if (hostRef.loaded) {
|
|
58
92
|
var _hostRef$instance, _hostRef$instance$pro;
|
|
59
93
|
(_hostRef$instance = hostRef.instance) === null || _hostRef$instance === void 0 || (_hostRef$instance$pro = _hostRef$instance.propertyChanged) === null || _hostRef$instance$pro === void 0 || _hostRef$instance$pro.call(_hostRef$instance, prop.name, oldValue, value);
|
|
@@ -68,6 +102,7 @@ function syncAttributeToProperty(hostRef, attrName, _oldValue, newValue) {
|
|
|
68
102
|
const newPropValue = parseAttributeValue(prop, newValue);
|
|
69
103
|
if (Object.is(oldPropValue, newPropValue)) return;
|
|
70
104
|
hostRef.values.set(prop.name, newPropValue);
|
|
105
|
+
hostRef.attributeProps.add(prop.name);
|
|
71
106
|
if (hostRef.loaded) {
|
|
72
107
|
var _hostRef$instance2, _hostRef$instance2$pr;
|
|
73
108
|
(_hostRef$instance2 = hostRef.instance) === null || _hostRef$instance2 === void 0 || (_hostRef$instance2$pr = _hostRef$instance2.propertyChanged) === null || _hostRef$instance2$pr === void 0 || _hostRef$instance2$pr.call(_hostRef$instance2, prop.name, oldPropValue, newPropValue);
|
|
@@ -80,6 +115,7 @@ function applyInitialValues(hostRef) {
|
|
|
80
115
|
const attrName = getAttrName(prop);
|
|
81
116
|
if (attrName && host.hasAttribute(attrName)) {
|
|
82
117
|
hostRef.values.set(prop.name, parseAttributeValue(prop, host.getAttribute(attrName)));
|
|
118
|
+
hostRef.attributeProps.add(prop.name);
|
|
83
119
|
continue;
|
|
84
120
|
}
|
|
85
121
|
if ("default" in prop) hostRef.values.set(prop.name, prop.default);
|
|
@@ -119,7 +155,7 @@ function findPropByAttrName(hostRef, attrName) {
|
|
|
119
155
|
function getAttrName(prop) {
|
|
120
156
|
var _prop$attrName;
|
|
121
157
|
if (prop.attrName === false) return;
|
|
122
|
-
if (!isAttributeBackedType(prop.type)) return;
|
|
158
|
+
if (!isAttributeBackedType(prop.type) && !prop.deserialize) return;
|
|
123
159
|
return normalizeAttrName((_prop$attrName = prop.attrName) !== null && _prop$attrName !== void 0 ? _prop$attrName : toKebabCase(prop.name));
|
|
124
160
|
}
|
|
125
161
|
function isAttributeBackedType(type) {
|
|
@@ -129,6 +165,7 @@ function normalizeAttrName(value) {
|
|
|
129
165
|
return value.toLowerCase();
|
|
130
166
|
}
|
|
131
167
|
function parseAttributeValue(prop, value) {
|
|
168
|
+
if (prop.deserialize) return value;
|
|
132
169
|
switch (prop.type) {
|
|
133
170
|
case "boolean": return value !== null;
|
|
134
171
|
case "number":
|
|
@@ -206,6 +243,7 @@ function _initializeComponent() {
|
|
|
206
243
|
if (hostRef.loaded) {
|
|
207
244
|
var _hostRef$instance, _hostRef$instance$con;
|
|
208
245
|
(_hostRef$instance = hostRef.instance) === null || _hostRef$instance === void 0 || (_hostRef$instance$con = _hostRef$instance.connected) === null || _hostRef$instance$con === void 0 || _hostRef$instance$con.call(_hostRef$instance);
|
|
246
|
+
flushPendingFormCallbacks(hostRef);
|
|
209
247
|
return;
|
|
210
248
|
}
|
|
211
249
|
if (hostRef.loading) {
|
|
@@ -238,6 +276,7 @@ function _doInitializeComponent() {
|
|
|
238
276
|
try {
|
|
239
277
|
var _instance$connected, _instance$render;
|
|
240
278
|
(_instance$connected = instance.connected) === null || _instance$connected === void 0 || _instance$connected.call(instance);
|
|
279
|
+
flushPendingFormCallbacks(hostRef);
|
|
241
280
|
const rendered = (_instance$render = instance.render) === null || _instance$render === void 0 ? void 0 : _instance$render.call(instance);
|
|
242
281
|
if (rendered !== void 0) mountRenderedOutput(hostRef, rendered);
|
|
243
282
|
hostRef.loaded = true;
|
|
@@ -252,6 +291,12 @@ function _doInitializeComponent() {
|
|
|
252
291
|
});
|
|
253
292
|
return _doInitializeComponent.apply(this, arguments);
|
|
254
293
|
}
|
|
294
|
+
function flushPendingFormCallbacks(hostRef) {
|
|
295
|
+
while (hostRef.pendingFormCallbacks.length > 0) {
|
|
296
|
+
invokeFormCallback(hostRef, hostRef.pendingFormCallbacks[0]);
|
|
297
|
+
hostRef.pendingFormCallbacks.shift();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
255
300
|
function loadComponentModule(_x3) {
|
|
256
301
|
return _loadComponentModule.apply(this, arguments);
|
|
257
302
|
}
|
|
@@ -331,6 +376,28 @@ function createLazyElementClass(meta) {
|
|
|
331
376
|
if (oldValue === newValue) return;
|
|
332
377
|
syncAttributeToProperty(requireHostRef(this), name, oldValue, newValue);
|
|
333
378
|
}
|
|
379
|
+
formAssociatedCallback(form) {
|
|
380
|
+
dispatchFormCallback(requireHostRef(this), {
|
|
381
|
+
type: "associated",
|
|
382
|
+
form
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
formDisabledCallback(disabled) {
|
|
386
|
+
dispatchFormCallback(requireHostRef(this), {
|
|
387
|
+
type: "disabled",
|
|
388
|
+
disabled
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
formResetCallback() {
|
|
392
|
+
dispatchFormCallback(requireHostRef(this), { type: "reset" });
|
|
393
|
+
}
|
|
394
|
+
formStateRestoreCallback(state, mode) {
|
|
395
|
+
dispatchFormCallback(requireHostRef(this), {
|
|
396
|
+
type: "stateRestore",
|
|
397
|
+
state,
|
|
398
|
+
mode
|
|
399
|
+
});
|
|
400
|
+
}
|
|
334
401
|
componentOnReady() {
|
|
335
402
|
const hostRef = requireHostRef(this);
|
|
336
403
|
if (hostRef.connected && !hostRef.loaded && !hostRef.loading) initializeComponent(hostRef).catch((error) => {
|
|
@@ -339,9 +406,37 @@ function createLazyElementClass(meta) {
|
|
|
339
406
|
return waitForComponentReady(hostRef);
|
|
340
407
|
}
|
|
341
408
|
}
|
|
409
|
+
ZeusLazyElement.formAssociated = Boolean(meta.formAssociated);
|
|
342
410
|
installPropertyAccessors(ZeusLazyElement.prototype, meta.props);
|
|
411
|
+
installMethodProxies(ZeusLazyElement.prototype, meta.methods);
|
|
343
412
|
return ZeusLazyElement;
|
|
344
413
|
}
|
|
414
|
+
function dispatchFormCallback(hostRef, callback) {
|
|
415
|
+
if (!hostRef.instance || !hostRef.connected) {
|
|
416
|
+
hostRef.pendingFormCallbacks.push(callback);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
invokeFormCallback(hostRef, callback);
|
|
420
|
+
}
|
|
421
|
+
function installMethodProxies(proto, methods) {
|
|
422
|
+
if (!methods) return;
|
|
423
|
+
for (const name of methods) {
|
|
424
|
+
if (name in proto) continue;
|
|
425
|
+
Object.defineProperty(proto, name, {
|
|
426
|
+
configurable: true,
|
|
427
|
+
value: function() {
|
|
428
|
+
const host = this;
|
|
429
|
+
const args = Array.prototype.slice.call(arguments);
|
|
430
|
+
const hostRef = requireHostRef(host);
|
|
431
|
+
return waitForComponentReady(hostRef).then((readyHost) => {
|
|
432
|
+
const method = readyHost[name];
|
|
433
|
+
if (typeof method !== "function") throw new Error(`[zeus:web-c] Method "${name}" is not exposed on <${hostRef.meta.tagName}>.`);
|
|
434
|
+
return method.apply(readyHost, args);
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
}
|
|
345
440
|
//#endregion
|
|
346
441
|
//#region packages/web-c/web-c-runtime/src/bootstrapLazy.ts
|
|
347
442
|
function bootstrapLazy(components) {
|