Package Exports
- @polight/lego
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@polight/lego) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
LEGO: Modern Web-Components
LEGO (Lightweight Embedded Gluten-free Objects) is a thin layer to build web-component bricks that are easy to digest for your browser.
Lego is inspired from great libraries such as Riot, VueJS or Polymer. It's just much lighter with no complexity, easier to read code, maintain and interact with the source.
Install
The compiler can be installed via a simple command:
npm install @polight/legoThat will permit to compile your components. See the Compiling section for further info.
Quick start
Create an element:
components/user-profile.html
<template>
<h1>${ this.firstName } ${ this.lastName }'s profile</h1>
<p>Welcome ${ this.firstName }!</p>
<p :if="this.registered">You are fully registered</p>
<button :if="!this.registered" on:click="this.register">Register now</button>
</template>
<script>
this.setState({
firstName: 'John',
lastName: 'Doe',
registered: false
})
this.register = () => {
this.state.registered = true
this.render() // update the interface
}
</script>Then include it in your page:
index.html
<user-profile></user-profile>
<script src="./dist.js" type="module"></script>Notice that you don't need to include Lego script in your index.html file.
Now you need to compile your components into a js file:
npx lego ./components/ ./dist.jsThat will read all HTML components from the ./components folder and sub-folders and create a dist.js file.
When developing you may want to automatically watch files changes. In that case pass the
-wflag:npx lego -w ./components/ ./dist.js
Trick: you probably want to store this task with a shortcut like
npm run watch. To do so just add"watch": "lego -w ./components/ ./dist.js"in you package.json scripts.
Writing a component
A component can optionnaly have 3 parts: some HTML in a <template> tag, some JavaScript
in a <script> tag and some CSS in a <style> tag.
Template tag
A template is written within a <template> tag.
It's just HTML with some empowerments for reactiveness.
These superpowers can be recognized with their : prefix.
Note that these tags are interpreted and removed. You can't read them with CSS or script.
:if
Conditionally display a tag and its descendants.
Example: <p :if="this.state.count < 5">Less than 5</p> will be displayed if the condition is met.
:for
Repeat a tag reading from a variable.
The syntax is as follow: :for="item in this.state.items".
The item value will be available trough this.item within the loop.
Example: <li :for="attendee in this.state.attendees">${ this.attendee }</li> with a state as
this.setState({ attendees: ['John', 'Mary'] }) will display <li>John</li><li>Mary</li>
Boolean attributes
Boolean attributes
like required, checked, selected, disabled, … are interpreted with a simple : prefix.
Example: <input type=checkbox :checked="this.state.agreed" :required="this.state.mustAgree">.
With the following state: this.setState({ agreed: false, mustAgree: true }) would render
<input type=checkbox required="required">.
Event listener
An event can be attached to a DOM element with the prefix on: and the event name.
Example: <button on:click="this.clicked">Click me</button> will call the this.clicked
method in the component.
Ractive components
When changing an attribute you may want the component to be updated automatically.
In order to listen to the attribute, you can simply declare it as an attribute of your <template> tag:
<template firstname="John" lastname="Doe" age="42">
<h1>Welcome ${ this.firstname } ${ this.lastname }</h1>
</template>This will:
- listen to changes on the 3 attributes firstname, lastname and age.
- declare the default values for each of your attributes into your state.
Note that these default values will be available for your script into the state:
console.log(this.state.age) // 42When compiling, the attributes values are evaluated whenever possible. In the current example "42" will become a Number. You could therefore pass
kids="['Brice', 'Kelly']"and retrieve an array of 2 kids.
Slots
Slots are part of the native web-component. Because Lego build native web-components, you can use the standard slots.
Example:
index.html
<user-profile>
<span>This user is in Paris</span>
<user-profile>components/user-profile.html
<template>
<h1>User profile</h1>
<p>important information: <slot></slot></p>
</template>Will write …<p>important information: <span>This user is in Paris</span></p>
Script tag
The <script> tag contains HTML that will be injected into the component on initialisation.
It can provide information to the template via the state object.
Example: this.state.userName = 'John' will permit to render <p>Hello ${ this.userName }</p>.
Rendering
Rendering is calculating the template tag and displaying it.
It is processed with the render() method.
Most of the time when you change the state, you probably then want to call this.render()
in order to update your HTML with the new state value(s).
Note that you can also pass the state as an object to the render method:
this.render({ userName: 'John' }).
In other words, calling this.render() is the way to update your component!
Binding event methods
on:eventName will bind the eventName to the DOM object and trigger the method.
In most cases you will want to bind that event with a call to a script function.
Example:
<template>
<button on:click="this.clicked">Click me</button>
</template>
<script>
this.clicked = () => {
alert('you clicked the button!')
}
</script>The events are native HTML. Meaning you can call on:click, on:change, on:submit, …
Behind the scene, it creates an addEventListener(eventName), meaning you can use the
native browser debug, remove events and play with the full power of native events!
Style tag
CSS is much more fun when it's scoped. Here it come with the web-components.
Here again, no trick or magic, though the full power of web-components and scoping.
Writing CSS is as easy as
<template>
<h1>Bonjour!</h1>
</template>
<style>
h1 {
padding: 1rem;
text-align: center;
}
</style>Host
:host is a native selector
for web-components.
It allows to select the current component itself.
Variables
You can use variables in your CSS just like in your templates.
Example:
<template>
<h1>Bonjour<h1>
</template>
<script>
this.state.color = '#357';
</script>
<style>
h1 {
color: ${ this.color };
}
</style>will apply the #357 color onto h1.
Compiling
npx lego <source_path> <target_file_path>Would compile the source_path file or folder (recursively) into target_file_path js file.
As mentioned before, when developing you probably want to watch for changes with the -w
option: npx lego -w <source_path> <target_file_path>
source_path: either a file or a directory (relative or absolute). If it's a directory, it will recursively read all the .html files and compile them into the target_file.
target_file_path: (default: components.js) the path (relative or absolute) to a .js file. That file will be created and contain all the components.
Naming a component
The name of the file will be the name of the component.
Example: components/x-button.html will create <x-button> component.
However in some cases you may want to give your component a different name than the file.
To do so, you may give your template a name with the name attribute.
Example:
components/x-button.html:
<template name="my-super-button"></template>Will create a <my-super-button> component.
Note that because it builds native web-components, the naming convention must respect the ones from the standards (lowercase, with a dash in the name, starting with a letter, …)
Testing
Running tests 
Just install node dev dependencies (npm install) and run the tests (npm test).
Under the hood
Native web-components
Because Lego is actual native web-components, all its native possibilities (like slots), :host and whatever exists or will exist are on board.
Browser compatibility
Lego is based on native customElements. Support for customElement is spreading and shall increase in time.
When building a web-app you may have control of the browsers. If you're building a more general website you may need to increase the overall browser compatibility and install the custom-element polyfill.
Dependencies
It is still fully compatible with native custom elements. No magic behind the scene, no complexity, just a couple of useful methods to write native web-components easier.
Using a compiled component has no dependency, nothing extra injected in the browser. Compiling depends on jsdom.