Repository: WebReflection/hyperHTML-Element
Branch: master
Commit: 418299139c31
Files: 28
Total size: 259.4 KB
Directory structure:
gitextract_91jr2tdp/
├── .github/
│ └── workflows/
│ └── node.js.yml
├── .gitignore
├── .npmignore
├── .npmrc
├── LICENSE.txt
├── README.md
├── cjs/
│ ├── index.d.ts
│ ├── index.js
│ └── package.json
├── es5.config.js
├── es5.js
├── esm/
│ ├── index.d.ts
│ └── index.js
├── esm.config.js
├── index.d.ts
├── index.js
├── min.js
├── package.json
├── test/
│ ├── boolean.html
│ ├── builtin.html
│ ├── button.html
│ ├── ce.js
│ ├── checked.html
│ ├── index.html
│ ├── test.es5.js
│ └── test.js
├── test.js
└── typescript.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/node.js.yml
================================================
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run build --if-present
- run: npm test
- run: npm run coverage --if-present
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .gitignore
================================================
.DS_Store
.nyc_output/
node_modules/
coverage/
================================================
FILE: .npmignore
================================================
.nyc_output/
coverage/
node_modules/
test/*
.babelrc
.gitignore
.travis.yml
es5.config.js
esm.config.js
package-lock.json
test.js
typescript.md
================================================
FILE: .npmrc
================================================
package-lock=true
package-lock=true
================================================
FILE: LICENSE.txt
================================================
ISC License
Copyright (c) 2017-2018, Andrea Giammarchi, @WebReflection
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
================================================
FILE: README.md
================================================
# hyperHTML-Element
[](https://opensource.org/licenses/ISC) [](https://travis-ci.org/WebReflection/hyperHTML-Element) [](https://greenkeeper.io/) 
An extensible class to define hyperHTML based Custom Elements.
`npm install hyperhtml-element`
#### hyperHTML included
This class attaches all `hyperHTML` methods to itself,
with the only exception of the `define` method,
used in here to define Custom Elements instead.
To have same [define functionality](https://viperhtml.js.org/hyperhtml/documentation/#api-3),
please use `HyperHTMLElement.intent(...)` which provides exact same API.
### Documentation
You can find more info about this helper in [hyperHTML documentation](https://viperhtml.js.org/hyperhtml/documentation/#components-2) page.
### The Class
```js
const HyperHTMLElement = require('hyperhtml-element');
class MyElement extends HyperHTMLElement {
// observed attributes are automatically defined as accessors
static get observedAttributes() { return ['key']; }
// boolean attributes are automatically defined as accessors
// and will set or remove the passed value
static get booleanAttributes() { return ['active']; }
// invoked once the component has been fully upgraded
// suitable to perform any sort of setup
// granted to be invoked right before either
// connectedCallback or attributeChangedCallback
created() {
// triggers automatically attributeChangedCallback
this.key = 'value';
}
attributeChangedCallback(name, prev, curr) {
// when invoked, attributes will be already reflected
// through their accessor
this.key === curr; // true, and curr === "value"
this.getAttribute('key') === this.key; // always true
this.render();
}
render() {
// lazily defined, this.html property points to an hyperHTML bound context
// which could be the element shadowRoot or the element itself.
// All events can be handled directly by the context, thanks to handleEvent
// https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38
return this.html`
Hello HyperHTMLElement
( ${this.state.clicks} )`;
}
// using the inherited handleEvent,
// events can be easily defined as methods with `on` prefix.
onclick(e) {
// `this` refers to the current custom element
console.log(this, 'click', e.target);
// state handling, updates the view
this.setState({clicks: this.state.clicks + 1});
}
// alternatively, you can specify a `data-call`
// attribute with the name of the method to invoke
// this.html`try`;
onAnyEvent(e) {
// `this` still refers to the current custom element
console.log(this, e.type, e.currentTarget, e.target);
}
// you can also use Preact-like events handling
// this is less efficient, but migration friendly.
// The method is bound once per instance so that
// this.handleClick === this.handleClick is always true
// this.html`try`;
handleClick(e) {
// `this` still refers to the current custom element
console.log(this, e.type, e.currentTarget, e.target);
}
// define a default state to use whenever this.state is accessed
// it can create states from observed properties too
get defaultState() {
return {clicks: 0, key: this.key};
}
// this method is Preact friendly, once invoked
// as this.setState({new: 'value'});
// it will shallow copy properties over
// and it will invoke this.render() right after
setState(objOrFn)
// all other native Custom Elements method works as usual
// connectedCallback() { ... }
// adoptedCallback() { ... }
}
// classes must be defined through their public static method
// this is the moment the class will be fully setup once
// and registered to the customElements Registry.
MyElement.define('my-element');
```
#### New in v1.8
You can now define custom elements builtins too:
```js
class MyLink extends HyperHTMLElement {
created() { this.render(); }
render() {
return this.html`hello there!`;
}
}
MyLink.define('my-link', {extends: 'a'});
```
### Compatibility
`HyperHTMLElement` is compatible with every mobile browser and IE11 or greater.
There is a [native live test](https://webreflection.github.io/hyperHTML-Element/test/) page also [transpiled for ES5](https://webreflection.github.io/hyperHTML-Element/test/?es5) browsers.
================================================
FILE: cjs/index.d.ts
================================================
import HyperHTMLElement from "..";
export * from '..';
export default HyperHTMLElement;
================================================
FILE: cjs/index.js
================================================
'use strict';
/*! (C) 2017-2018 Andrea Giammarchi - ISC Style License */
const {Component, bind, define, hyper, wire} = require('hyperhtml');
// utils to deal with custom elements builtin extends
const ATTRIBUTE_CHANGED_CALLBACK = 'attributeChangedCallback';
const O = Object;
const classes = [];
const defineProperty = O.defineProperty;
const getOwnPropertyDescriptor = O.getOwnPropertyDescriptor;
const getOwnPropertyNames = O.getOwnPropertyNames;
/* istanbul ignore next */
const getOwnPropertySymbols = O.getOwnPropertySymbols || (() => []);
/* istanbul ignore next */
const getPrototypeOf = O.getPrototypeOf || (o => o.__proto__);
/* istanbul ignore next */
const ownKeys = typeof Reflect === 'object' && Reflect.ownKeys ||
(o => getOwnPropertyNames(o).concat(getOwnPropertySymbols(o)));
/* istanbul ignore next */
const setPrototypeOf = O.setPrototypeOf ||
((o, p) => (o.__proto__ = p, o));
/* istanbul ignore stop */
const camel = name => name.replace(/-([a-z])/g, ($0, $1) => $1.toUpperCase());
const {attachShadow} = HTMLElement.prototype;
const sr = new WeakMap;
class HyperHTMLElement extends HTMLElement {
// define a custom-element in the CustomElementsRegistry
// class MyEl extends HyperHTMLElement {}
// MyEl.define('my-el');
static define(name, options) {
const Class = this;
const proto = Class.prototype;
const onChanged = proto[ATTRIBUTE_CHANGED_CALLBACK];
const hasChange = !!onChanged;
// Class.booleanAttributes
// -----------------------------------------------
// attributes defined as boolean will have
// an either available or not available attribute
// regardless of the value.
// All falsy values, or "false", mean attribute removed
// while truthy values will be set as is.
// Boolean attributes are also automatically observed.
const booleanAttributes = Class.booleanAttributes || [];
booleanAttributes.forEach(attribute => {
const name = camel(attribute);
if (!(name in proto)) defineProperty(
proto,
name,
{
configurable: true,
get() {
return this.hasAttribute(attribute);
},
set(value) {
if (!value || value === 'false')
this.removeAttribute(attribute);
else
this.setAttribute(attribute, '');
}
}
);
});
// Class.observedAttributes
// -------------------------------------------------------
// HyperHTMLElement will directly reflect get/setAttribute
// operation once these attributes are used, example:
// el.observed = 123;
// will automatically do
// el.setAttribute('observed', 123);
// triggering also the attributeChangedCallback
const observedAttributes = (Class.observedAttributes || []).filter(
attribute => booleanAttributes.indexOf(attribute) < 0
);
observedAttributes.forEach(attribute => {
// it is possible to redefine the behavior at any time
// simply overwriting get prop() and set prop(value)
const name = camel(attribute);
if (!(name in proto)) defineProperty(
proto,
name,
{
configurable: true,
get() {
return this.getAttribute(attribute);
},
set(value) {
if (value == null)
this.removeAttribute(attribute);
else
this.setAttribute(attribute, value);
}
}
);
});
// if these are defined, overwrite the observedAttributes getter
// to include also booleanAttributes
const attributes = booleanAttributes.concat(observedAttributes);
if (attributes.length)
defineProperty(Class, 'observedAttributes', {
get() { return attributes; }
});
// created() {}
// ---------------------------------
// an initializer method that grants
// the node is fully known to the browser.
// It is ensured to run either after DOMContentLoaded,
// or once there is a next sibling (stream-friendly) so that
// you have full access to element attributes and/or childNodes.
const created = proto.created || function () {
this.render();
};
// used to ensure create() is called once and once only
defineProperty(
proto,
'_init$',
{
configurable: true,
writable: true,
value: true
}
);
defineProperty(
proto,
ATTRIBUTE_CHANGED_CALLBACK,
{
configurable: true,
value: function aCC(name, prev, curr) {
if (this._init$) {
checkReady.call(this, created, attributes, booleanAttributes);
if (this._init$)
return this._init$$.push(aCC.bind(this, name, prev, curr));
}
// ensure setting same value twice
// won't trigger twice attributeChangedCallback
if (hasChange && prev !== curr) {
onChanged.apply(this, arguments);
}
}
}
);
const onConnected = proto.connectedCallback;
const hasConnect = !!onConnected;
defineProperty(
proto,
'connectedCallback',
{
configurable: true,
value: function cC() {
if (this._init$) {
checkReady.call(this, created, attributes, booleanAttributes);
if (this._init$)
return this._init$$.push(cC.bind(this));
}
if (hasConnect) {
onConnected.apply(this, arguments);
}
}
}
);
// define lazily all handlers
// class { handleClick() { ... }
// render() { `` } }
getOwnPropertyNames(proto).forEach(key => {
if (/^handle[A-Z]/.test(key)) {
const _key$ = '_' + key + '$';
const method = proto[key];
defineProperty(proto, key, {
configurable: true,
get() {
return this[_key$] ||
(this[_key$] = method.bind(this));
}
});
}
});
// whenever you want to directly use the component itself
// as EventListener, you can pass it directly.
// https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38
// class Reactive extends HyperHTMLElement {
// oninput(e) { console.log(this, 'changed', e.target.value); }
// render() { this.html``; }
// }
if (!('handleEvent' in proto)) {
defineProperty(
proto,
'handleEvent',
{
configurable: true,
value(event) {
this[
(event.currentTarget.dataset || {}).call ||
('on' + event.type)
](event);
}
}
);
}
if (options && options.extends) {
const Native = document.createElement(options.extends).constructor;
const Intermediate = class extends Native {};
const ckeys = ['length', 'name', 'arguments', 'caller', 'prototype'];
const pkeys = [];
let Super = null;
let BaseClass = Class;
while (Super = getPrototypeOf(BaseClass)) {
[
{target: Intermediate, base: Super, keys: ckeys},
{target: Intermediate.prototype, base: Super.prototype, keys: pkeys}
]
.forEach(({target, base, keys}) => {
ownKeys(base)
.filter(key => keys.indexOf(key) < 0)
.forEach((key) => {
keys.push(key);
defineProperty(
target,
key,
getOwnPropertyDescriptor(base, key)
);
});
});
BaseClass = Super;
if (Super === HyperHTMLElement)
break;
}
setPrototypeOf(Class, Intermediate);
setPrototypeOf(proto, Intermediate.prototype);
customElements.define(name, Class, options);
} else {
customElements.define(name, Class);
}
classes.push(Class);
return Class;
}
// weakly relate the shadowRoot for refs usage
attachShadow() {
const shadowRoot = attachShadow.apply(this, arguments);
sr.set(this, shadowRoot);
return shadowRoot;
}
// returns elements by ref
get refs() {
const value = {};
if ('_html$' in this) {
const all = (sr.get(this) || this).querySelectorAll('[ref]');
for (let {length} = all, i = 0; i < length; i++) {
const node = all[i];
value[node.getAttribute('ref')] = node;
}
Object.defineProperty(this, 'refs', {value});
return value;
}
return value;
}
// lazily bind once hyperHTML logic
// to either the shadowRoot, if present and open,
// the _shadowRoot property, if set due closed shadow root,
// or the custom-element itself if no Shadow DOM is used.
get html() {
return this._html$ || (this.html = bind(
// in a way or another, bind to the right node
// backward compatible, first two could probably go already
this.shadowRoot || this._shadowRoot || sr.get(this) || this
));
}
// it can be set too if necessary, it won't invoke render()
set html(value) {
defineProperty(this, '_html$', {configurable: true, value: value});
}
// overwrite this method with your own render
render() {}
// ---------------------//
// Basic State Handling //
// ---------------------//
// define the default state object
// you could use observed properties too
get defaultState() { return {}; }
// the state with a default
get state() {
return this._state$ || (this.state = this.defaultState);
}
// it can be set too if necessary, it won't invoke render()
set state(value) {
defineProperty(this, '_state$', {configurable: true, value: value});
}
// currently a state is a shallow copy, like in Preact or other libraries.
// after the state is updated, the render() method will be invoked.
// ⚠️ do not ever call this.setState() inside this.render()
setState(state, render) {
const target = this.state;
const source = typeof state === 'function' ? state.call(this, target) : state;
for (const key in source) target[key] = source[key];
if (render !== false) this.render();
return this;
}
};
// exposing hyperHTML utilities
HyperHTMLElement.Component = Component;
HyperHTMLElement.bind = bind;
HyperHTMLElement.intent = define;
HyperHTMLElement.wire = wire;
HyperHTMLElement.hyper = hyper;
try {
if (Symbol.hasInstance) classes.push(
defineProperty(HyperHTMLElement, Symbol.hasInstance, {
enumerable: false,
configurable: true,
value(instance) {
return classes.some(isPrototypeOf, getPrototypeOf(instance));
}
}));
} catch(meh) {}
Object.defineProperty(exports, '__esModule', {value: true}).default = HyperHTMLElement;
// ------------------------------//
// DOMContentLoaded VS created() //
// ------------------------------//
const dom = {
type: 'DOMContentLoaded',
handleEvent() {
if (dom.ready()) {
document.removeEventListener(dom.type, dom, false);
dom.list.splice(0).forEach(invoke);
}
else
setTimeout(dom.handleEvent);
},
ready() {
return document.readyState === 'complete';
},
list: []
};
if (!dom.ready()) {
document.addEventListener(dom.type, dom, false);
}
function checkReady(created, attributes, booleanAttributes) {
if (dom.ready() || isReady.call(this, created, attributes, booleanAttributes)) {
if (this._init$) {
const list = this._init$$ || [];
delete this._init$$;
const self = defineProperty(this, '_init$', {value: false});
booleanAttributes.forEach(name => {
if (self.getAttribute(name) === 'false')
self.removeAttribute(name);
});
attributes.forEach(name => {
if (self.hasOwnProperty(name)) {
const curr = self[name];
delete self[name];
list.unshift(() => { self[name] = curr; });
}
});
created.call(self);
list.forEach(invoke);
}
} else {
if (!this.hasOwnProperty('_init$$'))
defineProperty(this, '_init$$', {configurable: true, value: []});
dom.list.push(checkReady.bind(this, created, attributes, booleanAttributes));
}
}
function invoke(fn) {
fn();
}
function isPrototypeOf(Class) {
return this === Class.prototype;
}
function isReady(created, attributes, booleanAttributes) {
let el = this;
do { if (el.nextSibling) return true; }
while (el = el.parentNode);
setTimeout(checkReady.bind(this, created, attributes, booleanAttributes));
return false;
}
================================================
FILE: cjs/package.json
================================================
{"type":"commonjs"}
================================================
FILE: es5.config.js
================================================
import resolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';
export default {
input: 'esm/index.js',
plugins: [
resolve({module: true}),
babel({presets: ["@babel/preset-env"]})
],
context: 'null',
moduleContext: 'null',
output: {
exports: 'named',
file: 'es5.js',
format: 'iife',
name: 'HyperHTMLElement'
}
};
================================================
FILE: es5.js
================================================
var HyperHTMLElement = (function (exports) {
'use strict';
function _typeof(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof(obj);
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _construct(Parent, args, Class) {
if (_isNativeReflectConstruct()) {
_construct = Reflect.construct;
} else {
_construct = function _construct(Parent, args, Class) {
var a = [null];
a.push.apply(a, args);
var Constructor = Function.bind.apply(Parent, a);
var instance = new Constructor();
if (Class) _setPrototypeOf(instance, Class.prototype);
return instance;
};
}
return _construct.apply(null, arguments);
}
function _isNativeFunction(fn) {
return Function.toString.call(fn).indexOf("[native code]") !== -1;
}
function _wrapNativeSuper(Class) {
var _cache = typeof Map === "function" ? new Map() : undefined;
_wrapNativeSuper = function _wrapNativeSuper(Class) {
if (Class === null || !_isNativeFunction(Class)) return Class;
if (typeof Class !== "function") {
throw new TypeError("Super expression must either be null or a function");
}
if (typeof _cache !== "undefined") {
if (_cache.has(Class)) return _cache.get(Class);
_cache.set(Class, Wrapper);
}
function Wrapper() {
return _construct(Class, arguments, _getPrototypeOf(this).constructor);
}
Wrapper.prototype = Object.create(Class.prototype, {
constructor: {
value: Wrapper,
enumerable: false,
writable: true,
configurable: true
}
});
return _setPrototypeOf(Wrapper, Class);
};
return _wrapNativeSuper(Class);
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _possibleConstructorReturn(self, call) {
if (call && (typeof call === "object" || typeof call === "function")) {
return call;
} else if (call !== void 0) {
throw new TypeError("Derived constructors may only return object or undefined");
}
return _assertThisInitialized(self);
}
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
/*! (c) Andrea Giammarchi - ISC */
var self$3 = {};
try {
self$3.WeakMap = WeakMap;
} catch (WeakMap) {
// this could be better but 90% of the time
// it's everything developers need as fallback
self$3.WeakMap = function (id, Object) {
var dP = Object.defineProperty;
var hOP = Object.hasOwnProperty;
var proto = WeakMap.prototype;
proto["delete"] = function (key) {
return this.has(key) && delete key[this._];
};
proto.get = function (key) {
return this.has(key) ? key[this._] : void 0;
};
proto.has = function (key) {
return hOP.call(key, this._);
};
proto.set = function (key, value) {
dP(key, this._, {
configurable: true,
value: value
});
return this;
};
return WeakMap;
function WeakMap(iterable) {
dP(this, '_', {
value: '_@ungap/weakmap' + id++
});
if (iterable) iterable.forEach(add, this);
}
function add(pair) {
this.set(pair[0], pair[1]);
}
}(Math.random(), Object);
}
var WeakMap$1 = self$3.WeakMap;
/*! (c) Andrea Giammarchi - ISC */
var self$2 = {};
try {
self$2.WeakSet = WeakSet;
} catch (WeakSet) {
(function (id, dP) {
var proto = WeakSet.prototype;
proto.add = function (object) {
if (!this.has(object)) dP(object, this._, {
value: true,
configurable: true
});
return this;
};
proto.has = function (object) {
return this.hasOwnProperty.call(object, this._);
};
proto["delete"] = function (object) {
return this.has(object) && delete object[this._];
};
self$2.WeakSet = WeakSet;
function WeakSet() {
dP(this, '_', {
value: '_@ungap/weakmap' + id++
});
}
})(Math.random(), Object.defineProperty);
}
var WeakSet$1 = self$2.WeakSet;
var _ref = [],
indexOf$1 = _ref.indexOf;
var append = function append(get, parent, children, start, end, before) {
var isSelect = ('selectedIndex' in parent);
var noSelection = isSelect;
while (start < end) {
var child = get(children[start], 1);
parent.insertBefore(child, before);
if (isSelect && noSelection && child.selected) {
noSelection = !noSelection;
var selectedIndex = parent.selectedIndex;
parent.selectedIndex = selectedIndex < 0 ? start : indexOf$1.call(parent.querySelectorAll('option'), child);
}
start++;
}
};
var eqeq = function eqeq(a, b) {
return a == b;
};
var identity = function identity(O) {
return O;
};
var indexOf = function indexOf(moreNodes, moreStart, moreEnd, lessNodes, lessStart, lessEnd, compare) {
var length = lessEnd - lessStart;
/* istanbul ignore if */
if (length < 1) return -1;
while (moreEnd - moreStart >= length) {
var m = moreStart;
var l = lessStart;
while (m < moreEnd && l < lessEnd && compare(moreNodes[m], lessNodes[l])) {
m++;
l++;
}
if (l === lessEnd) return moreStart;
moreStart = m + 1;
}
return -1;
};
var isReversed = function isReversed(futureNodes, futureEnd, currentNodes, currentStart, currentEnd, compare) {
while (currentStart < currentEnd && compare(currentNodes[currentStart], futureNodes[futureEnd - 1])) {
currentStart++;
futureEnd--;
}
return futureEnd === 0;
};
var next = function next(get, list, i, length, before) {
return i < length ? get(list[i], 0) : 0 < i ? get(list[i - 1], -0).nextSibling : before;
};
var remove = function remove(get, children, start, end) {
while (start < end) {
drop(get(children[start++], -1));
}
}; // - - - - - - - - - - - - - - - - - - -
// diff related constants and utilities
// - - - - - - - - - - - - - - - - - - -
var DELETION = -1;
var INSERTION = 1;
var SKIP = 0;
var SKIP_OND = 50;
var HS = function HS(futureNodes, futureStart, futureEnd, futureChanges, currentNodes, currentStart, currentEnd, currentChanges) {
var k = 0;
/* istanbul ignore next */
var minLen = futureChanges < currentChanges ? futureChanges : currentChanges;
var link = Array(minLen++);
var tresh = Array(minLen);
tresh[0] = -1;
for (var i = 1; i < minLen; i++) {
tresh[i] = currentEnd;
}
var nodes = currentNodes.slice(currentStart, currentEnd);
for (var _i = futureStart; _i < futureEnd; _i++) {
var index = nodes.indexOf(futureNodes[_i]);
if (-1 < index) {
var idxInOld = index + currentStart;
k = findK(tresh, minLen, idxInOld);
/* istanbul ignore else */
if (-1 < k) {
tresh[k] = idxInOld;
link[k] = {
newi: _i,
oldi: idxInOld,
prev: link[k - 1]
};
}
}
}
k = --minLen;
--currentEnd;
while (tresh[k] > currentEnd) {
--k;
}
minLen = currentChanges + futureChanges - k;
var diff = Array(minLen);
var ptr = link[k];
--futureEnd;
while (ptr) {
var _ptr = ptr,
newi = _ptr.newi,
oldi = _ptr.oldi;
while (futureEnd > newi) {
diff[--minLen] = INSERTION;
--futureEnd;
}
while (currentEnd > oldi) {
diff[--minLen] = DELETION;
--currentEnd;
}
diff[--minLen] = SKIP;
--futureEnd;
--currentEnd;
ptr = ptr.prev;
}
while (futureEnd >= futureStart) {
diff[--minLen] = INSERTION;
--futureEnd;
}
while (currentEnd >= currentStart) {
diff[--minLen] = DELETION;
--currentEnd;
}
return diff;
}; // this is pretty much the same petit-dom code without the delete map part
// https://github.com/yelouafi/petit-dom/blob/bd6f5c919b5ae5297be01612c524c40be45f14a7/src/vdom.js#L556-L561
var OND = function OND(futureNodes, futureStart, rows, currentNodes, currentStart, cols, compare) {
var length = rows + cols;
var v = [];
var d, k, r, c, pv, cv, pd;
outer: for (d = 0; d <= length; d++) {
/* istanbul ignore if */
if (d > SKIP_OND) return null;
pd = d - 1;
/* istanbul ignore next */
pv = d ? v[d - 1] : [0, 0];
cv = v[d] = [];
for (k = -d; k <= d; k += 2) {
if (k === -d || k !== d && pv[pd + k - 1] < pv[pd + k + 1]) {
c = pv[pd + k + 1];
} else {
c = pv[pd + k - 1] + 1;
}
r = c - k;
while (c < cols && r < rows && compare(currentNodes[currentStart + c], futureNodes[futureStart + r])) {
c++;
r++;
}
if (c === cols && r === rows) {
break outer;
}
cv[d + k] = c;
}
}
var diff = Array(d / 2 + length / 2);
var diffIdx = diff.length - 1;
for (d = v.length - 1; d >= 0; d--) {
while (c > 0 && r > 0 && compare(currentNodes[currentStart + c - 1], futureNodes[futureStart + r - 1])) {
// diagonal edge = equality
diff[diffIdx--] = SKIP;
c--;
r--;
}
if (!d) break;
pd = d - 1;
/* istanbul ignore next */
pv = d ? v[d - 1] : [0, 0];
k = c - r;
if (k === -d || k !== d && pv[pd + k - 1] < pv[pd + k + 1]) {
// vertical edge = insertion
r--;
diff[diffIdx--] = INSERTION;
} else {
// horizontal edge = deletion
c--;
diff[diffIdx--] = DELETION;
}
}
return diff;
};
var applyDiff = function applyDiff(diff, get, parentNode, futureNodes, futureStart, currentNodes, currentStart, currentLength, before) {
var live = [];
var length = diff.length;
var currentIndex = currentStart;
var i = 0;
while (i < length) {
switch (diff[i++]) {
case SKIP:
futureStart++;
currentIndex++;
break;
case INSERTION:
// TODO: bulk appends for sequential nodes
live.push(futureNodes[futureStart]);
append(get, parentNode, futureNodes, futureStart++, futureStart, currentIndex < currentLength ? get(currentNodes[currentIndex], 0) : before);
break;
case DELETION:
currentIndex++;
break;
}
}
i = 0;
while (i < length) {
switch (diff[i++]) {
case SKIP:
currentStart++;
break;
case DELETION:
// TODO: bulk removes for sequential nodes
if (-1 < live.indexOf(currentNodes[currentStart])) currentStart++;else remove(get, currentNodes, currentStart++, currentStart);
break;
}
}
};
var findK = function findK(ktr, length, j) {
var lo = 1;
var hi = length;
while (lo < hi) {
var mid = (lo + hi) / 2 >>> 0;
if (j < ktr[mid]) hi = mid;else lo = mid + 1;
}
return lo;
};
var smartDiff = function smartDiff(get, parentNode, futureNodes, futureStart, futureEnd, futureChanges, currentNodes, currentStart, currentEnd, currentChanges, currentLength, compare, before) {
applyDiff(OND(futureNodes, futureStart, futureChanges, currentNodes, currentStart, currentChanges, compare) || HS(futureNodes, futureStart, futureEnd, futureChanges, currentNodes, currentStart, currentEnd, currentChanges), get, parentNode, futureNodes, futureStart, currentNodes, currentStart, currentLength, before);
};
var drop = function drop(node) {
return (node.remove || dropChild).call(node);
};
function dropChild() {
var parentNode = this.parentNode;
/* istanbul ignore else */
if (parentNode) parentNode.removeChild(this);
}
/*! (c) 2018 Andrea Giammarchi (ISC) */
var domdiff = function domdiff(parentNode, // where changes happen
currentNodes, // Array of current items/nodes
futureNodes, // Array of future items/nodes
options // optional object with one of the following properties
// before: domNode
// compare(generic, generic) => true if same generic
// node(generic) => Node
) {
if (!options) options = {};
var compare = options.compare || eqeq;
var get = options.node || identity;
var before = options.before == null ? null : get(options.before, 0);
var currentLength = currentNodes.length;
var currentEnd = currentLength;
var currentStart = 0;
var futureEnd = futureNodes.length;
var futureStart = 0; // common prefix
while (currentStart < currentEnd && futureStart < futureEnd && compare(currentNodes[currentStart], futureNodes[futureStart])) {
currentStart++;
futureStart++;
} // common suffix
while (currentStart < currentEnd && futureStart < futureEnd && compare(currentNodes[currentEnd - 1], futureNodes[futureEnd - 1])) {
currentEnd--;
futureEnd--;
}
var currentSame = currentStart === currentEnd;
var futureSame = futureStart === futureEnd; // same list
if (currentSame && futureSame) return futureNodes; // only stuff to add
if (currentSame && futureStart < futureEnd) {
append(get, parentNode, futureNodes, futureStart, futureEnd, next(get, currentNodes, currentStart, currentLength, before));
return futureNodes;
} // only stuff to remove
if (futureSame && currentStart < currentEnd) {
remove(get, currentNodes, currentStart, currentEnd);
return futureNodes;
}
var currentChanges = currentEnd - currentStart;
var futureChanges = futureEnd - futureStart;
var i = -1; // 2 simple indels: the shortest sequence is a subsequence of the longest
if (currentChanges < futureChanges) {
i = indexOf(futureNodes, futureStart, futureEnd, currentNodes, currentStart, currentEnd, compare); // inner diff
if (-1 < i) {
append(get, parentNode, futureNodes, futureStart, i, get(currentNodes[currentStart], 0));
append(get, parentNode, futureNodes, i + currentChanges, futureEnd, next(get, currentNodes, currentEnd, currentLength, before));
return futureNodes;
}
}
/* istanbul ignore else */
else if (futureChanges < currentChanges) {
i = indexOf(currentNodes, currentStart, currentEnd, futureNodes, futureStart, futureEnd, compare); // outer diff
if (-1 < i) {
remove(get, currentNodes, currentStart, i);
remove(get, currentNodes, i + futureChanges, currentEnd);
return futureNodes;
}
} // common case with one replacement for many nodes
// or many nodes replaced for a single one
/* istanbul ignore else */
if (currentChanges < 2 || futureChanges < 2) {
append(get, parentNode, futureNodes, futureStart, futureEnd, get(currentNodes[currentStart], 0));
remove(get, currentNodes, currentStart, currentEnd);
return futureNodes;
} // the half match diff part has been skipped in petit-dom
// https://github.com/yelouafi/petit-dom/blob/bd6f5c919b5ae5297be01612c524c40be45f14a7/src/vdom.js#L391-L397
// accordingly, I think it's safe to skip in here too
// if one day it'll come out like the speediest thing ever to do
// then I might add it in here too
// Extra: before going too fancy, what about reversed lists ?
// This should bail out pretty quickly if that's not the case.
if (currentChanges === futureChanges && isReversed(futureNodes, futureEnd, currentNodes, currentStart, currentEnd, compare)) {
append(get, parentNode, futureNodes, futureStart, futureEnd, next(get, currentNodes, currentEnd, currentLength, before));
return futureNodes;
} // last resort through a smart diff
smartDiff(get, parentNode, futureNodes, futureStart, futureEnd, futureChanges, currentNodes, currentStart, currentEnd, currentChanges, currentLength, compare, before);
return futureNodes;
};
/*! (c) Andrea Giammarchi - ISC */
var self$1 = {};
self$1.CustomEvent = typeof CustomEvent === 'function' ? CustomEvent : function (__p__) {
CustomEvent[__p__] = new CustomEvent('').constructor[__p__];
return CustomEvent;
function CustomEvent(type, init) {
if (!init) init = {};
var e = document.createEvent('CustomEvent');
e.initCustomEvent(type, !!init.bubbles, !!init.cancelable, init.detail);
return e;
}
}('prototype');
var CustomEvent$1 = self$1.CustomEvent;
/*! (c) Andrea Giammarchi - ISC */
var self = {};
try {
self.Map = Map;
} catch (Map) {
self.Map = function Map() {
var i = 0;
var k = [];
var v = [];
return {
"delete": function _delete(key) {
var had = contains(key);
if (had) {
k.splice(i, 1);
v.splice(i, 1);
}
return had;
},
forEach: function forEach(callback, context) {
k.forEach(function (key, i) {
callback.call(context, v[i], key, this);
}, this);
},
get: function get(key) {
return contains(key) ? v[i] : void 0;
},
has: function has(key) {
return contains(key);
},
set: function set(key, value) {
v[contains(key) ? i : k.push(key) - 1] = value;
return this;
}
};
function contains(v) {
i = k.indexOf(v);
return -1 < i;
}
};
}
var Map$1 = self.Map;
// able to create Custom Elements like components
// including the ability to listen to connect/disconnect
// events via onconnect/ondisconnect attributes
// Components can be created imperatively or declaratively.
// The main difference is that declared components
// will not automatically render on setState(...)
// to simplify state handling on render.
function Component() {
return this; // this is needed in Edge !!!
} // Component is lazily setup because it needs
// wire mechanism as lazy content
function setup(content) {
// there are various weakly referenced variables in here
// and mostly are to use Component.for(...) static method.
var children = new WeakMap$1();
var create = Object.create;
var createEntry = function createEntry(wm, id, component) {
wm.set(id, component);
return component;
};
var get = function get(Class, info, context, id) {
var relation = info.get(Class) || relate(Class, info);
switch (_typeof(id)) {
case 'object':
case 'function':
var wm = relation.w || (relation.w = new WeakMap$1());
return wm.get(id) || createEntry(wm, id, new Class(context));
default:
var sm = relation.p || (relation.p = create(null));
return sm[id] || (sm[id] = new Class(context));
}
};
var relate = function relate(Class, info) {
var relation = {
w: null,
p: null
};
info.set(Class, relation);
return relation;
};
var set = function set(context) {
var info = new Map$1();
children.set(context, info);
return info;
}; // The Component Class
Object.defineProperties(Component, {
// Component.for(context[, id]) is a convenient way
// to automatically relate data/context to children components
// If not created yet, the new Component(context) is weakly stored
// and after that same instance would always be returned.
"for": {
configurable: true,
value: function value(context, id) {
return get(this, children.get(context) || set(context), context, id == null ? 'default' : id);
}
}
});
Object.defineProperties(Component.prototype, {
// all events are handled with the component as context
handleEvent: {
value: function value(e) {
var ct = e.currentTarget;
this['getAttribute' in ct && ct.getAttribute('data-call') || 'on' + e.type](e);
}
},
// components will lazily define html or svg properties
// as soon as these are invoked within the .render() method
// Such render() method is not provided by the base class
// but it must be available through the Component extend.
// Declared components could implement a
// render(props) method too and use props as needed.
html: lazyGetter('html', content),
svg: lazyGetter('svg', content),
// the state is a very basic/simple mechanism inspired by Preact
state: lazyGetter('state', function () {
return this.defaultState;
}),
// it is possible to define a default state that'd be always an object otherwise
defaultState: {
get: function get() {
return {};
}
},
// dispatch a bubbling, cancelable, custom event
// through the first known/available node
dispatch: {
value: function value(type, detail) {
var _wire$ = this._wire$;
if (_wire$) {
var event = new CustomEvent$1(type, {
bubbles: true,
cancelable: true,
detail: detail
});
event.component = this;
return (_wire$.dispatchEvent ? _wire$ : _wire$.firstChild).dispatchEvent(event);
}
return false;
}
},
// setting some property state through a new object
// or a callback, triggers also automatically a render
// unless explicitly specified to not do so (render === false)
setState: {
value: function value(state, render) {
var target = this.state;
var source = typeof state === 'function' ? state.call(this, target) : state;
for (var key in source) {
target[key] = source[key];
}
if (render !== false) this.render();
return this;
}
}
});
} // instead of a secret key I could've used a WeakMap
// However, attaching a property directly will result
// into better performance with thousands of components
// hanging around, and less memory pressure caused by the WeakMap
var lazyGetter = function lazyGetter(type, fn) {
var secret = '_' + type + '$';
return {
get: function get() {
return this[secret] || setValue(this, secret, fn.call(this, type));
},
set: function set(value) {
setValue(this, secret, value);
}
};
}; // shortcut to set value on get or set(value)
var setValue = function setValue(self, secret, value) {
return Object.defineProperty(self, secret, {
configurable: true,
value: typeof value === 'function' ? function () {
return self._wire$ = value.apply(this, arguments);
} : value
})[secret];
};
Object.defineProperties(Component.prototype, {
// used to distinguish better than instanceof
ELEMENT_NODE: {
value: 1
},
nodeType: {
value: -1
}
});
var attributes = {};
var intents = {};
var keys = [];
var hasOwnProperty = intents.hasOwnProperty;
var length = 0;
var Intent = {
// used to invoke right away hyper:attributes
attributes: attributes,
// hyperHTML.define('intent', (object, update) => {...})
// can be used to define a third parts update mechanism
// when every other known mechanism failed.
// hyper.define('user', info => info.name);
// hyper(node)` ${{user}}
${{user}}
`; define: (intent, callback) => { if (intent.indexOf('-') < 0) { if (!(intent in intents)) { length = keys.push(intent); } intents[intent] = callback; } else { attributes[intent] = callback; } }, // this method is used internally as last resort // to retrieve a value out of an object invoke: (object, callback) => { for (let i = 0; i < length; i++) { let key = keys[i]; if (hasOwnProperty.call(object, key)) { return intents[key](object[key], callback); } } } }; var isArray = Array.isArray || /* istanbul ignore next */ (function (toString) { /* istanbul ignore next */ var $ = toString.call([]); /* istanbul ignore next */ return function isArray(object) { return toString.call(object) === $; }; }({}.toString)); /*! (c) Andrea Giammarchi - ISC */ var createContent = (function (document) { var FRAGMENT = 'fragment'; var TEMPLATE = 'template'; var HAS_CONTENT = 'content' in create(TEMPLATE); var createHTML = HAS_CONTENT ? function (html) { var template = create(TEMPLATE); template.innerHTML = html; return template.content; } : function (html) { var content = create(FRAGMENT); var template = create(TEMPLATE); var childNodes = null; if (/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(html)) { var selector = RegExp.$1; template.innerHTML = '