@sendbird/actionbook-core 0.10.6 → 0.10.8
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.d.ts +2 -2
- package/dist/index.js +58 -4
- package/dist/index.js.map +1 -1
- package/dist/{types-DK_GhIWZ.d.ts → types-BQ95zx4j.d.ts} +1 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +297 -126
- package/dist/ui/index.js.map +1 -1
- package/package.json +1 -1
package/dist/ui/index.js
CHANGED
|
@@ -55,7 +55,7 @@ var actionbookSchema = new Schema({
|
|
|
55
55
|
},
|
|
56
56
|
listItem: {
|
|
57
57
|
content: "block+",
|
|
58
|
-
attrs: { checked: { default: null } },
|
|
58
|
+
attrs: { checked: { default: null }, value: { default: null } },
|
|
59
59
|
parseDOM: [
|
|
60
60
|
{
|
|
61
61
|
tag: "li",
|
|
@@ -63,20 +63,25 @@ var actionbookSchema = new Schema({
|
|
|
63
63
|
const el = dom;
|
|
64
64
|
const checkbox = el.querySelector('input[type="checkbox"]');
|
|
65
65
|
if (checkbox) {
|
|
66
|
-
return { checked: checkbox.checked };
|
|
66
|
+
return { checked: checkbox.checked, value: el.value || null };
|
|
67
67
|
}
|
|
68
68
|
if (el.dataset.checked != null) {
|
|
69
|
-
return { checked: el.dataset.checked === "true" };
|
|
69
|
+
return { checked: el.dataset.checked === "true", value: el.value || null };
|
|
70
70
|
}
|
|
71
|
-
return { checked: null };
|
|
71
|
+
return { checked: null, value: el.value || null };
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
],
|
|
75
75
|
toDOM(node) {
|
|
76
|
+
const liAttrs = {};
|
|
76
77
|
if (node.attrs.checked != null) {
|
|
77
|
-
|
|
78
|
+
liAttrs.class = "todo-item";
|
|
79
|
+
liAttrs["data-checked"] = String(node.attrs.checked);
|
|
78
80
|
}
|
|
79
|
-
|
|
81
|
+
if (node.attrs.value != null) {
|
|
82
|
+
liAttrs.value = String(node.attrs.value);
|
|
83
|
+
}
|
|
84
|
+
return Object.keys(liAttrs).length > 0 ? ["li", liAttrs, 0] : ["li", 0];
|
|
80
85
|
},
|
|
81
86
|
defining: true
|
|
82
87
|
},
|
|
@@ -1425,6 +1430,10 @@ function convertPMListItem(node, depth = 0) {
|
|
|
1425
1430
|
if (typeof checked === "boolean") {
|
|
1426
1431
|
base.checked = checked;
|
|
1427
1432
|
}
|
|
1433
|
+
const value = node.attrs?.value;
|
|
1434
|
+
if (value != null) {
|
|
1435
|
+
base.value = value;
|
|
1436
|
+
}
|
|
1428
1437
|
return base;
|
|
1429
1438
|
}
|
|
1430
1439
|
function fromProseMirrorJSON(pmJSON) {
|
|
@@ -2320,13 +2329,21 @@ function blockToMdast(node, depth = 0) {
|
|
|
2320
2329
|
];
|
|
2321
2330
|
}
|
|
2322
2331
|
case "orderedList": {
|
|
2323
|
-
const
|
|
2332
|
+
const spread = node.spread ?? false;
|
|
2333
|
+
let counter = node.start;
|
|
2334
|
+
const items = node.content.map((li) => {
|
|
2335
|
+
const mdastLi = listItemToMdast(li, depth + 1);
|
|
2336
|
+
if (li.value != null) counter = li.value;
|
|
2337
|
+
mdastLi._ordinalValue = counter;
|
|
2338
|
+
counter++;
|
|
2339
|
+
return mdastLi;
|
|
2340
|
+
});
|
|
2324
2341
|
return [
|
|
2325
2342
|
{
|
|
2326
2343
|
type: "list",
|
|
2327
2344
|
ordered: true,
|
|
2328
|
-
start: node.start,
|
|
2329
|
-
spread
|
|
2345
|
+
start: node.content[0]?.value ?? node.start,
|
|
2346
|
+
spread,
|
|
2330
2347
|
children: items
|
|
2331
2348
|
}
|
|
2332
2349
|
];
|
|
@@ -2401,6 +2418,14 @@ var gfmNoAutolinkToMarkdown = () => ({
|
|
|
2401
2418
|
function isEmptyParagraph(node) {
|
|
2402
2419
|
return node.type === "paragraph" && (!("children" in node) || !node.children || node.children.length === 0);
|
|
2403
2420
|
}
|
|
2421
|
+
var JINJA_TAG_RE = /^\{%\s*(if|elif|else|endif)\b/;
|
|
2422
|
+
function isJinjaTagParagraph(node) {
|
|
2423
|
+
if (node.type !== "paragraph") return false;
|
|
2424
|
+
const children = node.children;
|
|
2425
|
+
if (!children || children.length !== 1) return false;
|
|
2426
|
+
const child = children[0];
|
|
2427
|
+
return child.type === "text" && typeof child.value === "string" && JINJA_TAG_RE.test(child.value);
|
|
2428
|
+
}
|
|
2404
2429
|
function textHandler(node, parent, state, info) {
|
|
2405
2430
|
const originalUnsafe = state.unsafe;
|
|
2406
2431
|
state.unsafe = originalUnsafe.filter((p) => !(p.character === "_" && !p.atBreak));
|
|
@@ -2415,10 +2440,24 @@ function linkHandler(node, parent, state, info) {
|
|
|
2415
2440
|
const titlePart = title ? ` "${title.replace(/"/g, '\\"')}"` : "";
|
|
2416
2441
|
return `[${childrenText}](${url}${titlePart})`;
|
|
2417
2442
|
}
|
|
2443
|
+
function listItemHandler(node, parent, state, info) {
|
|
2444
|
+
const value = node._ordinalValue;
|
|
2445
|
+
if (value != null && parent && parent.ordered) {
|
|
2446
|
+
const list = parent;
|
|
2447
|
+
const savedStart = list.start;
|
|
2448
|
+
const idx = list.children.indexOf(node);
|
|
2449
|
+
list.start = value - idx;
|
|
2450
|
+
const result = defaultHandlers3.listItem(node, parent, state, info);
|
|
2451
|
+
list.start = savedStart;
|
|
2452
|
+
return result;
|
|
2453
|
+
}
|
|
2454
|
+
return defaultHandlers3.listItem(node, parent, state, info);
|
|
2455
|
+
}
|
|
2418
2456
|
function serializeToMarkdown(doc2) {
|
|
2419
2457
|
const mdastTree = toMdast(doc2);
|
|
2420
2458
|
const raw = toMarkdown(mdastTree, {
|
|
2421
2459
|
bullet: "-",
|
|
2460
|
+
bulletOrdered: ".",
|
|
2422
2461
|
rule: "-",
|
|
2423
2462
|
listItemIndent: "one",
|
|
2424
2463
|
incrementListMarker: true,
|
|
@@ -2429,11 +2468,15 @@ function serializeToMarkdown(doc2) {
|
|
|
2429
2468
|
// Empty paragraphs represent blank-line spacers.
|
|
2430
2469
|
// Reduce the separator after an empty paragraph from \n\n to \n
|
|
2431
2470
|
// so that 1 empty paragraph = 1 extra blank line in the output.
|
|
2432
|
-
(left) => isEmptyParagraph(left) ? 0 : null
|
|
2471
|
+
(left) => isEmptyParagraph(left) ? 0 : null,
|
|
2472
|
+
// Consecutive paragraphs: single newline instead of blank line
|
|
2473
|
+
// (skip jinja tag paragraphs — they need blank lines for proper roundtrip)
|
|
2474
|
+
(left, right) => left.type === "paragraph" && right.type === "paragraph" && !isJinjaTagParagraph(left) && !isJinjaTagParagraph(right) ? 0 : null
|
|
2433
2475
|
],
|
|
2434
2476
|
handlers: {
|
|
2435
2477
|
text: textHandler,
|
|
2436
2478
|
link: linkHandler,
|
|
2479
|
+
listItem: listItemHandler,
|
|
2437
2480
|
...resourceTagToMarkdown().handlers,
|
|
2438
2481
|
...jumpPointToMarkdown().handlers
|
|
2439
2482
|
},
|
|
@@ -2569,8 +2612,11 @@ function convertBlock2(node) {
|
|
|
2569
2612
|
type: "listItem",
|
|
2570
2613
|
content: node.content.flatMap(convertBlockToArray)
|
|
2571
2614
|
};
|
|
2572
|
-
if (node.checked != null) {
|
|
2573
|
-
result.attrs = {
|
|
2615
|
+
if (node.checked != null || node.value != null) {
|
|
2616
|
+
result.attrs = {
|
|
2617
|
+
...node.checked != null ? { checked: node.checked } : {},
|
|
2618
|
+
...node.value != null ? { value: node.value } : {}
|
|
2619
|
+
};
|
|
2574
2620
|
}
|
|
2575
2621
|
return result;
|
|
2576
2622
|
}
|
|
@@ -3025,15 +3071,22 @@ var STRIKE_RE = /(?:^|[^~])~~([^~]+)~~$/;
|
|
|
3025
3071
|
var CODE_RE = /(?:^|[^`])`([^`]+)`$/;
|
|
3026
3072
|
function findParentList(state, pos) {
|
|
3027
3073
|
const $pos = state.doc.resolve(pos);
|
|
3028
|
-
const { bulletList: blType, orderedList: olType } = actionbookSchema.nodes;
|
|
3029
3074
|
for (let d = $pos.depth; d > 0; d--) {
|
|
3030
3075
|
const node = $pos.node(d);
|
|
3031
|
-
|
|
3076
|
+
const name = node.type.name;
|
|
3077
|
+
if (name === "bulletList" || name === "orderedList") {
|
|
3032
3078
|
return { depth: d, node };
|
|
3033
3079
|
}
|
|
3034
3080
|
}
|
|
3035
3081
|
return null;
|
|
3036
3082
|
}
|
|
3083
|
+
function isInsideList(state, pos) {
|
|
3084
|
+
const $pos = state.doc.resolve(pos);
|
|
3085
|
+
for (let d = $pos.depth; d > 0; d--) {
|
|
3086
|
+
if ($pos.node(d).type.name === "listItem") return true;
|
|
3087
|
+
}
|
|
3088
|
+
return false;
|
|
3089
|
+
}
|
|
3037
3090
|
var NOOP = /* @__PURE__ */ Symbol("noop");
|
|
3038
3091
|
function handleListInputRule(state, start, end, listType, attrs) {
|
|
3039
3092
|
const resolvePos = Math.max(start, end - 1);
|
|
@@ -3044,27 +3097,46 @@ function handleListInputRule(state, start, end, listType, attrs) {
|
|
|
3044
3097
|
const paraContentSize = $from.parent.content.size;
|
|
3045
3098
|
const matchedLen = end - start;
|
|
3046
3099
|
const isMarkerOnly = paraContentSize === matchedLen;
|
|
3047
|
-
if (listNode.type === listType) {
|
|
3048
|
-
if (
|
|
3049
|
-
const
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3100
|
+
if (listNode.type.name === listType.name) {
|
|
3101
|
+
if (listType.name === "orderedList" && attrs?.start != null) {
|
|
3102
|
+
const newValue = attrs.start;
|
|
3103
|
+
let liDepth2 = -1;
|
|
3104
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
3105
|
+
if ($from.node(d).type.name === "listItem") {
|
|
3106
|
+
liDepth2 = d;
|
|
3107
|
+
break;
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
if (liDepth2 > 0) {
|
|
3111
|
+
const liIndex2 = $from.index(listDepth);
|
|
3112
|
+
const listStartNum = listNode.attrs.start ?? 1;
|
|
3113
|
+
const naturalNumber = listStartNum + liIndex2;
|
|
3114
|
+
const currentValue = $from.node(liDepth2).attrs.value;
|
|
3115
|
+
if (currentValue === newValue || currentValue == null && newValue === naturalNumber) {
|
|
3116
|
+
const tr3 = state.tr.delete(start, end);
|
|
3117
|
+
tr3.setSelection(TextSelection.near(tr3.doc.resolve(tr3.mapping.map(start))));
|
|
3118
|
+
return tr3;
|
|
3119
|
+
}
|
|
3053
3120
|
const tr2 = state.tr.delete(start, end);
|
|
3054
|
-
tr2.
|
|
3055
|
-
|
|
3056
|
-
|
|
3121
|
+
const $afterDelete = tr2.doc.resolve(tr2.mapping.map(resolvePos));
|
|
3122
|
+
for (let d = $afterDelete.depth; d > 0; d--) {
|
|
3123
|
+
if ($afterDelete.node(d).type.name === "listItem") {
|
|
3124
|
+
const pos = $afterDelete.before(d);
|
|
3125
|
+
const node = $afterDelete.node(d);
|
|
3126
|
+
tr2.setNodeMarkup(pos, void 0, { ...node.attrs, value: newValue });
|
|
3127
|
+
tr2.setSelection(TextSelection.near(tr2.doc.resolve(tr2.mapping.map(start))));
|
|
3128
|
+
return tr2;
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3057
3131
|
}
|
|
3058
3132
|
}
|
|
3059
3133
|
return NOOP;
|
|
3060
3134
|
}
|
|
3061
|
-
if (!isMarkerOnly) return NOOP;
|
|
3062
|
-
const { listItem: liType } = actionbookSchema.nodes;
|
|
3063
3135
|
const tr = state.tr.delete(start, end);
|
|
3064
3136
|
const $pos = tr.doc.resolve(tr.mapping.map(resolvePos));
|
|
3065
3137
|
let liDepth = -1;
|
|
3066
3138
|
for (let d = $pos.depth; d > 0; d--) {
|
|
3067
|
-
if ($pos.node(d).type ===
|
|
3139
|
+
if ($pos.node(d).type.name === "listItem") {
|
|
3068
3140
|
liDepth = d;
|
|
3069
3141
|
break;
|
|
3070
3142
|
}
|
|
@@ -3120,9 +3192,16 @@ function createInputRulesPlugin() {
|
|
|
3120
3192
|
level: match[1].length
|
|
3121
3193
|
}))
|
|
3122
3194
|
);
|
|
3123
|
-
rules.push(
|
|
3195
|
+
rules.push(
|
|
3196
|
+
new InputRule(BLOCKQUOTE_RE, (state, match, start, end) => {
|
|
3197
|
+
if (isInsideList(state, start)) return null;
|
|
3198
|
+
const fallback = wrappingInputRule(BLOCKQUOTE_RE, actionbookSchema.nodes.blockquote);
|
|
3199
|
+
return fallback.handler(state, match, start, end);
|
|
3200
|
+
})
|
|
3201
|
+
);
|
|
3124
3202
|
rules.push(
|
|
3125
3203
|
new InputRule(CODE_BLOCK_RE, (state, match, start, end) => {
|
|
3204
|
+
if (isInsideList(state, start)) return null;
|
|
3126
3205
|
const language = match[1] || null;
|
|
3127
3206
|
const $start = state.doc.resolve(start);
|
|
3128
3207
|
const blockStart = $start.before($start.depth);
|
|
@@ -3138,6 +3217,7 @@ function createInputRulesPlugin() {
|
|
|
3138
3217
|
);
|
|
3139
3218
|
rules.push(
|
|
3140
3219
|
new InputRule(HR_RE, (state, _match, start, end) => {
|
|
3220
|
+
if (isInsideList(state, start)) return null;
|
|
3141
3221
|
const { horizontalRule: hrType, paragraph: pType } = actionbookSchema.nodes;
|
|
3142
3222
|
const $start = state.doc.resolve(start);
|
|
3143
3223
|
const blockStart = $start.before($start.depth);
|
|
@@ -3177,9 +3257,29 @@ function createInputRulesPlugin() {
|
|
|
3177
3257
|
const fallback = wrappingInputRule(ORDERED_LIST_RE, olType, (m) => ({ start: +m[1] }));
|
|
3178
3258
|
rules.push(
|
|
3179
3259
|
new InputRule(ORDERED_LIST_RE, (state, match, start, end) => {
|
|
3180
|
-
const
|
|
3181
|
-
|
|
3182
|
-
|
|
3260
|
+
const typedNumber = +match[1];
|
|
3261
|
+
const resolvePos = Math.max(start, end - 1);
|
|
3262
|
+
const parentList = findParentList(state, resolvePos);
|
|
3263
|
+
if (parentList) {
|
|
3264
|
+
const { node: listNode } = parentList;
|
|
3265
|
+
if (listNode.type.name === "orderedList") {
|
|
3266
|
+
const tr = state.tr.delete(start, end);
|
|
3267
|
+
const $after = tr.doc.resolve(tr.mapping.map(resolvePos));
|
|
3268
|
+
for (let d = $after.depth; d > 0; d--) {
|
|
3269
|
+
if ($after.node(d).type.name === "listItem") {
|
|
3270
|
+
const liPos = $after.before(d);
|
|
3271
|
+
const liNode = $after.node(d);
|
|
3272
|
+
tr.setNodeMarkup(liPos, void 0, { ...liNode.attrs, value: typedNumber });
|
|
3273
|
+
tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));
|
|
3274
|
+
return tr;
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3277
|
+
return null;
|
|
3278
|
+
}
|
|
3279
|
+
const result = handleListInputRule(state, start, end, olType, { start: typedNumber });
|
|
3280
|
+
if (result === NOOP) return null;
|
|
3281
|
+
if (result) return result;
|
|
3282
|
+
}
|
|
3183
3283
|
const handler = fallback.handler;
|
|
3184
3284
|
return handler(state, match, start, end);
|
|
3185
3285
|
})
|
|
@@ -5508,6 +5608,11 @@ function tokenize(input) {
|
|
|
5508
5608
|
i++;
|
|
5509
5609
|
continue;
|
|
5510
5610
|
}
|
|
5611
|
+
if (input[i] === ",") {
|
|
5612
|
+
tokens.push({ type: "COMMA", value: "," });
|
|
5613
|
+
i++;
|
|
5614
|
+
continue;
|
|
5615
|
+
}
|
|
5511
5616
|
return { tokens: [], error: `Unexpected character: ${input[i]}` };
|
|
5512
5617
|
}
|
|
5513
5618
|
tokens.push({ type: "EOF", value: "" });
|
|
@@ -5638,6 +5743,17 @@ var Parser = class {
|
|
|
5638
5743
|
return null;
|
|
5639
5744
|
case "IDENT": {
|
|
5640
5745
|
this.advance();
|
|
5746
|
+
if (this.peek().type === "LPAREN") {
|
|
5747
|
+
this.advance();
|
|
5748
|
+
while (this.peek().type !== "RPAREN" && this.peek().type !== "EOF") {
|
|
5749
|
+
this.orExpr();
|
|
5750
|
+
if (this.peek().type === "COMMA") {
|
|
5751
|
+
this.advance();
|
|
5752
|
+
}
|
|
5753
|
+
}
|
|
5754
|
+
this.expect("RPAREN");
|
|
5755
|
+
return null;
|
|
5756
|
+
}
|
|
5641
5757
|
return this.resolveVariable(t.value);
|
|
5642
5758
|
}
|
|
5643
5759
|
case "LPAREN": {
|
|
@@ -5853,7 +5969,7 @@ function buildDocumentTree(doc2) {
|
|
|
5853
5969
|
|
|
5854
5970
|
// src/ui/plugin/markdownClipboard.ts
|
|
5855
5971
|
var key = new PluginKey2("markdownClipboard");
|
|
5856
|
-
var MAX_PASTE_LIST_DEPTH =
|
|
5972
|
+
var MAX_PASTE_LIST_DEPTH = 15;
|
|
5857
5973
|
var MAX_FLATTEN_DEPTH = 128;
|
|
5858
5974
|
function flattenDeepLists(node, listDepth = 0, _recurseDepth = 0) {
|
|
5859
5975
|
if (_recurseDepth > MAX_FLATTEN_DEPTH) return node;
|
|
@@ -5944,6 +6060,22 @@ function createPlugin() {
|
|
|
5944
6060
|
keyup() {
|
|
5945
6061
|
shiftHeld = false;
|
|
5946
6062
|
return false;
|
|
6063
|
+
},
|
|
6064
|
+
paste(view, event) {
|
|
6065
|
+
if (shiftHeld) return false;
|
|
6066
|
+
const clipboardData = event.clipboardData;
|
|
6067
|
+
const text2 = clipboardData?.getData("text/plain");
|
|
6068
|
+
if (!text2 || !URL_RE.test(text2.trim())) return false;
|
|
6069
|
+
const { from, to } = view.state.selection;
|
|
6070
|
+
if (from >= to) return false;
|
|
6071
|
+
const selectedText = view.state.doc.textBetween(from, to);
|
|
6072
|
+
if (!selectedText) return false;
|
|
6073
|
+
event.preventDefault();
|
|
6074
|
+
const linkType = view.state.schema.marks.link;
|
|
6075
|
+
if (!linkType) return false;
|
|
6076
|
+
const linkMark2 = linkType.create({ href: text2.trim() });
|
|
6077
|
+
view.dispatch(view.state.tr.addMark(from, to, linkMark2));
|
|
6078
|
+
return true;
|
|
5947
6079
|
}
|
|
5948
6080
|
},
|
|
5949
6081
|
handlePaste(view, event) {
|
|
@@ -6551,7 +6683,7 @@ function createInlineToolTagNodeViewPlugin() {
|
|
|
6551
6683
|
import { Plugin as Plugin6, PluginKey as PluginKey5 } from "prosemirror-state";
|
|
6552
6684
|
import { Decoration as Decoration4, DecorationSet as DecorationSet4 } from "prosemirror-view";
|
|
6553
6685
|
var jinjaPluginKey = new PluginKey5("jinjaDecoration");
|
|
6554
|
-
var
|
|
6686
|
+
var JINJA_TAG_RE2 = /\{%\s*(if|elif|else|endif)\s*([^%]*?)\s*%\}/g;
|
|
6555
6687
|
function getBlockPositions(doc2) {
|
|
6556
6688
|
const blocks = [];
|
|
6557
6689
|
let index = 0;
|
|
@@ -6565,9 +6697,9 @@ function addInlineChipDecorations(doc2, decorations) {
|
|
|
6565
6697
|
doc2.descendants((node, pos) => {
|
|
6566
6698
|
if (!node.isText) return;
|
|
6567
6699
|
const text2 = node.text;
|
|
6568
|
-
|
|
6700
|
+
JINJA_TAG_RE2.lastIndex = 0;
|
|
6569
6701
|
let match;
|
|
6570
|
-
while ((match =
|
|
6702
|
+
while ((match = JINJA_TAG_RE2.exec(text2)) !== null) {
|
|
6571
6703
|
const from = pos + match.index;
|
|
6572
6704
|
const to = from + match[0].length;
|
|
6573
6705
|
const keyword = match[1];
|
|
@@ -6732,6 +6864,7 @@ var JINJA_STYLES = `
|
|
|
6732
6864
|
.jinja-branch-condition {
|
|
6733
6865
|
flex: 1;
|
|
6734
6866
|
min-width: 0;
|
|
6867
|
+
min-height: 20px;
|
|
6735
6868
|
display: flex;
|
|
6736
6869
|
flex-wrap: wrap;
|
|
6737
6870
|
gap: 8px;
|
|
@@ -6909,6 +7042,15 @@ var JINJA_STYLES = `
|
|
|
6909
7042
|
background: rgba(13, 13, 13, 0.04);
|
|
6910
7043
|
}
|
|
6911
7044
|
|
|
7045
|
+
.jinja-ghost-btn.jinja-add-btn {
|
|
7046
|
+
color: #5E5E5E;
|
|
7047
|
+
}
|
|
7048
|
+
|
|
7049
|
+
.jinja-ghost-btn.jinja-add-btn.active {
|
|
7050
|
+
background: #DCDBFF;
|
|
7051
|
+
color: #6210CC;
|
|
7052
|
+
}
|
|
7053
|
+
|
|
6912
7054
|
.jinja-ghost-btn:disabled {
|
|
6913
7055
|
opacity: 0.45;
|
|
6914
7056
|
cursor: default;
|
|
@@ -7103,60 +7245,18 @@ function deleteBranch(view, nodePos, branchType) {
|
|
|
7103
7245
|
const context = getBranchContext(view, nodePos);
|
|
7104
7246
|
if (!context) return false;
|
|
7105
7247
|
const { branchNode, branchPos, branchIndex, blockNode, blockPos } = context;
|
|
7106
|
-
const branchContent = branchNode.content;
|
|
7107
7248
|
if (branchType === "if") {
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
tr2.setSelection(TextSelection4.near(tr2.doc.resolve(blockPos)));
|
|
7113
|
-
} else {
|
|
7114
|
-
tr2.replaceWith(blockPos, blockPos + blockNode.nodeSize, branchContent);
|
|
7115
|
-
tr2.setSelection(TextSelection4.near(tr2.doc.resolve(blockPos)));
|
|
7116
|
-
}
|
|
7117
|
-
view.dispatch(tr2.scrollIntoView());
|
|
7118
|
-
view.focus();
|
|
7119
|
-
return true;
|
|
7120
|
-
}
|
|
7121
|
-
const nextBranch = blockNode.child(branchIndex + 1);
|
|
7122
|
-
const promotedCondition = typeof nextBranch.attrs.condition === "string" ? nextBranch.attrs.condition : "";
|
|
7123
|
-
const tr = view.state.tr;
|
|
7124
|
-
if (!isBranchBodyEmpty(branchNode)) {
|
|
7125
|
-
const nextBranchPos = branchPos + branchNode.nodeSize;
|
|
7126
|
-
const nextBranchContentStart = nextBranchPos + 1;
|
|
7127
|
-
for (let i = branchContent.childCount - 1; i >= 0; i--) {
|
|
7128
|
-
tr.insert(nextBranchContentStart, branchContent.child(i));
|
|
7129
|
-
}
|
|
7130
|
-
}
|
|
7131
|
-
const mappedBranchPos = tr.mapping.map(branchPos);
|
|
7132
|
-
const mappedBranchEnd = tr.mapping.map(branchPos + branchNode.nodeSize);
|
|
7133
|
-
tr.delete(mappedBranchPos, mappedBranchEnd);
|
|
7134
|
-
tr.setNodeMarkup(mappedBranchPos, void 0, {
|
|
7135
|
-
...nextBranch.attrs,
|
|
7136
|
-
branchType: "if",
|
|
7137
|
-
condition: promotedCondition
|
|
7138
|
-
});
|
|
7139
|
-
view.dispatch(tr.scrollIntoView());
|
|
7249
|
+
const tr2 = view.state.tr;
|
|
7250
|
+
tr2.replaceWith(blockPos, blockPos + blockNode.nodeSize, view.state.schema.nodes.paragraph.create());
|
|
7251
|
+
tr2.setSelection(TextSelection4.near(tr2.doc.resolve(blockPos)));
|
|
7252
|
+
view.dispatch(tr2.scrollIntoView());
|
|
7140
7253
|
view.focus();
|
|
7141
7254
|
return true;
|
|
7142
7255
|
}
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
const tr = view.state.tr;
|
|
7148
|
-
for (let i = 0; i < branchContent.childCount; i++) {
|
|
7149
|
-
tr.insert(prevBranchContentEnd + i, branchContent.child(i));
|
|
7150
|
-
}
|
|
7151
|
-
const mappedBranchPos = tr.mapping.map(branchPos);
|
|
7152
|
-
const mappedBranchEnd = tr.mapping.map(branchPos + branchNode.nodeSize);
|
|
7153
|
-
tr.delete(mappedBranchPos, mappedBranchEnd);
|
|
7154
|
-
tr.setSelection(TextSelection4.near(tr.doc.resolve(tr.mapping.map(prevBranchContentEnd)), -1));
|
|
7155
|
-
view.dispatch(tr.scrollIntoView());
|
|
7156
|
-
view.focus();
|
|
7157
|
-
return true;
|
|
7158
|
-
}
|
|
7159
|
-
view.dispatch(view.state.tr.delete(branchPos, branchPos + branchNode.nodeSize).scrollIntoView());
|
|
7256
|
+
const tr = view.state.tr;
|
|
7257
|
+
tr.delete(branchPos, branchPos + branchNode.nodeSize);
|
|
7258
|
+
tr.setSelection(TextSelection4.near(tr.doc.resolve(tr.mapping.map(branchPos)), -1));
|
|
7259
|
+
view.dispatch(tr.scrollIntoView());
|
|
7160
7260
|
view.focus();
|
|
7161
7261
|
return true;
|
|
7162
7262
|
}
|
|
@@ -7204,11 +7304,11 @@ function ConditionDisplay({
|
|
|
7204
7304
|
return /* @__PURE__ */ jsx6("span", { className: "jinja-otherwise", children: "Otherwise" });
|
|
7205
7305
|
}
|
|
7206
7306
|
const commit = () => {
|
|
7207
|
-
setIsEditing(false);
|
|
7208
|
-
onConditionBlur?.();
|
|
7209
7307
|
if (draftValue !== condition) {
|
|
7210
7308
|
onConditionChange(draftValue);
|
|
7211
7309
|
}
|
|
7310
|
+
setIsEditing(false);
|
|
7311
|
+
onConditionBlur?.();
|
|
7212
7312
|
};
|
|
7213
7313
|
const cancel = () => {
|
|
7214
7314
|
setDraftValue(condition);
|
|
@@ -7253,7 +7353,7 @@ function ConditionDisplay({
|
|
|
7253
7353
|
setIsEditing(true);
|
|
7254
7354
|
}
|
|
7255
7355
|
},
|
|
7256
|
-
children: condition.length > 0 ? renderCondition(condition) : /* @__PURE__ */ jsx6("span", { className: "jinja-condition-placeholder", children: CONDITION_PLACEHOLDER })
|
|
7356
|
+
children: condition.length > 0 ? condition.trim().length > 0 ? renderCondition(condition) : /* @__PURE__ */ jsx6("span", { className: "jinja-token-identifier", children: condition }) : /* @__PURE__ */ jsx6("span", { className: "jinja-condition-placeholder", children: CONDITION_PLACEHOLDER })
|
|
7257
7357
|
}
|
|
7258
7358
|
);
|
|
7259
7359
|
}
|
|
@@ -7326,24 +7426,19 @@ function JinjaBranchHeader({
|
|
|
7326
7426
|
};
|
|
7327
7427
|
}, [menuSource]);
|
|
7328
7428
|
const menuItems = [];
|
|
7329
|
-
const isOnlyIfBranch = branchType === "if" && isLastBranch && !hasElseBranch;
|
|
7330
|
-
const canAddElif = editable && branchType !== "else" && (branchType === "elif" || isLastBranch);
|
|
7331
|
-
const canAddElse = editable && branchType !== "else" && isLastBranch && !hasElseBranch;
|
|
7332
|
-
if (canAddElif) {
|
|
7333
|
-
menuItems.push({
|
|
7334
|
-
label: "Else if",
|
|
7335
|
-
onSelect: () => onAddBranch("elif")
|
|
7336
|
-
});
|
|
7337
|
-
}
|
|
7338
|
-
if (canAddElse) {
|
|
7339
|
-
menuItems.push({
|
|
7340
|
-
label: "Else",
|
|
7341
|
-
onSelect: () => onAddBranch("else")
|
|
7342
|
-
});
|
|
7343
|
-
}
|
|
7344
7429
|
if (editable) {
|
|
7430
|
+
if (!hasElseBranch) {
|
|
7431
|
+
menuItems.push({
|
|
7432
|
+
label: "Else if",
|
|
7433
|
+
onSelect: () => onAddBranch("elif")
|
|
7434
|
+
});
|
|
7435
|
+
menuItems.push({
|
|
7436
|
+
label: "Else",
|
|
7437
|
+
onSelect: () => onAddBranch("else")
|
|
7438
|
+
});
|
|
7439
|
+
}
|
|
7345
7440
|
menuItems.push({
|
|
7346
|
-
label:
|
|
7441
|
+
label: "Delete",
|
|
7347
7442
|
onSelect: onDelete
|
|
7348
7443
|
});
|
|
7349
7444
|
}
|
|
@@ -7396,8 +7491,9 @@ function JinjaBranchHeader({
|
|
|
7396
7491
|
BranchPopupMenu,
|
|
7397
7492
|
{
|
|
7398
7493
|
position: { top: 28, right: 0 },
|
|
7399
|
-
items: menuItems.map((item) => ({
|
|
7494
|
+
items: menuItems.filter((item) => item.label === "Delete").map((item) => ({
|
|
7400
7495
|
...item,
|
|
7496
|
+
label: branchType === "if" ? "Delete all" : "Delete",
|
|
7401
7497
|
onSelect: () => {
|
|
7402
7498
|
setMenuSource(null);
|
|
7403
7499
|
item.onSelect();
|
|
@@ -7414,7 +7510,7 @@ function JinjaBranchHeader({
|
|
|
7414
7510
|
"button",
|
|
7415
7511
|
{
|
|
7416
7512
|
type: "button",
|
|
7417
|
-
className:
|
|
7513
|
+
className: `jinja-ghost-btn jinja-add-btn${menuSource === "footer" ? " active" : ""}`,
|
|
7418
7514
|
"aria-label": "Add branch",
|
|
7419
7515
|
disabled: !canOpenFooterMenu,
|
|
7420
7516
|
onMouseDown: (event) => event.preventDefault(),
|
|
@@ -7423,9 +7519,9 @@ function JinjaBranchHeader({
|
|
|
7423
7519
|
setMenuSource((current) => current === "footer" ? null : "footer");
|
|
7424
7520
|
}
|
|
7425
7521
|
},
|
|
7426
|
-
children: /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none",
|
|
7427
|
-
/* @__PURE__ */ jsx6("
|
|
7428
|
-
/* @__PURE__ */ jsx6("
|
|
7522
|
+
children: /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
7523
|
+
/* @__PURE__ */ jsx6("path", { d: "M7.33337 11L7.33337 8.66666L5.00004 8.66666V7.33333L7.33337 7.33333V4.99999H8.66671V7.33333H11V8.66666H8.66671L8.66671 11H7.33337Z", fill: "currentColor" }),
|
|
7524
|
+
/* @__PURE__ */ jsx6("path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M8.00004 14.6667C11.6819 14.6667 14.6667 11.6819 14.6667 7.99999C14.6667 4.3181 11.6819 1.33333 8.00004 1.33333C4.31814 1.33333 1.33337 4.3181 1.33337 7.99999C1.33337 11.6819 4.31814 14.6667 8.00004 14.6667ZM13.3334 7.99999C13.3334 10.9455 10.9456 13.3333 8.00004 13.3333C5.05452 13.3333 2.66671 10.9455 2.66671 7.99999C2.66671 5.05448 5.05452 2.66666 8.00004 2.66666C10.9456 2.66666 13.3334 5.05448 13.3334 7.99999Z", fill: "currentColor" })
|
|
7429
7525
|
] })
|
|
7430
7526
|
}
|
|
7431
7527
|
),
|
|
@@ -7823,7 +7919,7 @@ function createLinkPlugin() {
|
|
|
7823
7919
|
// src/ui/plugin/dragHandlePlugin.ts
|
|
7824
7920
|
import { Plugin as Plugin9, PluginKey as PluginKey7 } from "prosemirror-state";
|
|
7825
7921
|
var PLUGIN_KEY = new PluginKey7("dragHandle");
|
|
7826
|
-
var GRIP_SVG = `<svg width="
|
|
7922
|
+
var GRIP_SVG = `<svg width="16" height="16" viewBox="0 0 12 12" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
7827
7923
|
<circle cx="4" cy="2.5" r="1.2"/><circle cx="8" cy="2.5" r="1.2"/>
|
|
7828
7924
|
<circle cx="4" cy="6" r="1.2"/><circle cx="8" cy="6" r="1.2"/>
|
|
7829
7925
|
<circle cx="4" cy="9.5" r="1.2"/><circle cx="8" cy="9.5" r="1.2"/>
|
|
@@ -8433,6 +8529,7 @@ var DragHandleController = class {
|
|
|
8433
8529
|
this.dropIndicator.className = "ab-drop-indicator";
|
|
8434
8530
|
this.dropIndicator.style.display = "none";
|
|
8435
8531
|
parent.appendChild(this.dropIndicator);
|
|
8532
|
+
this.scrollContainer = this.findScrollContainer(this.view.dom);
|
|
8436
8533
|
this.tickAutoScroll();
|
|
8437
8534
|
}
|
|
8438
8535
|
addGlobalDragListeners(pointerId) {
|
|
@@ -8581,6 +8678,7 @@ var DragHandleController = class {
|
|
|
8581
8678
|
while (current) {
|
|
8582
8679
|
const overflow = getComputedStyle(current).overflowY;
|
|
8583
8680
|
if (overflow === "auto" || overflow === "scroll") return current;
|
|
8681
|
+
if (overflow === "hidden" && (current.classList.contains("ps") || current.scrollHeight > current.clientHeight + 1)) return current;
|
|
8584
8682
|
current = current.parentElement;
|
|
8585
8683
|
}
|
|
8586
8684
|
return el.parentElement ?? el;
|
|
@@ -8654,6 +8752,7 @@ function createDragHandlePlugin() {
|
|
|
8654
8752
|
}
|
|
8655
8753
|
|
|
8656
8754
|
// src/ui/plugin/todoNodeViewPlugin.tsx
|
|
8755
|
+
import { Plugin as Plugin10 } from "prosemirror-state";
|
|
8657
8756
|
function createCheckboxDOM(checked) {
|
|
8658
8757
|
const el = document.createElement("span");
|
|
8659
8758
|
el.contentEditable = "false";
|
|
@@ -8736,14 +8835,63 @@ var TodoListItemView = class {
|
|
|
8736
8835
|
return true;
|
|
8737
8836
|
}
|
|
8738
8837
|
};
|
|
8838
|
+
function createListItemValueResetPlugin() {
|
|
8839
|
+
return new Plugin10({
|
|
8840
|
+
appendTransaction(trs, oldState, newState) {
|
|
8841
|
+
if (!trs.some((tr2) => tr2.docChanged)) return null;
|
|
8842
|
+
const oldCount = oldState.doc.childCount;
|
|
8843
|
+
let hasNewListItems = false;
|
|
8844
|
+
newState.doc.descendants((node) => {
|
|
8845
|
+
if (hasNewListItems) return false;
|
|
8846
|
+
if (node.type.name === "listItem" && node.attrs.value != null) {
|
|
8847
|
+
hasNewListItems = true;
|
|
8848
|
+
}
|
|
8849
|
+
});
|
|
8850
|
+
if (!hasNewListItems) return null;
|
|
8851
|
+
let tr = newState.tr;
|
|
8852
|
+
let changed = false;
|
|
8853
|
+
newState.doc.descendants((node, pos) => {
|
|
8854
|
+
if (node.type.name !== "orderedList") return;
|
|
8855
|
+
let prevValue = null;
|
|
8856
|
+
node.forEach((li, offset) => {
|
|
8857
|
+
const liValue = li.attrs.value;
|
|
8858
|
+
if (liValue != null && liValue === prevValue) {
|
|
8859
|
+
const liPos = pos + 1 + offset;
|
|
8860
|
+
tr = tr.setNodeMarkup(liPos, void 0, { ...li.attrs, value: null });
|
|
8861
|
+
changed = true;
|
|
8862
|
+
}
|
|
8863
|
+
prevValue = liValue;
|
|
8864
|
+
});
|
|
8865
|
+
});
|
|
8866
|
+
return changed ? tr : null;
|
|
8867
|
+
}
|
|
8868
|
+
});
|
|
8869
|
+
}
|
|
8739
8870
|
function createTodoNodeViewPlugin() {
|
|
8740
8871
|
return {
|
|
8741
8872
|
name: "todoNodeView",
|
|
8873
|
+
plugins: () => [createListItemValueResetPlugin()],
|
|
8742
8874
|
nodeViews: () => ({
|
|
8743
8875
|
listItem: ((node, view, getPos) => {
|
|
8744
8876
|
if (node.attrs.checked == null) {
|
|
8745
8877
|
const li = document.createElement("li");
|
|
8746
|
-
|
|
8878
|
+
if (node.attrs.value != null) {
|
|
8879
|
+
li.value = node.attrs.value;
|
|
8880
|
+
}
|
|
8881
|
+
return {
|
|
8882
|
+
dom: li,
|
|
8883
|
+
contentDOM: li,
|
|
8884
|
+
update(updatedNode) {
|
|
8885
|
+
if (updatedNode.type.name !== "listItem") return false;
|
|
8886
|
+
if (updatedNode.attrs.checked != null) return false;
|
|
8887
|
+
if (updatedNode.attrs.value != null) {
|
|
8888
|
+
li.value = updatedNode.attrs.value;
|
|
8889
|
+
} else {
|
|
8890
|
+
li.removeAttribute("value");
|
|
8891
|
+
}
|
|
8892
|
+
return true;
|
|
8893
|
+
}
|
|
8894
|
+
};
|
|
8747
8895
|
}
|
|
8748
8896
|
return new TodoListItemView(node, view, getPos);
|
|
8749
8897
|
})
|
|
@@ -8752,7 +8900,7 @@ function createTodoNodeViewPlugin() {
|
|
|
8752
8900
|
}
|
|
8753
8901
|
|
|
8754
8902
|
// src/ui/plugin/placeholderPlugin.ts
|
|
8755
|
-
import { Plugin as
|
|
8903
|
+
import { Plugin as Plugin11, PluginKey as PluginKey8 } from "prosemirror-state";
|
|
8756
8904
|
import { Decoration as Decoration5, DecorationSet as DecorationSet5 } from "prosemirror-view";
|
|
8757
8905
|
var pluginKey2 = new PluginKey8("placeholder");
|
|
8758
8906
|
function buildDecorations4(state) {
|
|
@@ -8771,7 +8919,8 @@ function buildDecorations4(state) {
|
|
|
8771
8919
|
}
|
|
8772
8920
|
const pos = $from.before($from.depth);
|
|
8773
8921
|
const deco = Decoration5.node(pos, pos + parent.nodeSize, {
|
|
8774
|
-
class: "ab-empty-paragraph"
|
|
8922
|
+
class: "ab-empty-paragraph",
|
|
8923
|
+
"data-placeholder": "Type to start writing, or press / to insert an action."
|
|
8775
8924
|
});
|
|
8776
8925
|
return DecorationSet5.create(doc2, [deco]);
|
|
8777
8926
|
}
|
|
@@ -8780,7 +8929,7 @@ function createPlaceholderPlugin() {
|
|
|
8780
8929
|
return {
|
|
8781
8930
|
name: "placeholder",
|
|
8782
8931
|
plugins: () => [
|
|
8783
|
-
new
|
|
8932
|
+
new Plugin11({
|
|
8784
8933
|
key: pluginKey2,
|
|
8785
8934
|
view(editorView) {
|
|
8786
8935
|
isEditable = editorView.editable;
|
|
@@ -8899,27 +9048,49 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
8899
9048
|
view.focus();
|
|
8900
9049
|
}
|
|
8901
9050
|
}
|
|
9051
|
+
if (e.key === "Escape") {
|
|
9052
|
+
e.preventDefault();
|
|
9053
|
+
e.stopPropagation();
|
|
9054
|
+
if (range) {
|
|
9055
|
+
view.dispatch(view.state.tr.delete(range.from, range.to));
|
|
9056
|
+
}
|
|
9057
|
+
view.focus();
|
|
9058
|
+
}
|
|
8902
9059
|
};
|
|
8903
9060
|
document.addEventListener("keydown", onKeyDown, true);
|
|
8904
9061
|
return () => document.removeEventListener("keydown", onKeyDown, true);
|
|
8905
9062
|
}, [active, view, filtered, selectedIndex, range]);
|
|
8906
|
-
|
|
8907
|
-
const
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
9063
|
+
const [menuPos, setMenuPos] = useState4(null);
|
|
9064
|
+
const menuRef = useRef4(null);
|
|
9065
|
+
useLayoutEffect(() => {
|
|
9066
|
+
if (!active || !view || !range || filtered.length === 0) {
|
|
9067
|
+
setMenuPos(null);
|
|
9068
|
+
return;
|
|
9069
|
+
}
|
|
9070
|
+
try {
|
|
9071
|
+
const coords = view.coordsAtPos(range.to);
|
|
9072
|
+
let left = coords.left;
|
|
9073
|
+
left = Math.max(VPORT_MARGIN, Math.min(left, window.innerWidth - MENU_WIDTH - VPORT_MARGIN));
|
|
9074
|
+
const menuHeight = menuRef.current?.offsetHeight ?? MAX_MENU_H;
|
|
9075
|
+
let top = coords.bottom + 4;
|
|
9076
|
+
if (top + menuHeight > window.innerHeight - VPORT_MARGIN) {
|
|
9077
|
+
top = coords.top - menuHeight - 4;
|
|
9078
|
+
}
|
|
9079
|
+
setMenuPos({ top, left });
|
|
9080
|
+
} catch {
|
|
9081
|
+
}
|
|
9082
|
+
});
|
|
9083
|
+
if (!active || !view || !range || filtered.length === 0 || !menuPos) return null;
|
|
8914
9084
|
return createPortal2(
|
|
8915
9085
|
/* @__PURE__ */ jsx7(
|
|
8916
9086
|
"div",
|
|
8917
9087
|
{
|
|
9088
|
+
ref: menuRef,
|
|
8918
9089
|
className: "ab-slash-menu",
|
|
8919
9090
|
style: {
|
|
8920
9091
|
position: "fixed",
|
|
8921
|
-
top,
|
|
8922
|
-
left,
|
|
9092
|
+
top: menuPos.top,
|
|
9093
|
+
left: menuPos.left,
|
|
8923
9094
|
width: MENU_WIDTH,
|
|
8924
9095
|
maxHeight: MAX_MENU_H,
|
|
8925
9096
|
overflowY: "auto",
|
|
@@ -9594,7 +9765,7 @@ function DropdownItem({ item, onRun }) {
|
|
|
9594
9765
|
transition: "background 0.1s"
|
|
9595
9766
|
},
|
|
9596
9767
|
children: [
|
|
9597
|
-
/* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: "#6210CC" }, children: item.shortLabel }),
|
|
9768
|
+
/* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: item.active ? "#6210CC" : "#666" }, children: item.shortLabel }),
|
|
9598
9769
|
item.label
|
|
9599
9770
|
]
|
|
9600
9771
|
}
|
|
@@ -10718,7 +10889,7 @@ function FloatingMenu({ view, editorState }) {
|
|
|
10718
10889
|
}
|
|
10719
10890
|
|
|
10720
10891
|
// src/ui/plugin/inlineSuggestPlugin.ts
|
|
10721
|
-
import { Plugin as
|
|
10892
|
+
import { Plugin as Plugin12, PluginKey as PluginKey9 } from "prosemirror-state";
|
|
10722
10893
|
import { Decoration as Decoration6, DecorationSet as DecorationSet6 } from "prosemirror-view";
|
|
10723
10894
|
var inlineSuggestKey = new PluginKey9("inlineSuggest");
|
|
10724
10895
|
var DEBOUNCE_MS = 600;
|
|
@@ -10727,7 +10898,7 @@ function createInlineSuggestPlugin(provider, endpoint, options) {
|
|
|
10727
10898
|
return {
|
|
10728
10899
|
name: "inlineSuggest",
|
|
10729
10900
|
plugins: () => [
|
|
10730
|
-
new
|
|
10901
|
+
new Plugin12({
|
|
10731
10902
|
key: inlineSuggestKey,
|
|
10732
10903
|
state: {
|
|
10733
10904
|
init: () => ({ suggestion: null, anchorPos: null }),
|