@dxos/react-ui-editor 0.4.4-next.e0df51e → 0.4.4
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 +39 -25
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/package.json +24 -24
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +6 -0
- package/src/components/TextEditor/TextEditor.tsx +18 -5
- package/src/components/TextEditor/automerge.stories.tsx +9 -6
- package/src/components/TextEditor/hooks.stories.tsx +44 -10
- package/src/hooks/useTextEditor.ts +6 -2
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
import '@dxosTheme';
|
|
6
6
|
|
|
7
|
-
import React from 'react';
|
|
7
|
+
import React, { useMemo, useState } from 'react';
|
|
8
8
|
|
|
9
|
-
import { useThemeContext } from '@dxos/react-ui';
|
|
9
|
+
import { Toolbar as NaturalToolbar, Select, useThemeContext } from '@dxos/react-ui';
|
|
10
10
|
import { attentionSurface, mx, textBlockWidth } from '@dxos/react-ui-theme';
|
|
11
11
|
import { withTheme } from '@dxos/storybook-utils';
|
|
12
12
|
|
|
13
13
|
import { TextEditor } from './TextEditor';
|
|
14
14
|
import {
|
|
15
|
+
type EditorMode,
|
|
16
|
+
EditorModes,
|
|
15
17
|
code,
|
|
16
18
|
createMarkdownExtensions,
|
|
17
19
|
formatting,
|
|
@@ -45,11 +47,10 @@ type StoryProps = {
|
|
|
45
47
|
const Story = ({ autoFocus, placeholder, doc, readonly }: StoryProps) => {
|
|
46
48
|
const { themeMode } = useThemeContext();
|
|
47
49
|
const [formattingState, trackFormatting] = useFormattingState();
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
//
|
|
50
|
+
const [editorMode, setEditorMode] = useState<EditorMode>('default');
|
|
51
|
+
const extensions = useMemo(
|
|
52
|
+
() => [
|
|
53
|
+
editorMode ? EditorModes[editorMode] : [],
|
|
53
54
|
createDataExtensions({ readonly }),
|
|
54
55
|
createThemeExtensions({
|
|
55
56
|
themeMode,
|
|
@@ -71,16 +72,19 @@ const Story = ({ autoFocus, placeholder, doc, readonly }: StoryProps) => {
|
|
|
71
72
|
tasklist(),
|
|
72
73
|
trackFormatting,
|
|
73
74
|
],
|
|
74
|
-
|
|
75
|
+
[editorMode, themeMode, placeholder, trackFormatting, readonly],
|
|
76
|
+
);
|
|
77
|
+
const { parentRef, view } = useTextEditor({ autoFocus, doc, extensions });
|
|
75
78
|
|
|
76
79
|
const handleAction = useActionHandler(view);
|
|
77
80
|
|
|
78
|
-
//
|
|
79
|
-
// sure if view is even guaranteed to exist at this point.
|
|
81
|
+
// TODO(marijn) This doesn't update the state on view changes.
|
|
82
|
+
// Also not sure if view is even guaranteed to exist at this point.
|
|
80
83
|
return (
|
|
81
84
|
<div role='none' className={mx('fixed inset-0', editorWithToolbarLayout)}>
|
|
82
85
|
<Toolbar.Root onAction={handleAction} state={formattingState} classNames={textBlockWidth}>
|
|
83
86
|
<Toolbar.Markdown />
|
|
87
|
+
<EditorModeToolbar editorMode={editorMode} setEditorMode={setEditorMode} />
|
|
84
88
|
</Toolbar.Root>
|
|
85
89
|
<div role='none' className='overflow-y-auto'>
|
|
86
90
|
<div
|
|
@@ -93,6 +97,36 @@ const Story = ({ autoFocus, placeholder, doc, readonly }: StoryProps) => {
|
|
|
93
97
|
);
|
|
94
98
|
};
|
|
95
99
|
|
|
100
|
+
const EditorModeToolbar = ({
|
|
101
|
+
editorMode,
|
|
102
|
+
setEditorMode,
|
|
103
|
+
}: {
|
|
104
|
+
editorMode: EditorMode;
|
|
105
|
+
setEditorMode: (mode: EditorMode) => void;
|
|
106
|
+
}) => {
|
|
107
|
+
return (
|
|
108
|
+
<Select.Root value={editorMode} onValueChange={(value) => setEditorMode(value as EditorMode)}>
|
|
109
|
+
<NaturalToolbar.Button asChild>
|
|
110
|
+
<Select.TriggerButton variant='ghost'>{editorMode}</Select.TriggerButton>
|
|
111
|
+
</NaturalToolbar.Button>
|
|
112
|
+
<Select.Portal>
|
|
113
|
+
<Select.Content>
|
|
114
|
+
<Select.ScrollUpButton />
|
|
115
|
+
<Select.Viewport>
|
|
116
|
+
{['default', 'vim'].map((mode) => (
|
|
117
|
+
<Select.Option key={mode} value={mode}>
|
|
118
|
+
{mode}
|
|
119
|
+
</Select.Option>
|
|
120
|
+
))}
|
|
121
|
+
</Select.Viewport>
|
|
122
|
+
<Select.ScrollDownButton />
|
|
123
|
+
<Select.Arrow />
|
|
124
|
+
</Select.Content>
|
|
125
|
+
</Select.Portal>
|
|
126
|
+
</Select.Root>
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
|
|
96
130
|
export default {
|
|
97
131
|
title: 'react-ui-editor/useTextEditor',
|
|
98
132
|
component: TextEditor,
|
|
@@ -34,6 +34,7 @@ export type UseTextEditor = {
|
|
|
34
34
|
/**
|
|
35
35
|
* Hook for creating editor.
|
|
36
36
|
*/
|
|
37
|
+
// TODO(wittjosiah): Does not work in strict mode.
|
|
37
38
|
export const useTextEditor = ({
|
|
38
39
|
autoFocus,
|
|
39
40
|
scrollTo,
|
|
@@ -45,7 +46,9 @@ export const useTextEditor = ({
|
|
|
45
46
|
const onUpdate = useRef<() => void>();
|
|
46
47
|
const [view, setView] = useState<EditorView>();
|
|
47
48
|
const parentRef = useRef<HTMLDivElement>(null);
|
|
49
|
+
|
|
48
50
|
useEffect(() => {
|
|
51
|
+
let view: EditorView;
|
|
49
52
|
if (parentRef.current) {
|
|
50
53
|
// https://codemirror.net/docs/ref/#state.EditorStateConfig
|
|
51
54
|
const state = EditorState.create({
|
|
@@ -64,7 +67,7 @@ export const useTextEditor = ({
|
|
|
64
67
|
});
|
|
65
68
|
|
|
66
69
|
// https://codemirror.net/docs/ref/#view.EditorViewConfig
|
|
67
|
-
|
|
70
|
+
view = new EditorView({
|
|
68
71
|
parent: parentRef.current,
|
|
69
72
|
scrollTo,
|
|
70
73
|
state,
|
|
@@ -84,7 +87,8 @@ export const useTextEditor = ({
|
|
|
84
87
|
return () => {
|
|
85
88
|
view?.destroy();
|
|
86
89
|
};
|
|
87
|
-
|
|
90
|
+
// TODO(wittjosiah): Does `parentRef` ever change? Only `.current` changes?
|
|
91
|
+
}, [parentRef, extensions]);
|
|
88
92
|
|
|
89
93
|
useEffect(() => {
|
|
90
94
|
if (view) {
|