-
Notifications
You must be signed in to change notification settings - Fork 25
Allow mixins to describe custom elements #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
1af2a7f
ab1ec94
2d1bb35
d1e77b0
f5ca047
5ffe59f
f65cdff
6fee0eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -131,7 +131,7 @@ export type Declaration = | |
| FunctionDeclaration | ||
| MixinDeclaration | ||
| VariableDeclaration | ||
| CustomElement; | ||
| CustomElementDeclaration; | ||
|
||
/** | ||
* A reference to an export of a module. | ||
|
@@ -149,7 +149,7 @@ export interface Reference { | |
} | ||
|
||
/** | ||
* Description of a custom element class. | ||
* A description of a custom element class. | ||
* | ||
* Custom elements are JavaScript classes, so this extends from | ||
* `ClassDeclaration` and adds custom-element-specific features like | ||
|
@@ -168,7 +168,13 @@ export interface Reference { | |
* tagName, and another `Module` should contain the | ||
* `CustomElement`. | ||
*/ | ||
export interface CustomElement extends ClassDeclaration { | ||
export interface CustomElementDeclaration extends ClassDeclaration {} | ||
|
||
|
||
/** | ||
* The additional fields that a custom element adds to classes and mixins. | ||
*/ | ||
export interface CustomElement extends ClassLike { | ||
/** | ||
* An optional tag name that should be specified if this is a | ||
* self-registering element. | ||
|
@@ -193,7 +199,7 @@ export interface CustomElement extends ClassDeclaration { | |
*/ | ||
slots?: Slot[]; | ||
|
||
parts?: CssPart[]; | ||
cssParts?: CssPart[]; | ||
|
||
cssProperties?: CssCustomProperty[]; | ||
|
||
|
@@ -404,9 +410,55 @@ export interface ClassMethod extends FunctionLike { | |
} | ||
|
||
/** | ||
* | ||
* A description of a mixin. | ||
* | ||
* Mixins are functions which generate a new subclass of a given superclass. | ||
* This interfaces describes the class and custom element features that | ||
* are added by the mixin. As such, it extends the CustomElement interface and | ||
* ClassLike interface. | ||
* | ||
* Since mixins are functions, it also extends the FunctionLike interface. This | ||
* means a mixin is callable, and has parameters and a return type. | ||
* | ||
* The return type is often hard or impossible to accurately describe in type | ||
* systems like TypeScript. It requires generics and an `extends` operator | ||
* that TypeScript lacks. Therefore it's recommended that the return type is | ||
* left empty. The most common form of a mixin function takes a single | ||
* argument, so consumers of this interface should assume that the return type | ||
* is the single argument subclassed by this declaration. | ||
* | ||
* A mixin should only have a superclass if it composes another mixin, and the | ||
|
||
* superclass should reference that mixin. | ||
* | ||
* @example | ||
* | ||
* This JavaScript mixin declaration: | ||
* ```javascript | ||
* const MyMixin = (base) => class extends base { | ||
* foo() { ... } | ||
* } | ||
* ``` | ||
* | ||
* Is described by this JSON: | ||
* ```json | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it still have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No - mixins (usually) don't have superclasses until they are applied to a specific superclass. When mixins do have a superclass, it's because of mixin composition: const MixinA = (base) => class extends base {
fieldA;
}
const MixinB = (base) class extends MixinA(base) {
fieldB;
}
class C extends MixinB(S) {
}
const c = new C();
c.fieldA; // exists
c.fieldB; // exists So here the superclass of MixinB would be MixinA. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added a short mention of this in the docs There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When a mixin has nested mixins, though, are those nested mixins then documented as being mixins, or superclasses? E.g.: const MixinA = (base) => class extends base {
fieldA;
}
const MixinB = (base) => class extends MixinA(base) {
fieldB;
} Would the mixin declaration look like this: {
"kind": "mixin",
"description": "",
"name": "MixinB",
"mixins": [
{
"name": "MixinA"
}
],
"parameters": [
{
"name": "base"
}
],
"members": ["//etc"]
} If we consider Intuitively, I feel like I'd prefer to name "nested mixins" just mixins in this case though There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good point, I'll change the comments to says composed mixins should go in the mixins field. |
||
* { | ||
* "kind": "mixin", | ||
* "name": "MyMixin", | ||
* "parameters": [ | ||
* { | ||
* "name": "base", | ||
* } | ||
* ], | ||
* "members": [ | ||
* { | ||
* "kind": "method", | ||
* "name": "foo", | ||
* } | ||
* ] | ||
* } | ||
* ``` | ||
*/ | ||
export interface MixinDeclaration extends ClassLike, FunctionLike { | ||
export interface MixinDeclaration extends CustomElement, FunctionLike { | ||
kind: 'mixin'; | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.