From e6cde05b5960edf3451aa5dcb4db16ceddafbda4 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Tue, 17 Mar 2026 13:12:29 +0800 Subject: [PATCH] feat: tiptap preview --- packages/effects/plugins/src/tiptap/index.ts | 4 + .../effects/plugins/src/tiptap/preview.vue | 34 +++++++ packages/effects/plugins/src/tiptap/style.css | 56 +++++++++++ .../effects/plugins/src/tiptap/tiptap.vue | 97 ++++++++----------- packages/effects/plugins/src/tiptap/types.ts | 7 ++ packages/locales/src/langs/en-US/ui.json | 1 + packages/locales/src/langs/zh-CN/ui.json | 1 + .../src/views/examples/tiptap/index.vue | 8 +- 8 files changed, 149 insertions(+), 59 deletions(-) create mode 100644 packages/effects/plugins/src/tiptap/preview.vue create mode 100644 packages/effects/plugins/src/tiptap/style.css diff --git a/packages/effects/plugins/src/tiptap/index.ts b/packages/effects/plugins/src/tiptap/index.ts index 7b66f3469..f51ac75ee 100644 --- a/packages/effects/plugins/src/tiptap/index.ts +++ b/packages/effects/plugins/src/tiptap/index.ts @@ -1,7 +1,11 @@ +import './style.css'; + export { createDefaultTiptapExtensions } from './extensions'; +export { default as VbenTiptapPreview } from './preview.vue'; export { default as VbenTiptap } from './tiptap.vue'; export type { + TipTapPreviewProps, VbenTiptapChangeEvent, VbenTiptapExtensionOptions, } from './types'; diff --git a/packages/effects/plugins/src/tiptap/preview.vue b/packages/effects/plugins/src/tiptap/preview.vue new file mode 100644 index 000000000..c7d183988 --- /dev/null +++ b/packages/effects/plugins/src/tiptap/preview.vue @@ -0,0 +1,34 @@ + + + diff --git a/packages/effects/plugins/src/tiptap/style.css b/packages/effects/plugins/src/tiptap/style.css new file mode 100644 index 000000000..90e9a28c0 --- /dev/null +++ b/packages/effects/plugins/src/tiptap/style.css @@ -0,0 +1,56 @@ +@reference "@vben-core/design/theme"; + +.vben-tiptap-content > * + * { + @apply mt-3; +} + +.vben-tiptap-content h1 { + @apply text-2xl font-bold leading-[1.4]; +} + +.vben-tiptap-content h2 { + @apply text-xl font-bold leading-[1.45]; +} + +.vben-tiptap-content h3 { + @apply text-lg font-semibold leading-[1.5]; +} + +.vben-tiptap-content h4 { + @apply text-base font-semibold leading-[1.55]; +} + +.vben-tiptap-content ul { + @apply list-disc pl-6; +} + +.vben-tiptap-content ol { + @apply list-decimal pl-6; +} + +.vben-tiptap-content blockquote { + @apply border-l-4 border-primary pl-4 text-muted-foreground; +} + +.vben-tiptap-content a { + @apply text-primary underline decoration-1 underline-offset-[3px]; +} + +.vben-tiptap-content code { + @apply rounded-[0.45rem] border border-border bg-secondary px-[0.35rem] py-[0.15rem] text-[0.9em] text-primary; +} + +.vben-tiptap-content pre { + @apply overflow-x-auto rounded-[0.9rem] border border-border bg-popover p-4 text-popover-foreground; +} + +.vben-tiptap-content pre code { + @apply border-none bg-transparent p-0 text-inherit; +} + +.vben-tiptap-content img, +.vben-tiptap-content .vben-tiptap__image { + @apply my-4 block h-auto rounded-2xl border border-border; + + max-width: min(100%, 640px); +} diff --git a/packages/effects/plugins/src/tiptap/tiptap.vue b/packages/effects/plugins/src/tiptap/tiptap.vue index 6c297a42f..a268ecf76 100644 --- a/packages/effects/plugins/src/tiptap/tiptap.vue +++ b/packages/effects/plugins/src/tiptap/tiptap.vue @@ -7,15 +7,17 @@ import type { import { computed, onBeforeUnmount, watch } from 'vue'; -import { Check, ChevronDown } from '@vben/icons'; +import { Check, ChevronDown, Eye } from '@vben/icons'; import { $t } from '@vben/locales'; +import { useVbenModal } from '@vben-core/popup-ui'; import { VbenIconButton, VbenPopover } from '@vben-core/shadcn-ui'; import { cn } from '@vben-core/shared/utils'; import { EditorContent, useEditor } from '@tiptap/vue-3'; import { createDefaultTiptapExtensions } from './extensions'; +import Preview from './preview.vue'; import { createToolbarGroups } from './toolbar'; import { useTiptapToolbar } from './use-tiptap-toolbar'; @@ -24,6 +26,7 @@ const props = withDefaults(defineProps(), { extensions: undefined, minHeight: 240, placeholder: $t('ui.tiptap.placeholder'), + previewable: true, toolbar: true, }); @@ -39,7 +42,7 @@ const contentMinHeight = computed(() => : props.minHeight, ); const tiptapContentClass = cn( - 'vben-tiptap__content', + 'vben-tiptap-content vben-tiptap__content', 'min-h-(--vben-tiptap-min-height) leading-7 text-foreground outline-none', ); @@ -74,6 +77,13 @@ const editor = useEditor({ const toolbarGroups = computed(() => { return createToolbarGroups(); }); +const previewContent = computed( + () => editor.value?.getHTML() ?? modelValue.value, +); +const [PreviewModal, previewModalApi] = useVbenModal({ + footer: false, + fullscreenButton: false, +}); const { applyPaletteColor, canRunAction, @@ -92,6 +102,10 @@ const { editor, }); +function openPreviewModal() { + previewModalApi.open(); +} + watch( () => props.editable, (editable) => { @@ -244,67 +258,36 @@ onBeforeUnmount(() => { class="ml-1 h-5 w-px bg-border" > +
+ + + +
+ + +