From 5872073c817d903dcad76d6d9886bf0d67e1853f Mon Sep 17 00:00:00 2001 From: Brian Liu Date: Tue, 19 Jan 2021 15:25:13 +1100 Subject: [PATCH] Template draft version --- content-visibility-template.d.ts | 39 ++++++++ content-visibility-template.d.ts.map | 1 + content-visibility-template.js | 75 ++++++++++++++++ content-visibility-template.js.map | 1 + custom-elements.json | 17 +++- dev/index.html | 75 ++++++++-------- package-lock.json | 22 +++-- package.json | 4 +- src/content-visibility-template.ts | 94 ++++++++++++++++++++ src/content-visibility.ts | 10 ++- src/test/content-visibility-template_test.ts | 30 +++++++ src/test/content-visibility_test.ts | 10 +-- 12 files changed, 323 insertions(+), 55 deletions(-) create mode 100644 content-visibility-template.d.ts create mode 100644 content-visibility-template.d.ts.map create mode 100644 content-visibility-template.js create mode 100644 content-visibility-template.js.map create mode 100644 src/content-visibility-template.ts create mode 100644 src/test/content-visibility-template_test.ts diff --git a/content-visibility-template.d.ts b/content-visibility-template.d.ts new file mode 100644 index 0000000..b139705 --- /dev/null +++ b/content-visibility-template.d.ts @@ -0,0 +1,39 @@ +import 'intersection-observer'; +import '@ungap/custom-elements'; +/** + * + * @author Brian YP Liu + * @copyright 2021 Brian YP Liu + * + * ContentVisibilityTemplate, a simple webcomponent extends the built-in + * HTMLTemplateElement to convey document fragment and render until it appears + * on the browser viewport (Intersection Observer) to provide truely lazy load + * + * Currently, the webcomponent only support lazy loading on + * Chrome, Edge, Opera but not Safari and Firefox, thank you to the CSS + * content-visibility property. + * + */ +export declare class ContentVisibilityTemplate extends HTMLTemplateElement { + private observer?; + private inView; + private placeholder; + /** + * @property {string} threshold - Intersection Observer threshold (0~1), see + * (https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) + * @default [0] + */ + get threshold(): number; + /** + * @property {string} containIntrinsicSize -
placholder height to take + * up space before rendering to avoid content jumping, same concept as CSS + * contain-intrinsic-size, see + * https://developer.mozilla.org/en-US/docs/Web/CSS/contain-intrinsic-size + * @default [600px] + */ + get containIntrinsicSize(): string; + constructor(); + connectedCallback(): void; + disconnectedCallback(): void; +} +//# sourceMappingURL=content-visibility-template.d.ts.map \ No newline at end of file diff --git a/content-visibility-template.d.ts.map b/content-visibility-template.d.ts.map new file mode 100644 index 0000000..4cfd7e9 --- /dev/null +++ b/content-visibility-template.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"content-visibility-template.d.ts","sourceRoot":"","sources":["src/content-visibility-template.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAEhC;;;;;;;;;;;;;GAaG;AACH,qBAAa,yBAA0B,SAAQ,mBAAmB;IAChE,OAAO,CAAC,QAAQ,CAAC,CAAuB;IAExC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAiC;IAEpD;;;;OAIG;IACH,IAAI,SAAS,WAIZ;IAED;;;;;;OAMG;IACH,IAAI,oBAAoB,WAEvB;;IAWD,iBAAiB;IAyBjB,oBAAoB;CAMrB"} \ No newline at end of file diff --git a/content-visibility-template.js b/content-visibility-template.js new file mode 100644 index 0000000..f9ab2f6 --- /dev/null +++ b/content-visibility-template.js @@ -0,0 +1,75 @@ +import 'intersection-observer'; +import '@ungap/custom-elements'; +/** + * + * @author Brian YP Liu + * @copyright 2021 Brian YP Liu + * + * ContentVisibilityTemplate, a simple webcomponent extends the built-in + * HTMLTemplateElement to convey document fragment and render until it appears + * on the browser viewport (Intersection Observer) to provide truely lazy load + * + * Currently, the webcomponent only support lazy loading on + * Chrome, Edge, Opera but not Safari and Firefox, thank you to the CSS + * content-visibility property. + * + */ +export class ContentVisibilityTemplate extends HTMLTemplateElement { + constructor() { + super(); + this.inView = false; + this.placeholder = document.createElement('div'); + this.placeholder.setAttribute('style', `height: ${this.containIntrinsicSize};`); + } + /** + * @property {string} threshold - Intersection Observer threshold (0~1), see + * (https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) + * @default [0] + */ + get threshold() { + var _a; + const threshold = parseFloat((_a = this.getAttribute('threshold')) !== null && _a !== void 0 ? _a : '0'); + return isNaN(threshold) ? 0 : threshold; + } + /** + * @property {string} containIntrinsicSize -
placholder height to take + * up space before rendering to avoid content jumping, same concept as CSS + * contain-intrinsic-size, see + * https://developer.mozilla.org/en-US/docs/Web/CSS/contain-intrinsic-size + * @default [600px] + */ + get containIntrinsicSize() { + var _a; + return (_a = this.getAttribute('containIntrinsicSize')) !== null && _a !== void 0 ? _a : '600px'; + } + connectedCallback() { + this.insertAdjacentElement('beforebegin', this.placeholder); + this.observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting && entry.target === this.placeholder) { + if (!this.inView) { + this.inView = true; + this.placeholder.remove(); + if (this.innerHTML) { + this.insertAdjacentHTML('beforebegin', this.innerHTML); + } + else if (this.firstElementChild) { + this.before(this.firstElementChild); + } + } + } + }); + }, { threshold: this.threshold }); + this.observer.observe(this.placeholder); + } + disconnectedCallback() { + if (this.observer) { + this.observer.unobserve(this.placeholder); + this.observer.disconnect(); + } + } +} +customElements.define('content-visibility-template', ContentVisibilityTemplate, { + extends: 'template', +}); +//# sourceMappingURL=content-visibility-template.js.map \ No newline at end of file diff --git a/content-visibility-template.js.map b/content-visibility-template.js.map new file mode 100644 index 0000000..60d82e4 --- /dev/null +++ b/content-visibility-template.js.map @@ -0,0 +1 @@ +{"version":3,"file":"content-visibility-template.js","sourceRoot":"","sources":["src/content-visibility-template.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAEhC;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,yBAA0B,SAAQ,mBAAmB;IA4BhE;QACE,KAAK,EAAE,CAAC;QA1BF,WAAM,GAAG,KAAK,CAAC;QACf,gBAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QA2BlD,IAAI,CAAC,WAAW,CAAC,YAAY,CAC3B,OAAO,EACP,WAAW,IAAI,CAAC,oBAAoB,GAAG,CACxC,CAAC;IACJ,CAAC;IA7BD;;;;OAIG;IACH,IAAI,SAAS;;QACX,MAAM,SAAS,GAAG,UAAU,OAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,mCAAI,GAAG,CAAC,CAAC;QAEpE,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1C,CAAC;IAED;;;;;;OAMG;IACH,IAAI,oBAAoB;;QACtB,aAAO,IAAI,CAAC,YAAY,CAAC,sBAAsB,CAAC,mCAAI,OAAO,CAAC;IAC9D,CAAC;IAWD,iBAAiB;QACf,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAE5D,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAoB,CACtC,CAAC,OAAO,EAAE,EAAE;YACV,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;gBACxB,IAAI,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,WAAW,EAAE;oBAC7D,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;wBAChB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;wBACnB,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;wBAE1B,IAAI,IAAI,CAAC,SAAS,EAAE;4BAClB,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;yBACxD;6BAAM,IAAI,IAAI,CAAC,iBAAiB,EAAE;4BACjC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;yBACrC;qBACF;iBACF;YACH,CAAC,CAAC,CAAC;QACL,CAAC,EACD,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAC9B,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAED,oBAAoB;QAClB,IAAI,IAAI,CAAC,QAAQ,EAAE;YACjB,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1C,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;SAC5B;IACH,CAAC;CACF;AAED,cAAc,CAAC,MAAM,CACnB,6BAA6B,EAC7B,yBAAyB,EACzB;IACE,OAAO,EAAE,UAAU;CACpB,CACF,CAAC"} \ No newline at end of file diff --git a/custom-elements.json b/custom-elements.json index 2cfc9d2..81d05cb 100644 --- a/custom-elements.json +++ b/custom-elements.json @@ -1,10 +1,25 @@ { "version": "experimental", "tags": [ + { + "name": "content-visibility-template", + "path": "./src/content-visibility-template.ts", + "properties": [ + { + "name": "threshold", + "type": "number", + "default": "\"[0]\"" + }, + { + "name": "containIntrinsicSize", + "type": "string", + "default": "\"[600px]\"" + } + ] + }, { "name": "content-visibility", "path": "./src/content-visibility.ts", - "description": "content-visibility, a web component leverages CSS content-visibility and the\nIntersection Observer API to provide cross browsers content-visibility solution.", "attributes": [ { "name": "containIntrinsicSize", diff --git a/dev/index.html b/dev/index.html index 412961b..611d77c 100644 --- a/dev/index.html +++ b/dev/index.html @@ -5,6 +5,7 @@ <content-visibility> Demo +