@dxos/react-ui-editor 0.4.8-main.6919ef3 → 0.4.8-main.6dbc1f1
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 +1388 -1298
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +1 -0
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +12 -11
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +4 -2
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +1 -0
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/dnd.d.ts +7 -1
- package/dist/types/src/extensions/dnd.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts +5 -1
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +0 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/action.d.ts +9 -0
- package/dist/types/src/extensions/markdown/action.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +7 -4
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/image.d.ts +6 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/modes.d.ts +1 -1
- package/dist/types/src/extensions/modes.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +2 -2
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useDocAccessor.d.ts +4 -2
- package/dist/types/src/hooks/useDocAccessor.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.stories.d.ts +1 -0
- package/dist/types/src/hooks/useTextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/package.json +26 -24
- package/src/components/TextEditor/TextEditor.stories.tsx +14 -2
- package/src/components/TextEditor/TextEditor.tsx +2 -2
- package/src/components/Toolbar/Toolbar.stories.tsx +23 -24
- package/src/components/Toolbar/Toolbar.tsx +102 -60
- package/src/extensions/automerge/automerge.ts +4 -4
- package/src/extensions/command/state.ts +2 -2
- package/src/extensions/comments.ts +2 -2
- package/src/extensions/dnd.ts +31 -9
- package/src/extensions/factories.ts +41 -15
- package/src/extensions/index.ts +0 -1
- package/src/extensions/markdown/action.ts +112 -0
- package/src/extensions/markdown/bundle.ts +8 -11
- package/src/extensions/markdown/formatting.test.ts +13 -13
- package/src/extensions/markdown/formatting.ts +95 -87
- package/src/extensions/markdown/image.ts +6 -0
- package/src/extensions/markdown/index.ts +1 -0
- package/src/extensions/modes.ts +8 -1
- package/src/hooks/useActionHandler.ts +4 -85
- package/src/hooks/useDocAccessor.ts +8 -2
- package/src/hooks/useTextEditor.stories.tsx +3 -3
- package/src/hooks/useTextEditor.ts +3 -0
- package/src/themes/default.ts +24 -8
- package/src/translations.ts +1 -0
- package/dist/types/src/extensions/cursor-line-margin.d.ts +0 -7
- package/dist/types/src/extensions/cursor-line-margin.d.ts.map +0 -1
- package/src/extensions/cursor-line-margin.ts +0 -94
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/markdown/image.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoB,KAAK,SAAS,EAA4C,MAAM,mBAAmB,CAAC;AAG/G,MAAM,MAAM,YAAY,GAAG,EAAE,CAAC;AAE9B,eAAO,MAAM,KAAK,aAAa,YAAY,KAAQ,SA8BlD,CAAC"}
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/markdown/image.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoB,KAAK,SAAS,EAA4C,MAAM,mBAAmB,CAAC;AAG/G,MAAM,MAAM,YAAY,GAAG,EAAE,CAAC;AAE9B,eAAO,MAAM,KAAK,aAAa,YAAY,KAAQ,SA8BlD,CAAC;AA4DF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,WAAW,aAAa,YAAY,SAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/markdown/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/markdown/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Extension, Facet } from '@codemirror/state';
|
|
2
2
|
export declare const focusEvent = "focus.container";
|
|
3
|
-
export type EditorMode = 'default' | 'vim' | undefined;
|
|
3
|
+
export type EditorMode = 'default' | 'vim' | 'vscode' | undefined;
|
|
4
4
|
export type EditorConfig = {
|
|
5
5
|
type: string;
|
|
6
6
|
noTabster?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modes.d.ts","sourceRoot":"","sources":["../../../../src/extensions/modes.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"modes.d.ts","sourceRoot":"","sources":["../../../../src/extensions/modes.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAK1D,eAAO,MAAM,UAAU,oBAAoB,CAAC;AAE5C,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElE,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,UAAU,mCAErB,CAAC;AAEH,eAAO,MAAM,WAAW,EAAE;IAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;CAsBpD,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
1
|
+
import { type EditorView } from '@codemirror/view';
|
|
2
|
+
import { type ToolbarProps } from '../components';
|
|
3
3
|
export declare const useActionHandler: (view?: EditorView | null) => ToolbarProps['onAction'];
|
|
4
4
|
//# sourceMappingURL=useActionHandler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useActionHandler.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useActionHandler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"useActionHandler.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useActionHandler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,eAAO,MAAM,gBAAgB,UAAW,UAAU,GAAG,IAAI,KAAG,YAAY,CAAC,UAAU,CAElF,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { type DocAccessor, type TextObject } from '@dxos/echo-schema';
|
|
2
|
-
export declare const useDocAccessor: <T = any>(text: TextObject
|
|
1
|
+
import { type DocAccessor, type TextObject, type EchoReactiveObject } from '@dxos/echo-schema';
|
|
2
|
+
export declare const useDocAccessor: <T = any>(text: TextObject | EchoReactiveObject<{
|
|
3
|
+
content: string;
|
|
4
|
+
}>) => {
|
|
3
5
|
id: string;
|
|
4
6
|
doc: string | undefined;
|
|
5
7
|
accessor: DocAccessor<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDocAccessor.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useDocAccessor.ts"],"names":[],"mappings":"AAMA,OAAO,
|
|
1
|
+
{"version":3,"file":"useDocAccessor.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useDocAccessor.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAG3B,eAAO,MAAM,cAAc,kBACnB,UAAU,GAAG,mBAAmB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;QACnD,MAAM;SAAO,MAAM,GAAG,SAAS;;CASvC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTextEditor.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useTextEditor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAwC,MAAM,OAAO,CAAC;AAKlG,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAIrD,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,eAAe,EAAE,iBAAiB,GAAG,YAAY,CAAC,CAAC;AAEzF;;GAEG;AACH,eAAO,MAAM,aAAa,QAAQ,MAAM,kBAAkB,4BAA2C,
|
|
1
|
+
{"version":3,"file":"useTextEditor.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useTextEditor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAwC,MAAM,OAAO,CAAC;AAKlG,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAIrD,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,eAAe,EAAE,iBAAiB,GAAG,YAAY,CAAC,CAAC;AAEzF;;GAEG;AACH,eAAO,MAAM,aAAa,QAAQ,MAAM,kBAAkB,4BAA2C,aA4EpG,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTextEditor.stories.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useTextEditor.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAwBpB,KAAK,UAAU,GAAG;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;;;;mBA2Ee,UAAU
|
|
1
|
+
{"version":3,"file":"useTextEditor.stories.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useTextEditor.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAwBpB,KAAK,UAAU,GAAG;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;;;;mBA2Ee,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;AAH3B,wBASE;AAEF,eAAO,MAAM,OAAO;;CAKnB,CAAC;AAEF,eAAO,MAAM,KAAK;;CAQjB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;CAMpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../../../src/themes/default.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,WAAW,EAAU,MAAM,WAAW,CAAC;AAKrD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../../../src/themes/default.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,WAAW,EAAU,MAAM,WAAW,CAAC;AAKrD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,WAgQ1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../../src/translations.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,oBAAoB,CAAC
|
|
1
|
+
{"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../../src/translations.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,oBAAoB,CAAC;;;;;;;;;;;;;;;;;;;;;AAEhD,wBAqBE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-editor",
|
|
3
|
-
"version": "0.4.8-main.
|
|
3
|
+
"version": "0.4.8-main.6dbc1f1",
|
|
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",
|
|
@@ -30,27 +30,29 @@
|
|
|
30
30
|
"@lezer/markdown": "^1.2.0",
|
|
31
31
|
"@radix-ui/react-context": "^1.0.0",
|
|
32
32
|
"@replit/codemirror-vim": "^6.0.14",
|
|
33
|
+
"@replit/codemirror-vscode-keymap": "^6.0.2",
|
|
33
34
|
"codemirror": "^6.0.1",
|
|
34
35
|
"lib0": "^0.2.65",
|
|
35
36
|
"lodash.defaultsdeep": "^4.6.1",
|
|
36
37
|
"lodash.get": "^4.4.2",
|
|
37
38
|
"lodash.pick": "^4.4.0",
|
|
38
39
|
"lodash.sortby": "^4.7.0",
|
|
40
|
+
"react-dropzone": "^14.2.3",
|
|
39
41
|
"style-mod": "^4.1.0",
|
|
40
|
-
"@dxos/async": "0.4.8-main.
|
|
41
|
-
"@dxos/automerge": "0.4.8-main.
|
|
42
|
-
"@dxos/context": "0.4.8-main.
|
|
43
|
-
"@dxos/debug": "0.4.8-main.
|
|
44
|
-
"@dxos/display-name": "0.4.8-main.
|
|
45
|
-
"@dxos/
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/react-async": "0.4.8-main.
|
|
50
|
-
"@dxos/react-ui": "0.4.8-main.
|
|
51
|
-
"@dxos/react-ui-theme": "0.4.8-main.
|
|
52
|
-
"@dxos/
|
|
53
|
-
"@dxos/
|
|
42
|
+
"@dxos/async": "0.4.8-main.6dbc1f1",
|
|
43
|
+
"@dxos/automerge": "0.4.8-main.6dbc1f1",
|
|
44
|
+
"@dxos/context": "0.4.8-main.6dbc1f1",
|
|
45
|
+
"@dxos/debug": "0.4.8-main.6dbc1f1",
|
|
46
|
+
"@dxos/display-name": "0.4.8-main.6dbc1f1",
|
|
47
|
+
"@dxos/echo-schema": "0.4.8-main.6dbc1f1",
|
|
48
|
+
"@dxos/log": "0.4.8-main.6dbc1f1",
|
|
49
|
+
"@dxos/invariant": "0.4.8-main.6dbc1f1",
|
|
50
|
+
"@dxos/protocols": "0.4.8-main.6dbc1f1",
|
|
51
|
+
"@dxos/react-async": "0.4.8-main.6dbc1f1",
|
|
52
|
+
"@dxos/react-ui": "0.4.8-main.6dbc1f1",
|
|
53
|
+
"@dxos/react-ui-theme": "0.4.8-main.6dbc1f1",
|
|
54
|
+
"@dxos/util": "0.4.8-main.6dbc1f1",
|
|
55
|
+
"@dxos/text-model": "0.4.8-main.6dbc1f1"
|
|
54
56
|
},
|
|
55
57
|
"devDependencies": {
|
|
56
58
|
"@automerge/automerge-repo-network-broadcastchannel": "^1.1.1",
|
|
@@ -77,20 +79,20 @@
|
|
|
77
79
|
"vite-plugin-top-level-await": "^1.4.1",
|
|
78
80
|
"vite-plugin-wasm": "^3.3.0",
|
|
79
81
|
"vitest": "^1.3.1",
|
|
80
|
-
"@dxos/config": "0.4.8-main.
|
|
81
|
-
"@dxos/echo-
|
|
82
|
-
"@dxos/
|
|
83
|
-
"@dxos/
|
|
84
|
-
"@dxos/
|
|
85
|
-
"@dxos/react-ui": "0.4.8-main.
|
|
86
|
-
"@dxos/
|
|
87
|
-
"@dxos/
|
|
82
|
+
"@dxos/config": "0.4.8-main.6dbc1f1",
|
|
83
|
+
"@dxos/echo-typegen": "0.4.8-main.6dbc1f1",
|
|
84
|
+
"@dxos/keyboard": "0.4.8-main.6dbc1f1",
|
|
85
|
+
"@dxos/echo-signals": "0.4.8-main.6dbc1f1",
|
|
86
|
+
"@dxos/react-client": "0.4.8-main.6dbc1f1",
|
|
87
|
+
"@dxos/react-ui": "0.4.8-main.6dbc1f1",
|
|
88
|
+
"@dxos/random": "0.4.8-main.6dbc1f1",
|
|
89
|
+
"@dxos/storybook-utils": "0.4.8-main.6dbc1f1"
|
|
88
90
|
},
|
|
89
91
|
"peerDependencies": {
|
|
90
92
|
"@phosphor-icons/react": "^2.0.5",
|
|
91
93
|
"react": "^18.2.0",
|
|
92
94
|
"react-dom": "^18.2.0",
|
|
93
|
-
"@dxos/react-client": "0.4.8-main.
|
|
95
|
+
"@dxos/react-client": "0.4.8-main.6dbc1f1"
|
|
94
96
|
},
|
|
95
97
|
"publishConfig": {
|
|
96
98
|
"access": "public"
|
|
@@ -13,6 +13,7 @@ import { createRoot } from 'react-dom/client';
|
|
|
13
13
|
import { TextObject } from '@dxos/echo-schema';
|
|
14
14
|
import { keySymbols, parseShortcut } from '@dxos/keyboard';
|
|
15
15
|
import { PublicKey } from '@dxos/keys';
|
|
16
|
+
import { log } from '@dxos/log';
|
|
16
17
|
import { faker } from '@dxos/random';
|
|
17
18
|
import { Button, DensityProvider, Input, ThemeProvider, useThemeContext } from '@dxos/react-ui';
|
|
18
19
|
import { baseSurface, defaultTx, getSize, mx, textBlockWidth } from '@dxos/react-ui-theme';
|
|
@@ -32,7 +33,7 @@ import {
|
|
|
32
33
|
createThemeExtensions,
|
|
33
34
|
decorateMarkdown,
|
|
34
35
|
defaultOptions,
|
|
35
|
-
|
|
36
|
+
dropFile,
|
|
36
37
|
formattingKeymap,
|
|
37
38
|
image,
|
|
38
39
|
linkTooltip,
|
|
@@ -501,7 +502,18 @@ export const Annotations = {
|
|
|
501
502
|
};
|
|
502
503
|
|
|
503
504
|
export const DND = {
|
|
504
|
-
render: () =>
|
|
505
|
+
render: () => (
|
|
506
|
+
<Story
|
|
507
|
+
text={str('# DND', '')}
|
|
508
|
+
extensions={[
|
|
509
|
+
dropFile({
|
|
510
|
+
onDrop: (view, event) => {
|
|
511
|
+
log.info('drop', event);
|
|
512
|
+
},
|
|
513
|
+
}),
|
|
514
|
+
]}
|
|
515
|
+
/>
|
|
516
|
+
),
|
|
505
517
|
};
|
|
506
518
|
|
|
507
519
|
const typewriterItems = localStorage.getItem('dxos.org/plugin/markdown/typewriter')?.split(',');
|
|
@@ -85,7 +85,7 @@ export const TextEditor = forwardRef<EditorView | null, TextEditorProps>(
|
|
|
85
85
|
// Create editor state and view.
|
|
86
86
|
// The view is recreated if the model or extensions are changed.
|
|
87
87
|
useEffect(() => {
|
|
88
|
-
log('
|
|
88
|
+
log('create', { id, instanceId });
|
|
89
89
|
|
|
90
90
|
//
|
|
91
91
|
// EditorState
|
|
@@ -147,8 +147,8 @@ export const TextEditor = forwardRef<EditorView | null, TextEditorProps>(
|
|
|
147
147
|
setView(view);
|
|
148
148
|
|
|
149
149
|
return () => {
|
|
150
|
+
log('destroy', { id, instanceId });
|
|
150
151
|
view?.destroy();
|
|
151
|
-
setView(null);
|
|
152
152
|
};
|
|
153
153
|
}, [doc, selection, extensions]);
|
|
154
154
|
|
|
@@ -16,17 +16,17 @@ import { withTheme } from '@dxos/storybook-utils';
|
|
|
16
16
|
import { Toolbar } from './Toolbar';
|
|
17
17
|
import {
|
|
18
18
|
type Comment,
|
|
19
|
-
decorateMarkdown,
|
|
20
19
|
comments,
|
|
21
20
|
createBasicExtensions,
|
|
22
21
|
createDataExtensions,
|
|
22
|
+
createMarkdownExtensions,
|
|
23
23
|
createThemeExtensions,
|
|
24
|
+
decorateMarkdown,
|
|
24
25
|
formattingKeymap,
|
|
26
|
+
image,
|
|
25
27
|
table,
|
|
26
28
|
useComments,
|
|
27
29
|
useFormattingState,
|
|
28
|
-
createMarkdownExtensions,
|
|
29
|
-
image,
|
|
30
30
|
} from '../../extensions';
|
|
31
31
|
import { useActionHandler, useDocAccessor, useTextEditor } from '../../hooks';
|
|
32
32
|
import translations from '../../translations';
|
|
@@ -34,15 +34,17 @@ import translations from '../../translations';
|
|
|
34
34
|
faker.seed(101);
|
|
35
35
|
|
|
36
36
|
const Story: FC<{ content: string }> = ({ content }) => {
|
|
37
|
+
console.log('STORY');
|
|
37
38
|
const { themeMode } = useThemeContext();
|
|
38
39
|
const [item] = useState({ text: new TextObject(content) });
|
|
39
40
|
const { id, doc, accessor } = useDocAccessor(item.text);
|
|
40
41
|
const [formattingState, formattingObserver] = useFormattingState();
|
|
41
|
-
const { parentRef, view } = useTextEditor(
|
|
42
|
-
|
|
42
|
+
const { parentRef, view } = useTextEditor(() => {
|
|
43
|
+
return {
|
|
43
44
|
id,
|
|
44
45
|
doc,
|
|
45
46
|
extensions: [
|
|
47
|
+
formattingObserver,
|
|
46
48
|
createBasicExtensions(),
|
|
47
49
|
createMarkdownExtensions({ themeMode }),
|
|
48
50
|
createThemeExtensions({ themeMode, slots: { editor: { className: 'p-2' } } }),
|
|
@@ -58,39 +60,36 @@ const Story: FC<{ content: string }> = ({ content }) => {
|
|
|
58
60
|
formattingKeymap(),
|
|
59
61
|
image(),
|
|
60
62
|
table(),
|
|
61
|
-
formattingObserver,
|
|
62
63
|
],
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
};
|
|
65
|
+
}, [id, accessor, formattingObserver, themeMode]);
|
|
66
|
+
|
|
67
|
+
const handleAction = useActionHandler(view);
|
|
66
68
|
|
|
67
69
|
const [_comments, setComments] = useState<Comment[]>([]);
|
|
68
70
|
useComments(view, id, _comments);
|
|
69
71
|
|
|
70
|
-
const handleAction = useActionHandler(view);
|
|
71
|
-
|
|
72
72
|
return (
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
<Toolbar.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
<Tooltip.Provider>
|
|
74
|
+
<div role='none' className='fixed inset-0 flex flex-col'>
|
|
75
|
+
<Toolbar.Root onAction={handleAction} state={formattingState} classNames={textBlockWidth}>
|
|
76
|
+
<Toolbar.Markdown />
|
|
77
|
+
<Toolbar.Custom onUpload={async (file) => ({ url: file.name })} />
|
|
78
|
+
<Toolbar.Separator />
|
|
79
|
+
<Toolbar.Actions />
|
|
80
|
+
</Toolbar.Root>
|
|
81
|
+
<div ref={parentRef} className={textBlockWidth} />
|
|
82
|
+
</div>
|
|
83
|
+
</Tooltip.Provider>
|
|
81
84
|
);
|
|
82
85
|
};
|
|
83
86
|
|
|
84
87
|
export default {
|
|
85
88
|
title: 'react-ui-editor/Toolbar',
|
|
86
89
|
component: Toolbar,
|
|
87
|
-
render: (args: any) => (
|
|
88
|
-
<Tooltip.Provider>
|
|
89
|
-
<Story {...args} />
|
|
90
|
-
</Tooltip.Provider>
|
|
91
|
-
),
|
|
92
90
|
decorators: [withTheme],
|
|
93
91
|
parameters: { translations, layout: 'fullscreen' },
|
|
92
|
+
render: (args: any) => <Story {...args} />,
|
|
94
93
|
};
|
|
95
94
|
|
|
96
95
|
const content = [
|
|
@@ -7,11 +7,13 @@ import {
|
|
|
7
7
|
ChatText,
|
|
8
8
|
Code,
|
|
9
9
|
CodeBlock,
|
|
10
|
+
Image,
|
|
10
11
|
Link,
|
|
11
12
|
ListBullets,
|
|
12
13
|
ListChecks,
|
|
13
14
|
ListNumbers,
|
|
14
15
|
Paragraph,
|
|
16
|
+
Quotes,
|
|
15
17
|
TextStrikethrough,
|
|
16
18
|
Table,
|
|
17
19
|
TextB,
|
|
@@ -22,24 +24,25 @@ import {
|
|
|
22
24
|
TextHFive,
|
|
23
25
|
TextHSix,
|
|
24
26
|
TextItalic,
|
|
25
|
-
Quotes,
|
|
26
27
|
} from '@phosphor-icons/react';
|
|
27
28
|
import { createContext } from '@radix-ui/react-context';
|
|
28
|
-
import React, { type PropsWithChildren, useRef, useState } from 'react';
|
|
29
|
+
import React, { type PropsWithChildren, useEffect, useRef, useState } from 'react';
|
|
30
|
+
import { useDropzone } from 'react-dropzone';
|
|
29
31
|
|
|
30
32
|
import {
|
|
31
33
|
DensityProvider,
|
|
32
34
|
ElevationProvider,
|
|
33
35
|
Select,
|
|
34
|
-
type ThemedClassName,
|
|
35
36
|
Toolbar as NaturalToolbar,
|
|
36
37
|
Tooltip,
|
|
37
|
-
type
|
|
38
|
+
type ThemedClassName,
|
|
39
|
+
type ToolbarToggleGroupItemProps as NaturalToolbarToggleGroupItemProps,
|
|
40
|
+
type ToolbarButtonProps as NaturalToolbarButtonProps,
|
|
38
41
|
useTranslation,
|
|
39
42
|
} from '@dxos/react-ui';
|
|
40
43
|
import { getSize } from '@dxos/react-ui-theme';
|
|
41
44
|
|
|
42
|
-
import { type Formatting } from '../../extensions';
|
|
45
|
+
import { type Action, type ActionType, type Formatting } from '../../extensions';
|
|
43
46
|
import { translationKey } from '../../translations';
|
|
44
47
|
|
|
45
48
|
const tooltipProps = { side: 'top' as const, classNames: 'z-10' };
|
|
@@ -54,33 +57,9 @@ const HeadingIcons: { [key: string]: Icon } = {
|
|
|
54
57
|
'6': TextHSix,
|
|
55
58
|
};
|
|
56
59
|
|
|
57
|
-
// TODO(burdon): Revert to string to make extensible?
|
|
58
|
-
export type ActionType =
|
|
59
|
-
| 'blockquote'
|
|
60
|
-
| 'strong'
|
|
61
|
-
| 'codeblock'
|
|
62
|
-
| 'comment'
|
|
63
|
-
| 'heading'
|
|
64
|
-
| 'image'
|
|
65
|
-
| 'emphasis'
|
|
66
|
-
| 'code'
|
|
67
|
-
| 'link'
|
|
68
|
-
| 'list-bullet'
|
|
69
|
-
| 'list-ordered'
|
|
70
|
-
| 'list-task'
|
|
71
|
-
| 'mention'
|
|
72
|
-
| 'prompt'
|
|
73
|
-
| 'strikethrough'
|
|
74
|
-
| 'table';
|
|
75
|
-
|
|
76
|
-
export type Action = {
|
|
77
|
-
type: ActionType;
|
|
78
|
-
data?: any;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
60
|
export type ToolbarProps = ThemedClassName<
|
|
82
61
|
PropsWithChildren<{
|
|
83
|
-
state: Formatting |
|
|
62
|
+
state: Formatting | undefined;
|
|
84
63
|
onAction?: (action: Action) => void;
|
|
85
64
|
}>
|
|
86
65
|
>;
|
|
@@ -111,9 +90,9 @@ type ButtonProps = {
|
|
|
111
90
|
disabled?: (state: Formatting) => boolean;
|
|
112
91
|
};
|
|
113
92
|
|
|
114
|
-
type
|
|
93
|
+
type ToolbarToggleButtonProps = NaturalToolbarToggleGroupItemProps & { Icon: Icon };
|
|
115
94
|
|
|
116
|
-
const
|
|
95
|
+
const ToolbarToggleButton = ({ Icon, children, ...props }: ToolbarToggleButtonProps) => {
|
|
117
96
|
return (
|
|
118
97
|
<Tooltip.Root>
|
|
119
98
|
<Tooltip.Trigger asChild>
|
|
@@ -132,6 +111,27 @@ const ToolbarButton = ({ Icon, children, ...props }: ToolbarButtonProps) => {
|
|
|
132
111
|
);
|
|
133
112
|
};
|
|
134
113
|
|
|
114
|
+
type ToolbarButtonProps = NaturalToolbarButtonProps & { Icon: Icon };
|
|
115
|
+
|
|
116
|
+
const ToolbarButton = ({ Icon, children, ...props }: ToolbarButtonProps) => {
|
|
117
|
+
return (
|
|
118
|
+
<Tooltip.Root>
|
|
119
|
+
<Tooltip.Trigger asChild>
|
|
120
|
+
<NaturalToolbar.Button variant='ghost' {...props} classNames={buttonStyles}>
|
|
121
|
+
<Icon className={iconStyles} />
|
|
122
|
+
<span className='sr-only'>{children}</span>
|
|
123
|
+
</NaturalToolbar.Button>
|
|
124
|
+
</Tooltip.Trigger>
|
|
125
|
+
<Tooltip.Portal>
|
|
126
|
+
<Tooltip.Content {...tooltipProps}>
|
|
127
|
+
{children}
|
|
128
|
+
<Tooltip.Arrow />
|
|
129
|
+
</Tooltip.Content>
|
|
130
|
+
</Tooltip.Portal>
|
|
131
|
+
</Tooltip.Root>
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
135
|
const ToolbarSeparator = () => <div role='separator' className='grow' />;
|
|
136
136
|
|
|
137
137
|
const MarkdownHeading = () => {
|
|
@@ -227,7 +227,7 @@ const MarkdownStyles = () => {
|
|
|
227
227
|
value={markdownStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)}
|
|
228
228
|
>
|
|
229
229
|
{markdownStyles.map(({ type, getState, Icon }) => (
|
|
230
|
-
<
|
|
230
|
+
<ToolbarToggleButton
|
|
231
231
|
key={type}
|
|
232
232
|
value={type}
|
|
233
233
|
Icon={Icon}
|
|
@@ -235,7 +235,7 @@ const MarkdownStyles = () => {
|
|
|
235
235
|
onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
|
|
236
236
|
>
|
|
237
237
|
{t(`${type} label`)}
|
|
238
|
-
</
|
|
238
|
+
</ToolbarToggleButton>
|
|
239
239
|
))}
|
|
240
240
|
</NaturalToolbar.ToggleGroup>
|
|
241
241
|
);
|
|
@@ -253,14 +253,14 @@ const MarkdownLists = () => {
|
|
|
253
253
|
return (
|
|
254
254
|
<NaturalToolbar.ToggleGroup type='single' value={state?.listStyle ? `list-${state.listStyle}` : ''}>
|
|
255
255
|
{markdownLists.map(({ type, getState, Icon }) => (
|
|
256
|
-
<
|
|
256
|
+
<ToolbarToggleButton
|
|
257
257
|
key={type}
|
|
258
258
|
value={type}
|
|
259
259
|
Icon={Icon}
|
|
260
260
|
onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
|
|
261
261
|
>
|
|
262
262
|
{t(`${type} label`)}
|
|
263
|
-
</
|
|
263
|
+
</ToolbarToggleButton>
|
|
264
264
|
))}
|
|
265
265
|
</NaturalToolbar.ToggleGroup>
|
|
266
266
|
);
|
|
@@ -292,7 +292,7 @@ const MarkdownBlocks = () => {
|
|
|
292
292
|
return (
|
|
293
293
|
<NaturalToolbar.ToggleGroup type='single' value={value?.type ?? ''}>
|
|
294
294
|
{markdownBlocks.map(({ type, disabled, getState, Icon }) => (
|
|
295
|
-
<
|
|
295
|
+
<ToolbarToggleButton
|
|
296
296
|
key={type}
|
|
297
297
|
value={type}
|
|
298
298
|
Icon={Icon}
|
|
@@ -300,7 +300,7 @@ const MarkdownBlocks = () => {
|
|
|
300
300
|
onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
|
|
301
301
|
>
|
|
302
302
|
{t(`${type} label`)}
|
|
303
|
-
</
|
|
303
|
+
</ToolbarToggleButton>
|
|
304
304
|
))}
|
|
305
305
|
</NaturalToolbar.ToggleGroup>
|
|
306
306
|
);
|
|
@@ -315,38 +315,80 @@ const MarkdownStandard = () => (
|
|
|
315
315
|
</>
|
|
316
316
|
);
|
|
317
317
|
|
|
318
|
-
|
|
318
|
+
// TODO(burdon): Make extensible.
|
|
319
|
+
export type MarkdownCustomOptions = {
|
|
320
|
+
onUpload?: (file: File) => Promise<{ url?: string }>;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const MarkdownCustom = ({ onUpload }: MarkdownCustomOptions = {}) => {
|
|
319
324
|
const { onAction } = useToolbarContext('MarkdownStyles');
|
|
320
325
|
const { t } = useTranslation(translationKey);
|
|
326
|
+
// https://react-dropzone.js.org/#src
|
|
327
|
+
const { acceptedFiles, getInputProps, open } = useDropzone({
|
|
328
|
+
multiple: false,
|
|
329
|
+
noDrag: true,
|
|
330
|
+
accept: {
|
|
331
|
+
'image/*': ['.jpg', '.jpeg', '.png', '.gif'],
|
|
332
|
+
},
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
useEffect(() => {
|
|
336
|
+
if (onUpload && acceptedFiles.length) {
|
|
337
|
+
requestAnimationFrame(async () => {
|
|
338
|
+
// NOTE: Clone file since react-dropzone patches in a non-standard `path` property, which confuses IPFS.
|
|
339
|
+
const f = acceptedFiles[0];
|
|
340
|
+
const file = new File([f], f.name, {
|
|
341
|
+
type: f.type,
|
|
342
|
+
lastModified: f.lastModified,
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
const { url } = await onUpload(file);
|
|
346
|
+
if (url) {
|
|
347
|
+
onAction?.({ type: 'image', data: url });
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
}, [acceptedFiles]);
|
|
352
|
+
|
|
321
353
|
return (
|
|
322
|
-
|
|
323
|
-
<
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
354
|
+
<>
|
|
355
|
+
<input {...getInputProps()} />
|
|
356
|
+
<ToolbarButton value='image' Icon={Image} onClick={() => open()}>
|
|
357
|
+
{t('image label')}
|
|
358
|
+
</ToolbarButton>
|
|
359
|
+
</>
|
|
360
|
+
);
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
// TODO(burdon): Make extensible.
|
|
364
|
+
const MarkdownActions = () => {
|
|
365
|
+
const { onAction } = useToolbarContext('MarkdownStyles');
|
|
366
|
+
const { t } = useTranslation(translationKey);
|
|
367
|
+
return (
|
|
368
|
+
<>
|
|
369
|
+
{/* TODO(burdon): Toggle readonly state. */}
|
|
370
|
+
{/* <ToolbarButton value='comment' Icon={BookOpenText} onClick={() => onAction?.({ type: 'comment' })}> */}
|
|
371
|
+
{/* {t('comment label')} */}
|
|
372
|
+
{/* </ToolbarButton> */}
|
|
373
|
+
<ToolbarButton
|
|
374
|
+
value='comment'
|
|
375
|
+
Icon={ChatText}
|
|
376
|
+
data-testid='editor.toolbar.comment'
|
|
377
|
+
onClick={() => onAction?.({ type: 'comment' })}
|
|
378
|
+
>
|
|
379
|
+
{t('comment label')}
|
|
380
|
+
</ToolbarButton>
|
|
381
|
+
</>
|
|
341
382
|
);
|
|
342
383
|
};
|
|
343
384
|
|
|
344
385
|
export const Toolbar = {
|
|
345
386
|
Root: ToolbarRoot,
|
|
346
|
-
Button:
|
|
387
|
+
Button: ToolbarToggleButton,
|
|
347
388
|
Separator: ToolbarSeparator,
|
|
348
389
|
Markdown: MarkdownStandard,
|
|
349
|
-
|
|
390
|
+
Custom: MarkdownCustom,
|
|
391
|
+
Actions: MarkdownActions,
|
|
350
392
|
};
|
|
351
393
|
|
|
352
394
|
export { useToolbarContext };
|
|
@@ -60,16 +60,16 @@ export const automerge = (accessor: DocAccessor): Extension => {
|
|
|
60
60
|
ViewPlugin.fromClass(
|
|
61
61
|
class {
|
|
62
62
|
constructor(private readonly _view: EditorView) {
|
|
63
|
-
accessor.handle.addListener('change', this._handleChange
|
|
63
|
+
accessor.handle.addListener('change', this._handleChange);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
destroy() {
|
|
67
|
-
accessor.handle.removeListener('change', this._handleChange
|
|
67
|
+
accessor.handle.removeListener('change', this._handleChange);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
_handleChange() {
|
|
70
|
+
readonly _handleChange = () => {
|
|
71
71
|
syncer.reconcile(this._view, false);
|
|
72
|
-
}
|
|
72
|
+
};
|
|
73
73
|
},
|
|
74
74
|
),
|
|
75
75
|
|
|
@@ -59,8 +59,8 @@ export const commandState = StateField.define<CommandState>({
|
|
|
59
59
|
selection: { anchor: pos + action.insert.length },
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
|
-
//
|
|
63
|
-
|
|
62
|
+
// NOTE: Truncates text if set focus immediately.
|
|
63
|
+
requestAnimationFrame(() => view.focus());
|
|
64
64
|
});
|
|
65
65
|
},
|
|
66
66
|
};
|