corrad-bp/components/ComponentPreview.vue
Afiq 63a7d0f870 Implement component resizing and grid optimization in Form Builder
- Added functionality for resizing components within the Form Builder, allowing users to adjust widths dynamically.
- Introduced a method to find optimal grid placement for new components, ensuring efficient use of available space.
- Enhanced layout optimization after component addition, deletion, and reordering to maintain a clean and organized interface.
- Updated the FormBuilderConfiguration to include width settings for components, improving customization options.
- Refactored styles for grid layout and component previews to enhance visual consistency and user experience.
2025-04-10 18:31:17 +08:00

102 lines
2.9 KiB
Vue

<template>
<div class="component-preview" :style="componentStyle">
<!-- Basic Input Types -->
<FormKit
v-if="isInputType"
:id="`preview-${component.id}`"
:type="component.props.type"
:name="component.props.name"
:label="component.props.label"
:help="component.props.help"
:placeholder="component.props.placeholder"
:validation="component.props.validation"
:validation-visibility="isPreview ? 'live' : 'blur'"
:disabled="isPreview"
:options="component.props.options || undefined"
:value="component.props.value || undefined"
:accept="component.props.accept || undefined"
:max="component.props.max || undefined"
:preserve-events="isPreview"
@input.capture.stop="isPreview ? $event.stopPropagation() : null"
@click.capture.stop="isPreview ? $event.stopPropagation() : null"
/>
<!-- Heading -->
<div v-else-if="component.type === 'heading'" class="py-2">
<component
:is="`h${component.props.level || 2}`"
class="font-semibold"
:class="{
'text-2xl': component.props.level === 2,
'text-xl': component.props.level === 3,
'text-lg': component.props.level === 4
}"
>
{{ component.props.value }}
</component>
</div>
<!-- Paragraph -->
<div v-else-if="component.type === 'paragraph'" class="py-2">
<p class="text-gray-600">{{ component.props.value }}</p>
</div>
<!-- Divider -->
<div v-else-if="component.type === 'divider'" class="py-4">
<hr class="border-gray-200" />
</div>
<!-- Unknown Component Type Fallback -->
<div v-else class="p-4 border border-dashed border-gray-300 rounded">
<div class="text-gray-500">Unknown component type: {{ component.type }}</div>
</div>
</div>
</template>
<script setup>
const props = defineProps({
component: {
type: Object,
required: true
},
isPreview: {
type: Boolean,
default: false
}
});
// Check if the component is a standard FormKit input type
const isInputType = computed(() => {
const inputTypes = [
'text', 'textarea', 'number', 'email', 'password',
'date', 'time', 'datetime-local', 'url', 'tel',
'select', 'checkbox', 'radio', 'file', 'range',
'color', 'hidden', 'group', 'repeater'
];
return inputTypes.includes(props.component.type);
});
// Compute style based on grid properties
const componentStyle = computed(() => {
// Only apply grid styles in the non-preview mode (actual form)
if (props.isPreview) {
return {}; // Styling is handled by parent in canvas mode
}
// Apply grid column in preview mode
const gridColumn = props.component.props.gridColumn || 'span 12';
return {
gridColumn: gridColumn,
width: '100%', // Always use 100% within the grid cell
boxSizing: 'border-box'
};
});
</script>
<style scoped>
.component-preview {
width: 100%;
}
</style>