CMS: Put Documents component in a tiptap node
This commit is contained in:
parent
b52a1f8ae2
commit
73b6343a43
2 changed files with 91 additions and 8 deletions
|
|
@ -215,6 +215,48 @@ function insertVerse() {
|
|||
}).run()
|
||||
}
|
||||
|
||||
function insertGeneralResources() {
|
||||
editor.value?.chain().focus().insertContent({
|
||||
type: 'generalResources',
|
||||
attrs: { useDocuments: false, layout: 'on-sidebar-page' }
|
||||
}).run()
|
||||
}
|
||||
|
||||
function toggleGeneralResourcesUseDocuments() {
|
||||
const e = editor.value
|
||||
if (!e) return
|
||||
const current = e.getAttributes('generalResources')
|
||||
e.chain().focus().updateAttributes('generalResources', {
|
||||
useDocuments: !current.useDocuments
|
||||
}).run()
|
||||
}
|
||||
|
||||
function setGeneralResourcesLayout(layout: 'on-sidebar-page' | 'on-page') {
|
||||
editor.value?.chain().focus().updateAttributes('generalResources', { layout }).run()
|
||||
}
|
||||
|
||||
function generalResourcesAttr<K extends 'useDocuments' | 'layout'>(key: K): unknown {
|
||||
return editor.value?.getAttributes('generalResources')?.[key]
|
||||
}
|
||||
|
||||
const customNodeMenuItems = computed(() => [
|
||||
{
|
||||
label: 'UUPG list',
|
||||
icon: 'i-lucide-globe',
|
||||
onSelect: () => insertUupgsList()
|
||||
},
|
||||
{
|
||||
label: 'Verse',
|
||||
icon: 'i-lucide-book-open',
|
||||
onSelect: () => insertVerse()
|
||||
},
|
||||
{
|
||||
label: 'Adoption resources',
|
||||
icon: 'i-lucide-library',
|
||||
onSelect: () => insertGeneralResources()
|
||||
}
|
||||
])
|
||||
|
||||
// Clicks on the padding area around the ProseMirror content don't move
|
||||
// the cursor by default. Forward those clicks to the editor and focus
|
||||
// at end-of-doc so the click anywhere inside the body area starts editing.
|
||||
|
|
@ -278,8 +320,44 @@ function onBodyClick(e: MouseEvent) {
|
|||
</UPopover>
|
||||
<UButton size="xs" variant="ghost" color="neutral" icon="i-lucide-image" aria-label="Image" :loading="uploading" @click="insertImage" />
|
||||
<UButton size="xs" variant="ghost" color="neutral" icon="i-lucide-youtube" aria-label="YouTube" @click="insertYoutube" />
|
||||
<UButton size="xs" variant="ghost" :color="isActive('uupgsList') ? 'primary' : 'neutral'" icon="i-lucide-globe" label="UUPG list" aria-label="Insert UUPG list" @click="insertUupgsList" />
|
||||
<UButton size="xs" variant="ghost" :color="isActive('verse') ? 'primary' : 'neutral'" icon="i-lucide-book-open" label="Verse" aria-label="Insert verse" @click="insertVerse" />
|
||||
<UDropdownMenu :items="customNodeMenuItems">
|
||||
<UButton
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
:color="isActive('uupgsList') || isActive('verse') || isActive('generalResources') ? 'primary' : 'neutral'"
|
||||
icon="i-lucide-plus"
|
||||
label="Insert"
|
||||
trailing-icon="i-lucide-chevron-down"
|
||||
aria-label="Insert custom block"
|
||||
/>
|
||||
</UDropdownMenu>
|
||||
<template v-if="isActive('generalResources')">
|
||||
<div class="w-px bg-(--ui-border) mx-1" />
|
||||
<UButton
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
:color="generalResourcesAttr('useDocuments') ? 'primary' : 'neutral'"
|
||||
:label="generalResourcesAttr('useDocuments') ? 'Documents list' : 'General resources'"
|
||||
aria-label="Toggle list type"
|
||||
@click="toggleGeneralResourcesUseDocuments"
|
||||
/>
|
||||
<UButton
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
:color="generalResourcesAttr('layout') === 'on-sidebar-page' ? 'primary' : 'neutral'"
|
||||
label="Sidebar"
|
||||
aria-label="Layout: on a sidebar page"
|
||||
@click="setGeneralResourcesLayout('on-sidebar-page')"
|
||||
/>
|
||||
<UButton
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
:color="generalResourcesAttr('layout') === 'on-page' ? 'primary' : 'neutral'"
|
||||
label="Full page"
|
||||
aria-label="Layout: on a full page"
|
||||
@click="setGeneralResourcesLayout('on-page')"
|
||||
/>
|
||||
</template>
|
||||
<div class="w-px bg-(--ui-border) mx-1" />
|
||||
<UButton size="xs" variant="ghost" color="neutral" icon="i-lucide-undo-2" aria-label="Undo" @click="cmd(e => e.chain().focus().undo().run())" />
|
||||
<UButton size="xs" variant="ghost" color="neutral" icon="i-lucide-redo-2" aria-label="Redo" @click="cmd(e => e.chain().focus().redo().run())" />
|
||||
|
|
@ -315,7 +393,8 @@ function onBodyClick(e: MouseEvent) {
|
|||
.tiptap-body :deep(iframe) { max-width: 100%; }
|
||||
.tiptap-body :deep(.ProseMirror:focus) { outline: none; }
|
||||
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip) {
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip),
|
||||
.tiptap-body :deep(.doxa-general-resources-editor-chip) {
|
||||
display: block;
|
||||
margin: 0.75rem 0;
|
||||
padding: 0.75rem 1rem;
|
||||
|
|
@ -326,19 +405,23 @@ function onBodyClick(e: MouseEvent) {
|
|||
user-select: none;
|
||||
cursor: grab;
|
||||
}
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip.is-selected) {
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip.is-selected),
|
||||
.tiptap-body :deep(.doxa-general-resources-editor-chip.is-selected) {
|
||||
outline: 2px solid var(--ui-primary);
|
||||
outline-offset: 1px;
|
||||
}
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip__header) {
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip__header),
|
||||
.tiptap-body :deep(.doxa-general-resources-editor-chip__header) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip__icon) { font-size: 1rem; }
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip__detail) {
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip__icon),
|
||||
.tiptap-body :deep(.doxa-general-resources-editor-chip__icon) { font-size: 1rem; }
|
||||
.tiptap-body :deep(.doxa-uupgs-list-editor-chip__detail),
|
||||
.tiptap-body :deep(.doxa-general-resources-editor-chip__detail) {
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--ui-text-muted);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ export const GeneralResourcesNode = Node.create({
|
|||
const paintFrom = (n: typeof node) => {
|
||||
const attrs: Record<string, any> = n.attrs
|
||||
const parts: string[] = []
|
||||
parts.push(attrs.useDocuments ? 'documents list' : 'general resources list')
|
||||
parts.push(attrs.useDocuments ? 'documents list' : 'adoption resources list')
|
||||
if (attrs.layout && attrs.layout !== 'on-sidebar-page') parts.push(`layout: ${attrs.layout}`)
|
||||
const detail = parts.join(' · ')
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue