import type { DragHandleRule } from '../types/rules.js'
/**
* The first child inside a list item is the list item's content.
* It cannot be dragged separately - you drag the list item instead.
*
* Example: In `
Text
`, the paragraph is excluded,
* but the listItem is draggable.
*/
export const listItemFirstChild: DragHandleRule = {
id: 'listItemFirstChild',
evaluate: ({ parent, isFirst }) => {
if (!isFirst) {
return 0
}
const listItemTypes = ['listItem', 'taskItem']
if (parent && listItemTypes.includes(parent.type.name)) {
return 1000
}
return 0
},
}
/**
* Nodes that contain list items (listItem/taskItem) as direct children
* are deprioritized. This makes it easier to target individual list items
* rather than the entire list wrapper.
*
* This rule detects list wrappers dynamically by checking if the first child
* is a list item, rather than hardcoding wrapper type names.
*
* Users can still target the list wrapper by moving to the very edge
* where edge detection kicks in.
*/
export const listWrapperDeprioritize: DragHandleRule = {
id: 'listWrapperDeprioritize',
evaluate: ({ node }) => {
const listItemTypes = ['listItem', 'taskItem']
const firstChild = node.firstChild
if (firstChild && listItemTypes.includes(firstChild.type.name)) {
return 1000
}
return 0
},
}
/**
* Table rows, cells, and content inside table headers should never be drag targets.
* Table dragging is handled by table extensions. Only the table wrapper
* itself or content inside regular table cells should be draggable.
*/
export const tableStructure: DragHandleRule = {
id: 'tableStructure',
evaluate: ({ node, parent }) => {
const tableStructureTypes = ['tableRow', 'tableCell', 'tableHeader']
if (tableStructureTypes.includes(node.type.name)) {
return 1000
}
if (parent && parent.type.name === 'tableHeader') {
return 1000
}
return 0
},
}
/**
* Inline nodes (text, marks, inline atoms) should never be drag targets.
*/
export const inlineContent: DragHandleRule = {
id: 'inlineContent',
evaluate: ({ node }) => {
if (node.isInline || node.isText) {
return 1000
}
return 0
},
}
/**
* All default rules.
* Users can extend these or replace them entirely.
*/
export const defaultRules: DragHandleRule[] = [
listItemFirstChild,
listWrapperDeprioritize,
tableStructure,
inlineContent,
]