@tiptap/extension-details 2.24.1 → 3.0.0-beta.10
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/LICENSE.md +21 -0
- package/dist/index.cjs +372 -370
- package/dist/index.cjs.map +1 -1
- package/dist/{details.d.ts → index.d.cts} +5 -3
- package/dist/index.d.ts +35 -4
- package/dist/index.js +347 -367
- package/dist/index.js.map +1 -1
- package/package.json +13 -9
- package/src/details.ts +95 -120
- package/src/helpers/findClosestVisibleNode.ts +14 -8
- package/src/helpers/isNodeVisible.ts +1 -1
- package/src/helpers/setGapCursor.ts +7 -13
- package/dist/details.d.ts.map +0 -1
- package/dist/helpers/findClosestVisibleNode.d.ts +0 -9
- package/dist/helpers/findClosestVisibleNode.d.ts.map +0 -1
- package/dist/helpers/isNodeVisible.d.ts +0 -3
- package/dist/helpers/isNodeVisible.d.ts.map +0 -1
- package/dist/helpers/setGapCursor.d.ts +0 -3
- package/dist/helpers/setGapCursor.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.umd.js +0 -388
- package/dist/index.umd.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,386 +1,388 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
2
19
|
|
|
3
|
-
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Details: () => Details,
|
|
24
|
+
default: () => index_default
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
4
27
|
|
|
5
|
-
|
|
6
|
-
var
|
|
7
|
-
var
|
|
28
|
+
// src/details.ts
|
|
29
|
+
var import_core2 = require("@tiptap/core");
|
|
30
|
+
var import_state = require("@tiptap/pm/state");
|
|
8
31
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
32
|
+
// src/helpers/isNodeVisible.ts
|
|
33
|
+
var isNodeVisible = (position, editor) => {
|
|
34
|
+
const node = editor.view.domAtPos(position).node;
|
|
35
|
+
const isOpen = node.offsetParent !== null;
|
|
36
|
+
return isOpen;
|
|
13
37
|
};
|
|
14
38
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
39
|
+
// src/helpers/findClosestVisibleNode.ts
|
|
40
|
+
var findClosestVisibleNode = ($pos, predicate, editor) => {
|
|
41
|
+
for (let i = $pos.depth; i > 0; i -= 1) {
|
|
42
|
+
const node = $pos.node(i);
|
|
43
|
+
const match = predicate(node);
|
|
44
|
+
const isVisible = isNodeVisible($pos.start(i), editor);
|
|
45
|
+
if (match && isVisible) {
|
|
46
|
+
return {
|
|
47
|
+
pos: i > 0 ? $pos.before(i) : 0,
|
|
48
|
+
start: $pos.start(i),
|
|
49
|
+
depth: i,
|
|
50
|
+
node
|
|
51
|
+
};
|
|
28
52
|
}
|
|
53
|
+
}
|
|
29
54
|
};
|
|
30
55
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
// src/helpers/setGapCursor.ts
|
|
57
|
+
var import_core = require("@tiptap/core");
|
|
58
|
+
var import_gapcursor = require("@tiptap/pm/gapcursor");
|
|
59
|
+
var setGapCursor = (editor, direction) => {
|
|
60
|
+
const { state, view, extensionManager } = editor;
|
|
61
|
+
const { schema, selection } = state;
|
|
62
|
+
const { empty, $anchor } = selection;
|
|
63
|
+
const hasGapCursorExtension = !!extensionManager.extensions.find((extension) => extension.name === "gapCursor");
|
|
64
|
+
if (!empty || $anchor.parent.type !== schema.nodes.detailsSummary || !hasGapCursorExtension) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (direction === "right" && $anchor.parentOffset !== $anchor.parent.nodeSize - 2) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const details = (0, import_core.findParentNode)((node) => node.type === schema.nodes.details)(selection);
|
|
71
|
+
if (!details) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
const detailsContent = (0, import_core.findChildren)(details.node, (node) => node.type === schema.nodes.detailsContent);
|
|
75
|
+
if (!detailsContent.length) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const isOpen = isNodeVisible(details.start + detailsContent[0].pos + 1, editor);
|
|
79
|
+
if (isOpen) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
const $position = state.doc.resolve(details.pos + details.node.nodeSize);
|
|
83
|
+
const $validPosition = import_gapcursor.GapCursor.findFrom($position, 1, false);
|
|
84
|
+
if (!$validPosition) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
const { tr } = state;
|
|
88
|
+
const gapCursorSelection = new import_gapcursor.GapCursor($validPosition);
|
|
89
|
+
tr.setSelection(gapCursorSelection);
|
|
90
|
+
tr.scrollIntoView();
|
|
91
|
+
view.dispatch(tr);
|
|
92
|
+
return true;
|
|
68
93
|
};
|
|
69
94
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
95
|
+
// src/details.ts
|
|
96
|
+
var Details = import_core2.Node.create({
|
|
97
|
+
name: "details",
|
|
98
|
+
content: "detailsSummary detailsContent",
|
|
99
|
+
group: "block",
|
|
100
|
+
defining: true,
|
|
101
|
+
isolating: true,
|
|
102
|
+
// @ts-ignore: allowGapCursor is not a valid option by default, dts on build doesnt pick this up
|
|
103
|
+
allowGapCursor: false,
|
|
104
|
+
addOptions() {
|
|
105
|
+
return {
|
|
106
|
+
persist: false,
|
|
107
|
+
openClassName: "is-open",
|
|
108
|
+
HTMLAttributes: {}
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
addAttributes() {
|
|
112
|
+
if (!this.options.persist) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
open: {
|
|
117
|
+
default: false,
|
|
118
|
+
parseHTML: (element) => element.hasAttribute("open"),
|
|
119
|
+
renderHTML: ({ open }) => {
|
|
120
|
+
if (!open) {
|
|
121
|
+
return {};
|
|
122
|
+
}
|
|
123
|
+
return { open: "" };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
parseHTML() {
|
|
129
|
+
return [
|
|
130
|
+
{
|
|
131
|
+
tag: "details"
|
|
132
|
+
}
|
|
133
|
+
];
|
|
134
|
+
},
|
|
135
|
+
renderHTML({ HTMLAttributes }) {
|
|
136
|
+
return ["details", (0, import_core2.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes), 0];
|
|
137
|
+
},
|
|
138
|
+
addNodeView() {
|
|
139
|
+
return ({ editor, getPos, node, HTMLAttributes }) => {
|
|
140
|
+
const dom = document.createElement("div");
|
|
141
|
+
const attributes = (0, import_core2.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, {
|
|
142
|
+
"data-type": this.name
|
|
143
|
+
});
|
|
144
|
+
Object.entries(attributes).forEach(([key, value]) => dom.setAttribute(key, value));
|
|
145
|
+
const toggle = document.createElement("button");
|
|
146
|
+
toggle.type = "button";
|
|
147
|
+
dom.append(toggle);
|
|
148
|
+
const content = document.createElement("div");
|
|
149
|
+
dom.append(content);
|
|
150
|
+
const toggleDetailsContent = (setToValue) => {
|
|
151
|
+
if (setToValue !== void 0) {
|
|
152
|
+
if (setToValue) {
|
|
153
|
+
if (dom.classList.contains(this.options.openClassName)) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
dom.classList.add(this.options.openClassName);
|
|
157
|
+
} else {
|
|
158
|
+
if (!dom.classList.contains(this.options.openClassName)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
dom.classList.remove(this.options.openClassName);
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
dom.classList.toggle(this.options.openClassName);
|
|
165
|
+
}
|
|
166
|
+
const event = new Event("toggleDetailsContent");
|
|
167
|
+
const detailsContent = content.querySelector(':scope > div[data-type="detailsContent"]');
|
|
168
|
+
detailsContent == null ? void 0 : detailsContent.dispatchEvent(event);
|
|
169
|
+
};
|
|
170
|
+
if (node.attrs.open) {
|
|
171
|
+
setTimeout(() => toggleDetailsContent());
|
|
172
|
+
}
|
|
173
|
+
toggle.addEventListener("click", () => {
|
|
174
|
+
toggleDetailsContent();
|
|
85
175
|
if (!this.options.persist) {
|
|
86
|
-
|
|
176
|
+
editor.commands.focus(void 0, { scrollIntoView: false });
|
|
177
|
+
return;
|
|
87
178
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return {};
|
|
95
|
-
}
|
|
96
|
-
return { open: '' };
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
},
|
|
101
|
-
parseHTML() {
|
|
102
|
-
return [
|
|
103
|
-
{
|
|
104
|
-
tag: 'details',
|
|
105
|
-
},
|
|
106
|
-
];
|
|
107
|
-
},
|
|
108
|
-
renderHTML({ HTMLAttributes }) {
|
|
109
|
-
return [
|
|
110
|
-
'details',
|
|
111
|
-
core.mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
|
|
112
|
-
0,
|
|
113
|
-
];
|
|
114
|
-
},
|
|
115
|
-
addNodeView() {
|
|
116
|
-
return ({ editor, getPos, node, HTMLAttributes, }) => {
|
|
117
|
-
const dom = document.createElement('div');
|
|
118
|
-
const attributes = core.mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
|
|
119
|
-
'data-type': this.name,
|
|
120
|
-
});
|
|
121
|
-
Object.entries(attributes).forEach(([key, value]) => dom.setAttribute(key, value));
|
|
122
|
-
const toggle = document.createElement('button');
|
|
123
|
-
toggle.type = 'button';
|
|
124
|
-
dom.append(toggle);
|
|
125
|
-
const content = document.createElement('div');
|
|
126
|
-
dom.append(content);
|
|
127
|
-
const toggleDetailsContent = (setToValue) => {
|
|
128
|
-
if (setToValue !== undefined) {
|
|
129
|
-
if (setToValue) {
|
|
130
|
-
if (dom.classList.contains(this.options.openClassName)) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
dom.classList.add(this.options.openClassName);
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
if (!dom.classList.contains(this.options.openClassName)) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
dom.classList.remove(this.options.openClassName);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
dom.classList.toggle(this.options.openClassName);
|
|
144
|
-
}
|
|
145
|
-
const event = new Event('toggleDetailsContent');
|
|
146
|
-
const detailsContent = content.querySelector(':scope > div[data-type="detailsContent"]');
|
|
147
|
-
detailsContent === null || detailsContent === void 0 ? void 0 : detailsContent.dispatchEvent(event);
|
|
148
|
-
};
|
|
149
|
-
if (node.attrs.open) {
|
|
150
|
-
setTimeout(() => toggleDetailsContent());
|
|
179
|
+
if (editor.isEditable && typeof getPos === "function") {
|
|
180
|
+
const { from, to } = editor.state.selection;
|
|
181
|
+
editor.chain().command(({ tr }) => {
|
|
182
|
+
const pos = getPos();
|
|
183
|
+
if (pos === void 0) {
|
|
184
|
+
return false;
|
|
151
185
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
if (editor.isEditable && typeof getPos === 'function') {
|
|
160
|
-
const { from, to } = editor.state.selection;
|
|
161
|
-
editor
|
|
162
|
-
.chain()
|
|
163
|
-
.command(({ tr }) => {
|
|
164
|
-
const pos = getPos();
|
|
165
|
-
const currentNode = tr.doc.nodeAt(pos);
|
|
166
|
-
if ((currentNode === null || currentNode === void 0 ? void 0 : currentNode.type) !== this.type) {
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
tr.setNodeMarkup(pos, undefined, {
|
|
170
|
-
open: !currentNode.attrs.open,
|
|
171
|
-
});
|
|
172
|
-
return true;
|
|
173
|
-
})
|
|
174
|
-
.setTextSelection({
|
|
175
|
-
from,
|
|
176
|
-
to,
|
|
177
|
-
})
|
|
178
|
-
.focus(undefined, { scrollIntoView: false })
|
|
179
|
-
.run();
|
|
180
|
-
}
|
|
186
|
+
const currentNode = tr.doc.nodeAt(pos);
|
|
187
|
+
if ((currentNode == null ? void 0 : currentNode.type) !== this.type) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
tr.setNodeMarkup(pos, void 0, {
|
|
191
|
+
open: !currentNode.attrs.open
|
|
181
192
|
});
|
|
182
|
-
return
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const selectionDirection = oldState.selection.from < newState.selection.from
|
|
370
|
-
? 'forward'
|
|
371
|
-
: 'backward';
|
|
372
|
-
const correctedPosition = selectionDirection === 'forward'
|
|
373
|
-
? details.start + detailsSummary.pos
|
|
374
|
-
: details.pos + detailsSummary.pos + detailsSummary.node.nodeSize;
|
|
375
|
-
const selection = state.TextSelection.create(newState.doc, correctedPosition);
|
|
376
|
-
const transaction = newState.tr.setSelection(selection);
|
|
377
|
-
return transaction;
|
|
378
|
-
},
|
|
379
|
-
}),
|
|
380
|
-
];
|
|
381
|
-
},
|
|
193
|
+
return true;
|
|
194
|
+
}).setTextSelection({
|
|
195
|
+
from,
|
|
196
|
+
to
|
|
197
|
+
}).focus(void 0, { scrollIntoView: false }).run();
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
return {
|
|
201
|
+
dom,
|
|
202
|
+
contentDOM: content,
|
|
203
|
+
ignoreMutation(mutation) {
|
|
204
|
+
if (mutation.type === "selection") {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
return !dom.contains(mutation.target) || dom === mutation.target;
|
|
208
|
+
},
|
|
209
|
+
update: (updatedNode) => {
|
|
210
|
+
if (updatedNode.type !== this.type) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
if (updatedNode.attrs.open !== void 0) {
|
|
214
|
+
toggleDetailsContent(updatedNode.attrs.open);
|
|
215
|
+
}
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
},
|
|
221
|
+
addCommands() {
|
|
222
|
+
return {
|
|
223
|
+
setDetails: () => ({ state, chain }) => {
|
|
224
|
+
var _a;
|
|
225
|
+
const { schema, selection } = state;
|
|
226
|
+
const { $from, $to } = selection;
|
|
227
|
+
const range = $from.blockRange($to);
|
|
228
|
+
if (!range) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
const slice = state.doc.slice(range.start, range.end);
|
|
232
|
+
const match = schema.nodes.detailsContent.contentMatch.matchFragment(slice.content);
|
|
233
|
+
if (!match) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
const content = ((_a = slice.toJSON()) == null ? void 0 : _a.content) || [];
|
|
237
|
+
return chain().insertContentAt(
|
|
238
|
+
{ from: range.start, to: range.end },
|
|
239
|
+
{
|
|
240
|
+
type: this.name,
|
|
241
|
+
content: [
|
|
242
|
+
{
|
|
243
|
+
type: "detailsSummary"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
type: "detailsContent",
|
|
247
|
+
content
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
).setTextSelection(range.start + 2).run();
|
|
252
|
+
},
|
|
253
|
+
unsetDetails: () => ({ state, chain }) => {
|
|
254
|
+
const { selection, schema } = state;
|
|
255
|
+
const details = (0, import_core2.findParentNode)((node) => node.type === this.type)(selection);
|
|
256
|
+
if (!details) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
const detailsSummaries = (0, import_core2.findChildren)(details.node, (node) => node.type === schema.nodes.detailsSummary);
|
|
260
|
+
const detailsContents = (0, import_core2.findChildren)(details.node, (node) => node.type === schema.nodes.detailsContent);
|
|
261
|
+
if (!detailsSummaries.length || !detailsContents.length) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
const detailsSummary = detailsSummaries[0];
|
|
265
|
+
const detailsContent = detailsContents[0];
|
|
266
|
+
const from = details.pos;
|
|
267
|
+
const $from = state.doc.resolve(from);
|
|
268
|
+
const to = from + details.node.nodeSize;
|
|
269
|
+
const range = { from, to };
|
|
270
|
+
const content = detailsContent.node.content.toJSON() || [];
|
|
271
|
+
const defaultTypeForSummary = $from.parent.type.contentMatch.defaultType;
|
|
272
|
+
const summaryContent = defaultTypeForSummary == null ? void 0 : defaultTypeForSummary.create(null, detailsSummary.node.content).toJSON();
|
|
273
|
+
const mergedContent = [summaryContent, ...content];
|
|
274
|
+
return chain().insertContentAt(range, mergedContent).setTextSelection(from + 1).run();
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
},
|
|
278
|
+
addKeyboardShortcuts() {
|
|
279
|
+
return {
|
|
280
|
+
Backspace: () => {
|
|
281
|
+
const { schema, selection } = this.editor.state;
|
|
282
|
+
const { empty, $anchor } = selection;
|
|
283
|
+
if (!empty || $anchor.parent.type !== schema.nodes.detailsSummary) {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
if ($anchor.parentOffset !== 0) {
|
|
287
|
+
return this.editor.commands.command(({ tr }) => {
|
|
288
|
+
const from = $anchor.pos - 1;
|
|
289
|
+
const to = $anchor.pos;
|
|
290
|
+
tr.delete(from, to);
|
|
291
|
+
return true;
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return this.editor.commands.unsetDetails();
|
|
295
|
+
},
|
|
296
|
+
// Creates a new node below it if it is closed.
|
|
297
|
+
// Otherwise inside `DetailsContent`.
|
|
298
|
+
Enter: ({ editor }) => {
|
|
299
|
+
const { state, view } = editor;
|
|
300
|
+
const { schema, selection } = state;
|
|
301
|
+
const { $head } = selection;
|
|
302
|
+
if ($head.parent.type !== schema.nodes.detailsSummary) {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
const isVisible = isNodeVisible($head.after() + 1, editor);
|
|
306
|
+
const above = isVisible ? state.doc.nodeAt($head.after()) : $head.node(-2);
|
|
307
|
+
if (!above) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
const after = isVisible ? 0 : $head.indexAfter(-1);
|
|
311
|
+
const type = (0, import_core2.defaultBlockAt)(above.contentMatchAt(after));
|
|
312
|
+
if (!type || !above.canReplaceWith(after, after, type)) {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
const node = type.createAndFill();
|
|
316
|
+
if (!node) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
const pos = isVisible ? $head.after() + 1 : $head.after(-1);
|
|
320
|
+
const tr = state.tr.replaceWith(pos, pos, node);
|
|
321
|
+
const $pos = tr.doc.resolve(pos);
|
|
322
|
+
const newSelection = import_state.Selection.near($pos, 1);
|
|
323
|
+
tr.setSelection(newSelection);
|
|
324
|
+
tr.scrollIntoView();
|
|
325
|
+
view.dispatch(tr);
|
|
326
|
+
return true;
|
|
327
|
+
},
|
|
328
|
+
// The default gapcursor implementation can’t handle hidden content, so we need to fix this.
|
|
329
|
+
ArrowRight: ({ editor }) => {
|
|
330
|
+
return setGapCursor(editor, "right");
|
|
331
|
+
},
|
|
332
|
+
// The default gapcursor implementation can’t handle hidden content, so we need to fix this.
|
|
333
|
+
ArrowDown: ({ editor }) => {
|
|
334
|
+
return setGapCursor(editor, "down");
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
},
|
|
338
|
+
addProseMirrorPlugins() {
|
|
339
|
+
return [
|
|
340
|
+
// This plugin prevents text selections within the hidden content in `DetailsContent`.
|
|
341
|
+
// The cursor is moved to the next visible position.
|
|
342
|
+
new import_state.Plugin({
|
|
343
|
+
key: new import_state.PluginKey("detailsSelection"),
|
|
344
|
+
appendTransaction: (transactions, oldState, newState) => {
|
|
345
|
+
const { editor, type } = this;
|
|
346
|
+
const selectionSet = transactions.some((transaction2) => transaction2.selectionSet);
|
|
347
|
+
if (!selectionSet || !oldState.selection.empty || !newState.selection.empty) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const detailsIsActive = (0, import_core2.isActive)(newState, type.name);
|
|
351
|
+
if (!detailsIsActive) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
const { $from } = newState.selection;
|
|
355
|
+
const isVisible = isNodeVisible($from.pos, editor);
|
|
356
|
+
if (isVisible) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const details = findClosestVisibleNode($from, (node) => node.type === type, editor);
|
|
360
|
+
if (!details) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const detailsSummaries = (0, import_core2.findChildren)(
|
|
364
|
+
details.node,
|
|
365
|
+
(node) => node.type === newState.schema.nodes.detailsSummary
|
|
366
|
+
);
|
|
367
|
+
if (!detailsSummaries.length) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const detailsSummary = detailsSummaries[0];
|
|
371
|
+
const selectionDirection = oldState.selection.from < newState.selection.from ? "forward" : "backward";
|
|
372
|
+
const correctedPosition = selectionDirection === "forward" ? details.start + detailsSummary.pos : details.pos + detailsSummary.pos + detailsSummary.node.nodeSize;
|
|
373
|
+
const selection = import_state.TextSelection.create(newState.doc, correctedPosition);
|
|
374
|
+
const transaction = newState.tr.setSelection(selection);
|
|
375
|
+
return transaction;
|
|
376
|
+
}
|
|
377
|
+
})
|
|
378
|
+
];
|
|
379
|
+
}
|
|
382
380
|
});
|
|
383
381
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
382
|
+
// src/index.ts
|
|
383
|
+
var index_default = Details;
|
|
384
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
385
|
+
0 && (module.exports = {
|
|
386
|
+
Details
|
|
387
|
+
});
|
|
388
|
+
//# sourceMappingURL=index.cjs.map
|