@zeus-js/output-wc 0.1.0-beta.3 → 0.1.0-beta.5
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/capabilities.cjs.js +2 -2
- package/dist/capabilities.cjs.prod.js +2 -2
- package/dist/capabilities.js +1 -1
- package/dist/capabilities.prod.js +1 -1
- package/dist/output-wc.cjs.js +120 -28
- package/dist/output-wc.cjs.prod.js +120 -28
- package/dist/output-wc.d.ts +0 -1
- package/dist/output-wc.esm-bundler.js +120 -28
- package/package.json +6 -6
package/dist/capabilities.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* output-wc v0.1.0-beta.
|
|
2
|
+
* output-wc v0.1.0-beta.5
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -9,7 +9,7 @@ Object.defineProperties(exports, {
|
|
|
9
9
|
});
|
|
10
10
|
const ZEUS_OUTPUT_WC_CAPABILITIES = {
|
|
11
11
|
packageName: "@zeus-js/output-wc",
|
|
12
|
-
version: "0.1.0-beta.
|
|
12
|
+
version: "0.1.0-beta.5",
|
|
13
13
|
output: {
|
|
14
14
|
webComponent: true,
|
|
15
15
|
customElements: true,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* output-wc v0.1.0-beta.
|
|
2
|
+
* output-wc v0.1.0-beta.5
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -9,7 +9,7 @@ Object.defineProperties(exports, {
|
|
|
9
9
|
});
|
|
10
10
|
const ZEUS_OUTPUT_WC_CAPABILITIES = {
|
|
11
11
|
packageName: "@zeus-js/output-wc",
|
|
12
|
-
version: "0.1.0-beta.
|
|
12
|
+
version: "0.1.0-beta.5",
|
|
13
13
|
output: {
|
|
14
14
|
webComponent: true,
|
|
15
15
|
customElements: true,
|
package/dist/capabilities.js
CHANGED
package/dist/output-wc.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* output-wc v0.1.0-beta.
|
|
2
|
+
* output-wc v0.1.0-beta.5
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -54,7 +54,10 @@ function generateCustomElementsJson(options) {
|
|
|
54
54
|
events: generateEvents(component),
|
|
55
55
|
slots: generateSlots(component),
|
|
56
56
|
cssParts: component.cssParts.map((name) => ({ name })),
|
|
57
|
-
cssProperties: component.
|
|
57
|
+
cssProperties: getCssVars(component).map((variable) => ({
|
|
58
|
+
name: variable.name,
|
|
59
|
+
description: variable.description
|
|
60
|
+
}))
|
|
58
61
|
}],
|
|
59
62
|
exports: [{
|
|
60
63
|
kind: "js",
|
|
@@ -84,7 +87,8 @@ function generateAttributes(component) {
|
|
|
84
87
|
return result;
|
|
85
88
|
}
|
|
86
89
|
function generateMembers(component) {
|
|
87
|
-
|
|
90
|
+
var _component$methods;
|
|
91
|
+
const fields = Object.entries(component.props).map(([name, prop]) => {
|
|
88
92
|
return {
|
|
89
93
|
kind: "field",
|
|
90
94
|
name,
|
|
@@ -93,18 +97,28 @@ function generateMembers(component) {
|
|
|
93
97
|
default: prop.default === void 0 ? void 0 : JSON.stringify(prop.default)
|
|
94
98
|
};
|
|
95
99
|
});
|
|
100
|
+
const methods = Object.keys((_component$methods = component.methods) !== null && _component$methods !== void 0 ? _component$methods : {}).map((name) => {
|
|
101
|
+
return {
|
|
102
|
+
kind: "method",
|
|
103
|
+
name
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
return [...fields, ...methods];
|
|
96
107
|
}
|
|
97
108
|
function generateEvents(component) {
|
|
98
|
-
return Object.entries(component.events).map(([
|
|
109
|
+
return Object.entries(component.events).map(([key, event]) => {
|
|
110
|
+
var _event$name, _event$key;
|
|
99
111
|
return {
|
|
100
|
-
name,
|
|
112
|
+
name: (_event$name = event.name) !== null && _event$name !== void 0 ? _event$name : toKebabCase$1((_event$key = event.key) !== null && _event$key !== void 0 ? _event$key : key),
|
|
101
113
|
description: event.description,
|
|
102
114
|
type: { text: event.detail ? `CustomEvent<${formatDetailType(event.detail)}>` : "CustomEvent" }
|
|
103
115
|
};
|
|
104
116
|
});
|
|
105
117
|
}
|
|
106
118
|
function generateSlots(component) {
|
|
107
|
-
return Object.entries(component.slots).map(([
|
|
119
|
+
return Object.entries(component.slots).map(([key, slot]) => {
|
|
120
|
+
var _slot$name;
|
|
121
|
+
const name = (_slot$name = slot.name) !== null && _slot$name !== void 0 ? _slot$name : key;
|
|
108
122
|
return {
|
|
109
123
|
name: name === "default" ? "" : name,
|
|
110
124
|
description: slot.description
|
|
@@ -114,6 +128,7 @@ function generateSlots(component) {
|
|
|
114
128
|
function getAttributeName(propName, prop) {
|
|
115
129
|
if (prop.attr === false) return false;
|
|
116
130
|
if (typeof prop.attr === "string") return prop.attr;
|
|
131
|
+
if (!isAttributeBackedType$1(prop.type)) return false;
|
|
117
132
|
return propName.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
118
133
|
}
|
|
119
134
|
function formatPropType(prop) {
|
|
@@ -125,15 +140,25 @@ function formatPropType(prop) {
|
|
|
125
140
|
case "boolean": return "boolean";
|
|
126
141
|
case "array": return "unknown[]";
|
|
127
142
|
case "object": return "Record<string, unknown>";
|
|
143
|
+
case "function": return "Function";
|
|
128
144
|
default: return "unknown";
|
|
129
145
|
}
|
|
130
146
|
}
|
|
147
|
+
function isAttributeBackedType$1(type) {
|
|
148
|
+
return type === "string" || type === "number" || type === "boolean";
|
|
149
|
+
}
|
|
131
150
|
function formatDetailType(detail) {
|
|
132
151
|
return `{ ${Object.entries(detail).map(([name, type]) => `${name}: ${type}`).join("; ")} }`;
|
|
133
152
|
}
|
|
134
153
|
function normalizeModulePath(value) {
|
|
135
154
|
return value.replace(/\\/g, "/");
|
|
136
155
|
}
|
|
156
|
+
function getCssVars(component) {
|
|
157
|
+
return Object.values(component.cssVars);
|
|
158
|
+
}
|
|
159
|
+
function toKebabCase$1(value) {
|
|
160
|
+
return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
161
|
+
}
|
|
137
162
|
//#endregion
|
|
138
163
|
//#region packages/web-c/output-wc/src/imports.ts
|
|
139
164
|
function toAbsoluteImportPath(root, source) {
|
|
@@ -186,7 +211,11 @@ function generateLazyEntry(options) {
|
|
|
186
211
|
"",
|
|
187
212
|
`export function createComponent(hostRef) {`,
|
|
188
213
|
` let mounted;`,
|
|
189
|
-
` const mountState = {
|
|
214
|
+
` const mountState = {`,
|
|
215
|
+
` attributeProps: hostRef.attributeProps,`,
|
|
216
|
+
` internals: hostRef.internals,`,
|
|
217
|
+
` reflectingAttrs: hostRef.reflectingAttrs,`,
|
|
218
|
+
` };`,
|
|
190
219
|
"",
|
|
191
220
|
` return {`,
|
|
192
221
|
` connected() {`,
|
|
@@ -208,6 +237,22 @@ function generateLazyEntry(options) {
|
|
|
208
237
|
` propertyChanged(name, oldValue, newValue) {`,
|
|
209
238
|
` mounted?.propertyChanged(name, oldValue, newValue);`,
|
|
210
239
|
` },`,
|
|
240
|
+
"",
|
|
241
|
+
` formAssociated(form) {`,
|
|
242
|
+
` mounted?.formAssociated(form);`,
|
|
243
|
+
` },`,
|
|
244
|
+
"",
|
|
245
|
+
` formDisabled(disabled) {`,
|
|
246
|
+
` mounted?.formDisabled(disabled);`,
|
|
247
|
+
` },`,
|
|
248
|
+
"",
|
|
249
|
+
` formReset() {`,
|
|
250
|
+
` mounted?.formReset();`,
|
|
251
|
+
` },`,
|
|
252
|
+
"",
|
|
253
|
+
` formStateRestore(state, mode) {`,
|
|
254
|
+
` mounted?.formStateRestore(state, mode);`,
|
|
255
|
+
` },`,
|
|
211
256
|
` };`,
|
|
212
257
|
`}`,
|
|
213
258
|
"",
|
|
@@ -229,15 +274,19 @@ function generateLazyManifest(options) {
|
|
|
229
274
|
const { components, getEntryFileName } = options;
|
|
230
275
|
return `export const components = [
|
|
231
276
|
${components.map((component) => {
|
|
232
|
-
var _component$runtimePro, _component$meta$shado, _component$meta;
|
|
277
|
+
var _component$runtimePro, _component$methods, _component$meta$shado, _component$meta, _component$meta$formA, _component$meta2;
|
|
233
278
|
const entryFile = getEntryFileName(component.tag).replace(/\\/g, "/");
|
|
234
279
|
const props = generatePropsArray((_component$runtimePro = component.runtimeProps) !== null && _component$runtimePro !== void 0 ? _component$runtimePro : component.props);
|
|
280
|
+
const methods = Object.keys((_component$methods = component.methods) !== null && _component$methods !== void 0 ? _component$methods : {});
|
|
235
281
|
const importPath = entryFile.startsWith(".") ? JSON.stringify(entryFile) : JSON.stringify(`./${entryFile}`);
|
|
282
|
+
const methodLine = methods.length ? ` methods: ${JSON.stringify(methods)},\n` : "";
|
|
236
283
|
return ` {
|
|
237
284
|
tagName: ${JSON.stringify(component.tag)},
|
|
238
285
|
shadow: ${(_component$meta$shado = (_component$meta = component.meta) === null || _component$meta === void 0 ? void 0 : _component$meta.shadow) !== null && _component$meta$shado !== void 0 ? _component$meta$shado : false},
|
|
286
|
+
formAssociated: ${(_component$meta$formA = (_component$meta2 = component.meta) === null || _component$meta2 === void 0 ? void 0 : _component$meta2.formAssociated) !== null && _component$meta$formA !== void 0 ? _component$meta$formA : false},
|
|
239
287
|
load: () => import(${importPath}),
|
|
240
288
|
props: ${props},
|
|
289
|
+
${methodLine}
|
|
241
290
|
}`;
|
|
242
291
|
}).join(",\n")}
|
|
243
292
|
];
|
|
@@ -248,14 +297,16 @@ function generatePropsArray(props) {
|
|
|
248
297
|
if (entries.length === 0) return "[]";
|
|
249
298
|
return `[\n${entries.map(([name, prop]) => {
|
|
250
299
|
const parts = [`name: ${JSON.stringify(name)}`];
|
|
251
|
-
if (!isAttributeBackedType(prop.type) || prop.attr === false) parts.push("attrName: false");
|
|
300
|
+
if (!isAttributeBackedType(prop.type) && !prop.deserialize || prop.attr === false) parts.push("attrName: false");
|
|
252
301
|
else {
|
|
253
302
|
var _prop$attr;
|
|
254
303
|
const attrName = (_prop$attr = prop.attr) !== null && _prop$attr !== void 0 ? _prop$attr : toKebabCase(name);
|
|
255
304
|
if (attrName !== toKebabCase(name)) parts.push(`attrName: ${JSON.stringify(attrName)}`);
|
|
256
305
|
}
|
|
257
306
|
parts.push(`type: ${JSON.stringify(prop.type)}`);
|
|
258
|
-
if (prop.reflect && isAttributeBackedType(prop.type)) parts.push("reflect: true");
|
|
307
|
+
if (prop.reflect && (isAttributeBackedType(prop.type) || Boolean(prop.serialize))) parts.push("reflect: true");
|
|
308
|
+
if (prop.serialize) parts.push("serialize: true");
|
|
309
|
+
if (prop.deserialize) parts.push("deserialize: true");
|
|
259
310
|
return ` { ${parts.join(", ")} }`;
|
|
260
311
|
}).join(",\n")}\n ]`;
|
|
261
312
|
}
|
|
@@ -271,22 +322,60 @@ function generateLoader() {
|
|
|
271
322
|
return `import { bootstrapLazy } from "@zeus-js/web-c-runtime";
|
|
272
323
|
import { components } from "./components.manifest.js";
|
|
273
324
|
|
|
274
|
-
|
|
325
|
+
const componentsByTagName = new Map(
|
|
326
|
+
components.map(component => [component.tagName, component]),
|
|
327
|
+
);
|
|
275
328
|
|
|
276
|
-
|
|
277
|
-
|
|
329
|
+
const definedTagsByRegistry = new WeakMap();
|
|
330
|
+
|
|
331
|
+
function resolveRegistry(options) {
|
|
332
|
+
return options.registry ??
|
|
333
|
+
(typeof customElements === "undefined" ? undefined : customElements);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function getDefinedTags(registry) {
|
|
337
|
+
let definedTags = definedTagsByRegistry.get(registry);
|
|
338
|
+
|
|
339
|
+
if (!definedTags) {
|
|
340
|
+
definedTags = new Set();
|
|
341
|
+
definedTagsByRegistry.set(registry, definedTags);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return definedTags;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function defineCustomElement(tagName, options = {}) {
|
|
348
|
+
const registry = resolveRegistry(options);
|
|
349
|
+
|
|
350
|
+
if (!registry) {
|
|
278
351
|
return;
|
|
279
352
|
}
|
|
280
353
|
|
|
281
|
-
|
|
354
|
+
const component = componentsByTagName.get(tagName);
|
|
355
|
+
|
|
356
|
+
if (!component) {
|
|
357
|
+
throw new Error(\`[zeus:web-c] Unknown custom element: <\${tagName}>.\`);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const definedTags = getDefinedTags(registry);
|
|
361
|
+
|
|
362
|
+
if (definedTags.has(tagName) || registry.get(tagName)) {
|
|
363
|
+
definedTags.add(tagName);
|
|
282
364
|
return;
|
|
283
365
|
}
|
|
284
366
|
|
|
285
|
-
bootstrapLazy(
|
|
367
|
+
bootstrapLazy([component], { registry });
|
|
286
368
|
|
|
287
|
-
|
|
369
|
+
definedTags.add(tagName);
|
|
288
370
|
}
|
|
289
371
|
|
|
372
|
+
export function defineCustomElements(options = {}) {
|
|
373
|
+
for (const component of components) {
|
|
374
|
+
defineCustomElement(component.tagName, options);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export const defineLazyElement = defineCustomElement;
|
|
290
379
|
export const defineLazyElements = defineCustomElements;
|
|
291
380
|
`;
|
|
292
381
|
}
|
|
@@ -300,7 +389,9 @@ export {};
|
|
|
300
389
|
}
|
|
301
390
|
function generateLazyIndex() {
|
|
302
391
|
return `export {
|
|
392
|
+
defineCustomElement,
|
|
303
393
|
defineCustomElements,
|
|
394
|
+
defineLazyElement,
|
|
304
395
|
defineLazyElements,
|
|
305
396
|
} from "./loader.js";
|
|
306
397
|
`;
|
|
@@ -319,8 +410,8 @@ function wc(options = {}) {
|
|
|
319
410
|
outDir: (_options$outDir = options.outDir) !== null && _options$outDir !== void 0 ? _options$outDir : "wc",
|
|
320
411
|
stripPrefix: (_options$stripPrefix = options.stripPrefix) !== null && _options$stripPrefix !== void 0 ? _options$stripPrefix : false,
|
|
321
412
|
fileName: options.fileName,
|
|
322
|
-
manifestFile:
|
|
323
|
-
customElementsFile:
|
|
413
|
+
manifestFile: (_options$manifestFile = options.manifestFile) !== null && _options$manifestFile !== void 0 ? _options$manifestFile : "zeus.components.json",
|
|
414
|
+
customElementsFile: (_options$customElemen = options.customElementsFile) !== null && _options$customElemen !== void 0 ? _options$customElemen : "custom-elements.json",
|
|
324
415
|
dts: (_options$dts = options.dts) !== null && _options$dts !== void 0 ? _options$dts : true,
|
|
325
416
|
jsxDts: (_options$jsxDts = options.jsxDts) !== null && _options$jsxDts !== void 0 ? _options$jsxDts : true,
|
|
326
417
|
index: (_options$index = options.index) !== null && _options$index !== void 0 ? _options$index : true,
|
|
@@ -349,15 +440,15 @@ function wc(options = {}) {
|
|
|
349
440
|
const runtimeProps = (_component$runtimePro2 = component.runtimeProps) !== null && _component$runtimePro2 !== void 0 ? _component$runtimePro2 : {};
|
|
350
441
|
for (const [name, prop] of Object.entries(runtimeProps)) {
|
|
351
442
|
if (isAttributeBackedRuntimeProp(prop.type)) continue;
|
|
352
|
-
if (prop.attr !== void 0 && prop.attr !== false) ctx.error([
|
|
443
|
+
if (prop.attr !== void 0 && prop.attr !== false && !prop.deserialize) ctx.error([
|
|
353
444
|
`[zeus-output-wc] <${component.tag}> prop "${name}" cannot use attr:${JSON.stringify(prop.attr)} with register:"lazy".`,
|
|
354
|
-
"
|
|
355
|
-
"
|
|
445
|
+
"Non-primitive lazy attributes require a custom deserialize function.",
|
|
446
|
+
"Add deserialize or use attr:false and pass the value as a property."
|
|
356
447
|
].join("\n"));
|
|
357
|
-
if (prop.reflect) ctx.error([
|
|
448
|
+
if (prop.reflect && !prop.serialize) ctx.error([
|
|
358
449
|
`[zeus-output-wc] <${component.tag}> prop "${name}" cannot use reflect:true with register:"lazy".`,
|
|
359
|
-
"
|
|
360
|
-
"
|
|
450
|
+
"Non-primitive lazy reflection requires a custom serialize function.",
|
|
451
|
+
"Add serialize or remove reflect:true."
|
|
361
452
|
].join("\n"));
|
|
362
453
|
}
|
|
363
454
|
}
|
|
@@ -404,7 +495,7 @@ function wc(options = {}) {
|
|
|
404
495
|
}
|
|
405
496
|
for (const component of ctx.manifest.components) if (isLazy) {
|
|
406
497
|
/**
|
|
407
|
-
*
|
|
498
|
+
* Registration bridge module consumed by Vue / React wrappers.
|
|
408
499
|
*
|
|
409
500
|
* It only registers lazy Proxy Elements.
|
|
410
501
|
* It does not import the real component implementation.
|
|
@@ -489,17 +580,18 @@ export {};
|
|
|
489
580
|
fileName: joinPath("types/jsx.d.ts"),
|
|
490
581
|
source: (0, _zeus_js_component_dts.generateWCJsxDts)(ctx.manifest)
|
|
491
582
|
});
|
|
492
|
-
}
|
|
583
|
+
}
|
|
584
|
+
if (normalized.manifestFile) files.push({
|
|
493
585
|
type: "asset",
|
|
494
586
|
fileName: normalized.manifestFile,
|
|
495
587
|
source: generateZeusComponentsManifest(ctx.manifest)
|
|
496
588
|
});
|
|
497
|
-
if (
|
|
589
|
+
if (normalized.customElementsFile) files.push({
|
|
498
590
|
type: "asset",
|
|
499
591
|
fileName: normalized.customElementsFile,
|
|
500
592
|
source: generateCustomElementsJson({
|
|
501
593
|
manifest: ctx.manifest,
|
|
502
|
-
getModulePath: (component) => joinPath(getFileName(component.tag))
|
|
594
|
+
getModulePath: (component) => isLazy ? joinPath(getLazyEntryFileName(normalized.entryFileName, component.tag)) : joinPath(getFileName(component.tag))
|
|
503
595
|
})
|
|
504
596
|
});
|
|
505
597
|
if (!isLazy && (dts || jsxDts)) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* output-wc v0.1.0-beta.
|
|
2
|
+
* output-wc v0.1.0-beta.5
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -54,7 +54,10 @@ function generateCustomElementsJson(options) {
|
|
|
54
54
|
events: generateEvents(component),
|
|
55
55
|
slots: generateSlots(component),
|
|
56
56
|
cssParts: component.cssParts.map((name) => ({ name })),
|
|
57
|
-
cssProperties: component.
|
|
57
|
+
cssProperties: getCssVars(component).map((variable) => ({
|
|
58
|
+
name: variable.name,
|
|
59
|
+
description: variable.description
|
|
60
|
+
}))
|
|
58
61
|
}],
|
|
59
62
|
exports: [{
|
|
60
63
|
kind: "js",
|
|
@@ -84,7 +87,8 @@ function generateAttributes(component) {
|
|
|
84
87
|
return result;
|
|
85
88
|
}
|
|
86
89
|
function generateMembers(component) {
|
|
87
|
-
|
|
90
|
+
var _component$methods;
|
|
91
|
+
const fields = Object.entries(component.props).map(([name, prop]) => {
|
|
88
92
|
return {
|
|
89
93
|
kind: "field",
|
|
90
94
|
name,
|
|
@@ -93,18 +97,28 @@ function generateMembers(component) {
|
|
|
93
97
|
default: prop.default === void 0 ? void 0 : JSON.stringify(prop.default)
|
|
94
98
|
};
|
|
95
99
|
});
|
|
100
|
+
const methods = Object.keys((_component$methods = component.methods) !== null && _component$methods !== void 0 ? _component$methods : {}).map((name) => {
|
|
101
|
+
return {
|
|
102
|
+
kind: "method",
|
|
103
|
+
name
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
return [...fields, ...methods];
|
|
96
107
|
}
|
|
97
108
|
function generateEvents(component) {
|
|
98
|
-
return Object.entries(component.events).map(([
|
|
109
|
+
return Object.entries(component.events).map(([key, event]) => {
|
|
110
|
+
var _event$name, _event$key;
|
|
99
111
|
return {
|
|
100
|
-
name,
|
|
112
|
+
name: (_event$name = event.name) !== null && _event$name !== void 0 ? _event$name : toKebabCase$1((_event$key = event.key) !== null && _event$key !== void 0 ? _event$key : key),
|
|
101
113
|
description: event.description,
|
|
102
114
|
type: { text: event.detail ? `CustomEvent<${formatDetailType(event.detail)}>` : "CustomEvent" }
|
|
103
115
|
};
|
|
104
116
|
});
|
|
105
117
|
}
|
|
106
118
|
function generateSlots(component) {
|
|
107
|
-
return Object.entries(component.slots).map(([
|
|
119
|
+
return Object.entries(component.slots).map(([key, slot]) => {
|
|
120
|
+
var _slot$name;
|
|
121
|
+
const name = (_slot$name = slot.name) !== null && _slot$name !== void 0 ? _slot$name : key;
|
|
108
122
|
return {
|
|
109
123
|
name: name === "default" ? "" : name,
|
|
110
124
|
description: slot.description
|
|
@@ -114,6 +128,7 @@ function generateSlots(component) {
|
|
|
114
128
|
function getAttributeName(propName, prop) {
|
|
115
129
|
if (prop.attr === false) return false;
|
|
116
130
|
if (typeof prop.attr === "string") return prop.attr;
|
|
131
|
+
if (!isAttributeBackedType$1(prop.type)) return false;
|
|
117
132
|
return propName.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
118
133
|
}
|
|
119
134
|
function formatPropType(prop) {
|
|
@@ -125,15 +140,25 @@ function formatPropType(prop) {
|
|
|
125
140
|
case "boolean": return "boolean";
|
|
126
141
|
case "array": return "unknown[]";
|
|
127
142
|
case "object": return "Record<string, unknown>";
|
|
143
|
+
case "function": return "Function";
|
|
128
144
|
default: return "unknown";
|
|
129
145
|
}
|
|
130
146
|
}
|
|
147
|
+
function isAttributeBackedType$1(type) {
|
|
148
|
+
return type === "string" || type === "number" || type === "boolean";
|
|
149
|
+
}
|
|
131
150
|
function formatDetailType(detail) {
|
|
132
151
|
return `{ ${Object.entries(detail).map(([name, type]) => `${name}: ${type}`).join("; ")} }`;
|
|
133
152
|
}
|
|
134
153
|
function normalizeModulePath(value) {
|
|
135
154
|
return value.replace(/\\/g, "/");
|
|
136
155
|
}
|
|
156
|
+
function getCssVars(component) {
|
|
157
|
+
return Object.values(component.cssVars);
|
|
158
|
+
}
|
|
159
|
+
function toKebabCase$1(value) {
|
|
160
|
+
return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
161
|
+
}
|
|
137
162
|
//#endregion
|
|
138
163
|
//#region packages/web-c/output-wc/src/imports.ts
|
|
139
164
|
function toAbsoluteImportPath(root, source) {
|
|
@@ -186,7 +211,11 @@ function generateLazyEntry(options) {
|
|
|
186
211
|
"",
|
|
187
212
|
`export function createComponent(hostRef) {`,
|
|
188
213
|
` let mounted;`,
|
|
189
|
-
` const mountState = {
|
|
214
|
+
` const mountState = {`,
|
|
215
|
+
` attributeProps: hostRef.attributeProps,`,
|
|
216
|
+
` internals: hostRef.internals,`,
|
|
217
|
+
` reflectingAttrs: hostRef.reflectingAttrs,`,
|
|
218
|
+
` };`,
|
|
190
219
|
"",
|
|
191
220
|
` return {`,
|
|
192
221
|
` connected() {`,
|
|
@@ -208,6 +237,22 @@ function generateLazyEntry(options) {
|
|
|
208
237
|
` propertyChanged(name, oldValue, newValue) {`,
|
|
209
238
|
` mounted?.propertyChanged(name, oldValue, newValue);`,
|
|
210
239
|
` },`,
|
|
240
|
+
"",
|
|
241
|
+
` formAssociated(form) {`,
|
|
242
|
+
` mounted?.formAssociated(form);`,
|
|
243
|
+
` },`,
|
|
244
|
+
"",
|
|
245
|
+
` formDisabled(disabled) {`,
|
|
246
|
+
` mounted?.formDisabled(disabled);`,
|
|
247
|
+
` },`,
|
|
248
|
+
"",
|
|
249
|
+
` formReset() {`,
|
|
250
|
+
` mounted?.formReset();`,
|
|
251
|
+
` },`,
|
|
252
|
+
"",
|
|
253
|
+
` formStateRestore(state, mode) {`,
|
|
254
|
+
` mounted?.formStateRestore(state, mode);`,
|
|
255
|
+
` },`,
|
|
211
256
|
` };`,
|
|
212
257
|
`}`,
|
|
213
258
|
"",
|
|
@@ -229,15 +274,19 @@ function generateLazyManifest(options) {
|
|
|
229
274
|
const { components, getEntryFileName } = options;
|
|
230
275
|
return `export const components = [
|
|
231
276
|
${components.map((component) => {
|
|
232
|
-
var _component$runtimePro, _component$meta$shado, _component$meta;
|
|
277
|
+
var _component$runtimePro, _component$methods, _component$meta$shado, _component$meta, _component$meta$formA, _component$meta2;
|
|
233
278
|
const entryFile = getEntryFileName(component.tag).replace(/\\/g, "/");
|
|
234
279
|
const props = generatePropsArray((_component$runtimePro = component.runtimeProps) !== null && _component$runtimePro !== void 0 ? _component$runtimePro : component.props);
|
|
280
|
+
const methods = Object.keys((_component$methods = component.methods) !== null && _component$methods !== void 0 ? _component$methods : {});
|
|
235
281
|
const importPath = entryFile.startsWith(".") ? JSON.stringify(entryFile) : JSON.stringify(`./${entryFile}`);
|
|
282
|
+
const methodLine = methods.length ? ` methods: ${JSON.stringify(methods)},\n` : "";
|
|
236
283
|
return ` {
|
|
237
284
|
tagName: ${JSON.stringify(component.tag)},
|
|
238
285
|
shadow: ${(_component$meta$shado = (_component$meta = component.meta) === null || _component$meta === void 0 ? void 0 : _component$meta.shadow) !== null && _component$meta$shado !== void 0 ? _component$meta$shado : false},
|
|
286
|
+
formAssociated: ${(_component$meta$formA = (_component$meta2 = component.meta) === null || _component$meta2 === void 0 ? void 0 : _component$meta2.formAssociated) !== null && _component$meta$formA !== void 0 ? _component$meta$formA : false},
|
|
239
287
|
load: () => import(${importPath}),
|
|
240
288
|
props: ${props},
|
|
289
|
+
${methodLine}
|
|
241
290
|
}`;
|
|
242
291
|
}).join(",\n")}
|
|
243
292
|
];
|
|
@@ -248,14 +297,16 @@ function generatePropsArray(props) {
|
|
|
248
297
|
if (entries.length === 0) return "[]";
|
|
249
298
|
return `[\n${entries.map(([name, prop]) => {
|
|
250
299
|
const parts = [`name: ${JSON.stringify(name)}`];
|
|
251
|
-
if (!isAttributeBackedType(prop.type) || prop.attr === false) parts.push("attrName: false");
|
|
300
|
+
if (!isAttributeBackedType(prop.type) && !prop.deserialize || prop.attr === false) parts.push("attrName: false");
|
|
252
301
|
else {
|
|
253
302
|
var _prop$attr;
|
|
254
303
|
const attrName = (_prop$attr = prop.attr) !== null && _prop$attr !== void 0 ? _prop$attr : toKebabCase(name);
|
|
255
304
|
if (attrName !== toKebabCase(name)) parts.push(`attrName: ${JSON.stringify(attrName)}`);
|
|
256
305
|
}
|
|
257
306
|
parts.push(`type: ${JSON.stringify(prop.type)}`);
|
|
258
|
-
if (prop.reflect && isAttributeBackedType(prop.type)) parts.push("reflect: true");
|
|
307
|
+
if (prop.reflect && (isAttributeBackedType(prop.type) || Boolean(prop.serialize))) parts.push("reflect: true");
|
|
308
|
+
if (prop.serialize) parts.push("serialize: true");
|
|
309
|
+
if (prop.deserialize) parts.push("deserialize: true");
|
|
259
310
|
return ` { ${parts.join(", ")} }`;
|
|
260
311
|
}).join(",\n")}\n ]`;
|
|
261
312
|
}
|
|
@@ -271,22 +322,60 @@ function generateLoader() {
|
|
|
271
322
|
return `import { bootstrapLazy } from "@zeus-js/web-c-runtime";
|
|
272
323
|
import { components } from "./components.manifest.js";
|
|
273
324
|
|
|
274
|
-
|
|
325
|
+
const componentsByTagName = new Map(
|
|
326
|
+
components.map(component => [component.tagName, component]),
|
|
327
|
+
);
|
|
275
328
|
|
|
276
|
-
|
|
277
|
-
|
|
329
|
+
const definedTagsByRegistry = new WeakMap();
|
|
330
|
+
|
|
331
|
+
function resolveRegistry(options) {
|
|
332
|
+
return options.registry ??
|
|
333
|
+
(typeof customElements === "undefined" ? undefined : customElements);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function getDefinedTags(registry) {
|
|
337
|
+
let definedTags = definedTagsByRegistry.get(registry);
|
|
338
|
+
|
|
339
|
+
if (!definedTags) {
|
|
340
|
+
definedTags = new Set();
|
|
341
|
+
definedTagsByRegistry.set(registry, definedTags);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return definedTags;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function defineCustomElement(tagName, options = {}) {
|
|
348
|
+
const registry = resolveRegistry(options);
|
|
349
|
+
|
|
350
|
+
if (!registry) {
|
|
278
351
|
return;
|
|
279
352
|
}
|
|
280
353
|
|
|
281
|
-
|
|
354
|
+
const component = componentsByTagName.get(tagName);
|
|
355
|
+
|
|
356
|
+
if (!component) {
|
|
357
|
+
throw new Error(\`[zeus:web-c] Unknown custom element: <\${tagName}>.\`);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const definedTags = getDefinedTags(registry);
|
|
361
|
+
|
|
362
|
+
if (definedTags.has(tagName) || registry.get(tagName)) {
|
|
363
|
+
definedTags.add(tagName);
|
|
282
364
|
return;
|
|
283
365
|
}
|
|
284
366
|
|
|
285
|
-
bootstrapLazy(
|
|
367
|
+
bootstrapLazy([component], { registry });
|
|
286
368
|
|
|
287
|
-
|
|
369
|
+
definedTags.add(tagName);
|
|
288
370
|
}
|
|
289
371
|
|
|
372
|
+
export function defineCustomElements(options = {}) {
|
|
373
|
+
for (const component of components) {
|
|
374
|
+
defineCustomElement(component.tagName, options);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export const defineLazyElement = defineCustomElement;
|
|
290
379
|
export const defineLazyElements = defineCustomElements;
|
|
291
380
|
`;
|
|
292
381
|
}
|
|
@@ -300,7 +389,9 @@ export {};
|
|
|
300
389
|
}
|
|
301
390
|
function generateLazyIndex() {
|
|
302
391
|
return `export {
|
|
392
|
+
defineCustomElement,
|
|
303
393
|
defineCustomElements,
|
|
394
|
+
defineLazyElement,
|
|
304
395
|
defineLazyElements,
|
|
305
396
|
} from "./loader.js";
|
|
306
397
|
`;
|
|
@@ -319,8 +410,8 @@ function wc(options = {}) {
|
|
|
319
410
|
outDir: (_options$outDir = options.outDir) !== null && _options$outDir !== void 0 ? _options$outDir : "wc",
|
|
320
411
|
stripPrefix: (_options$stripPrefix = options.stripPrefix) !== null && _options$stripPrefix !== void 0 ? _options$stripPrefix : false,
|
|
321
412
|
fileName: options.fileName,
|
|
322
|
-
manifestFile:
|
|
323
|
-
customElementsFile:
|
|
413
|
+
manifestFile: (_options$manifestFile = options.manifestFile) !== null && _options$manifestFile !== void 0 ? _options$manifestFile : "zeus.components.json",
|
|
414
|
+
customElementsFile: (_options$customElemen = options.customElementsFile) !== null && _options$customElemen !== void 0 ? _options$customElemen : "custom-elements.json",
|
|
324
415
|
dts: (_options$dts = options.dts) !== null && _options$dts !== void 0 ? _options$dts : true,
|
|
325
416
|
jsxDts: (_options$jsxDts = options.jsxDts) !== null && _options$jsxDts !== void 0 ? _options$jsxDts : true,
|
|
326
417
|
index: (_options$index = options.index) !== null && _options$index !== void 0 ? _options$index : true,
|
|
@@ -349,15 +440,15 @@ function wc(options = {}) {
|
|
|
349
440
|
const runtimeProps = (_component$runtimePro2 = component.runtimeProps) !== null && _component$runtimePro2 !== void 0 ? _component$runtimePro2 : {};
|
|
350
441
|
for (const [name, prop] of Object.entries(runtimeProps)) {
|
|
351
442
|
if (isAttributeBackedRuntimeProp(prop.type)) continue;
|
|
352
|
-
if (prop.attr !== void 0 && prop.attr !== false) ctx.error([
|
|
443
|
+
if (prop.attr !== void 0 && prop.attr !== false && !prop.deserialize) ctx.error([
|
|
353
444
|
`[zeus-output-wc] <${component.tag}> prop "${name}" cannot use attr:${JSON.stringify(prop.attr)} with register:"lazy".`,
|
|
354
|
-
"
|
|
355
|
-
"
|
|
445
|
+
"Non-primitive lazy attributes require a custom deserialize function.",
|
|
446
|
+
"Add deserialize or use attr:false and pass the value as a property."
|
|
356
447
|
].join("\n"));
|
|
357
|
-
if (prop.reflect) ctx.error([
|
|
448
|
+
if (prop.reflect && !prop.serialize) ctx.error([
|
|
358
449
|
`[zeus-output-wc] <${component.tag}> prop "${name}" cannot use reflect:true with register:"lazy".`,
|
|
359
|
-
"
|
|
360
|
-
"
|
|
450
|
+
"Non-primitive lazy reflection requires a custom serialize function.",
|
|
451
|
+
"Add serialize or remove reflect:true."
|
|
361
452
|
].join("\n"));
|
|
362
453
|
}
|
|
363
454
|
}
|
|
@@ -404,7 +495,7 @@ function wc(options = {}) {
|
|
|
404
495
|
}
|
|
405
496
|
for (const component of ctx.manifest.components) if (isLazy) {
|
|
406
497
|
/**
|
|
407
|
-
*
|
|
498
|
+
* Registration bridge module consumed by Vue / React wrappers.
|
|
408
499
|
*
|
|
409
500
|
* It only registers lazy Proxy Elements.
|
|
410
501
|
* It does not import the real component implementation.
|
|
@@ -489,17 +580,18 @@ export {};
|
|
|
489
580
|
fileName: joinPath("types/jsx.d.ts"),
|
|
490
581
|
source: (0, _zeus_js_component_dts.generateWCJsxDts)(ctx.manifest)
|
|
491
582
|
});
|
|
492
|
-
}
|
|
583
|
+
}
|
|
584
|
+
if (normalized.manifestFile) files.push({
|
|
493
585
|
type: "asset",
|
|
494
586
|
fileName: normalized.manifestFile,
|
|
495
587
|
source: generateZeusComponentsManifest(ctx.manifest)
|
|
496
588
|
});
|
|
497
|
-
if (
|
|
589
|
+
if (normalized.customElementsFile) files.push({
|
|
498
590
|
type: "asset",
|
|
499
591
|
fileName: normalized.customElementsFile,
|
|
500
592
|
source: generateCustomElementsJson({
|
|
501
593
|
manifest: ctx.manifest,
|
|
502
|
-
getModulePath: (component) => joinPath(getFileName(component.tag))
|
|
594
|
+
getModulePath: (component) => isLazy ? joinPath(getLazyEntryFileName(normalized.entryFileName, component.tag)) : joinPath(getFileName(component.tag))
|
|
503
595
|
})
|
|
504
596
|
});
|
|
505
597
|
if (!isLazy && (dts || jsxDts)) {
|
package/dist/output-wc.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* output-wc v0.1.0-beta.
|
|
2
|
+
* output-wc v0.1.0-beta.5
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -27,7 +27,10 @@ function generateCustomElementsJson(options) {
|
|
|
27
27
|
events: generateEvents(component),
|
|
28
28
|
slots: generateSlots(component),
|
|
29
29
|
cssParts: component.cssParts.map((name) => ({ name })),
|
|
30
|
-
cssProperties: component.
|
|
30
|
+
cssProperties: getCssVars(component).map((variable) => ({
|
|
31
|
+
name: variable.name,
|
|
32
|
+
description: variable.description
|
|
33
|
+
}))
|
|
31
34
|
}],
|
|
32
35
|
exports: [{
|
|
33
36
|
kind: "js",
|
|
@@ -57,7 +60,8 @@ function generateAttributes(component) {
|
|
|
57
60
|
return result;
|
|
58
61
|
}
|
|
59
62
|
function generateMembers(component) {
|
|
60
|
-
|
|
63
|
+
var _component$methods;
|
|
64
|
+
const fields = Object.entries(component.props).map(([name, prop]) => {
|
|
61
65
|
return {
|
|
62
66
|
kind: "field",
|
|
63
67
|
name,
|
|
@@ -66,18 +70,28 @@ function generateMembers(component) {
|
|
|
66
70
|
default: prop.default === void 0 ? void 0 : JSON.stringify(prop.default)
|
|
67
71
|
};
|
|
68
72
|
});
|
|
73
|
+
const methods = Object.keys((_component$methods = component.methods) !== null && _component$methods !== void 0 ? _component$methods : {}).map((name) => {
|
|
74
|
+
return {
|
|
75
|
+
kind: "method",
|
|
76
|
+
name
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
return [...fields, ...methods];
|
|
69
80
|
}
|
|
70
81
|
function generateEvents(component) {
|
|
71
|
-
return Object.entries(component.events).map(([
|
|
82
|
+
return Object.entries(component.events).map(([key, event]) => {
|
|
83
|
+
var _event$name, _event$key;
|
|
72
84
|
return {
|
|
73
|
-
name,
|
|
85
|
+
name: (_event$name = event.name) !== null && _event$name !== void 0 ? _event$name : toKebabCase$1((_event$key = event.key) !== null && _event$key !== void 0 ? _event$key : key),
|
|
74
86
|
description: event.description,
|
|
75
87
|
type: { text: event.detail ? `CustomEvent<${formatDetailType(event.detail)}>` : "CustomEvent" }
|
|
76
88
|
};
|
|
77
89
|
});
|
|
78
90
|
}
|
|
79
91
|
function generateSlots(component) {
|
|
80
|
-
return Object.entries(component.slots).map(([
|
|
92
|
+
return Object.entries(component.slots).map(([key, slot]) => {
|
|
93
|
+
var _slot$name;
|
|
94
|
+
const name = (_slot$name = slot.name) !== null && _slot$name !== void 0 ? _slot$name : key;
|
|
81
95
|
return {
|
|
82
96
|
name: name === "default" ? "" : name,
|
|
83
97
|
description: slot.description
|
|
@@ -87,6 +101,7 @@ function generateSlots(component) {
|
|
|
87
101
|
function getAttributeName(propName, prop) {
|
|
88
102
|
if (prop.attr === false) return false;
|
|
89
103
|
if (typeof prop.attr === "string") return prop.attr;
|
|
104
|
+
if (!isAttributeBackedType$1(prop.type)) return false;
|
|
90
105
|
return propName.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
91
106
|
}
|
|
92
107
|
function formatPropType(prop) {
|
|
@@ -98,15 +113,25 @@ function formatPropType(prop) {
|
|
|
98
113
|
case "boolean": return "boolean";
|
|
99
114
|
case "array": return "unknown[]";
|
|
100
115
|
case "object": return "Record<string, unknown>";
|
|
116
|
+
case "function": return "Function";
|
|
101
117
|
default: return "unknown";
|
|
102
118
|
}
|
|
103
119
|
}
|
|
120
|
+
function isAttributeBackedType$1(type) {
|
|
121
|
+
return type === "string" || type === "number" || type === "boolean";
|
|
122
|
+
}
|
|
104
123
|
function formatDetailType(detail) {
|
|
105
124
|
return `{ ${Object.entries(detail).map(([name, type]) => `${name}: ${type}`).join("; ")} }`;
|
|
106
125
|
}
|
|
107
126
|
function normalizeModulePath(value) {
|
|
108
127
|
return value.replace(/\\/g, "/");
|
|
109
128
|
}
|
|
129
|
+
function getCssVars(component) {
|
|
130
|
+
return Object.values(component.cssVars);
|
|
131
|
+
}
|
|
132
|
+
function toKebabCase$1(value) {
|
|
133
|
+
return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
134
|
+
}
|
|
110
135
|
//#endregion
|
|
111
136
|
//#region packages/web-c/output-wc/src/imports.ts
|
|
112
137
|
function toAbsoluteImportPath(root, source) {
|
|
@@ -159,7 +184,11 @@ function generateLazyEntry(options) {
|
|
|
159
184
|
"",
|
|
160
185
|
`export function createComponent(hostRef) {`,
|
|
161
186
|
` let mounted;`,
|
|
162
|
-
` const mountState = {
|
|
187
|
+
` const mountState = {`,
|
|
188
|
+
` attributeProps: hostRef.attributeProps,`,
|
|
189
|
+
` internals: hostRef.internals,`,
|
|
190
|
+
` reflectingAttrs: hostRef.reflectingAttrs,`,
|
|
191
|
+
` };`,
|
|
163
192
|
"",
|
|
164
193
|
` return {`,
|
|
165
194
|
` connected() {`,
|
|
@@ -181,6 +210,22 @@ function generateLazyEntry(options) {
|
|
|
181
210
|
` propertyChanged(name, oldValue, newValue) {`,
|
|
182
211
|
` mounted?.propertyChanged(name, oldValue, newValue);`,
|
|
183
212
|
` },`,
|
|
213
|
+
"",
|
|
214
|
+
` formAssociated(form) {`,
|
|
215
|
+
` mounted?.formAssociated(form);`,
|
|
216
|
+
` },`,
|
|
217
|
+
"",
|
|
218
|
+
` formDisabled(disabled) {`,
|
|
219
|
+
` mounted?.formDisabled(disabled);`,
|
|
220
|
+
` },`,
|
|
221
|
+
"",
|
|
222
|
+
` formReset() {`,
|
|
223
|
+
` mounted?.formReset();`,
|
|
224
|
+
` },`,
|
|
225
|
+
"",
|
|
226
|
+
` formStateRestore(state, mode) {`,
|
|
227
|
+
` mounted?.formStateRestore(state, mode);`,
|
|
228
|
+
` },`,
|
|
184
229
|
` };`,
|
|
185
230
|
`}`,
|
|
186
231
|
"",
|
|
@@ -202,15 +247,19 @@ function generateLazyManifest(options) {
|
|
|
202
247
|
const { components, getEntryFileName } = options;
|
|
203
248
|
return `export const components = [
|
|
204
249
|
${components.map((component) => {
|
|
205
|
-
var _component$runtimePro, _component$meta$shado, _component$meta;
|
|
250
|
+
var _component$runtimePro, _component$methods, _component$meta$shado, _component$meta, _component$meta$formA, _component$meta2;
|
|
206
251
|
const entryFile = getEntryFileName(component.tag).replace(/\\/g, "/");
|
|
207
252
|
const props = generatePropsArray((_component$runtimePro = component.runtimeProps) !== null && _component$runtimePro !== void 0 ? _component$runtimePro : component.props);
|
|
253
|
+
const methods = Object.keys((_component$methods = component.methods) !== null && _component$methods !== void 0 ? _component$methods : {});
|
|
208
254
|
const importPath = entryFile.startsWith(".") ? JSON.stringify(entryFile) : JSON.stringify(`./${entryFile}`);
|
|
255
|
+
const methodLine = methods.length ? ` methods: ${JSON.stringify(methods)},\n` : "";
|
|
209
256
|
return ` {
|
|
210
257
|
tagName: ${JSON.stringify(component.tag)},
|
|
211
258
|
shadow: ${(_component$meta$shado = (_component$meta = component.meta) === null || _component$meta === void 0 ? void 0 : _component$meta.shadow) !== null && _component$meta$shado !== void 0 ? _component$meta$shado : false},
|
|
259
|
+
formAssociated: ${(_component$meta$formA = (_component$meta2 = component.meta) === null || _component$meta2 === void 0 ? void 0 : _component$meta2.formAssociated) !== null && _component$meta$formA !== void 0 ? _component$meta$formA : false},
|
|
212
260
|
load: () => import(${importPath}),
|
|
213
261
|
props: ${props},
|
|
262
|
+
${methodLine}
|
|
214
263
|
}`;
|
|
215
264
|
}).join(",\n")}
|
|
216
265
|
];
|
|
@@ -221,14 +270,16 @@ function generatePropsArray(props) {
|
|
|
221
270
|
if (entries.length === 0) return "[]";
|
|
222
271
|
return `[\n${entries.map(([name, prop]) => {
|
|
223
272
|
const parts = [`name: ${JSON.stringify(name)}`];
|
|
224
|
-
if (!isAttributeBackedType(prop.type) || prop.attr === false) parts.push("attrName: false");
|
|
273
|
+
if (!isAttributeBackedType(prop.type) && !prop.deserialize || prop.attr === false) parts.push("attrName: false");
|
|
225
274
|
else {
|
|
226
275
|
var _prop$attr;
|
|
227
276
|
const attrName = (_prop$attr = prop.attr) !== null && _prop$attr !== void 0 ? _prop$attr : toKebabCase(name);
|
|
228
277
|
if (attrName !== toKebabCase(name)) parts.push(`attrName: ${JSON.stringify(attrName)}`);
|
|
229
278
|
}
|
|
230
279
|
parts.push(`type: ${JSON.stringify(prop.type)}`);
|
|
231
|
-
if (prop.reflect && isAttributeBackedType(prop.type)) parts.push("reflect: true");
|
|
280
|
+
if (prop.reflect && (isAttributeBackedType(prop.type) || Boolean(prop.serialize))) parts.push("reflect: true");
|
|
281
|
+
if (prop.serialize) parts.push("serialize: true");
|
|
282
|
+
if (prop.deserialize) parts.push("deserialize: true");
|
|
232
283
|
return ` { ${parts.join(", ")} }`;
|
|
233
284
|
}).join(",\n")}\n ]`;
|
|
234
285
|
}
|
|
@@ -244,22 +295,60 @@ function generateLoader() {
|
|
|
244
295
|
return `import { bootstrapLazy } from "@zeus-js/web-c-runtime";
|
|
245
296
|
import { components } from "./components.manifest.js";
|
|
246
297
|
|
|
247
|
-
|
|
298
|
+
const componentsByTagName = new Map(
|
|
299
|
+
components.map(component => [component.tagName, component]),
|
|
300
|
+
);
|
|
248
301
|
|
|
249
|
-
|
|
250
|
-
|
|
302
|
+
const definedTagsByRegistry = new WeakMap();
|
|
303
|
+
|
|
304
|
+
function resolveRegistry(options) {
|
|
305
|
+
return options.registry ??
|
|
306
|
+
(typeof customElements === "undefined" ? undefined : customElements);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function getDefinedTags(registry) {
|
|
310
|
+
let definedTags = definedTagsByRegistry.get(registry);
|
|
311
|
+
|
|
312
|
+
if (!definedTags) {
|
|
313
|
+
definedTags = new Set();
|
|
314
|
+
definedTagsByRegistry.set(registry, definedTags);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return definedTags;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function defineCustomElement(tagName, options = {}) {
|
|
321
|
+
const registry = resolveRegistry(options);
|
|
322
|
+
|
|
323
|
+
if (!registry) {
|
|
251
324
|
return;
|
|
252
325
|
}
|
|
253
326
|
|
|
254
|
-
|
|
327
|
+
const component = componentsByTagName.get(tagName);
|
|
328
|
+
|
|
329
|
+
if (!component) {
|
|
330
|
+
throw new Error(\`[zeus:web-c] Unknown custom element: <\${tagName}>.\`);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const definedTags = getDefinedTags(registry);
|
|
334
|
+
|
|
335
|
+
if (definedTags.has(tagName) || registry.get(tagName)) {
|
|
336
|
+
definedTags.add(tagName);
|
|
255
337
|
return;
|
|
256
338
|
}
|
|
257
339
|
|
|
258
|
-
bootstrapLazy(
|
|
340
|
+
bootstrapLazy([component], { registry });
|
|
259
341
|
|
|
260
|
-
|
|
342
|
+
definedTags.add(tagName);
|
|
261
343
|
}
|
|
262
344
|
|
|
345
|
+
export function defineCustomElements(options = {}) {
|
|
346
|
+
for (const component of components) {
|
|
347
|
+
defineCustomElement(component.tagName, options);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export const defineLazyElement = defineCustomElement;
|
|
263
352
|
export const defineLazyElements = defineCustomElements;
|
|
264
353
|
`;
|
|
265
354
|
}
|
|
@@ -273,7 +362,9 @@ export {};
|
|
|
273
362
|
}
|
|
274
363
|
function generateLazyIndex() {
|
|
275
364
|
return `export {
|
|
365
|
+
defineCustomElement,
|
|
276
366
|
defineCustomElements,
|
|
367
|
+
defineLazyElement,
|
|
277
368
|
defineLazyElements,
|
|
278
369
|
} from "./loader.js";
|
|
279
370
|
`;
|
|
@@ -292,8 +383,8 @@ function wc(options = {}) {
|
|
|
292
383
|
outDir: (_options$outDir = options.outDir) !== null && _options$outDir !== void 0 ? _options$outDir : "wc",
|
|
293
384
|
stripPrefix: (_options$stripPrefix = options.stripPrefix) !== null && _options$stripPrefix !== void 0 ? _options$stripPrefix : false,
|
|
294
385
|
fileName: options.fileName,
|
|
295
|
-
manifestFile:
|
|
296
|
-
customElementsFile:
|
|
386
|
+
manifestFile: (_options$manifestFile = options.manifestFile) !== null && _options$manifestFile !== void 0 ? _options$manifestFile : "zeus.components.json",
|
|
387
|
+
customElementsFile: (_options$customElemen = options.customElementsFile) !== null && _options$customElemen !== void 0 ? _options$customElemen : "custom-elements.json",
|
|
297
388
|
dts: (_options$dts = options.dts) !== null && _options$dts !== void 0 ? _options$dts : true,
|
|
298
389
|
jsxDts: (_options$jsxDts = options.jsxDts) !== null && _options$jsxDts !== void 0 ? _options$jsxDts : true,
|
|
299
390
|
index: (_options$index = options.index) !== null && _options$index !== void 0 ? _options$index : true,
|
|
@@ -322,15 +413,15 @@ function wc(options = {}) {
|
|
|
322
413
|
const runtimeProps = (_component$runtimePro2 = component.runtimeProps) !== null && _component$runtimePro2 !== void 0 ? _component$runtimePro2 : {};
|
|
323
414
|
for (const [name, prop] of Object.entries(runtimeProps)) {
|
|
324
415
|
if (isAttributeBackedRuntimeProp(prop.type)) continue;
|
|
325
|
-
if (prop.attr !== void 0 && prop.attr !== false) ctx.error([
|
|
416
|
+
if (prop.attr !== void 0 && prop.attr !== false && !prop.deserialize) ctx.error([
|
|
326
417
|
`[zeus-output-wc] <${component.tag}> prop "${name}" cannot use attr:${JSON.stringify(prop.attr)} with register:"lazy".`,
|
|
327
|
-
"
|
|
328
|
-
"
|
|
418
|
+
"Non-primitive lazy attributes require a custom deserialize function.",
|
|
419
|
+
"Add deserialize or use attr:false and pass the value as a property."
|
|
329
420
|
].join("\n"));
|
|
330
|
-
if (prop.reflect) ctx.error([
|
|
421
|
+
if (prop.reflect && !prop.serialize) ctx.error([
|
|
331
422
|
`[zeus-output-wc] <${component.tag}> prop "${name}" cannot use reflect:true with register:"lazy".`,
|
|
332
|
-
"
|
|
333
|
-
"
|
|
423
|
+
"Non-primitive lazy reflection requires a custom serialize function.",
|
|
424
|
+
"Add serialize or remove reflect:true."
|
|
334
425
|
].join("\n"));
|
|
335
426
|
}
|
|
336
427
|
}
|
|
@@ -377,7 +468,7 @@ function wc(options = {}) {
|
|
|
377
468
|
}
|
|
378
469
|
for (const component of ctx.manifest.components) if (isLazy) {
|
|
379
470
|
/**
|
|
380
|
-
*
|
|
471
|
+
* Registration bridge module consumed by Vue / React wrappers.
|
|
381
472
|
*
|
|
382
473
|
* It only registers lazy Proxy Elements.
|
|
383
474
|
* It does not import the real component implementation.
|
|
@@ -462,17 +553,18 @@ export {};
|
|
|
462
553
|
fileName: joinPath("types/jsx.d.ts"),
|
|
463
554
|
source: generateWCJsxDts(ctx.manifest)
|
|
464
555
|
});
|
|
465
|
-
}
|
|
556
|
+
}
|
|
557
|
+
if (normalized.manifestFile) files.push({
|
|
466
558
|
type: "asset",
|
|
467
559
|
fileName: normalized.manifestFile,
|
|
468
560
|
source: generateZeusComponentsManifest(ctx.manifest)
|
|
469
561
|
});
|
|
470
|
-
if (
|
|
562
|
+
if (normalized.customElementsFile) files.push({
|
|
471
563
|
type: "asset",
|
|
472
564
|
fileName: normalized.customElementsFile,
|
|
473
565
|
source: generateCustomElementsJson({
|
|
474
566
|
manifest: ctx.manifest,
|
|
475
|
-
getModulePath: (component) => joinPath(getFileName(component.tag))
|
|
567
|
+
getModulePath: (component) => isLazy ? joinPath(getLazyEntryFileName(normalized.entryFileName, component.tag)) : joinPath(getFileName(component.tag))
|
|
476
568
|
})
|
|
477
569
|
});
|
|
478
570
|
if (!isLazy && (dts || jsxDts)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeus-js/output-wc",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.5",
|
|
4
4
|
"description": "Zeus Web Component output plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
]
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@zeus-js/bundler-plugin": "0.1.0-beta.
|
|
56
|
-
"@zeus-js/component-analyzer": "0.1.0-beta.
|
|
57
|
-
"@zeus-js/runtime-dom": "0.1.0-beta.
|
|
58
|
-
"@zeus-js/
|
|
59
|
-
"@zeus-js/
|
|
55
|
+
"@zeus-js/bundler-plugin": "0.1.0-beta.5",
|
|
56
|
+
"@zeus-js/component-analyzer": "0.1.0-beta.5",
|
|
57
|
+
"@zeus-js/runtime-dom": "0.1.0-beta.5",
|
|
58
|
+
"@zeus-js/web-c-runtime": "0.2.0",
|
|
59
|
+
"@zeus-js/component-dts": "0.1.0-beta.5"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"rollup": "^4.0.0"
|