@marcoms/make-element
Advanced tools
Comparing version 4.1.9 to 5.0.0
@@ -85,2 +85,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); | ||
/* harmony export (immutable) */ __webpack_exports__["defer"] = defer; | ||
// utility functions | ||
@@ -100,2 +101,17 @@ function noop() { } | ||
} | ||
// returns true if the work was deferred | ||
function defer(work) { | ||
return new Promise((resolve, reject) => { | ||
if (document.readyState === 'loading') { | ||
document.addEventListener('DOMContentLoaded', () => { | ||
work(); | ||
resolve(true); | ||
}); | ||
} | ||
else { | ||
work(); | ||
resolve(false); | ||
} | ||
}); | ||
} | ||
function makeElement(def = {}) { | ||
@@ -210,28 +226,30 @@ const props = def.props || {}; | ||
propVal = internalProp.coerce.call(this, propVal); | ||
if (internalProp.settingInitialValue) { | ||
internalProp.settingInitialValue = false; | ||
} | ||
internalProp.val = propVal; | ||
internalProp.set.call(this, propVal); | ||
/* | ||
We only propagate from the property to the attribute if: | ||
- A linked attribute was defined | ||
- The property setter is not being triggered by attributeChangedCallback | ||
*/ | ||
const beingInitialized = (this.hasAttribute(attrName) | ||
&& !internalProp.hasSet); | ||
if (hasLinkedAttr && !beingInitialized) { | ||
const attrVal = internalProp.toAttr.call(this, propVal); | ||
// prevent the attribute from reflowing back to the | ||
// property in attributeChangedCallback | ||
internalAttr.needsPropagation = false; | ||
if (attrVal !== undefined) { | ||
// invoke attributeChangedCallback | ||
this.setAttribute(attrName, attrVal); | ||
defer(() => { | ||
if (internalProp.settingInitialValue) { | ||
internalProp.settingInitialValue = false; | ||
} | ||
else { | ||
this.removeAttribute(attrName); | ||
internalProp.val = propVal; | ||
internalProp.set.call(this, propVal); | ||
/* | ||
We only propagate from the property to the attribute if: | ||
- A linked attribute was defined | ||
- The property setter is not being triggered by attributeChangedCallback | ||
*/ | ||
const beingInitialized = (this.hasAttribute(attrName) | ||
&& !internalProp.hasSet); | ||
if (hasLinkedAttr && !beingInitialized) { | ||
const attrVal = internalProp.toAttr.call(this, propVal); | ||
// prevent the attribute from reflowing back to the | ||
// property in attributeChangedCallback | ||
internalAttr.needsPropagation = false; | ||
if (attrVal !== undefined) { | ||
// invoke attributeChangedCallback | ||
this.setAttribute(attrName, attrVal); | ||
} | ||
else { | ||
this.removeAttribute(attrName); | ||
} | ||
} | ||
} | ||
internalProp.hasSet = true; | ||
internalProp.hasSet = true; | ||
}); | ||
}, | ||
@@ -298,15 +316,17 @@ get() { | ||
} | ||
// only run once | ||
for (const propName of Object.keys(this._props)) { | ||
const internalProp = this._props[propName]; | ||
// if there is a defined initial value but the setter has not run | ||
if (internalProp.init !== undefined | ||
&& internalProp.init !== null | ||
&& !internalProp.hasSet) { | ||
internalProp.settingInitialValue = true; | ||
// kick off property setter | ||
this[propName] = internalProp.init; | ||
defer(() => { | ||
// only run once | ||
for (const propName of Object.keys(this._props)) { | ||
const internalProp = this._props[propName]; | ||
// if there is a defined initial value but the setter has not run | ||
if (internalProp.init !== undefined | ||
&& internalProp.init !== null | ||
&& !internalProp.hasSet) { | ||
internalProp.settingInitialValue = true; | ||
// kick off property setter | ||
this[propName] = internalProp.init; | ||
} | ||
} | ||
} | ||
this._readyFn(); | ||
this._readyFn(); | ||
}); | ||
this._hasConnected = true; | ||
@@ -321,8 +341,10 @@ } | ||
if (internalAttr.needsPropagation) { | ||
// propagation should only occur once | ||
internalAttr.needsPropagation = false; | ||
const propName = internalAttr.propName; | ||
const internalProp = this._props[propName]; | ||
const propVal = internalProp.fromAttr.call(this, val); | ||
this[propName] = propVal; | ||
defer(() => { | ||
// propagation should only occur once | ||
internalAttr.needsPropagation = false; | ||
const propName = internalAttr.propName; | ||
const internalProp = this._props[propName]; | ||
const propVal = internalProp.fromAttr.call(this, val); | ||
this[propName] = propVal; | ||
}); | ||
} | ||
@@ -329,0 +351,0 @@ } |
export interface ArbitraryFn { | ||
(...args: any[]): any; | ||
} | ||
export interface BoundArbitraryFn { | ||
(this: CustomElement, ...args: any[]): any; | ||
@@ -19,3 +22,3 @@ } | ||
} | ||
export declare type ReadyFn = ArbitraryFn; | ||
export declare type ReadyFn = BoundArbitraryFn; | ||
export interface ElementDef { | ||
@@ -44,3 +47,3 @@ props?: PropDefs; | ||
export interface MethodsDef { | ||
[index: string]: ArbitraryFn; | ||
[index: string]: BoundArbitraryFn; | ||
} | ||
@@ -59,3 +62,4 @@ export interface IdMap { | ||
} | ||
export declare function defer(work: ArbitraryFn): Promise<boolean>; | ||
declare function makeElement(def?: ElementDef): CustomElementClass; | ||
export default makeElement; |
{ | ||
"name": "@marcoms/make-element", | ||
"version": "4.1.9", | ||
"version": "5.0.0", | ||
"description": "Create custom elements without boilerplate", | ||
@@ -25,2 +25,3 @@ "main": "build/make-element.js", | ||
"@types/mocha": "^2.2.41", | ||
"@types/node": "^8.0.17", | ||
"chai": "^4.1.0", | ||
@@ -34,2 +35,3 @@ "eslint": "^3.15.0", | ||
"mocha": "^3.4.2", | ||
"mocha.parallel": "^0.15.2", | ||
"ts-loader": "^2.2.2", | ||
@@ -36,0 +38,0 @@ "tslint": "^5.5.0", |
129
src/index.ts
@@ -1,2 +0,6 @@ | ||
export interface ArbitraryFn { (this: CustomElement, ...args: any[]): any; } | ||
export interface ArbitraryFn { (...args: any[]): any; } | ||
export interface BoundArbitraryFn { | ||
(this: CustomElement, ...args: any[]): any; | ||
} | ||
export interface GetFn { (this: CustomElement, val: any): void; } | ||
@@ -8,3 +12,3 @@ export interface SetFn { (this: CustomElement, val: any): any; } | ||
export type ReadyFn = ArbitraryFn; | ||
export type ReadyFn = BoundArbitraryFn; | ||
@@ -37,3 +41,3 @@ export interface ElementDef { | ||
export interface MethodsDef { | ||
[index: string]: ArbitraryFn; | ||
[index: string]: BoundArbitraryFn; | ||
} | ||
@@ -101,3 +105,5 @@ | ||
function convertToBoolAttr(val: any): string | undefined { | ||
type BoolAttr = string | undefined; | ||
function convertToBoolAttr(val: any): BoolAttr { | ||
if (Boolean(val)) { | ||
@@ -110,2 +116,18 @@ return ''; | ||
// returns true if the work was deferred | ||
export function defer(work: ArbitraryFn): Promise<boolean> { | ||
return new Promise((resolve, reject) => { | ||
if (document.readyState === 'loading') { | ||
document.addEventListener('DOMContentLoaded', () => { | ||
work(); | ||
resolve(true); | ||
}); | ||
} else { | ||
work(); | ||
resolve(false); | ||
} | ||
}); | ||
} | ||
function makeElement(def: ElementDef = {}): CustomElementClass { | ||
@@ -259,36 +281,38 @@ const props: PropDefs = def.props || {}; | ||
if (internalProp.settingInitialValue) { | ||
internalProp.settingInitialValue = false; | ||
} | ||
defer(() => { | ||
if (internalProp.settingInitialValue) { | ||
internalProp.settingInitialValue = false; | ||
} | ||
internalProp.val = propVal; | ||
internalProp.set.call(this, propVal); | ||
internalProp.val = propVal; | ||
internalProp.set.call(this, propVal); | ||
/* | ||
We only propagate from the property to the attribute if: | ||
- A linked attribute was defined | ||
- The property setter is not being triggered by attributeChangedCallback | ||
*/ | ||
/* | ||
We only propagate from the property to the attribute if: | ||
- A linked attribute was defined | ||
- The property setter is not being triggered by attributeChangedCallback | ||
*/ | ||
const beingInitialized = ( | ||
this.hasAttribute(attrName) | ||
&& !internalProp.hasSet | ||
); | ||
const beingInitialized = ( | ||
this.hasAttribute(attrName) | ||
&& !internalProp.hasSet | ||
); | ||
if (hasLinkedAttr && !beingInitialized) { | ||
const attrVal = internalProp.toAttr.call(this, propVal); | ||
if (hasLinkedAttr && !beingInitialized) { | ||
const attrVal = internalProp.toAttr.call(this, propVal); | ||
// prevent the attribute from reflowing back to the | ||
// property in attributeChangedCallback | ||
internalAttr.needsPropagation = false; | ||
// prevent the attribute from reflowing back to the | ||
// property in attributeChangedCallback | ||
internalAttr.needsPropagation = false; | ||
if (attrVal !== undefined) { | ||
// invoke attributeChangedCallback | ||
this.setAttribute(attrName, attrVal); | ||
} else { | ||
this.removeAttribute(attrName); | ||
if (attrVal !== undefined) { | ||
// invoke attributeChangedCallback | ||
this.setAttribute(attrName, attrVal); | ||
} else { | ||
this.removeAttribute(attrName); | ||
} | ||
} | ||
} | ||
internalProp.hasSet = true; | ||
internalProp.hasSet = true; | ||
}); | ||
}, | ||
@@ -362,22 +386,25 @@ | ||
// only run once | ||
defer(() => { | ||
// only run once | ||
for (const propName of Object.keys(this._props)) { | ||
const internalProp = this._props[propName] as InternalProp; | ||
for (const propName of Object.keys(this._props)) { | ||
const internalProp = this._props[propName] as InternalProp; | ||
// if there is a defined initial value but the setter has not run | ||
// if there is a defined initial value but the setter has not run | ||
if ( | ||
internalProp.init !== undefined | ||
&& internalProp.init !== null | ||
&& !internalProp.hasSet | ||
) { | ||
internalProp.settingInitialValue = true; | ||
if ( | ||
internalProp.init !== undefined | ||
&& internalProp.init !== null | ||
&& !internalProp.hasSet | ||
) { | ||
internalProp.settingInitialValue = true; | ||
// kick off property setter | ||
this[propName] = internalProp.init; | ||
// kick off property setter | ||
this[propName] = internalProp.init; | ||
} | ||
} | ||
} | ||
this._readyFn(); | ||
this._readyFn(); | ||
}); | ||
this._hasConnected = true; | ||
@@ -394,10 +421,12 @@ } | ||
if (internalAttr.needsPropagation) { | ||
// propagation should only occur once | ||
internalAttr.needsPropagation = false; | ||
defer(() => { | ||
// propagation should only occur once | ||
internalAttr.needsPropagation = false; | ||
const propName = internalAttr.propName; | ||
const internalProp = this._props[propName] as InternalProp; | ||
const propName = internalAttr.propName; | ||
const internalProp = this._props[propName] as InternalProp; | ||
const propVal = internalProp.fromAttr.call(this, val); | ||
this[propName] = propVal; | ||
const propVal = internalProp.fromAttr.call(this, val); | ||
this[propName] = propVal; | ||
}); | ||
} | ||
@@ -404,0 +433,0 @@ } |
@@ -0,5 +1,6 @@ | ||
const parallel = require('mocha.parallel'); | ||
import { assert } from 'chai'; | ||
import me from 'src/index'; | ||
import { customElName } from './tools'; | ||
import {default as me, defer} from 'src/index'; | ||
import {customElName} from './tools'; | ||
@@ -24,3 +25,6 @@ describe('props', () => { | ||
el.prop = 24; | ||
assert.strictEqual(el.prop, 24); | ||
return defer(() => { | ||
assert.strictEqual(el.prop, 24); | ||
}); | ||
}); | ||
@@ -76,3 +80,6 @@ | ||
el.prop = 24; | ||
assert.strictEqual(el.prop, 48); | ||
return defer(() => { | ||
assert.strictEqual(el.prop, 48); | ||
}); | ||
}); | ||
@@ -115,4 +122,7 @@ | ||
el.prop = 24; | ||
assert.strictEqual(el.prop, 24); | ||
assert.strictEqual(el.getAttribute('prop'), '24'); | ||
return defer(() => { | ||
assert.strictEqual(el.prop, 24); | ||
assert.strictEqual(el.getAttribute('prop'), '24'); | ||
}); | ||
}); | ||
@@ -135,3 +145,6 @@ | ||
customElements.define(elName, El); | ||
assert.strictEqual((el as any).prop, '24'); | ||
return defer(() => { | ||
assert.strictEqual((el as any).prop, '24'); | ||
}); | ||
}); | ||
@@ -153,3 +166,6 @@ | ||
el.prop = 24; | ||
assert.strictEqual(el.getAttribute('prop'), ''); | ||
return defer(() => { | ||
assert.strictEqual(el.getAttribute('prop'), ''); | ||
}); | ||
}); | ||
@@ -171,3 +187,6 @@ | ||
el.prop = 0; | ||
assert.strictEqual(el.getAttribute('prop'), null); | ||
return defer(() => { | ||
assert.strictEqual(el.getAttribute('prop'), null); | ||
}); | ||
}); | ||
@@ -191,3 +210,6 @@ | ||
el.prop = 24; | ||
assert.strictEqual(el.getAttribute('prop'), '24-toAttr'); | ||
return defer(() => { | ||
assert.strictEqual(el.getAttribute('prop'), '24-toAttr'); | ||
}); | ||
}); | ||
@@ -232,3 +254,5 @@ | ||
assert.strictEqual((el as any).prop, 24); | ||
return defer(() => { | ||
assert.strictEqual((el as any).prop, 24); | ||
}); | ||
}); | ||
@@ -269,3 +293,6 @@ | ||
el.prop = 24; | ||
assert.strictEqual(el.prop, '24-coerce'); | ||
return defer(() => { | ||
assert.strictEqual(el.prop, '24-coerce'); | ||
}); | ||
}); | ||
@@ -285,8 +312,10 @@ | ||
const elA = new El(); | ||
const elB = new El(); | ||
document.body.appendChild(elA); | ||
assert.strictEqual(elA.prop, 24); | ||
document.body.appendChild(elB); | ||
const elB = new El(); | ||
document.body.appendChild(elB); | ||
assert.strictEqual(elB.prop, 24); | ||
return defer(() => { | ||
assert.strictEqual(elA.prop, 24); | ||
assert.strictEqual(elB.prop, 24); | ||
}); | ||
}); | ||
@@ -307,8 +336,10 @@ | ||
const elA = new El(); | ||
const elB = new El(); | ||
document.body.appendChild(elA); | ||
assert.strictEqual(elA.getAttribute('prop'), '24'); | ||
document.body.appendChild(elB); | ||
const elB = new El(); | ||
document.body.appendChild(elB); | ||
assert.strictEqual(elB.getAttribute('prop'), '24'); | ||
return defer(() => { | ||
assert.strictEqual(elA.getAttribute('prop'), '24'); | ||
assert.strictEqual(elB.getAttribute('prop'), '24'); | ||
}); | ||
}); | ||
@@ -334,3 +365,5 @@ | ||
assert.strictEqual((el as any).prop, '48'); | ||
return defer(() => { | ||
assert.strictEqual((el as any).prop, '48'); | ||
}); | ||
}); | ||
@@ -353,4 +386,7 @@ | ||
document.body.appendChild(el); | ||
assert.strictEqual(el.prop, '24-coerce'); | ||
return defer(() => { | ||
assert.strictEqual(el.prop, '24-coerce'); | ||
}); | ||
}); | ||
}); |
@@ -54,2 +54,14 @@ import { assert } from 'chai'; | ||
}); | ||
it('should call ready after DOMContentLoaded', () => { | ||
const El = me({ | ||
ready() { | ||
assert.notStrictEqual(document.readyState, 'complete'); | ||
}, | ||
}); | ||
customElements.define(customElName(), El); | ||
const el = new El(); | ||
document.body.appendChild(el); | ||
}); | ||
}); |
@@ -14,3 +14,2 @@ { | ||
"check-decl", | ||
"check-module", | ||
"check-operator", | ||
@@ -17,0 +16,0 @@ "check-operator", |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
208626
1540
15