@dxos/react-ui-editor 0.4.8-main.97e86fe → 0.4.8-main.a4c603b
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 +941 -776
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +103 -0
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +34 -18
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +5 -79
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +15 -1
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/index.d.ts +1 -0
- package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/sync.d.ts +1 -2
- package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +1 -2
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness.d.ts.map +1 -0
- package/dist/types/src/extensions/comments.d.ts +2 -2
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/cursor-line-margin.d.ts +7 -6
- package/dist/types/src/extensions/cursor-line-margin.d.ts.map +1 -1
- package/dist/types/src/extensions/cursor.d.ts +1 -1
- package/dist/types/src/extensions/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +1 -3
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +4 -5
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/table.d.ts +2 -2
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner.d.ts +4 -0
- package/dist/types/src/extensions/outliner.d.ts.map +1 -0
- package/dist/types/src/{extensions/awareness → hooks}/awareness-provider.d.ts +1 -1
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -0
- package/dist/types/src/hooks/defs.d.ts +20 -0
- package/dist/types/src/hooks/defs.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +4 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useEditorView.d.ts +20 -0
- package/dist/types/src/hooks/useEditorView.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +44 -3
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.stories.d.ts +0 -6
- package/dist/types/src/hooks/useTextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +33 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -0
- package/dist/types/src/themes/default.d.ts +3 -0
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/package.json +24 -24
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +524 -0
- package/src/components/TextEditor/TextEditor.stories.tsx +23 -508
- package/src/components/TextEditor/TextEditor.tsx +149 -37
- package/src/components/Toolbar/Toolbar.stories.tsx +42 -42
- package/src/extensions/automerge/automerge.stories.tsx +17 -16
- package/src/extensions/automerge/automerge.ts +1 -2
- package/src/extensions/automerge/cursor.ts +1 -1
- package/src/extensions/automerge/defs.ts +22 -1
- package/src/extensions/automerge/index.ts +1 -0
- package/src/extensions/automerge/sync.ts +9 -2
- package/src/extensions/automerge/update-automerge.ts +1 -2
- package/src/extensions/{awareness/awareness.ts → awareness.ts} +1 -1
- package/src/extensions/command/state.ts +1 -1
- package/src/extensions/comments.ts +5 -9
- package/src/extensions/cursor-line-margin.ts +18 -17
- package/src/extensions/cursor.ts +1 -1
- package/src/extensions/index.ts +1 -3
- package/src/extensions/markdown/bundle.ts +28 -11
- package/src/extensions/markdown/decorate.ts +4 -2
- package/src/extensions/markdown/formatting.ts +10 -15
- package/src/extensions/markdown/image.ts +0 -1
- package/src/extensions/markdown/table.ts +3 -11
- package/src/extensions/outliner.ts +12 -0
- package/src/{extensions/awareness → hooks}/awareness-provider.ts +1 -1
- package/src/hooks/defs.ts +30 -0
- package/src/hooks/index.ts +5 -1
- package/src/hooks/useEditorView.ts +32 -0
- package/src/hooks/useTextEditor.stories.tsx +34 -39
- package/src/hooks/useTextEditor.ts +120 -11
- package/src/hooks/useTextModel.ts +121 -0
- package/src/index.ts +1 -1
- package/src/themes/default.ts +28 -1
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness/awareness.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness/index.d.ts +0 -3
- package/dist/types/src/extensions/awareness/index.d.ts.map +0 -1
- package/dist/types/src/extensions/doc.d.ts +0 -3
- package/dist/types/src/extensions/doc.d.ts.map +0 -1
- package/dist/types/src/extensions/factories.d.ts +0 -49
- package/dist/types/src/extensions/factories.d.ts.map +0 -1
- package/dist/types/src/extensions/types.d.ts +0 -9
- package/dist/types/src/extensions/types.d.ts.map +0 -1
- package/dist/types/src/hooks/useDocAccessor.d.ts +0 -7
- package/dist/types/src/hooks/useDocAccessor.d.ts.map +0 -1
- package/src/extensions/awareness/index.ts +0 -6
- package/src/extensions/doc.ts +0 -14
- package/src/extensions/factories.ts +0 -167
- package/src/extensions/types.ts +0 -16
- package/src/hooks/useDocAccessor.ts +0 -21
- /package/dist/types/src/extensions/{awareness/awareness.d.ts → awareness.d.ts} +0 -0
|
@@ -29,12 +29,16 @@ import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
|
29
29
|
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
30
30
|
|
|
31
31
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
32
|
-
import { EditorState as
|
|
33
|
-
import { EditorView as
|
|
32
|
+
import { EditorState as EditorState3 } from "@codemirror/state";
|
|
33
|
+
import { EditorView as EditorView17, scrollPastEnd as scrollPastEnd2 } from "@codemirror/view";
|
|
34
34
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
35
|
-
import
|
|
35
|
+
import defaultsDeep3 from "lodash.defaultsdeep";
|
|
36
|
+
import React, { forwardRef, useCallback, useEffect as useEffect3, useImperativeHandle, useRef as useRef3, useState as useState5, useMemo as useMemo3 } from "react";
|
|
37
|
+
import { DocAccessor } from "@dxos/echo-schema";
|
|
36
38
|
import { log as log9 } from "@dxos/log";
|
|
37
|
-
import {
|
|
39
|
+
import { useThemeContext } from "@dxos/react-ui";
|
|
40
|
+
import { focusRing } from "@dxos/react-ui-theme";
|
|
41
|
+
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
38
42
|
|
|
39
43
|
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
|
40
44
|
import { StateField } from "@codemirror/state";
|
|
@@ -239,6 +243,7 @@ var cursorConverter = ({ handle, path }) => ({
|
|
|
239
243
|
|
|
240
244
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
241
245
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
246
|
+
import get2 from "lodash.get";
|
|
242
247
|
var getPath = (state, field) => state.field(field).path;
|
|
243
248
|
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
244
249
|
var updateHeadsEffect = StateEffect.define({});
|
|
@@ -492,7 +497,7 @@ var automerge = (accessor) => {
|
|
|
492
497
|
];
|
|
493
498
|
};
|
|
494
499
|
|
|
495
|
-
// packages/ui/react-ui-editor/src/extensions/awareness
|
|
500
|
+
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
496
501
|
import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
|
|
497
502
|
import { Decoration as Decoration2, EditorView as EditorView3, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
498
503
|
import { Event } from "@dxos/async";
|
|
@@ -727,115 +732,11 @@ var styles2 = EditorView3.baseTheme({
|
|
|
727
732
|
}
|
|
728
733
|
});
|
|
729
734
|
|
|
730
|
-
// packages/ui/react-ui-editor/src/extensions/awareness/awareness-provider.ts
|
|
731
|
-
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
732
|
-
import { Context as Context2 } from "@dxos/context";
|
|
733
|
-
import { invariant } from "@dxos/invariant";
|
|
734
|
-
import { log as log2 } from "@dxos/log";
|
|
735
|
-
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness-provider.ts";
|
|
736
|
-
var DEBOUNCE_INTERVAL = 100;
|
|
737
|
-
var SpaceAwarenessProvider = class {
|
|
738
|
-
constructor(params) {
|
|
739
|
-
this._remoteStates = /* @__PURE__ */ new Map();
|
|
740
|
-
this.remoteStateChange = new Event2();
|
|
741
|
-
this._space = params.space;
|
|
742
|
-
this._channel = params.channel;
|
|
743
|
-
this._peerId = params.peerId;
|
|
744
|
-
this._info = params.info;
|
|
745
|
-
}
|
|
746
|
-
open() {
|
|
747
|
-
this._ctx = new Context2();
|
|
748
|
-
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
749
|
-
if (this._localState) {
|
|
750
|
-
await this._space.postMessage(this._channel, {
|
|
751
|
-
kind: "post",
|
|
752
|
-
state: this._localState
|
|
753
|
-
});
|
|
754
|
-
await sleep(DEBOUNCE_INTERVAL);
|
|
755
|
-
}
|
|
756
|
-
});
|
|
757
|
-
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
758
|
-
switch (message.payload.kind) {
|
|
759
|
-
case "query": {
|
|
760
|
-
this._handleQueryMessage();
|
|
761
|
-
break;
|
|
762
|
-
}
|
|
763
|
-
case "post": {
|
|
764
|
-
this._handlePostMessage(message.payload);
|
|
765
|
-
break;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
}));
|
|
769
|
-
void this._space.postMessage(this._channel, {
|
|
770
|
-
kind: "query"
|
|
771
|
-
}).catch((err) => {
|
|
772
|
-
log2.debug("failed to query awareness", {
|
|
773
|
-
err
|
|
774
|
-
}, {
|
|
775
|
-
F: __dxlog_file2,
|
|
776
|
-
L: 89,
|
|
777
|
-
S: this,
|
|
778
|
-
C: (f, a) => f(...a)
|
|
779
|
-
});
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
close() {
|
|
783
|
-
void this._ctx?.dispose();
|
|
784
|
-
this._ctx = void 0;
|
|
785
|
-
this._postTask = void 0;
|
|
786
|
-
}
|
|
787
|
-
getRemoteStates() {
|
|
788
|
-
return Array.from(this._remoteStates.values());
|
|
789
|
-
}
|
|
790
|
-
update(position) {
|
|
791
|
-
invariant(this._postTask, void 0, {
|
|
792
|
-
F: __dxlog_file2,
|
|
793
|
-
L: 104,
|
|
794
|
-
S: this,
|
|
795
|
-
A: [
|
|
796
|
-
"this._postTask",
|
|
797
|
-
""
|
|
798
|
-
]
|
|
799
|
-
});
|
|
800
|
-
this._localState = {
|
|
801
|
-
peerId: this._peerId,
|
|
802
|
-
position,
|
|
803
|
-
info: this._info
|
|
804
|
-
};
|
|
805
|
-
this._postTask.schedule();
|
|
806
|
-
}
|
|
807
|
-
_handleQueryMessage() {
|
|
808
|
-
invariant(this._postTask, void 0, {
|
|
809
|
-
F: __dxlog_file2,
|
|
810
|
-
L: 115,
|
|
811
|
-
S: this,
|
|
812
|
-
A: [
|
|
813
|
-
"this._postTask",
|
|
814
|
-
""
|
|
815
|
-
]
|
|
816
|
-
});
|
|
817
|
-
this._postTask.schedule();
|
|
818
|
-
}
|
|
819
|
-
_handlePostMessage(message) {
|
|
820
|
-
invariant(message.kind === "post", void 0, {
|
|
821
|
-
F: __dxlog_file2,
|
|
822
|
-
L: 120,
|
|
823
|
-
S: this,
|
|
824
|
-
A: [
|
|
825
|
-
"message.kind === 'post'",
|
|
826
|
-
""
|
|
827
|
-
]
|
|
828
|
-
});
|
|
829
|
-
this._remoteStates.set(message.state.peerId, message.state);
|
|
830
|
-
this.remoteStateChange.emit();
|
|
831
|
-
}
|
|
832
|
-
};
|
|
833
|
-
|
|
834
735
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
835
736
|
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
836
737
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
837
|
-
import { invariant
|
|
838
|
-
var
|
|
738
|
+
import { invariant } from "@dxos/invariant";
|
|
739
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
839
740
|
var defaultOptions = {
|
|
840
741
|
effect: 2,
|
|
841
742
|
maxParticles: 200,
|
|
@@ -961,8 +862,8 @@ var Blaster = class {
|
|
|
961
862
|
return this._node;
|
|
962
863
|
}
|
|
963
864
|
initialize() {
|
|
964
|
-
|
|
965
|
-
F:
|
|
865
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
866
|
+
F: __dxlog_file2,
|
|
966
867
|
L: 141,
|
|
967
868
|
S: this,
|
|
968
869
|
A: [
|
|
@@ -998,8 +899,8 @@ var Blaster = class {
|
|
|
998
899
|
}
|
|
999
900
|
}
|
|
1000
901
|
start() {
|
|
1001
|
-
|
|
1002
|
-
F:
|
|
902
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
903
|
+
F: __dxlog_file2,
|
|
1003
904
|
L: 180,
|
|
1004
905
|
S: this,
|
|
1005
906
|
A: [
|
|
@@ -1209,8 +1110,8 @@ var commandState = StateField3.define({
|
|
|
1209
1110
|
}
|
|
1210
1111
|
return state;
|
|
1211
1112
|
},
|
|
1212
|
-
provide: (
|
|
1213
|
-
showTooltip.from(
|
|
1113
|
+
provide: (f) => [
|
|
1114
|
+
showTooltip.from(f, (value) => value.tooltip ?? null)
|
|
1214
1115
|
]
|
|
1215
1116
|
});
|
|
1216
1117
|
var openEffect = StateEffect2.define();
|
|
@@ -1365,7 +1266,7 @@ import { hoverTooltip, keymap as keymap4, Decoration as Decoration4, EditorView
|
|
|
1365
1266
|
import sortBy from "lodash.sortby";
|
|
1366
1267
|
import { useEffect } from "react";
|
|
1367
1268
|
import { debounce } from "@dxos/async";
|
|
1368
|
-
import { log as
|
|
1269
|
+
import { log as log3 } from "@dxos/log";
|
|
1369
1270
|
import { nonNullable } from "@dxos/util";
|
|
1370
1271
|
|
|
1371
1272
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
@@ -1392,10 +1293,10 @@ var inlineUrl = mx(code, "px-1");
|
|
|
1392
1293
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
1393
1294
|
|
|
1394
1295
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1395
|
-
import
|
|
1296
|
+
import get3 from "lodash.get";
|
|
1396
1297
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1397
1298
|
var tokens = tailwindConfig({}).theme;
|
|
1398
|
-
var getToken = (path, defaultValue = void 0) =>
|
|
1299
|
+
var getToken = (path, defaultValue = void 0) => get3(tokens, path, defaultValue);
|
|
1399
1300
|
|
|
1400
1301
|
// packages/ui/react-ui-editor/src/styles/layout.ts
|
|
1401
1302
|
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
|
@@ -1403,14 +1304,14 @@ var editorFillLayoutRoot = "bs-full relative";
|
|
|
1403
1304
|
var editorFillLayoutEditor = "!absolute inset-0";
|
|
1404
1305
|
|
|
1405
1306
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1406
|
-
import { log as
|
|
1407
|
-
var
|
|
1307
|
+
import { log as log2 } from "@dxos/log";
|
|
1308
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1408
1309
|
var callbackWrapper = (fn) => (...args) => {
|
|
1409
1310
|
try {
|
|
1410
1311
|
return fn(...args);
|
|
1411
1312
|
} catch (err) {
|
|
1412
|
-
|
|
1413
|
-
F:
|
|
1313
|
+
log2.catch(err, void 0, {
|
|
1314
|
+
F: __dxlog_file3,
|
|
1414
1315
|
L: 18,
|
|
1415
1316
|
S: void 0,
|
|
1416
1317
|
C: (f, a) => f(...a)
|
|
@@ -1433,10 +1334,10 @@ var logChanges = (trs) => {
|
|
|
1433
1334
|
return changes2;
|
|
1434
1335
|
}).filter(Boolean);
|
|
1435
1336
|
if (changes.length) {
|
|
1436
|
-
|
|
1337
|
+
log2.info("changes", {
|
|
1437
1338
|
changes
|
|
1438
1339
|
}, {
|
|
1439
|
-
F:
|
|
1340
|
+
F: __dxlog_file3,
|
|
1440
1341
|
L: 39,
|
|
1441
1342
|
S: void 0,
|
|
1442
1343
|
C: (f, a) => f(...a)
|
|
@@ -1445,7 +1346,7 @@ var logChanges = (trs) => {
|
|
|
1445
1346
|
};
|
|
1446
1347
|
|
|
1447
1348
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1448
|
-
var
|
|
1349
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1449
1350
|
var documentId = Facet4.define({
|
|
1450
1351
|
combine: (values) => values[0]
|
|
1451
1352
|
});
|
|
@@ -1531,8 +1432,8 @@ var commentsDecorations = EditorView7.decorations.compute([
|
|
|
1531
1432
|
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1532
1433
|
const range = comment.range;
|
|
1533
1434
|
if (!range || range.from === range.to) {
|
|
1534
|
-
|
|
1535
|
-
F:
|
|
1435
|
+
log3.warn("Invalid range:", range, {
|
|
1436
|
+
F: __dxlog_file4,
|
|
1536
1437
|
L: 132,
|
|
1537
1438
|
S: void 0,
|
|
1538
1439
|
C: (f, a) => f(...a)
|
|
@@ -1834,14 +1735,12 @@ var focusComment = (view, id, center = true) => {
|
|
|
1834
1735
|
var useComments = (view, id, comments2 = []) => {
|
|
1835
1736
|
useEffect(() => {
|
|
1836
1737
|
if (view) {
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
});
|
|
1844
|
-
}
|
|
1738
|
+
view.dispatch({
|
|
1739
|
+
effects: setComments.of({
|
|
1740
|
+
id,
|
|
1741
|
+
comments: comments2
|
|
1742
|
+
})
|
|
1743
|
+
});
|
|
1845
1744
|
}
|
|
1846
1745
|
}, [
|
|
1847
1746
|
id,
|
|
@@ -1851,97 +1750,74 @@ var useComments = (view, id, comments2 = []) => {
|
|
|
1851
1750
|
};
|
|
1852
1751
|
|
|
1853
1752
|
// packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts
|
|
1854
|
-
import { Transaction } from "@codemirror/state";
|
|
1753
|
+
import { Facet as Facet5, Transaction } from "@codemirror/state";
|
|
1855
1754
|
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1856
|
-
import { log as
|
|
1857
|
-
var
|
|
1755
|
+
import { log as log4 } from "@dxos/log";
|
|
1756
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts";
|
|
1757
|
+
var cursorLineMarginFacet = Facet5.define({
|
|
1758
|
+
combine: (input) => input[0] ?? 3
|
|
1759
|
+
});
|
|
1858
1760
|
var annotation = "cursorLineMargin";
|
|
1859
1761
|
var lineAtPos = (s, pos) => s.doc.lineAt(pos).number;
|
|
1860
|
-
var cursorLineMargin = (
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
const { lines } = options;
|
|
1864
|
-
if (!lines || lines <= 0) {
|
|
1865
|
-
return [];
|
|
1762
|
+
var cursorLineMargin = EditorView8.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
|
|
1763
|
+
if (transactions.length < 1 || transactions.some((tr) => tr.isUserEvent(annotation))) {
|
|
1764
|
+
return;
|
|
1866
1765
|
}
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1766
|
+
const s = state;
|
|
1767
|
+
const { main } = s.selection;
|
|
1768
|
+
const cursorLineMargin2 = s.facet(cursorLineMarginFacet);
|
|
1769
|
+
const rect = view.dom.getBoundingClientRect();
|
|
1770
|
+
const viewportTop = rect.top - view.documentTop;
|
|
1771
|
+
const viewportBottom = rect.bottom - view.documentTop;
|
|
1772
|
+
const mainLine = lineAtPos(s, main.head);
|
|
1773
|
+
const _visTopLine = lineAtPos(s, view.lineBlockAtHeight(viewportTop).from);
|
|
1774
|
+
const botLineBlk = view.lineBlockAtHeight(viewportBottom);
|
|
1775
|
+
const visBotLineDoc = lineAtPos(s, Math.min(botLineBlk.to, s.doc.length));
|
|
1776
|
+
const visBotLine = botLineBlk.bottom >= viewportBottom ? visBotLineDoc : visBotLineDoc + Math.floor((viewportBottom - botLineBlk.bottom) / view.defaultLineHeight);
|
|
1777
|
+
const needsScrollTop = false;
|
|
1778
|
+
const needsScrollBot = mainLine >= visBotLine - cursorLineMargin2;
|
|
1779
|
+
if (needsScrollTop && needsScrollBot) {
|
|
1780
|
+
log4.warn("is cursorScrollMargin too large for the editor size?", void 0, {
|
|
1781
|
+
F: __dxlog_file5,
|
|
1782
|
+
L: 66,
|
|
1783
|
+
S: void 0,
|
|
1784
|
+
C: (f, a) => f(...a)
|
|
1785
|
+
});
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1788
|
+
if (!needsScrollTop && !needsScrollBot) {
|
|
1789
|
+
return;
|
|
1790
|
+
}
|
|
1791
|
+
if (selectionSet) {
|
|
1792
|
+
const { head } = startState.selection.main;
|
|
1793
|
+
const oldMainLine = lineAtPos(startState, head);
|
|
1794
|
+
if (needsScrollTop && oldMainLine < mainLine) {
|
|
1890
1795
|
return;
|
|
1891
1796
|
}
|
|
1892
|
-
if (
|
|
1797
|
+
if (needsScrollBot && oldMainLine > mainLine) {
|
|
1893
1798
|
return;
|
|
1894
1799
|
}
|
|
1895
|
-
if (selectionSet) {
|
|
1896
|
-
const { head } = startState.selection.main;
|
|
1897
|
-
const oldMainLine = lineAtPos(startState, head);
|
|
1898
|
-
if (needsScrollTop && oldMainLine < mainLine) {
|
|
1899
|
-
return;
|
|
1900
|
-
}
|
|
1901
|
-
if (needsScrollBot && oldMainLine > mainLine) {
|
|
1902
|
-
return;
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
view.dispatch({
|
|
1906
|
-
annotations: Transaction.userEvent.of(annotation),
|
|
1907
|
-
effects: EditorView8.scrollIntoView(s.selection.main.head, {
|
|
1908
|
-
y: needsScrollTop ? "start" : "end",
|
|
1909
|
-
yMargin: view.defaultLineHeight * lines
|
|
1910
|
-
})
|
|
1911
|
-
});
|
|
1912
|
-
});
|
|
1913
|
-
};
|
|
1914
|
-
|
|
1915
|
-
// packages/ui/react-ui-editor/src/extensions/doc.ts
|
|
1916
|
-
import { Facet as Facet5 } from "@codemirror/state";
|
|
1917
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1918
|
-
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/doc.ts";
|
|
1919
|
-
var documentId2 = Facet5.define({
|
|
1920
|
-
combine: (providers) => {
|
|
1921
|
-
invariant3(providers.length <= 1, void 0, {
|
|
1922
|
-
F: __dxlog_file7,
|
|
1923
|
-
L: 11,
|
|
1924
|
-
S: void 0,
|
|
1925
|
-
A: [
|
|
1926
|
-
"providers.length <= 1",
|
|
1927
|
-
""
|
|
1928
|
-
]
|
|
1929
|
-
});
|
|
1930
|
-
return providers[0];
|
|
1931
1800
|
}
|
|
1801
|
+
view.dispatch({
|
|
1802
|
+
annotations: Transaction.userEvent.of(annotation),
|
|
1803
|
+
effects: EditorView8.scrollIntoView(s.selection.main.head, {
|
|
1804
|
+
y: needsScrollTop ? "start" : "end",
|
|
1805
|
+
yMargin: view.defaultLineHeight * cursorLineMargin2
|
|
1806
|
+
})
|
|
1807
|
+
});
|
|
1932
1808
|
});
|
|
1933
1809
|
|
|
1934
1810
|
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
|
1935
1811
|
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1936
|
-
import { log as
|
|
1937
|
-
var
|
|
1812
|
+
import { log as log5 } from "@dxos/log";
|
|
1813
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/dnd.ts";
|
|
1938
1814
|
var dnd = () => {
|
|
1939
1815
|
return EditorView9.domEventHandlers({
|
|
1940
1816
|
drop: (event, view) => {
|
|
1941
|
-
|
|
1817
|
+
log5.info("domEventHandlersDrop", {
|
|
1942
1818
|
event
|
|
1943
1819
|
}, {
|
|
1944
|
-
F:
|
|
1820
|
+
F: __dxlog_file6,
|
|
1945
1821
|
L: 14,
|
|
1946
1822
|
S: void 0,
|
|
1947
1823
|
C: (f, a) => f(...a)
|
|
@@ -1950,350 +1826,31 @@ var dnd = () => {
|
|
|
1950
1826
|
});
|
|
1951
1827
|
};
|
|
1952
1828
|
|
|
1953
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1954
|
-
import {
|
|
1955
|
-
|
|
1956
|
-
|
|
1829
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1830
|
+
import { EditorView as EditorView10 } from "@codemirror/view";
|
|
1831
|
+
var listener = ({ onFocus, onChange }) => {
|
|
1832
|
+
const extensions = [];
|
|
1833
|
+
onFocus && extensions.push(EditorView10.focusChangeEffect.of((_, focusing) => {
|
|
1834
|
+
onFocus(focusing);
|
|
1835
|
+
return null;
|
|
1836
|
+
}));
|
|
1837
|
+
onChange && extensions.push(EditorView10.updateListener.of((update2) => {
|
|
1838
|
+
onChange(update2.state.doc.toString());
|
|
1839
|
+
}));
|
|
1840
|
+
return extensions;
|
|
1841
|
+
};
|
|
1842
|
+
|
|
1843
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1844
|
+
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1845
|
+
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1846
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1847
|
+
import { bracketMatching, defaultHighlightStyle, indentOnInput, syntaxHighlighting } from "@codemirror/language";
|
|
1848
|
+
import { languages } from "@codemirror/language-data";
|
|
1849
|
+
import { searchKeymap } from "@codemirror/search";
|
|
1957
1850
|
import { EditorState } from "@codemirror/state";
|
|
1958
|
-
import {
|
|
1959
|
-
import
|
|
1960
|
-
import {
|
|
1961
|
-
import { log as log7 } from "@dxos/log";
|
|
1962
|
-
import { hueTokens } from "@dxos/react-ui-theme";
|
|
1963
|
-
import { hexToHue, isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1964
|
-
|
|
1965
|
-
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
1966
|
-
import get3 from "lodash.get";
|
|
1967
|
-
var defaultTheme = {
|
|
1968
|
-
//
|
|
1969
|
-
// Main layout:
|
|
1970
|
-
// https://codemirror.net/examples/styling
|
|
1971
|
-
//
|
|
1972
|
-
// <div class="cm-editor [cm-focused] [generated classes]">
|
|
1973
|
-
// <div class="cm-scroller">
|
|
1974
|
-
// <div class="cm-gutters">
|
|
1975
|
-
// <div class="cm-gutter [...]">
|
|
1976
|
-
// <div class="cm-gutterElement">...</div>
|
|
1977
|
-
// </div>
|
|
1978
|
-
// </div>
|
|
1979
|
-
// <div class="cm-content" role="textbox" contenteditable="true">
|
|
1980
|
-
// <div class="cm-line"></div>
|
|
1981
|
-
// </div>
|
|
1982
|
-
// <div class="cm-selectionLayer">
|
|
1983
|
-
// <div class="cm-selectionBackground"></div>
|
|
1984
|
-
// </div>
|
|
1985
|
-
// <div class="cm-cursorLayer">
|
|
1986
|
-
// <div class="cm-cursor"></div>
|
|
1987
|
-
// </div>
|
|
1988
|
-
// </div>
|
|
1989
|
-
// </div>
|
|
1990
|
-
//
|
|
1991
|
-
"&": {},
|
|
1992
|
-
"&.cm-focused": {
|
|
1993
|
-
outline: "none"
|
|
1994
|
-
},
|
|
1995
|
-
// NOTE: See https://codemirror.net/docs/guide (DOM Structure).
|
|
1996
|
-
".cm-scroller": {
|
|
1997
|
-
// TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
|
|
1998
|
-
// Inside of that is the scroller element. If the editor has its own scrollbar, this one should be styled with overflow: auto. But it doesn't have to—the editor also supports growing to accomodate its content, or growing up to a certain max-height and then scrolling.
|
|
1999
|
-
overflowY: "auto",
|
|
2000
|
-
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2001
|
-
lineHeight: 1.5
|
|
2002
|
-
},
|
|
2003
|
-
".cm-content": {
|
|
2004
|
-
// TODO(burdon): Is it possible to remove the padding value from CM's default theme?
|
|
2005
|
-
// padding: 'unset',
|
|
2006
|
-
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
2007
|
-
fontSize: "16px"
|
|
2008
|
-
},
|
|
2009
|
-
"&light .cm-content": {
|
|
2010
|
-
color: get3(tokens, "extend.semanticColors.base.fg.light", "black"),
|
|
2011
|
-
caretColor: "black"
|
|
2012
|
-
},
|
|
2013
|
-
"&dark .cm-content": {
|
|
2014
|
-
color: get3(tokens, "extend.semanticColors.base.fg.dark", "white"),
|
|
2015
|
-
caretColor: "white"
|
|
2016
|
-
},
|
|
2017
|
-
//
|
|
2018
|
-
// Cursor
|
|
2019
|
-
//
|
|
2020
|
-
"&light .cm-cursor, &light .cm-dropCursor": {
|
|
2021
|
-
borderLeft: "2px solid black"
|
|
2022
|
-
},
|
|
2023
|
-
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2024
|
-
borderLeft: "2px solid white"
|
|
2025
|
-
},
|
|
2026
|
-
"&light .cm-placeholder": {
|
|
2027
|
-
color: get3(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
2028
|
-
},
|
|
2029
|
-
"&dark .cm-placeholder": {
|
|
2030
|
-
color: get3(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
2031
|
-
},
|
|
2032
|
-
//
|
|
2033
|
-
// line
|
|
2034
|
-
//
|
|
2035
|
-
".cm-line": {
|
|
2036
|
-
paddingInline: 0
|
|
2037
|
-
},
|
|
2038
|
-
".cm-activeLine": {
|
|
2039
|
-
background: "transparent"
|
|
2040
|
-
},
|
|
2041
|
-
//
|
|
2042
|
-
// gutter
|
|
2043
|
-
//
|
|
2044
|
-
".cm-gutterElement": {
|
|
2045
|
-
width: "48px"
|
|
2046
|
-
},
|
|
2047
|
-
//
|
|
2048
|
-
// Selection
|
|
2049
|
-
//
|
|
2050
|
-
"&light .cm-selectionBackground": {
|
|
2051
|
-
background: get3(tokens, "extend.colors.primary.100")
|
|
2052
|
-
},
|
|
2053
|
-
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2054
|
-
background: get3(tokens, "extend.colors.primary.200")
|
|
2055
|
-
},
|
|
2056
|
-
"&dark .cm-selectionBackground": {
|
|
2057
|
-
background: get3(tokens, "extend.colors.primary.700")
|
|
2058
|
-
},
|
|
2059
|
-
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2060
|
-
background: get3(tokens, "extend.colors.primary.600")
|
|
2061
|
-
},
|
|
2062
|
-
//
|
|
2063
|
-
// Search
|
|
2064
|
-
//
|
|
2065
|
-
"&light .cm-searchMatch": {
|
|
2066
|
-
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
2067
|
-
},
|
|
2068
|
-
"&dark .cm-searchMatch": {
|
|
2069
|
-
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2070
|
-
},
|
|
2071
|
-
//
|
|
2072
|
-
// link
|
|
2073
|
-
//
|
|
2074
|
-
".cm-link": {
|
|
2075
|
-
color: get3(tokens, "extend.colors.primary.500"),
|
|
2076
|
-
textDecorationLine: "underline",
|
|
2077
|
-
textDecorationThickness: "1px",
|
|
2078
|
-
textUnderlineOffset: "2px",
|
|
2079
|
-
borderRadius: ".125rem",
|
|
2080
|
-
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2081
|
-
},
|
|
2082
|
-
//
|
|
2083
|
-
// tooltip
|
|
2084
|
-
//
|
|
2085
|
-
".cm-tooltip": {
|
|
2086
|
-
border: "none",
|
|
2087
|
-
background: "unset"
|
|
2088
|
-
},
|
|
2089
|
-
".cm-tooltip-below": {},
|
|
2090
|
-
//
|
|
2091
|
-
// autocomplete
|
|
2092
|
-
//
|
|
2093
|
-
".cm-tooltip-autocomplete": {
|
|
2094
|
-
marginTop: "4px",
|
|
2095
|
-
marginLeft: "-3px"
|
|
2096
|
-
},
|
|
2097
|
-
".cm-tooltip-autocomplete ul li": {},
|
|
2098
|
-
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
2099
|
-
".cm-completionIcon": {
|
|
2100
|
-
display: "none"
|
|
2101
|
-
},
|
|
2102
|
-
".cm-completionLabel": {
|
|
2103
|
-
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2104
|
-
},
|
|
2105
|
-
".cm-completionMatchedText": {
|
|
2106
|
-
textDecoration: "none"
|
|
2107
|
-
},
|
|
2108
|
-
//
|
|
2109
|
-
// table
|
|
2110
|
-
//
|
|
2111
|
-
".cm-table *": {
|
|
2112
|
-
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
2113
|
-
textDecoration: "none !important"
|
|
2114
|
-
},
|
|
2115
|
-
".cm-table-head": {
|
|
2116
|
-
padding: "2px 16px 2px 0px",
|
|
2117
|
-
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
2118
|
-
fontWeight: 100,
|
|
2119
|
-
textAlign: "left",
|
|
2120
|
-
color: get3(tokens, "extend.colors.neutral.500")
|
|
2121
|
-
},
|
|
2122
|
-
".cm-table-cell": {
|
|
2123
|
-
padding: "2px 16px 2px 0px"
|
|
2124
|
-
},
|
|
2125
|
-
//
|
|
2126
|
-
// image
|
|
2127
|
-
//
|
|
2128
|
-
".cm-image": {
|
|
2129
|
-
display: "block",
|
|
2130
|
-
height: "0"
|
|
2131
|
-
},
|
|
2132
|
-
".cm-image.cm-loaded-image": {
|
|
2133
|
-
height: "auto",
|
|
2134
|
-
borderTop: "0.5rem solid transparent",
|
|
2135
|
-
borderBottom: "0.5rem solid transparent"
|
|
2136
|
-
},
|
|
2137
|
-
//
|
|
2138
|
-
// font size
|
|
2139
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2140
|
-
// but it's far more verbose than it needs to be.
|
|
2141
|
-
//
|
|
2142
|
-
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2143
|
-
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2144
|
-
//
|
|
2145
|
-
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2146
|
-
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2147
|
-
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2148
|
-
// return acc;
|
|
2149
|
-
// }, {}),
|
|
2150
|
-
/**
|
|
2151
|
-
* Panels
|
|
2152
|
-
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
2153
|
-
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
|
2154
|
-
*
|
|
2155
|
-
* Find/replace panel.
|
|
2156
|
-
* <div class="cm-announced">...</div>
|
|
2157
|
-
* <div class="cm-scroller">...</div>
|
|
2158
|
-
* <div class="cm-panels cm-panels-bottom">
|
|
2159
|
-
* <div class="cm-search cm-panel">
|
|
2160
|
-
* <input class="cm-textfield" />
|
|
2161
|
-
* <button class="cm-button">...</button>
|
|
2162
|
-
* <label><input type="checkbox" />...</label>
|
|
2163
|
-
* </div>
|
|
2164
|
-
* </div
|
|
2165
|
-
*/
|
|
2166
|
-
".cm-panels": {
|
|
2167
|
-
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
|
|
2168
|
-
},
|
|
2169
|
-
".cm-panel": {
|
|
2170
|
-
background: get3(tokens, "extend.colors.neutral.50"),
|
|
2171
|
-
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2172
|
-
},
|
|
2173
|
-
".cm-button": {
|
|
2174
|
-
margin: "4px",
|
|
2175
|
-
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2176
|
-
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2177
|
-
backgroundImage: "none",
|
|
2178
|
-
border: "none",
|
|
2179
|
-
"&:hover": {
|
|
2180
|
-
background: get3(tokens, "extend.colors.neutral.200")
|
|
2181
|
-
},
|
|
2182
|
-
"&:active": {
|
|
2183
|
-
background: get3(tokens, "extend.colors.neutral.300"),
|
|
2184
|
-
backgroundImage: "none"
|
|
2185
|
-
}
|
|
2186
|
-
},
|
|
2187
|
-
".cm-panel input[type=checkbox]": {
|
|
2188
|
-
marginRight: "0.4rem !important"
|
|
2189
|
-
}
|
|
2190
|
-
};
|
|
2191
|
-
|
|
2192
|
-
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
|
2193
|
-
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
|
2194
|
-
var defaults = {
|
|
2195
|
-
bracketMatching: true,
|
|
2196
|
-
closeBrackets: true,
|
|
2197
|
-
drawSelection: true,
|
|
2198
|
-
editable: true,
|
|
2199
|
-
history: true,
|
|
2200
|
-
lineWrapping: true
|
|
2201
|
-
};
|
|
2202
|
-
var createBasicExtensions = (_props) => {
|
|
2203
|
-
const props = defaultsDeep2({}, _props, defaults);
|
|
2204
|
-
return [
|
|
2205
|
-
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2206
|
-
EditorView10.exceptionSink.of((err) => {
|
|
2207
|
-
log7.catch(err, void 0, {
|
|
2208
|
-
F: __dxlog_file9,
|
|
2209
|
-
L: 78,
|
|
2210
|
-
S: void 0,
|
|
2211
|
-
C: (f, a) => f(...a)
|
|
2212
|
-
});
|
|
2213
|
-
}),
|
|
2214
|
-
props.allowMultipleSelections && EditorState.allowMultipleSelections.of(true),
|
|
2215
|
-
props.bracketMatching && bracketMatching(),
|
|
2216
|
-
props.closeBrackets && closeBrackets(),
|
|
2217
|
-
props.crosshairCursor && crosshairCursor(),
|
|
2218
|
-
props.dropCursor && dropCursor(),
|
|
2219
|
-
props.drawSelection && drawSelection(),
|
|
2220
|
-
props.highlightActiveLine && highlightActiveLine(),
|
|
2221
|
-
props.history && history(),
|
|
2222
|
-
props.lineNumbers && lineNumbers(),
|
|
2223
|
-
props.lineWrapping && EditorView10.lineWrapping,
|
|
2224
|
-
props.placeholder && placeholder(props.placeholder),
|
|
2225
|
-
props.readonly && [
|
|
2226
|
-
EditorState.readOnly.of(true),
|
|
2227
|
-
EditorView10.editable.of(false)
|
|
2228
|
-
],
|
|
2229
|
-
props.scrollPastEnd && scrollPastEnd(),
|
|
2230
|
-
props.tabSize && EditorState.tabSize.of(props.tabSize)
|
|
2231
|
-
].filter(isNotFalsy2);
|
|
2232
|
-
};
|
|
2233
|
-
var defaultSlots = {
|
|
2234
|
-
editor: {
|
|
2235
|
-
className: "w-full bs-full"
|
|
2236
|
-
}
|
|
2237
|
-
};
|
|
2238
|
-
var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
|
|
2239
|
-
const slots = defaultsDeep2({}, _slots, defaultSlots);
|
|
2240
|
-
return [
|
|
2241
|
-
EditorView10.baseTheme(defaultTheme),
|
|
2242
|
-
EditorView10.darkTheme.of(themeMode === "dark"),
|
|
2243
|
-
theme && EditorView10.theme(theme),
|
|
2244
|
-
slots.editor?.className && EditorView10.editorAttributes.of({
|
|
2245
|
-
class: slots.editor.className
|
|
2246
|
-
}),
|
|
2247
|
-
slots.content?.className && EditorView10.contentAttributes.of({
|
|
2248
|
-
class: slots.content.className
|
|
2249
|
-
})
|
|
2250
|
-
].filter(isNotFalsy2);
|
|
2251
|
-
};
|
|
2252
|
-
var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2253
|
-
const extensions = [
|
|
2254
|
-
automerge(text)
|
|
2255
|
-
];
|
|
2256
|
-
if (space && identity) {
|
|
2257
|
-
const peerId = identity?.identityKey.toHex();
|
|
2258
|
-
const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
|
|
2259
|
-
const awarenessProvider2 = new SpaceAwarenessProvider({
|
|
2260
|
-
space,
|
|
2261
|
-
channel: `awareness.${id}`,
|
|
2262
|
-
peerId: identity.identityKey.toHex(),
|
|
2263
|
-
info: {
|
|
2264
|
-
displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
|
|
2265
|
-
color: cursorDarkValue,
|
|
2266
|
-
lightColor: cursorLightValue
|
|
2267
|
-
}
|
|
2268
|
-
});
|
|
2269
|
-
extensions.push(awareness(awarenessProvider2));
|
|
2270
|
-
}
|
|
2271
|
-
return extensions;
|
|
2272
|
-
};
|
|
2273
|
-
|
|
2274
|
-
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
2275
|
-
import { EditorView as EditorView11 } from "@codemirror/view";
|
|
2276
|
-
var listener = ({ onFocus, onChange }) => {
|
|
2277
|
-
const extensions = [];
|
|
2278
|
-
onFocus && extensions.push(EditorView11.focusChangeEffect.of((_, focusing) => {
|
|
2279
|
-
onFocus(focusing);
|
|
2280
|
-
return null;
|
|
2281
|
-
}));
|
|
2282
|
-
onChange && extensions.push(EditorView11.updateListener.of((update2) => {
|
|
2283
|
-
onChange(update2.state.doc.toString());
|
|
2284
|
-
}));
|
|
2285
|
-
return extensions;
|
|
2286
|
-
};
|
|
2287
|
-
|
|
2288
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
2289
|
-
import { closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
2290
|
-
import { historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
2291
|
-
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
2292
|
-
import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
2293
|
-
import { languages } from "@codemirror/language-data";
|
|
2294
|
-
import { searchKeymap } from "@codemirror/search";
|
|
2295
|
-
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
2296
|
-
import { keymap as keymap5 } from "@codemirror/view";
|
|
1851
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
1852
|
+
import { EditorView as EditorView11, drawSelection, dropCursor, keymap as keymap5, placeholder } from "@codemirror/view";
|
|
1853
|
+
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
2297
1854
|
|
|
2298
1855
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
2299
1856
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -2484,8 +2041,19 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
2484
2041
|
};
|
|
2485
2042
|
|
|
2486
2043
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
2487
|
-
var createMarkdownExtensions = ({ themeMode } = {}) => {
|
|
2044
|
+
var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
|
|
2488
2045
|
return [
|
|
2046
|
+
// TODO(burdon): Reconcile with createBasicExtensions.
|
|
2047
|
+
lineWrapping && EditorView11.lineWrapping,
|
|
2048
|
+
EditorState.allowMultipleSelections.of(true),
|
|
2049
|
+
EditorState.tabSize.of(2),
|
|
2050
|
+
bracketMatching(),
|
|
2051
|
+
closeBrackets(),
|
|
2052
|
+
dropCursor(),
|
|
2053
|
+
drawSelection(),
|
|
2054
|
+
history(),
|
|
2055
|
+
indentOnInput(),
|
|
2056
|
+
_placeholder && placeholder(_placeholder),
|
|
2489
2057
|
// Main extension.
|
|
2490
2058
|
// https://github.com/codemirror/lang-markdown
|
|
2491
2059
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -2520,7 +2088,7 @@ var createMarkdownExtensions = ({ themeMode } = {}) => {
|
|
|
2520
2088
|
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2521
2089
|
...standardKeymap
|
|
2522
2090
|
])
|
|
2523
|
-
];
|
|
2091
|
+
].filter(isNotFalsy2);
|
|
2524
2092
|
};
|
|
2525
2093
|
|
|
2526
2094
|
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
|
@@ -2560,7 +2128,7 @@ var CheckboxWidget = class extends WidgetType3 {
|
|
|
2560
2128
|
}
|
|
2561
2129
|
toDOM(view) {
|
|
2562
2130
|
const input = document.createElement("input");
|
|
2563
|
-
input.className = "cm-task-checkbox
|
|
2131
|
+
input.className = "cm-task-checkbox";
|
|
2564
2132
|
input.type = "checkbox";
|
|
2565
2133
|
input.checked = this._checked;
|
|
2566
2134
|
if (view.state.readOnly) {
|
|
@@ -3450,8 +3018,8 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
3450
3018
|
return true;
|
|
3451
3019
|
};
|
|
3452
3020
|
var toggleList = (type) => (target) => {
|
|
3453
|
-
const
|
|
3454
|
-
const active =
|
|
3021
|
+
const formatting2 = getFormatting(target.state);
|
|
3022
|
+
const active = formatting2.listStyle === (type === 1 ? "bullet" : type === 0 ? "ordered" : "task");
|
|
3455
3023
|
return (active ? removeList(type) : addList(type))(target);
|
|
3456
3024
|
};
|
|
3457
3025
|
var renumberListItems = (item, counter, changes, doc) => {
|
|
@@ -3665,7 +3233,7 @@ var removeCodeblock = ({ state, dispatch }) => {
|
|
|
3665
3233
|
var toggleCodeblock = (target) => {
|
|
3666
3234
|
return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
|
|
3667
3235
|
};
|
|
3668
|
-
var
|
|
3236
|
+
var formatting = (options = {}) => {
|
|
3669
3237
|
return [
|
|
3670
3238
|
keymap6.of([
|
|
3671
3239
|
{
|
|
@@ -4046,11 +3614,9 @@ var update = (state, options) => {
|
|
|
4046
3614
|
});
|
|
4047
3615
|
tables.forEach((table2) => {
|
|
4048
3616
|
const hide2 = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
}));
|
|
4053
|
-
}
|
|
3617
|
+
hide2 && builder.add(table2.from, table2.to, Decoration7.replace({
|
|
3618
|
+
widget: new TableWidget(table2)
|
|
3619
|
+
}));
|
|
4054
3620
|
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
4055
3621
|
class: "cm-table"
|
|
4056
3622
|
}));
|
|
@@ -4096,8 +3662,8 @@ var TableWidget = class extends WidgetType5 {
|
|
|
4096
3662
|
|
|
4097
3663
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
4098
3664
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
4099
|
-
import { log as
|
|
4100
|
-
var
|
|
3665
|
+
import { log as log6 } from "@dxos/log";
|
|
3666
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
|
|
4101
3667
|
var mention = ({ onSearch }) => {
|
|
4102
3668
|
return autocompletion2({
|
|
4103
3669
|
// TODO(burdon): Not working.
|
|
@@ -4109,10 +3675,10 @@ var mention = ({ onSearch }) => {
|
|
|
4109
3675
|
icons: false,
|
|
4110
3676
|
override: [
|
|
4111
3677
|
(context) => {
|
|
4112
|
-
|
|
3678
|
+
log6.info("completion context", {
|
|
4113
3679
|
context
|
|
4114
3680
|
}, {
|
|
4115
|
-
F:
|
|
3681
|
+
F: __dxlog_file7,
|
|
4116
3682
|
L: 26,
|
|
4117
3683
|
S: void 0,
|
|
4118
3684
|
C: (f, a) => f(...a)
|
|
@@ -4161,6 +3727,11 @@ var EditorModes = {
|
|
|
4161
3727
|
]
|
|
4162
3728
|
};
|
|
4163
3729
|
|
|
3730
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
3731
|
+
var outliner = (options = {}) => {
|
|
3732
|
+
return [];
|
|
3733
|
+
};
|
|
3734
|
+
|
|
4164
3735
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
4165
3736
|
import { keymap as keymap8 } from "@codemirror/view";
|
|
4166
3737
|
var defaultItems = [
|
|
@@ -4218,63 +3789,728 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
4218
3789
|
];
|
|
4219
3790
|
};
|
|
4220
3791
|
|
|
4221
|
-
// packages/ui/react-ui-editor/src/
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
F: __dxlog_file11,
|
|
4248
|
-
L: 88,
|
|
4249
|
-
S: void 0,
|
|
4250
|
-
C: (f, a) => f(...a)
|
|
3792
|
+
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
3793
|
+
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
3794
|
+
import { Context as Context2 } from "@dxos/context";
|
|
3795
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
3796
|
+
import { log as log7 } from "@dxos/log";
|
|
3797
|
+
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
3798
|
+
var DEBOUNCE_INTERVAL = 100;
|
|
3799
|
+
var SpaceAwarenessProvider = class {
|
|
3800
|
+
constructor(params) {
|
|
3801
|
+
this._remoteStates = /* @__PURE__ */ new Map();
|
|
3802
|
+
this.remoteStateChange = new Event2();
|
|
3803
|
+
this._space = params.space;
|
|
3804
|
+
this._channel = params.channel;
|
|
3805
|
+
this._peerId = params.peerId;
|
|
3806
|
+
this._info = params.info;
|
|
3807
|
+
}
|
|
3808
|
+
open() {
|
|
3809
|
+
this._ctx = new Context2();
|
|
3810
|
+
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
3811
|
+
if (this._localState) {
|
|
3812
|
+
await this._space.postMessage(this._channel, {
|
|
3813
|
+
kind: "post",
|
|
3814
|
+
state: this._localState
|
|
3815
|
+
});
|
|
3816
|
+
await sleep(DEBOUNCE_INTERVAL);
|
|
3817
|
+
}
|
|
4251
3818
|
});
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
3819
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
3820
|
+
switch (message.payload.kind) {
|
|
3821
|
+
case "query": {
|
|
3822
|
+
this._handleQueryMessage();
|
|
3823
|
+
break;
|
|
3824
|
+
}
|
|
3825
|
+
case "post": {
|
|
3826
|
+
this._handlePostMessage(message.payload);
|
|
3827
|
+
break;
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
}));
|
|
3831
|
+
void this._space.postMessage(this._channel, {
|
|
3832
|
+
kind: "query"
|
|
3833
|
+
}).catch((err) => {
|
|
3834
|
+
log7.debug("failed to query awareness", {
|
|
3835
|
+
err
|
|
3836
|
+
}, {
|
|
3837
|
+
F: __dxlog_file8,
|
|
3838
|
+
L: 89,
|
|
3839
|
+
S: this,
|
|
3840
|
+
C: (f, a) => f(...a)
|
|
3841
|
+
});
|
|
3842
|
+
});
|
|
3843
|
+
}
|
|
3844
|
+
close() {
|
|
3845
|
+
void this._ctx?.dispose();
|
|
3846
|
+
this._ctx = void 0;
|
|
3847
|
+
this._postTask = void 0;
|
|
3848
|
+
}
|
|
3849
|
+
getRemoteStates() {
|
|
3850
|
+
return Array.from(this._remoteStates.values());
|
|
3851
|
+
}
|
|
3852
|
+
update(position) {
|
|
3853
|
+
invariant2(this._postTask, void 0, {
|
|
3854
|
+
F: __dxlog_file8,
|
|
3855
|
+
L: 104,
|
|
3856
|
+
S: this,
|
|
3857
|
+
A: [
|
|
3858
|
+
"this._postTask",
|
|
3859
|
+
""
|
|
3860
|
+
]
|
|
3861
|
+
});
|
|
3862
|
+
this._localState = {
|
|
3863
|
+
peerId: this._peerId,
|
|
3864
|
+
position,
|
|
3865
|
+
info: this._info
|
|
3866
|
+
};
|
|
3867
|
+
this._postTask.schedule();
|
|
3868
|
+
}
|
|
3869
|
+
_handleQueryMessage() {
|
|
3870
|
+
invariant2(this._postTask, void 0, {
|
|
3871
|
+
F: __dxlog_file8,
|
|
3872
|
+
L: 115,
|
|
3873
|
+
S: this,
|
|
3874
|
+
A: [
|
|
3875
|
+
"this._postTask",
|
|
3876
|
+
""
|
|
3877
|
+
]
|
|
3878
|
+
});
|
|
3879
|
+
this._postTask.schedule();
|
|
3880
|
+
}
|
|
3881
|
+
_handlePostMessage(message) {
|
|
3882
|
+
invariant2(message.kind === "post", void 0, {
|
|
3883
|
+
F: __dxlog_file8,
|
|
3884
|
+
L: 120,
|
|
3885
|
+
S: this,
|
|
3886
|
+
A: [
|
|
3887
|
+
"message.kind === 'post'",
|
|
3888
|
+
""
|
|
3889
|
+
]
|
|
3890
|
+
});
|
|
3891
|
+
this._remoteStates.set(message.state.peerId, message.state);
|
|
3892
|
+
this.remoteStateChange.emit();
|
|
3893
|
+
}
|
|
3894
|
+
};
|
|
3895
|
+
|
|
3896
|
+
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
3897
|
+
var useActionHandler = (view) => {
|
|
3898
|
+
return (action) => {
|
|
3899
|
+
if (!view) {
|
|
3900
|
+
return;
|
|
3901
|
+
}
|
|
3902
|
+
let inlineType, listType;
|
|
3903
|
+
switch (action.type) {
|
|
3904
|
+
case "heading":
|
|
3905
|
+
setHeading(parseInt(action.data))(view);
|
|
3906
|
+
break;
|
|
3907
|
+
case "strong":
|
|
3908
|
+
case "emphasis":
|
|
3909
|
+
case "strikethrough":
|
|
3910
|
+
case "code":
|
|
3911
|
+
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
3912
|
+
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
3913
|
+
break;
|
|
3914
|
+
case "list-ordered":
|
|
3915
|
+
case "list-bullet":
|
|
3916
|
+
case "list-task":
|
|
3917
|
+
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
3918
|
+
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
3919
|
+
break;
|
|
3920
|
+
case "blockquote":
|
|
3921
|
+
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
3922
|
+
break;
|
|
3923
|
+
case "codeblock":
|
|
3924
|
+
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
3925
|
+
break;
|
|
3926
|
+
case "table":
|
|
3927
|
+
insertTable(view);
|
|
3928
|
+
break;
|
|
3929
|
+
case "link":
|
|
3930
|
+
(action.data === false ? removeLink : addLink)(view);
|
|
3931
|
+
break;
|
|
3932
|
+
case "comment":
|
|
3933
|
+
createComment(view);
|
|
3934
|
+
break;
|
|
3935
|
+
}
|
|
3936
|
+
setTimeout(() => {
|
|
3937
|
+
if (!view.hasFocus) {
|
|
3938
|
+
view.focus();
|
|
3939
|
+
}
|
|
3940
|
+
});
|
|
3941
|
+
};
|
|
3942
|
+
};
|
|
3943
|
+
|
|
3944
|
+
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
3945
|
+
import { useRef, useState as useState2 } from "react";
|
|
3946
|
+
var useEditorView = (id) => {
|
|
3947
|
+
const editorRef = useRef(null);
|
|
3948
|
+
const [prev, setPrev] = useState2([
|
|
3949
|
+
null,
|
|
3950
|
+
""
|
|
3951
|
+
]);
|
|
3952
|
+
if (prev[0] !== editorRef.current) {
|
|
3953
|
+
setPrev([
|
|
3954
|
+
editorRef.current,
|
|
3955
|
+
id
|
|
3956
|
+
]);
|
|
3957
|
+
}
|
|
3958
|
+
return [
|
|
3959
|
+
editorRef,
|
|
3960
|
+
prev[1] !== id
|
|
3961
|
+
];
|
|
3962
|
+
};
|
|
3963
|
+
|
|
3964
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
3965
|
+
import { closeBrackets as closeBrackets2 } from "@codemirror/autocomplete";
|
|
3966
|
+
import { history as history2 } from "@codemirror/commands";
|
|
3967
|
+
import { bracketMatching as bracketMatching2 } from "@codemirror/language";
|
|
3968
|
+
import { EditorSelection as EditorSelection2, EditorState as EditorState2 } from "@codemirror/state";
|
|
3969
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor as dropCursor2, EditorView as EditorView16, highlightActiveLine, lineNumbers, placeholder as placeholder2, scrollPastEnd } from "@codemirror/view";
|
|
3970
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
3971
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
|
|
3972
|
+
import { log as log8 } from "@dxos/log";
|
|
3973
|
+
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
3974
|
+
|
|
3975
|
+
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
3976
|
+
import get4 from "lodash.get";
|
|
3977
|
+
var defaultTheme = {
|
|
3978
|
+
//
|
|
3979
|
+
// Main layout:
|
|
3980
|
+
// https://codemirror.net/examples/styling
|
|
3981
|
+
//
|
|
3982
|
+
// <div class="cm-editor [cm-focused] [generated classes]">
|
|
3983
|
+
// <div class="cm-scroller">
|
|
3984
|
+
// <div class="cm-gutters">
|
|
3985
|
+
// <div class="cm-gutter [...]">
|
|
3986
|
+
// <div class="cm-gutterElement">...</div>
|
|
3987
|
+
// </div>
|
|
3988
|
+
// </div>
|
|
3989
|
+
// <div class="cm-content" role="textbox" contenteditable="true">
|
|
3990
|
+
// <div class="cm-line"></div>
|
|
3991
|
+
// </div>
|
|
3992
|
+
// <div class="cm-selectionLayer">
|
|
3993
|
+
// <div class="cm-selectionBackground"></div>
|
|
3994
|
+
// </div>
|
|
3995
|
+
// <div class="cm-cursorLayer">
|
|
3996
|
+
// <div class="cm-cursor"></div>
|
|
3997
|
+
// </div>
|
|
3998
|
+
// </div>
|
|
3999
|
+
// </div>
|
|
4000
|
+
//
|
|
4001
|
+
"&": {},
|
|
4002
|
+
"&.cm-focused": {
|
|
4003
|
+
outline: "none"
|
|
4004
|
+
},
|
|
4005
|
+
// NOTE: See https://codemirror.net/docs/guide (DOM Structure).
|
|
4006
|
+
".cm-scroller": {
|
|
4007
|
+
// TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
|
|
4008
|
+
// Inside of that is the scroller element. If the editor has its own scrollbar, this one should be styled with overflow: auto. But it doesn't have to—the editor also supports growing to accomodate its content, or growing up to a certain max-height and then scrolling.
|
|
4009
|
+
overflowY: "auto",
|
|
4010
|
+
fontFamily: get4(tokens, "fontFamily.mono", []).join(","),
|
|
4011
|
+
lineHeight: 1.5
|
|
4012
|
+
},
|
|
4013
|
+
".cm-content": {
|
|
4014
|
+
// TODO(burdon): Is it possible to remove the padding value from CM's default theme?
|
|
4015
|
+
// padding: 'unset',
|
|
4016
|
+
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
4017
|
+
fontSize: "16px"
|
|
4018
|
+
},
|
|
4019
|
+
"&light .cm-content": {
|
|
4020
|
+
color: get4(tokens, "extend.semanticColors.base.fg.light", "black"),
|
|
4021
|
+
caretColor: "black"
|
|
4022
|
+
},
|
|
4023
|
+
"&dark .cm-content": {
|
|
4024
|
+
color: get4(tokens, "extend.semanticColors.base.fg.dark", "white"),
|
|
4025
|
+
caretColor: "white"
|
|
4026
|
+
},
|
|
4027
|
+
//
|
|
4028
|
+
// Cursor
|
|
4029
|
+
//
|
|
4030
|
+
"&light .cm-cursor, &light .cm-dropCursor": {
|
|
4031
|
+
borderLeft: "2px solid black"
|
|
4032
|
+
},
|
|
4033
|
+
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
4034
|
+
borderLeft: "2px solid white"
|
|
4035
|
+
},
|
|
4036
|
+
"&light .cm-placeholder": {
|
|
4037
|
+
color: get4(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
4038
|
+
},
|
|
4039
|
+
"&dark .cm-placeholder": {
|
|
4040
|
+
color: get4(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
4041
|
+
},
|
|
4042
|
+
//
|
|
4043
|
+
// line
|
|
4044
|
+
//
|
|
4045
|
+
".cm-line": {
|
|
4046
|
+
paddingInline: 0
|
|
4047
|
+
},
|
|
4048
|
+
".cm-activeLine": {
|
|
4049
|
+
background: "transparent"
|
|
4050
|
+
},
|
|
4051
|
+
//
|
|
4052
|
+
// gutter
|
|
4053
|
+
//
|
|
4054
|
+
".cm-gutterElement": {
|
|
4055
|
+
width: "48px"
|
|
4056
|
+
},
|
|
4057
|
+
//
|
|
4058
|
+
// Selection
|
|
4059
|
+
//
|
|
4060
|
+
"&light .cm-selectionBackground": {
|
|
4061
|
+
background: get4(tokens, "extend.colors.primary.100")
|
|
4062
|
+
},
|
|
4063
|
+
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
4064
|
+
background: get4(tokens, "extend.colors.primary.200")
|
|
4065
|
+
},
|
|
4066
|
+
"&dark .cm-selectionBackground": {
|
|
4067
|
+
background: get4(tokens, "extend.colors.primary.700")
|
|
4068
|
+
},
|
|
4069
|
+
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
4070
|
+
background: get4(tokens, "extend.colors.primary.600")
|
|
4071
|
+
},
|
|
4072
|
+
//
|
|
4073
|
+
// Search
|
|
4074
|
+
//
|
|
4075
|
+
"&light .cm-searchMatch": {
|
|
4076
|
+
backgroundColor: get4(tokens, "extend.colors.yellow.100")
|
|
4077
|
+
},
|
|
4078
|
+
"&dark .cm-searchMatch": {
|
|
4079
|
+
backgroundColor: get4(tokens, "extend.colors.yellow.700")
|
|
4080
|
+
},
|
|
4081
|
+
//
|
|
4082
|
+
// link
|
|
4083
|
+
//
|
|
4084
|
+
".cm-link": {
|
|
4085
|
+
color: get4(tokens, "extend.colors.primary.500"),
|
|
4086
|
+
textDecorationLine: "underline",
|
|
4087
|
+
textDecorationThickness: "1px",
|
|
4088
|
+
textUnderlineOffset: "2px",
|
|
4089
|
+
borderRadius: ".125rem",
|
|
4090
|
+
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
4091
|
+
},
|
|
4092
|
+
//
|
|
4093
|
+
// tooltip
|
|
4094
|
+
//
|
|
4095
|
+
".cm-tooltip": {
|
|
4096
|
+
border: "none",
|
|
4097
|
+
background: "unset"
|
|
4098
|
+
},
|
|
4099
|
+
".cm-tooltip-below": {},
|
|
4100
|
+
//
|
|
4101
|
+
// autocomplete
|
|
4102
|
+
//
|
|
4103
|
+
".cm-tooltip-autocomplete": {
|
|
4104
|
+
marginTop: "4px",
|
|
4105
|
+
marginLeft: "-3px"
|
|
4106
|
+
},
|
|
4107
|
+
".cm-tooltip-autocomplete ul li": {},
|
|
4108
|
+
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
4109
|
+
".cm-completionIcon": {
|
|
4110
|
+
display: "none"
|
|
4111
|
+
},
|
|
4112
|
+
".cm-completionLabel": {
|
|
4113
|
+
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
4114
|
+
},
|
|
4115
|
+
".cm-completionMatchedText": {
|
|
4116
|
+
textDecoration: "none"
|
|
4117
|
+
},
|
|
4118
|
+
//
|
|
4119
|
+
// table
|
|
4120
|
+
//
|
|
4121
|
+
".cm-table *": {
|
|
4122
|
+
fontFamily: `${get4(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
4123
|
+
textDecoration: "none !important"
|
|
4124
|
+
},
|
|
4125
|
+
".cm-table-head": {
|
|
4126
|
+
padding: "2px 16px 2px 0px",
|
|
4127
|
+
borderBottom: `1px solid ${get4(tokens, "extend.colors.neutral.500")}`,
|
|
4128
|
+
fontWeight: 100,
|
|
4129
|
+
textAlign: "left",
|
|
4130
|
+
color: get4(tokens, "extend.colors.neutral.500")
|
|
4131
|
+
},
|
|
4132
|
+
".cm-table-cell": {
|
|
4133
|
+
padding: "2px 16px 2px 0px"
|
|
4134
|
+
},
|
|
4135
|
+
//
|
|
4136
|
+
// image
|
|
4137
|
+
//
|
|
4138
|
+
".cm-image": {
|
|
4139
|
+
display: "block",
|
|
4140
|
+
height: "0"
|
|
4141
|
+
},
|
|
4142
|
+
".cm-image.cm-loaded-image": {
|
|
4143
|
+
height: "auto",
|
|
4144
|
+
borderTop: "0.5rem solid transparent",
|
|
4145
|
+
borderBottom: "0.5rem solid transparent"
|
|
4146
|
+
},
|
|
4147
|
+
//
|
|
4148
|
+
// font size
|
|
4149
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
4150
|
+
// but it's far more verbose than it needs to be.
|
|
4151
|
+
//
|
|
4152
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
4153
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
4154
|
+
//
|
|
4155
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
4156
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
4157
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
4158
|
+
// return acc;
|
|
4159
|
+
// }, {}),
|
|
4160
|
+
/**
|
|
4161
|
+
* Panels
|
|
4162
|
+
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
4163
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
|
4164
|
+
*
|
|
4165
|
+
* Find/replace panel.
|
|
4166
|
+
* <div class="cm-announced">...</div>
|
|
4167
|
+
* <div class="cm-scroller">...</div>
|
|
4168
|
+
* <div class="cm-panels cm-panels-bottom">
|
|
4169
|
+
* <div class="cm-search cm-panel">
|
|
4170
|
+
* <input class="cm-textfield" />
|
|
4171
|
+
* <button class="cm-button">...</button>
|
|
4172
|
+
* <label><input type="checkbox" />...</label>
|
|
4173
|
+
* </div>
|
|
4174
|
+
* </div
|
|
4175
|
+
*/
|
|
4176
|
+
".cm-panels": {
|
|
4177
|
+
border: `1px solid ${get4(tokens, "extend.colors.neutral.200")}`
|
|
4178
|
+
},
|
|
4179
|
+
".cm-panel": {
|
|
4180
|
+
background: get4(tokens, "extend.colors.neutral.50"),
|
|
4181
|
+
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
4182
|
+
},
|
|
4183
|
+
".cm-button": {
|
|
4184
|
+
margin: "4px",
|
|
4185
|
+
fontFamily: get4(tokens, "fontFamily.body", []).join(","),
|
|
4186
|
+
background: get4(tokens, "extend.colors.neutral.100"),
|
|
4187
|
+
backgroundImage: "none",
|
|
4188
|
+
border: "none",
|
|
4189
|
+
"&:hover": {
|
|
4190
|
+
background: get4(tokens, "extend.colors.neutral.200")
|
|
4191
|
+
},
|
|
4192
|
+
"&:active": {
|
|
4193
|
+
background: get4(tokens, "extend.colors.neutral.300"),
|
|
4194
|
+
backgroundImage: "none"
|
|
4195
|
+
}
|
|
4196
|
+
},
|
|
4197
|
+
".cm-panel input[type=checkbox]": {
|
|
4198
|
+
marginRight: "0.4rem !important"
|
|
4199
|
+
}
|
|
4200
|
+
};
|
|
4201
|
+
var textTheme = {
|
|
4202
|
+
".cm-scroller": {
|
|
4203
|
+
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
4204
|
+
},
|
|
4205
|
+
".cm-placeholder": {
|
|
4206
|
+
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
4207
|
+
}
|
|
4208
|
+
};
|
|
4209
|
+
var markdownTheme = {
|
|
4210
|
+
".cm-scroller": {
|
|
4211
|
+
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
4212
|
+
},
|
|
4213
|
+
".cm-placeholder": {
|
|
4214
|
+
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
4215
|
+
}
|
|
4216
|
+
};
|
|
4217
|
+
var codeTheme = {
|
|
4218
|
+
".cm-scroller": {
|
|
4219
|
+
fontFamily: get4(tokens, "fontFamily.mono", []).join(",")
|
|
4220
|
+
},
|
|
4221
|
+
".cm-placeholder": {
|
|
4222
|
+
fontFamily: get4(tokens, "fontFamily.mono", []).join(",")
|
|
4223
|
+
}
|
|
4224
|
+
};
|
|
4225
|
+
|
|
4226
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4227
|
+
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4228
|
+
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}, deps = []) => {
|
|
4229
|
+
const onUpdate = useRef2();
|
|
4230
|
+
const [view, setView] = useState3();
|
|
4231
|
+
const parentRef = useRef2(null);
|
|
4232
|
+
useEffect2(() => {
|
|
4233
|
+
let view2;
|
|
4234
|
+
if (parentRef.current) {
|
|
4235
|
+
const state = EditorState2.create({
|
|
4236
|
+
doc,
|
|
4237
|
+
selection,
|
|
4238
|
+
extensions: [
|
|
4239
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4240
|
+
EditorView16.exceptionSink.of((err) => {
|
|
4241
|
+
log8.catch(err, void 0, {
|
|
4242
|
+
F: __dxlog_file9,
|
|
4243
|
+
L: 70,
|
|
4244
|
+
S: void 0,
|
|
4245
|
+
C: (f, a) => f(...a)
|
|
4246
|
+
});
|
|
4247
|
+
}),
|
|
4248
|
+
extensions,
|
|
4249
|
+
EditorView16.updateListener.of(() => {
|
|
4250
|
+
onUpdate.current?.();
|
|
4251
|
+
})
|
|
4252
|
+
].filter(isNotFalsy3)
|
|
4253
|
+
});
|
|
4254
|
+
view2 = new EditorView16({
|
|
4255
|
+
parent: parentRef.current,
|
|
4256
|
+
scrollTo,
|
|
4257
|
+
state,
|
|
4258
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
4259
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
4260
|
+
dispatchTransactions: (trs, view3) => {
|
|
4261
|
+
if (debug) {
|
|
4262
|
+
logChanges(trs);
|
|
4263
|
+
}
|
|
4264
|
+
view3.update(trs);
|
|
4265
|
+
}
|
|
4266
|
+
});
|
|
4267
|
+
setView(view2);
|
|
4268
|
+
}
|
|
4269
|
+
return () => {
|
|
4270
|
+
view2?.destroy();
|
|
4271
|
+
};
|
|
4272
|
+
}, deps);
|
|
4273
|
+
useEffect2(() => {
|
|
4274
|
+
if (view) {
|
|
4275
|
+
if (!selection && !view.state.selection.main.anchor) {
|
|
4276
|
+
selection = EditorSelection2.single(view.state.doc.line(1).to);
|
|
4277
|
+
}
|
|
4278
|
+
if (selection || scrollTo) {
|
|
4279
|
+
onUpdate.current = () => {
|
|
4280
|
+
onUpdate.current = void 0;
|
|
4281
|
+
view.dispatch({
|
|
4282
|
+
selection,
|
|
4283
|
+
effects: scrollTo && [
|
|
4284
|
+
scrollTo
|
|
4285
|
+
],
|
|
4286
|
+
scrollIntoView: !scrollTo
|
|
4287
|
+
});
|
|
4288
|
+
};
|
|
4289
|
+
}
|
|
4290
|
+
if (autoFocus) {
|
|
4291
|
+
view.focus();
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4294
|
+
}, [
|
|
4295
|
+
view,
|
|
4296
|
+
autoFocus,
|
|
4297
|
+
selection,
|
|
4298
|
+
scrollTo
|
|
4299
|
+
]);
|
|
4300
|
+
return {
|
|
4301
|
+
parentRef,
|
|
4302
|
+
view
|
|
4303
|
+
};
|
|
4304
|
+
};
|
|
4305
|
+
var defaults = {
|
|
4306
|
+
bracketMatching: true,
|
|
4307
|
+
closeBrackets: true,
|
|
4308
|
+
drawSelection: true,
|
|
4309
|
+
editable: true,
|
|
4310
|
+
history: true,
|
|
4311
|
+
lineWrapping: true
|
|
4312
|
+
};
|
|
4313
|
+
var createBasicExtensions = (_props) => {
|
|
4314
|
+
const props = defaultsDeep2({}, _props, defaults);
|
|
4315
|
+
return [
|
|
4316
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4317
|
+
EditorView16.exceptionSink.of((err) => {
|
|
4318
|
+
log8.catch(err, void 0, {
|
|
4319
|
+
F: __dxlog_file9,
|
|
4320
|
+
L: 167,
|
|
4321
|
+
S: void 0,
|
|
4322
|
+
C: (f, a) => f(...a)
|
|
4323
|
+
});
|
|
4324
|
+
}),
|
|
4325
|
+
props.allowMultipleSelections && EditorState2.allowMultipleSelections.of(true),
|
|
4326
|
+
props.bracketMatching && bracketMatching2(),
|
|
4327
|
+
props.closeBrackets && closeBrackets2(),
|
|
4328
|
+
props.crosshairCursor && crosshairCursor(),
|
|
4329
|
+
props.dropCursor && dropCursor2(),
|
|
4330
|
+
props.drawSelection && drawSelection2(),
|
|
4331
|
+
props.highlightActiveLine && highlightActiveLine(),
|
|
4332
|
+
props.history && history2(),
|
|
4333
|
+
props.lineNumbers && lineNumbers(),
|
|
4334
|
+
props.lineWrapping && EditorView16.lineWrapping,
|
|
4335
|
+
props.placeholder && placeholder2(props.placeholder),
|
|
4336
|
+
props.readonly && [
|
|
4337
|
+
EditorState2.readOnly.of(true),
|
|
4338
|
+
EditorView16.editable.of(false)
|
|
4339
|
+
],
|
|
4340
|
+
props.scrollPastEnd && scrollPastEnd(),
|
|
4341
|
+
props.tabSize && EditorState2.tabSize.of(props.tabSize)
|
|
4342
|
+
].filter(isNotFalsy3);
|
|
4343
|
+
};
|
|
4344
|
+
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
4345
|
+
return [
|
|
4346
|
+
EditorView16.baseTheme(defaultTheme),
|
|
4347
|
+
EditorView16.darkTheme.of(themeMode === "dark"),
|
|
4348
|
+
theme && EditorView16.theme(theme),
|
|
4349
|
+
slots?.editor?.className && EditorView16.editorAttributes.of({
|
|
4350
|
+
class: slots.editor.className
|
|
4351
|
+
}),
|
|
4352
|
+
slots?.content?.className && EditorView16.contentAttributes.of({
|
|
4353
|
+
class: slots.content.className
|
|
4354
|
+
})
|
|
4355
|
+
].filter(isNotFalsy3);
|
|
4356
|
+
};
|
|
4357
|
+
|
|
4358
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
4359
|
+
import get5 from "lodash.get";
|
|
4360
|
+
import { useState as useState4, useMemo as useMemo2 } from "react";
|
|
4361
|
+
import { generateName } from "@dxos/display-name";
|
|
4362
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
4363
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
4364
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
4365
|
+
import { hueTokens } from "@dxos/react-ui-theme";
|
|
4366
|
+
import { hexToHue } from "@dxos/util";
|
|
4367
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
4368
|
+
var useTextExtensions = ({ id, text, space, identity }) => {
|
|
4369
|
+
const extensions = [
|
|
4370
|
+
automerge(text)
|
|
4371
|
+
];
|
|
4372
|
+
const peerId = identity?.identityKey.toHex();
|
|
4373
|
+
const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
|
|
4374
|
+
if (space && identity) {
|
|
4375
|
+
const awarenessProvider2 = new SpaceAwarenessProvider({
|
|
4376
|
+
space,
|
|
4377
|
+
channel: `awareness.${id}`,
|
|
4378
|
+
peerId: identity.identityKey.toHex(),
|
|
4379
|
+
info: {
|
|
4380
|
+
displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
|
|
4381
|
+
color: cursorDarkValue,
|
|
4382
|
+
lightColor: cursorLightValue
|
|
4383
|
+
}
|
|
4384
|
+
});
|
|
4385
|
+
extensions.push(awareness(awarenessProvider2));
|
|
4386
|
+
}
|
|
4387
|
+
return extensions;
|
|
4388
|
+
};
|
|
4389
|
+
var useTextModel = (props) => useMemo2(() => createModel(props), Object.values(props));
|
|
4390
|
+
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
4391
|
+
const [content, setContent] = useState4(defaultContent ?? "");
|
|
4392
|
+
return {
|
|
4393
|
+
id,
|
|
4394
|
+
content,
|
|
4395
|
+
text: () => content,
|
|
4396
|
+
setContent
|
|
4397
|
+
};
|
|
4398
|
+
};
|
|
4399
|
+
var createModel = ({ space, identity, text }) => {
|
|
4400
|
+
if (!text) {
|
|
4401
|
+
return void 0;
|
|
4402
|
+
}
|
|
4403
|
+
invariant3(isAutomergeObject(text), void 0, {
|
|
4404
|
+
F: __dxlog_file10,
|
|
4405
|
+
L: 89,
|
|
4406
|
+
S: void 0,
|
|
4407
|
+
A: [
|
|
4408
|
+
"isAutomergeObject(text)",
|
|
4409
|
+
""
|
|
4410
|
+
]
|
|
4411
|
+
});
|
|
4412
|
+
const obj = text;
|
|
4413
|
+
const doc = getRawDoc(obj, [
|
|
4414
|
+
obj.field
|
|
4415
|
+
]);
|
|
4416
|
+
const peerId = identity?.identityKey.toHex();
|
|
4417
|
+
const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
|
|
4418
|
+
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
4419
|
+
space,
|
|
4420
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
4421
|
+
info: {
|
|
4422
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
4423
|
+
color: cursorLightValue,
|
|
4424
|
+
lightColor: cursorDarkValue
|
|
4425
|
+
},
|
|
4426
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
4427
|
+
});
|
|
4428
|
+
const extensions = [
|
|
4429
|
+
automerge({
|
|
4430
|
+
handle: doc.handle,
|
|
4431
|
+
path: doc.path
|
|
4432
|
+
})
|
|
4433
|
+
];
|
|
4434
|
+
if (awarenessProvider2) {
|
|
4435
|
+
extensions.push(awareness(awarenessProvider2));
|
|
4436
|
+
}
|
|
4437
|
+
return {
|
|
4438
|
+
id: obj.id,
|
|
4439
|
+
content: doc,
|
|
4440
|
+
text: () => get5(doc.handle.docSync(), doc.path),
|
|
4441
|
+
extension: extensions
|
|
4442
|
+
};
|
|
4443
|
+
};
|
|
4444
|
+
|
|
4445
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
4446
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
4447
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo = EditorView17.scrollIntoView(0), moveToEndOfLine, selection, theme, slots = defaultSlots, extensions = [], scrollPastEnd: _scrollPastEnd, debug }, forwardedRef) => {
|
|
4448
|
+
const tabsterDOMAttribute = useFocusableGroup({
|
|
4449
|
+
tabBehavior: "limited"
|
|
4450
|
+
});
|
|
4451
|
+
const { themeMode } = useThemeContext();
|
|
4452
|
+
const rootRef = useRef3(null);
|
|
4453
|
+
const [view, setView] = useState5(null);
|
|
4454
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
4455
|
+
view
|
|
4456
|
+
]);
|
|
4457
|
+
useEffect3(() => {
|
|
4458
|
+
if (autoFocus) {
|
|
4459
|
+
view?.focus();
|
|
4460
|
+
}
|
|
4461
|
+
}, [
|
|
4462
|
+
view,
|
|
4463
|
+
autoFocus
|
|
4464
|
+
]);
|
|
4465
|
+
useEffect3(() => {
|
|
4466
|
+
if (!model || !rootRef.current) {
|
|
4467
|
+
return;
|
|
4468
|
+
}
|
|
4469
|
+
const state = EditorState3.create({
|
|
4470
|
+
doc: typeof model.content === "string" ? model.content : DocAccessor.getValue(model.content),
|
|
4471
|
+
selection,
|
|
4472
|
+
extensions: [
|
|
4473
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4474
|
+
EditorView17.exceptionSink.of((err) => {
|
|
4475
|
+
log9.catch(err, void 0, {
|
|
4476
|
+
F: __dxlog_file11,
|
|
4477
|
+
L: 123,
|
|
4262
4478
|
S: void 0,
|
|
4263
4479
|
C: (f, a) => f(...a)
|
|
4264
4480
|
});
|
|
4265
4481
|
}),
|
|
4482
|
+
// Theme.
|
|
4483
|
+
// TODO(burdon): Make base theme configurable.
|
|
4484
|
+
EditorView17.baseTheme(defaultTheme),
|
|
4485
|
+
theme && EditorView17.theme(theme),
|
|
4486
|
+
EditorView17.darkTheme.of(themeMode === "dark"),
|
|
4487
|
+
slots.editor?.className && EditorView17.editorAttributes.of({
|
|
4488
|
+
class: slots.editor.className
|
|
4489
|
+
}),
|
|
4490
|
+
slots.content?.className && EditorView17.contentAttributes.of({
|
|
4491
|
+
class: slots.content.className
|
|
4492
|
+
}),
|
|
4493
|
+
// NOTE: Assumes default line height.
|
|
4494
|
+
_scrollPastEnd && scrollPastEnd2(),
|
|
4266
4495
|
// Focus.
|
|
4267
|
-
|
|
4496
|
+
EditorView17.updateListener.of((update2) => {
|
|
4268
4497
|
update2.transactions.forEach((transaction) => {
|
|
4269
4498
|
if (transaction.isUserEvent("focus.container")) {
|
|
4270
4499
|
rootRef.current?.focus();
|
|
4271
4500
|
}
|
|
4272
4501
|
});
|
|
4273
4502
|
}),
|
|
4274
|
-
|
|
4275
|
-
|
|
4503
|
+
// State.
|
|
4504
|
+
EditorView17.editable.of(!readonly),
|
|
4505
|
+
EditorState3.readOnly.of(!!readonly),
|
|
4506
|
+
// Storage and replication.
|
|
4507
|
+
// NOTE: This must come before user extensions.
|
|
4508
|
+
model.extension,
|
|
4509
|
+
// Custom.
|
|
4510
|
+
...extensions
|
|
4511
|
+
].filter(isNotFalsy4)
|
|
4276
4512
|
});
|
|
4277
|
-
const view2 = new
|
|
4513
|
+
const view2 = new EditorView17({
|
|
4278
4514
|
state,
|
|
4279
4515
|
parent: rootRef.current,
|
|
4280
4516
|
scrollTo,
|
|
@@ -4297,16 +4533,18 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4297
4533
|
});
|
|
4298
4534
|
}
|
|
4299
4535
|
if (state.facet(editorMode).noTabster) {
|
|
4300
|
-
rootRef.current
|
|
4536
|
+
rootRef.current.removeAttribute("data-tabster");
|
|
4301
4537
|
}
|
|
4302
4538
|
return () => {
|
|
4303
4539
|
view2?.destroy();
|
|
4304
4540
|
setView(null);
|
|
4305
4541
|
};
|
|
4306
4542
|
}, [
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4543
|
+
rootRef,
|
|
4544
|
+
extensions,
|
|
4545
|
+
model,
|
|
4546
|
+
readonly,
|
|
4547
|
+
themeMode
|
|
4310
4548
|
]);
|
|
4311
4549
|
const handleKeyUp = useCallback((event) => {
|
|
4312
4550
|
const { key } = event;
|
|
@@ -4322,18 +4560,82 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4322
4560
|
return /* @__PURE__ */ React.createElement("div", {
|
|
4323
4561
|
role: "none",
|
|
4324
4562
|
ref: rootRef,
|
|
4563
|
+
key: model.id,
|
|
4325
4564
|
tabIndex: 0,
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
...tabsterDOMAttribute
|
|
4329
|
-
|
|
4565
|
+
onKeyUp: handleKeyUp,
|
|
4566
|
+
...slots.root,
|
|
4567
|
+
...tabsterDOMAttribute
|
|
4568
|
+
});
|
|
4569
|
+
});
|
|
4570
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping = true, theme = textTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
|
|
4571
|
+
const { themeMode } = useThemeContext();
|
|
4572
|
+
const updatedSlots = defaultsDeep3({}, slots, defaultTextSlots);
|
|
4573
|
+
const extensions = useMemo3(() => [
|
|
4574
|
+
createBasicExtensions({
|
|
4575
|
+
lineWrapping,
|
|
4576
|
+
placeholder: placeholder3
|
|
4577
|
+
}),
|
|
4578
|
+
createThemeExtensions({
|
|
4579
|
+
themeMode
|
|
4580
|
+
}),
|
|
4581
|
+
..._extensions ?? []
|
|
4582
|
+
], [
|
|
4583
|
+
themeMode,
|
|
4584
|
+
placeholder3,
|
|
4585
|
+
lineWrapping,
|
|
4586
|
+
_extensions
|
|
4587
|
+
]);
|
|
4588
|
+
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
4589
|
+
ref: forwardedRef,
|
|
4590
|
+
readonly,
|
|
4591
|
+
extensions,
|
|
4592
|
+
theme,
|
|
4593
|
+
slots: updatedSlots,
|
|
4594
|
+
...props
|
|
4595
|
+
});
|
|
4596
|
+
});
|
|
4597
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
|
|
4598
|
+
const { themeMode } = useThemeContext();
|
|
4599
|
+
const updatedSlots = defaultsDeep3({}, slots, defaultMarkdownSlots);
|
|
4600
|
+
const extensions = useMemo3(() => [
|
|
4601
|
+
createMarkdownExtensions({
|
|
4602
|
+
themeMode,
|
|
4603
|
+
placeholder: placeholder3
|
|
4604
|
+
}),
|
|
4605
|
+
..._extensions ?? []
|
|
4606
|
+
], [
|
|
4607
|
+
themeMode,
|
|
4608
|
+
placeholder3,
|
|
4609
|
+
_extensions
|
|
4610
|
+
]);
|
|
4611
|
+
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
4612
|
+
ref: forwardedRef,
|
|
4613
|
+
readonly,
|
|
4614
|
+
extensions,
|
|
4615
|
+
theme,
|
|
4616
|
+
slots: updatedSlots,
|
|
4617
|
+
...props
|
|
4330
4618
|
});
|
|
4331
4619
|
});
|
|
4620
|
+
var defaultSlots = {
|
|
4621
|
+
root: {
|
|
4622
|
+
className: focusRing
|
|
4623
|
+
},
|
|
4624
|
+
editor: {
|
|
4625
|
+
className: "bs-full"
|
|
4626
|
+
}
|
|
4627
|
+
};
|
|
4628
|
+
var defaultTextSlots = {
|
|
4629
|
+
...defaultSlots
|
|
4630
|
+
};
|
|
4631
|
+
var defaultMarkdownSlots = {
|
|
4632
|
+
...defaultSlots
|
|
4633
|
+
};
|
|
4332
4634
|
|
|
4333
4635
|
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
4334
4636
|
import { ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic, Quotes } from "@phosphor-icons/react";
|
|
4335
4637
|
import { createContext } from "@radix-ui/react-context";
|
|
4336
|
-
import React2, { useRef as
|
|
4638
|
+
import React2, { useRef as useRef4, useState as useState6 } from "react";
|
|
4337
4639
|
import { DensityProvider, ElevationProvider, Select, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
|
|
4338
4640
|
import { getSize } from "@dxos/react-ui-theme";
|
|
4339
4641
|
var tooltipProps = {
|
|
@@ -4391,9 +4693,9 @@ var MarkdownHeading = () => {
|
|
|
4391
4693
|
const header = blockType && /heading(\d)/.exec(blockType);
|
|
4392
4694
|
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
|
4393
4695
|
const HeadingIcon = HeadingIcons[value ?? "0"];
|
|
4394
|
-
const suppressNextTooltip =
|
|
4395
|
-
const [tooltipOpen, setTooltipOpen] =
|
|
4396
|
-
const [selectOpen, setSelectOpen] =
|
|
4696
|
+
const suppressNextTooltip = useRef4(false);
|
|
4697
|
+
const [tooltipOpen, setTooltipOpen] = useState6(false);
|
|
4698
|
+
const [selectOpen, setSelectOpen] = useState6(false);
|
|
4397
4699
|
return /* @__PURE__ */ React2.createElement(Tooltip.Root, {
|
|
4398
4700
|
open: tooltipOpen,
|
|
4399
4701
|
onOpenChange: (nextOpen) => {
|
|
@@ -4596,160 +4898,14 @@ var Toolbar = {
|
|
|
4596
4898
|
Markdown: MarkdownStandard,
|
|
4597
4899
|
Extended: MarkdownExtended
|
|
4598
4900
|
};
|
|
4599
|
-
|
|
4600
|
-
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
4601
|
-
var useActionHandler = (view) => {
|
|
4602
|
-
return (action) => {
|
|
4603
|
-
if (!view) {
|
|
4604
|
-
return;
|
|
4605
|
-
}
|
|
4606
|
-
let inlineType, listType;
|
|
4607
|
-
switch (action.type) {
|
|
4608
|
-
case "heading":
|
|
4609
|
-
setHeading(parseInt(action.data))(view);
|
|
4610
|
-
break;
|
|
4611
|
-
case "strong":
|
|
4612
|
-
case "emphasis":
|
|
4613
|
-
case "strikethrough":
|
|
4614
|
-
case "code":
|
|
4615
|
-
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
4616
|
-
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
4617
|
-
break;
|
|
4618
|
-
case "list-ordered":
|
|
4619
|
-
case "list-bullet":
|
|
4620
|
-
case "list-task":
|
|
4621
|
-
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
4622
|
-
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
4623
|
-
break;
|
|
4624
|
-
case "blockquote":
|
|
4625
|
-
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
4626
|
-
break;
|
|
4627
|
-
case "codeblock":
|
|
4628
|
-
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
4629
|
-
break;
|
|
4630
|
-
case "table":
|
|
4631
|
-
insertTable(view);
|
|
4632
|
-
break;
|
|
4633
|
-
case "link":
|
|
4634
|
-
(action.data === false ? removeLink : addLink)(view);
|
|
4635
|
-
break;
|
|
4636
|
-
case "comment":
|
|
4637
|
-
createComment(view);
|
|
4638
|
-
break;
|
|
4639
|
-
}
|
|
4640
|
-
setTimeout(() => {
|
|
4641
|
-
if (!view.hasFocus) {
|
|
4642
|
-
view.focus();
|
|
4643
|
-
}
|
|
4644
|
-
});
|
|
4645
|
-
};
|
|
4646
|
-
};
|
|
4647
|
-
|
|
4648
|
-
// packages/ui/react-ui-editor/src/hooks/useDocAccessor.ts
|
|
4649
|
-
import { useMemo as useMemo2 } from "react";
|
|
4650
|
-
import { createDocAccessor, getTextContent } from "@dxos/echo-schema";
|
|
4651
|
-
var useDocAccessor = (text) => {
|
|
4652
|
-
return useMemo2(() => ({
|
|
4653
|
-
id: text.id,
|
|
4654
|
-
doc: getTextContent(text),
|
|
4655
|
-
accessor: createDocAccessor(text)
|
|
4656
|
-
}), [
|
|
4657
|
-
text
|
|
4658
|
-
]);
|
|
4659
|
-
};
|
|
4660
|
-
|
|
4661
|
-
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4662
|
-
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4663
|
-
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
4664
|
-
import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
4665
|
-
import { log as log10 } from "@dxos/log";
|
|
4666
|
-
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
4667
|
-
var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4668
|
-
var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
4669
|
-
let { id, doc, selection, extensions, autoFocus, scrollTo, debug } = useMemo3(cb, deps ?? []);
|
|
4670
|
-
const onUpdate = useRef3();
|
|
4671
|
-
const [view, setView] = useState4();
|
|
4672
|
-
const parentRef = useRef3(null);
|
|
4673
|
-
useEffect3(() => {
|
|
4674
|
-
let view2;
|
|
4675
|
-
if (parentRef.current) {
|
|
4676
|
-
const state = EditorState3.create({
|
|
4677
|
-
doc,
|
|
4678
|
-
selection,
|
|
4679
|
-
extensions: [
|
|
4680
|
-
id && documentId2.of(id),
|
|
4681
|
-
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4682
|
-
EditorView17.exceptionSink.of((err) => {
|
|
4683
|
-
log10.catch(err, void 0, {
|
|
4684
|
-
F: __dxlog_file12,
|
|
4685
|
-
L: 44,
|
|
4686
|
-
S: void 0,
|
|
4687
|
-
C: (f, a) => f(...a)
|
|
4688
|
-
});
|
|
4689
|
-
}),
|
|
4690
|
-
extensions,
|
|
4691
|
-
EditorView17.updateListener.of(() => {
|
|
4692
|
-
onUpdate.current?.();
|
|
4693
|
-
})
|
|
4694
|
-
].filter(isNotFalsy4)
|
|
4695
|
-
});
|
|
4696
|
-
view2 = new EditorView17({
|
|
4697
|
-
parent: parentRef.current,
|
|
4698
|
-
scrollTo,
|
|
4699
|
-
state,
|
|
4700
|
-
// NOTE: Uncomment to debug/monitor all transactions.
|
|
4701
|
-
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
4702
|
-
dispatchTransactions: (trs, view3) => {
|
|
4703
|
-
if (debug) {
|
|
4704
|
-
logChanges(trs);
|
|
4705
|
-
}
|
|
4706
|
-
view3.update(trs);
|
|
4707
|
-
}
|
|
4708
|
-
});
|
|
4709
|
-
setView(view2);
|
|
4710
|
-
}
|
|
4711
|
-
return () => {
|
|
4712
|
-
view2?.destroy();
|
|
4713
|
-
};
|
|
4714
|
-
}, deps);
|
|
4715
|
-
useEffect3(() => {
|
|
4716
|
-
if (view) {
|
|
4717
|
-
if (!selection && !view.state.selection.main.anchor) {
|
|
4718
|
-
selection = EditorSelection2.single(view.state.doc.line(1).to);
|
|
4719
|
-
}
|
|
4720
|
-
if (selection || scrollTo) {
|
|
4721
|
-
onUpdate.current = () => {
|
|
4722
|
-
onUpdate.current = void 0;
|
|
4723
|
-
view.dispatch({
|
|
4724
|
-
selection,
|
|
4725
|
-
effects: scrollTo && [
|
|
4726
|
-
scrollTo
|
|
4727
|
-
],
|
|
4728
|
-
scrollIntoView: !scrollTo
|
|
4729
|
-
});
|
|
4730
|
-
};
|
|
4731
|
-
}
|
|
4732
|
-
if (autoFocus) {
|
|
4733
|
-
view.focus();
|
|
4734
|
-
}
|
|
4735
|
-
}
|
|
4736
|
-
}, [
|
|
4737
|
-
view,
|
|
4738
|
-
autoFocus,
|
|
4739
|
-
selection,
|
|
4740
|
-
scrollTo
|
|
4741
|
-
]);
|
|
4742
|
-
return {
|
|
4743
|
-
parentRef,
|
|
4744
|
-
view
|
|
4745
|
-
};
|
|
4746
|
-
};
|
|
4747
4901
|
export {
|
|
4902
|
+
BaseTextEditor,
|
|
4748
4903
|
Cursor,
|
|
4749
4904
|
Doc,
|
|
4750
4905
|
EditorModes,
|
|
4751
4906
|
Inline,
|
|
4752
4907
|
List,
|
|
4908
|
+
MarkdownEditor,
|
|
4753
4909
|
RemoteSelectionsDecorator,
|
|
4754
4910
|
SpaceAwarenessProvider,
|
|
4755
4911
|
TextEditor,
|
|
@@ -4769,26 +4925,29 @@ export {
|
|
|
4769
4925
|
awarenessProvider,
|
|
4770
4926
|
blast,
|
|
4771
4927
|
callbackWrapper,
|
|
4928
|
+
codeTheme,
|
|
4772
4929
|
command,
|
|
4773
4930
|
comments,
|
|
4774
4931
|
compareFormatting,
|
|
4775
4932
|
createBasicExtensions,
|
|
4776
4933
|
createComment,
|
|
4777
|
-
createDataExtensions,
|
|
4778
4934
|
createMarkdownExtensions,
|
|
4779
4935
|
createThemeExtensions,
|
|
4780
4936
|
cursorLineMargin,
|
|
4937
|
+
cursorLineMarginFacet,
|
|
4781
4938
|
decorateMarkdown,
|
|
4939
|
+
defaultMarkdownSlots,
|
|
4782
4940
|
defaultOptions,
|
|
4941
|
+
defaultSlots,
|
|
4942
|
+
defaultTextSlots,
|
|
4783
4943
|
defaultTheme,
|
|
4784
4944
|
dnd,
|
|
4785
|
-
documentId2 as documentId,
|
|
4786
4945
|
editorFillLayoutEditor,
|
|
4787
4946
|
editorFillLayoutRoot,
|
|
4788
4947
|
editorMode,
|
|
4789
4948
|
editorWithToolbarLayout,
|
|
4790
4949
|
focusComment,
|
|
4791
|
-
|
|
4950
|
+
formatting,
|
|
4792
4951
|
getFormatting,
|
|
4793
4952
|
getToken,
|
|
4794
4953
|
image,
|
|
@@ -4800,7 +4959,9 @@ export {
|
|
|
4800
4959
|
markdownHighlightStyle,
|
|
4801
4960
|
markdownTags,
|
|
4802
4961
|
markdownTagsExtensions,
|
|
4962
|
+
markdownTheme,
|
|
4803
4963
|
mention,
|
|
4964
|
+
outliner,
|
|
4804
4965
|
removeBlockquote,
|
|
4805
4966
|
removeCodeblock,
|
|
4806
4967
|
removeLink,
|
|
@@ -4813,6 +4974,7 @@ export {
|
|
|
4813
4974
|
setStyle,
|
|
4814
4975
|
table,
|
|
4815
4976
|
tags2 as tags,
|
|
4977
|
+
textTheme,
|
|
4816
4978
|
toggleBlockquote,
|
|
4817
4979
|
toggleCodeblock,
|
|
4818
4980
|
toggleEmphasis,
|
|
@@ -4825,9 +4987,12 @@ export {
|
|
|
4825
4987
|
typewriter,
|
|
4826
4988
|
useActionHandler,
|
|
4827
4989
|
useComments,
|
|
4828
|
-
|
|
4990
|
+
useEditorView,
|
|
4829
4991
|
useFormattingState,
|
|
4992
|
+
useInMemoryTextModel,
|
|
4830
4993
|
useTextEditor,
|
|
4994
|
+
useTextExtensions,
|
|
4995
|
+
useTextModel,
|
|
4831
4996
|
useToolbarContext
|
|
4832
4997
|
};
|
|
4833
4998
|
//# sourceMappingURL=index.mjs.map
|