feat: initial release

This commit is contained in:
Thomas Allmer
2018-09-02 22:48:23 +02:00
commit 54d963d53f
47 changed files with 1248 additions and 0 deletions

20
.gitignore vendored Normal file
View File

@@ -0,0 +1,20 @@
## editors
/.idea
/.vscode
## system files
.DS_Store
## npm
node_modules
npm-debug.log
## lerna
lerna-debug.log
## temp folders
/.tmp/
## we don't want lock files for now
yarn.lock
package-lock.json

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 open-wc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

35
README.md Normal file
View File

@@ -0,0 +1,35 @@
# Open Web Component Recommendations
We want to provide a good set of default on how to vasilitate your web component.
## Usage
```bash
mkdir my-element
cd my-element
# Minimum setup
npx -p yo -p generator-open-wc -c 'yo open-wc:vanilla-bare'
```
## Available Recommendations
```bash
# Demos using storybook
npx -p yo -p generator-open-wc -c 'yo open-wc:storybook'
# Linting using eslint
npx -p yo -p generator-open-wc -c 'yo open-wc:eslint'
```
## Working on it
```bash
npm run bootstrap
# does: lerna bootstrap --hoist
# run demos
lerna run storybook --scope @open-wc/example-vanilla --stream
# eslint
lerna run lint:eslint --scope @open-wc/example-vanilla --stream
```

11
lerna.json Normal file
View File

@@ -0,0 +1,11 @@
{
"packages": [
"packages/*"
],
"version": "independent",
"command": {
"publish": {
"conventionalCommits": true
}
}
}

11
package.json Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "@open-wc/root",
"private": true,
"license": "MIT",
"scripts": {
"bootstrap": "lerna bootstrap --hoist"
},
"devDependencies": {
"lerna": "^3.2.1"
}
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 open-wc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,29 @@
module.exports = {
extends: [
'eslint-config-airbnb-base',
].map(require.resolve),
env: {
browser: true,
},
rules: {
'import/extensions': 'off',
'no-underscore-dangle': 'off',
'import/prefer-default-export': 'off',
"import/no-extraneous-dependencies": ["error", {
"devDependencies": [
"**/*.test.js",
"**/*.spec.js",
"**/*.stories.js",
"**/*.stories.options.js"
]
}]
},
settings: {
'import/resolver': {
'node': {
'moduleDirectory': ['node_modules', 'bower_components']
}
}
},
plugins: ['html']
};

View File

@@ -0,0 +1,22 @@
{
"name": "@open-wc/eslint-config",
"version": "0.0.0",
"description": "Eslint config following open-wc recommendations",
"author": "open-wc",
"homepage": "https://github.com/open-wc/open-wc/",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"repository": "https://github.com/open-wc/open-wc/tree/master/packages/eslint-config",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"eslint": "^5.5.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-html": "^4.0.5",
"eslint-plugin-import": "^2.14.0"
}
}

View File

@@ -0,0 +1,29 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 2
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.json]
indent_size = 2
[*.{html,js}]
block_comment_start = /**
block_comment = *
block_comment_end = */

View File

@@ -0,0 +1 @@
/node_modules

View File

@@ -0,0 +1,5 @@
module.exports = {
extends: [
'@open-wc/eslint-config',
].map(require.resolve),
};

21
packages/example-vanilla/.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
## editors
/.idea
/.vscode
## system files
.DS_Store
## npm
/node_modules/
/npm-debug.log
## bower
/bower_components*/
/bower-*.json
## temp folders
/.tmp/
## we don't want lock files for now
yarn.lock
package-lock.json

View File

@@ -0,0 +1,8 @@
import '@storybook/addon-storysource/register';
import '@storybook/addon-actions/register';
import '@storybook/addon-backgrounds/register';
import '@storybook/addon-notes/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-links/register';
import '@storybook/addon-viewport/register';
import '@storybook/addon-options/register';

View File

@@ -0,0 +1,13 @@
import { configure } from '@storybook/polymer';
import { setOptions } from '@storybook/addon-options';
setOptions({
hierarchyRootSeparator: /\|/,
});
const req = require.context('../stories', true, /\.stories\.js$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);

View File

@@ -0,0 +1,17 @@
const path = require('path');
const webpack = require('webpack');
module.exports = (storybookBaseConfig, configType, defaultConfig) => {
defaultConfig.resolve.modules.push('bower_components');
defaultConfig.module.rules.push({
test: [/\.stories\.js$/, /index\.js$/],
loaders: [require.resolve('@storybook/addon-storysource/loader')],
enforce: 'pre',
});
// TEMP fix: https://github.com/plotly/plotly.js/issues/2466#issuecomment-372924684
defaultConfig.plugins.push(new webpack.IgnorePlugin(/vertx/));
return defaultConfig;
};

View File

@@ -0,0 +1,53 @@
import { html, render } from 'lit-html';
export default class ExampleVanilla extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.header = 'My Example';
}
connectedCallback() {
this.update();
}
update() {
render(this.renderShadowDom(), this.shadowRoot);
}
renderShadowDom() {
return html`
<style>
:host {
background: grey;
display: block;
padding: 25px;
}
h1 {
color: white;
font-size: 25px;
margin: 0;
}
:host(.right) {
background: green;
text-align: right;
}
:host(.right) h1 {
color: orange;
text-align: right;
}
:host(.right) div {
text-align: right;
}
</style>
<h1>${this.header}</h1>
<div>
<slot></slot>
</div>
`;
}
}

View File

@@ -0,0 +1,28 @@
# \<example-vanilla>
This webcomponent follows the [open-wc](https://github.com/open-wc/open-wc) recommendation.
## Installation
```bash
npm i example-vanilla
```
## Usage
```html
<script type="module">
import 'example-vanilla/example-vanilla.js';
</script>
<example-vanilla></example-vanilla>
```
## Demos using storybook (if applied by author)
```bash
npm run storybook
# visit provided url
```
## Linting using eslint (if applied by author)
```bash
npm run lint:eslint
```

View File

@@ -0,0 +1,3 @@
import ExampleVanilla from './ExampleVanilla.js';
window.customElements.define('example-vanilla', ExampleVanilla);

View File

@@ -0,0 +1,26 @@
{
"name": "@open-wc/example-vanilla",
"version": "0.0.0",
"description": "Example Webcomponent following open-wc recommendations",
"author": "open-wc",
"homepage": "https://github.com/open-wc/open-wc/",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"repository": "https://github.com/open-wc/open-wc/tree/master/packages/example-vanilla",
"private": true,
"dependencies": {
"lit-html": "^0.11.0"
},
"scripts": {
"build-storybook": "build-storybook",
"start": "webpack-dev-server",
"storybook": "start-storybook -p 9001 -c .storybook",
"lint:eslint": "eslint --ext .js,.html ."
},
"devDependencies": {
"@open-wc/storybook": "^0.0.0",
"@open-wc/eslint-config": "^0.0.0"
}
}

View File

@@ -0,0 +1,134 @@
/* eslint-disable no-alert */
import {
storiesOf,
addParameters,
html,
action,
linkTo,
withBackgrounds,
withNotes,
document,
withKnobs,
text,
button,
number,
select,
date,
color,
array,
boolean,
} from '@open-wc/storybook';
storiesOf('Addon|Actions', module)
.add('Action only', () => html`
<button @click=${action('log1')}>click me</button>
`)
.add('Action and method', () => html`
<button @click=${e => action('log2')(e.target)}>click me</button>
`);
storiesOf('Addon|Links', module)
.add('To Welcome', () => html`
<button @click=${linkTo('Welcome')}>Go to welcome</button>
`);
storiesOf('Addon|Backgrounds', module)
.addDecorator(
withBackgrounds([
{ name: 'twitter', value: '#00aced', default: true },
{ name: 'facebook', value: '#3b5998' },
]),
)
.add('Button with text', () => `
<button>Click me</button>
<p>See tab "Backgrounds" at the bottom</p>
`);
storiesOf('Addon|Notes', module)
.addDecorator(withNotes)
.add('Simple note', () => `
<p><strong>See tab "notes" at the bottom.</strong></p>
`, {
notes: 'My notes on some <strong>bold</strong> text',
});
storiesOf('Core|Methods for rendering', module)
.add('html string', () => '<div>Rendered with string</div>')
.add('document.createElement', () => {
const el = document.createElement('button');
el.innerText = 'click me';
el.foo = 'bar';
el.addEventListener('click', e => alert(e.target.foo));
return el;
})
.add('lit-html', () => html`
<button .foo=${'bar'} @click=${e => alert(e.target.foo)}>click me</button>
`);
const globalParameter = 'globalParameter';
const chapterParameter = 'chapterParameter';
const storyParameter = 'storyParameter';
addParameters({ globalParameter });
storiesOf('Core|Parameters', module)
.addParameters({ chapterParameter })
.add('passed to story', ({ parameters: { fileName, ...parameters } }) => `
<div>Parameters are ${JSON.stringify(parameters)}</div>
`, {
storyParameter,
});
storiesOf('Addon|Knobs', module)
.addDecorator(withKnobs)
.add('button label', () => html`
<button>${text('Button label', 'You can change me in the tab KNOBS')}</button>
`)
.add('complex', () => {
const name = text('Name', 'Jane');
const stock = number('Stock', 20, {
range: true, min: 0, max: 30, step: 5,
});
const fruits = {
Apple: 'apples',
Banana: 'bananas',
Cherry: 'cherries',
};
const fruit = select('Fruit', fruits, 'apples');
const price = number('Price', 2.25);
const colour = color('Border', 'deeppink');
const today = date('Today', new Date('Jan 20 2017 GMT+0'));
const items = array('Items', ['Laptop', 'Book', 'Whiskey']);
const nice = boolean('Nice', true);
const stockMessage = stock
? html`I have a stock of ${stock} ${fruit}, costing &dollar;${price} each.`
: html`I'm out of ${fruit}${nice ? ', Sorry!' : '.'}`;
const dateOptions = {
year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC',
};
button('Arbitrary action', () => alert('You clicked it!'));
return html`
<div style="border:2px dotted ${colour}; padding: 8px 22px; border-radius: 8px">
<h1>My name is ${name},</h1>
<h3>today is ${new Date(today).toLocaleDateString('en-US', dateOptions)}</h3>
<p>${stockMessage}</p>
<p>Also, I have:</p>
<ul>
${items.map(item => html`
<li>${item}</li>
`)}
</ul>
<p>${nice ? 'Nice to meet you!' : 'Leave me alone!'}</p>
</div>
`;
});

View File

@@ -0,0 +1,15 @@
import {
storiesOf,
html,
} from '@open-wc/storybook';
import { opts } from './index.stories.options.js';
import '../example-vanilla.js';
storiesOf(`${opts.header}`, module)
.add('default', () => html`
<${opts.tag}>user content tag: ${opts.tag}</${opts.tag}>
`)
.add('right', () => html`
<${opts.tag} class="right">user content tag: ${opts.tag}</${opts.tag}>
`);

View File

@@ -0,0 +1,11 @@
import { unsafeStatic } from '@open-wc/storybook';
// eslint-disable-next-line import/no-mutable-exports
export let opts = {
tag: unsafeStatic('example-vanilla'),
header: '<example-vanilla>',
};
export function setOptions(newOptions) {
opts = newOptions;
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 open-wc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,53 @@
var Generator = require('yeoman-generator');
const glob = require('glob');
function getClassName(tagName) {
return tagName.split('-').reduce((previous, part) => {
return previous + part.charAt(0).toUpperCase() + part.slice(1);
}, '');
}
module.exports = class GeneratorOpenWc extends Generator {
prompting() {
const done = this.async();
return this.prompt(PROMPTS).then(answers => {
this.props = answers;
done();
});
}
default() {
const { tagName, type } = this.props;
// Build component class
this.props.className = getClassName(tagName);
}
writing() {
const { tagName, className } = this.props;
// extend package.json
this.fs.extendJSON(
this.destinationPath('package.json'),
this.fs.readJSON(this.templatePath('package.json'))
);
// Write everything else
this.fs.copyTpl(
glob.sync(this.templatePath('!(package.json)'), { dot: true }),
this.destinationPath(),
this
);
}
};
const PROMPTS = [
{
name: 'tagName',
type: 'input',
required: true,
message: 'Give it a tag name (min two words separated by dashes)',
validate: str => /^([a-z])(?!.*[<>])(?=.*-).+$/.test(str)
},
];

View File

@@ -0,0 +1 @@
/node_modules

View File

@@ -0,0 +1,5 @@
module.exports = {
extends: [
'@open-wc/eslint-config',
].map(require.resolve),
};

View File

@@ -0,0 +1,8 @@
{
"scripts": {
"lint:eslint": "eslint --ext .js,.html ."
},
"devDependencies": {
"@open-wc/eslint-config": "^0.0.0"
}
}

View File

@@ -0,0 +1,53 @@
var Generator = require('yeoman-generator');
const glob = require('glob');
function getClassName(tagName) {
return tagName.split('-').reduce((previous, part) => {
return previous + part.charAt(0).toUpperCase() + part.slice(1);
}, '');
}
module.exports = class GeneratorOpenWc extends Generator {
prompting() {
const done = this.async();
return this.prompt(PROMPTS).then(answers => {
this.props = answers;
done();
});
}
default() {
const { tagName, type } = this.props;
// Build component class
this.props.className = getClassName(tagName);
}
writing() {
const { tagName, className } = this.props;
// extend package.json
this.fs.extendJSON(
this.destinationPath('package.json'),
this.fs.readJSON(this.templatePath('package.json'))
);
// Write everything else
this.fs.copyTpl(
glob.sync(this.templatePath('!(package.json)'), { dot: true }),
this.destinationPath(),
this
);
}
};
const PROMPTS = [
{
name: 'tagName',
type: 'input',
required: true,
message: 'Give it a tag name (min two words separated by dashes)',
validate: str => /^([a-z])(?!.*[<>])(?=.*-).+$/.test(str)
},
];

View File

@@ -0,0 +1,8 @@
import '@storybook/addon-storysource/register';
import '@storybook/addon-actions/register';
import '@storybook/addon-backgrounds/register';
import '@storybook/addon-notes/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-links/register';
import '@storybook/addon-viewport/register';
import '@storybook/addon-options/register';

View File

@@ -0,0 +1,13 @@
import { configure } from '@storybook/polymer';
import { setOptions } from '@storybook/addon-options';
setOptions({
hierarchyRootSeparator: /\|/,
});
const req = require.context('../stories', true, /\.stories\.js$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);

View File

@@ -0,0 +1,17 @@
const path = require('path');
const webpack = require('webpack');
module.exports = (storybookBaseConfig, configType, defaultConfig) => {
defaultConfig.resolve.modules.push('bower_components');
defaultConfig.module.rules.push({
test: [/\.stories\.js$/, /index\.js$/],
loaders: [require.resolve('@storybook/addon-storysource/loader')],
enforce: 'pre',
});
// TEMP fix: https://github.com/plotly/plotly.js/issues/2466#issuecomment-372924684
defaultConfig.plugins.push(new webpack.IgnorePlugin(/vertx/));
return defaultConfig;
};

View File

@@ -0,0 +1,10 @@
{
"scripts": {
"build-storybook": "build-storybook",
"start": "webpack-dev-server",
"storybook": "start-storybook -p 9001 -c .storybook"
},
"devDependencies": {
"@open-wc/storybook": "^0.0.0"
}
}

View File

@@ -0,0 +1,134 @@
/* eslint-disable no-alert */
import {
storiesOf,
addParameters,
html,
action,
linkTo,
withBackgrounds,
withNotes,
document,
withKnobs,
text,
button,
number,
select,
date,
color,
array,
boolean,
} from '@open-wc/storybook';
storiesOf('Addon|Actions', module)
.add('Action only', () => html`
<button @click=${action('log1')}>click me</button>
`)
.add('Action and method', () => html`
<button @click=${e => action('log2')(e.target)}>click me</button>
`);
storiesOf('Addon|Links', module)
.add('To Welcome', () => html`
<button @click=${linkTo('Welcome')}>Go to welcome</button>
`);
storiesOf('Addon|Backgrounds', module)
.addDecorator(
withBackgrounds([
{ name: 'twitter', value: '#00aced', default: true },
{ name: 'facebook', value: '#3b5998' },
]),
)
.add('Button with text', () => `
<button>Click me</button>
<p>See tab "Backgrounds" at the bottom</p>
`);
storiesOf('Addon|Notes', module)
.addDecorator(withNotes)
.add('Simple note', () => `
<p><strong>See tab "notes" at the bottom.</strong></p>
`, {
notes: 'My notes on some <strong>bold</strong> text',
});
storiesOf('Core|Methods for rendering', module)
.add('html string', () => '<div>Rendered with string</div>')
.add('document.createElement', () => {
const el = document.createElement('button');
el.innerText = 'click me';
el.foo = 'bar';
el.addEventListener('click', e => alert(e.target.foo));
return el;
})
.add('lit-html', () => html`
<button .foo=${'bar'} @click=${e => alert(e.target.foo)}>click me</button>
`);
const globalParameter = 'globalParameter';
const chapterParameter = 'chapterParameter';
const storyParameter = 'storyParameter';
addParameters({ globalParameter });
storiesOf('Core|Parameters', module)
.addParameters({ chapterParameter })
.add('passed to story', ({ parameters: { fileName, ...parameters } }) => `
<div>Parameters are ${JSON.stringify(parameters)}</div>
`, {
storyParameter,
});
storiesOf('Addon|Knobs', module)
.addDecorator(withKnobs)
.add('button label', () => html`
<button>${text('Button label', 'You can change me in the tab KNOBS')}</button>
`)
.add('complex', () => {
const name = text('Name', 'Jane');
const stock = number('Stock', 20, {
range: true, min: 0, max: 30, step: 5,
});
const fruits = {
Apple: 'apples',
Banana: 'bananas',
Cherry: 'cherries',
};
const fruit = select('Fruit', fruits, 'apples');
const price = number('Price', 2.25);
const colour = color('Border', 'deeppink');
const today = date('Today', new Date('Jan 20 2017 GMT+0'));
const items = array('Items', ['Laptop', 'Book', 'Whiskey']);
const nice = boolean('Nice', true);
const stockMessage = stock
? html`I have a stock of ${stock} ${fruit}, costing &dollar;${price} each.`
: html`I'm out of ${fruit}${nice ? ', Sorry!' : '.'}`;
const dateOptions = {
year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC',
};
button('Arbitrary action', () => alert('You clicked it!'));
return html`
<div style="border:2px dotted ${colour}; padding: 8px 22px; border-radius: 8px">
<h1>My name is ${name},</h1>
<h3>today is ${new Date(today).toLocaleDateString('en-US', dateOptions)}</h3>
<p>${stockMessage}</p>
<p>Also, I have:</p>
<ul>
${items.map(item => html`
<li>${item}</li>
`)}
</ul>
<p>${nice ? 'Nice to meet you!' : 'Leave me alone!'}</p>
</div>
`;
});

View File

@@ -0,0 +1,15 @@
import {
storiesOf,
html,
} from '@open-wc/storybook';
import { opts } from './index.stories.options.js';
import '../<%= props.tagName %>.js';
storiesOf(`${opts.header}`, module)
.add('default', () => html`
<${opts.tag}>user content tag: ${opts.tag}</${opts.tag}>
`)
.add('right', () => html`
<${opts.tag} class="right">user content tag: ${opts.tag}</${opts.tag}>
`);

View File

@@ -0,0 +1,11 @@
import { unsafeStatic } from '@open-wc/storybook';
// eslint-disable-next-line import/no-mutable-exports
export let opts = {
tag: unsafeStatic('<%= props.tagName %>'),
header: '<<%= props.tagName %>>',
};
export function setOptions(newOptions) {
opts = newOptions;
}

View File

@@ -0,0 +1,61 @@
var Generator = require('yeoman-generator');
const glob = require('glob');
function getClassName(tagName) {
return tagName.split('-').reduce((previous, part) => {
return previous + part.charAt(0).toUpperCase() + part.slice(1);
}, '');
}
module.exports = class GeneratorOpenWc extends Generator {
prompting() {
const done = this.async();
return this.prompt(PROMPTS).then(answers => {
this.props = answers;
done();
});
}
default() {
const { tagName, type } = this.props;
// Build component class
this.props.className = getClassName(tagName);
}
writing() {
const { tagName, className } = this.props;
// Write & rename element src
this.fs.copyTpl(
this.templatePath('ExampleElement.js'),
this.destinationPath(`${className}.js`),
this
);
// Write & rename element definition
this.fs.copyTpl(
this.templatePath('example-element.js'),
this.destinationPath(`${tagName}.js`),
this
);
// Write everything else
this.fs.copyTpl(
glob.sync(this.templatePath('!(ExampleElement.js|example-element.js)'), { dot: true }),
this.destinationPath(),
this
);
}
};
const PROMPTS = [
{
name: 'tagName',
type: 'input',
required: true,
message: 'Give it a tag name (min two words separated by dashes)',
validate: str => /^([a-z])(?!.*[<>])(?=.*-).+$/.test(str)
},
];

View File

@@ -0,0 +1,29 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 2
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.json]
indent_size = 2
[*.{html,js}]
block_comment_start = /**
block_comment = *
block_comment_end = */

View File

@@ -0,0 +1,21 @@
## editors
/.idea
/.vscode
## system files
.DS_Store
## npm
/node_modules/
/npm-debug.log
## bower
/bower_components*/
/bower-*.json
## temp folders
/.tmp/
## we don't want lock files for now
yarn.lock
package-lock.json

View File

@@ -0,0 +1,53 @@
import { html, render } from 'lit-html';
export default class <%= props.className %> extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.header = 'My Example';
}
connectedCallback() {
this.update();
}
update() {
render(this.renderShadowDom(), this.shadowRoot);
}
renderShadowDom() {
return html`
<style>
:host {
background: grey;
display: block;
padding: 25px;
}
h1 {
color: white;
font-size: 25px;
margin: 0;
}
:host(.right) {
background: green;
text-align: right;
}
:host(.right) h1 {
color: orange;
text-align: right;
}
:host(.right) div {
text-align: right;
}
</style>
<h1>${this.header}</h1>
<div>
<slot></slot>
</div>
`;
}
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 <%= props.tagName %>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,28 @@
# \<<%= props.tagName %>>
This webcomponent follows the [open-wc](https://github.com/open-wc/open-wc) recommendation.
## Installation
```bash
npm i <%= props.tagName %>
```
## Usage
```html
<script type="module">
import '<%= props.tagName %>/<%= props.tagName %>.js';
</script>
<<%= props.tagName %>></<%= props.tagName %>>
```
## Demos using storybook (if applied by author)
```bash
npm run storybook
# visit provided url
```
## Linting using eslint (if applied by author)
```bash
npm run lint:eslint
```

View File

@@ -0,0 +1,3 @@
import <%= props.className %> from './<%= props.className %>.js';
window.customElements.define('<%= props.tagName %>', <%= props.className %>);

View File

@@ -0,0 +1,12 @@
{
"name": "<%= props.tagName %>",
"version": "0.0.0",
"description": "Webcomponent <%= props.tagName %> following open-wc recommendations",
"author": "<%= props.tagName %>",
"homepage": "https://github.com/open-wc/open-wc/",
"license": "MIT",
"repository": "https://github.com/open-wc/open-wc/",
"dependencies": {
"lit-html": "^0.11.0"
}
}

View File

@@ -0,0 +1,16 @@
{
"name": "generator-open-wc",
"version": "0.0.0",
"description": "Scaffold web components following open-wc recommendations",
"author": "open-wc",
"homepage": "https://github.com/open-wc/open-wc/",
"license": "MIT",
"repository": "https://github.com/open-wc/open-wc/tree/master/packages/generator-open-wc",
"keywords": [
"yeoman-generator",
"open-wc"
],
"dependencies": {
"yeoman-generator": "^1.0.0"
}
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 open-wc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,71 @@
export { storiesOf, addParameters } from '@storybook/polymer';
export { action } from '@storybook/addon-actions';
export { linkTo } from '@storybook/addon-links';
export { withBackgrounds } from '@storybook/addon-backgrounds';
export { withNotes } from '@storybook/addon-notes';
export { document } from 'global';
export {
withKnobs,
text,
button,
number,
select,
date,
color,
array,
boolean,
} from '@storybook/addon-knobs';
import { html as litHtml } from 'lit-html';
/**
* This is a wrapper around lit-html that supports dynamic strings to be added as a preprocessing
* step, before a template is passed to lit's html function.
* A dynamic string will be evaluated one time (on init) and passed to lit-html as being
* part of the static string.
*
* WARNING: do not use in production!!! has a huge performance penalty as every string is
* different from lit-htmls perspective so a new tag is created every time.
*
* A valid use case for this would be to create dynamic tag names.
*
* @example:
* const tag = unsafeStatic('my-tag');
* html`<${tag} prop="${prop}"></${tag>`
* // will in turn calls lit-html html function as:
* html`<my-tag prop="${prop}"></my-tag>`
*/
export function html(strings, ...values) {
const newVal = []; // result values to be passed on to lit-html
const newStr = []; // result strings to be passed on to lit-html
const isDynamicProp = p => p && p.d && typeof p.d === 'string' && Object.keys(p).length === 1;
const addToCurrentString = (add) => {
newStr[newStr.length - 1] = newStr[newStr.length - 1] + add;
};
// Create the result arrays
values.forEach((string, index) => {
if (index === 0) {
newStr.push(strings[0]); // this is either ''(if tagged starts with value) or string
}
// Situation 1 : dynamic string
const p = values[index]; // potential dynamic string
if (isDynamicProp(p)) {
addToCurrentString(p.d);
addToCurrentString(strings[index + 1]);
} else {
// Situation 2: no dynamic string, just push string and value
newVal.push(p); // a 'real' value
newStr.push(strings[index + 1]);
}
});
// Return lit template
return litHtml(newStr, ...newVal);
};
export function unsafeStatic(options) {
return {
d: options
};
}

View File

@@ -0,0 +1,29 @@
{
"name": "@open-wc/storybook",
"version": "0.0.0",
"description": "Storybook configuration following open-wc recommendations",
"author": "open-wc",
"homepage": "https://github.com/open-wc/open-wc/",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"repository": "https://github.com/open-wc/open-wc/tree/master/packages/storybook",
"dependencies": {
"@babel/core": "^7.0.0",
"@storybook/addon-actions": "^4.0.0-alpha.20",
"@storybook/addon-backgrounds": "^4.0.0-alpha.20",
"@storybook/addon-knobs": "^4.0.0-alpha.20",
"@storybook/addon-links": "^4.0.0-alpha.20",
"@storybook/addon-notes": "^4.0.0-alpha.20",
"@storybook/addon-options": "^4.0.0-alpha.20",
"@storybook/addon-storysource": "^4.0.0-alpha.20",
"@storybook/addon-viewport": "^4.0.0-alpha.20",
"@storybook/polymer": "^4.0.0-alpha.20",
"@webcomponents/webcomponentsjs": "^1.2.0",
"babel-loader": "^8.0.1",
"lit-html": "^0.11.0",
"moment": "^2.22.2",
"polymer-webpack-loader": "^2.0.3"
}
}