Compare commits

...

3 Commits

Author SHA1 Message Date
Libin YANG
ea0a42dffb
fix: update button (#477)
All checks were successful
Build and Deploy / build-and-deploy (push) Has been skipped
2024-12-18 12:59:50 +08:00
Libin YANG
3442a94c51
fix: update button (#476) 2024-12-18 12:39:55 +08:00
YangFong
71de06633e
feat: init post list (#475) 2024-12-18 09:53:56 +08:00
21 changed files with 281 additions and 36 deletions

View File

@ -33,7 +33,7 @@ import {
} from '@/config' } from '@/config'
import { useDisplayStore, useStore } from '@/stores' import { useDisplayStore, useStore } from '@/stores'
import { mergeCss, solveWeChatImage } from '@/utils' import { mergeCss, solveWeChatImage } from '@/utils'
import { Moon, Paintbrush, Sun } from 'lucide-vue-next' import { Moon, Paintbrush, PanelLeftClose, PanelLeftOpen, Sun } from 'lucide-vue-next'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { nextTick, ref, useTemplateRef } from 'vue' import { nextTick, ref, useTemplateRef } from 'vue'
import PickColors from 'vue-pick-colors' import PickColors from 'vue-pick-colors'
@ -122,10 +122,10 @@ function copy() {
// position translateY // position translateY
.replace(/top:(.*?)em/g, `transform: translateY($1em)`) .replace(/top:(.*?)em/g, `transform: translateY($1em)`)
// //
.replaceAll(`hsl(var(--foreground))`, `#3f3f3f`) .replace(/hsl\(var\(--foreground\)\)/g, `#3f3f3f`)
.replaceAll(`var(--blockquote-background)`, `#f7f7f7`) .replace(/var\(--blockquote-background\)/g, `#f7f7f7`)
.replaceAll(`var(--md-primary-color)`, primaryColor.value) .replace(/var\(--md-primary-color\)/g, primaryColor.value)
.replaceAll(/--md-primary-color:.+?;/g, ``) .replace(/--md-primary-color:.+?;/g, ``)
.replace(/<span class="nodeLabel"([^>]*)><p[^>]*>(.*?)<\/p><\/span>/g, `<span class="nodeLabel"$1>$2</span>`) .replace(/<span class="nodeLabel"([^>]*)><p[^>]*>(.*?)<\/p><\/span>/g, `<span class="nodeLabel"$1>$2</span>`)
clipboardDiv.focus() clipboardDiv.focus()
@ -219,6 +219,12 @@ const formatOptions = ref<Format[]>([`rgb`, `hex`, `hsl`, `hsv`])
<HelpDropdown /> <HelpDropdown />
</Menubar> </Menubar>
<Button v-if="!store.isOpenPostSlider" variant="outline" class="mr-2" @click="store.isOpenPostSlider = true">
<PanelLeftOpen class="size-4" />
</Button>
<Button v-else variant="outline" class="mr-2" @click="store.isOpenPostSlider = false">
<PanelLeftClose class="size-4" />
</Button>
<Popover> <Popover>
<PopoverTrigger> <PopoverTrigger>
<Button variant="outline"> <Button variant="outline">

View File

@ -0,0 +1,189 @@
<script setup lang="ts">
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { Input } from '@/components/ui/input'
import { useStore } from '@/stores'
import { Edit3, Ellipsis, Plus, Trash } from 'lucide-vue-next'
import { ref, watch } from 'vue'
import { toast } from 'vue-sonner'
const store = useStore()
const isOpen = ref(false)
const addPostInputVal = ref(``)
watch(isOpen, () => {
if (isOpen.value) {
addPostInputVal.value = ``
}
})
function addPost() {
if (addPostInputVal.value === ``) {
toast.error(`文章标题不可为空`)
return
}
store.addPost(addPostInputVal.value)
isOpen.value = false
toast.success(`文章新增成功`)
}
const editTarget = ref(-1)
const isOpenEditDialog = ref(false)
const renamePostInputVal = ref(``)
function startRenamePost(index: number) {
editTarget.value = index
renamePostInputVal.value = store.posts[index].title
isOpenEditDialog.value = true
}
function renamePost() {
if (renamePostInputVal.value === ``) {
toast.error(`文章标题不可为空`)
return
}
store.renamePost(editTarget.value, renamePostInputVal.value)
isOpenEditDialog.value = false
toast.success(`文章更名成功`)
}
const isOpenDelPostConfirmDialog = ref(false)
function startDelPost(index: number) {
editTarget.value = index
isOpenDelPostConfirmDialog.value = true
}
function delPost() {
store.delPost(editTarget.value)
isOpenDelPostConfirmDialog.value = false
toast.success(`文章删除成功`)
}
</script>
<template>
<div
class="overflow-hidden border-r bg-gray/20 transition-width dark:bg-gray/40"
:class="{
'w-0': !store.isOpenPostSlider,
'w-50': store.isOpenPostSlider,
}"
>
<nav class="space-y-1 h-full overflow-auto p-2">
<Dialog v-model:open="isOpen">
<DialogTrigger as-child>
<Button variant="outline" class="w-full" size="xs">
<Plus /> 新增文章
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>新增文章</DialogTitle>
<DialogDescription>
请输入文章名称
</DialogDescription>
</DialogHeader>
<Input v-model="addPostInputVal" />
<DialogFooter>
<Button @click="addPost()">
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<a
v-for="(post, index) in store.posts"
:key="post.title"
href="#"
:class="{
'bg-primary text-primary-foreground': store.currentPostIndex === index,
}"
class="hover:bg-primary/90 hover:text-primary-foreground dark:bg-muted dark:hover:bg-muted h-8 w-full inline-flex items-center justify-start gap-2 whitespace-nowrap rounded px-2 text-sm transition-colors dark:text-white dark:hover:text-white"
@click="store.currentPostIndex = index"
>
<span class="line-clamp-1">{{ post.title }}</span>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<Button size="xs" variant="ghost" class="ml-auto px-1.5">
<Ellipsis class="size-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem @click.stop="startRenamePost(index)">
<Edit3 class="mr-2 size-4" />
更名
</DropdownMenuItem>
<DropdownMenuItem @click.stop="startDelPost(index)">
<Trash class="mr-2 size-4" />
删除
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</a>
<!-- 重命名弹窗 -->
<Dialog v-model:open="isOpenEditDialog">
<DialogContent class="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>编辑文章名称</DialogTitle>
<DialogDescription>
请输入新的文章名称
</DialogDescription>
</DialogHeader>
<Input v-model="renamePostInputVal" />
<DialogFooter>
<Button variant="outline" @click="isOpenEditDialog = false">
取消
</Button>
<Button @click="renamePost()">
保存
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<AlertDialog v-model:open="isOpenDelPostConfirmDialog">
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>提示</AlertDialogTitle>
<AlertDialogDescription>
此操作将删除该文章是否继续
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>取消</AlertDialogCancel>
<AlertDialogAction @click="delPost()">
确认
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</nav>
</div>
</template>
<style scoped lang="less">
</style>

View File

@ -601,6 +601,7 @@ function onDrop(e: DragEvent) {
<Button <Button
variant="link" variant="link"
class="p-0" class="p-0"
as="a"
href="https://developer.qiniu.com/kodo" href="https://developer.qiniu.com/kodo"
target="_blank" target="_blank"
> >
@ -642,6 +643,7 @@ function onDrop(e: DragEvent) {
<Button <Button
variant="link" variant="link"
class="p-0" class="p-0"
as="a"
href="http://docs.minio.org.cn/docs/master/minio-client-complete-guide" href="http://docs.minio.org.cn/docs/master/minio-client-complete-guide"
target="_blank" target="_blank"
> >
@ -680,6 +682,7 @@ function onDrop(e: DragEvent) {
<Button <Button
variant="link" variant="link"
class="p-0" class="p-0"
as="a"
href="https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Getting_Started_Guide.html" href="https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Getting_Started_Guide.html"
target="_blank" target="_blank"
> >
@ -688,6 +691,7 @@ function onDrop(e: DragEvent) {
<Button <Button
variant="link" variant="link"
class="p-0" class="p-0"
as="a"
href="https://mpmd.pages.dev/tutorial/" href="https://mpmd.pages.dev/tutorial/"
target="_blank" target="_blank"
> >

View File

@ -10,7 +10,7 @@ const props = defineProps<{
<template> <template>
<div> <div>
<Label class="flex items-center"> <Label class="flex items-center">
<span class="mr-4 w-[150px] text-right font-bold min-h-4 flex-shrink-0" :class="{ required: props.required }"> <span class="mr-4 min-h-4 w-[150px] flex-shrink-0 text-right font-bold" :class="{ required: props.required }">
{{ props.label }} {{ props.label }}
</span> </span>
<slot /> <slot />

View File

@ -4,8 +4,8 @@ import { cn } from '@/lib/utils'
import { type AlertVariants, alertVariants } from '.' import { type AlertVariants, alertVariants } from '.'
const props = defineProps<{ const props = defineProps<{
class?: HTMLAttributes['class'] class?: HTMLAttributes[`class`]
variant?: AlertVariants['variant'] variant?: AlertVariants[`variant`]
}>() }>()
</script> </script>

View File

@ -3,7 +3,7 @@ import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<{ const props = defineProps<{
class?: HTMLAttributes['class'] class?: HTMLAttributes[`class`]
}>() }>()
</script> </script>

View File

@ -3,7 +3,7 @@ import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<{ const props = defineProps<{
class?: HTMLAttributes['class'] class?: HTMLAttributes[`class`]
}>() }>()
</script> </script>

View File

@ -5,17 +5,17 @@ export { default as AlertDescription } from './AlertDescription.vue'
export { default as AlertTitle } from './AlertTitle.vue' export { default as AlertTitle } from './AlertTitle.vue'
export const alertVariants = cva( export const alertVariants = cva(
'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground', `relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground`,
{ {
variants: { variants: {
variant: { variant: {
default: 'bg-background text-foreground', default: `bg-background text-foreground`,
destructive: destructive:
'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive', `border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive`,
}, },
}, },
defaultVariants: { defaultVariants: {
variant: 'default', variant: `default`,
}, },
}, },
) )

View File

@ -3,7 +3,7 @@ import { cn } from '@/lib/utils'
import { Label, type LabelProps } from 'radix-vue' import { Label, type LabelProps } from 'radix-vue'
import { computed, type HTMLAttributes } from 'vue' import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<LabelProps & { class?: HTMLAttributes['class'] }>() const props = defineProps<LabelProps & { class?: HTMLAttributes[`class`] }>()
const delegatedProps = computed(() => { const delegatedProps = computed(() => {
const { class: _, ...delegated } = props const { class: _, ...delegated } = props

View File

@ -4,7 +4,7 @@ import { cn } from '@/lib/utils'
import { NumberFieldRoot, useForwardPropsEmits } from 'radix-vue' import { NumberFieldRoot, useForwardPropsEmits } from 'radix-vue'
import { computed, type HTMLAttributes } from 'vue' import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<NumberFieldRootProps & { class?: HTMLAttributes['class'] }>() const props = defineProps<NumberFieldRootProps & { class?: HTMLAttributes[`class`] }>()
const emits = defineEmits<NumberFieldRootEmits>() const emits = defineEmits<NumberFieldRootEmits>()
const delegatedProps = computed(() => { const delegatedProps = computed(() => {

View File

@ -3,7 +3,7 @@ import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<{ const props = defineProps<{
class?: HTMLAttributes['class'] class?: HTMLAttributes[`class`]
}>() }>()
</script> </script>

View File

@ -5,7 +5,7 @@ import { Minus } from 'lucide-vue-next'
import { NumberFieldDecrement, useForwardProps } from 'radix-vue' import { NumberFieldDecrement, useForwardProps } from 'radix-vue'
import { computed, type HTMLAttributes } from 'vue' import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<NumberFieldDecrementProps & { class?: HTMLAttributes['class'] }>() const props = defineProps<NumberFieldDecrementProps & { class?: HTMLAttributes[`class`] }>()
const delegatedProps = computed(() => { const delegatedProps = computed(() => {
const { class: _, ...delegated } = props const { class: _, ...delegated } = props

View File

@ -5,7 +5,7 @@ import { Plus } from 'lucide-vue-next'
import { NumberFieldIncrement, useForwardProps } from 'radix-vue' import { NumberFieldIncrement, useForwardProps } from 'radix-vue'
import { computed, type HTMLAttributes } from 'vue' import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<NumberFieldIncrementProps & { class?: HTMLAttributes['class'] }>() const props = defineProps<NumberFieldIncrementProps & { class?: HTMLAttributes[`class`] }>()
const delegatedProps = computed(() => { const delegatedProps = computed(() => {
const { class: _, ...delegated } = props const { class: _, ...delegated } = props

View File

@ -4,7 +4,7 @@ import { cn } from '@/lib/utils'
import { NumberFieldInput } from 'radix-vue' import { NumberFieldInput } from 'radix-vue'
const props = defineProps<{ const props = defineProps<{
class?: HTMLAttributes['class'] class?: HTMLAttributes[`class`]
}>() }>()
</script> </script>

View File

@ -9,7 +9,7 @@ import {
} from 'radix-vue' } from 'radix-vue'
import { computed, type HTMLAttributes } from 'vue' import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<SwitchRootProps & { class?: HTMLAttributes['class'] }>() const props = defineProps<SwitchRootProps & { class?: HTMLAttributes[`class`] }>()
const emits = defineEmits<SwitchRootEmits>() const emits = defineEmits<SwitchRootEmits>()

View File

@ -3,7 +3,7 @@ import { cn } from '@/lib/utils'
import { TabsContent, type TabsContentProps } from 'radix-vue' import { TabsContent, type TabsContentProps } from 'radix-vue'
import { computed, type HTMLAttributes } from 'vue' import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<TabsContentProps & { class?: HTMLAttributes['class'] }>() const props = defineProps<TabsContentProps & { class?: HTMLAttributes[`class`] }>()
const delegatedProps = computed(() => { const delegatedProps = computed(() => {
const { class: _, ...delegated } = props const { class: _, ...delegated } = props

View File

@ -3,7 +3,7 @@ import { cn } from '@/lib/utils'
import { TabsList, type TabsListProps } from 'radix-vue' import { TabsList, type TabsListProps } from 'radix-vue'
import { computed, type HTMLAttributes } from 'vue' import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<TabsListProps & { class?: HTMLAttributes['class'] }>() const props = defineProps<TabsListProps & { class?: HTMLAttributes[`class`] }>()
const delegatedProps = computed(() => { const delegatedProps = computed(() => {
const { class: _, ...delegated } = props const { class: _, ...delegated } = props

View File

@ -3,7 +3,7 @@ import { cn } from '@/lib/utils'
import { TabsTrigger, type TabsTriggerProps, useForwardProps } from 'radix-vue' import { TabsTrigger, type TabsTriggerProps, useForwardProps } from 'radix-vue'
import { computed, type HTMLAttributes } from 'vue' import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<TabsTriggerProps & { class?: HTMLAttributes['class'] }>() const props = defineProps<TabsTriggerProps & { class?: HTMLAttributes[`class`] }>()
const delegatedProps = computed(() => { const delegatedProps = computed(() => {
const { class: _, ...delegated } = props const { class: _, ...delegated } = props

View File

@ -4,16 +4,16 @@ import { cn } from '@/lib/utils'
import { useVModel } from '@vueuse/core' import { useVModel } from '@vueuse/core'
const props = defineProps<{ const props = defineProps<{
class?: HTMLAttributes['class'] class?: HTMLAttributes[`class`]
defaultValue?: string | number defaultValue?: string | number
modelValue?: string | number modelValue?: string | number
}>() }>()
const emits = defineEmits<{ const emits = defineEmits<{
(e: 'update:modelValue', payload: string | number): void (e: `update:modelValue`, payload: string | number): void
}>() }>()
const modelValue = useVModel(props, 'modelValue', emits, { const modelValue = useVModel(props, `modelValue`, emits, {
passive: true, passive: true,
defaultValue: props.defaultValue, defaultValue: props.defaultValue,
}) })

View File

@ -52,12 +52,50 @@ export const useStore = defineStore(`store`, () => {
// 内容编辑器编辑器 // 内容编辑器编辑器
const editor = ref<CodeMirror.EditorFromTextArea | null>(null) const editor = ref<CodeMirror.EditorFromTextArea | null>(null)
// 编辑区域内容 // 编辑区域内容
// 预备弃用
const editorContent = useStorage(`__editor_content`, DEFAULT_CONTENT) const editorContent = useStorage(`__editor_content`, DEFAULT_CONTENT)
const isOpenPostSlider = useStorage(addPrefix(`is_open_post_slider`), false)
// 文章列表
const posts = useStorage(addPrefix(`posts`), [{
title: `文章1`,
content: DEFAULT_CONTENT,
}])
// 当前文章
const currentPostIndex = useStorage(addPrefix(`current_post_index`), 0)
const addPost = (title: string) => {
currentPostIndex.value = posts.value.push({
title,
content: DEFAULT_CONTENT,
}) - 1
}
const renamePost = (index: number, title: string) => {
posts.value[index].title = title
}
const delPost = (index: number) => {
posts.value.splice(index, 1)
currentPostIndex.value = 0
}
watch(currentPostIndex, () => {
toRaw(editor.value!).setValue(posts.value[currentPostIndex.value].content)
})
onMounted(() => {
// 迁移阶段,兼容之前的方案
if (editorContent.value !== DEFAULT_CONTENT) {
posts.value[currentPostIndex.value].content = editorContent.value
editorContent.value = DEFAULT_CONTENT
}
})
// 格式化文档 // 格式化文档
const formatContent = () => { const formatContent = () => {
formatDoc((editor.value!).getValue()).then((doc) => { formatDoc((editor.value!).getValue()).then((doc) => {
editorContent.value = doc posts.value[currentPostIndex.value].content = doc
toRaw(editor.value!).setValue(doc) toRaw(editor.value!).setValue(doc)
}) })
} }
@ -421,7 +459,6 @@ export const useStore = defineStore(`store`, () => {
isOpenConfirmDialog, isOpenConfirmDialog,
resetStyleConfirm, resetStyleConfirm,
resetStyle, resetStyle,
editorContent,
cssContentConfig, cssContentConfig,
addCssContentTab, addCssContentTab,
@ -429,6 +466,12 @@ export const useStore = defineStore(`store`, () => {
setCssEditorValue, setCssEditorValue,
tabChanged, tabChanged,
renameTab, renameTab,
posts,
currentPostIndex,
addPost,
renamePost,
delPost,
isOpenPostSlider,
} }
}) })

View File

@ -3,6 +3,7 @@ import type { ComponentPublicInstance } from 'vue'
import CssEditor from '@/components/CodemirrorEditor/CssEditor.vue' import CssEditor from '@/components/CodemirrorEditor/CssEditor.vue'
import EditorHeader from '@/components/CodemirrorEditor/EditorHeader/index.vue' import EditorHeader from '@/components/CodemirrorEditor/EditorHeader/index.vue'
import InsertFormDialog from '@/components/CodemirrorEditor/InsertFormDialog.vue' import InsertFormDialog from '@/components/CodemirrorEditor/InsertFormDialog.vue'
import PostSlider from '@/components/CodemirrorEditor/PostSlider.vue'
import UploadImgDialog from '@/components/CodemirrorEditor/UploadImgDialog.vue' import UploadImgDialog from '@/components/CodemirrorEditor/UploadImgDialog.vue'
import RunLoading from '@/components/RunLoading.vue' import RunLoading from '@/components/RunLoading.vue'
import { import {
@ -15,6 +16,7 @@ import {
AlertDialogHeader, AlertDialogHeader,
AlertDialogTitle, AlertDialogTitle,
} from '@/components/ui/alert-dialog' } from '@/components/ui/alert-dialog'
import { import {
ContextMenu, ContextMenu,
ContextMenuContent, ContextMenuContent,
@ -38,7 +40,7 @@ import { toast } from 'vue-sonner'
const store = useStore() const store = useStore()
const displayStore = useDisplayStore() const displayStore = useDisplayStore()
const { isDark, output, editor, editorContent } = storeToRefs(store) const { isDark, output, editor } = storeToRefs(store)
const { isShowCssEditor } = storeToRefs(displayStore) const { isShowCssEditor } = storeToRefs(displayStore)
const { const {
@ -201,7 +203,7 @@ function initEditor() {
const editorDom = document.querySelector<HTMLTextAreaElement>(`#editor`)! const editorDom = document.querySelector<HTMLTextAreaElement>(`#editor`)!
if (!editorDom.value) { if (!editorDom.value) {
editorDom.value = editorContent.value editorDom.value = store.posts[store.currentPostIndex].content
} }
editor.value = CodeMirror.fromTextArea(editorDom, { editor.value = CodeMirror.fromTextArea(editorDom, {
mode: `text/x-markdown`, mode: `text/x-markdown`,
@ -248,7 +250,7 @@ function initEditor() {
clearTimeout(changeTimer.value) clearTimeout(changeTimer.value)
changeTimer.value = setTimeout(() => { changeTimer.value = setTimeout(() => {
onEditorRefresh() onEditorRefresh()
editorContent.value = e.getValue() store.posts[store.currentPostIndex].content = e.getValue()
}, 300) }, 300)
}) })
@ -396,10 +398,11 @@ onMounted(() => {
@end-copy="endCopy" @end-copy="endCopy"
/> />
<main class="container-main flex-1"> <main class="container-main flex-1">
<div class="container-main-section grid h-full border-1" :class="isShowCssEditor ? 'grid-cols-3' : 'grid-cols-2'"> <div class="container-main-section h-full flex border-1">
<PostSlider />
<div <div
ref="codeMirrorWrapper" ref="codeMirrorWrapper"
class="codeMirror-wrapper border-r-1" class="codeMirror-wrapper flex-1 border-r-1"
:class="{ :class="{
'order-1': !store.isEditOnLeft, 'order-1': !store.isEditOnLeft,
}" }"
@ -443,7 +446,7 @@ onMounted(() => {
id="preview" id="preview"
ref="preview" ref="preview"
:span="isShowCssEditor ? 8 : 12" :span="isShowCssEditor ? 8 : 12"
class="preview-wrapper p-5" class="preview-wrapper flex-1 p-5"
> >
<div id="output-wrapper" :class="{ output_night: !backLight }"> <div id="output-wrapper" :class="{ output_night: !backLight }">
<div class="preview border shadow-xl"> <div class="preview border shadow-xl">
@ -457,7 +460,7 @@ onMounted(() => {
</div> </div>
</div> </div>
</div> </div>
<CssEditor /> <CssEditor class="flex-1" />
</div> </div>
</main> </main>