knxdisplay/web-interface/src/components/widgets/elements/TabPageElement.vue
2026-02-04 21:11:04 +01:00

73 lines
1.9 KiB
Vue

<template>
<div
class="z-[1] select-none touch-none"
:class="selected ? 'outline outline-2 outline-accent outline-offset-2' : ''"
:style="computedStyle"
@click.stop="$emit('select')"
>
<!-- Children widgets inside the tab page -->
<WidgetElement
v-for="child in children"
:key="child.id"
:widget="child"
:scale="scale"
:selected="store.selectedWidgetId === child.id"
@select="store.selectedWidgetId = child.id"
@drag-start="$emit('drag-start', $event)"
@resize-start="$emit('resize-start', $event)"
/>
</div>
</template>
<script setup>
import { computed, defineAsyncComponent } from 'vue';
import { useEditorStore } from '../../../stores/editor';
import { fontSizes } from '../../../constants';
import { clamp, hexToRgba, getBorderStyle } from '../shared/utils';
const WidgetElement = defineAsyncComponent(() => import('../../WidgetElement.vue'));
const props = defineProps({
widget: { type: Object, required: true },
scale: { type: Number, default: 1 },
selected: { type: Boolean, default: false }
});
defineEmits(['select', 'drag-start', 'resize-start']);
const store = useEditorStore();
const children = computed(() => {
if (!store.activeScreen) return [];
return store.activeScreen.widgets.filter(w => w.parentId === props.widget.id);
});
const computedStyle = computed(() => {
const w = props.widget;
const s = props.scale;
const style = {
position: 'relative',
width: '100%',
height: '100%',
left: '0',
top: '0',
fontSize: `${(fontSizes[w.fontSize] || 14) * s}px`,
color: w.textColor,
zIndex: 1,
userSelect: 'none',
touchAction: 'none'
};
if ((w.bgOpacity ?? 0) > 0) {
style.background = hexToRgba(w.bgColor, clamp((w.bgOpacity ?? 255) / 255, 0, 1));
}
if ((w.radius || 0) > 0) {
style.borderRadius = `${(w.radius || 0) * s}px`;
}
Object.assign(style, getBorderStyle(w, s));
return style;
});
</script>