UNPKG

claritykit-svelte

Version:

A comprehensive Svelte component library focused on accessibility, ADHD-optimized design, developer experience, and full SSR compatibility

176 lines (175 loc) 6.68 kB
import { Node, mergeAttributes } from '@tiptap/core'; export const BlockTransclusion = Node.create({ name: 'blockTransclusion', addOptions() { return { HTMLAttributes: { class: 'block-transclusion', }, renderTransclusion: async (blockId) => { // This would fetch the actual block content // For now, return a placeholder return `<div class="transclusion-content">Content of block ${blockId}</div>`; }, }; }, group: 'block', atom: true, addAttributes() { return { blockId: { default: null, parseHTML: (element) => element.getAttribute('data-block-id'), renderHTML: (attributes) => { if (!attributes.blockId) { return {}; } return { 'data-block-id': attributes.blockId, }; }, }, preview: { default: true, parseHTML: (element) => element.getAttribute('data-preview') === 'true', renderHTML: (attributes) => { return { 'data-preview': attributes.preview ? 'true' : 'false', }; }, }, }; }, parseHTML() { return [ { tag: 'div[data-block-id].block-transclusion', getAttrs: (element) => { const blockId = element.getAttribute('data-block-id'); const preview = element.getAttribute('data-preview') === 'true'; return blockId ? { blockId, preview } : false; }, }, ]; }, renderHTML({ HTMLAttributes }) { return [ 'div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { class: 'block-transclusion', 'data-type': 'block-transclusion', role: 'region', 'aria-label': `Transcluded content from block ${HTMLAttributes['data-block-id']}`, }), [ 'div', { class: 'transclusion-header' }, [ 'span', { class: 'transclusion-indicator' }, '📎', ], [ 'span', { class: 'transclusion-label' }, `Block ${HTMLAttributes['data-block-id']}`, ], ], [ 'div', { class: 'transclusion-content' }, `Loading content from block ${HTMLAttributes['data-block-id']}...`, ], ]; }, addCommands() { return { insertBlockTransclusion: (attributes) => ({ commands }) => { return commands.insertContent({ type: this.name, attrs: attributes, }); }, updateBlockTransclusion: (attributes) => ({ commands }) => { return commands.updateAttributes(this.name, attributes); }, }; }, addKeyboardShortcuts() { return { 'Mod-Shift-t': () => { // This would open a block selector for transclusion return this.editor.commands.insertBlockTransclusion({ blockId: 'placeholder' }); }, }; }, addNodeView() { return ({ node, HTMLAttributes, getPos, editor }) => { const dom = document.createElement('div'); dom.className = 'block-transclusion-wrapper'; const blockId = node.attrs.blockId; const preview = node.attrs.preview; // Create the transclusion container const container = document.createElement('div'); container.className = 'block-transclusion'; container.setAttribute('data-block-id', blockId); container.setAttribute('data-preview', preview.toString()); // Header with indicator and controls const header = document.createElement('div'); header.className = 'transclusion-header'; header.innerHTML = ` <span class="transclusion-indicator">📎</span> <span class="transclusion-label">Block ${blockId}</span> <button class="transclusion-toggle" title="Toggle preview">👁️</button> `; // Content area const content = document.createElement('div'); content.className = 'transclusion-content'; content.innerHTML = 'Loading...'; // Load the transcluded content this.options.renderTransclusion(blockId).then((html) => { content.innerHTML = html; }); // Toggle preview functionality const toggleButton = header.querySelector('.transclusion-toggle'); toggleButton?.addEventListener('click', () => { const newPreview = !preview; if (typeof getPos === 'function') { editor.commands.updateAttributes(this.name, { preview: newPreview }); } }); container.appendChild(header); if (preview) { container.appendChild(content); } dom.appendChild(container); return { dom, update: (updatedNode) => { if (updatedNode.type !== this.type) { return false; } // Update the node view when attributes change const newBlockId = updatedNode.attrs.blockId; const newPreview = updatedNode.attrs.preview; if (newBlockId !== blockId) { // Reload content for new block this.options.renderTransclusion(newBlockId).then((html) => { content.innerHTML = html; }); } // Update preview visibility if (newPreview !== preview) { if (newPreview) { container.appendChild(content); } else { content.remove(); } } return true; }, }; }; }, });