Skip to content

Automagic Custom Element transformorama#133

Merged
matt-gadd merged 11 commits intodojo:masterfrom
rorticus:grayrest-element-transformer
May 3, 2019
Merged

Automagic Custom Element transformorama#133
matt-gadd merged 11 commits intodojo:masterfrom
rorticus:grayrest-element-transformer

Conversation

@rorticus
Copy link
Contributor

@rorticus rorticus commented Feb 22, 2019

Type: feature

The following has been addressed in the PR:

Description:

Working off of #98, refactored a bit to better align with our wants. This is really part 2 of what will be a 3 step process:

  1. Supporting custom element decorator stacking
  2. Apply decorator defaults in registerCustomElement
  3. Autogenerate custom element information (this)
  4. Update cli-build-widget to apply this transformation.
  5. Remove custom element decorators from @dojo/widgets

The general idea is that if you have a widget like this,

import { v } from '@dojo/framework/widget-core/d';
import { WidgetBase as base } from '@dojo/framework/widget-core/WidgetBase';

interface HelloProperties {
	name: string;
	flag: boolean;
	onClick(): void;
	onChange(value: string): void;
}

export class Hello extends base<HelloProperties> {
	protected render() {
		const { name } = this.properties;
		return v('h1', { }, [
			'Hello!'
		]);
	}
}

export default Hello;

When targeted, it will automatically turn into:

import { v } from '@dojo/framework/widget-core/d';
import { WidgetBase as base } from '@dojo/framework/widget-core/WidgetBase';

interface HelloProperties {
	name: string;
	flag: boolean;
	onClick(): void;
	onChange(value: string): void;
}

export class Hello extends base<HelloProperties> {
	protected render() {
		const { name } = this.properties;
		return v('h1', { }, [
			'Hello!'
		]);
	}
}
Hello.prototype.__customElementDescriptor = { ...{ tagName: 'hello-widget', attributes: ['name'], properties: ['flag'], events: ['onClick', onChange'] }, ...Hello.prototype.__customElementDescriptor || {} };

export default Hello;

The generated tag name is the name of the widget class, dashed on lower/uppercase boundaries, and lowercased. If the name has no dashes in it, it'll have -widget appended to the end so that it conforms to the custom element spec. So Hello becomes hello-widget, and HelloWorld becomes hello-world. The user will be able to override the tag name by manually applying a custom element decorator.

@customElement({ tag: 'hello-world' })
export class Hello extends base<HelloProperties> {
	protected render() {
		const { name } = this.properties;
		return v('h1', { }, [
			'Hello!'
		]);
	}
}

Resolves #43

@rorticus rorticus requested a review from matt-gadd February 22, 2019 17:41
@codecov
Copy link

codecov bot commented Feb 22, 2019

Codecov Report

Merging #133 into master will increase coverage by 0.39%.
The diff coverage is 97.91%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #133      +/-   ##
==========================================
+ Coverage   84.43%   84.82%   +0.39%     
==========================================
  Files          38       39       +1     
  Lines        1593     1641      +48     
  Branches      389      407      +18     
==========================================
+ Hits         1345     1392      +47     
- Misses        248      249       +1
Impacted Files Coverage Δ
src/element-transformer/index.ts 97.91% <97.91%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d790b44...a7eb58d. Read the comment docs.

@codecov
Copy link

codecov bot commented Feb 22, 2019

Codecov Report

Merging #133 into master will increase coverage by 0.58%.
The diff coverage is 98.43%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #133      +/-   ##
==========================================
+ Coverage   84.43%   85.01%   +0.58%     
==========================================
  Files          38       39       +1     
  Lines        1593     1662      +69     
  Branches      389      414      +25     
==========================================
+ Hits         1345     1413      +68     
- Misses        248      249       +1
Impacted Files Coverage Δ
src/element-transformer/ElementTransformer.ts 98.43% <98.43%> (ø)
src/build-time-render/BuildTimeRender.ts 100% <0%> (ø) ⬆️
src/registry-transformer/index.ts 98.31% <0%> (+0.02%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d790b44...d6b8cb1. Read the comment docs.

@matt-gadd
Copy link
Contributor

matt-gadd commented Feb 22, 2019

@rorticus small thought re the -widget suffix. most custom elements tend to use a prefix as the namespace rather than a suffix, for example ionic is ion-{name}. with that do you think we could perhaps take a prefix as an option to the transformer? we could then perhaps default it to widget- in cli-build-app and support a prefix in the .dojorc?

@rorticus
Copy link
Contributor Author

Yeah thats a good idea @matt-gadd. We could possibly pass in the package name as the default prefix, so it could be like myapp-select or ui-components-select, depending on what your package name is?

@rorticus
Copy link
Contributor Author

Updated to set the __customElementDescriptor on the prototype. This better aligns with the custom element decorator.

@matt-gadd matt-gadd merged commit 26a85e7 into dojo:master May 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a TypeScript transformer to autogenerate properties and attributes for Custom Elements

3 participants