@dxos/react-ui-editor 0.3.11-main.346d280 → 0.3.11-main.3a8a0ef
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/lib/browser/index.mjs +111 -65
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +4 -0
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/tasklist.d.ts +5 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/package.json +25 -25
- package/src/components/TextEditor/comments.stories.tsx +15 -1
- package/src/extensions/comments.ts +66 -1
- package/src/extensions/tasklist.ts +51 -75
- package/src/extensions/yjs/yjs.test.ts +1 -1
- package/src/themes/default.ts +0 -8
|
@@ -1214,6 +1214,60 @@ var highlightDecorations = EditorView5.decorations.compute([
|
|
|
1214
1214
|
}).filter(nonNullable) ?? [];
|
|
1215
1215
|
return Decoration3.set(decorations);
|
|
1216
1216
|
});
|
|
1217
|
+
var trackPastedComments = (onMove) => {
|
|
1218
|
+
let tracked = null;
|
|
1219
|
+
const registerCopy = (event, view) => {
|
|
1220
|
+
const comments2 = view.state.field(commentsStateField);
|
|
1221
|
+
const { main } = view.state.selection;
|
|
1222
|
+
const inSel = comments2.ranges.filter((range) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1223
|
+
if (!inSel.length) {
|
|
1224
|
+
tracked = null;
|
|
1225
|
+
} else {
|
|
1226
|
+
tracked = {
|
|
1227
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1228
|
+
comments: inSel.map((range) => ({
|
|
1229
|
+
from: range.from - main.from,
|
|
1230
|
+
to: range.to - main.from,
|
|
1231
|
+
id: range.id
|
|
1232
|
+
}))
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
return [
|
|
1237
|
+
EditorView5.domEventHandlers({
|
|
1238
|
+
cut: registerCopy,
|
|
1239
|
+
copy: registerCopy
|
|
1240
|
+
}),
|
|
1241
|
+
EditorView5.updateListener.of((update2) => {
|
|
1242
|
+
if (tracked) {
|
|
1243
|
+
const paste = update2.transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1244
|
+
if (paste) {
|
|
1245
|
+
let found = -1;
|
|
1246
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1247
|
+
if (text.eq(tracked.text)) {
|
|
1248
|
+
for (let i = update2.transactions.indexOf(paste) + 1; i < update2.transactions.length; i++) {
|
|
1249
|
+
fromB = update2.transactions[i].changes.mapPos(fromB);
|
|
1250
|
+
}
|
|
1251
|
+
found = fromB;
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
1254
|
+
if (found > -1) {
|
|
1255
|
+
const active = update2.view.state.field(commentsStateField).ranges;
|
|
1256
|
+
for (const moved of tracked.comments) {
|
|
1257
|
+
if (active.some((range) => range.id === moved.id && range.from === range.to)) {
|
|
1258
|
+
onMove(moved.id, Cursor.getCursorFromRange(update2.view.state.facet(Cursor.converter), {
|
|
1259
|
+
from: found + moved.from,
|
|
1260
|
+
to: found + moved.to
|
|
1261
|
+
}));
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
tracked = null;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
})
|
|
1269
|
+
];
|
|
1270
|
+
};
|
|
1217
1271
|
var comments = (options = {}) => {
|
|
1218
1272
|
const { key: shortcut = "meta-'" } = options;
|
|
1219
1273
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
@@ -1221,7 +1275,7 @@ var comments = (options = {}) => {
|
|
|
1221
1275
|
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1222
1276
|
invariant2(options.onCreate, void 0, {
|
|
1223
1277
|
F: __dxlog_file3,
|
|
1224
|
-
L:
|
|
1278
|
+
L: 240,
|
|
1225
1279
|
S: void 0,
|
|
1226
1280
|
A: [
|
|
1227
1281
|
"options.onCreate",
|
|
@@ -1324,7 +1378,7 @@ var comments = (options = {}) => {
|
|
|
1324
1378
|
thread: range.id
|
|
1325
1379
|
}, {
|
|
1326
1380
|
F: __dxlog_file3,
|
|
1327
|
-
L:
|
|
1381
|
+
L: 337,
|
|
1328
1382
|
S: void 0,
|
|
1329
1383
|
C: (f, a) => f(...a)
|
|
1330
1384
|
});
|
|
@@ -1377,7 +1431,8 @@ var comments = (options = {}) => {
|
|
|
1377
1431
|
});
|
|
1378
1432
|
}
|
|
1379
1433
|
}
|
|
1380
|
-
})
|
|
1434
|
+
}),
|
|
1435
|
+
options.onMove ? trackPastedComments(options.onMove) : []
|
|
1381
1436
|
];
|
|
1382
1437
|
};
|
|
1383
1438
|
|
|
@@ -2025,87 +2080,85 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2025
2080
|
};
|
|
2026
2081
|
|
|
2027
2082
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2028
|
-
import {
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
paddingLeft: "4px",
|
|
2032
|
-
paddingRight: "8px"
|
|
2033
|
-
}
|
|
2034
|
-
});
|
|
2083
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2084
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
2085
|
+
import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
2035
2086
|
var CheckboxWidget = class extends WidgetType6 {
|
|
2036
|
-
constructor(_checked
|
|
2087
|
+
constructor(_checked) {
|
|
2037
2088
|
super();
|
|
2038
2089
|
this._checked = _checked;
|
|
2039
|
-
this._indent = _indent;
|
|
2040
|
-
this._onCheck = _onCheck;
|
|
2041
2090
|
}
|
|
2042
2091
|
eq(other) {
|
|
2043
|
-
return this._checked === other._checked
|
|
2092
|
+
return this._checked === other._checked;
|
|
2044
2093
|
}
|
|
2045
2094
|
toDOM(view) {
|
|
2046
|
-
const
|
|
2047
|
-
wrap.className = "cm-task-item";
|
|
2048
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
2049
|
-
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
2050
|
-
const input = wrap.appendChild(document.createElement("input"));
|
|
2095
|
+
const input = document.createElement("input");
|
|
2051
2096
|
input.type = "checkbox";
|
|
2052
2097
|
input.checked = this._checked;
|
|
2053
|
-
if (
|
|
2098
|
+
if (view.state.readOnly) {
|
|
2054
2099
|
input.setAttribute("disabled", "true");
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2100
|
+
} else {
|
|
2101
|
+
input.onmousedown = (event) => {
|
|
2102
|
+
const pos = view.posAtDOM(input);
|
|
2103
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2104
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2105
|
+
view.dispatch({
|
|
2106
|
+
changes: {
|
|
2107
|
+
from: pos + 1,
|
|
2108
|
+
to: pos + 2,
|
|
2109
|
+
insert: this._checked ? " " : "x"
|
|
2110
|
+
}
|
|
2111
|
+
});
|
|
2112
|
+
event.preventDefault();
|
|
2113
|
+
}
|
|
2060
2114
|
};
|
|
2061
2115
|
}
|
|
2062
|
-
return
|
|
2116
|
+
return input;
|
|
2063
2117
|
}
|
|
2064
2118
|
ignoreEvent() {
|
|
2065
2119
|
return false;
|
|
2066
2120
|
}
|
|
2067
2121
|
};
|
|
2122
|
+
var checkedDeco = Decoration8.replace({
|
|
2123
|
+
widget: new CheckboxWidget(true)
|
|
2124
|
+
});
|
|
2125
|
+
var uncheckedDeco = Decoration8.replace({
|
|
2126
|
+
widget: new CheckboxWidget(false)
|
|
2127
|
+
});
|
|
2068
2128
|
var tasklist = (options = {}) => {
|
|
2069
|
-
|
|
2070
|
-
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
2071
|
-
decoration: (match, view, pos) => {
|
|
2072
|
-
const indent = Math.floor(match[1].length / 2);
|
|
2073
|
-
const checked = match[2] === "x" || match[2] === "X";
|
|
2074
|
-
return Decoration8.replace({
|
|
2075
|
-
widget: new CheckboxWidget(checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2076
|
-
const idx = pos + match[0].indexOf("[") + 1;
|
|
2077
|
-
view.dispatch({
|
|
2078
|
-
changes: {
|
|
2079
|
-
from: idx,
|
|
2080
|
-
to: idx + 1,
|
|
2081
|
-
insert: checked2 ? "x" : " "
|
|
2082
|
-
},
|
|
2083
|
-
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
2084
|
-
selection: {
|
|
2085
|
-
anchor: idx + 3
|
|
2086
|
-
}
|
|
2087
|
-
});
|
|
2088
|
-
})
|
|
2089
|
-
});
|
|
2090
|
-
}
|
|
2091
|
-
});
|
|
2092
|
-
const tasks = ViewPlugin6.fromClass(class {
|
|
2129
|
+
return ViewPlugin6.fromClass(class {
|
|
2093
2130
|
constructor(view) {
|
|
2094
|
-
this.
|
|
2131
|
+
this.decorations = buildDecorations3(view);
|
|
2095
2132
|
}
|
|
2096
2133
|
update(update2) {
|
|
2097
|
-
|
|
2134
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2135
|
+
this.decorations = buildDecorations3(update2.view);
|
|
2136
|
+
}
|
|
2098
2137
|
}
|
|
2099
2138
|
}, {
|
|
2100
|
-
decorations: (
|
|
2139
|
+
decorations: (v) => v.decorations,
|
|
2101
2140
|
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2102
|
-
return view.plugin(plugin)?.
|
|
2141
|
+
return view.plugin(plugin)?.decorations || Decoration8.none;
|
|
2103
2142
|
})
|
|
2104
2143
|
});
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2144
|
+
};
|
|
2145
|
+
var buildDecorations3 = (view) => {
|
|
2146
|
+
const builder = new RangeSetBuilder3();
|
|
2147
|
+
const { state } = view;
|
|
2148
|
+
const cursor = state.selection.main.head;
|
|
2149
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2150
|
+
syntaxTree4(state).iterate({
|
|
2151
|
+
enter: (node) => {
|
|
2152
|
+
if (node.name === "TaskMarker" && (cursor < node.from || cursor > node.to)) {
|
|
2153
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2154
|
+
builder.add(node.from, node.to, checked ? checkedDeco : uncheckedDeco);
|
|
2155
|
+
}
|
|
2156
|
+
},
|
|
2157
|
+
from,
|
|
2158
|
+
to
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2161
|
+
return builder.finish();
|
|
2109
2162
|
};
|
|
2110
2163
|
|
|
2111
2164
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
@@ -2315,13 +2368,6 @@ var defaultTheme = {
|
|
|
2315
2368
|
textDecoration: "none"
|
|
2316
2369
|
},
|
|
2317
2370
|
//
|
|
2318
|
-
// widgets
|
|
2319
|
-
//
|
|
2320
|
-
".cm-widgetBuffer": {
|
|
2321
|
-
display: "none",
|
|
2322
|
-
height: 0
|
|
2323
|
-
},
|
|
2324
|
-
//
|
|
2325
2371
|
// table
|
|
2326
2372
|
//
|
|
2327
2373
|
".cm-table *": {
|