Extract DesignPanel from PropertiesPanel
This commit is contained in:
parent
bf5c905134
commit
b10785fdee
1
components.d.ts
vendored
1
components.d.ts
vendored
|
|
@ -16,6 +16,7 @@ declare module 'vue' {
|
|||
ChatPanel: typeof import('./src/components/ChatPanel.vue')['default']
|
||||
ColorInput: typeof import('./src/components/ColorInput.vue')['default']
|
||||
ColorPicker: typeof import('./src/components/ColorPicker.vue')['default']
|
||||
DesignPanel: typeof import('./src/components/DesignPanel.vue')['default']
|
||||
EditorCanvas: typeof import('./src/components/EditorCanvas.vue')['default']
|
||||
EffectsSection: typeof import('./src/components/properties/EffectsSection.vue')['default']
|
||||
ExportSection: typeof import('./src/components/properties/ExportSection.vue')['default']
|
||||
|
|
|
|||
85
src/components/DesignPanel.vue
Normal file
85
src/components/DesignPanel.vue
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import { useEditorStore } from '@/stores/editor'
|
||||
|
||||
import VariablesDialog from './VariablesDialog.vue'
|
||||
import AppearanceSection from './properties/AppearanceSection.vue'
|
||||
import EffectsSection from './properties/EffectsSection.vue'
|
||||
import ExportSection from './properties/ExportSection.vue'
|
||||
import FillSection from './properties/FillSection.vue'
|
||||
import LayoutSection from './properties/LayoutSection.vue'
|
||||
import PageSection from './properties/PageSection.vue'
|
||||
import PositionSection from './properties/PositionSection.vue'
|
||||
import StrokeSection from './properties/StrokeSection.vue'
|
||||
import TypographySection from './properties/TypographySection.vue'
|
||||
import VariablesSection from './properties/VariablesSection.vue'
|
||||
|
||||
const store = useEditorStore()
|
||||
const variablesOpen = ref(false)
|
||||
|
||||
const node = computed(() => store.selectedNode.value)
|
||||
const multiCount = computed(() => store.selectedNodes.value.length)
|
||||
const isComponentType = computed(() => {
|
||||
const t = node.value?.type
|
||||
return t === 'COMPONENT' || t === 'COMPONENT_SET' || t === 'INSTANCE'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Multi-select summary -->
|
||||
<div v-if="multiCount > 1" class="flex-1 overflow-y-auto pb-4">
|
||||
<div class="flex items-center gap-1.5 border-b border-border px-3 py-2">
|
||||
<span class="text-[11px] text-muted">Mixed</span>
|
||||
<span class="text-xs font-semibold">{{ multiCount }} layers</span>
|
||||
</div>
|
||||
<AppearanceSection />
|
||||
</div>
|
||||
|
||||
<!-- Single selection -->
|
||||
<div v-else-if="node" class="flex-1 overflow-y-auto pb-4">
|
||||
<!-- Node header -->
|
||||
<div class="flex items-center gap-1.5 border-b border-border px-3 py-2">
|
||||
<span class="text-[11px]" :class="isComponentType ? 'text-[#9747ff]' : 'text-muted'">{{
|
||||
node.type
|
||||
}}</span>
|
||||
<span class="text-xs font-semibold">{{ node.name }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Component actions -->
|
||||
<div
|
||||
v-if="node.type === 'INSTANCE'"
|
||||
class="flex flex-col gap-1 border-b border-border px-3 py-2"
|
||||
>
|
||||
<button
|
||||
class="rounded bg-[#9747ff]/10 px-2 py-1 text-left text-[11px] text-[#9747ff] hover:bg-[#9747ff]/20"
|
||||
@click="store.goToMainComponent()"
|
||||
>
|
||||
Go to Main Component
|
||||
</button>
|
||||
<button
|
||||
class="rounded px-2 py-1 text-left text-[11px] text-muted hover:bg-hover"
|
||||
@click="store.detachInstance()"
|
||||
>
|
||||
Detach Instance
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<PositionSection />
|
||||
<LayoutSection />
|
||||
<AppearanceSection />
|
||||
<TypographySection v-if="node.type === 'TEXT'" />
|
||||
<FillSection />
|
||||
<StrokeSection />
|
||||
<EffectsSection />
|
||||
|
||||
<ExportSection />
|
||||
</div>
|
||||
|
||||
<div v-else class="flex-1 overflow-y-auto pb-4">
|
||||
<PageSection />
|
||||
<VariablesSection @open-dialog="variablesOpen = true" />
|
||||
</div>
|
||||
|
||||
<VariablesDialog v-model:open="variablesOpen" />
|
||||
</template>
|
||||
|
|
@ -1,32 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import { useAIChat } from '@/composables/use-chat'
|
||||
import { useEditorStore } from '@/stores/editor'
|
||||
|
||||
import ChatPanel from './ChatPanel.vue'
|
||||
import VariablesDialog from './VariablesDialog.vue'
|
||||
import AppearanceSection from './properties/AppearanceSection.vue'
|
||||
import EffectsSection from './properties/EffectsSection.vue'
|
||||
import ExportSection from './properties/ExportSection.vue'
|
||||
import FillSection from './properties/FillSection.vue'
|
||||
import LayoutSection from './properties/LayoutSection.vue'
|
||||
import PageSection from './properties/PageSection.vue'
|
||||
import PositionSection from './properties/PositionSection.vue'
|
||||
import StrokeSection from './properties/StrokeSection.vue'
|
||||
import TypographySection from './properties/TypographySection.vue'
|
||||
import VariablesSection from './properties/VariablesSection.vue'
|
||||
import DesignPanel from './DesignPanel.vue'
|
||||
|
||||
const store = useEditorStore()
|
||||
const { activeTab } = useAIChat()
|
||||
const variablesOpen = ref(false)
|
||||
|
||||
const node = computed(() => store.selectedNode.value)
|
||||
const multiCount = computed(() => store.selectedNodes.value.length)
|
||||
const isComponentType = computed(() => {
|
||||
const t = node.value?.type
|
||||
return t === 'COMPONENT' || t === 'COMPONENT_SET' || t === 'INSTANCE'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -61,66 +41,7 @@ const isComponentType = computed(() => {
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<!-- AI Chat tab -->
|
||||
<ChatPanel v-if="activeTab === 'ai'" />
|
||||
|
||||
<!-- Design tab -->
|
||||
<template v-else>
|
||||
<!-- Multi-select summary -->
|
||||
<div v-if="multiCount > 1" class="flex-1 overflow-y-auto pb-4">
|
||||
<div class="flex items-center gap-1.5 border-b border-border px-3 py-2">
|
||||
<span class="text-[11px] text-muted">Mixed</span>
|
||||
<span class="text-xs font-semibold">{{ multiCount }} layers</span>
|
||||
</div>
|
||||
<AppearanceSection />
|
||||
</div>
|
||||
|
||||
<!-- Single selection -->
|
||||
<div v-else-if="node" class="flex-1 overflow-y-auto pb-4">
|
||||
<!-- Node header -->
|
||||
<div class="flex items-center gap-1.5 border-b border-border px-3 py-2">
|
||||
<span class="text-[11px]" :class="isComponentType ? 'text-[#9747ff]' : 'text-muted'">{{
|
||||
node.type
|
||||
}}</span>
|
||||
<span class="text-xs font-semibold">{{ node.name }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Component actions -->
|
||||
<div
|
||||
v-if="node.type === 'INSTANCE'"
|
||||
class="flex flex-col gap-1 border-b border-border px-3 py-2"
|
||||
>
|
||||
<button
|
||||
class="rounded bg-[#9747ff]/10 px-2 py-1 text-left text-[11px] text-[#9747ff] hover:bg-[#9747ff]/20"
|
||||
@click="store.goToMainComponent()"
|
||||
>
|
||||
Go to Main Component
|
||||
</button>
|
||||
<button
|
||||
class="rounded px-2 py-1 text-left text-[11px] text-muted hover:bg-hover"
|
||||
@click="store.detachInstance()"
|
||||
>
|
||||
Detach Instance
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<PositionSection />
|
||||
<LayoutSection />
|
||||
<AppearanceSection />
|
||||
<TypographySection v-if="node.type === 'TEXT'" />
|
||||
<FillSection />
|
||||
<StrokeSection />
|
||||
<EffectsSection />
|
||||
|
||||
<ExportSection />
|
||||
</div>
|
||||
|
||||
<div v-else class="flex-1 overflow-y-auto pb-4">
|
||||
<PageSection />
|
||||
<VariablesSection @open-dialog="variablesOpen = true" />
|
||||
</div>
|
||||
|
||||
<VariablesDialog v-model:open="variablesOpen" />
|
||||
</template>
|
||||
<DesignPanel v-else />
|
||||
</aside>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Reference in a new issue