@tiptap/extension-drag-handle 3.22.4 → 3.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +341 -57
- package/dist/index.d.ts +341 -57
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/src/drag-handle.ts +19 -15
- package/src/types/options.ts +280 -32
- package/src/types/rules.ts +46 -14
package/dist/index.d.ts
CHANGED
|
@@ -5,42 +5,76 @@ import { EditorView } from '@tiptap/pm/view';
|
|
|
5
5
|
import { PluginKey, Plugin } from '@tiptap/pm/state';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Context provided to each rule
|
|
9
|
-
*
|
|
8
|
+
* Context provided to each rule evaluation function.
|
|
9
|
+
*
|
|
10
|
+
* Contains information about the node being evaluated and its position in the
|
|
11
|
+
* ProseMirror document tree. This is the full context available for making
|
|
12
|
+
* scoring decisions in custom `DragHandleRule` implementations.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Typical usage in a custom rule
|
|
16
|
+
* evaluate: ({ node, parent, depth, isFirst }) => {
|
|
17
|
+
* if (parent?.type.name === 'listItem' && isFirst) {
|
|
18
|
+
* return 1000 // exclude first child of list items
|
|
19
|
+
* }
|
|
20
|
+
* if (depth > 3) {
|
|
21
|
+
* return depth * 200 // deprioritize deep nesting
|
|
22
|
+
* }
|
|
23
|
+
* return 0
|
|
24
|
+
* }
|
|
10
25
|
*/
|
|
11
26
|
interface RuleContext {
|
|
12
|
-
/** The node being evaluated */
|
|
27
|
+
/** The ProseMirror node being evaluated as a potential drag target */
|
|
13
28
|
node: Node;
|
|
14
29
|
/** Absolute position of the node in the document */
|
|
15
30
|
pos: number;
|
|
16
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Depth in the document tree (0 = document root).
|
|
33
|
+
* A paragraph inside a listItem inside a bulletList has depth 3.
|
|
34
|
+
*/
|
|
17
35
|
depth: number;
|
|
18
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Parent node of the node being evaluated.
|
|
38
|
+
* `null` if the node is the document root (depth 0).
|
|
39
|
+
*/
|
|
19
40
|
parent: Node | null;
|
|
20
|
-
/** This node's index among
|
|
41
|
+
/** This node's index among its parent's children (0-based) */
|
|
21
42
|
index: number;
|
|
22
|
-
/** Convenience: true
|
|
43
|
+
/** Convenience: `true` when this node is the first child of its parent (index === 0) */
|
|
23
44
|
isFirst: boolean;
|
|
24
|
-
/** Convenience: true
|
|
45
|
+
/** Convenience: `true` when this node is the last child of its parent */
|
|
25
46
|
isLast: boolean;
|
|
26
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* The resolved position for advanced ProseMirror queries.
|
|
49
|
+
* Allows access to ancestor nodes, child nodes, and document structure
|
|
50
|
+
* beyond the current node.
|
|
51
|
+
*/
|
|
27
52
|
$pos: ResolvedPos;
|
|
28
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* The editor view for DOM access if needed in custom rules.
|
|
55
|
+
* Can be used to access the editor DOM element, measure dimensions, etc.
|
|
56
|
+
*/
|
|
29
57
|
view: EditorView;
|
|
30
58
|
}
|
|
31
59
|
/**
|
|
32
60
|
* A rule that determines whether a node should be a drag target.
|
|
61
|
+
*
|
|
62
|
+
* Each rule receives a `RuleContext` and returns a numeric deduction.
|
|
63
|
+
* Multiple rules are evaluated in sequence; the total deduction is subtracted
|
|
64
|
+
* from the node's base score (1000). If the score drops to 0 or below,
|
|
65
|
+
* the node is excluded as a drag target.
|
|
33
66
|
*/
|
|
34
67
|
interface DragHandleRule {
|
|
35
68
|
/**
|
|
36
69
|
* Unique identifier for debugging and rule management.
|
|
70
|
+
* Choose a descriptive name that explains what the rule does.
|
|
37
71
|
*/
|
|
38
72
|
id: string;
|
|
39
73
|
/**
|
|
40
74
|
* Evaluate the node and return a score deduction.
|
|
41
75
|
*
|
|
42
|
-
* The return value is subtracted from the node's score (
|
|
43
|
-
* Higher deductions make the node less likely to be selected
|
|
76
|
+
* The return value is subtracted from the node's base score (1000).
|
|
77
|
+
* Higher deductions make the node less likely to be selected.
|
|
44
78
|
*
|
|
45
79
|
* @returns A number representing the score deduction:
|
|
46
80
|
* - `0` - No deduction, node remains fully eligible
|
|
@@ -59,7 +93,6 @@ interface DragHandleRule {
|
|
|
59
93
|
* @example
|
|
60
94
|
* // Prefer shallower nodes with partial deduction
|
|
61
95
|
* evaluate: ({ depth }) => {
|
|
62
|
-
* // Deeper nodes get small deductions, making shallower nodes win ties
|
|
63
96
|
* return depth * 50
|
|
64
97
|
* }
|
|
65
98
|
*
|
|
@@ -67,7 +100,6 @@ interface DragHandleRule {
|
|
|
67
100
|
* // Context-based partial deductions
|
|
68
101
|
* evaluate: ({ node, parent }) => {
|
|
69
102
|
* if (parent?.type.name === 'tableCell') {
|
|
70
|
-
* // Inside table cells, slightly prefer the cell over its content
|
|
71
103
|
* return node.type.name === 'paragraph' ? 100 : 0
|
|
72
104
|
* }
|
|
73
105
|
* return 0
|
|
@@ -78,39 +110,216 @@ interface DragHandleRule {
|
|
|
78
110
|
|
|
79
111
|
/**
|
|
80
112
|
* Edge detection presets for common use cases.
|
|
113
|
+
*
|
|
114
|
+
* Edge detection helps you grab parent containers (lists, blockquotes, etc.)
|
|
115
|
+
* by moving the cursor near the edge of a nested element. When the cursor is
|
|
116
|
+
* within the `threshold` zone of a configured edge, the scoring system deducts
|
|
117
|
+
* `strength * depth` from deeper nodes, making the outer container the easier
|
|
118
|
+
* target.
|
|
119
|
+
*
|
|
120
|
+
* In short: cursor near edge prefers parent; cursor centered prefers child.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* // Left/top edges, natural for LTR layouts (default)
|
|
124
|
+
* DragHandle.configure({
|
|
125
|
+
* nested: {
|
|
126
|
+
* edgeDetection: 'left',
|
|
127
|
+
* },
|
|
128
|
+
* })
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // Right/top edges, for RTL layouts
|
|
132
|
+
* DragHandle.configure({
|
|
133
|
+
* nested: {
|
|
134
|
+
* edgeDetection: 'right',
|
|
135
|
+
* },
|
|
136
|
+
* })
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* // No edge detection, cursor position does not affect scoring
|
|
140
|
+
* DragHandle.configure({
|
|
141
|
+
* nested: {
|
|
142
|
+
* edgeDetection: 'none',
|
|
143
|
+
* },
|
|
144
|
+
* })
|
|
81
145
|
*/
|
|
82
146
|
type EdgeDetectionPreset = 'left' | 'right' | 'both' | 'none';
|
|
83
147
|
/**
|
|
84
|
-
* Advanced edge detection configuration.
|
|
85
|
-
*
|
|
148
|
+
* Advanced edge detection configuration for fine-grained control.
|
|
149
|
+
*
|
|
150
|
+
* Use this interface when the preset strings (\`'left'\`, \`'right'\`, etc.) aren't
|
|
151
|
+
* enough and you need to customize **which edges**, **how wide the zone is**,
|
|
152
|
+
* or **how aggressive** the parent preference should be.
|
|
153
|
+
*
|
|
154
|
+
* Most users should use \`EdgeDetectionPreset\` strings instead of this interface.
|
|
155
|
+
* Only reach for this when you need precise control.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* // Wider edge zone, gentler deduction, top/bottom edges only
|
|
159
|
+
* DragHandle.configure({
|
|
160
|
+
* nested: {
|
|
161
|
+
* edgeDetection: {
|
|
162
|
+
* edges: ['top', 'bottom'],
|
|
163
|
+
* threshold: 24,
|
|
164
|
+
* strength: 300,
|
|
165
|
+
* },
|
|
166
|
+
* },
|
|
167
|
+
* })
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* // Aggressive left-edge only: narrow zone, strong deduction
|
|
171
|
+
* DragHandle.configure({
|
|
172
|
+
* nested: {
|
|
173
|
+
* edgeDetection: {
|
|
174
|
+
* edges: ['left'],
|
|
175
|
+
* threshold: 8,
|
|
176
|
+
* strength: 800,
|
|
177
|
+
* },
|
|
178
|
+
* },
|
|
179
|
+
* })
|
|
86
180
|
*/
|
|
87
181
|
interface EdgeDetectionConfig {
|
|
88
182
|
/**
|
|
89
183
|
* Which edges trigger parent preference.
|
|
184
|
+
* - `'left'`: Cursor within threshold pixels of the element's left edge
|
|
185
|
+
* - `'right'`: Cursor within threshold pixels of the element's right edge
|
|
186
|
+
* - `'top'`: Cursor within threshold pixels of the element's top edge
|
|
187
|
+
* - `'bottom'`: Cursor within threshold pixels of the element's bottom edge
|
|
188
|
+
*
|
|
90
189
|
* @default ['left', 'top']
|
|
91
190
|
*/
|
|
92
191
|
edges: Array<'left' | 'right' | 'top' | 'bottom'>;
|
|
93
192
|
/**
|
|
94
|
-
* Distance in pixels from edge
|
|
193
|
+
* Distance in pixels from the element edge that triggers the deduction.
|
|
194
|
+
*
|
|
195
|
+
* Think of this as the size of an invisible "edge zone" around the element.
|
|
196
|
+
* When the cursor is inside this zone, `strength * depth` is deducted from
|
|
197
|
+
* deeper nodes, making parent containers easier to grab.
|
|
198
|
+
*
|
|
199
|
+
* - **Higher value** (e.g., 24): The zone is wider, edge detection triggers
|
|
200
|
+
* even when the cursor is relatively far from the element's edge. Parent
|
|
201
|
+
* selection feels more "eager."
|
|
202
|
+
* - **Lower value** (e.g., 6): The zone is narrower, the cursor must be
|
|
203
|
+
* very close to the edge before parent preference kicks in. You need to be
|
|
204
|
+
* more deliberate to grab a parent container.
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* // threshold: 12 means the cursor must be within 12px of the edge
|
|
208
|
+
* // threshold: 24 doubles the trigger zone
|
|
209
|
+
*
|
|
95
210
|
* @default 12
|
|
96
211
|
*/
|
|
97
212
|
threshold: number;
|
|
98
213
|
/**
|
|
99
|
-
* How strongly to prefer parent (higher = stronger preference).
|
|
100
|
-
*
|
|
214
|
+
* How strongly to prefer parent nodes near edges (higher = stronger preference).
|
|
215
|
+
*
|
|
216
|
+
* The deduction formula is: `strength * depth`. This means the penalty grows
|
|
217
|
+
* linearly with nesting depth, making deeply nested children less attractive
|
|
218
|
+
* targets when you're near an edge, exactly what you want when trying to
|
|
219
|
+
* grab the outer list rather than the inner paragraph.
|
|
220
|
+
*
|
|
221
|
+
* **Visual guide, default strength (500):**
|
|
222
|
+
* ```
|
|
223
|
+
* Depth | Deduction | Eligible?
|
|
224
|
+
* ──────┼───────────┼──────────
|
|
225
|
+
* 1 | 500 │ Yes, still a valid target
|
|
226
|
+
* 2 | 1000 │ No, penalty matches base score
|
|
227
|
+
* 3 | 1500 │ No, penalty exceeds base score
|
|
228
|
+
* 4 | 2000 │ No, deeply buried
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* **Lower strength (200):**
|
|
232
|
+
* ```
|
|
233
|
+
* Depth | Deduction | Eligible?
|
|
234
|
+
* ──────┼───────────┼──────────
|
|
235
|
+
* 1 | 200 │ Yes
|
|
236
|
+
* 2 | 400 │ Yes
|
|
237
|
+
* 3 | 600 │ Yes
|
|
238
|
+
* 4 | 800 │ Yes (but parent still preferred)
|
|
239
|
+
* 5 | 1000 │ No, excluded at threshold
|
|
240
|
+
* ```
|
|
241
|
+
* Good when you want edge detection to nudge toward parents without
|
|
242
|
+
* excluding typical nesting depths.
|
|
243
|
+
*
|
|
244
|
+
* **Higher strength (1000):**
|
|
245
|
+
* ```
|
|
246
|
+
* Depth | Deduction | Eligible?
|
|
247
|
+
* ──────┼───────────┼──────────
|
|
248
|
+
* 1 | 1000 │ No, excluded at threshold
|
|
249
|
+
* ```
|
|
250
|
+
* Every non-doc candidate near the edge is excluded from being a drag
|
|
251
|
+
* target. Use when you want edge detection to completely disable nested
|
|
252
|
+
* dragging near the edges and force root-level handles.
|
|
253
|
+
*
|
|
101
254
|
* @default 500
|
|
102
255
|
*/
|
|
103
256
|
strength: number;
|
|
104
257
|
}
|
|
105
258
|
/**
|
|
106
259
|
* Configuration for nested drag handle behavior.
|
|
260
|
+
*
|
|
261
|
+
* When enabled, the drag handle can target nodes at any depth in the document
|
|
262
|
+
* tree (not just top-level blocks). A rule-based scoring system evaluates all
|
|
263
|
+
* ancestor nodes at the cursor position and selects the best drag target.
|
|
264
|
+
*
|
|
265
|
+
* **How the scoring works:**
|
|
266
|
+
* 1. Each ancestor node at the cursor position starts with a base score of 1000
|
|
267
|
+
* 2. Default rules are applied first (subtracting deductions for lists, tables, etc.)
|
|
268
|
+
* 3. Your custom rules are applied next (for app-specific logic)
|
|
269
|
+
* 4. Edge detection adds a final deduction (`strength * depth`) when near element edges
|
|
270
|
+
* 5. The highest-scoring node wins; ties are broken by depth (deeper nodes win)
|
|
271
|
+
* 6. Any node with a score of 0 or below is excluded as a drag target
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* // Simple enable with sensible defaults
|
|
275
|
+
* DragHandle.configure({
|
|
276
|
+
* nested: true,
|
|
277
|
+
* })
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* // Full custom configuration
|
|
281
|
+
* DragHandle.configure({
|
|
282
|
+
* nested: {
|
|
283
|
+
* defaultRules: true,
|
|
284
|
+
* allowedContainers: ['bulletList', 'orderedList', 'blockquote'],
|
|
285
|
+
* edgeDetection: 'left',
|
|
286
|
+
* rules: [
|
|
287
|
+
* {
|
|
288
|
+
* id: 'myCustomRule',
|
|
289
|
+
* evaluate: ({ node }) =>
|
|
290
|
+
* node.type.name === 'myCustomBlock' ? 1000 : 0,
|
|
291
|
+
* },
|
|
292
|
+
* ],
|
|
293
|
+
* },
|
|
294
|
+
* })
|
|
107
295
|
*/
|
|
108
296
|
interface NestedOptions {
|
|
109
297
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
298
|
+
* Custom rules that determine which nodes are draggable.
|
|
299
|
+
*
|
|
300
|
+
* Rules are evaluated AFTER the default rules. Each rule receives a
|
|
301
|
+
* `RuleContext` and returns a score deduction:
|
|
302
|
+
* - `0`: No effect, node remains fully eligible
|
|
303
|
+
* - `1-999`: Partial deduction, node is less preferred but still eligible
|
|
304
|
+
* - `>= 1000`: Node is **excluded** from being a drag target
|
|
305
|
+
*
|
|
306
|
+
* Common use cases for custom rules:
|
|
307
|
+
* - Exclude specific node types from being draggable
|
|
308
|
+
* - Deprioritize certain nodes with partial deductions
|
|
309
|
+
* - Scope dragging to specific document structures
|
|
112
310
|
*
|
|
113
311
|
* @example
|
|
312
|
+
* // Exclude code blocks from being draggable
|
|
313
|
+
* rules: [
|
|
314
|
+
* {
|
|
315
|
+
* id: 'excludeCodeBlocks',
|
|
316
|
+
* evaluate: ({ node }) =>
|
|
317
|
+
* node.type.name === 'codeBlock' ? 1000 : 0,
|
|
318
|
+
* },
|
|
319
|
+
* ]
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* // Inside a custom "question" block, only allow dragging "alternative" children
|
|
114
323
|
* rules: [
|
|
115
324
|
* {
|
|
116
325
|
* id: 'onlyAlternatives',
|
|
@@ -122,57 +331,128 @@ interface NestedOptions {
|
|
|
122
331
|
* },
|
|
123
332
|
* },
|
|
124
333
|
* ]
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* // Deprioritize deeper nodes with partial deduction
|
|
337
|
+
* rules: [
|
|
338
|
+
* {
|
|
339
|
+
* id: 'preferShallow',
|
|
340
|
+
* evaluate: ({ depth }) => depth * 100,
|
|
341
|
+
* },
|
|
342
|
+
* ]
|
|
125
343
|
*/
|
|
126
344
|
rules?: DragHandleRule[];
|
|
127
345
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
346
|
+
* Whether to include the built-in default rules before your custom rules.
|
|
347
|
+
*
|
|
348
|
+
* The default rules handle common editor patterns:
|
|
349
|
+
* - \`listItemFirstChild\` -- Excludes the first child of listItem/taskItem
|
|
350
|
+
* (the content paragraph), so the list item itself is the drag target
|
|
351
|
+
* - \`listWrapperDeprioritize\` -- Excludes bulletList/orderedList wrappers,
|
|
352
|
+
* so individual list items are the default drag target
|
|
353
|
+
* - \`tableStructure\` -- Excludes tableRow, tableCell, tableHeader from dragging
|
|
354
|
+
* (table extensions handle their own drag behavior)
|
|
355
|
+
* - \`inlineContent\` -- Excludes inline nodes and text from being drag targets
|
|
356
|
+
*
|
|
357
|
+
* Set to `false` to disable all default rules and use only your custom `rules`.
|
|
358
|
+
* This is useful when the default behavior conflicts with your custom setup.
|
|
130
359
|
*
|
|
131
360
|
* @default true
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* // Use only your own rule, no defaults
|
|
364
|
+
* nested: {
|
|
365
|
+
* defaultRules: false,
|
|
366
|
+
* rules: [{
|
|
367
|
+
* id: 'onlyParagraphs',
|
|
368
|
+
* evaluate: ({ node }) =>
|
|
369
|
+
* node.type.name === 'paragraph' ? 0 : 1000,
|
|
370
|
+
* }],
|
|
371
|
+
* }
|
|
132
372
|
*/
|
|
133
373
|
defaultRules?: boolean;
|
|
134
374
|
/**
|
|
135
|
-
* Restrict nested drag handles to specific container types.
|
|
136
|
-
*
|
|
375
|
+
* Restrict nested drag handles to specific container node types.
|
|
376
|
+
*
|
|
377
|
+
* When set, nested dragging only activates when the cursor is inside one of
|
|
378
|
+
* the specified node types (at any ancestor level). When the cursor is
|
|
379
|
+
* outside these containers, the drag handle hides entirely for nested
|
|
380
|
+
* content positioned inside those regions.
|
|
381
|
+
*
|
|
382
|
+
* This is useful for scoping nested drag handles to specific editor regions
|
|
383
|
+
* (e.g., lists and blockquotes) while keeping simpler blocks (headings,
|
|
384
|
+
* paragraphs) working with only top-level handles.
|
|
137
385
|
*
|
|
138
386
|
* @example
|
|
139
|
-
* // Only enable nested dragging
|
|
140
|
-
* allowedContainers: ['bulletList', 'orderedList'
|
|
387
|
+
* // Only enable nested dragging inside lists
|
|
388
|
+
* allowedContainers: ['bulletList', 'orderedList']
|
|
389
|
+
*
|
|
390
|
+
* @example
|
|
391
|
+
* // Enable nested dragging inside lists and blockquotes
|
|
392
|
+
* allowedContainers: ['bulletList', 'orderedList', 'blockquote']
|
|
141
393
|
*/
|
|
142
394
|
allowedContainers?: string[];
|
|
143
395
|
/**
|
|
144
|
-
*
|
|
396
|
+
* Controls when the drag handle prefers a parent node over a deeply nested
|
|
397
|
+
* child node, based on cursor proximity to element edges.
|
|
398
|
+
*
|
|
399
|
+
* When the cursor is near a configured edge of a nested element, the scoring
|
|
400
|
+
* system deducts \`strength * depth\` from deeper nodes, making the parent
|
|
401
|
+
* container (like an entire list) easier to grab.
|
|
145
402
|
*
|
|
146
|
-
* Presets
|
|
147
|
-
* - `'left'` (default)
|
|
148
|
-
* - `'right'
|
|
149
|
-
* - `'both'
|
|
150
|
-
* -
|
|
403
|
+
* **Presets (quick and simple):**
|
|
404
|
+
* - `'left'` (default): Cursor near left or top edge → prefer parent (LTR)
|
|
405
|
+
* - `'right'`: Cursor near right or top edge → prefer parent (RTL)
|
|
406
|
+
* - `'both'`: Cursor near left, right, or top edge → prefer parent
|
|
407
|
+
* - \`'none'\`: Disabled, cursor position does not affect scoring at all
|
|
151
408
|
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
409
|
+
* **Fine-tuned object (full control):**
|
|
410
|
+
* Pass a partial `EdgeDetectionConfig` to override only what you need:
|
|
411
|
+
* - `edges`: Which element edges trigger parent preference (default: `['left', 'top']`)
|
|
412
|
+
* - `threshold`: Width of the edge zone in pixels (default: `12`). Higher = easier to trigger.
|
|
413
|
+
* - `strength`: Deduction multiplier per depth level (default: `500`). Higher = stronger parent preference.
|
|
414
|
+
*
|
|
415
|
+
* The effective deduction when near an edge is `strength * depth`, so deeper
|
|
416
|
+
* nesting always gets penalized more, you naturally grab the outer wrapper.
|
|
154
417
|
*
|
|
155
418
|
* @default 'left'
|
|
156
419
|
*
|
|
157
420
|
* @example
|
|
158
|
-
* //
|
|
159
|
-
* edgeDetection: { threshold:
|
|
421
|
+
* // Just widen the trigger zone to 24px
|
|
422
|
+
* edgeDetection: { threshold: 24 }
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* // Top/bottom edges only, very aggressive parent preference
|
|
426
|
+
* edgeDetection: {
|
|
427
|
+
* edges: ['top', 'bottom'],
|
|
428
|
+
* threshold: 30,
|
|
429
|
+
* strength: 1000,
|
|
430
|
+
* }
|
|
431
|
+
*
|
|
432
|
+
* @example
|
|
433
|
+
* // Gentle edge detection, nudges toward parents without blocking typical depths
|
|
434
|
+
* edgeDetection: {
|
|
435
|
+
* threshold: 6,
|
|
436
|
+
* strength: 200,
|
|
437
|
+
* }
|
|
160
438
|
*/
|
|
161
439
|
edgeDetection?: EdgeDetectionPreset | Partial<EdgeDetectionConfig>;
|
|
162
440
|
}
|
|
163
441
|
/**
|
|
164
|
-
*
|
|
442
|
+
* Fully resolved nested drag handle options after normalization.
|
|
443
|
+
* Produced by `normalizeNestedOptions()` from user-provided `NestedOptions`
|
|
444
|
+
* or a boolean flag. This is the internal representation consumed by the plugin.
|
|
165
445
|
*/
|
|
166
446
|
interface NormalizedNestedOptions {
|
|
167
447
|
/** Whether nested drag handles are enabled */
|
|
168
448
|
enabled: boolean;
|
|
169
|
-
/** Custom rules to apply */
|
|
449
|
+
/** Custom rules to apply (combined with default rules if `defaultRules` is true) */
|
|
170
450
|
rules: DragHandleRule[];
|
|
171
|
-
/** Whether
|
|
451
|
+
/** Whether the built-in default rules are included alongside custom rules */
|
|
172
452
|
defaultRules: boolean;
|
|
173
|
-
/** Allowed container node types
|
|
453
|
+
/** Allowed container node types, or `undefined` to allow all containers */
|
|
174
454
|
allowedContainers: string[] | undefined;
|
|
175
|
-
/**
|
|
455
|
+
/** Fully resolved edge detection configuration with all defaults applied */
|
|
176
456
|
edgeDetection: EdgeDetectionConfig;
|
|
177
457
|
}
|
|
178
458
|
|
|
@@ -214,24 +494,14 @@ interface DragHandleOptions {
|
|
|
214
494
|
/**
|
|
215
495
|
* Enable drag handles for nested content (list items, blockquotes, etc.).
|
|
216
496
|
*
|
|
217
|
-
* When enabled, the drag handle
|
|
218
|
-
* top-level blocks. A rule-based scoring system
|
|
219
|
-
*
|
|
497
|
+
* When enabled, the drag handle appears for block nodes at any depth, not just
|
|
498
|
+
* top-level blocks. A rule-based scoring system evaluates all ancestor nodes
|
|
499
|
+
* at the cursor position and selects the best drag target.
|
|
220
500
|
*
|
|
221
501
|
* **Values:**
|
|
222
502
|
* - `false` (default): Only root-level blocks show drag handles
|
|
223
503
|
* - `true`: Enable with sensible defaults (left edge detection, default rules)
|
|
224
|
-
* - `NestedOptions`: Enable with custom configuration
|
|
225
|
-
*
|
|
226
|
-
* **Configuration options:**
|
|
227
|
-
* - `rules`: Custom rules to determine which nodes are draggable
|
|
228
|
-
* - `defaultRules`: Whether to include default rules (default: true)
|
|
229
|
-
* - `allowedContainers`: Restrict nested dragging to specific container types
|
|
230
|
-
* - `edgeDetection`: Control when to prefer parent over nested node
|
|
231
|
-
* - `'left'` (default): Prefer parent near left/top edges
|
|
232
|
-
* - `'right'`: Prefer parent near right/top edges (for RTL)
|
|
233
|
-
* - `'both'`: Prefer parent near any horizontal edge
|
|
234
|
-
* - `'none'`: Disable edge detection
|
|
504
|
+
* - `NestedOptions`: Enable with full custom configuration
|
|
235
505
|
*
|
|
236
506
|
* @default false
|
|
237
507
|
*
|
|
@@ -250,7 +520,7 @@ interface DragHandleOptions {
|
|
|
250
520
|
* })
|
|
251
521
|
*
|
|
252
522
|
* @example
|
|
253
|
-
* // With custom rules
|
|
523
|
+
* // With custom rules and edge detection disabled
|
|
254
524
|
* DragHandle.configure({
|
|
255
525
|
* nested: {
|
|
256
526
|
* rules: [{
|
|
@@ -260,6 +530,20 @@ interface DragHandleOptions {
|
|
|
260
530
|
* edgeDetection: 'none',
|
|
261
531
|
* },
|
|
262
532
|
* })
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* // Full configuration
|
|
536
|
+
* DragHandle.configure({
|
|
537
|
+
* nested: {
|
|
538
|
+
* defaultRules: true,
|
|
539
|
+
* allowedContainers: ['bulletList', 'orderedList', 'blockquote'],
|
|
540
|
+
* edgeDetection: { threshold: 20 },
|
|
541
|
+
* rules: [{
|
|
542
|
+
* id: 'preferShallow',
|
|
543
|
+
* evaluate: ({ depth }) => depth * 200,
|
|
544
|
+
* }],
|
|
545
|
+
* },
|
|
546
|
+
* })
|
|
263
547
|
*/
|
|
264
548
|
nested?: boolean | NestedOptions;
|
|
265
549
|
}
|