@dxos/react-ui-editor 0.8.3 → 0.8.4-main.3a94e84
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/chunk-22UMM3QJ.mjs +22 -0
- package/dist/lib/browser/chunk-22UMM3QJ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +570 -530
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/browser/types/index.mjs +13 -0
- package/dist/lib/browser/types/index.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-YXYQPV6R.mjs +24 -0
- package/dist/lib/node-esm/chunk-YXYQPV6R.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +570 -531
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +1 -1
- package/dist/lib/node-esm/types/index.mjs +14 -0
- package/dist/lib/node-esm/types/index.mjs.map +7 -0
- package/dist/types/src/components/Editor/Editor.d.ts +19 -0
- package/dist/types/src/components/Editor/Editor.d.ts.map +1 -0
- package/dist/types/src/components/Editor/index.d.ts +2 -0
- package/dist/types/src/components/Editor/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/util.d.ts +4 -3
- package/dist/types/src/components/EditorToolbar/util.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts +1 -1
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
- package/dist/types/src/components/Popover/RefDropdownMenu.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +28 -28
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/blast.d.ts.map +1 -1
- package/dist/types/src/extensions/command/index.d.ts +1 -1
- package/dist/types/src/extensions/command/index.d.ts.map +1 -1
- package/dist/types/src/extensions/command/typeahead.d.ts +7 -2
- package/dist/types/src/extensions/command/typeahead.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts +19 -0
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/modes.d.ts +0 -7
- package/dist/types/src/extensions/modes.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/stories/CommandMenu.stories.d.ts +1 -1
- package/dist/types/src/stories/CommandMenu.stories.d.ts.map +1 -1
- package/dist/types/src/stories/EditorToolbar.stories.d.ts +1 -1
- package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -1
- package/dist/types/src/stories/components/EditorStory.d.ts +2 -2
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +28 -29
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +2 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/src/types/types.d.ts +21 -0
- package/dist/types/src/types/types.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +44 -41
- package/src/components/Editor/Editor.tsx +39 -0
- package/src/components/Editor/index.ts +5 -0
- package/src/components/EditorToolbar/blocks.ts +1 -1
- package/src/components/EditorToolbar/util.ts +5 -4
- package/src/components/EditorToolbar/view-mode.ts +1 -1
- package/src/components/Popover/RefDropdownMenu.tsx +9 -3
- package/src/components/index.ts +1 -0
- package/src/extensions/automerge/automerge.stories.tsx +4 -2
- package/src/extensions/blast.ts +3 -16
- package/src/extensions/command/index.ts +1 -1
- package/src/extensions/command/typeahead.ts +26 -13
- package/src/extensions/factories.ts +24 -5
- package/src/extensions/markdown/formatting.test.ts +1 -1
- package/src/extensions/markdown/formatting.ts +14 -12
- package/src/extensions/modes.ts +0 -9
- package/src/index.ts +1 -1
- package/src/stories/CommandMenu.stories.tsx +2 -2
- package/src/stories/EditorToolbar.stories.tsx +3 -4
- package/src/stories/Preview.stories.tsx +4 -4
- package/src/stories/TextEditor.stories.tsx +1 -1
- package/src/styles/theme.ts +4 -5
- package/src/translations.ts +4 -2
- package/src/types/index.ts +5 -0
- package/src/types/types.ts +32 -0
- package/dist/lib/node/index.cjs +0 -7754
- package/dist/lib/node/index.cjs.map +0 -7
- package/dist/lib/node/meta.json +0 -1
- package/dist/lib/node/testing/index.cjs +0 -29
- package/dist/lib/node/testing/index.cjs.map +0 -7
- package/dist/types/src/types.d.ts +0 -14
- package/dist/types/src/types.d.ts.map +0 -1
- package/src/types.ts +0 -23
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@dxos/react-ui-editor",
|
3
|
-
"version": "0.8.
|
3
|
+
"version": "0.8.4-main.3a94e84",
|
4
4
|
"description": "Document editing experience within a DXOS shell.",
|
5
5
|
"homepage": "https://dxos.org",
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
@@ -14,6 +14,11 @@
|
|
14
14
|
"browser": "./dist/lib/browser/index.mjs",
|
15
15
|
"node": "./dist/lib/node-esm/index.mjs"
|
16
16
|
},
|
17
|
+
"./types": {
|
18
|
+
"types": "./dist/types/src/types/index.d.ts",
|
19
|
+
"browser": "./dist/lib/browser/types/index.mjs",
|
20
|
+
"node": "./dist/lib/node-esm/types/index.mjs"
|
21
|
+
},
|
17
22
|
"./testing": {
|
18
23
|
"types": "./dist/types/src/testing/index.d.ts",
|
19
24
|
"browser": "./dist/lib/browser/testing/index.mjs",
|
@@ -29,7 +34,7 @@
|
|
29
34
|
"src"
|
30
35
|
],
|
31
36
|
"dependencies": {
|
32
|
-
"@automerge/automerge": "3.0.0
|
37
|
+
"@automerge/automerge": "3.0.0",
|
33
38
|
"@codemirror/autocomplete": "^6.18.1",
|
34
39
|
"@codemirror/commands": "^6.6.2",
|
35
40
|
"@codemirror/lang-javascript": "^6.2.2",
|
@@ -59,29 +64,28 @@
|
|
59
64
|
"lodash.merge": "^4.6.2",
|
60
65
|
"lodash.sortby": "^4.7.0",
|
61
66
|
"style-mod": "^4.1.0",
|
62
|
-
"@dxos/
|
63
|
-
"@dxos/
|
64
|
-
"@dxos/
|
65
|
-
"@dxos/debug": "0.8.
|
66
|
-
"@dxos/
|
67
|
-
"@dxos/
|
68
|
-
"@dxos/lit-ui": "0.8.
|
69
|
-
"@dxos/
|
70
|
-
"@dxos/
|
71
|
-
"@dxos/
|
72
|
-
"@dxos/
|
73
|
-
"@dxos/react-hooks": "0.8.
|
74
|
-
"@dxos/react-ui-
|
75
|
-
"@dxos/react-ui-
|
76
|
-
"@dxos/util": "0.8.
|
67
|
+
"@dxos/async": "0.8.4-main.3a94e84",
|
68
|
+
"@dxos/context": "0.8.4-main.3a94e84",
|
69
|
+
"@dxos/app-graph": "0.8.4-main.3a94e84",
|
70
|
+
"@dxos/debug": "0.8.4-main.3a94e84",
|
71
|
+
"@dxos/invariant": "0.8.4-main.3a94e84",
|
72
|
+
"@dxos/live-object": "0.8.4-main.3a94e84",
|
73
|
+
"@dxos/lit-ui": "0.8.4-main.3a94e84",
|
74
|
+
"@dxos/display-name": "0.8.4-main.3a94e84",
|
75
|
+
"@dxos/log": "0.8.4-main.3a94e84",
|
76
|
+
"@dxos/protocols": "0.8.4-main.3a94e84",
|
77
|
+
"@dxos/echo-schema": "0.8.4-main.3a94e84",
|
78
|
+
"@dxos/react-hooks": "0.8.4-main.3a94e84",
|
79
|
+
"@dxos/react-ui-stack": "0.8.4-main.3a94e84",
|
80
|
+
"@dxos/react-ui-menu": "0.8.4-main.3a94e84",
|
81
|
+
"@dxos/util": "0.8.4-main.3a94e84"
|
77
82
|
},
|
78
83
|
"devDependencies": {
|
79
|
-
"@automerge/automerge": "3.0.0
|
80
|
-
"@automerge/automerge-repo": "2.0.
|
81
|
-
"@automerge/automerge-repo-network-broadcastchannel": "2.0.
|
82
|
-
"@effect-rx/rx-react": "
|
83
|
-
"@effect/platform": "0.
|
84
|
-
"@phosphor-icons/react": "^2.1.5",
|
84
|
+
"@automerge/automerge": "3.0.0",
|
85
|
+
"@automerge/automerge-repo": "2.0.8",
|
86
|
+
"@automerge/automerge-repo-network-broadcastchannel": "2.0.8",
|
87
|
+
"@effect-rx/rx-react": "0.38.0",
|
88
|
+
"@effect/platform": "0.89.0",
|
85
89
|
"@types/chai": "^4.2.15",
|
86
90
|
"@types/chai-dom": "^1.11.0",
|
87
91
|
"@types/lodash.defaultsdeep": "^4.6.6",
|
@@ -92,7 +96,7 @@
|
|
92
96
|
"@types/react-test-renderer": "^17.0.2",
|
93
97
|
"chai": "^4.4.1",
|
94
98
|
"chai-dom": "^1.11.0",
|
95
|
-
"effect": "3.
|
99
|
+
"effect": "3.17.0",
|
96
100
|
"happy-dom": "^13.3.1",
|
97
101
|
"jsdom": "^24.0.0",
|
98
102
|
"mocha": "^10.6.0",
|
@@ -102,29 +106,28 @@
|
|
102
106
|
"vite": "5.4.7",
|
103
107
|
"vite-plugin-top-level-await": "^1.4.1",
|
104
108
|
"vite-plugin-wasm": "^3.3.0",
|
105
|
-
"@dxos/config": "0.8.
|
106
|
-
"@dxos/echo": "0.8.
|
107
|
-
"@dxos/echo-signals": "0.8.
|
108
|
-
"@dxos/keyboard": "0.8.
|
109
|
-
"@dxos/random": "0.8.
|
110
|
-
"@dxos/react-
|
111
|
-
"@dxos/react-ui
|
112
|
-
"@dxos/react-ui-attention": "0.8.
|
113
|
-
"@dxos/react-
|
114
|
-
"@dxos/
|
115
|
-
"@dxos/
|
116
|
-
"@dxos/
|
109
|
+
"@dxos/config": "0.8.4-main.3a94e84",
|
110
|
+
"@dxos/echo": "0.8.4-main.3a94e84",
|
111
|
+
"@dxos/echo-signals": "0.8.4-main.3a94e84",
|
112
|
+
"@dxos/keyboard": "0.8.4-main.3a94e84",
|
113
|
+
"@dxos/random": "0.8.4-main.3a94e84",
|
114
|
+
"@dxos/react-client": "0.8.4-main.3a94e84",
|
115
|
+
"@dxos/react-ui": "0.8.4-main.3a94e84",
|
116
|
+
"@dxos/react-ui-attention": "0.8.4-main.3a94e84",
|
117
|
+
"@dxos/react-ui-syntax-highlighter": "0.8.4-main.3a94e84",
|
118
|
+
"@dxos/schema": "0.8.4-main.3a94e84",
|
119
|
+
"@dxos/react-ui-theme": "0.8.4-main.3a94e84",
|
120
|
+
"@dxos/storybook-utils": "0.8.4-main.3a94e84"
|
117
121
|
},
|
118
122
|
"peerDependencies": {
|
119
123
|
"@effect-rx/rx-react": "^0.34.1",
|
120
|
-
"@effect/platform": "0.80.12",
|
121
|
-
"@phosphor-icons/react": "^2.1.5",
|
124
|
+
"@effect/platform": "^0.80.12",
|
122
125
|
"effect": "^3.13.3",
|
123
126
|
"react": "~18.2.0",
|
124
127
|
"react-dom": "~18.2.0",
|
125
|
-
"@dxos/react-client": "0.8.
|
126
|
-
"@dxos/react-ui": "0.8.
|
127
|
-
"@dxos/react-ui
|
128
|
+
"@dxos/react-client": "0.8.4-main.3a94e84",
|
129
|
+
"@dxos/react-ui-theme": "0.8.4-main.3a94e84",
|
130
|
+
"@dxos/react-ui": "0.8.4-main.3a94e84"
|
128
131
|
},
|
129
132
|
"publishConfig": {
|
130
133
|
"access": "public"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
//
|
2
|
+
// Copyright 2025 DXOS.org
|
3
|
+
//
|
4
|
+
|
5
|
+
import { type EditorView } from '@codemirror/view';
|
6
|
+
import React, { forwardRef, useImperativeHandle } from 'react';
|
7
|
+
|
8
|
+
import { type ThemedClassName, useThemeContext } from '@dxos/react-ui';
|
9
|
+
import { mx } from '@dxos/react-ui-theme';
|
10
|
+
import { type DataType } from '@dxos/schema';
|
11
|
+
|
12
|
+
import { useTextEditor, type UseTextEditorProps } from '../../hooks';
|
13
|
+
|
14
|
+
export type EditorProps = ThemedClassName<
|
15
|
+
{
|
16
|
+
id: string;
|
17
|
+
text: DataType.Text;
|
18
|
+
} & Omit<UseTextEditorProps, 'id'>
|
19
|
+
>;
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Minimal text editor.
|
23
|
+
*/
|
24
|
+
export const Editor = forwardRef<EditorView | undefined, EditorProps>(
|
25
|
+
({ classNames, id, text, ...props }, forwardedRef) => {
|
26
|
+
const { themeMode } = useThemeContext();
|
27
|
+
const { parentRef, focusAttributes, view } = useTextEditor(
|
28
|
+
() => ({
|
29
|
+
id,
|
30
|
+
initialValue: text.content,
|
31
|
+
...props,
|
32
|
+
}),
|
33
|
+
[id, text, themeMode],
|
34
|
+
);
|
35
|
+
|
36
|
+
useImperativeHandle(forwardedRef, () => view, [view]);
|
37
|
+
return <div ref={parentRef} className={mx(classNames)} {...focusAttributes} />;
|
38
|
+
},
|
39
|
+
);
|
@@ -49,7 +49,7 @@ const createBlockActions = (value: string, getView: () => EditorView, blankLine?
|
|
49
49
|
});
|
50
50
|
|
51
51
|
export const createBlocks = (state: EditorToolbarState, getView: () => EditorView) => {
|
52
|
-
const value = state?.blockQuote ? 'blockquote' : state.blockType ?? '';
|
52
|
+
const value = state?.blockQuote ? 'blockquote' : (state.blockType ?? '');
|
53
53
|
const blockGroupAction = createBlockGroupAction(value);
|
54
54
|
const blockActions = createBlockActions(value, getView, state.blankLine);
|
55
55
|
return {
|
@@ -10,17 +10,18 @@ import { type Action } from '@dxos/app-graph';
|
|
10
10
|
import { live, type Live } from '@dxos/live-object';
|
11
11
|
import { type ThemedClassName } from '@dxos/react-ui';
|
12
12
|
import {
|
13
|
-
type
|
13
|
+
type ActionGraphProps,
|
14
|
+
type MenuActionProperties,
|
14
15
|
type MenuItemGroup,
|
16
|
+
type MenuSeparator,
|
15
17
|
type ToolbarMenuActionGroupProperties,
|
16
18
|
createMenuAction,
|
17
19
|
createMenuItemGroup,
|
18
|
-
type ActionGraphProps,
|
19
|
-
type MenuActionProperties,
|
20
20
|
} from '@dxos/react-ui-menu';
|
21
21
|
|
22
|
-
import type { EditorAction,
|
22
|
+
import type { EditorAction, Formatting } from '../../extensions';
|
23
23
|
import { translationKey } from '../../translations';
|
24
|
+
import { type EditorViewMode } from '../../types';
|
24
25
|
|
25
26
|
export type EditorToolbarState = Formatting & Partial<{ viewMode: EditorViewMode }>;
|
26
27
|
|
@@ -6,8 +6,8 @@ import { type NodeArg } from '@dxos/app-graph';
|
|
6
6
|
import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
|
7
7
|
|
8
8
|
import { createEditorAction, createEditorActionGroup, type EditorToolbarState } from './util';
|
9
|
-
import { type EditorViewMode } from '../../extensions';
|
10
9
|
import { translationKey } from '../../translations';
|
10
|
+
import { type EditorViewMode } from '../../types';
|
11
11
|
|
12
12
|
const createViewModeGroupAction = (value: string) =>
|
13
13
|
createEditorActionGroup(
|
@@ -11,17 +11,23 @@ import { DropdownMenu } from '@dxos/react-ui';
|
|
11
11
|
|
12
12
|
import { type PreviewLinkRef, type PreviewLinkTarget, type PreviewLookup } from '../../extensions';
|
13
13
|
|
14
|
-
// TODO(burdon): Reconcile with RefPopover?
|
14
|
+
// TODO(burdon): Reconcile this file with RefPopover?
|
15
15
|
|
16
16
|
const customEventOptions = { capture: true, passive: false };
|
17
17
|
|
18
18
|
// Create a context for the dxn value.
|
19
|
-
type RefDropdownMenuValue = Partial<{
|
19
|
+
type RefDropdownMenuValue = Partial<{
|
20
|
+
link: PreviewLinkRef;
|
21
|
+
target: PreviewLinkTarget;
|
22
|
+
pending: boolean;
|
23
|
+
}>;
|
20
24
|
|
21
25
|
const REF_DROPDOWN_MENU = 'RefDropdownMenu';
|
22
26
|
const [RefDropdownMenuContextProvider, useRefDropdownMenu] = createContext<RefDropdownMenuValue>(REF_DROPDOWN_MENU, {});
|
23
27
|
|
24
|
-
type RefDropdownMenuProviderProps = PropsWithChildren<{
|
28
|
+
type RefDropdownMenuProviderProps = PropsWithChildren<{
|
29
|
+
onLookup?: PreviewLookup;
|
30
|
+
}>;
|
25
31
|
|
26
32
|
const RefDropdownMenuProvider = ({ children, onLookup }: RefDropdownMenuProviderProps) => {
|
27
33
|
const trigger = useRef<DxRefTag | null>(null);
|
package/src/components/index.ts
CHANGED
@@ -19,7 +19,7 @@ import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
19
19
|
|
20
20
|
import { editorSlots } from '../../defaults';
|
21
21
|
import { useTextEditor } from '../../hooks';
|
22
|
-
import translations from '../../translations';
|
22
|
+
import { translations } from '../../translations';
|
23
23
|
import { createBasicExtensions, createDataExtensions, createThemeExtensions } from '../factories';
|
24
24
|
|
25
25
|
const initialContent = 'Hello world!';
|
@@ -93,7 +93,9 @@ export default {
|
|
93
93
|
component: Editor,
|
94
94
|
decorators: [withTheme, withLayout({ fullscreen: true })],
|
95
95
|
render: () => <Story />,
|
96
|
-
parameters: {
|
96
|
+
parameters: {
|
97
|
+
translations,
|
98
|
+
},
|
97
99
|
};
|
98
100
|
|
99
101
|
const EchoStory = ({ spaceKey }: ClientRepeatedComponentProps) => {
|
package/src/extensions/blast.ts
CHANGED
@@ -9,6 +9,7 @@ import { type Extension } from '@codemirror/state';
|
|
9
9
|
import { EditorView, keymap } from '@codemirror/view';
|
10
10
|
import defaultsDeep from 'lodash.defaultsdeep';
|
11
11
|
|
12
|
+
import { throttle } from '@dxos/async';
|
12
13
|
import { invariant } from '@dxos/invariant';
|
13
14
|
|
14
15
|
export type BlastOptions = {
|
@@ -214,12 +215,12 @@ class Blaster {
|
|
214
215
|
requestAnimationFrame(this.loop.bind(this));
|
215
216
|
}
|
216
217
|
|
217
|
-
shake = throttle
|
218
|
+
shake = throttle(({ time }: { time: number }) => {
|
218
219
|
this._shakeTime = this._shakeTimeMax || time;
|
219
220
|
this._shakeTimeMax = time;
|
220
221
|
}, 100);
|
221
222
|
|
222
|
-
spawn = throttle
|
223
|
+
spawn = throttle(({ element, point }: { element: Element; point: { x: number; y: number } }) => {
|
223
224
|
const color = getRGBComponents(element, this._options.color);
|
224
225
|
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
225
226
|
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
@@ -336,20 +337,6 @@ class Effect2 extends Effect {
|
|
336
337
|
// Utils
|
337
338
|
//
|
338
339
|
|
339
|
-
function throttle<T>(callback: (arg: T) => void, limit: number): (arg: T) => void {
|
340
|
-
let wait = false;
|
341
|
-
return function (...args: any[]) {
|
342
|
-
if (!wait) {
|
343
|
-
// @ts-ignore
|
344
|
-
callback.apply(this, args);
|
345
|
-
wait = true;
|
346
|
-
setTimeout(() => {
|
347
|
-
wait = false;
|
348
|
-
}, limit);
|
349
|
-
}
|
350
|
-
};
|
351
|
-
}
|
352
|
-
|
353
340
|
const getRGBComponents = (node: Element, color: BlastOptions['color']): Particle['color'] => {
|
354
341
|
if (typeof color === 'function') {
|
355
342
|
return color();
|
@@ -87,30 +87,43 @@ export const typeahead = ({ onComplete }: TypeaheadOptions = {}): Extension => {
|
|
87
87
|
];
|
88
88
|
};
|
89
89
|
|
90
|
+
type CompletionOptions = {
|
91
|
+
default?: string;
|
92
|
+
minLength?: number;
|
93
|
+
};
|
94
|
+
|
90
95
|
/**
|
91
96
|
* Util to match current line to a static list of completions.
|
92
97
|
*/
|
93
98
|
export const staticCompletion =
|
94
|
-
(completions: string[],
|
99
|
+
(completions: string[], options: CompletionOptions = {}) =>
|
95
100
|
({ line }: TypeaheadContext) => {
|
96
|
-
if (line.length === 0 &&
|
97
|
-
return
|
101
|
+
if (line.length === 0 && options.default) {
|
102
|
+
return options.default;
|
98
103
|
}
|
99
104
|
|
100
|
-
const
|
101
|
-
if (
|
102
|
-
const
|
103
|
-
|
104
|
-
const
|
105
|
-
|
106
|
-
|
105
|
+
const parts = line.split(/\s+/).filter(Boolean);
|
106
|
+
if (parts.length) {
|
107
|
+
const str = parts.at(-1)!;
|
108
|
+
if (str.length >= (options.minLength ?? 0)) {
|
109
|
+
for (const completion of completions) {
|
110
|
+
const match = matchCompletion(completion, str);
|
111
|
+
if (match) {
|
112
|
+
return match;
|
113
|
+
}
|
107
114
|
}
|
108
115
|
}
|
109
116
|
}
|
110
117
|
};
|
111
118
|
|
112
|
-
export const matchCompletion = (completion: string,
|
113
|
-
if (
|
114
|
-
|
119
|
+
export const matchCompletion = (completion: string, str: string, minLength = 0): string | undefined => {
|
120
|
+
if (
|
121
|
+
str.length >= minLength &&
|
122
|
+
completion.length > str.length &&
|
123
|
+
completion.startsWith(str)
|
124
|
+
// TODO(burdon): If case insensitive, need to replace existing chars.
|
125
|
+
// completion.toLowerCase().startsWith(str.toLowerCase())
|
126
|
+
) {
|
127
|
+
return completion.slice(str.length);
|
115
128
|
}
|
116
129
|
};
|
@@ -83,7 +83,7 @@ const defaultBasicOptions: BasicExtensionsOptions = {
|
|
83
83
|
keymap: 'standard',
|
84
84
|
lineWrapping: true,
|
85
85
|
search: true,
|
86
|
-
};
|
86
|
+
} as const;
|
87
87
|
|
88
88
|
const keymaps: { [key: string]: readonly KeyBinding[] } = {
|
89
89
|
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
@@ -93,7 +93,7 @@ const keymaps: { [key: string]: readonly KeyBinding[] } = {
|
|
93
93
|
};
|
94
94
|
|
95
95
|
export const createBasicExtensions = (_props?: BasicExtensionsOptions): Extension => {
|
96
|
-
const props
|
96
|
+
const props = defaultsDeep({}, _props, defaultBasicOptions);
|
97
97
|
return [
|
98
98
|
// NOTE: Doesn't catch errors in keymap functions.
|
99
99
|
EditorView.exceptionSink.of((err) => {
|
@@ -157,17 +157,28 @@ export type ThemeExtensionsOptions = {
|
|
157
157
|
scroll?: {
|
158
158
|
className?: string;
|
159
159
|
};
|
160
|
+
scroller?: {
|
161
|
+
className?: string;
|
162
|
+
};
|
160
163
|
content?: {
|
161
164
|
className?: string;
|
162
165
|
};
|
163
166
|
};
|
164
167
|
};
|
165
168
|
|
166
|
-
const
|
169
|
+
export const grow: ThemeExtensionsOptions['slots'] = {
|
167
170
|
editor: {
|
168
|
-
className: '
|
171
|
+
className: 'is-full bs-full',
|
169
172
|
},
|
170
|
-
};
|
173
|
+
} as const;
|
174
|
+
|
175
|
+
export const fullWidth: ThemeExtensionsOptions['slots'] = {
|
176
|
+
editor: {
|
177
|
+
className: 'is-full',
|
178
|
+
},
|
179
|
+
} as const;
|
180
|
+
|
181
|
+
export const defaultThemeSlots = grow;
|
171
182
|
|
172
183
|
/**
|
173
184
|
* https://codemirror.net/examples/styling
|
@@ -195,6 +206,14 @@ export const createThemeExtensions = ({
|
|
195
206
|
}
|
196
207
|
},
|
197
208
|
),
|
209
|
+
slots.scroller?.className &&
|
210
|
+
ViewPlugin.fromClass(
|
211
|
+
class {
|
212
|
+
constructor(view: EditorView) {
|
213
|
+
view.dom.querySelector('.cm-scroller')?.classList.add(...slots.scroller.className.split(' '));
|
214
|
+
}
|
215
|
+
},
|
216
|
+
),
|
198
217
|
].filter(isNotFalsy);
|
199
218
|
};
|
200
219
|
|
@@ -182,7 +182,7 @@ describe('removeStyle', () => {
|
|
182
182
|
|
183
183
|
testCommand('can remove code style', 'a `{variable}`', code, 'a {variable}');
|
184
184
|
|
185
|
-
// TODO(dmaretskyi): Flaky on CI
|
185
|
+
// TODO(dmaretskyi): Flaky on CI.
|
186
186
|
// testCommand(
|
187
187
|
// 'can remove emphasis across multiple blocks',
|
188
188
|
// '{*one*\n\n# *two*\n\n> 1. *three} four*\n',
|
@@ -13,10 +13,11 @@ import {
|
|
13
13
|
type StateCommand,
|
14
14
|
type Text,
|
15
15
|
} from '@codemirror/state';
|
16
|
-
import { EditorView, keymap } from '@codemirror/view';
|
16
|
+
import { EditorView, keymap, type ViewUpdate } from '@codemirror/view';
|
17
17
|
import { type SyntaxNodeRef, type SyntaxNode } from '@lezer/common';
|
18
|
-
import { useMemo } from 'react';
|
18
|
+
import { useCallback, useMemo } from 'react';
|
19
19
|
|
20
|
+
import { debounceAndThrottle } from '@dxos/async';
|
20
21
|
import { type Live } from '@dxos/live-object';
|
21
22
|
|
22
23
|
import { type EditorToolbarState } from '../../components';
|
@@ -1251,15 +1252,16 @@ export const getFormatting = (state: EditorState): Formatting => {
|
|
1251
1252
|
* Hook provides an extension to compute the current formatting state.
|
1252
1253
|
*/
|
1253
1254
|
export const useFormattingState = (state: Live<EditorToolbarState>): Extension => {
|
1254
|
-
|
1255
|
-
() =>
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
[],
|
1255
|
+
const handleUpdate = useCallback(
|
1256
|
+
debounceAndThrottle((update: ViewUpdate) => {
|
1257
|
+
if (update.docChanged || update.selectionSet) {
|
1258
|
+
Object.entries(getFormatting(update.state)).forEach(([key, active]) => {
|
1259
|
+
state[key as keyof Formatting] = active as any;
|
1260
|
+
});
|
1261
|
+
}
|
1262
|
+
}, 100),
|
1263
|
+
[state],
|
1264
1264
|
);
|
1265
|
+
|
1266
|
+
return useMemo(() => EditorView.updateListener.of(handleUpdate), [handleUpdate]);
|
1265
1267
|
};
|
package/src/extensions/modes.ts
CHANGED
@@ -6,18 +6,9 @@ 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
|
-
import { Schema } from 'effect';
|
10
9
|
|
11
10
|
import { singleValueFacet } from '../util';
|
12
11
|
|
13
|
-
export const EditorViewModes = ['preview', 'readonly', 'source'] as const;
|
14
|
-
export const EditorViewMode = Schema.Union(...EditorViewModes.map((mode) => Schema.Literal(mode)));
|
15
|
-
export type EditorViewMode = Schema.Schema.Type<typeof EditorViewMode>;
|
16
|
-
|
17
|
-
export const EditorInputModes = ['default', 'vim', 'vscode'] as const;
|
18
|
-
export const EditorInputMode = Schema.Union(...EditorInputModes.map((mode) => Schema.Literal(mode)));
|
19
|
-
export type EditorInputMode = Schema.Schema.Type<typeof EditorInputMode>;
|
20
|
-
|
21
12
|
export type EditorInputConfig = {
|
22
13
|
type?: string;
|
23
14
|
noTabster?: boolean;
|
package/src/index.ts
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
import '@dxos-theme';
|
6
6
|
|
7
7
|
import { type EditorView } from '@codemirror/view';
|
8
|
-
import { type StoryObj } from '@storybook/react';
|
8
|
+
import { type StoryObj } from '@storybook/react-vite';
|
9
9
|
import React, { useCallback, useRef } from 'react';
|
10
10
|
|
11
11
|
import { Obj, Query } from '@dxos/echo';
|
@@ -113,7 +113,7 @@ export const Link: Story = {
|
|
113
113
|
return [];
|
114
114
|
}
|
115
115
|
|
116
|
-
const name = query?.startsWith('@') ? query.slice(1).toLowerCase() : query?.toLowerCase() ?? '';
|
116
|
+
const name = query?.startsWith('@') ? query.slice(1).toLowerCase() : (query?.toLowerCase() ?? '');
|
117
117
|
const result = await space?.db.query(Query.type(Testing.Contact)).run();
|
118
118
|
const items = result.objects
|
119
119
|
.filter((object) => object.name.toLowerCase().includes(name))
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
import '@dxos-theme';
|
6
6
|
|
7
|
-
import { type StoryObj } from '@storybook/react';
|
7
|
+
import { type StoryObj } from '@storybook/react-vite';
|
8
8
|
import React, { useCallback, useState } from 'react';
|
9
9
|
|
10
10
|
import { invariant } from '@dxos/invariant';
|
@@ -15,8 +15,6 @@ import { type Meta, withLayout, withTheme } from '@dxos/storybook-utils';
|
|
15
15
|
import { EditorToolbar, useEditorToolbarState } from '../components';
|
16
16
|
import { editorWidth } from '../defaults';
|
17
17
|
import {
|
18
|
-
type EditorInputMode,
|
19
|
-
type EditorViewMode,
|
20
18
|
InputModeExtensions,
|
21
19
|
createMarkdownExtensions,
|
22
20
|
createBasicExtensions,
|
@@ -26,7 +24,8 @@ import {
|
|
26
24
|
useFormattingState,
|
27
25
|
} from '../extensions';
|
28
26
|
import { useTextEditor, type UseTextEditorProps } from '../hooks';
|
29
|
-
import translations from '../translations';
|
27
|
+
import { translations } from '../translations';
|
28
|
+
import { type EditorInputMode, type EditorViewMode } from '../types';
|
30
29
|
|
31
30
|
type StoryProps = { placeholder?: string } & UseTextEditorProps;
|
32
31
|
|
@@ -48,10 +48,10 @@ const PreviewCard = () => {
|
|
48
48
|
<Popover.Portal>
|
49
49
|
<Popover.Content onOpenAutoFocus={(event) => event.preventDefault()}>
|
50
50
|
<Popover.Viewport>
|
51
|
-
<Card.
|
51
|
+
<Card.SurfaceRoot role='card--popover'>
|
52
52
|
<Card.Heading>{target?.label}</Card.Heading>
|
53
53
|
{target && <Card.Text classNames='line-clamp-3'>{target.text}</Card.Text>}
|
54
|
-
</Card.
|
54
|
+
</Card.SurfaceRoot>
|
55
55
|
</Popover.Viewport>
|
56
56
|
<Popover.Arrow />
|
57
57
|
</Popover.Content>
|
@@ -126,7 +126,7 @@ const PreviewBlock = ({ link, el, view }: { link: PreviewLinkRef; el: HTMLElemen
|
|
126
126
|
}, [handleAction, link, target]);
|
127
127
|
|
128
128
|
return createPortal(
|
129
|
-
<Card.
|
129
|
+
<Card.StaticRoot classNames={hoverableControls}>
|
130
130
|
<div className='flex items-start'>
|
131
131
|
{!view?.state.readOnly && (
|
132
132
|
<Card.Toolbar classNames='is-min p-[--dx-cardSpacingInline]'>
|
@@ -159,7 +159,7 @@ const PreviewBlock = ({ link, el, view }: { link: PreviewLinkRef; el: HTMLElemen
|
|
159
159
|
</Card.Heading>
|
160
160
|
</div>
|
161
161
|
{target && <Card.Text classNames='line-clamp-3 mbs-0'>{target.text}</Card.Text>}
|
162
|
-
</Card.
|
162
|
+
</Card.StaticRoot>,
|
163
163
|
el,
|
164
164
|
);
|
165
165
|
};
|
@@ -217,7 +217,7 @@ export const Typeahead = {
|
|
217
217
|
extensions={[
|
218
218
|
decorateMarkdown({ renderLinkButton }),
|
219
219
|
typeahead({
|
220
|
-
onComplete: staticCompletion(completions,
|
220
|
+
onComplete: staticCompletion(completions, { minLength: 2 }),
|
221
221
|
}),
|
222
222
|
]}
|
223
223
|
/>
|