diff --git a/dist/element-queries.js b/dist/element-queries.js index 8a2f70d..49991fb 100644 --- a/dist/element-queries.js +++ b/dist/element-queries.js @@ -3,10 +3,10 @@ module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); - else { - var a = factory(); - for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; - } + else if(typeof exports === 'object') + exports["ElementQueries"] = factory(); + else + root["ElementQueries"] = factory(); })(window, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache @@ -100,11 +100,11 @@ return /******/ (function(modules) { // webpackBootstrap /*!*******************************!*\ !*** ./src/ElementQueries.js ***! \*******************************/ -/*! exports provided: ElementQueries */ +/*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ElementQueries\", function() { return ElementQueries; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.js\");\n\n\nconst DEFAULT_OPTS = {\n htmlAttrBreakpoints: 'data-eq-breakpoints',\n htmlAttrActive: 'data-eq-active',\n}\n\nclass ElementQueries {\n constructor(opts) {\n this.opts = Object.freeze({ ...DEFAULT_OPTS, ...opts })\n\n this.observer = new ResizeObserver(this.onResize.bind(this))\n this.elements = new WeakMap()\n\n // wait for document load\n if (/complete|interactive|loaded/.test(document.readyState)) {\n this.onDocumentLoad()\n } else {\n document.addEventListener('DOMContentLoaded', this.onDocumentLoad.bind(this), { once: true })\n }\n }\n\n // Internal\n onDocumentLoad() {\n this.init()\n\n this.domObserver = new MutationObserver(this.onDomMutation.bind(this))\n this.domObserver.observe(document.body, { childList: true, subtree: true })\n }\n\n init() {\n const elements = document.querySelectorAll(`[${this.opts.htmlAttrBreakpoints}]`)\n\n for (const element of elements) {\n try {\n this.watch(element)\n } catch (error) {\n console.error(error, element)\n }\n }\n }\n\n onResize(entries) {\n const toUpdate = new Set()\n\n // eslint-disable-next-line no-var\n for (var i = entries.length - 1; i >= 0; i--) {\n const { target: element, borderBoxSize } = entries[i]\n\n if (this.elements.has(element)) {\n let width\n let height\n\n if (borderBoxSize && borderBoxSize[0]) {\n width = borderBoxSize[0].inlineSize\n height = borderBoxSize[0].blockSize\n } else {\n // fallback for Safari\n const rect = element.getBoundingClientRect()\n width = rect.width\n height = rect.height\n }\n\n const elementsEntry = this.elements.get(element)\n this.elements.set(element, { ...elementsEntry, ...{ width, height } })\n toUpdate.add(element)\n }\n }\n\n this.update([...toUpdate])\n }\n\n onDomMutation(mutations) {\n // eslint-disable-next-line no-var\n for (var i = mutations.length - 1; i >= 0; i--) {\n if (mutations[i].addedNodes.length) {\n // eslint-disable-next-line no-var\n for (var k = mutations[i].addedNodes.length - 1; k >= 0; k--) {\n const element = mutations[i].addedNodes[k]\n if (\n element instanceof HTMLElement\n && element.hasAttribute(this.opts.htmlAttrBreakpoints)\n ) {\n try {\n this.watch(element)\n } catch (e) {\n console.error(e, element)\n }\n }\n }\n }\n }\n }\n\n // Methods & Helpers\n /**\n * Watch an element manually\n * @param {HTMLElement} element The DOM element you would like to watch\n */\n watch(element) {\n if (!element || !(element instanceof HTMLElement)) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].INVALID_ELEMENT)\n if (!element.hasAttribute(this.opts.htmlAttrBreakpoints)) {\n throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].BREAKPOINTS_MISSING)\n }\n\n const breakpointString = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[\"removeWhitespace\"])(element.getAttribute(this.opts.htmlAttrBreakpoints))\n const breakpointMatches = [...breakpointString.matchAll(_utils__WEBPACK_IMPORTED_MODULE_0__[\"BREAKPOINT_REGEX\"])]\n\n if (!breakpointMatches.length) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].BREAKPOINTS_MISSING)\n\n const breakpoints = breakpointMatches.reduce((acc, match) => {\n if (!match[1] || !match[2]) return acc\n\n acc[match[1]] = +match[2]\n return acc\n }, {})\n\n this.elements.set(element, { breakpoints })\n this.observer.observe(element, { box: 'border-box' })\n }\n\n /**\n * Updates the given elements according to their internal state (eq.elements)\n * @param {Array} elements Array of DOM elements\n */\n update(elements) {\n if (\n !elements\n || !Array.isArray(elements)\n || !elements.length\n || !elements.every(el => el instanceof HTMLElement)\n ) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].INVALID_ELEMENTS)\n\n // eslint-disable-next-line no-var\n for (var i = elements.length - 1; i >= 0; i--) {\n const element = elements[i]\n\n const entry = this.elements.get(element)\n if (entry && entry.breakpoints) {\n const { width } = entry\n let active = null\n\n const bpsFlipped = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[\"flipObject\"])(entry.breakpoints)\n const bpWidths = Object.values(entry.breakpoints).sort() // sort ASC\n const bpLargest = bpWidths[bpWidths.length - 1]\n\n if (width >= bpLargest) {\n active = bpsFlipped[bpLargest]\n } else if (width > bpWidths[0]) {\n for (let k = 0; k < bpWidths.length; k++) {\n const bpWidth = bpWidths[k]\n\n if (width >= bpWidth) {\n active = bpsFlipped[bpWidth]\n }\n }\n }\n\n if (active) {\n element.setAttribute(this.opts.htmlAttrActive, active)\n continue\n }\n }\n\n element.removeAttribute(this.opts.htmlAttrActive)\n }\n }\n\n /**\n * Disconnects all observers and clears element references\n */\n destroy() {\n if (this.observer) this.observer.disconnect()\n if (this.domObserver) this.domObserver.disconnect()\n\n this.elements = new WeakMap()\n }\n}\n\n\n//# sourceURL=webpack:///./src/ElementQueries.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return ElementQueries; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.js\");\n\n\nconst DEFAULT_OPTS = {\n htmlAttrBreakpoints: 'data-eq-breakpoints',\n htmlAttrActive: 'data-eq-active',\n}\n\nclass ElementQueries {\n constructor(opts) {\n this.opts = Object.freeze({ ...DEFAULT_OPTS, ...opts })\n\n this.observer = new ResizeObserver(this.onResize.bind(this))\n this.elements = new WeakMap()\n\n // wait for document load\n if (/complete|interactive|loaded/.test(document.readyState)) {\n this.onDocumentLoad()\n } else {\n document.addEventListener('DOMContentLoaded', this.onDocumentLoad.bind(this), { once: true })\n }\n }\n\n // Internal\n onDocumentLoad() {\n this.init()\n\n this.domObserver = new MutationObserver(this.onDomMutation.bind(this))\n this.domObserver.observe(document.body, { childList: true, subtree: true })\n }\n\n init() {\n const elements = document.querySelectorAll(`[${this.opts.htmlAttrBreakpoints}]`)\n\n for (const element of elements) {\n try {\n this.watch(element)\n } catch (error) {\n console.error(error, element)\n }\n }\n }\n\n onResize(entries) {\n const toUpdate = new Set()\n\n // eslint-disable-next-line no-var\n for (var i = entries.length - 1; i >= 0; i--) {\n const { target: element, borderBoxSize } = entries[i]\n\n if (this.elements.has(element)) {\n let width\n let height\n\n if (borderBoxSize && borderBoxSize[0]) {\n width = borderBoxSize[0].inlineSize\n height = borderBoxSize[0].blockSize\n } else {\n // fallback for Safari\n const rect = element.getBoundingClientRect()\n width = rect.width\n height = rect.height\n }\n\n const elementsEntry = this.elements.get(element)\n this.elements.set(element, { ...elementsEntry, ...{ width, height } })\n toUpdate.add(element)\n }\n }\n\n this.update([...toUpdate])\n }\n\n onDomMutation(mutations) {\n // eslint-disable-next-line no-var\n for (var i = mutations.length - 1; i >= 0; i--) {\n if (mutations[i].addedNodes.length) {\n // eslint-disable-next-line no-var\n for (var k = mutations[i].addedNodes.length - 1; k >= 0; k--) {\n const element = mutations[i].addedNodes[k]\n if (\n element instanceof HTMLElement\n && element.hasAttribute(this.opts.htmlAttrBreakpoints)\n ) {\n try {\n this.watch(element)\n } catch (e) {\n console.error(e, element)\n }\n }\n }\n }\n }\n }\n\n // Methods & Helpers\n /**\n * Watch an element manually\n * @param {HTMLElement} element The DOM element you would like to watch\n */\n watch(element) {\n if (!element || !(element instanceof HTMLElement)) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].INVALID_ELEMENT)\n if (!element.hasAttribute(this.opts.htmlAttrBreakpoints)) {\n throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].BREAKPOINTS_MISSING)\n }\n\n const breakpointString = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[\"removeWhitespace\"])(element.getAttribute(this.opts.htmlAttrBreakpoints))\n const breakpointMatches = [...breakpointString.matchAll(_utils__WEBPACK_IMPORTED_MODULE_0__[\"BREAKPOINT_REGEX\"])]\n\n if (!breakpointMatches.length) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].BREAKPOINTS_MISSING)\n\n const breakpoints = breakpointMatches.reduce((acc, match) => {\n if (!match[1] || !match[2]) return acc\n\n acc[match[1]] = +match[2]\n return acc\n }, {})\n\n this.elements.set(element, { breakpoints })\n this.observer.observe(element, { box: 'border-box' })\n }\n\n /**\n * Updates the given elements according to their internal state (eq.elements)\n * @param {Array} elements Array of DOM elements\n */\n update(elements) {\n if (\n !elements\n || !Array.isArray(elements)\n || !elements.length\n || !elements.every(el => el instanceof HTMLElement)\n ) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].INVALID_ELEMENTS)\n\n // eslint-disable-next-line no-var\n for (var i = elements.length - 1; i >= 0; i--) {\n const element = elements[i]\n\n const entry = this.elements.get(element)\n if (entry && entry.breakpoints) {\n const { width } = entry\n let active = null\n\n const bpsFlipped = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[\"flipObject\"])(entry.breakpoints)\n const bpWidths = Object.values(entry.breakpoints).sort() // sort ASC\n const bpLargest = bpWidths[bpWidths.length - 1]\n\n if (width >= bpLargest) {\n active = bpsFlipped[bpLargest]\n } else if (width > bpWidths[0]) {\n for (let k = 0; k < bpWidths.length; k++) {\n const bpWidth = bpWidths[k]\n\n if (width >= bpWidth) {\n active = bpsFlipped[bpWidth]\n }\n }\n }\n\n if (active) {\n element.setAttribute(this.opts.htmlAttrActive, active)\n continue\n }\n }\n\n element.removeAttribute(this.opts.htmlAttrActive)\n }\n }\n\n /**\n * Disconnects all observers and clears element references\n */\n destroy() {\n if (this.observer) this.observer.disconnect()\n if (this.domObserver) this.domObserver.disconnect()\n\n this.elements = new WeakMap()\n }\n}\n\n\n//# sourceURL=webpack://ElementQueries/./src/ElementQueries.js?"); /***/ }), @@ -112,11 +112,11 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /*!**********************!*\ !*** ./src/index.js ***! \**********************/ -/*! exports provided: ElementQueries */ +/*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ElementQueries__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ElementQueries */ \"./src/ElementQueries.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"ElementQueries\", function() { return _ElementQueries__WEBPACK_IMPORTED_MODULE_0__[\"ElementQueries\"]; });\n\n\n\n/** TODOs\n * TODO move this out of here :)\n * TODO allow passing breakpoint object to .watch() which overrides htmlAttrBreakpoints\n * TODO Support HTMLElement *AND* SVGElement\n * TODO disable if ResizeObserver isnt supported\n * TODO config option: dom observing on/off\n * NOTE general browser-support checks (MutationObserver, etc)\n * NOTE batching resize updates?\n * NOTE throttle observer?\n * NOTE debounce updates on a per-element basis?\n * NOTE use requestAnimationFrame on resize callback?\n * NOTE what do if user changes htmlAttrBreakpoints dynamically\n */\n\n\n//# sourceURL=webpack:///./src/index.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ElementQueries__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ElementQueries */ \"./src/ElementQueries.js\");\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (_ElementQueries__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n\n/** TODOs\n * TODO move this out of here :)\n * TODO allow passing breakpoint object to .watch() which overrides htmlAttrBreakpoints\n * TODO Support HTMLElement *AND* SVGElement\n * TODO disable if ResizeObserver isnt supported\n * TODO config option: dom observing on/off\n * NOTE general browser-support checks (MutationObserver, etc)\n * NOTE batching resize updates?\n * NOTE throttle observer?\n * NOTE debounce updates on a per-element basis?\n * NOTE use requestAnimationFrame on resize callback?\n * NOTE what do if user changes htmlAttrBreakpoints dynamically\n */\n\n\n//# sourceURL=webpack://ElementQueries/./src/index.js?"); /***/ }), @@ -128,7 +128,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Ele /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BREAKPOINT_REGEX\", function() { return BREAKPOINT_REGEX; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Errors\", function() { return Errors; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"removeWhitespace\", function() { return removeWhitespace; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"flipObject\", function() { return flipObject; });\n// Constants\nconst BREAKPOINT_REGEX = /([_A-z]+[A-z0-9-_]+):(\\d+)/g\n\nconst Errors = {\n INVALID_ELEMENT: 'Please provide a HTMLElement',\n INVALID_ELEMENTS: 'Please provide an array of HTMLElements',\n BREAKPOINTS_MISSING: 'No breakpoints found on element',\n}\n\n// Functions\nconst removeWhitespace = str => str.replace(/ /g, '')\nconst flipObject = o => Object.entries(o)\n .reduce((r, [k, v]) => Object.assign(r, { [v]: k }), {})\n\n\n//# sourceURL=webpack:///./src/utils.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BREAKPOINT_REGEX\", function() { return BREAKPOINT_REGEX; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Errors\", function() { return Errors; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"removeWhitespace\", function() { return removeWhitespace; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"flipObject\", function() { return flipObject; });\n// Constants\nconst BREAKPOINT_REGEX = /([_A-z]+[A-z0-9-_]+):(\\d+)/g\n\nconst Errors = {\n INVALID_ELEMENT: 'Please provide a HTMLElement',\n INVALID_ELEMENTS: 'Please provide an array of HTMLElements',\n BREAKPOINTS_MISSING: 'No breakpoints found on element',\n}\n\n// Functions\nconst removeWhitespace = str => str.replace(/ /g, '')\nconst flipObject = o => Object.entries(o)\n .reduce((r, [k, v]) => Object.assign(r, { [v]: k }), {})\n\n\n//# sourceURL=webpack://ElementQueries/./src/utils.js?"); /***/ }), @@ -139,9 +139,9 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -eval("module.exports = __webpack_require__(/*! ./src/index.js */\"./src/index.js\");\n\n\n//# sourceURL=webpack:///multi_./src/index.js?"); +eval("module.exports = __webpack_require__(/*! ./src/index.js */\"./src/index.js\");\n\n\n//# sourceURL=webpack://ElementQueries/multi_./src/index.js?"); /***/ }) -/******/ }); +/******/ })["default"]; }); \ No newline at end of file diff --git a/dist/element-queries.min.js b/dist/element-queries.min.js index c256ff5..344656e 100644 --- a/dist/element-queries.min.js +++ b/dist/element-queries.min.js @@ -1 +1 @@ -!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var o=t();for(var n in o)("object"==typeof exports?exports:e)[n]=o[n]}}(window,(function(){return function(e){var t={};function o(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}return o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)o.d(n,r,function(t){return e[t]}.bind(null,r));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=0)}([function(e,t,o){e.exports=o(1)},function(e,t,o){"use strict";o.r(t),o.d(t,"ElementQueries",(function(){return a}));const n=/([_A-z]+[A-z0-9-_]+):(\d+)/g,r="Please provide a HTMLElement",i="Please provide an array of HTMLElements",s="No breakpoints found on element",c={htmlAttrBreakpoints:"data-eq-breakpoints",htmlAttrActive:"data-eq-active"};class a{constructor(e){this.opts=Object.freeze({...c,...e}),this.observer=new ResizeObserver(this.onResize.bind(this)),this.elements=new WeakMap,/complete|interactive|loaded/.test(document.readyState)?this.onDocumentLoad():document.addEventListener("DOMContentLoaded",this.onDocumentLoad.bind(this),{once:!0})}onDocumentLoad(){this.init(),this.domObserver=new MutationObserver(this.onDomMutation.bind(this)),this.domObserver.observe(document.body,{childList:!0,subtree:!0})}init(){const e=document.querySelectorAll(`[${this.opts.htmlAttrBreakpoints}]`);for(const t of e)try{this.watch(t)}catch(e){console.error(e,t)}}onResize(e){const t=new Set;for(var o=e.length-1;o>=0;o--){const{target:n,borderBoxSize:r}=e[o];if(this.elements.has(n)){let e,o;if(r&&r[0])e=r[0].inlineSize,o=r[0].blockSize;else{const t=n.getBoundingClientRect();e=t.width,o=t.height}const i=this.elements.get(n);this.elements.set(n,{...i,width:e,height:o}),t.add(n)}}this.update([...t])}onDomMutation(e){for(var t=e.length-1;t>=0;t--)if(e[t].addedNodes.length)for(var o=e[t].addedNodes.length-1;o>=0;o--){const n=e[t].addedNodes[o];if(n instanceof HTMLElement&&n.hasAttribute(this.opts.htmlAttrBreakpoints))try{this.watch(n)}catch(e){console.error(e,n)}}}watch(e){if(!(e&&e instanceof HTMLElement))throw new Error(r);if(!e.hasAttribute(this.opts.htmlAttrBreakpoints))throw new Error(s);const t=[...e.getAttribute(this.opts.htmlAttrBreakpoints).replace(/ /g,"").matchAll(n)];if(!t.length)throw new Error(s);const o=t.reduce((e,t)=>t[1]&&t[2]?(e[t[1]]=+t[2],e):e,{});this.elements.set(e,{breakpoints:o}),this.observer.observe(e,{box:"border-box"})}update(e){if(!(e&&Array.isArray(e)&&e.length&&e.every(e=>e instanceof HTMLElement)))throw new Error(i);for(var t=e.length-1;t>=0;t--){const n=e[t],r=this.elements.get(n);if(r&&r.breakpoints){const{width:e}=r;let t=null;const i=(o=r.breakpoints,Object.entries(o).reduce((e,[t,o])=>Object.assign(e,{[o]:t}),{})),s=Object.values(r.breakpoints).sort(),c=s[s.length-1];if(e>=c)t=i[c];else if(e>s[0])for(let o=0;o=n&&(t=i[n])}if(t){n.setAttribute(this.opts.htmlAttrActive,t);continue}}n.removeAttribute(this.opts.htmlAttrActive)}var o}destroy(){this.observer&&this.observer.disconnect(),this.domObserver&&this.domObserver.disconnect(),this.elements=new WeakMap}}}])})); \ No newline at end of file +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.ElementQueries=t():e.ElementQueries=t()}(window,(function(){return function(e){var t={};function o(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}return o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)o.d(n,r,function(t){return e[t]}.bind(null,r));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=0)}([function(e,t,o){e.exports=o(1)},function(e,t,o){"use strict";o.r(t);const n=/([_A-z]+[A-z0-9-_]+):(\d+)/g,r="Please provide a HTMLElement",i="Please provide an array of HTMLElements",s="No breakpoints found on element",a={htmlAttrBreakpoints:"data-eq-breakpoints",htmlAttrActive:"data-eq-active"};t.default=class{constructor(e){this.opts=Object.freeze({...a,...e}),this.observer=new ResizeObserver(this.onResize.bind(this)),this.elements=new WeakMap,/complete|interactive|loaded/.test(document.readyState)?this.onDocumentLoad():document.addEventListener("DOMContentLoaded",this.onDocumentLoad.bind(this),{once:!0})}onDocumentLoad(){this.init(),this.domObserver=new MutationObserver(this.onDomMutation.bind(this)),this.domObserver.observe(document.body,{childList:!0,subtree:!0})}init(){const e=document.querySelectorAll(`[${this.opts.htmlAttrBreakpoints}]`);for(const t of e)try{this.watch(t)}catch(e){console.error(e,t)}}onResize(e){const t=new Set;for(var o=e.length-1;o>=0;o--){const{target:n,borderBoxSize:r}=e[o];if(this.elements.has(n)){let e,o;if(r&&r[0])e=r[0].inlineSize,o=r[0].blockSize;else{const t=n.getBoundingClientRect();e=t.width,o=t.height}const i=this.elements.get(n);this.elements.set(n,{...i,width:e,height:o}),t.add(n)}}this.update([...t])}onDomMutation(e){for(var t=e.length-1;t>=0;t--)if(e[t].addedNodes.length)for(var o=e[t].addedNodes.length-1;o>=0;o--){const n=e[t].addedNodes[o];if(n instanceof HTMLElement&&n.hasAttribute(this.opts.htmlAttrBreakpoints))try{this.watch(n)}catch(e){console.error(e,n)}}}watch(e){if(!(e&&e instanceof HTMLElement))throw new Error(r);if(!e.hasAttribute(this.opts.htmlAttrBreakpoints))throw new Error(s);const t=[...e.getAttribute(this.opts.htmlAttrBreakpoints).replace(/ /g,"").matchAll(n)];if(!t.length)throw new Error(s);const o=t.reduce((e,t)=>t[1]&&t[2]?(e[t[1]]=+t[2],e):e,{});this.elements.set(e,{breakpoints:o}),this.observer.observe(e,{box:"border-box"})}update(e){if(!(e&&Array.isArray(e)&&e.length&&e.every(e=>e instanceof HTMLElement)))throw new Error(i);for(var t=e.length-1;t>=0;t--){const n=e[t],r=this.elements.get(n);if(r&&r.breakpoints){const{width:e}=r;let t=null;const i=(o=r.breakpoints,Object.entries(o).reduce((e,[t,o])=>Object.assign(e,{[o]:t}),{})),s=Object.values(r.breakpoints).sort(),a=s[s.length-1];if(e>=a)t=i[a];else if(e>s[0])for(let o=0;o=n&&(t=i[n])}if(t){n.setAttribute(this.opts.htmlAttrActive,t);continue}}n.removeAttribute(this.opts.htmlAttrActive)}var o}destroy(){this.observer&&this.observer.disconnect(),this.domObserver&&this.domObserver.disconnect(),this.elements=new WeakMap}}}]).default})); \ No newline at end of file diff --git a/lib/ElementQueries.js b/lib/ElementQueries.js index 5efc430..3986d04 100644 --- a/lib/ElementQueries.js +++ b/lib/ElementQueries.js @@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.ElementQueries = void 0; +exports["default"] = void 0; var _utils = require("./utils"); @@ -239,4 +239,4 @@ var ElementQueries = /*#__PURE__*/function () { return ElementQueries; }(); -exports.ElementQueries = ElementQueries; \ No newline at end of file +exports["default"] = ElementQueries; \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index a23e54b..2c271d9 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,11 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true }); -Object.defineProperty(exports, "ElementQueries", { - enumerable: true, - get: function get() { - return _ElementQueries.ElementQueries; - } -}); +exports["default"] = void 0; + +var _ElementQueries = _interopRequireDefault(require("./ElementQueries")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +var _default = _ElementQueries["default"]; +/** TODOs + * TODO move this out of here :) + * TODO allow passing breakpoint object to .watch() which overrides htmlAttrBreakpoints + * TODO Support HTMLElement *AND* SVGElement + * TODO disable if ResizeObserver isnt supported + * TODO config option: dom observing on/off + * NOTE general browser-support checks (MutationObserver, etc) + * NOTE batching resize updates? + * NOTE throttle observer? + * NOTE debounce updates on a per-element basis? + * NOTE use requestAnimationFrame on resize callback? + * NOTE what do if user changes htmlAttrBreakpoints dynamically + */ -var _ElementQueries = require("./ElementQueries"); \ No newline at end of file +exports["default"] = _default; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 28c72b6..1facd92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "element-queries", - "version": "0.3.2", + "version": "0.3.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 254b1e6..229907b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "element-queries", - "version": "0.3.2", + "version": "0.3.3", "description": "A responsive element queries library based on modern ResizeObserver technology.", "author": "Danian de Leeuw ", "keywords": [