Git Product home page Git Product logo

lego's Introduction

Lego is a fast & native web-components library

LEGO: Modern Web-Components

Native Web-Components?

Yes, you write native HTML, CSS and JS and create a native web-components W3C compliant.

It's stable and predictable.

If you have ever played with Web-Component-like frameworks (not to name Vue, React, Svelte…), you may know how debugging gets tricky and requires extra tooling.

Because LEGO is native, your browser developper toobar is all you need.

  • debugger works as expected,
  • step-by-step debugging,
  • element inspector,
  • the console with the live JS in the context…

It's all just normal!

What does LEGO actually look like?

/bricks/lean-welcome.html:

<template>
  <h1>Welcome to LEGO</h1>
  <p>The lean way to make web-components <slot></slot></p>
</template>

Later you can use it anywhere in your HTML:

<lean-welcome>powerful and easy</lean-welcome>

Will read in your HTML:

Welcome to LEGO
The lean way to make web-components powerful and easy

Of course there's so much more you can do. The documentation will guide you 📓

Pretty neat!

Getting Started in 3 minutes

You can just hop in and experiment your first HTML Element.

Follow this Getting Started guide for installing and writing your first component.

Once you're done with it you can write more components the same way and play with daily usage guide for passing advanced arguments, writing conditions and loops, dynamic styling, connecting to APIs…

What Can You Actually Do With It?

You can create a simple reusable web-components for your HTML website or build a full fledge app with it. It's as light as powerful, fully driven by the web-browsers standards.

Various applications are running Lego in production for years now.

Because of the standards and the zero dependency you can rely on it for the long term.

Your site/app will still running and remain editable in 10+ years, and as long as web browsers will exist.

How Does LEGO Work?

LEGO (Lightweight Embedded Gluten-free Objects) is a base class that you extend and provide you with methods to use ♻️ reactive and 🏡 native web-components that are easy to digest 🌱 for your browser.

A small CLI in NodeJS come along to build 🚀 your component. There's no Vite nor other 3rd parties, it's just an interpreter of ±180 lines of readable code.

What is LEGO Behind?

  • 👙 Minimalist: 74 61 lines of readable code in its core (non-optimised, uncompressed, no cheating)
  • 🌱 Zero dependency: it uses Petit-Dom which is stable and embedded, so no bad suprise in the future
  • ♻️ Reactive: updating the state recalculate the Virtual Dom when needed
  • 🚀 fast: using virtual dom through a thin layer makes it close to bare-metal
  • 💧 Simple: that's Vanilla, there isn't much to know, it's a raw class to extend; no magic ✨
  • 🪶 3 directives to enhance HTML: :if for conditions, :for for loops, @myfuncname to call an action
  • 🏡 Native: LEGO components are actual native web-components, you benefit from all the today's and tomorrow's possibilites (slot, Shadow DOM, …).

Lego is not (and will never be):

  • 🏯 A full bloated frontend framework with routing. Others do it well.
  • 🏗 A website builder with SSR or similar complexities.
  • 🔐 An HTML replacement that locks you into a specific technology.

Next Steps, Demo and Doc

🧪 View the demo and their source.

📕 Read the full documentation at https://lego.js.org

💭 Lego is inspired from the native Web-Component spec and Riot.

🔧 Customizing and contributing is just much lighter with simplicity, source that are easy to read, to hack and to maintain.

🎈 You can read the core code that is only 61 LOC resulting that Lego is as light as 3Kb for the full bundle!

lego's People

Contributors

cba85 avatar davidbgk avatar ioo avatar mark-russ avatar schafeld avatar schindld avatar vinyll avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

lego's Issues

Default path issues on Windows

Related to #19

I'm supposing Windows does not support ./ paths.
However the default paths innn config are ./bricks and ./dist for now and may have further slash path later.

A resolution might be to replace / with \ when Windows is detected.
Anyone with a little Windows experience is more than welcome to suggest :)

Missing documentation for passing objects as attributes

Lego supports passing strings, arrays, objects… to children.
They should be passed as attributes as so:

<my-child :user="state.user"></my-child>
<script>
  this.init() {
    this.state = { user: {fistname: "John", lastname: "Doe"} }
  }
</script>

Now the <my-child> component can have a state.user that is updated per instance.

-> This should be in the doc

Separation by file

Currently, a component consist of up to three different types of content (template, style, script) in the same file. this makes it more difficult for multiple developers to work on the same components, particular if components are large.

Perhaps this can be better handled by splitting the three functions into separate files, by some naming convention? perhaps like aurelia does it where they have component.html, component.css and component.js/ts

Use components with export/import

The way Lego is used now may be confusing.
The module way is not obvious while it should be the way to go.

goal:

<template>
  hey ${state.name}
</template>

<script>
  export default {
    state = { name: "Joe" }
  }
</script>

this.document returns undefined

Within the Lego.js documentation, it specifies that you can get access to the DOM via the this.document shortcut, but when I try to use it, it always returns undefined. If I could just use this.shadowRoot as I can in vanilla web components, this wouldn't be a problem, but that returns null.

Name Lego is not available on npm

Lego stands for Lightweight Embedded Gluten-free Objects
Suggestion is to rename :(

Proposals:

  • LegoJS
  • Leggo
  • Leego
  • Briquet
  • Bricket
  • Brique
  • Briquette
  • Ligo (Lightweight Isolated…)
  • Nanoblock
  • Particle
  • Particule
  • Spark
  • Ergo
  • partikl
  • Tublo
  • Duplo
  • Block
  • DNA
  • Monomer
  • Nanomer
  • Lipid
  • Phenol
  • Plego
  • Pley
  • Prick
  • Booze
  • Boose
  • Aie
  • Horny

Names that are striked are not available on https://www.npmjs.com/

Enable hyphened attribute to state

Today attribute must be one word:

<my-user firstname="John"></my-user>

We may need to consider hyphened attributes, which are HTML compliant:

<my-user first-name="John"></my-user>

A proposal would be to access this property in camelCase:

bricks/my-user.html

<script>
  <template>
    <p :if="state.firstName">Hello ${state.firstName}</p>
  </template>
  init() {
    this.state = { firstName: "" }
  }
</script>

It might need to be set in the setAttribute() extended function if it the __attributesToState() is not enough.

Query selector

Hi, is there a way to access to a element like querySelector?

my element<\div>
<script> this.shadowRoot.querySelector?? Didn't work :( <script> Anyone?

Typescript

I don't see any mention of typescript in this project, is there any setup where typescript can be used here?

Syntax for attributes

Lego permits to deal with special attributes for conditions, loops, booleans and events.
A syntax has to be defined.

The examples below are considering this context: this.state.people = ['John', 'Maria', 'Socrate']

Conditions

Conditions are evaluated in the :if="${ trueOrFalse }" attribute.

<div :if="${ this.state.people > 5 }">Too many people are present</div>

Condition is false, tag won't be displayed.

<div :if="${ this.state.people < 5 }">Everyone may join</div>

Ouput:

<div>Everyone may join</div>

Loops

A loop attributes is declared as :for="${ itemName in collection }" where collection is the array of items and itemName is the name of the variable in the loop.

<ul>
  <li :for="${ person in this.state.people }">${ this.person }</li>
</ul>

Ouput:

```html
<ul>
  <li>John</li>
  <li>Maria</li>
  <li>Socrate</li>
</ul>

Boolean evaluation

An attribute that ends with a ? will be given a value when true or removed when false.

This is especially useful for attributes like required, checked, selected, …

<input type=checkbox checked?="${ this.state.length > 5 }">

Ouput:

<input type=checkbox>
<input type=checkbox checked?="${ this.state.length < 5 }">

Ouput:

<input type=checkbox checked="checked">

Events

Events are declared with a on- attribute prefix.

<input type=checkbox on-change="this.boxHasChanged">

<script>
  this.boxHasChanged = (event) => {
    alert(`box is now ${ event.target.checked ? 'checked' : 'unchecked' }`)
  }
</script>

cutom events

i've tried use custom events and i failed forthright, someone has used lego with custom events?

Tests are broken due to `window`

We should probably pass the notion of window a different way for the tests to be able to consider that object as with a browser. Probably just including jsdom at the right spot (in the tests?) should do the job.

any help :D

i really like web components and finally found a nice library

i tried your example https://lego.js.org/getting-started/ but..

step 1: npm init -y
step 2: create a file bricks/hello-world.html (with your example code)
step 3: npx @polight/lego and then throw an error

⚠️  Missing lego.config.js file, building with defaults.
El formato del par�metro no es correcto: "bricks".
(node:12984) UnhandledPromiseRejectionWarning: Error: Command failed: cmd /c dir /s /b ./bricks
El formato del par�metro no es correcto: "bricks".

    at checkExecSyncError (child_process.js:616:11)
    at execFileSync (child_process.js:634:15)
    at walkDir "(myPath)"
(Use `node --trace-warnings ...` to show where the warning was created)
(node:12984) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled 
promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). 
(rejection id: 3)
(node:12984) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Allow access to specific variables/functions

A real world usecase requires to access the document, as for collecting data from a form (ex: document.querySelector('a')).

Right now document can't be accessed outside of the component class and we must still extend the Lego class to use it.
We may want to consider to make the document variable accessible.

Same issue with the component itself.
I do have a case where the component itself, as a dom element, has to modify its classList from within the component.
Using the Lego class it's as easy as this.classList but in the new version this is undefined.
We may want to consider to make the component available to the script like with a reference to it such as self, node, component or another name.

This will lead to a reserved words list that must be listed in the doc.
Currently the only reserved words are state and render.
We could either extend the list, or only add a reference to the component and call methods or properties from there.

We need to decide:

  • wether we make a list of reserved keywords or a sole access to one variable that represents the component
  • decide of these names

Pass all attributes to child

In React one can do <ChildElement {...props} /> to pass all parent attributes to the child.

How to do this with Lego?

Plugin system

Some functionalities need to extend Lego.
However writing these functionalities to the core will enlarge the size and might not interest all users.

One of the extension would be to bind local state to a global state to do a job similar to react hooks, context api, …; but simpler.

Other extensions may be useful.

execFileSync find fails on Windows

const stdout = await execFileSync('find', [dirname])

☝️ this is Linux/Mac-specific code. It fails on Windows with "FIND: Parameter format not correct".

The find command on windows is more like grep. The dir /s /b command would be better.

Here's a cross-platform fix:

  let stdout
  if(os.platform() === 'win32') stdout =  execFileSync('cmd', ['/c', 'dir', '/s', '/b', dirname])
  else stdout =  execFileSync('find', [dirname])
  const dirs = String(stdout).split(os.EOL).filter(d => d)

Notice the os.EOL as well, otherwise you end up with a leftover carriage return at the end of each line in Windows.

interact between components

After I have made some components, how do I expose functions or data from one component, to be used by a different component?

Project name makes it difficulty to find documentation

Whenever you try to search for something related to this project, be it on duckduckgo, google or youtube, you get 99.9% false positives and it's essentially impossible to find information.

Even a simple change to the project name, like WebLego or ReactiveLego, would likely make it much easier to discover content.

State changes are not accessible

The following example will toggle only once:

<script>
  const state = { enabled: false }
  
  function toggle() {
    render({ state: !state.enabled })
  }
</script>

<template>
  <p>Status is ${ state.enabled ? 'enabled' : 'disabled' }</p>
  <button @click="toggle">toggle status</button>
</template>

The reason is that const state is sent to this.state in the component init().
However the toggle() function will always refer to the state that was declared, not from the copy of state from within the component.

A solution is to refer this.state from the component to the const state by reference (default in JS).
However this has as drawback: all instances of the component will share the same state.

  • State by reference: this.state = state
  • State by copy: this.state = Object.assign({}, state)

Test SSR

Sounds like webcomponents could be rendered on the server side. Even ShadowDom.
This may be worth a try!

Uniformize module import

Right now we have 2 types of imports: ES6 modules (import … from …) and ES5 imports (const … = require('…')).

The reasons are that Node does not permit ES6 imports while the browser does.

One resolution would be to have ES6 modules all the way. Would Babel be a way to solve?

An extra topic would be to permit Lego to work on "older" browsers. ie not needing to have ES6 modules in the browser.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.