Skip to content

Commit

Permalink
Decouple templating engine from “x-element”.
Browse files Browse the repository at this point in the history
This makes the following changes:

1. The library no longer declares _any_ dependencies.
2. A new, default template engine is provided.
3. Integrators may self-configure the templating engine to be used.
4. Adds TypeScript “x-element.d.ts” declarations.

Closes #105. Closes #113. Closes #115. Closes #121. Closes #122.
Closes #124. Closes #131.
  • Loading branch information
theengineear committed Mar 8, 2023
1 parent e14ce92 commit fbcf57c
Show file tree
Hide file tree
Showing 50 changed files with 3,305 additions and 479 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = {
'quotes': ['warn', 'single', { avoidEscape: true, allowTemplateLiterals: true }],
'semi': 'warn',
},
ignorePatterns: ['*.d.ts'],
env: {
es6: true,
browser: true,
Expand Down
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

A dead simple starting point for custom elements. It provides the following functionality:

- Efficient element generation and data binding via [lit-html](https://lit.dev)
- Efficient element generation and data binding via default templating engine
- ...or drop in an engine of your choice (e.g., [lit-html](https://lit.dev))
- Automatic `.property` to `[attribute]` reflection (opt-in)
- Automatic `[attribute]` to `.property` synchronization (one-directional, on connected)
- Simple and efficient property observation and computation
Expand All @@ -28,10 +29,14 @@ curl https://raw.githubusercontent.com/Netflix/x-element/master/x-element.js > x
```
yarn add @netflix/x-element
```
or
or
```
npm install @netflix/x-element
```
or
```
import XElement from 'https://deno.land/x/element/x-element.js';
```

## Project Philosophy:

Expand All @@ -42,7 +47,7 @@ npm install @netflix/x-element
5. Follow the web platform precedents whenever possible
6. Remain compatible with any browser which fully supports custom elements
7. Prioritize simple syntax and useful comments in the code itself
8. Strive for zero dependencies (never add more!)
8. Zero dependencies

## Development:

Expand All @@ -51,7 +56,12 @@ yarn install && yarn start
```

Then...
* http://localhost:8080
* http://localhost:8080/demo
* http://localhost:8080/demo/chess
* http://localhost:8080/demo/lit-html
* http://localhost:8080/demo/uhtml
* http://localhost:8080/demo/react
* http://localhost:8080/test
* * http://localhost:8080/performance

(See [SPEC.md](./SPEC.md) for more details.)
38 changes: 35 additions & 3 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ A base class for custom elements.
Define and register your element:

```javascript
import XElement from 'https://unpkg.com/@netflix/x-element/x-element.js';
import XElement from 'https://deno.land/x/element/x-element.js';

class HelloWorld extends XElement {
static template(html) {
Expand Down Expand Up @@ -34,8 +34,40 @@ And use it in your markup:

## Rendering

XElement uses [lit-html] to efficiently turn interpolated html markup into dom
nodes.
XElement uses default templating engine (or one you choose like [lit-html]) to
efficiently turn interpolated html markup into dom nodes. Here's an example
using [lit-html]:

```javascript
import XElement from 'https://deno.land/x/element/x-element.js';
import { asyncAppend } from 'https://unpkg.com/lit-html/directives/async-append.js?module';
import { asyncReplace } from 'https://unpkg.com/lit-html/directives/async-replace.js?module';
import { cache } from 'https://unpkg.com/lit-html/directives/cache.js?module';
import { classMap } from 'https://unpkg.com/lit-html/directives/class-map.js?module';
import { directive } from 'https://unpkg.com/lit-html/directive.js?module';
import { guard } from 'https://unpkg.com/lit-html/directives/guard.js?module';
import { html, render as originalRender, svg } from 'https://unpkg.com/lit-html/lit-html.js?module';
import { ifDefined } from 'https://unpkg.com/lit-html/directives/if-defined.js?module';
import { live } from 'https://unpkg.com/lit-html/directives/live.js?module';
import { repeat } from 'https://unpkg.com/lit-html/directives/repeat.js?module';
import { styleMap } from 'https://unpkg.com/lit-html/directives/style-map.js?module';
import { templateContent } from 'https://unpkg.com/lit-html/directives/template-content.js?module';
import { unsafeHTML } from 'https://unpkg.com/lit-html/directives/unsafe-html.js?module';
import { unsafeSVG } from 'https://unpkg.com/lit-html/directives/unsafe-svg.js?module';
import { until } from 'https://unpkg.com/lit-html/directives/until.js?module';

export default class BaseElement extends XElement {
// Use lit-html's template engine rather than the built-in x-element engine.
static get templateEngine() {
const render = (container, template) => originalRender(template, container);
return {
render, html, svg, asyncAppend, asyncReplace, cache, classMap, directive,
guard, ifDefined, live, repeat, styleMap, templateContent, unsafeHTML,
unsafeSVG, until,
};
}
}
```

## Properties

Expand Down
14 changes: 3 additions & 11 deletions index.css → demo/chess/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@
font-size: 1.2rem;
}

a {
color: hsl(270, 100%, 50%);
}

a:not(:hover) {
text-decoration: none;
}

#container {
max-width: 12rem;
display: flex;
Expand All @@ -20,14 +12,14 @@ a:not(:hover) {
perspective: 1000px;
}

hello-world + hello-world {
chess-piece + chess-piece {
--hello-size: 6rem;
}

hello-world + hello-world + hello-world {
chess-piece + chess-piece + chess-piece {
--hello-size: 5rem;
}

hello-world:last-of-type {
chess-piece:last-of-type {
--hello-size: 4rem;
}
16 changes: 16 additions & 0 deletions demo/chess/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="index.css">
<script type="module" src="index.js"></script>
</head>
<body>
<div id="container">
<chess-piece rank="&#9813;"></chess-piece>
<chess-piece rank="&#9812;"></chess-piece>
<chess-piece rank="&#9816;"></chess-piece>
<chess-piece></chess-piece>
</div>
</body>
</html>
6 changes: 3 additions & 3 deletions index.js → demo/chess/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import XElement from './x-element.js';
import XElement from '../../x-element.js';

class HelloElement extends XElement {
class ChessPieceElement extends XElement {
static get properties() {
return {
rank: {
Expand Down Expand Up @@ -80,4 +80,4 @@ class HelloElement extends XElement {
}
}

customElements.define('hello-world', HelloElement);
customElements.define('chess-piece', ChessPieceElement);
38 changes: 0 additions & 38 deletions demo/demo-element-attributes.js

This file was deleted.

41 changes: 0 additions & 41 deletions demo/demo-element-properties.js

This file was deleted.

41 changes: 0 additions & 41 deletions demo/demo-element.js

This file was deleted.

70 changes: 70 additions & 0 deletions demo/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
:root {
font-family: monospace;
font-size: 1.2rem;
}

body {
margin: 0;
}

#content {
position: relative;
z-index: 1;
padding: 8px 12px;
cursor: default;
}

#title {
position: fixed;
margin: 0;
top: 50vh;
left: 50vw;
transform: translate(-50%, -50%);
}

#title-link,
#title-link:visited {
color: inherit;
text-decoration: none;
}
#title-link:hover {
text-decoration: underline;
}
#title-link:active {
text-decoration: none;
}

#tagline,
#label {
font-size: 0.8rem;
}

#label {
margin-top: 20px;
margin-bottom: 0;
}

#list {
margin-top: 8px;
padding-inline-start: 30px;
}

#x {
position: relative;
z-index: 0;
}

ul {
font-size: 0.7rem;
}

a:any-link,
a:visited {
color: #047bff;
}
a:hover {
color: #ff2c55;
}
a:active {
color: #ffcc01;
}
Loading

0 comments on commit fbcf57c

Please sign in to comment.