@dxos/react-ui-editor 0.3.11-main.a6c4a82 → 0.3.11-main.a996413
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 +197 -163
- 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 +0 -3
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +2 -2
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/index.d.ts +0 -2
- package/dist/types/src/components/TextEditor/index.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -0
- package/dist/types/src/extensions/basic.d.ts.map +1 -0
- package/dist/types/src/extensions/blast.d.ts.map +1 -0
- package/dist/types/src/extensions/code.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor/extensions → extensions}/comments.d.ts +4 -2
- package/dist/types/src/extensions/comments.d.ts.map +1 -0
- package/dist/types/src/extensions/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/image.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor/extensions → extensions}/index.d.ts +0 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor/extensions → extensions}/link.d.ts +1 -0
- package/dist/types/src/extensions/link.d.ts.map +1 -0
- package/dist/types/src/extensions/listener.d.ts +10 -0
- package/dist/types/src/extensions/listener.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -0
- package/dist/types/src/extensions/mention.d.ts.map +1 -0
- package/dist/types/src/extensions/mermaid.d.ts.map +1 -0
- package/dist/types/src/extensions/table.d.ts.map +1 -0
- package/dist/types/src/extensions/tasklist.d.ts.map +1 -0
- package/dist/types/src/extensions/typewriter.d.ts.map +1 -0
- package/dist/types/src/extensions/util.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/plugin.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/{components/TextEditor/themes → themes}/default.d.ts +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -0
- package/dist/types/src/themes/index.d.ts.map +1 -0
- package/package.json +21 -21
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +11 -13
- package/src/components/TextEditor/TextEditor.stories.tsx +1 -1
- package/src/components/TextEditor/TextEditor.tsx +6 -6
- package/src/components/TextEditor/index.ts +0 -3
- package/src/{components/TextEditor/extensions → extensions}/code.ts +1 -1
- package/src/{components/TextEditor/extensions → extensions}/comments.ts +27 -10
- package/src/{components/TextEditor/extensions → extensions}/hr.ts +1 -1
- package/src/{components/TextEditor/extensions → extensions}/index.ts +0 -1
- package/src/{components/TextEditor/extensions → extensions}/link.ts +66 -10
- package/src/extensions/listener.ts +35 -0
- package/src/{components/TextEditor/extensions → extensions}/markdown/highlight.ts +1 -1
- package/src/{components/TextEditor/extensions → extensions}/typewriter.ts +1 -1
- package/src/hooks/automerge/plugin.ts +3 -5
- package/src/hooks/useTextModel.ts +5 -4
- package/src/index.ts +2 -0
- package/src/{components/TextEditor/themes → themes}/default.ts +1 -1
- package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/image.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/listener.d.ts +0 -9
- package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/mention.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/mermaid.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/table.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts +0 -12
- package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/typewriter.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/util.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/themes/default.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/themes/index.d.ts.map +0 -1
- package/src/components/TextEditor/extensions/listener.ts +0 -23
- package/src/components/TextEditor/extensions/tooltip.ts +0 -61
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/autocomplete.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/basic.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/blast.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/code.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/hr.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/image.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/bundle.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/highlight.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/index.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/mention.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/mermaid.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/table.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/tasklist.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/typewriter.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/util.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/themes → themes}/index.d.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/autocomplete.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/basic.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/blast.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/image.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/markdown/bundle.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/markdown/index.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/mention.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/mermaid.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/table.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/tasklist.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/util.ts +0 -0
- /package/src/{components/TextEditor/themes → themes}/index.ts +0 -0
|
@@ -12,8 +12,8 @@ import { fixedInsetFlexLayout, groupSurface, mx } from '@dxos/react-ui-theme';
|
|
|
12
12
|
import { withTheme } from '@dxos/storybook-utils';
|
|
13
13
|
|
|
14
14
|
import { defaultSlots, TextEditor, type TextEditorProps, type TextEditorRef, type TextEditorSlots } from './TextEditor';
|
|
15
|
-
import { textTheme } from './themes';
|
|
16
15
|
import { useTextModel } from '../../hooks';
|
|
16
|
+
import { textTheme } from '../../themes';
|
|
17
17
|
|
|
18
18
|
const initialText = [
|
|
19
19
|
'# TextEditor',
|
|
@@ -21,10 +21,10 @@ import { generateName } from '@dxos/display-name';
|
|
|
21
21
|
import { useThemeContext } from '@dxos/react-ui';
|
|
22
22
|
import { getColorForValue, inputSurface, mx } from '@dxos/react-ui-theme';
|
|
23
23
|
|
|
24
|
-
import { basicBundle, markdownBundle, setCommentRange } from '
|
|
25
|
-
import { defaultTheme, markdownTheme, textTheme } from './themes';
|
|
24
|
+
import { basicBundle, markdownBundle, setCommentRange } from '../../extensions';
|
|
26
25
|
import { type CommentRange, type EditorModel } from '../../hooks';
|
|
27
26
|
import { type ThemeStyles } from '../../styles';
|
|
27
|
+
import { defaultTheme, markdownTheme, textTheme } from '../../themes';
|
|
28
28
|
|
|
29
29
|
export const EditorModes = ['default', 'vim'] as const;
|
|
30
30
|
export type EditorMode = (typeof EditorModes)[number];
|
|
@@ -56,10 +56,10 @@ export type TextEditorSlots = {
|
|
|
56
56
|
|
|
57
57
|
export type TextEditorProps = {
|
|
58
58
|
model: EditorModel;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
editorMode?: EditorMode;
|
|
59
|
+
readonly?: boolean; // TODO(burdon): Move into model.
|
|
60
|
+
comments?: CommentRange[]; // TODO(burdon): Move into extension.
|
|
62
61
|
extensions?: Extension[];
|
|
62
|
+
editorMode?: EditorMode;
|
|
63
63
|
slots?: TextEditorSlots;
|
|
64
64
|
};
|
|
65
65
|
|
|
@@ -68,7 +68,7 @@ export type TextEditorProps = {
|
|
|
68
68
|
* NOTE: Rather than adding properties, try to create extensions that can be reused.
|
|
69
69
|
*/
|
|
70
70
|
export const BaseTextEditor = forwardRef<TextEditorRef, TextEditorProps>(
|
|
71
|
-
({ model,
|
|
71
|
+
({ model, readonly, comments, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
72
72
|
const { themeMode } = useThemeContext();
|
|
73
73
|
const tabsterDOMAttribute = useFocusableGroup({ tabBehavior: 'limited' });
|
|
74
74
|
const [root, setRoot] = useState<HTMLDivElement | null>(null);
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
WidgetType,
|
|
17
17
|
type Rect,
|
|
18
18
|
} from '@codemirror/view';
|
|
19
|
+
import get from 'lodash.get';
|
|
19
20
|
import sortBy from 'lodash.sortby';
|
|
20
21
|
|
|
21
22
|
import { debounce } from '@dxos/async';
|
|
@@ -24,7 +25,8 @@ import { log } from '@dxos/log';
|
|
|
24
25
|
import { nonNullable } from '@dxos/util';
|
|
25
26
|
|
|
26
27
|
import { callbackWrapper } from './util';
|
|
27
|
-
import { type CommentRange, type EditorModel, modelState, type Range } from '
|
|
28
|
+
import { type CommentRange, type EditorModel, modelState, type Range } from '../hooks';
|
|
29
|
+
import { tokens } from '../styles';
|
|
28
30
|
|
|
29
31
|
// TODO(burdon): Handle delete, cut, copy, and paste (separately) text that includes comment range.
|
|
30
32
|
// TODO(burdon): Consider breaking into separate plugin (since not standalone)? Like mermaid?
|
|
@@ -41,10 +43,10 @@ const styles = EditorView.baseTheme({
|
|
|
41
43
|
backgroundColor: 'orange',
|
|
42
44
|
},
|
|
43
45
|
'& .cm-comment': {
|
|
44
|
-
backgroundColor: 'yellow',
|
|
46
|
+
backgroundColor: get(tokens, 'extend.colors.yellow.50'),
|
|
45
47
|
},
|
|
46
48
|
'& .cm-comment-active': {
|
|
47
|
-
backgroundColor: '
|
|
49
|
+
backgroundColor: get(tokens, 'extend.colors.yellow.100'),
|
|
48
50
|
},
|
|
49
51
|
});
|
|
50
52
|
|
|
@@ -70,9 +72,22 @@ export type CommentsState = CommentSelected & {
|
|
|
70
72
|
ranges: ExtendedCommentRange[];
|
|
71
73
|
};
|
|
72
74
|
|
|
75
|
+
export const setFocus = (view: EditorView, thread: string) => {
|
|
76
|
+
const range = view.state.field(commentsStateField).ranges.find((range) => range.id === thread);
|
|
77
|
+
if (!range) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
view.dispatch({
|
|
82
|
+
effects: setSelection.of({ active: thread }),
|
|
83
|
+
selection: { anchor: range.from },
|
|
84
|
+
scrollIntoView: true,
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
73
88
|
export const setCommentRange = StateEffect.define<{ model: EditorModel; comments: CommentRange[] }>();
|
|
74
89
|
|
|
75
|
-
const setSelection = StateEffect.define<CommentSelected>();
|
|
90
|
+
export const setSelection = StateEffect.define<CommentSelected>();
|
|
76
91
|
|
|
77
92
|
const setCommentState = StateEffect.define<CommentsState>();
|
|
78
93
|
|
|
@@ -93,10 +108,12 @@ const commentsStateField = StateField.define<CommentsState>({
|
|
|
93
108
|
// Update range from store.
|
|
94
109
|
if (effect.is(setCommentRange)) {
|
|
95
110
|
const { model, comments } = effect.value;
|
|
96
|
-
const ranges: ExtendedCommentRange[] = comments
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
111
|
+
const ranges: ExtendedCommentRange[] = comments
|
|
112
|
+
.map((comment) => {
|
|
113
|
+
const range = model.getRangeFromCursor!(comment.cursor);
|
|
114
|
+
return range && { ...comment, ...range };
|
|
115
|
+
})
|
|
116
|
+
.filter(nonNullable);
|
|
100
117
|
|
|
101
118
|
return { ...value, ranges };
|
|
102
119
|
}
|
|
@@ -284,7 +301,7 @@ export const comments = (options: CommentsOptions = {}): Extension => {
|
|
|
284
301
|
? keymap.of([
|
|
285
302
|
{
|
|
286
303
|
key: options?.key ?? "meta-'",
|
|
287
|
-
run: createCommentThread,
|
|
304
|
+
run: callbackWrapper(createCommentThread),
|
|
288
305
|
},
|
|
289
306
|
])
|
|
290
307
|
: [],
|
|
@@ -334,7 +351,7 @@ export const comments = (options: CommentsOptions = {}): Extension => {
|
|
|
334
351
|
ranges.forEach((range) => {
|
|
335
352
|
if (from2 === to2) {
|
|
336
353
|
const newRange = model.getRangeFromCursor!(range.cursor);
|
|
337
|
-
if (newRange.to - newRange.from === 0) {
|
|
354
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
338
355
|
// TODO(burdon): Delete range if empty.
|
|
339
356
|
log.info('deleted comment', { thread: range.id });
|
|
340
357
|
}
|
|
@@ -12,7 +12,11 @@ import {
|
|
|
12
12
|
StateField,
|
|
13
13
|
type Transaction,
|
|
14
14
|
} from '@codemirror/state';
|
|
15
|
-
import { Decoration, EditorView, WidgetType } from '@codemirror/view';
|
|
15
|
+
import { Decoration, EditorView, WidgetType, hoverTooltip } from '@codemirror/view';
|
|
16
|
+
|
|
17
|
+
import { tooltipContent } from '@dxos/react-ui-theme';
|
|
18
|
+
|
|
19
|
+
const markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
16
20
|
|
|
17
21
|
// Adapted from:
|
|
18
22
|
// https://codemirror.net/try/?c=aW1wb3J0IHsgYmFzaWNTZXR1cCwgRWRpdG9yVmlldyB9IGZyb20gImNvZGVtaXJyb3IiCmltcG9ydCB7IG1hcmtkb3duIH0gZnJvbSAiQGNvZGVtaXJyb3IvbGFuZy1tYXJrZG93biIKaW1wb3J0IHsgc3ludGF4VHJlZSB9IGZyb20gIkBjb2RlbWlycm9yL2xhbmd1YWdlIjsKaW1wb3J0IHsgRWRpdG9yU3RhdGUsIFJhbmdlU2V0QnVpbGRlciwgU3RhdGVGaWVsZCB9IGZyb20gIkBjb2RlbWlycm9yL3N0YXRlIjsKaW1wb3J0IHsgRGVjb3JhdGlvbiwgV2lkZ2V0VHlwZSB9IGZyb20gIkBjb2RlbWlycm9yL3ZpZXciOwoKY2xhc3MgTGluayBleHRlbmRzIFdpZGdldFR5cGUgewogIGNvbnN0cnVjdG9yKHRleHQsIHVybCkgewogICAgc3VwZXIoKQogICAgdGhpcy50ZXh0ID0gdGV4dAogICAgdGhpcy51cmwgPSB1cmwKICB9CiAgZXEob3RoZXIpIHsgcmV0dXJuIHRoaXMudGV4dCA9PSBvdGhlci50ZXh0ICYmIHRoaXMudXJsID09IG90aGVyLnVybCB9CiAgdG9ET00oKSB7CiAgICBsZXQgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKQogICAgbGluay50ZXh0Q29udGVudCA9IHRoaXMudGV4dAogICAgbGluay5ocmVmID0gdGhpcy51cmwKICAgIHJldHVybiBsaW5rOwogIH0KfQoKbGV0IGRlY29yYXRpb25zRmllbGQgPSBTdGF0ZUZpZWxkLmRlZmluZSh7CiAgY3JlYXRlKCkgewogICAgcmV0dXJuIERlY29yYXRpb24ubm9uZTsKICB9LAogIHVwZGF0ZShfLCB0cikgewogICAgY29uc3QgYnVpbGRlciA9IG5ldyBSYW5nZVNldEJ1aWxkZXIoKTsKICAgIGxldCBjdXJzb3IgPSB0ci5zdGF0ZS5zZWxlY3Rpb24ubWFpbi5oZWFkOwogICAgc3ludGF4VHJlZSh0ci5zdGF0ZSkuaXRlcmF0ZSh7CiAgICAgIGVudGVyOiAobm9kZSkgPT4gewogICAgICAgIGlmICgoY3Vyc29yIDwgbm9kZS5mcm9tIHx8IGN1cnNvciA+IG5vZGUudG8pICYmIG5vZGUubmFtZSA9PSAiTGluayIpIHsKICAgICAgICAgIGxldCBtYXJrcyA9IG5vZGUubm9kZS5nZXRDaGlsZHJlbigiTGlua01hcmsiKTsKICAgICAgICAgIGxldCB0ZXh0ID0gbWFya3MubGVuZ3RoID49IDIgPyB0ci5zdGF0ZS5zbGljZURvYyhtYXJrc1swXS50bywgbWFya3NbMV0uZnJvbSkgOiAiIgoKICAgICAgICAgIGxldCB1cmxOb2RlID0gbm9kZS5ub2RlLmdldENoaWxkKCJVUkwiKTsKICAgICAgICAgIGxldCB1cmwgPSB1cmxOb2RlID8gdHIuc3RhdGUuc2xpY2VEb2ModXJsTm9kZS5mcm9tLCB1cmxOb2RlLnRvKSA6ICIiCiAgICAgICAgICBidWlsZGVyLmFkZChub2RlLmZyb20sIG5vZGUudG8sIERlY29yYXRpb24ucmVwbGFjZSh7CiAgICAgICAgICAgIHdpZGdldDogbmV3IExpbmsodGV4dCwgdXJsKSwKICAgICAgICAgIH0pLAogICAgICAgICAgICAgICAgICAgICApOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSwKICAgIH0pOwogICAgcmV0dXJuIGJ1aWxkZXIuZmluaXNoKCk7CiAgfSwKICBwcm92aWRlOiAoZikgPT4gRWRpdG9yVmlldy5kZWNvcmF0aW9ucy5mcm9tKGYpLAp9KTsKCmxldCB2aWV3ID0gbmV3IEVkaXRvclZpZXcoewogIGRvYzogIiMgSGVsbG8gV29ybGRcblxuW1Rlc3RdKGh0dHBzOi8vZXhhbXBsZS5jb20pXG5cblxuIiwKICBleHRlbnNpb25zOiBbZGVjb3JhdGlvbnNGaWVsZCwgbWFya2Rvd24oKV0sCiAgcGFyZW50OiBkb2N1bWVudC5ib2R5LAp9KTsKCnZpZXcuZm9jdXMoKTs=
|
|
@@ -20,6 +24,7 @@ import { Decoration, EditorView, WidgetType } from '@codemirror/view';
|
|
|
20
24
|
|
|
21
25
|
export type LinkOptions = {
|
|
22
26
|
link?: boolean;
|
|
27
|
+
onHover?: (el: Element, url: string) => void;
|
|
23
28
|
onRender?: (el: Element, url: string) => void;
|
|
24
29
|
};
|
|
25
30
|
|
|
@@ -28,11 +33,62 @@ export type LinkOptions = {
|
|
|
28
33
|
* https://codemirror.net/docs/ref/#state.StateField
|
|
29
34
|
*/
|
|
30
35
|
export const link = (options: LinkOptions = {}): Extension => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
const extensions: Extension[] = [
|
|
37
|
+
StateField.define<RangeSet<any>>({
|
|
38
|
+
create: (state) => update(state, options),
|
|
39
|
+
update: (_: RangeSet<any>, tr: Transaction) => update(tr.state, options),
|
|
40
|
+
provide: (field) => EditorView.decorations.from(field),
|
|
41
|
+
}),
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
if (options.onHover) {
|
|
45
|
+
extensions.push(
|
|
46
|
+
// https://codemirror.net/examples/tooltip
|
|
47
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
48
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
49
|
+
hoverTooltip((view, pos) => {
|
|
50
|
+
const { from, text } = view.state.doc.lineAt(pos);
|
|
51
|
+
const p = pos - from;
|
|
52
|
+
|
|
53
|
+
let idx = 0;
|
|
54
|
+
let match;
|
|
55
|
+
do {
|
|
56
|
+
match = text.substring(idx).match(markdownLinkRegexp);
|
|
57
|
+
if (!match) {
|
|
58
|
+
match = undefined;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
idx = text.indexOf(match[0]);
|
|
63
|
+
if (p >= idx && p < idx + match[0].length) {
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
idx += match[0].length;
|
|
68
|
+
} while (true);
|
|
69
|
+
|
|
70
|
+
if (!match) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const [, , url] = match ?? [];
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
pos: idx + from,
|
|
78
|
+
end: idx + from + match[0].length,
|
|
79
|
+
above: true,
|
|
80
|
+
create: () => {
|
|
81
|
+
const el = document.createElement('div');
|
|
82
|
+
el.className = tooltipContent({}, 'pli-2 plb-1');
|
|
83
|
+
options.onHover!(el, url);
|
|
84
|
+
return { dom: el, offset: { x: 0, y: 4 } };
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return extensions;
|
|
36
92
|
};
|
|
37
93
|
|
|
38
94
|
class LinkButton extends WidgetType {
|
|
@@ -56,12 +112,12 @@ class LinkButton extends WidgetType {
|
|
|
56
112
|
}
|
|
57
113
|
|
|
58
114
|
class LinkText extends WidgetType {
|
|
59
|
-
constructor(private readonly
|
|
115
|
+
constructor(private readonly _text: string, private readonly _url?: string) {
|
|
60
116
|
super();
|
|
61
117
|
}
|
|
62
118
|
|
|
63
119
|
override eq(other: LinkText) {
|
|
64
|
-
return this.
|
|
120
|
+
return this._url === other._url;
|
|
65
121
|
}
|
|
66
122
|
|
|
67
123
|
toDOM(view: EditorView) {
|
|
@@ -76,7 +132,7 @@ class LinkText extends WidgetType {
|
|
|
76
132
|
link.onclick = () => {
|
|
77
133
|
view.dispatch({
|
|
78
134
|
selection: {
|
|
79
|
-
anchor:
|
|
135
|
+
anchor: view.posAtDOM(link),
|
|
80
136
|
},
|
|
81
137
|
});
|
|
82
138
|
};
|
|
@@ -112,7 +168,7 @@ const update = (state: EditorState, options: LinkOptions) => {
|
|
|
112
168
|
node.from,
|
|
113
169
|
node.to,
|
|
114
170
|
Decoration.replace({
|
|
115
|
-
widget: new LinkText(
|
|
171
|
+
widget: new LinkText(text, options.link ? url : undefined),
|
|
116
172
|
}),
|
|
117
173
|
);
|
|
118
174
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Extension } from '@codemirror/state';
|
|
6
|
+
import { EditorView } from '@codemirror/view';
|
|
7
|
+
|
|
8
|
+
export type ListenerOptions = {
|
|
9
|
+
onFocus?: (focused: boolean) => void;
|
|
10
|
+
onChange?: (text: string) => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Event listener.
|
|
15
|
+
*/
|
|
16
|
+
export const listener = ({ onFocus, onChange }: ListenerOptions): Extension => {
|
|
17
|
+
const extensions: Extension[] = [];
|
|
18
|
+
|
|
19
|
+
onFocus &&
|
|
20
|
+
extensions.push(
|
|
21
|
+
EditorView.focusChangeEffect.of((_, focused) => {
|
|
22
|
+
onFocus(focused);
|
|
23
|
+
return null;
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
onChange &&
|
|
28
|
+
extensions.push(
|
|
29
|
+
EditorView.updateListener.of((update) => {
|
|
30
|
+
onChange(update.state.doc.toString());
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return extensions;
|
|
35
|
+
};
|
|
@@ -19,7 +19,7 @@ const defaultItems = ['hello world!', 'this is a test.', 'this is [DXOS](https:/
|
|
|
19
19
|
*/
|
|
20
20
|
export const typewriter = ({ delay = 75, items = defaultItems }: DemoOptions = {}): Extension => {
|
|
21
21
|
let t: any;
|
|
22
|
-
let idx = 0;
|
|
22
|
+
let idx = 0; // TODO(burdon): Make global.
|
|
23
23
|
|
|
24
24
|
return [
|
|
25
25
|
keymap.of([
|
|
@@ -83,15 +83,13 @@ export const automergePlugin = (handle: IDocHandle, path: Prop[]): AutomergePlug
|
|
|
83
83
|
|
|
84
84
|
const viewPlugin = ViewPlugin.fromClass(
|
|
85
85
|
class AutomergeCodemirrorViewPlugin implements PluginValue {
|
|
86
|
-
private _view: EditorView
|
|
87
|
-
|
|
88
|
-
constructor(view: EditorView) {
|
|
89
|
-
this._view = view;
|
|
86
|
+
constructor(private readonly _view: EditorView) {
|
|
90
87
|
handle.addListener('change', this._handleChange);
|
|
91
88
|
}
|
|
92
89
|
|
|
93
90
|
update(update: ViewUpdate) {
|
|
94
|
-
if (update.transactions.length > 0 && update.transactions.some((
|
|
91
|
+
if (update.transactions.length > 0 && update.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
92
|
+
// TODO(burdon): This is a hack to ensure that the view is updated after the transaction is applied.
|
|
95
93
|
queueMicrotask(() => {
|
|
96
94
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
97
95
|
});
|
|
@@ -55,7 +55,7 @@ export type EditorModel = {
|
|
|
55
55
|
content: string | YText | YXmlFragment | DocAccessor;
|
|
56
56
|
text: () => string;
|
|
57
57
|
getCursorFromRange?: (value: Range) => string;
|
|
58
|
-
getRangeFromCursor?: (cursor: string) => Range;
|
|
58
|
+
getRangeFromCursor?: (cursor: string) => Range | undefined;
|
|
59
59
|
extension?: Extension;
|
|
60
60
|
awareness?: Awareness;
|
|
61
61
|
peer?: {
|
|
@@ -110,16 +110,17 @@ const createYjsModel = ({ identity, space, text }: UseTextModelProps): EditorMod
|
|
|
110
110
|
return [arrayToString(from), arrayToString(to)].join(':');
|
|
111
111
|
},
|
|
112
112
|
getRangeFromCursor: (cursor: string) => {
|
|
113
|
+
invariant(text.doc);
|
|
113
114
|
const parts = cursor.split(':');
|
|
114
115
|
const from = Y.createAbsolutePositionFromRelativePosition(
|
|
115
116
|
Y.decodeRelativePosition(stringToArray(parts[0])),
|
|
116
|
-
text.doc
|
|
117
|
+
text.doc,
|
|
117
118
|
);
|
|
118
119
|
const to = Y.createAbsolutePositionFromRelativePosition(
|
|
119
120
|
Y.decodeRelativePosition(stringToArray(parts[1])),
|
|
120
|
-
text.doc
|
|
121
|
+
text.doc,
|
|
121
122
|
);
|
|
122
|
-
return { from: from
|
|
123
|
+
return from && to ? { from: from.index, to: to.index } : undefined;
|
|
123
124
|
},
|
|
124
125
|
extension: [yCollab(text.content as YText, provider?.awareness), modelState.init(() => model)],
|
|
125
126
|
awareness: provider?.awareness,
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import get from 'lodash.get';
|
|
6
6
|
|
|
7
|
-
import { type ThemeStyles, tokens } from '
|
|
7
|
+
import { type ThemeStyles, tokens } from '../styles';
|
|
8
8
|
|
|
9
9
|
// TODO(burdon): Can we erase All of the default CM styles?
|
|
10
10
|
// TODO(burdon): Theme styles seem to be added multiple times?
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/autocomplete.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,0BAA0B,CAAC;AAGlC,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,EAAE,CAAC;CAC1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,iBAAkB,mBAAmB,4CAgC7D,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"basic.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/basic.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAInD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,WAAW,uDAAwD,kBAAkB,KAAG,SAAS,EAa5E,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blast.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/blast.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAMnD,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,gBAAgB,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,qBAAqB,EAAE;QAAE,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IACpE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,YAU5B,CAAC;AAEF,eAAO,MAAM,KAAK,aAAa,QAAQ,YAAY,CAAC,KAAoB,SAmEvE,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/code.ts"],"names":[],"mappings":"AAuDA,eAAO,MAAM,IAAI,+CA2ChB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/comments.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAA2B,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAWL,KAAK,IAAI,EACV,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAc,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AA8B7F,KAAK,eAAe,GAAG;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAGF,KAAK,oBAAoB,GAAG,KAAK,GAC/B,YAAY,GAAG;IAEb,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB,CAAC;AAEJ,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG;IAC5C,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,eAAe;WAA+B,WAAW;cAAY,YAAY,EAAE;EAAK,CAAC;AA+FtG,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACjD;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;CACjC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,QAAQ,aAAa,eAAe,KAAQ,SA+LxD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hr.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/hr.ts"],"names":[],"mappings":"AAmDA,eAAO,MAAM,EAAE,+CAsBd,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/image.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,SAAS,EAKf,MAAM,mBAAmB,CAAC;AAG3B,MAAM,MAAM,YAAY,GAAG,EAAE,CAAC;AAE9B,eAAO,MAAM,KAAK,aAAa,YAAY,KAAQ,SAMlD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/index.ts"],"names":[],"mappings":"AAIA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,MAAM,CAAC;AACrB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/link.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,SAAS,EAKf,MAAM,mBAAmB,CAAC;AAO3B,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,IAAI,aAAa,WAAW,KAAQ,SAMhD,CAAC"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { StateField } from '@codemirror/state';
|
|
2
|
-
export type ListenerOptions = {
|
|
3
|
-
onChange: (text: string) => void;
|
|
4
|
-
};
|
|
5
|
-
/**
|
|
6
|
-
* Based on https://github.com/codemirror/dev/issues/44#issuecomment-789093799
|
|
7
|
-
*/
|
|
8
|
-
export declare const listener: ({ onChange }: ListenerOptions) => StateField<null>;
|
|
9
|
-
//# sourceMappingURL=listener.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/listener.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAAC;AAEnE;;GAEG;AACH,eAAO,MAAM,QAAQ,iBAAkB,eAAe,qBAWrD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/TextEditor/extensions/markdown/bundle.ts"],"names":[],"mappings":"AAUA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAYhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIhD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;GAOG;AAEH,eAAO,MAAM,cAAc,wDAIxB,qBAAqB,KAAG,SAAS,EA6CnC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"highlight.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/TextEditor/extensions/markdown/highlight.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAmB,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,KAAK,cAAc,EAAS,MAAM,iBAAiB,CAAC;AAgB7D;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;CAgBxB,CAAC;AAaF,eAAO,MAAM,sBAAsB,EAAE,cAAc,EAKlD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,cAAe,OAAO,mBAgIxD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/TextEditor/extensions/markdown/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mention.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/mention.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CACtC,CAAC;AAEF,eAAO,MAAM,OAAO,iBAAkB,cAAc,KAAG,SAmBtD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/mermaid.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAInD,eAAO,MAAM,OAAO,QAAO,SAE1B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/table.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoB,KAAK,QAAQ,EAAmB,UAAU,EAAoB,MAAM,mBAAmB,CAAC;AASnH,MAAM,MAAM,YAAY,GAAG,EAAE,CAAC;AAE9B;;;GAGG;AACH,eAAO,MAAM,KAAK,aAAa,YAAY,8BAM1C,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tasklist.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/tasklist.ts"],"names":[],"mappings":"AA+DA,MAAM,MAAM,eAAe,GAAG,EAAE,CAAC;AAEjC,eAAO,MAAM,QAAQ,aAAa,eAAe,4CAuDhD,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { type Extension } from '@codemirror/state';
|
|
2
|
-
export type TooltipOptions = {
|
|
3
|
-
onHover: (el: Element, url: string) => void;
|
|
4
|
-
regexp?: RegExp;
|
|
5
|
-
};
|
|
6
|
-
/**
|
|
7
|
-
* https://codemirror.net/examples/tooltip
|
|
8
|
-
* https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
9
|
-
* https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
10
|
-
*/
|
|
11
|
-
export declare const tooltip: ({ onHover, regexp }: TooltipOptions) => Extension;
|
|
12
|
-
//# sourceMappingURL=tooltip.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/tooltip.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAOnD,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,OAAO,wBAA8C,cAAc,KAAG,SAuC/E,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typewriter.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/typewriter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAKnD,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,UAAU,sBAA0C,WAAW,KAAQ,SAgDnF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/util.ts"],"names":[],"mappings":"AAMA;;GAEG;AAEH,eAAO,MAAM,eAAe,kCAOR,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/themes/default.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,WAAW,EAAU,MAAM,iBAAiB,CAAC;AAK3D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,WA8P1B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,WAOvB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAK3B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,WAOvB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/themes/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { StateField } from '@codemirror/state';
|
|
6
|
-
|
|
7
|
-
export type ListenerOptions = { onChange: (text: string) => void };
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Based on https://github.com/codemirror/dev/issues/44#issuecomment-789093799
|
|
11
|
-
*/
|
|
12
|
-
export const listener = ({ onChange }: ListenerOptions) => {
|
|
13
|
-
return StateField.define({
|
|
14
|
-
create: () => null,
|
|
15
|
-
update: (_value, transaction) => {
|
|
16
|
-
if (transaction.docChanged && onChange) {
|
|
17
|
-
onChange(transaction.newDoc.toString());
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return null;
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type Extension } from '@codemirror/state';
|
|
6
|
-
import { hoverTooltip } from '@codemirror/view';
|
|
7
|
-
|
|
8
|
-
import { tooltipContent } from '@dxos/react-ui-theme';
|
|
9
|
-
|
|
10
|
-
const markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
11
|
-
|
|
12
|
-
export type TooltipOptions = {
|
|
13
|
-
onHover: (el: Element, url: string) => void;
|
|
14
|
-
regexp?: RegExp;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* https://codemirror.net/examples/tooltip
|
|
19
|
-
* https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
20
|
-
* https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
21
|
-
*/
|
|
22
|
-
export const tooltip = ({ onHover, regexp = markdownLinkRegexp }: TooltipOptions): Extension =>
|
|
23
|
-
hoverTooltip((view, pos) => {
|
|
24
|
-
const { from, text } = view.state.doc.lineAt(pos);
|
|
25
|
-
const p = pos - from;
|
|
26
|
-
|
|
27
|
-
let idx = 0;
|
|
28
|
-
let match;
|
|
29
|
-
do {
|
|
30
|
-
match = text.substring(idx).match(regexp);
|
|
31
|
-
if (!match) {
|
|
32
|
-
match = undefined;
|
|
33
|
-
break;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
idx = text.indexOf(match[0]);
|
|
37
|
-
if (p >= idx && p < idx + match[0].length) {
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
idx += match[0].length;
|
|
42
|
-
} while (true);
|
|
43
|
-
|
|
44
|
-
if (!match) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const [, , url] = match ?? [];
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
pos: idx + from,
|
|
52
|
-
end: idx + from + match[0].length,
|
|
53
|
-
above: true,
|
|
54
|
-
create: () => {
|
|
55
|
-
const el = document.createElement('div');
|
|
56
|
-
el.className = tooltipContent({}, 'pli-2 plb-1');
|
|
57
|
-
onHover(el, url);
|
|
58
|
-
return { dom: el, offset: { x: 0, y: 4 } };
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/bundle.d.ts
RENAMED
|
File without changes
|