mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-10 06:34:05 -08:00
refactor: Migrate ResizeObserver
to composition API (no-changelog) (#9745)
This commit is contained in:
parent
8b4a9dbced
commit
2dad9ce44c
|
@ -1,86 +1,63 @@
|
|||
<template>
|
||||
<div ref="root">
|
||||
<slot :bp="bp"></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, computed } from 'vue';
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
export type BreakpointDefinition = { bp: string; width: number };
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ResizeObserver',
|
||||
props: {
|
||||
enabled: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
breakpoints: {
|
||||
type: Array,
|
||||
validator: (bps: Array<{ bp: string; width: number }>) => {
|
||||
return (
|
||||
Array.isArray(bps) &&
|
||||
bps.reduce(
|
||||
(accu, { width, bp }) => accu && typeof width === 'number' && typeof bp === 'string',
|
||||
true,
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
data(): { observer: ResizeObserver | null; bp: string } {
|
||||
return {
|
||||
observer: null,
|
||||
bp: '',
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const root = this.$refs.root as HTMLDivElement;
|
||||
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.bp = this.getBreakpointFromWidth(root.offsetWidth);
|
||||
|
||||
const observer = new ResizeObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
// We wrap it in requestAnimationFrame to avoid this error - ResizeObserver loop limit exceeded
|
||||
requestAnimationFrame(() => {
|
||||
this.bp = this.getBreakpointFromWidth(entry.contentRect.width);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.observer = observer;
|
||||
observer.observe(root);
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.enabled) {
|
||||
this.observer?.disconnect();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getBreakpointFromWidth(width: number): string {
|
||||
let newBP = 'default';
|
||||
const unsortedBreakpoints = [...(this.breakpoints || [])] as Array<{
|
||||
width: number;
|
||||
bp: string;
|
||||
}>;
|
||||
|
||||
const bps = unsortedBreakpoints.sort((a, b) => a.width - b.width);
|
||||
for (let i = 0; i < bps.length; i++) {
|
||||
if (width < bps[i].width) {
|
||||
newBP = bps[i].bp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return newBP;
|
||||
const props = defineProps({
|
||||
enabled: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
breakpoints: {
|
||||
type: Array as () => BreakpointDefinition[],
|
||||
validator: (breakpoints: BreakpointDefinition[]) => {
|
||||
if (breakpoints.length === 0) return true;
|
||||
|
||||
return breakpoints.every((bp) => typeof bp.width === 'number' && typeof bp.bp === 'string');
|
||||
},
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const observer = ref<ResizeObserver | null>(null);
|
||||
const breakpoint = ref('');
|
||||
const root = ref<HTMLDivElement | null>(null);
|
||||
|
||||
const sortedBreakpoints = computed(() => [...props.breakpoints].sort((a, b) => a.width - b.width));
|
||||
|
||||
const getBreakpointFromWidth = (width: number): string => {
|
||||
return (
|
||||
sortedBreakpoints.value.find((sortedBreakpoint) => width < sortedBreakpoint.width)?.bp ??
|
||||
'default'
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (!props.enabled) return;
|
||||
if (!root.value) return;
|
||||
|
||||
breakpoint.value = getBreakpointFromWidth(root.value.offsetWidth);
|
||||
|
||||
observer.value = new ResizeObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
requestAnimationFrame(() => {
|
||||
breakpoint.value = getBreakpointFromWidth(entry.contentRect.width);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
observer.value.observe(root.value);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (observer.value) {
|
||||
observer.value.disconnect();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="root">
|
||||
<slot :bp="breakpoint"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
|
Loading…
Reference in a new issue