feat: 添加 InspiraUI 组件和模式背景功能,更新依赖项
This commit is contained in:
80
src/components/InspiraUI/spline/ParentSize.vue
Normal file
80
src/components/InspiraUI/spline/ParentSize.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<!-- ParentSize.vue -->
|
||||
<template>
|
||||
<div ref="target" :style="mergedStyles" :class="cn('w-full h-full', props.class)" v-bind="attrsWithoutClassAndStyle">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, useAttrs } from 'vue';
|
||||
import { useDebounceFn, useResizeObserver } from '@vueuse/core';
|
||||
import { cn } from '@/shadcn/lib/utils';
|
||||
|
||||
const props = defineProps({
|
||||
class: String,
|
||||
debounceTime: {
|
||||
type: Number,
|
||||
default: 300,
|
||||
},
|
||||
ignoreDimensions: {
|
||||
type: [Array, String],
|
||||
default: () => [],
|
||||
},
|
||||
parentSizeStyles: Object,
|
||||
enableDebounceLeadingCall: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const attrs = useAttrs();
|
||||
const target = ref<HTMLElement | null>(null);
|
||||
const state = reactive({
|
||||
width: 0,
|
||||
height: 0,
|
||||
top: 0,
|
||||
left: 0,
|
||||
});
|
||||
|
||||
const mergedStyles = computed(() => ({
|
||||
...props.parentSizeStyles,
|
||||
...(attrs.style as object),
|
||||
}));
|
||||
|
||||
const mergedClass = computed(() => ['w-full h-full', props.class]);
|
||||
|
||||
const attrsWithoutClassAndStyle = computed(() => {
|
||||
const { class: _, style: __, ...rest } = attrs;
|
||||
return rest;
|
||||
});
|
||||
|
||||
const normalizedIgnore = computed(() =>
|
||||
Array.isArray(props.ignoreDimensions) ? props.ignoreDimensions : [props.ignoreDimensions],
|
||||
);
|
||||
|
||||
function updateDimensions(rect: DOMRectReadOnly) {
|
||||
const { width, height, top, left } = rect;
|
||||
const newState = { width, height, top, left };
|
||||
|
||||
const hasChange = Object.keys(newState).some(
|
||||
(key) => state[key as keyof typeof state] !== newState[key as keyof typeof state],
|
||||
);
|
||||
|
||||
if (!hasChange) return;
|
||||
|
||||
const shouldUpdate = !Object.keys(newState).every((key) =>
|
||||
normalizedIgnore.value.includes(key as keyof typeof state),
|
||||
);
|
||||
|
||||
if (shouldUpdate) {
|
||||
Object.assign(state, newState);
|
||||
}
|
||||
}
|
||||
|
||||
const debouncedUpdate = useDebounceFn(updateDimensions, props.debounceTime);
|
||||
|
||||
useResizeObserver(target, (entries) => {
|
||||
const entry = entries[0];
|
||||
if (entry) debouncedUpdate(entry.contentRect);
|
||||
});
|
||||
</script>
|
Reference in New Issue
Block a user