@studiometa/js-toolkit
Version:
A set of useful little bits of JavaScript to boost your project! 🚀
112 lines (111 loc) • 3.66 kB
JavaScript
import { useResize } from "../services/index.js";
import { isDev, startsWith } from "../utils/index.js";
import { features } from "../Base/features.js";
function testBreakpoints(instance, breakpoint = useResize().props().breakpoint) {
const { activeBreakpoints, inactiveBreakpoints } = instance.$options;
const isInActiveBreakpoint = activeBreakpoints && activeBreakpoints.split(" ").includes(breakpoint);
const isInInactiveBreakpoint = inactiveBreakpoints && inactiveBreakpoints.split(" ").includes(breakpoint);
if (activeBreakpoints && isInActiveBreakpoint || inactiveBreakpoints && !isInInactiveBreakpoint) {
return "$mount";
}
return "$destroy";
}
function hasBreakpointConfiguration(instance) {
const { activeBreakpoints, inactiveBreakpoints } = instance.$options;
return Boolean(activeBreakpoints || inactiveBreakpoints);
}
function testConflictingBreakpointConfiguration(instance) {
const { activeBreakpoints, inactiveBreakpoints, name } = instance.$options;
if (activeBreakpoints && inactiveBreakpoints) {
throw new Error(
`[${name}] Incorrect configuration: the \`activeBreakpoints\` and \`inactiveBreakpoints\` are not compatible.`
);
}
}
function createResizeCallback(instance) {
return ({ breakpoint }) => {
const action = testBreakpoints(instance, breakpoint);
if (action === "$destroy" && instance.$isMounted) {
instance[action]();
} else if (action === "$mount" && !instance.$isMounted) {
setTimeout(() => instance[action](), 0);
}
};
}
function addToResize(key, instance) {
if (isDev) {
testConflictingBreakpointConfiguration(instance);
}
const { add, has, props } = useResize();
if (!has(key)) {
const callback = createResizeCallback(instance);
add(key, callback);
callback(props());
}
}
function withBreakpointObserver(BaseClass) {
class WithBreakpointObserver extends BaseClass {
/**
* Config.
*/
static config = {
...BaseClass.config,
options: {
activeBreakpoints: String,
inactiveBreakpoints: String
}
};
/**
* Watch for the document resize to test the breakpoints.
*/
constructor(element) {
super(element);
const { remove, props } = useResize();
const { name } = this.$options;
if (!props().breakpoint) {
if (isDev) {
throw new Error(
`[${name}] The \`BreakpointObserver\` class requires breakpoints to be defined.`
);
}
return;
}
const key = `BreakpointObserver-${this.$id}`;
const attributes = features.get("attributes");
const mutationObserver = new MutationObserver(([mutation]) => {
if (mutation.type === "attributes" && startsWith(mutation.attributeName, `${attributes.option}-`)) {
if (!hasBreakpointConfiguration(this)) {
this.$mount();
remove(key);
return;
}
addToResize(key, this);
}
});
mutationObserver.observe(this.$el, { attributes: true });
if (!hasBreakpointConfiguration(this)) {
return;
}
addToResize(key, this);
}
/**
* Override the default $mount method to prevent component's from being
* mounted when they should not.
*/
async $mount() {
if (!hasBreakpointConfiguration(this)) {
return super.$mount();
}
const action = testBreakpoints(this);
if (action === "$mount") {
return super.$mount();
}
return this;
}
}
return WithBreakpointObserver;
}
export {
withBreakpointObserver
};
//# sourceMappingURL=withBreakpointObserver.js.map