ember-container-query
Version:
Make container queries that harness the power of Ember
110 lines (106 loc) • 3.18 kB
JavaScript
import { registerDestructor } from '@ember/destroyable';
import { action } from '@ember/object';
import { debounce } from '@ember/runloop';
import Modifier from 'ember-modifier';
import { resizeObserver } from 'ember-primitives/resize-observer';
import { n } from 'decorator-transforms/runtime-esm';
let ContainerQuery$1 = class ContainerQuery extends Modifier {
_dataAttributes = [];
_element;
_named;
#resizeObserver = resizeObserver(this);
dimensions;
queryResults;
get dataAttributePrefix() {
return this._named.dataAttributePrefix ?? 'container-query';
}
get debounce() {
return this._named.debounce ?? 0;
}
get features() {
return this._named.features ?? {};
}
constructor(owner, args) {
super(owner, args);
registerDestructor(this, () => {
if (this._element) {
this.#resizeObserver.unobserve(this._element, this.onResize);
}
});
}
evaluateQueries() {
const queryResults = {};
for (const [featureName, metadata] of Object.entries(this.features)) {
const {
dimension,
min,
max
} = metadata;
const value = this.dimensions[dimension];
queryResults[featureName] = min <= value && value < max;
}
this.queryResults = queryResults;
}
measureDimensions(element) {
const height = element.clientHeight;
const width = element.clientWidth;
this.dimensions = {
aspectRatio: width / height,
height,
width
};
}
modify(element, _positional, named) {
this._named = named;
this.registerResizeObserver(element);
this.queryContainer(element);
}
queryContainer(element) {
this.measureDimensions(element);
this.evaluateQueries();
this.resetDataAttributes(element);
this.setDataAttributes(element);
this._named.onQuery?.({
dimensions: this.dimensions,
queryResults: this.queryResults
});
}
registerResizeObserver(element) {
if (this._element) {
this.#resizeObserver.unobserve(this._element, this.onResize);
}
this._element = element;
this.#resizeObserver.observe(this._element, this.onResize);
}
resetDataAttributes(element) {
this._dataAttributes.forEach(dataAttribute => {
element.removeAttribute(dataAttribute);
});
this._dataAttributes = [];
}
setDataAttributes(element) {
const prefix = this.dataAttributePrefix;
for (const [featureName, meetsFeature] of Object.entries(this.queryResults)) {
if (!meetsFeature) {
continue;
}
const dataAttribute = prefix ? `data-${prefix}-${String(featureName)}` : `data-${String(featureName)}`;
element.setAttribute(dataAttribute, '');
this._dataAttributes.push(dataAttribute);
}
}
onResize(resizeObserverEntry) {
const element = resizeObserverEntry.target;
if (this.debounce > 0) {
// eslint-disable-next-line ember/no-runloop
debounce(this, this.queryContainer, element, this.debounce);
return;
}
this.queryContainer(element);
}
static {
n(this.prototype, "onResize", [action]);
}
};
export { ContainerQuery$1 as default };
//# sourceMappingURL=container-query.js.map