claritykit-svelte
Version:
A comprehensive Svelte component library focused on accessibility, ADHD-optimized design, developer experience, and full SSR compatibility
78 lines (77 loc) • 2.68 kB
JavaScript
/**
* Create a TipTap 3 compatible node view that renders a Svelte component
*/
export function createSvelteNodeView(options) {
const { component: Component, as = 'div', className, tag = 'div' } = options;
return ({ node, editor, getPos, decorations, selected }) => {
// Create container element
const container = document.createElement(tag);
if (className) {
container.className = className;
}
let svelteComponent = null;
const updateAttributes = (attributes) => {
const pos = getPos();
if (pos !== undefined) {
const transaction = editor.view.state.tr.setNodeMarkup(pos, undefined, {
...node.attrs,
...attributes,
});
editor.view.dispatch(transaction);
}
};
// Mount the Svelte component
const mount = () => {
try {
svelteComponent = new Component({
target: container,
props: {
node,
editor,
getPos,
decorations,
selected,
updateAttributes,
},
});
}
catch (error) {
console.error('Failed to mount Svelte component in node view:', error);
container.innerHTML = '<div class="error">Failed to load component</div>';
}
};
const update = (updatedNode, updatedDecorations, updatedSelected) => {
if (updatedNode.type !== node.type) {
return false;
}
// Update the component props
if (svelteComponent && svelteComponent.$set) {
svelteComponent.$set({
node: updatedNode,
decorations: updatedDecorations,
selected: updatedSelected,
updateAttributes,
});
}
return true;
};
const destroy = () => {
if (svelteComponent) {
svelteComponent.$destroy();
svelteComponent = null;
}
};
// Initial mount
mount();
return {
dom: container,
update,
destroy,
ignoreMutation: (mutation) => {
// Allow Svelte to handle its own mutations
return !container.contains(mutation.target) ||
container === mutation.target;
},
};
};
}