Skip to content

Commit

Permalink
docs: add different targets to getting started
Browse files Browse the repository at this point in the history
  • Loading branch information
smalluban committed May 28, 2019
1 parent cb375b0 commit 72efe86
Show file tree
Hide file tree
Showing 22 changed files with 508 additions and 445 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,15 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [3.0.2](https://github.com/hybridsjs/hybrids/compare/v3.0.1...v3.0.2) (2019-05-17)


### Bug Fixes

* **render:** minor performance refactor fixes ([85b7b46](https://github.com/hybridsjs/hybrids/commit/85b7b46))



### [3.0.1](https://github.com/hybridsjs/hybrids/compare/v3.0.0...v3.0.1) (2019-05-16)


Expand Down
21 changes: 20 additions & 1 deletion README.md
Expand Up @@ -54,11 +54,30 @@ Finally, use your custom element in HTML:
<simple-counter count="10"></simple-counter>
```

### ES Modules

If you target modern browsers and do not want to use external tooling (like [webpack](https://webpack.js.org) or [parcel](https://parceljs.org/)), you can use ES modules:

```html
<script type="module">
// We can use "/src" here - browsers, which support modules also support ES2015
import { html, define } from 'https://unpkg.com/hybrids@[PUT_VERSION_HERE:x.x.x]/src';
...
</script>
```

Please take to account, that it does not provide code minification and loads all required files in separate requests.

### Built Version

You can also use the built version from [unpkg.com](https://unpkg.com) CDN (with `window.hybrids` global namespace):
For older browsers support you can use the built version (with `window.hybrids` global namespace):

```html
<script src="https://unpkg.com/hybrids@[PUT_VERSION_HERE:x.x.x]/dist/hybrids.js"></script>
<script>
const { html, define } = window.hybrids;
...
</script>
```

## Overview
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "hybrids",
"version": "3.0.1",
"version": "3.0.2",
"description": "UI library for creating Web Components",
"main": "lib/index.js",
"module": "esm/index.js",
Expand Down
52 changes: 40 additions & 12 deletions src/cache.js
@@ -1,4 +1,5 @@
import { stringifyElement } from './utils';
import * as emitter from './emitter';

const entries = new WeakMap();
export function getEntry(target, key) {
Expand All @@ -15,27 +16,36 @@ export function getEntry(target, key) {
target,
key,
value: undefined,
deps: new Set(),
contexts: undefined,
deps: undefined,
state: 1,
checksum: 0,
observed: false,
};
targetMap.set(key, entry);
}

return entry;
}

function calculateChecksum({ state, deps }) {
let checksum = state;
deps.forEach((entry) => {
// eslint-disable-next-line no-unused-expressions
entry.target[entry.key];
checksum += entry.state;
});
function calculateChecksum(entry) {
let checksum = entry.state;
if (entry.deps) {
entry.deps.forEach((depEntry) => {
// eslint-disable-next-line no-unused-expressions
depEntry.target[depEntry.key];
checksum += depEntry.state;
});
}

return checksum;
}

function dispatchDeep(entry) {
if (entry.observed) emitter.dispatch(entry);
if (entry.contexts) entry.contexts.forEach(dispatchDeep);
}

let context = null;
export function get(target, key, getter) {
const entry = getEntry(target, key);
Expand All @@ -46,9 +56,15 @@ export function get(target, key, getter) {
}

if (context) {
context.deps = context.deps || new Set();
context.deps.add(entry);
}

if (context && (context.observed || (context.contexts && context.contexts.size))) {
entry.contexts = entry.contexts || new Set();
entry.contexts.add(context);
}

const parentContext = context;
context = entry;

Expand All @@ -57,16 +73,20 @@ export function get(target, key, getter) {
return entry.value;
}

if (entry.deps.size) {
entry.deps.clear();
if (entry.deps && entry.deps.size) {
entry.deps.forEach(depEntry => depEntry.contexts && depEntry.contexts.delete(entry));
entry.deps = undefined;
}

try {
const nextValue = getter(target, entry.value);

if (nextValue !== entry.value) {
entry.state += 1;
entry.lastValue = entry.value;
entry.value = nextValue;

dispatchDeep(entry);
}

entry.checksum = calculateChecksum(entry);
Expand All @@ -79,7 +99,7 @@ export function get(target, key, getter) {
return entry.value;
}

export function set(target, key, setter, value, callback) {
export function set(target, key, setter, value) {
if (context) {
context = null;
throw Error(`Try to set '${key}' of '${stringifyElement(target)}' in get call`);
Expand All @@ -92,7 +112,7 @@ export function set(target, key, setter, value, callback) {
entry.state += 1;
entry.value = newValue;

callback();
dispatchDeep(entry);
}
}

Expand All @@ -105,8 +125,16 @@ export function invalidate(target, key, clearValue) {
const entry = getEntry(target, key);

entry.checksum = 0;
dispatchDeep(entry);

if (clearValue) {
entry.value = undefined;
}
}

export function observe(target, key, fn) {
const entry = getEntry(target, key);
entry.observed = true;

return emitter.subscribe(entry, fn);
}
26 changes: 1 addition & 25 deletions src/children.js
@@ -1,5 +1,3 @@
import { deferred } from './utils';

function walk(node, fn, options, items = []) {
Array.from(node.children).forEach((child) => {
const hybrids = child.constructor.hybrids;
Expand All @@ -22,34 +20,12 @@ export default function children(hybridsOrFn, options = { deep: false, nested: f
get(host) { return walk(host, fn, options); },
connect(host, key, invalidate) {
const observer = new MutationObserver(invalidate);
const set = new Set();

const childEventListener = ({ target }) => {
if (!set.size) {
deferred.then(() => {
const list = host[key];
for (let i = 0; i < list.length; i += 1) {
if (set.has(list[i])) {
invalidate(false);
break;
}
}
set.clear();
});
}
set.add(target);
};

observer.observe(host, {
childList: true, subtree: !!options.deep,
});

host.addEventListener('@invalidate', childEventListener);

return () => {
observer.disconnect();
host.removeEventListener('@invalidate', childEventListener);
};
return () => { observer.disconnect(); };
},
};
}
80 changes: 39 additions & 41 deletions src/define.js
Expand Up @@ -2,45 +2,34 @@ import property from './property';
import render from './render';

import * as cache from './cache';
import { dispatch, pascalToDash, deferred } from './utils';
import { pascalToDash, deferred } from './utils';

/* istanbul ignore next */
try { process.env.NODE_ENV } catch(e) { var process = { env: { NODE_ENV: 'production' } }; } // eslint-disable-line

const dispatchSet = new Set();

function dispatchInvalidate(host) {
if (!dispatchSet.size) {
deferred.then(() => {
dispatchSet.forEach(target => dispatch(target, '@invalidate', { bubbles: true }));
dispatchSet.clear();
});
}

dispatchSet.add(host);
}

const defaultMethod = (host, value) => value;
const execute = fn => fn();

function compile(Hybrid, hybrids) {
Hybrid.hybrids = hybrids;
function compile(Hybrid, descriptors) {
Hybrid.hybrids = descriptors;
Hybrid.connects = [];

Object.keys(hybrids).forEach((key) => {
const value = hybrids[key];
const type = typeof value;
Object.keys(descriptors).forEach((key) => {
const desc = descriptors[key];
const type = typeof desc;

let config;

if (type === 'function') {
config = key === 'render' ? render(value) : { get: value };
} else if (value === null || type !== 'object' || (type === 'object' && !value.get && !value.set && !value.connect)) {
config = property(value);
config = key === 'render' ? render(desc) : { get: desc };
} else if (desc === null || type !== 'object' || (type === 'object' && !desc.get && !desc.set && !desc.connect && !desc.observe)) {
config = property(desc);
} else {
config = {
get: value.get || defaultMethod,
set: value.set || (!value.get && defaultMethod) || undefined,
connect: value.connect,
get: desc.get || defaultMethod,
set: desc.set || (!desc.get && defaultMethod) || undefined,
connect: desc.connect,
observe: desc.observe,
};
}

Expand All @@ -49,18 +38,28 @@ function compile(Hybrid, hybrids) {
return cache.get(this, key, config.get);
},
set: config.set && function set(newValue) {
cache.set(this, key, config.set, newValue, () => dispatchInvalidate(this));
cache.set(this, key, config.set, newValue);
},
enumerable: true,
configurable: process.env.NODE_ENV !== 'production',
});

if (config.connect) {
Hybrid.connects.push(host => config.connect(host, key, (clearCache = true) => {
if (clearCache) cache.invalidate(host, key);
dispatchInvalidate(host);
Hybrid.connects.push(host => config.connect(host, key, () => {
cache.invalidate(host, key);
}));
}

if (config.observe) {
Hybrid.connects.push((host) => {
let lastValue;
return cache.observe(host, key, () => {
const value = host[key];
config.observe(host, value, lastValue);
lastValue = value;
});
});
}
});
}

Expand Down Expand Up @@ -93,7 +92,6 @@ if (process.env.NODE_ENV !== 'production') {
});

node.connectedCallback();
dispatchInvalidate(node);
}
});
updateQueue.clear();
Expand All @@ -103,7 +101,7 @@ if (process.env.NODE_ENV !== 'production') {
};
}

const connects = new WeakMap();
const disconnects = new WeakMap();

function defineElement(tagName, hybridsOrConstructor) {
const type = typeof hybridsOrConstructor;
Expand Down Expand Up @@ -144,19 +142,19 @@ function defineElement(tagName, hybridsOrConstructor) {
static get name() { return tagName; }

connectedCallback() {
const list = this.constructor.connects.reduce((acc, fn) => {
const result = fn(this);
if (result) acc.add(result);
return acc;
}, new Set());

connects.set(this, list);
dispatchInvalidate(this);
const { connects } = this.constructor;
const list = [];

for (let index = 0; index < connects.length; index += 1) {
const disconnect = connects[index](this);
if (disconnect) list.push(disconnect);
}

disconnects.set(this, list);
}

disconnectedCallback() {
const list = connects.get(this);
list.forEach(fn => fn());
disconnects.get(this).forEach(execute);
}
}

Expand Down

0 comments on commit 72efe86

Please sign in to comment.