@openwebf/webf 0.23.10 → 0.24.1
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 +8 -0
- package/bin/webf.js +9 -1
- package/dist/agents.js +245 -0
- package/dist/commands.js +101 -7
- package/dist/generator.js +37 -36
- package/dist/module.js +43 -14
- package/dist/peerDeps.js +27 -0
- package/dist/react.js +10 -18
- package/dist/vue.js +138 -132
- package/package.json +2 -1
- package/src/agents.ts +267 -0
- package/src/commands.ts +110 -8
- package/src/generator.ts +38 -37
- package/src/module.ts +53 -21
- package/src/peerDeps.ts +21 -0
- package/src/react.ts +10 -18
- package/src/vue.ts +157 -142
- package/templates/react.component.tsx.tpl +2 -2
- package/templates/react.index.ts.tpl +2 -1
- package/templates/react.package.json.tpl +3 -4
- package/templates/react.tsconfig.json.tpl +8 -1
- package/templates/react.tsup.config.ts.tpl +1 -1
- package/templates/vue.component.partial.tpl +4 -4
- package/templates/vue.components.d.ts.tpl +24 -9
- package/templates/vue.package.json.tpl +3 -1
- package/test/agents-init.test.ts +80 -0
- package/test/commands.test.ts +5 -12
- package/test/generator.test.ts +17 -10
- package/test/peerDeps.test.ts +30 -0
- package/test/react-consts.test.ts +9 -3
- package/test/standard-props.test.ts +14 -14
- package/test/templates.test.ts +17 -0
- package/test/vue.test.ts +36 -11
- package/dist/constants.js +0 -242
package/src/react.ts
CHANGED
|
@@ -52,13 +52,12 @@ function generateReturnType(type: ParameterType): string {
|
|
|
52
52
|
return pointerType;
|
|
53
53
|
}
|
|
54
54
|
if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
|
|
55
|
-
const elemType =
|
|
56
|
-
|
|
57
|
-
if (elemType
|
|
58
|
-
|
|
59
|
-
return `(${elemType})[]`;
|
|
55
|
+
const elemType = generateReturnType(type.value);
|
|
56
|
+
if (!elemType) return 'any[]';
|
|
57
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
|
|
58
|
+
return `${elemType}[]`;
|
|
60
59
|
}
|
|
61
|
-
return
|
|
60
|
+
return `(${elemType})[]`;
|
|
62
61
|
}
|
|
63
62
|
switch (type.value) {
|
|
64
63
|
case FunctionArgumentType.int:
|
|
@@ -387,19 +386,12 @@ export function generateReactComponent(blob: IDLBlob, packageName?: string, rela
|
|
|
387
386
|
return pointerType;
|
|
388
387
|
}
|
|
389
388
|
if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
|
|
390
|
-
const elemType =
|
|
391
|
-
if (elemType
|
|
392
|
-
if (
|
|
393
|
-
|
|
394
|
-
return `(typeof __webfTypes.${ident})[]`;
|
|
395
|
-
}
|
|
396
|
-
if (typeof elemType === 'string' && /^(?:[A-Za-z_][A-Za-z0-9_]*)(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
|
|
397
|
-
const base = elemType.split('.')[0];
|
|
398
|
-
if (!localTypeNames.has(base)) {
|
|
399
|
-
return `__webfTypes.${elemType}[]`;
|
|
400
|
-
}
|
|
389
|
+
const elemType = genRT(type.value);
|
|
390
|
+
if (!elemType) return 'any[]';
|
|
391
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
|
|
392
|
+
return `${elemType}[]`;
|
|
401
393
|
}
|
|
402
|
-
return
|
|
394
|
+
return `(${elemType})[]`;
|
|
403
395
|
}
|
|
404
396
|
switch (type.value) {
|
|
405
397
|
case FunctionArgumentType.int:
|
package/src/vue.ts
CHANGED
|
@@ -2,10 +2,9 @@ import _ from "lodash";
|
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import {ParameterType} from "./analyzer";
|
|
5
|
-
import {ClassObject, FunctionArgumentType, FunctionDeclaration, ConstObject, EnumObject} from "./declaration";
|
|
5
|
+
import {ClassObject, FunctionArgumentType, FunctionDeclaration, ConstObject, EnumObject, TypeAliasObject} from "./declaration";
|
|
6
6
|
import {IDLBlob} from "./IDLBlob";
|
|
7
|
-
import {
|
|
8
|
-
import {getPointerType, isPointerType, isUnionType, trimNullTypeFromType} from "./utils";
|
|
7
|
+
import {getPointerType, isPointerType, isUnionType} from "./utils";
|
|
9
8
|
|
|
10
9
|
function readTemplate(name: string) {
|
|
11
10
|
return fs.readFileSync(path.join(__dirname, '../templates/' + name + '.tpl'), {encoding: 'utf-8'});
|
|
@@ -49,18 +48,17 @@ function generateReturnType(type: ParameterType): string {
|
|
|
49
48
|
if (pointerType === 'Type') return 'any';
|
|
50
49
|
if (typeof pointerType === 'string' && pointerType.startsWith('typeof ')) {
|
|
51
50
|
const ident = pointerType.substring('typeof '.length).trim();
|
|
52
|
-
return `typeof
|
|
51
|
+
return `typeof ${ident}`;
|
|
53
52
|
}
|
|
54
53
|
return pointerType;
|
|
55
54
|
}
|
|
56
55
|
if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
|
|
57
|
-
const elemType =
|
|
58
|
-
if (elemType
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
return `(typeof __webfTypes.${ident})[]`;
|
|
56
|
+
const elemType = generateReturnType(type.value);
|
|
57
|
+
if (!elemType) return 'any[]';
|
|
58
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
|
|
59
|
+
return `${elemType}[]`;
|
|
62
60
|
}
|
|
63
|
-
return
|
|
61
|
+
return `(${elemType})[]`;
|
|
64
62
|
}
|
|
65
63
|
switch (type.value) {
|
|
66
64
|
case FunctionArgumentType.int:
|
|
@@ -112,148 +110,139 @@ function generateMethodDeclaration(method: FunctionDeclaration) {
|
|
|
112
110
|
return `${methodName}(${args}): ${returnType};`;
|
|
113
111
|
}
|
|
114
112
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
const classObjectDictionary = Object.fromEntries(
|
|
123
|
-
classObjects.map(object => {
|
|
124
|
-
return [object.name, object];
|
|
125
|
-
})
|
|
126
|
-
);
|
|
113
|
+
type VueComponentSpec = {
|
|
114
|
+
className: string;
|
|
115
|
+
properties?: ClassObject;
|
|
116
|
+
events?: ClassObject;
|
|
117
|
+
methods?: ClassObject;
|
|
118
|
+
};
|
|
127
119
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const events = classObjects.filter(object => {
|
|
132
|
-
return object.name.endsWith('Events');
|
|
133
|
-
});
|
|
120
|
+
function getVueComponentSpecs(blob: IDLBlob): VueComponentSpec[] {
|
|
121
|
+
const classObjects = blob.objects.filter(obj => obj instanceof ClassObject) as ClassObject[];
|
|
122
|
+
if (classObjects.length === 0) return [];
|
|
134
123
|
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
});
|
|
124
|
+
const properties = classObjects.filter(object => object.name.endsWith('Properties'));
|
|
125
|
+
const events = classObjects.filter(object => object.name.endsWith('Events'));
|
|
126
|
+
const methods = classObjects.filter(object => object.name.endsWith('Methods'));
|
|
139
127
|
|
|
140
|
-
const
|
|
141
|
-
if (!object || !object.props || object.props.length === 0) {
|
|
142
|
-
return '';
|
|
143
|
-
}
|
|
128
|
+
const componentMap = new Map<string, VueComponentSpec>();
|
|
144
129
|
|
|
145
|
-
|
|
130
|
+
properties.forEach(prop => {
|
|
131
|
+
const className = prop.name.replace(/Properties$/, '');
|
|
132
|
+
if (!componentMap.has(className)) componentMap.set(className, { className });
|
|
133
|
+
componentMap.get(className)!.properties = prop;
|
|
134
|
+
});
|
|
146
135
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
interfaceLines.push(' */');
|
|
153
|
-
}
|
|
136
|
+
events.forEach(ev => {
|
|
137
|
+
const className = ev.name.replace(/Events$/, '');
|
|
138
|
+
if (!componentMap.has(className)) componentMap.set(className, { className });
|
|
139
|
+
componentMap.get(className)!.events = ev;
|
|
140
|
+
});
|
|
154
141
|
|
|
155
|
-
|
|
142
|
+
methods.forEach(m => {
|
|
143
|
+
const className = m.name.replace(/Methods$/, '');
|
|
144
|
+
if (!componentMap.has(className)) componentMap.set(className, { className });
|
|
145
|
+
componentMap.get(className)!.methods = m;
|
|
146
|
+
});
|
|
156
147
|
|
|
157
|
-
|
|
158
|
-
|
|
148
|
+
return Array.from(componentMap.values())
|
|
149
|
+
.filter(spec => spec.className.trim().length > 0)
|
|
150
|
+
.sort((a, b) => a.className.localeCompare(b.className));
|
|
151
|
+
}
|
|
159
152
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
153
|
+
function renderSupportingInterface(object: ClassObject): string {
|
|
154
|
+
const hasProps = !!object.props && object.props.length > 0;
|
|
155
|
+
const hasMethods = !!object.methods && object.methods.length > 0;
|
|
156
|
+
if (!hasProps && !hasMethods) {
|
|
157
|
+
return '';
|
|
158
|
+
}
|
|
167
159
|
|
|
168
|
-
|
|
169
|
-
lines.push(` ${prop.name}${optionalToken}: ${generateReturnType(prop.type)};`);
|
|
160
|
+
const interfaceLines: string[] = [];
|
|
170
161
|
|
|
171
|
-
|
|
162
|
+
if (object.documentation && object.documentation.trim().length > 0) {
|
|
163
|
+
interfaceLines.push('/**');
|
|
164
|
+
object.documentation.split('\n').forEach(line => {
|
|
165
|
+
interfaceLines.push(` * ${line}`);
|
|
172
166
|
});
|
|
167
|
+
interfaceLines.push(' */');
|
|
168
|
+
}
|
|
173
169
|
|
|
174
|
-
|
|
175
|
-
interfaceLines.push('}');
|
|
170
|
+
interfaceLines.push(`export interface ${object.name} {`);
|
|
176
171
|
|
|
177
|
-
|
|
178
|
-
|
|
172
|
+
const propLines = (object.props || []).map(prop => {
|
|
173
|
+
const lines: string[] = [];
|
|
179
174
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (componentEvents) {
|
|
187
|
-
return componentEvents.name.replace(/Events$/, '');
|
|
175
|
+
if (prop.documentation && prop.documentation.trim().length > 0) {
|
|
176
|
+
lines.push(' /**');
|
|
177
|
+
prop.documentation.split('\n').forEach(line => {
|
|
178
|
+
lines.push(` * ${line}`);
|
|
179
|
+
});
|
|
180
|
+
lines.push(' */');
|
|
188
181
|
}
|
|
189
|
-
return '';
|
|
190
|
-
})();
|
|
191
182
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
183
|
+
const optionalToken = prop.optional ? '?' : '';
|
|
184
|
+
lines.push(` ${prop.name}${optionalToken}: ${generateReturnType(prop.type)};`);
|
|
195
185
|
|
|
196
|
-
|
|
197
|
-
className: className,
|
|
198
|
-
properties: componentProperties,
|
|
199
|
-
events: componentEvents,
|
|
200
|
-
classObjectDictionary,
|
|
201
|
-
dependencies,
|
|
202
|
-
blob,
|
|
203
|
-
generateReturnType,
|
|
204
|
-
generateMethodDeclaration,
|
|
205
|
-
generateEventHandlerType,
|
|
186
|
+
return lines.join('\n');
|
|
206
187
|
});
|
|
207
188
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
189
|
+
interfaceLines.push(propLines.join('\n'));
|
|
190
|
+
|
|
191
|
+
if (object.methods && object.methods.length > 0) {
|
|
192
|
+
const methodLines = object.methods.map(method => {
|
|
193
|
+
return ` ${generateMethodDeclaration(method)}`;
|
|
194
|
+
});
|
|
195
|
+
interfaceLines.push(methodLines.join('\n'));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
interfaceLines.push('}');
|
|
211
199
|
|
|
212
|
-
return
|
|
200
|
+
return interfaceLines.join('\n');
|
|
213
201
|
}
|
|
214
202
|
|
|
215
|
-
function toVueTagName(
|
|
203
|
+
function toVueTagName(rawClassName: string): string {
|
|
204
|
+
const className = rawClassName.trim();
|
|
205
|
+
|
|
216
206
|
if (className.startsWith('WebF')) {
|
|
217
207
|
const withoutPrefix = className.substring(4);
|
|
218
|
-
|
|
219
|
-
|
|
208
|
+
const suffix = _.kebabCase(withoutPrefix);
|
|
209
|
+
return suffix.length > 0 ? 'webf-' + suffix : 'webf';
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (className.startsWith('Flutter')) {
|
|
220
213
|
const withoutPrefix = className.substring(7);
|
|
221
|
-
|
|
214
|
+
const suffix = _.kebabCase(withoutPrefix);
|
|
215
|
+
return suffix.length > 0 ? 'flutter-' + suffix : 'flutter';
|
|
222
216
|
}
|
|
223
|
-
|
|
217
|
+
|
|
218
|
+
const kebab = _.kebabCase(className);
|
|
219
|
+
return kebab.replace(/^web-f-/, 'webf-');
|
|
224
220
|
}
|
|
225
221
|
|
|
226
222
|
export function generateVueTypings(blobs: IDLBlob[]) {
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
223
|
+
const componentSpecMap = new Map<string, VueComponentSpec>();
|
|
224
|
+
blobs
|
|
225
|
+
.flatMap(blob => getVueComponentSpecs(blob))
|
|
226
|
+
.forEach(spec => {
|
|
227
|
+
if (!componentSpecMap.has(spec.className)) componentSpecMap.set(spec.className, spec);
|
|
232
228
|
});
|
|
233
|
-
|
|
234
|
-
|
|
229
|
+
|
|
230
|
+
const componentSpecs = Array.from(componentSpecMap.values()).sort((a, b) => a.className.localeCompare(b.className));
|
|
231
|
+
const componentNames = componentSpecs.map(spec => spec.className);
|
|
232
|
+
|
|
233
|
+
const components = componentSpecs.map(spec => {
|
|
234
|
+
const content = _.template(readTemplate('vue.component.partial'))({
|
|
235
|
+
className: spec.className,
|
|
236
|
+
properties: spec.properties,
|
|
237
|
+
events: spec.events,
|
|
238
|
+
methods: spec.methods,
|
|
239
|
+
generateReturnType,
|
|
240
|
+
generateMethodDeclaration,
|
|
241
|
+
generateEventHandlerType,
|
|
235
242
|
});
|
|
236
243
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const className = (() => {
|
|
240
|
-
if (componentProperties) {
|
|
241
|
-
return componentProperties.name.replace(/Properties$/, '');
|
|
242
|
-
}
|
|
243
|
-
if (componentEvents) {
|
|
244
|
-
return componentEvents.name.replace(/Events$/, '');
|
|
245
|
-
}
|
|
246
|
-
return '';
|
|
247
|
-
})();
|
|
248
|
-
return className;
|
|
249
|
-
}).filter(name => {
|
|
250
|
-
return name.length > 0;
|
|
251
|
-
});
|
|
252
|
-
const components = blobs.map(blob => {
|
|
253
|
-
return generateVueComponent(blob);
|
|
254
|
-
}).filter(component => {
|
|
255
|
-
return component.length > 0;
|
|
256
|
-
}).join('\n\n');
|
|
244
|
+
return content.split('\n').filter(str => str.trim().length > 0).join('\n');
|
|
245
|
+
}).filter(Boolean).join('\n\n');
|
|
257
246
|
|
|
258
247
|
// Collect declare consts across blobs and render as exported ambient declarations
|
|
259
248
|
const consts = blobs
|
|
@@ -267,6 +256,7 @@ export function generateVueTypings(blobs: IDLBlob[]) {
|
|
|
267
256
|
});
|
|
268
257
|
|
|
269
258
|
const constDeclarations = Array.from(uniqueConsts.values())
|
|
259
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
270
260
|
.map(c => `export declare const ${c.name}: ${c.type};`)
|
|
271
261
|
.join('\n');
|
|
272
262
|
|
|
@@ -275,29 +265,53 @@ export function generateVueTypings(blobs: IDLBlob[]) {
|
|
|
275
265
|
.flatMap(blob => blob.objects)
|
|
276
266
|
.filter(obj => obj instanceof EnumObject) as EnumObject[];
|
|
277
267
|
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
})
|
|
268
|
+
const uniqueEnums = new Map<string, EnumObject>();
|
|
269
|
+
enums.forEach(e => {
|
|
270
|
+
if (!uniqueEnums.has(e.name)) uniqueEnums.set(e.name, e);
|
|
271
|
+
});
|
|
282
272
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
273
|
+
const enumDeclarations = Array.from(uniqueEnums.values())
|
|
274
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
275
|
+
.map(e => {
|
|
276
|
+
const members = e.members.map(m => m.initializer ? `${m.name} = ${m.initializer}` : `${m.name}`).join(', ');
|
|
277
|
+
return `export declare enum ${e.name} { ${members} }`;
|
|
278
|
+
})
|
|
279
|
+
.join('\n');
|
|
280
|
+
|
|
281
|
+
// Collect type aliases across blobs and render as exported declarations.
|
|
282
|
+
const typeAliases = blobs
|
|
283
|
+
.flatMap(blob => blob.objects)
|
|
284
|
+
.filter(obj => obj instanceof TypeAliasObject) as TypeAliasObject[];
|
|
285
|
+
|
|
286
|
+
const uniqueTypeAliases = new Map<string, TypeAliasObject>();
|
|
287
|
+
typeAliases.forEach(t => {
|
|
288
|
+
if (!uniqueTypeAliases.has(t.name)) uniqueTypeAliases.set(t.name, t);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const typeAliasDeclarations = Array.from(uniqueTypeAliases.values())
|
|
292
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
293
|
+
.map(t => `export type ${t.name} = ${t.type};`)
|
|
294
|
+
.join('\n');
|
|
295
|
+
|
|
296
|
+
// Collect supporting interfaces (non-component interfaces) so referenced types exist.
|
|
297
|
+
const supportingInterfaces = blobs
|
|
298
|
+
.flatMap(blob => blob.objects)
|
|
299
|
+
.filter(obj => obj instanceof ClassObject) as ClassObject[];
|
|
300
|
+
|
|
301
|
+
const supporting = supportingInterfaces.filter(obj => {
|
|
302
|
+
return !obj.name.endsWith('Properties') && !obj.name.endsWith('Events') && !obj.name.endsWith('Methods');
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
const uniqueSupporting = new Map<string, ClassObject>();
|
|
306
|
+
supporting.forEach(obj => {
|
|
307
|
+
if (!uniqueSupporting.has(obj.name)) uniqueSupporting.set(obj.name, obj);
|
|
308
|
+
});
|
|
297
309
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
310
|
+
const supportingDeclarations = Array.from(uniqueSupporting.values())
|
|
311
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
312
|
+
.map(obj => renderSupportingInterface(obj))
|
|
313
|
+
.filter(Boolean)
|
|
314
|
+
.join('\n\n');
|
|
301
315
|
|
|
302
316
|
// Build mapping of template tag names to class names for GlobalComponents
|
|
303
317
|
const componentMetas = componentNames.map(className => ({
|
|
@@ -315,7 +329,8 @@ export function generateVueTypings(blobs: IDLBlob[]) {
|
|
|
315
329
|
components,
|
|
316
330
|
consts: constDeclarations,
|
|
317
331
|
enums: enumDeclarations,
|
|
318
|
-
|
|
332
|
+
typeAliases: typeAliasDeclarations,
|
|
333
|
+
dependencies: supportingDeclarations,
|
|
319
334
|
});
|
|
320
335
|
|
|
321
336
|
return content.split('\n').filter(str => {
|
|
@@ -146,8 +146,8 @@ export const <%= className %> = createWebFComponent<<%= className %>Element, <%=
|
|
|
146
146
|
{
|
|
147
147
|
propName: '<%= propName %>',
|
|
148
148
|
eventName: '<%= prop.name %>',
|
|
149
|
-
handler: (callback) => (event) => {
|
|
150
|
-
callback(
|
|
149
|
+
handler: (callback: (event: <%= getEventType(prop.type) %>) => void) => (event: Event) => {
|
|
150
|
+
callback(event as <%= getEventType(prop.type) %>);
|
|
151
151
|
},
|
|
152
152
|
},
|
|
153
153
|
<% }); %>
|
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
<% components.forEach(component => { %>
|
|
6
|
-
export { <%= component.className
|
|
6
|
+
export { <%= component.className %> } from "./<%= component.relativeDir ? component.relativeDir + '/' : '' %><%= component.fileName %>";
|
|
7
|
+
export type { <%= component.className %>Element } from "./<%= component.relativeDir ? component.relativeDir + '/' : '' %><%= component.fileName %>";
|
|
7
8
|
<% }); %>
|
|
@@ -15,12 +15,11 @@
|
|
|
15
15
|
"type": "commonjs",
|
|
16
16
|
"peerDependencies": {
|
|
17
17
|
"react": ">=16.8.0",
|
|
18
|
-
"react-dom": ">=16.8.0"
|
|
19
|
-
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"@openwebf/react-core-ui": "^0.2.1"
|
|
18
|
+
"react-dom": ">=16.8.0",
|
|
19
|
+
"@openwebf/react-core-ui": "^0.24.1"
|
|
22
20
|
},
|
|
23
21
|
"devDependencies": {
|
|
22
|
+
"@openwebf/react-core-ui": "^0.24.1",
|
|
24
23
|
"@types/react": "^19.1.0",
|
|
25
24
|
"@types/react-dom": "^19.1.2",
|
|
26
25
|
"picomatch": "^4.0.2",
|
|
@@ -10,7 +10,14 @@
|
|
|
10
10
|
"esModuleInterop": true,
|
|
11
11
|
"skipLibCheck": true,
|
|
12
12
|
"moduleResolution": "node",
|
|
13
|
-
"allowSyntheticDefaultImports": true
|
|
13
|
+
"allowSyntheticDefaultImports": true,
|
|
14
|
+
"baseUrl": ".",
|
|
15
|
+
"paths": {
|
|
16
|
+
"react": ["./node_modules/@types/react/index.d.ts"],
|
|
17
|
+
"react-dom": ["./node_modules/@types/react-dom/index.d.ts"],
|
|
18
|
+
"react/jsx-runtime": ["./node_modules/@types/react/jsx-runtime.d.ts"],
|
|
19
|
+
"react/jsx-dev-runtime": ["./node_modules/@types/react/jsx-dev-runtime.d.ts"]
|
|
20
|
+
}
|
|
14
21
|
},
|
|
15
22
|
"include": ["src"]
|
|
16
23
|
}
|
|
@@ -8,8 +8,8 @@ export type <%= className %>Props = {
|
|
|
8
8
|
<% } %>
|
|
9
9
|
<% }); %>
|
|
10
10
|
'id'?: string;
|
|
11
|
-
'class'?:
|
|
12
|
-
'style'?:
|
|
11
|
+
'class'?: ClassValue;
|
|
12
|
+
'style'?: StyleValue;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export interface <%= className %>Element {
|
|
@@ -21,7 +21,7 @@ export interface <%= className %>Element {
|
|
|
21
21
|
<%= propName %>: <%= generateReturnType(prop.type) %>;
|
|
22
22
|
<% } %>
|
|
23
23
|
<% }); %>
|
|
24
|
-
<% _.forEach(
|
|
24
|
+
<% _.forEach(methods?.methods, function(method, index) { %>
|
|
25
25
|
<%= generateMethodDeclaration(method) %>
|
|
26
26
|
<% }); %>
|
|
27
27
|
}
|
|
@@ -29,6 +29,6 @@ export interface <%= className %>Element {
|
|
|
29
29
|
export type <%= className %>Events = {
|
|
30
30
|
<% _.forEach(events?.props, function(prop, index) { %>
|
|
31
31
|
<% var propName = prop.name; %>
|
|
32
|
-
<%= propName
|
|
32
|
+
<%= propName %>: <%= generateEventHandlerType(prop.type) %>;
|
|
33
33
|
<% }); %>
|
|
34
34
|
}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
// Based on the Vue 3 documentation for defining custom elements:
|
|
5
5
|
// https://vuejs.org/guide/extras/web-components
|
|
6
|
-
import { EmitFn, PublicProps,
|
|
6
|
+
import type { EmitFn, PublicProps, StyleValue, ClassValue } from 'vue';
|
|
7
|
+
import '@openwebf/vue-core-ui';
|
|
7
8
|
|
|
8
|
-
<%=
|
|
9
|
+
<%= typeAliases %>
|
|
9
10
|
|
|
10
11
|
type EventMap = {
|
|
11
12
|
[event: string]: Event
|
|
@@ -13,29 +14,29 @@ type EventMap = {
|
|
|
13
14
|
|
|
14
15
|
// This maps an EventMap to the format that Vue's $emit type expects.
|
|
15
16
|
type VueEmit<T extends EventMap> = EmitFn<{
|
|
16
|
-
[K in keyof T]: (event: T[K]) => void
|
|
17
|
+
[K in keyof T]: (event: NonNullable<T[K]>) => void
|
|
17
18
|
}>
|
|
18
19
|
|
|
19
20
|
// Vue 3 event listener properties for template usage
|
|
20
21
|
type VueEventListeners<T extends EventMap> = {
|
|
21
|
-
[K in keyof T as `on${Capitalize<string & K>}`]?: (event: T[K]) => any
|
|
22
|
+
[K in keyof T as `on${Capitalize<string & K>}`]?: (event: NonNullable<T[K]>) => any
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
<%= consts %>
|
|
25
26
|
<%= enums %>
|
|
27
|
+
<%= dependencies %>
|
|
26
28
|
|
|
27
29
|
type DefineCustomElement<
|
|
28
30
|
ElementType,
|
|
31
|
+
Props,
|
|
29
32
|
Events extends EventMap = {},
|
|
30
|
-
SelectedAttributes extends keyof ElementType = keyof ElementType
|
|
31
33
|
> = new () => ElementType & VueEventListeners<Events> & {
|
|
32
34
|
// Use $props to define the properties exposed to template type checking. Vue
|
|
33
35
|
// specifically reads prop definitions from the `$props` type. Note that we
|
|
34
|
-
// combine the element's props with
|
|
35
|
-
// props.
|
|
36
|
+
// combine the element's props with Vue's special props.
|
|
36
37
|
/** @deprecated Do not use the $props property on a Custom Element ref,
|
|
37
38
|
this is for template prop types only. */
|
|
38
|
-
$props:
|
|
39
|
+
$props: Props & PublicProps & VueEventListeners<Events>
|
|
39
40
|
|
|
40
41
|
// Use $emit to specifically define event types. Vue specifically reads event
|
|
41
42
|
// types from the `$emit` type. Note that `$emit` expects a particular format
|
|
@@ -47,13 +48,27 @@ type DefineCustomElement<
|
|
|
47
48
|
|
|
48
49
|
<%= components %>
|
|
49
50
|
|
|
50
|
-
declare
|
|
51
|
+
declare const flutterAttached: (typeof import('@openwebf/vue-core-ui')) extends { flutterAttached: infer T } ? T : any;
|
|
52
|
+
|
|
53
|
+
declare module '@vue/runtime-core' {
|
|
54
|
+
interface GlobalDirectives {
|
|
55
|
+
vFlutterAttached: typeof flutterAttached;
|
|
56
|
+
}
|
|
57
|
+
|
|
51
58
|
interface GlobalComponents {
|
|
52
59
|
<% componentMetas.forEach(comp => { %>
|
|
53
60
|
'<%= comp.tagName %>': DefineCustomElement<
|
|
61
|
+
<%= comp.className %>Element,
|
|
54
62
|
<%= comp.className %>Props,
|
|
55
63
|
<%= comp.className %>Events
|
|
56
64
|
>
|
|
57
65
|
<% }) %>
|
|
58
66
|
}
|
|
59
67
|
}
|
|
68
|
+
|
|
69
|
+
// Some tooling (older IDE integrations) look for global directive/component typing
|
|
70
|
+
// augmentations on the `vue` module name instead of `@vue/runtime-core`.
|
|
71
|
+
declare module 'vue' {
|
|
72
|
+
interface GlobalDirectives extends import('@vue/runtime-core').GlobalDirectives {}
|
|
73
|
+
interface GlobalComponents extends import('@vue/runtime-core').GlobalComponents {}
|
|
74
|
+
}
|