tiptap/packages/core/src/commands/toggleNode.ts
Arnau Gómez Farell 89bd9c7d29
Fix/enforce-type-imports-so-that-bundler-ignores-types (#6132)
* fix: enforce type imports so that the bundler ignores types

* chore: add changeset

* fix: export types with export type keyword
2025-03-03 15:15:30 +01:00

48 lines
1.7 KiB
TypeScript

import type { NodeType } from '@tiptap/pm/model'
import { getNodeType } from '../helpers/getNodeType.js'
import { isNodeActive } from '../helpers/isNodeActive.js'
import type { RawCommands } from '../types.js'
declare module '@tiptap/core' {
interface Commands<ReturnType> {
toggleNode: {
/**
* Toggle a node with another node.
* @param typeOrName The type or name of the node.
* @param toggleTypeOrName The type or name of the node to toggle.
* @param attributes The attributes of the node.
* @example editor.commands.toggleNode('heading', 'paragraph')
*/
toggleNode: (
typeOrName: string | NodeType,
toggleTypeOrName: string | NodeType,
attributes?: Record<string, any>,
) => ReturnType
}
}
}
export const toggleNode: RawCommands['toggleNode'] =
(typeOrName, toggleTypeOrName, attributes = {}) =>
({ state, commands }) => {
const type = getNodeType(typeOrName, state.schema)
const toggleType = getNodeType(toggleTypeOrName, state.schema)
const isActive = isNodeActive(state, type, attributes)
let attributesToCopy: Record<string, any> | undefined
if (state.selection.$anchor.sameParent(state.selection.$head)) {
// only copy attributes if the selection is pointing to a node of the same type
attributesToCopy = state.selection.$anchor.parent.attrs
}
if (isActive) {
return commands.setNode(toggleType, attributesToCopy)
}
// If the node is not active, we want to set the new node type with the given attributes
// Copying over the attributes from the current node if the selection is pointing to a node of the same type
return commands.setNode(type, { ...attributesToCopy, ...attributes })
}