@dxos/react-ui-editor 0.6.13 → 0.6.14-main.1366248
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 +772 -712
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +5667 -0
- package/dist/lib/node/index.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -0
- package/dist/lib/node-esm/index.mjs +5650 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/types/src/InputMode.stories.d.ts +11 -11
- package/dist/types/src/InputMode.stories.d.ts.map +1 -1
- package/dist/types/src/TextEditor.stories.d.ts +4 -1
- package/dist/types/src/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/defaults.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete.d.ts +2 -1
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.test.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/awareness/awareness.d.ts +2 -2
- package/dist/types/src/extensions/awareness/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/command/state.d.ts +2 -2
- package/dist/types/src/extensions/command/state.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +1 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/debug.d.ts +2 -2
- package/dist/types/src/extensions/debug.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts +1 -0
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/focus.d.ts +7 -0
- package/dist/types/src/extensions/focus.d.ts.map +1 -0
- package/dist/types/src/extensions/folding.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +2 -4
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/listener.d.ts +2 -1
- package/dist/types/src/extensions/listener.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/image.d.ts +3 -6
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -1
- package/dist/types/src/extensions/modes.d.ts +3 -4
- package/dist/types/src/extensions/modes.d.ts.map +1 -1
- package/dist/types/src/extensions/{state.d.ts → selection.d.ts} +8 -4
- package/dist/types/src/extensions/selection.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts +1 -2
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/types.d.ts.map +1 -0
- package/dist/types/src/{extensions → util}/cursor.d.ts +9 -3
- package/dist/types/src/util/cursor.d.ts.map +1 -0
- package/dist/types/src/util/debug.d.ts +17 -0
- package/dist/types/src/util/debug.d.ts.map +1 -0
- package/dist/types/src/util/dom.d.ts.map +1 -0
- package/dist/types/src/util/facet.d.ts +3 -0
- package/dist/types/src/util/facet.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +6 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/src/{extensions/util → util}/react.d.ts +1 -1
- package/dist/types/src/util/react.d.ts.map +1 -0
- package/package.json +46 -41
- package/src/InputMode.stories.tsx +8 -8
- package/src/TextEditor.stories.tsx +100 -75
- package/src/components/Toolbar/Toolbar.tsx +8 -11
- package/src/defaults.ts +0 -2
- package/src/extensions/annotations.ts +1 -1
- package/src/extensions/autocomplete.ts +9 -8
- package/src/extensions/automerge/automerge.stories.tsx +2 -2
- package/src/extensions/automerge/{automerge.spec.tsx → automerge.test.tsx} +1 -0
- package/src/extensions/automerge/automerge.ts +2 -2
- package/src/extensions/automerge/cursor.ts +1 -1
- package/src/extensions/awareness/awareness.ts +3 -5
- package/src/extensions/command/hint.ts +1 -1
- package/src/extensions/command/state.ts +3 -4
- package/src/extensions/comments.ts +45 -47
- package/src/extensions/debug.ts +2 -2
- package/src/extensions/factories.ts +5 -1
- package/src/extensions/focus.ts +35 -0
- package/src/extensions/folding.tsx +7 -5
- package/src/extensions/index.ts +2 -4
- package/src/extensions/listener.ts +5 -2
- package/src/extensions/markdown/changes.test.ts +1 -3
- package/src/extensions/markdown/decorate.ts +50 -7
- package/src/extensions/markdown/formatting.test.ts +1 -3
- package/src/extensions/markdown/highlight.ts +0 -5
- package/src/extensions/markdown/image.ts +53 -42
- package/src/extensions/markdown/link.ts +3 -2
- package/src/extensions/markdown/parser.test.ts +1 -2
- package/src/extensions/markdown/styles.ts +10 -0
- package/src/extensions/markdown/table.ts +3 -3
- package/src/extensions/modes.ts +6 -7
- package/src/extensions/{state.ts → selection.ts} +20 -16
- package/src/hooks/useTextEditor.ts +36 -35
- package/src/index.ts +1 -0
- package/src/styles/markdown.ts +1 -3
- package/src/styles/theme.ts +3 -1
- package/src/{extensions → util}/cursor.ts +11 -8
- package/src/{util.ts → util/debug.ts} +25 -2
- package/src/util/facet.ts +13 -0
- package/src/{extensions/util → util}/index.ts +3 -2
- package/src/{extensions/util → util}/react.tsx +6 -1
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts +0 -2
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts.map +0 -1
- package/dist/types/src/extensions/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/doc.d.ts +0 -6
- package/dist/types/src/extensions/doc.d.ts.map +0 -1
- package/dist/types/src/extensions/state.d.ts.map +0 -1
- package/dist/types/src/extensions/types.d.ts.map +0 -1
- package/dist/types/src/extensions/util/dom.d.ts.map +0 -1
- package/dist/types/src/extensions/util/error.d.ts +0 -2
- package/dist/types/src/extensions/util/error.d.ts.map +0 -1
- package/dist/types/src/extensions/util/index.d.ts +0 -5
- package/dist/types/src/extensions/util/index.d.ts.map +0 -1
- package/dist/types/src/extensions/util/overlap.d.ts +0 -8
- package/dist/types/src/extensions/util/overlap.d.ts.map +0 -1
- package/dist/types/src/extensions/util/react.d.ts.map +0 -1
- package/dist/types/src/util.d.ts +0 -7
- package/dist/types/src/util.d.ts.map +0 -1
- package/src/extensions/automerge/automerge.test.ts +0 -13
- package/src/extensions/doc.ts +0 -17
- package/src/extensions/util/error.ts +0 -15
- package/src/extensions/util/overlap.ts +0 -12
- /package/dist/types/src/{extensions/types.d.ts → types.d.ts} +0 -0
- /package/dist/types/src/{extensions/util → util}/dom.d.ts +0 -0
- /package/src/{extensions/types.ts → types.ts} +0 -0
- /package/src/{extensions/util → util}/dom.ts +0 -0
@@ -25,9 +25,9 @@ export type TableOptions = {};
|
|
25
25
|
* https://github.github.com/gfm/#tables-extension
|
26
26
|
*/
|
27
27
|
export const table = (options: TableOptions = {}): Extension => {
|
28
|
-
return StateField.define<RangeSet<
|
28
|
+
return StateField.define<RangeSet<Decoration>>({
|
29
29
|
create: (state) => update(state, options),
|
30
|
-
update: (_: RangeSet<
|
30
|
+
update: (_: RangeSet<Decoration>, tr: Transaction) => update(tr.state, options),
|
31
31
|
provide: (field) => EditorView.decorations.from(field),
|
32
32
|
});
|
33
33
|
};
|
@@ -40,7 +40,7 @@ type Table = {
|
|
40
40
|
};
|
41
41
|
|
42
42
|
const update = (state: EditorState, _options: TableOptions) => {
|
43
|
-
const builder = new RangeSetBuilder();
|
43
|
+
const builder = new RangeSetBuilder<Decoration>();
|
44
44
|
const cursor = state.selection.main.head;
|
45
45
|
|
46
46
|
const tables: Table[] = [];
|
package/src/extensions/modes.ts
CHANGED
@@ -2,26 +2,25 @@
|
|
2
2
|
// Copyright 2024 DXOS.org
|
3
3
|
//
|
4
4
|
|
5
|
-
import { type Extension
|
5
|
+
import { type Extension } from '@codemirror/state';
|
6
6
|
import { keymap } from '@codemirror/view';
|
7
7
|
import { vim } from '@replit/codemirror-vim';
|
8
8
|
import { vscodeKeymap } from '@replit/codemirror-vscode-keymap';
|
9
9
|
|
10
|
-
|
10
|
+
import { singleValueFacet } from '../util';
|
11
11
|
|
12
12
|
export const EditorViewModes = ['preview', 'readonly', 'source'] as const;
|
13
13
|
export type EditorViewMode = (typeof EditorViewModes)[number];
|
14
|
+
|
14
15
|
export const EditorInputModes = ['default', 'vim', 'vscode'] as const;
|
15
16
|
export type EditorInputMode = (typeof EditorInputModes)[number];
|
16
17
|
|
17
18
|
export type EditorInputConfig = {
|
18
|
-
type
|
19
|
+
type?: string;
|
19
20
|
noTabster?: boolean;
|
20
21
|
};
|
21
22
|
|
22
|
-
export const editorInputMode =
|
23
|
-
combine: (modes) => modes[0] ?? {},
|
24
|
-
});
|
23
|
+
export const editorInputMode = singleValueFacet<EditorInputConfig>({});
|
25
24
|
|
26
25
|
export const InputModeExtensions: { [mode: string]: Extension } = {
|
27
26
|
default: [],
|
@@ -39,7 +38,7 @@ export const InputModeExtensions: { [mode: string]: Extension } = {
|
|
39
38
|
key: 'Alt-Escape',
|
40
39
|
run: (view) => {
|
41
40
|
// Focus container for tab navigation.
|
42
|
-
view.
|
41
|
+
view.dom.parentElement?.focus();
|
43
42
|
return true;
|
44
43
|
},
|
45
44
|
},
|
@@ -9,9 +9,12 @@ import { debounce } from '@dxos/async';
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
10
10
|
import { isNotFalsy } from '@dxos/util';
|
11
11
|
|
12
|
-
import {
|
12
|
+
import { singleValueFacet } from '../util';
|
13
13
|
|
14
|
-
|
14
|
+
/**
|
15
|
+
* Currently edited document id as FQ string.
|
16
|
+
*/
|
17
|
+
export const documentId = singleValueFacet<string>();
|
15
18
|
|
16
19
|
export type EditorSelection = {
|
17
20
|
anchor: number;
|
@@ -23,13 +26,23 @@ export type EditorSelectionState = {
|
|
23
26
|
selection?: EditorSelection;
|
24
27
|
};
|
25
28
|
|
26
|
-
export type
|
29
|
+
export type EditorStateStore = {
|
27
30
|
setState: (id: string, state: EditorSelectionState) => void;
|
28
31
|
getState: (id: string) => EditorSelectionState | undefined;
|
29
32
|
};
|
30
33
|
|
31
|
-
const
|
32
|
-
|
34
|
+
const stateRestoreAnnotation = 'dxos.org/cm/state-restore';
|
35
|
+
|
36
|
+
export const createEditorStateTransaction = ({ scrollTo, selection }: EditorSelectionState): TransactionSpec => {
|
37
|
+
return {
|
38
|
+
selection,
|
39
|
+
scrollIntoView: !scrollTo,
|
40
|
+
effects: scrollTo ? EditorView.scrollIntoView(scrollTo, { yMargin: 96 }) : undefined,
|
41
|
+
annotations: Transaction.userEvent.of(stateRestoreAnnotation),
|
42
|
+
};
|
43
|
+
};
|
44
|
+
|
45
|
+
export const createEditorStateStore = (keyPrefix: string): EditorStateStore => ({
|
33
46
|
getState: (id) => {
|
34
47
|
invariant(id);
|
35
48
|
const state = localStorage.getItem(`${keyPrefix}/${id}`);
|
@@ -40,21 +53,12 @@ export const localStorageStateStoreAdapter: EditorStateOptions = {
|
|
40
53
|
invariant(id);
|
41
54
|
localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state));
|
42
55
|
},
|
43
|
-
};
|
44
|
-
|
45
|
-
export const createEditorStateTransaction = ({ scrollTo, selection }: EditorSelectionState): TransactionSpec => {
|
46
|
-
return {
|
47
|
-
selection,
|
48
|
-
scrollIntoView: !scrollTo,
|
49
|
-
effects: scrollTo ? EditorView.scrollIntoView(scrollTo, { yMargin: 96 }) : undefined,
|
50
|
-
annotations: Transaction.userEvent.of(stateRestoreAnnotation),
|
51
|
-
};
|
52
|
-
};
|
56
|
+
});
|
53
57
|
|
54
58
|
/**
|
55
59
|
* Track scrolling and selection state to be restored when switching to document.
|
56
60
|
*/
|
57
|
-
export const
|
61
|
+
export const selectionState = ({ getState, setState }: Partial<EditorStateStore> = {}): Extension => {
|
58
62
|
const setStateDebounced = debounce(setState!, 1_000);
|
59
63
|
|
60
64
|
return [
|
@@ -19,10 +19,11 @@ import {
|
|
19
19
|
import { log } from '@dxos/log';
|
20
20
|
import { getProviderValue, isNotFalsy, type MaybeProvider } from '@dxos/util';
|
21
21
|
|
22
|
-
import {
|
23
|
-
import {
|
22
|
+
import { editorInputMode, type EditorSelection, documentId, createEditorStateTransaction } from '../extensions';
|
23
|
+
import { debugDispatcher } from '../util';
|
24
24
|
|
25
25
|
export type UseTextEditor = {
|
26
|
+
// TODO(burdon): Rename.
|
26
27
|
parentRef: RefObject<HTMLDivElement>;
|
27
28
|
view?: EditorView;
|
28
29
|
focusAttributes: ReturnType<typeof useFocusableGroup> & {
|
@@ -65,8 +66,6 @@ export const useTextEditor = (
|
|
65
66
|
|
66
67
|
// NOTE: Increments by 2 in strict mode.
|
67
68
|
const [instanceId] = useState(() => `text-editor-${++instanceCount}`);
|
68
|
-
// Callback once view is created.
|
69
|
-
const onUpdate = useRef<() => void>();
|
70
69
|
const [view, setView] = useState<EditorView>();
|
71
70
|
const parentRef = useRef<HTMLDivElement>(null);
|
72
71
|
|
@@ -87,44 +86,45 @@ export const useTextEditor = (
|
|
87
86
|
}
|
88
87
|
|
89
88
|
// https://codemirror.net/docs/ref/#state.EditorStateConfig
|
90
|
-
// NOTE: Don't set selection here in case it is invalid (and crashes the state); dispatch below.
|
91
89
|
const state = EditorState.create({
|
92
90
|
doc: initialValue,
|
93
|
-
selection: initialSelection,
|
91
|
+
// selection: initialSelection,
|
94
92
|
extensions: [
|
95
93
|
id && documentId.of(id),
|
96
|
-
|
94
|
+
extensions,
|
95
|
+
// NOTE: This doesn't catch errors in keymap functions.
|
97
96
|
EditorView.exceptionSink.of((err) => {
|
98
97
|
log.catch(err);
|
99
98
|
}),
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
}
|
99
|
+
// TODO(burdon): Factor out debug inspector.
|
100
|
+
// ViewPlugin.fromClass(
|
101
|
+
// class {
|
102
|
+
// constructor(_view: EditorView) {
|
103
|
+
// log('construct', { id });
|
104
|
+
// }
|
105
|
+
//
|
106
|
+
// destroy() {
|
107
|
+
// log('destroy', { id });
|
108
|
+
// }
|
109
|
+
// },
|
110
|
+
// ),
|
106
111
|
].filter(isNotFalsy),
|
107
112
|
});
|
108
113
|
|
109
114
|
// https://codemirror.net/docs/ref/#view.EditorViewConfig
|
110
115
|
view = new EditorView({
|
111
116
|
parent: parentRef.current,
|
112
|
-
selection: initialSelection,
|
113
117
|
state,
|
114
|
-
|
115
|
-
|
116
|
-
dispatchTransactions: (trs, view) => {
|
117
|
-
if (debug) {
|
118
|
-
logChanges(trs);
|
119
|
-
}
|
120
|
-
view.update(trs);
|
121
|
-
},
|
118
|
+
scrollTo: scrollTo ? EditorView.scrollIntoView(scrollTo, { yMargin: 96 }) : undefined, // TODO(burdon): Const.
|
119
|
+
dispatchTransactions: debug ? debugDispatcher : undefined,
|
122
120
|
});
|
123
121
|
|
124
|
-
// Move to end of line after document loaded.
|
125
|
-
if (
|
122
|
+
// Move to end of line after document loaded (unless selection is specified).
|
123
|
+
if (moveToEndOfLine && !initialSelection) {
|
126
124
|
const { to } = view.state.doc.lineAt(0);
|
127
|
-
|
125
|
+
if (to) {
|
126
|
+
view.dispatch({ selection: { anchor: to } });
|
127
|
+
}
|
128
128
|
}
|
129
129
|
|
130
130
|
setView(view);
|
@@ -138,18 +138,16 @@ export const useTextEditor = (
|
|
138
138
|
|
139
139
|
useEffect(() => {
|
140
140
|
if (view) {
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
141
|
+
if (scrollTo || selection) {
|
142
|
+
if (selection && selection.anchor > view.state.doc.length) {
|
143
|
+
log.warn('invalid selection', { length: view.state.doc.length, scrollTo, selection });
|
144
|
+
return;
|
145
|
+
}
|
146
146
|
|
147
|
-
|
148
|
-
if (view.state.facet(editorInputMode).noTabster) {
|
149
|
-
parentRef.current?.removeAttribute('data-tabster');
|
147
|
+
view.dispatch(createEditorStateTransaction({ scrollTo, selection }));
|
150
148
|
}
|
151
149
|
}
|
152
|
-
}, [view,
|
150
|
+
}, [view, scrollTo, selection]);
|
153
151
|
|
154
152
|
useEffect(() => {
|
155
153
|
if (view && autoFocus) {
|
@@ -157,7 +155,10 @@ export const useTextEditor = (
|
|
157
155
|
}
|
158
156
|
}, [autoFocus, view]);
|
159
157
|
|
160
|
-
const focusableGroup = useFocusableGroup({
|
158
|
+
const focusableGroup = useFocusableGroup({
|
159
|
+
tabBehavior: 'limited',
|
160
|
+
ignoreDefaultKeydown: { Escape: view?.state.facet(editorInputMode).noTabster },
|
161
|
+
});
|
161
162
|
|
162
163
|
// Focus editor on Enter (e.g., when tabbing to this component).
|
163
164
|
const handleKeyUp = useCallback<KeyboardEventHandler<HTMLDivElement>>(
|
package/src/index.ts
CHANGED
package/src/styles/markdown.ts
CHANGED
@@ -17,11 +17,9 @@ const headings: Record<HeadingLevel, string> = {
|
|
17
17
|
};
|
18
18
|
|
19
19
|
export const theme = {
|
20
|
-
mark: 'opacity-50',
|
21
20
|
code: 'font-mono !no-underline text-neutral-700 dark:text-neutral-300',
|
22
21
|
codeMark: 'font-mono text-primary-500',
|
23
|
-
|
24
|
-
blockquote: 'pl-1 mr-1 border-is-4 border-orange-500 dark:border-orange-500 dark:text-neutral-500',
|
22
|
+
mark: 'opacity-50',
|
25
23
|
heading: (level: HeadingLevel) => {
|
26
24
|
return mx(headings[level], 'dark:text-primary-400');
|
27
25
|
},
|
package/src/styles/theme.ts
CHANGED
@@ -71,9 +71,11 @@ export const defaultTheme: ThemeStyles = {
|
|
71
71
|
/**
|
72
72
|
* Gutters
|
73
73
|
* NOTE: Gutters should have the same top margin as the content.
|
74
|
+
* NOTE: They can't be transparent since the content needs to scroll below.
|
74
75
|
*/
|
75
76
|
'.cm-gutters': {
|
76
77
|
background: 'var(--surface-bg)',
|
78
|
+
borderRight: 'none',
|
77
79
|
},
|
78
80
|
'.cm-gutter': {},
|
79
81
|
'.cm-gutter.cm-lineNumbers .cm-gutterElement': {
|
@@ -95,7 +97,7 @@ export const defaultTheme: ThemeStyles = {
|
|
95
97
|
paddingInline: 0,
|
96
98
|
},
|
97
99
|
'.cm-activeLine': {
|
98
|
-
background: 'var(--dx-
|
100
|
+
background: 'var(--dx-cmActiveLine)',
|
99
101
|
},
|
100
102
|
|
101
103
|
/**
|
@@ -2,9 +2,17 @@
|
|
2
2
|
// Copyright 2024 DXOS.org
|
3
3
|
//
|
4
4
|
|
5
|
-
import { type EditorState
|
5
|
+
import { type EditorState } from '@codemirror/state';
|
6
6
|
|
7
|
-
import {
|
7
|
+
import { singleValueFacet } from './facet';
|
8
|
+
import { type Range } from '../types';
|
9
|
+
|
10
|
+
/**
|
11
|
+
* Determines if two ranges overlap.
|
12
|
+
* A range is considered to overlap if there is any intersection
|
13
|
+
* between the two ranges, inclusive of their boundaries.
|
14
|
+
*/
|
15
|
+
export const overlap = (a: Range, b: Range): boolean => a.from <= b.to && a.to >= b.from;
|
8
16
|
|
9
17
|
/**
|
10
18
|
* Converts indexes into the text document into stable peer-independent cursors.
|
@@ -27,15 +35,10 @@ const defaultCursorConverter: CursorConverter = {
|
|
27
35
|
};
|
28
36
|
|
29
37
|
export class Cursor {
|
30
|
-
static readonly converter =
|
31
|
-
combine: (providers) => {
|
32
|
-
return providers[0] ?? defaultCursorConverter;
|
33
|
-
},
|
34
|
-
});
|
38
|
+
static readonly converter = singleValueFacet(defaultCursorConverter);
|
35
39
|
|
36
40
|
static readonly getCursorFromRange = (state: EditorState, range: Range) => {
|
37
41
|
const cursorConverter = state.facet(Cursor.converter);
|
38
|
-
|
39
42
|
const from = cursorConverter.toCursor(range.from);
|
40
43
|
const to = cursorConverter.toCursor(range.to, -1);
|
41
44
|
return [from, to].join(':');
|
@@ -2,14 +2,25 @@
|
|
2
2
|
// Copyright 2024 DXOS.org
|
3
3
|
//
|
4
4
|
|
5
|
-
import type
|
5
|
+
import { type Transaction } from '@codemirror/state';
|
6
|
+
import { type EditorView } from '@codemirror/view';
|
6
7
|
|
7
8
|
import { log } from '@dxos/log';
|
8
9
|
|
10
|
+
export const wrapWithCatch = (fn: (...args: any[]) => any) => {
|
11
|
+
return (...args: any[]) => {
|
12
|
+
try {
|
13
|
+
return fn(...args);
|
14
|
+
} catch (err) {
|
15
|
+
log.catch(err);
|
16
|
+
}
|
17
|
+
};
|
18
|
+
};
|
19
|
+
|
9
20
|
/**
|
10
21
|
* CodeMirror callbacks swallow errors so wrap handlers.
|
11
22
|
*/
|
12
|
-
// TODO(burdon):
|
23
|
+
// TODO(burdon): Reconcile with wrapWithCatch.
|
13
24
|
export const callbackWrapper = <T extends Function>(fn: T): T =>
|
14
25
|
((...args: any[]) => {
|
15
26
|
try {
|
@@ -19,6 +30,18 @@ export const callbackWrapper = <T extends Function>(fn: T): T =>
|
|
19
30
|
}
|
20
31
|
}) as unknown as T;
|
21
32
|
|
33
|
+
/**
|
34
|
+
* Log all changes before dispatching them to the view.
|
35
|
+
* https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
36
|
+
*/
|
37
|
+
export const debugDispatcher = (trs: readonly Transaction[], view: EditorView) => {
|
38
|
+
logChanges(trs);
|
39
|
+
view.update(trs);
|
40
|
+
};
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Util to log transactions in update listener.
|
44
|
+
*/
|
22
45
|
export const logChanges = (trs: readonly Transaction[]) => {
|
23
46
|
const changes = trs
|
24
47
|
.flatMap((tr) => {
|
@@ -0,0 +1,13 @@
|
|
1
|
+
//
|
2
|
+
// Copyright 2024 DXOS.org
|
3
|
+
//
|
4
|
+
|
5
|
+
import { Facet } from '@codemirror/state';
|
6
|
+
|
7
|
+
export const singleValueFacet = <I, O = I>(defaultValue?: O) =>
|
8
|
+
Facet.define<I, O>({
|
9
|
+
// Called immediately.
|
10
|
+
combine: (providers) => {
|
11
|
+
return (providers[0] ?? defaultValue) as O;
|
12
|
+
},
|
13
|
+
});
|
@@ -8,6 +8,8 @@ import { createRoot } from 'react-dom/client';
|
|
8
8
|
import { ThemeProvider } from '@dxos/react-ui';
|
9
9
|
import { defaultTx } from '@dxos/react-ui-theme';
|
10
10
|
|
11
|
+
// TODO(burdon): Factor out.
|
12
|
+
|
11
13
|
export type ElementOptions = {
|
12
14
|
className?: string;
|
13
15
|
};
|
@@ -20,10 +22,13 @@ export const createElement = (tag: string, options?: ElementOptions, children?:
|
|
20
22
|
if (children) {
|
21
23
|
el.append(...(Array.isArray(children) ? children : [children]));
|
22
24
|
}
|
25
|
+
|
23
26
|
return el;
|
24
27
|
};
|
25
28
|
|
26
|
-
|
29
|
+
// TODO(burdon): Remove react rendering; use DOM directly.
|
30
|
+
// NOTE: CM seems to remove/detach/overwrite portals that are attached to the DOM it control.s
|
31
|
+
export const renderRoot = <T extends Element>(root: T, node: ReactNode): T => {
|
27
32
|
createRoot(root).render(<ThemeProvider tx={defaultTx}>{node}</ThemeProvider>);
|
28
33
|
return root;
|
29
34
|
};
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"automerge.spec.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/automerge/automerge.spec.tsx"],"names":[],"mappings":""}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../../../src/extensions/cursor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC;IAC/D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACpC;AAOD,qBAAa,MAAM;IACjB,MAAM,CAAC,QAAQ,CAAC,SAAS,0CAItB;IAEH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,UAAW,WAAW,SAAS,KAAK,YAMpE;IAEF,MAAM,CAAC,QAAQ,CAAC,kBAAkB,UAAW,WAAW,UAAU,MAAM;;;kBAOtE;CACH"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"doc.d.ts","sourceRoot":"","sources":["../../../../src/extensions/doc.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI1C;;GAEG;AACH,eAAO,MAAM,UAAU,uBAKrB,CAAC"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../src/extensions/state.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAe,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAWtF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC5D,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,oBAAoB,GAAG,SAAS,CAAC;CAC5D,CAAC;AAGF,eAAO,MAAM,6BAA6B,EAAE,kBAW3C,CAAC;AAEF,eAAO,MAAM,4BAA4B,4BAA6B,oBAAoB,KAAG,eAO5F,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,KAAK,4BAA4B,OAAO,CAAC,kBAAkB,CAAC,KAAQ,SAuChF,CAAC"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/extensions/types.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAIF,MAAM,MAAM,OAAO,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/util/dom.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,WAAW,SAAU,IAAI,QAAQ,OAAO;;;;;CAGpD,CAAC;AAIF,eAAO,MAAM,SAAS,SAAU,IAAI,QAAQ,MAAM,uBAKjD,CAAC;AAEF,eAAO,MAAM,cAAc,QAAS,IAAI,gBAQvC,CAAC"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/util/error.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,aAAa,OAAQ,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,eACtC,GAAG,EAAE,QAOvB,CAAC"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/util/index.ts"],"names":[],"mappings":"AAIA,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
@@ -1,8 +0,0 @@
|
|
1
|
-
import { type Range } from '../types';
|
2
|
-
/**
|
3
|
-
* Determines if two ranges overlap.
|
4
|
-
* A range is considered to overlap if there is any intersection
|
5
|
-
* between the two ranges, inclusive of their boundaries.
|
6
|
-
*/
|
7
|
-
export declare const overlap: (a: Range, b: Range) => boolean;
|
8
|
-
//# sourceMappingURL=overlap.d.ts.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"overlap.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/util/overlap.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,OAAO,MAAO,KAAK,KAAK,KAAK,KAAG,OAA2C,CAAC"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/util/react.tsx"],"names":[],"mappings":"AAIA,OAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAM9C,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,aAAa,QAAS,MAAM,YAAY,cAAc,aAAa,SAAS,KAAG,WAS3F,CAAC;AAEF,eAAO,MAAM,UAAU,SAAU,WAAW,QAAQ,SAAS,KAAG,WAG/D,CAAC"}
|
package/dist/types/src/util.d.ts
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
import type { Transaction } from '@codemirror/state';
|
2
|
-
/**
|
3
|
-
* CodeMirror callbacks swallow errors so wrap handlers.
|
4
|
-
*/
|
5
|
-
export declare const callbackWrapper: <T extends Function>(fn: T) => T;
|
6
|
-
export declare const logChanges: (trs: readonly Transaction[]) => void;
|
7
|
-
//# sourceMappingURL=util.d.ts.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/util.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD;;GAEG;AAEH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,QAAQ,MAAM,CAAC,KAAG,CAOxC,CAAC;AAErB,eAAO,MAAM,UAAU,QAAS,SAAS,WAAW,EAAE,SAmBrD,CAAC"}
|
package/src/extensions/doc.ts
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
//
|
2
|
-
// Copyright 2024 DXOS.org
|
3
|
-
//
|
4
|
-
|
5
|
-
import { Facet } from '@codemirror/state';
|
6
|
-
|
7
|
-
import { invariant } from '@dxos/invariant';
|
8
|
-
|
9
|
-
/**
|
10
|
-
* Currently edited document id as FQ string.
|
11
|
-
*/
|
12
|
-
export const documentId = Facet.define<string, string>({
|
13
|
-
combine: (providers) => {
|
14
|
-
invariant(providers.length <= 1);
|
15
|
-
return providers[0];
|
16
|
-
},
|
17
|
-
});
|
@@ -1,15 +0,0 @@
|
|
1
|
-
//
|
2
|
-
// Copyright 2024 DXOS.org
|
3
|
-
//
|
4
|
-
|
5
|
-
import { log } from '@dxos/log';
|
6
|
-
|
7
|
-
export const wrapWithCatch = (fn: (...args: any[]) => any) => {
|
8
|
-
return (...args: any[]) => {
|
9
|
-
try {
|
10
|
-
return fn(...args);
|
11
|
-
} catch (err) {
|
12
|
-
log.catch(err);
|
13
|
-
}
|
14
|
-
};
|
15
|
-
};
|
@@ -1,12 +0,0 @@
|
|
1
|
-
//
|
2
|
-
// Copyright 2024 DXOS.org
|
3
|
-
//
|
4
|
-
|
5
|
-
import { type Range } from '../types';
|
6
|
-
|
7
|
-
/**
|
8
|
-
* Determines if two ranges overlap.
|
9
|
-
* A range is considered to overlap if there is any intersection
|
10
|
-
* between the two ranges, inclusive of their boundaries.
|
11
|
-
*/
|
12
|
-
export const overlap = (a: Range, b: Range): boolean => a.from <= b.to && a.to >= b.from;
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|