@tiptap/extension-task-item 3.0.0-next.4 → 3.0.0-next.5
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 +1 -1
- package/dist/index.cjs +7 -152
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -41
- package/dist/index.d.ts +2 -41
- package/dist/index.js +5 -148
- package/dist/index.js.map +1 -1
- package/package.json +3 -5
- package/src/index.ts +2 -2
- package/src/task-item.ts +0 -219
package/LICENSE.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -20,162 +20,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
TaskItem: () => TaskItem,
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
TaskItem: () => import_extension_list2.TaskItem,
|
|
24
|
+
TaskItemOptions: () => import_extension_list2.TaskItemOptions,
|
|
25
|
+
default: () => index_default
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(index_exports);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
var
|
|
31
|
-
var inputRegex = /^\s*(\[([( |x])?\])\s$/;
|
|
32
|
-
var TaskItem = import_core.Node.create({
|
|
33
|
-
name: "taskItem",
|
|
34
|
-
addOptions() {
|
|
35
|
-
return {
|
|
36
|
-
nested: false,
|
|
37
|
-
HTMLAttributes: {},
|
|
38
|
-
taskListTypeName: "taskList"
|
|
39
|
-
};
|
|
40
|
-
},
|
|
41
|
-
content() {
|
|
42
|
-
return this.options.nested ? "paragraph block*" : "paragraph+";
|
|
43
|
-
},
|
|
44
|
-
defining: true,
|
|
45
|
-
addAttributes() {
|
|
46
|
-
return {
|
|
47
|
-
checked: {
|
|
48
|
-
default: false,
|
|
49
|
-
keepOnSplit: false,
|
|
50
|
-
parseHTML: (element) => {
|
|
51
|
-
const dataChecked = element.getAttribute("data-checked");
|
|
52
|
-
return dataChecked === "" || dataChecked === "true";
|
|
53
|
-
},
|
|
54
|
-
renderHTML: (attributes) => ({
|
|
55
|
-
"data-checked": attributes.checked
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
},
|
|
60
|
-
parseHTML() {
|
|
61
|
-
return [
|
|
62
|
-
{
|
|
63
|
-
tag: `li[data-type="${this.name}"]`,
|
|
64
|
-
priority: 51
|
|
65
|
-
}
|
|
66
|
-
];
|
|
67
|
-
},
|
|
68
|
-
renderHTML({ node, HTMLAttributes }) {
|
|
69
|
-
return [
|
|
70
|
-
"li",
|
|
71
|
-
(0, import_core.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, {
|
|
72
|
-
"data-type": this.name
|
|
73
|
-
}),
|
|
74
|
-
[
|
|
75
|
-
"label",
|
|
76
|
-
[
|
|
77
|
-
"input",
|
|
78
|
-
{
|
|
79
|
-
type: "checkbox",
|
|
80
|
-
checked: node.attrs.checked ? "checked" : null
|
|
81
|
-
}
|
|
82
|
-
],
|
|
83
|
-
["span"]
|
|
84
|
-
],
|
|
85
|
-
["div", 0]
|
|
86
|
-
];
|
|
87
|
-
},
|
|
88
|
-
addKeyboardShortcuts() {
|
|
89
|
-
const shortcuts = {
|
|
90
|
-
Enter: () => this.editor.commands.splitListItem(this.name),
|
|
91
|
-
"Shift-Tab": () => this.editor.commands.liftListItem(this.name)
|
|
92
|
-
};
|
|
93
|
-
if (!this.options.nested) {
|
|
94
|
-
return shortcuts;
|
|
95
|
-
}
|
|
96
|
-
return {
|
|
97
|
-
...shortcuts,
|
|
98
|
-
Tab: () => this.editor.commands.sinkListItem(this.name)
|
|
99
|
-
};
|
|
100
|
-
},
|
|
101
|
-
addNodeView() {
|
|
102
|
-
return ({ node, HTMLAttributes, getPos, editor }) => {
|
|
103
|
-
const listItem = document.createElement("li");
|
|
104
|
-
const checkboxWrapper = document.createElement("label");
|
|
105
|
-
const checkboxStyler = document.createElement("span");
|
|
106
|
-
const checkbox = document.createElement("input");
|
|
107
|
-
const content = document.createElement("div");
|
|
108
|
-
checkboxWrapper.contentEditable = "false";
|
|
109
|
-
checkbox.type = "checkbox";
|
|
110
|
-
checkbox.addEventListener("mousedown", (event) => event.preventDefault());
|
|
111
|
-
checkbox.addEventListener("change", (event) => {
|
|
112
|
-
if (!editor.isEditable && !this.options.onReadOnlyChecked) {
|
|
113
|
-
checkbox.checked = !checkbox.checked;
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const { checked } = event.target;
|
|
117
|
-
if (editor.isEditable && typeof getPos === "function") {
|
|
118
|
-
editor.chain().focus(void 0, { scrollIntoView: false }).command(({ tr }) => {
|
|
119
|
-
const position = getPos();
|
|
120
|
-
if (typeof position !== "number") {
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
const currentNode = tr.doc.nodeAt(position);
|
|
124
|
-
tr.setNodeMarkup(position, void 0, {
|
|
125
|
-
...currentNode == null ? void 0 : currentNode.attrs,
|
|
126
|
-
checked
|
|
127
|
-
});
|
|
128
|
-
return true;
|
|
129
|
-
}).run();
|
|
130
|
-
}
|
|
131
|
-
if (!editor.isEditable && this.options.onReadOnlyChecked) {
|
|
132
|
-
if (!this.options.onReadOnlyChecked(node, checked)) {
|
|
133
|
-
checkbox.checked = !checkbox.checked;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
Object.entries(this.options.HTMLAttributes).forEach(([key, value]) => {
|
|
138
|
-
listItem.setAttribute(key, value);
|
|
139
|
-
});
|
|
140
|
-
listItem.dataset.checked = node.attrs.checked;
|
|
141
|
-
checkbox.checked = node.attrs.checked;
|
|
142
|
-
checkboxWrapper.append(checkbox, checkboxStyler);
|
|
143
|
-
listItem.append(checkboxWrapper, content);
|
|
144
|
-
Object.entries(HTMLAttributes).forEach(([key, value]) => {
|
|
145
|
-
listItem.setAttribute(key, value);
|
|
146
|
-
});
|
|
147
|
-
return {
|
|
148
|
-
dom: listItem,
|
|
149
|
-
contentDOM: content,
|
|
150
|
-
update: (updatedNode) => {
|
|
151
|
-
if (updatedNode.type !== this.type) {
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
listItem.dataset.checked = updatedNode.attrs.checked;
|
|
155
|
-
checkbox.checked = updatedNode.attrs.checked;
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
};
|
|
160
|
-
},
|
|
161
|
-
addInputRules() {
|
|
162
|
-
return [
|
|
163
|
-
(0, import_core.wrappingInputRule)({
|
|
164
|
-
find: inputRegex,
|
|
165
|
-
type: this.type,
|
|
166
|
-
getAttributes: (match) => ({
|
|
167
|
-
checked: match[match.length - 1] === "x"
|
|
168
|
-
})
|
|
169
|
-
})
|
|
170
|
-
];
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
// src/index.ts
|
|
175
|
-
var index_default = TaskItem;
|
|
28
|
+
var import_extension_list = require("@tiptap/extension-list");
|
|
29
|
+
var import_extension_list2 = require("@tiptap/extension-list");
|
|
30
|
+
var index_default = import_extension_list.TaskItem;
|
|
176
31
|
// Annotate the CommonJS export names for ESM import in node:
|
|
177
32
|
0 && (module.exports = {
|
|
178
33
|
TaskItem,
|
|
179
|
-
|
|
34
|
+
TaskItemOptions
|
|
180
35
|
});
|
|
181
36
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { TaskItem } from '@tiptap/extension-list'\n\nexport { TaskItem, TaskItemOptions } from '@tiptap/extension-list'\n\nexport default TaskItem\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAyB;AAEzB,IAAAA,yBAA0C;AAE1C,IAAO,gBAAQ;","names":["import_extension_list"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,41 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
interface TaskItemOptions {
|
|
5
|
-
/**
|
|
6
|
-
* A callback function that is called when the checkbox is clicked while the editor is in readonly mode.
|
|
7
|
-
* @param node The prosemirror node of the task item
|
|
8
|
-
* @param checked The new checked state
|
|
9
|
-
* @returns boolean
|
|
10
|
-
*/
|
|
11
|
-
onReadOnlyChecked?: (node: Node, checked: boolean) => boolean;
|
|
12
|
-
/**
|
|
13
|
-
* Controls whether the task items can be nested or not.
|
|
14
|
-
* @default false
|
|
15
|
-
* @example true
|
|
16
|
-
*/
|
|
17
|
-
nested: boolean;
|
|
18
|
-
/**
|
|
19
|
-
* HTML attributes to add to the task item element.
|
|
20
|
-
* @default {}
|
|
21
|
-
* @example { class: 'foo' }
|
|
22
|
-
*/
|
|
23
|
-
HTMLAttributes: Record<string, any>;
|
|
24
|
-
/**
|
|
25
|
-
* The node type for taskList nodes
|
|
26
|
-
* @default 'taskList'
|
|
27
|
-
* @example 'myCustomTaskList'
|
|
28
|
-
*/
|
|
29
|
-
taskListTypeName: string;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Matches a task item to a - [ ] on input.
|
|
33
|
-
*/
|
|
34
|
-
declare const inputRegex: RegExp;
|
|
35
|
-
/**
|
|
36
|
-
* This extension allows you to create task items.
|
|
37
|
-
* @see https://www.tiptap.dev/api/nodes/task-item
|
|
38
|
-
*/
|
|
39
|
-
declare const TaskItem: Node$1<TaskItemOptions, any>;
|
|
40
|
-
|
|
41
|
-
export { TaskItem, type TaskItemOptions, TaskItem as default, inputRegex };
|
|
1
|
+
import { TaskItem } from '@tiptap/extension-list';
|
|
2
|
+
export { TaskItem, TaskItemOptions, TaskItem as default } from '@tiptap/extension-list';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,41 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
interface TaskItemOptions {
|
|
5
|
-
/**
|
|
6
|
-
* A callback function that is called when the checkbox is clicked while the editor is in readonly mode.
|
|
7
|
-
* @param node The prosemirror node of the task item
|
|
8
|
-
* @param checked The new checked state
|
|
9
|
-
* @returns boolean
|
|
10
|
-
*/
|
|
11
|
-
onReadOnlyChecked?: (node: Node, checked: boolean) => boolean;
|
|
12
|
-
/**
|
|
13
|
-
* Controls whether the task items can be nested or not.
|
|
14
|
-
* @default false
|
|
15
|
-
* @example true
|
|
16
|
-
*/
|
|
17
|
-
nested: boolean;
|
|
18
|
-
/**
|
|
19
|
-
* HTML attributes to add to the task item element.
|
|
20
|
-
* @default {}
|
|
21
|
-
* @example { class: 'foo' }
|
|
22
|
-
*/
|
|
23
|
-
HTMLAttributes: Record<string, any>;
|
|
24
|
-
/**
|
|
25
|
-
* The node type for taskList nodes
|
|
26
|
-
* @default 'taskList'
|
|
27
|
-
* @example 'myCustomTaskList'
|
|
28
|
-
*/
|
|
29
|
-
taskListTypeName: string;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Matches a task item to a - [ ] on input.
|
|
33
|
-
*/
|
|
34
|
-
declare const inputRegex: RegExp;
|
|
35
|
-
/**
|
|
36
|
-
* This extension allows you to create task items.
|
|
37
|
-
* @see https://www.tiptap.dev/api/nodes/task-item
|
|
38
|
-
*/
|
|
39
|
-
declare const TaskItem: Node$1<TaskItemOptions, any>;
|
|
40
|
-
|
|
41
|
-
export { TaskItem, type TaskItemOptions, TaskItem as default, inputRegex };
|
|
1
|
+
import { TaskItem } from '@tiptap/extension-list';
|
|
2
|
+
export { TaskItem, TaskItemOptions, TaskItem as default } from '@tiptap/extension-list';
|
package/dist/index.js
CHANGED
|
@@ -1,153 +1,10 @@
|
|
|
1
|
-
// src/task-item.ts
|
|
2
|
-
import { mergeAttributes, Node, wrappingInputRule } from "@tiptap/core";
|
|
3
|
-
var inputRegex = /^\s*(\[([( |x])?\])\s$/;
|
|
4
|
-
var TaskItem = Node.create({
|
|
5
|
-
name: "taskItem",
|
|
6
|
-
addOptions() {
|
|
7
|
-
return {
|
|
8
|
-
nested: false,
|
|
9
|
-
HTMLAttributes: {},
|
|
10
|
-
taskListTypeName: "taskList"
|
|
11
|
-
};
|
|
12
|
-
},
|
|
13
|
-
content() {
|
|
14
|
-
return this.options.nested ? "paragraph block*" : "paragraph+";
|
|
15
|
-
},
|
|
16
|
-
defining: true,
|
|
17
|
-
addAttributes() {
|
|
18
|
-
return {
|
|
19
|
-
checked: {
|
|
20
|
-
default: false,
|
|
21
|
-
keepOnSplit: false,
|
|
22
|
-
parseHTML: (element) => {
|
|
23
|
-
const dataChecked = element.getAttribute("data-checked");
|
|
24
|
-
return dataChecked === "" || dataChecked === "true";
|
|
25
|
-
},
|
|
26
|
-
renderHTML: (attributes) => ({
|
|
27
|
-
"data-checked": attributes.checked
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
},
|
|
32
|
-
parseHTML() {
|
|
33
|
-
return [
|
|
34
|
-
{
|
|
35
|
-
tag: `li[data-type="${this.name}"]`,
|
|
36
|
-
priority: 51
|
|
37
|
-
}
|
|
38
|
-
];
|
|
39
|
-
},
|
|
40
|
-
renderHTML({ node, HTMLAttributes }) {
|
|
41
|
-
return [
|
|
42
|
-
"li",
|
|
43
|
-
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
|
|
44
|
-
"data-type": this.name
|
|
45
|
-
}),
|
|
46
|
-
[
|
|
47
|
-
"label",
|
|
48
|
-
[
|
|
49
|
-
"input",
|
|
50
|
-
{
|
|
51
|
-
type: "checkbox",
|
|
52
|
-
checked: node.attrs.checked ? "checked" : null
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
["span"]
|
|
56
|
-
],
|
|
57
|
-
["div", 0]
|
|
58
|
-
];
|
|
59
|
-
},
|
|
60
|
-
addKeyboardShortcuts() {
|
|
61
|
-
const shortcuts = {
|
|
62
|
-
Enter: () => this.editor.commands.splitListItem(this.name),
|
|
63
|
-
"Shift-Tab": () => this.editor.commands.liftListItem(this.name)
|
|
64
|
-
};
|
|
65
|
-
if (!this.options.nested) {
|
|
66
|
-
return shortcuts;
|
|
67
|
-
}
|
|
68
|
-
return {
|
|
69
|
-
...shortcuts,
|
|
70
|
-
Tab: () => this.editor.commands.sinkListItem(this.name)
|
|
71
|
-
};
|
|
72
|
-
},
|
|
73
|
-
addNodeView() {
|
|
74
|
-
return ({ node, HTMLAttributes, getPos, editor }) => {
|
|
75
|
-
const listItem = document.createElement("li");
|
|
76
|
-
const checkboxWrapper = document.createElement("label");
|
|
77
|
-
const checkboxStyler = document.createElement("span");
|
|
78
|
-
const checkbox = document.createElement("input");
|
|
79
|
-
const content = document.createElement("div");
|
|
80
|
-
checkboxWrapper.contentEditable = "false";
|
|
81
|
-
checkbox.type = "checkbox";
|
|
82
|
-
checkbox.addEventListener("mousedown", (event) => event.preventDefault());
|
|
83
|
-
checkbox.addEventListener("change", (event) => {
|
|
84
|
-
if (!editor.isEditable && !this.options.onReadOnlyChecked) {
|
|
85
|
-
checkbox.checked = !checkbox.checked;
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
const { checked } = event.target;
|
|
89
|
-
if (editor.isEditable && typeof getPos === "function") {
|
|
90
|
-
editor.chain().focus(void 0, { scrollIntoView: false }).command(({ tr }) => {
|
|
91
|
-
const position = getPos();
|
|
92
|
-
if (typeof position !== "number") {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
const currentNode = tr.doc.nodeAt(position);
|
|
96
|
-
tr.setNodeMarkup(position, void 0, {
|
|
97
|
-
...currentNode == null ? void 0 : currentNode.attrs,
|
|
98
|
-
checked
|
|
99
|
-
});
|
|
100
|
-
return true;
|
|
101
|
-
}).run();
|
|
102
|
-
}
|
|
103
|
-
if (!editor.isEditable && this.options.onReadOnlyChecked) {
|
|
104
|
-
if (!this.options.onReadOnlyChecked(node, checked)) {
|
|
105
|
-
checkbox.checked = !checkbox.checked;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
Object.entries(this.options.HTMLAttributes).forEach(([key, value]) => {
|
|
110
|
-
listItem.setAttribute(key, value);
|
|
111
|
-
});
|
|
112
|
-
listItem.dataset.checked = node.attrs.checked;
|
|
113
|
-
checkbox.checked = node.attrs.checked;
|
|
114
|
-
checkboxWrapper.append(checkbox, checkboxStyler);
|
|
115
|
-
listItem.append(checkboxWrapper, content);
|
|
116
|
-
Object.entries(HTMLAttributes).forEach(([key, value]) => {
|
|
117
|
-
listItem.setAttribute(key, value);
|
|
118
|
-
});
|
|
119
|
-
return {
|
|
120
|
-
dom: listItem,
|
|
121
|
-
contentDOM: content,
|
|
122
|
-
update: (updatedNode) => {
|
|
123
|
-
if (updatedNode.type !== this.type) {
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
listItem.dataset.checked = updatedNode.attrs.checked;
|
|
127
|
-
checkbox.checked = updatedNode.attrs.checked;
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
};
|
|
132
|
-
},
|
|
133
|
-
addInputRules() {
|
|
134
|
-
return [
|
|
135
|
-
wrappingInputRule({
|
|
136
|
-
find: inputRegex,
|
|
137
|
-
type: this.type,
|
|
138
|
-
getAttributes: (match) => ({
|
|
139
|
-
checked: match[match.length - 1] === "x"
|
|
140
|
-
})
|
|
141
|
-
})
|
|
142
|
-
];
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
|
|
146
1
|
// src/index.ts
|
|
2
|
+
import { TaskItem } from "@tiptap/extension-list";
|
|
3
|
+
import { TaskItem as TaskItem2, TaskItemOptions } from "@tiptap/extension-list";
|
|
147
4
|
var index_default = TaskItem;
|
|
148
5
|
export {
|
|
149
|
-
TaskItem,
|
|
150
|
-
|
|
151
|
-
|
|
6
|
+
TaskItem2 as TaskItem,
|
|
7
|
+
TaskItemOptions,
|
|
8
|
+
index_default as default
|
|
152
9
|
};
|
|
153
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { TaskItem } from '@tiptap/extension-list'\n\nexport { TaskItem, TaskItemOptions } from '@tiptap/extension-list'\n\nexport default TaskItem\n"],"mappings":";AAAA,SAAS,gBAAgB;AAEzB,SAAS,YAAAA,WAAU,uBAAuB;AAE1C,IAAO,gBAAQ;","names":["TaskItem"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/extension-task-item",
|
|
3
3
|
"description": "task item extension for tiptap",
|
|
4
|
-
"version": "3.0.0-next.
|
|
4
|
+
"version": "3.0.0-next.5",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -31,12 +31,10 @@
|
|
|
31
31
|
"dist"
|
|
32
32
|
],
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@tiptap/
|
|
35
|
-
"@tiptap/pm": "^3.0.0-next.4"
|
|
34
|
+
"@tiptap/extension-list": "^3.0.0-next.5"
|
|
36
35
|
},
|
|
37
36
|
"peerDependencies": {
|
|
38
|
-
"@tiptap/
|
|
39
|
-
"@tiptap/pm": "^3.0.0-next.1"
|
|
37
|
+
"@tiptap/extension-list": "^3.0.0-next.4"
|
|
40
38
|
},
|
|
41
39
|
"repository": {
|
|
42
40
|
"type": "git",
|
package/src/index.ts
CHANGED
package/src/task-item.ts
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { KeyboardShortcutCommand, mergeAttributes, Node, wrappingInputRule } from '@tiptap/core'
|
|
2
|
-
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
|
3
|
-
|
|
4
|
-
export interface TaskItemOptions {
|
|
5
|
-
/**
|
|
6
|
-
* A callback function that is called when the checkbox is clicked while the editor is in readonly mode.
|
|
7
|
-
* @param node The prosemirror node of the task item
|
|
8
|
-
* @param checked The new checked state
|
|
9
|
-
* @returns boolean
|
|
10
|
-
*/
|
|
11
|
-
onReadOnlyChecked?: (node: ProseMirrorNode, checked: boolean) => boolean
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Controls whether the task items can be nested or not.
|
|
15
|
-
* @default false
|
|
16
|
-
* @example true
|
|
17
|
-
*/
|
|
18
|
-
nested: boolean
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* HTML attributes to add to the task item element.
|
|
22
|
-
* @default {}
|
|
23
|
-
* @example { class: 'foo' }
|
|
24
|
-
*/
|
|
25
|
-
HTMLAttributes: Record<string, any>
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* The node type for taskList nodes
|
|
29
|
-
* @default 'taskList'
|
|
30
|
-
* @example 'myCustomTaskList'
|
|
31
|
-
*/
|
|
32
|
-
taskListTypeName: string
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Matches a task item to a - [ ] on input.
|
|
37
|
-
*/
|
|
38
|
-
export const inputRegex = /^\s*(\[([( |x])?\])\s$/
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* This extension allows you to create task items.
|
|
42
|
-
* @see https://www.tiptap.dev/api/nodes/task-item
|
|
43
|
-
*/
|
|
44
|
-
export const TaskItem = Node.create<TaskItemOptions>({
|
|
45
|
-
name: 'taskItem',
|
|
46
|
-
|
|
47
|
-
addOptions() {
|
|
48
|
-
return {
|
|
49
|
-
nested: false,
|
|
50
|
-
HTMLAttributes: {},
|
|
51
|
-
taskListTypeName: 'taskList',
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
content() {
|
|
56
|
-
return this.options.nested ? 'paragraph block*' : 'paragraph+'
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
defining: true,
|
|
60
|
-
|
|
61
|
-
addAttributes() {
|
|
62
|
-
return {
|
|
63
|
-
checked: {
|
|
64
|
-
default: false,
|
|
65
|
-
keepOnSplit: false,
|
|
66
|
-
parseHTML: element => {
|
|
67
|
-
const dataChecked = element.getAttribute('data-checked')
|
|
68
|
-
|
|
69
|
-
return dataChecked === '' || dataChecked === 'true'
|
|
70
|
-
},
|
|
71
|
-
renderHTML: attributes => ({
|
|
72
|
-
'data-checked': attributes.checked,
|
|
73
|
-
}),
|
|
74
|
-
},
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
parseHTML() {
|
|
79
|
-
return [
|
|
80
|
-
{
|
|
81
|
-
tag: `li[data-type="${this.name}"]`,
|
|
82
|
-
priority: 51,
|
|
83
|
-
},
|
|
84
|
-
]
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
renderHTML({ node, HTMLAttributes }) {
|
|
88
|
-
return [
|
|
89
|
-
'li',
|
|
90
|
-
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
|
|
91
|
-
'data-type': this.name,
|
|
92
|
-
}),
|
|
93
|
-
[
|
|
94
|
-
'label',
|
|
95
|
-
[
|
|
96
|
-
'input',
|
|
97
|
-
{
|
|
98
|
-
type: 'checkbox',
|
|
99
|
-
checked: node.attrs.checked ? 'checked' : null,
|
|
100
|
-
},
|
|
101
|
-
],
|
|
102
|
-
['span'],
|
|
103
|
-
],
|
|
104
|
-
['div', 0],
|
|
105
|
-
]
|
|
106
|
-
},
|
|
107
|
-
|
|
108
|
-
addKeyboardShortcuts() {
|
|
109
|
-
const shortcuts: {
|
|
110
|
-
[key: string]: KeyboardShortcutCommand
|
|
111
|
-
} = {
|
|
112
|
-
Enter: () => this.editor.commands.splitListItem(this.name),
|
|
113
|
-
'Shift-Tab': () => this.editor.commands.liftListItem(this.name),
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (!this.options.nested) {
|
|
117
|
-
return shortcuts
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
...shortcuts,
|
|
122
|
-
Tab: () => this.editor.commands.sinkListItem(this.name),
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
addNodeView() {
|
|
127
|
-
return ({ node, HTMLAttributes, getPos, editor }) => {
|
|
128
|
-
const listItem = document.createElement('li')
|
|
129
|
-
const checkboxWrapper = document.createElement('label')
|
|
130
|
-
const checkboxStyler = document.createElement('span')
|
|
131
|
-
const checkbox = document.createElement('input')
|
|
132
|
-
const content = document.createElement('div')
|
|
133
|
-
|
|
134
|
-
checkboxWrapper.contentEditable = 'false'
|
|
135
|
-
checkbox.type = 'checkbox'
|
|
136
|
-
checkbox.addEventListener('mousedown', event => event.preventDefault())
|
|
137
|
-
checkbox.addEventListener('change', event => {
|
|
138
|
-
// if the editor isn’t editable and we don't have a handler for
|
|
139
|
-
// readonly checks we have to undo the latest change
|
|
140
|
-
if (!editor.isEditable && !this.options.onReadOnlyChecked) {
|
|
141
|
-
checkbox.checked = !checkbox.checked
|
|
142
|
-
|
|
143
|
-
return
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const { checked } = event.target as any
|
|
147
|
-
|
|
148
|
-
if (editor.isEditable && typeof getPos === 'function') {
|
|
149
|
-
editor
|
|
150
|
-
.chain()
|
|
151
|
-
.focus(undefined, { scrollIntoView: false })
|
|
152
|
-
.command(({ tr }) => {
|
|
153
|
-
const position = getPos()
|
|
154
|
-
|
|
155
|
-
if (typeof position !== 'number') {
|
|
156
|
-
return false
|
|
157
|
-
}
|
|
158
|
-
const currentNode = tr.doc.nodeAt(position)
|
|
159
|
-
|
|
160
|
-
tr.setNodeMarkup(position, undefined, {
|
|
161
|
-
...currentNode?.attrs,
|
|
162
|
-
checked,
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
return true
|
|
166
|
-
})
|
|
167
|
-
.run()
|
|
168
|
-
}
|
|
169
|
-
if (!editor.isEditable && this.options.onReadOnlyChecked) {
|
|
170
|
-
// Reset state if onReadOnlyChecked returns false
|
|
171
|
-
if (!this.options.onReadOnlyChecked(node, checked)) {
|
|
172
|
-
checkbox.checked = !checkbox.checked
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
Object.entries(this.options.HTMLAttributes).forEach(([key, value]) => {
|
|
178
|
-
listItem.setAttribute(key, value)
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
listItem.dataset.checked = node.attrs.checked
|
|
182
|
-
checkbox.checked = node.attrs.checked
|
|
183
|
-
|
|
184
|
-
checkboxWrapper.append(checkbox, checkboxStyler)
|
|
185
|
-
listItem.append(checkboxWrapper, content)
|
|
186
|
-
|
|
187
|
-
Object.entries(HTMLAttributes).forEach(([key, value]) => {
|
|
188
|
-
listItem.setAttribute(key, value)
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
return {
|
|
192
|
-
dom: listItem,
|
|
193
|
-
contentDOM: content,
|
|
194
|
-
update: updatedNode => {
|
|
195
|
-
if (updatedNode.type !== this.type) {
|
|
196
|
-
return false
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
listItem.dataset.checked = updatedNode.attrs.checked
|
|
200
|
-
checkbox.checked = updatedNode.attrs.checked
|
|
201
|
-
|
|
202
|
-
return true
|
|
203
|
-
},
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
},
|
|
207
|
-
|
|
208
|
-
addInputRules() {
|
|
209
|
-
return [
|
|
210
|
-
wrappingInputRule({
|
|
211
|
-
find: inputRegex,
|
|
212
|
-
type: this.type,
|
|
213
|
-
getAttributes: match => ({
|
|
214
|
-
checked: match[match.length - 1] === 'x',
|
|
215
|
-
}),
|
|
216
|
-
}),
|
|
217
|
-
]
|
|
218
|
-
},
|
|
219
|
-
})
|