UNPKG

@studiometa/js-toolkit

Version:

A set of useful little bits of JavaScript to boost your project! 🚀

112 lines (111 loc) • 3.66 kB
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