@dxos/react-ui-editor 0.3.9-main.2b2db7f → 0.3.9-main.2dc53cf

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.
Files changed (48) hide show
  1. package/dist/lib/browser/index.mjs +298 -26
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/automerge/automerge-plugin/index.d.ts +1 -1
  5. package/dist/types/src/automerge/automerge-plugin/index.d.ts.map +1 -1
  6. package/dist/types/src/automerge/automerge.stories.d.ts.map +1 -1
  7. package/dist/types/src/components/Editor/Editor.stories.d.ts +3 -2
  8. package/dist/types/src/components/Editor/Editor.stories.d.ts.map +1 -1
  9. package/dist/types/src/components/Markdown/Markdown.d.ts +2 -1
  10. package/dist/types/src/components/Markdown/Markdown.d.ts.map +1 -1
  11. package/dist/types/src/components/Markdown/Markdown.stories.d.ts +2 -1
  12. package/dist/types/src/components/Markdown/Markdown.stories.d.ts.map +1 -1
  13. package/dist/types/src/components/Markdown/markdownTheme.d.ts +2 -16
  14. package/dist/types/src/components/Markdown/markdownTheme.d.ts.map +1 -1
  15. package/dist/types/src/components/RichText/RichText.stories.d.ts +2 -1
  16. package/dist/types/src/components/RichText/RichText.stories.d.ts.map +1 -1
  17. package/dist/types/src/components/TextEditor/TextEditor.d.ts +39 -0
  18. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -0
  19. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +32 -0
  20. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -0
  21. package/dist/types/src/components/TextEditor/extensions/hyperlink.d.ts +10 -0
  22. package/dist/types/src/components/TextEditor/extensions/hyperlink.d.ts.map +1 -0
  23. package/dist/types/src/components/TextEditor/extensions/hyperlinkTooltip.d.ts +9 -0
  24. package/dist/types/src/components/TextEditor/extensions/hyperlinkTooltip.d.ts.map +1 -0
  25. package/dist/types/src/components/TextEditor/extensions/index.d.ts +3 -0
  26. package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -0
  27. package/dist/types/src/components/TextEditor/index.d.ts +6 -0
  28. package/dist/types/src/components/TextEditor/index.d.ts.map +1 -0
  29. package/dist/types/src/components/TextEditor/theme.d.ts +8 -0
  30. package/dist/types/src/components/TextEditor/theme.d.ts.map +1 -0
  31. package/dist/types/src/components/index.d.ts +1 -0
  32. package/dist/types/src/components/index.d.ts.map +1 -1
  33. package/package.json +20 -16
  34. package/src/automerge/automerge-plugin/index.ts +1 -1
  35. package/src/automerge/automerge.stories.tsx +1 -2
  36. package/src/components/Editor/Editor.stories.tsx +2 -0
  37. package/src/components/Markdown/Markdown.stories.tsx +2 -0
  38. package/src/components/Markdown/Markdown.tsx +6 -2
  39. package/src/components/Markdown/markdownTheme.ts +20 -16
  40. package/src/components/RichText/RichText.stories.tsx +2 -0
  41. package/src/components/TextEditor/TextEditor.stories.tsx +83 -0
  42. package/src/components/TextEditor/TextEditor.tsx +130 -0
  43. package/src/components/TextEditor/extensions/hyperlink.tsx +108 -0
  44. package/src/components/TextEditor/extensions/hyperlinkTooltip.tsx +76 -0
  45. package/src/components/TextEditor/extensions/index.ts +6 -0
  46. package/src/components/TextEditor/index.ts +11 -0
  47. package/src/components/TextEditor/theme.ts +33 -0
  48. package/src/components/index.ts +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"markdownTheme.d.ts","sourceRoot":"","sources":["../../../../../src/components/Markdown/markdownTheme.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAUtD,eAAO,MAAM,MAAM,YAAY,CAAC;AAChC,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,IAAI,YAAY,CAAC;AAC9B,eAAO,MAAM,OAAO,YAAY,CAAC;AACjC,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,MAAM,YAAY,CAAC;AAChC,eAAO,MAAM,IAAI,YAAY,CAAC;AAC9B,eAAO,MAAM,OAAO,YAAY,CAAC;AACjC,eAAO,MAAM,MAAM,YAAY,CAAC;AAEhC,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAE7C,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAE3C,eAAO,MAAM,MAAM,YAAY,CAAC;AAIhC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwIzB,CAAC;AAEF,eAAO,MAAM,wBAAwB,gBA6EpC,CAAC"}
1
+ {"version":3,"file":"markdownTheme.d.ts","sourceRoot":"","sources":["../../../../../src/components/Markdown/markdownTheme.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAUtD,eAAO,MAAM,MAAM,YAAY,CAAC;AAChC,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,IAAI,YAAY,CAAC;AAC9B,eAAO,MAAM,OAAO,YAAY,CAAC;AACjC,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,MAAM,YAAY,CAAC;AAChC,eAAO,MAAM,IAAI,YAAY,CAAC;AAC9B,eAAO,MAAM,OAAO,YAAY,CAAC;AACjC,eAAO,MAAM,MAAM,YAAY,CAAC;AAEhC,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAE7C,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAE3C,eAAO,MAAM,MAAM,YAAY,CAAC;AAIhC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4IzB,CAAC;AAEF,eAAO,MAAM,wBAAwB,gBA6EpC,CAAC"}
@@ -9,6 +9,7 @@ declare const _default: {
9
9
  } & {
10
10
  slots?: import("../..").EditorSlots | undefined;
11
11
  } & React.RefAttributes<import("@tiptap/react").Editor | null>>;
12
+ decorators: import("@storybook/react").Decorator[];
12
13
  };
13
14
  export default _default;
14
15
  export declare const Default: {
@@ -21,6 +22,6 @@ export declare const Default: {
21
22
  };
22
23
  export declare const WithYjs: {
23
24
  render: (args: Omit<RichTextEditorProps, 'model'>) => JSX.Element;
24
- decorators: import("@storybook/csf").DecoratorFunction<import("@storybook/react/dist/types-0a347bb9").R, any>[];
25
+ decorators: import("@storybook/csf").DecoratorFunction<import("@storybook/react/dist/types-0fc72a6d").R, any>[];
25
26
  };
26
27
  //# sourceMappingURL=RichText.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RichText.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/RichText/RichText.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAEpB,OAAO,KAAmB,MAAM,OAAO,CAAC;AAQxC,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;;;;;;;;;;AAGtE,wBAEE;AAEF,eAAO,MAAM,OAAO;;;;;;;CAOnB,CAAC;AAGF,eAAO,MAAM,OAAO;mBACH,KAAK,mBAAmB,EAAE,OAAO,CAAC;;CAmClD,CAAC"}
1
+ {"version":3,"file":"RichText.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/RichText/RichText.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAEpB,OAAO,KAAmB,MAAM,OAAO,CAAC;AASxC,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;;;;;;;;;;;AAGtE,wBAGE;AAEF,eAAO,MAAM,OAAO;;;;;;;CAOnB,CAAC;AAGF,eAAO,MAAM,OAAO;mBACH,KAAK,mBAAmB,EAAE,OAAO,CAAC;;CAmClD,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { EditorState, type Extension } from '@codemirror/state';
2
+ import { EditorView } from '@codemirror/view';
3
+ import React, { type KeyboardEvent, type HTMLAttributes } from 'react';
4
+ import { type StyleSpec } from 'style-mod';
5
+ import { type EditorModel, type EditorSlots } from '../../model';
6
+ export type CursorInfo = {
7
+ from: number;
8
+ to: number;
9
+ line: number;
10
+ lines: number;
11
+ after?: string;
12
+ };
13
+ export type TextEditorRef = {
14
+ editor: HTMLDivElement | null;
15
+ state?: EditorState;
16
+ view?: EditorView;
17
+ };
18
+ export type TextEditorProps = {
19
+ model?: EditorModel;
20
+ extensions?: Extension[];
21
+ theme?: {
22
+ [selector: string]: StyleSpec;
23
+ };
24
+ slots?: EditorSlots;
25
+ onKeyDown?: (event: KeyboardEvent, info: CursorInfo) => void;
26
+ } & Pick<HTMLAttributes<HTMLDivElement>, 'onBlur' | 'onFocus'>;
27
+ /**
28
+ * Simple text editor.
29
+ */
30
+ export declare const TextEditor: React.ForwardRefExoticComponent<{
31
+ model?: EditorModel | undefined;
32
+ extensions?: Extension[] | undefined;
33
+ theme?: {
34
+ [selector: string]: StyleSpec;
35
+ } | undefined;
36
+ slots?: EditorSlots | undefined;
37
+ onKeyDown?: ((event: KeyboardEvent, info: CursorInfo) => void) | undefined;
38
+ } & Pick<React.HTMLAttributes<HTMLDivElement>, "onFocus" | "onBlur"> & React.RefAttributes<TextEditorRef>>;
39
+ //# sourceMappingURL=TextEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextEditor.d.ts","sourceRoot":"","sources":["../../../../../src/components/TextEditor/TextEditor.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAe,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,EACZ,KAAK,aAAa,EAMlB,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAO3C,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAEjE,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE;QACN,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;KAC/B,CAAC;IACF,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CAC9D,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;yBAND,aAAa,QAAQ,UAAU,KAAK,IAAI;0GAiF7D,CAAC"}
@@ -0,0 +1,32 @@
1
+ import '@dxosTheme';
2
+ import { HighlightStyle, StreamLanguage } from '@codemirror/language';
3
+ import React from 'react';
4
+ export declare const nameRegex: RegExp;
5
+ /**
6
+ * Simple Monaco language extension.
7
+ * https://github.com/codemirror/stream-parser/blob/main/test/test-stream-parser.ts
8
+ */
9
+ export declare const promptLanguage: StreamLanguage<{
10
+ count: number;
11
+ }>;
12
+ /**
13
+ * https://codemirror.net/examples/styling
14
+ * https://lezer.codemirror.net/docs/ref/#highlight
15
+ */
16
+ export declare const promptHighlightStyles: HighlightStyle;
17
+ declare const _default: {
18
+ component: React.ForwardRefExoticComponent<{
19
+ model?: import("../../model").EditorModel | undefined;
20
+ extensions?: import("@codemirror/state").Extension[] | undefined;
21
+ theme?: {
22
+ [selector: string]: import("style-mod").StyleSpec;
23
+ } | undefined;
24
+ slots?: import("../../model").EditorSlots | undefined;
25
+ onKeyDown?: ((event: React.KeyboardEvent<Element>, info: import("./TextEditor").CursorInfo) => void) | undefined;
26
+ } & Pick<React.HTMLAttributes<HTMLDivElement>, "onFocus" | "onBlur"> & React.RefAttributes<import("./TextEditor").TextEditorRef>>;
27
+ decorators: import("@storybook/react").Decorator[];
28
+ render: () => JSX.Element;
29
+ };
30
+ export default _default;
31
+ export declare const Default: {};
32
+ //# sourceMappingURL=TextEditor.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextEditor.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/TextEditor/TextEditor.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,OAAO,KAAmB,MAAM,OAAO,CAAC;AAUxC,eAAO,MAAM,SAAS,QAAgB,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,cAAc;WAAkC,MAAM;EAcjE,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB,gBAShC,CAAC;;;;;;;;;;;;;;AAuBH,wBAIE;AAEF,eAAO,MAAM,OAAO,IAAK,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type Extension } from '@codemirror/state';
2
+ import { type DecorationSet, MatchDecorator, ViewPlugin, type ViewUpdate } from '@codemirror/view';
3
+ export declare function hyperLinkExtension(): ViewPlugin<{
4
+ readonly decorator: MatchDecorator;
5
+ decorations: DecorationSet;
6
+ update(update: ViewUpdate): void;
7
+ }>;
8
+ export declare const hyperLinkStyle: Extension;
9
+ export declare const hyperlink: Extension;
10
+ //# sourceMappingURL=hyperlink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyperlink.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/hyperlink.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAEL,KAAK,aAAa,EAElB,cAAc,EACd,UAAU,EACV,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AA4C1B,wBAAgB,kBAAkB;wBAGR,cAAc;;mBAOnB,UAAU;GAwB9B;AAED,eAAO,MAAM,cAAc,WAYzB,CAAC;AAEH,eAAO,MAAM,SAAS,EAAE,SAAkD,CAAC"}
@@ -0,0 +1,9 @@
1
+ export type OnHyperlinkHover = (el: Element, url: string) => void;
2
+ /**
3
+ * https://codemirror.net/examples/tooltip
4
+ * https://codemirror.net/docs/ref/#view.hoverTooltip
5
+ * https://github.com/codemirror/view/blob/main/src/tooltip.ts
6
+ */
7
+ export declare const createHyperlinkTooltip: (onHover: OnHyperlinkHover, regexp?: RegExp) => import("@codemirror/state").Extension;
8
+ export declare const defaultHyperLinkTooltip: import("@codemirror/state").Extension;
9
+ //# sourceMappingURL=hyperlinkTooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyperlinkTooltip.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/hyperlinkTooltip.tsx"],"names":[],"mappings":"AAaA,MAAM,MAAM,gBAAgB,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,YAAa,gBAAgB,2DA0C5D,CAAC;AAGL,eAAO,MAAM,uBAAuB,uCAUlC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './hyperlink';
2
+ export * from './hyperlinkTooltip';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TextEditor/extensions/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { type StyleSpec } from 'style-mod';
2
+ export { tags } from '@lezer/highlight';
3
+ export * from './TextEditor';
4
+ export * from './extensions';
5
+ export * from './theme';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/TextEditor/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,cAAc,cAAc,CAAC;AAE7B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type StyleSpec } from 'style-mod';
2
+ /**
3
+ * https://codemirror.net/examples/styling
4
+ */
5
+ export declare const defaultStyles: {
6
+ [selector: string]: StyleSpec;
7
+ };
8
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../../../../src/components/TextEditor/theme.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAM3C;;GAEG;AAEH,eAAO,MAAM,aAAa,EAAE;IAC1B,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAgB/B,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from './Editor';
2
2
  export * from './Markdown';
3
3
  export * from './RichText';
4
+ export * from './TextEditor';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-editor",
3
- "version": "0.3.9-main.2b2db7f",
3
+ "version": "0.3.9-main.2dc53cf",
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",
@@ -27,6 +27,7 @@
27
27
  "@lezer/common": "^1.1.1",
28
28
  "@lezer/highlight": "^1.2.0",
29
29
  "@lezer/markdown": "^1.1.1",
30
+ "@phosphor-icons/react": "^2.0.5",
30
31
  "@replit/codemirror-vim": "^6.0.14",
31
32
  "@tiptap/core": "2.0.0-beta.220",
32
33
  "@tiptap/extension-collaboration": "2.0.0-beta.220",
@@ -43,19 +44,20 @@
43
44
  "prosemirror-model": "^1.19.0",
44
45
  "prosemirror-state": "^1.4.2",
45
46
  "prosemirror-view": "^1.30.1",
47
+ "style-mod": "^4.1.0",
46
48
  "y-codemirror.next": "^0.3.2",
47
49
  "y-prosemirror": "~1.0.20",
48
50
  "y-protocols": "^1.0.5",
49
51
  "yjs": "^13.6.10",
50
- "@dxos/debug": "0.3.9-main.2b2db7f",
51
- "@dxos/display-name": "0.3.9-main.2b2db7f",
52
- "@dxos/log": "0.3.9-main.2b2db7f",
53
- "@dxos/react-async": "0.3.9-main.2b2db7f",
54
- "@dxos/react-ui": "0.3.9-main.2b2db7f",
55
- "@dxos/react-ui-theme": "0.3.9-main.2b2db7f",
56
- "@dxos/text-model": "0.3.9-main.2b2db7f",
57
- "@dxos/util": "0.3.9-main.2b2db7f",
58
- "@dxos/protocols": "0.3.9-main.2b2db7f"
52
+ "@dxos/debug": "0.3.9-main.2dc53cf",
53
+ "@dxos/display-name": "0.3.9-main.2dc53cf",
54
+ "@dxos/log": "0.3.9-main.2dc53cf",
55
+ "@dxos/react-ui": "0.3.9-main.2dc53cf",
56
+ "@dxos/protocols": "0.3.9-main.2dc53cf",
57
+ "@dxos/react-async": "0.3.9-main.2dc53cf",
58
+ "@dxos/react-ui-theme": "0.3.9-main.2dc53cf",
59
+ "@dxos/util": "0.3.9-main.2dc53cf",
60
+ "@dxos/text-model": "0.3.9-main.2dc53cf"
59
61
  },
60
62
  "devDependencies": {
61
63
  "@codemirror/basic-setup": "^0.20.0",
@@ -65,16 +67,18 @@
65
67
  "@types/react-dom": "^18.0.6",
66
68
  "react": "^18.2.0",
67
69
  "react-dom": "^18.2.0",
68
- "@dxos/config": "0.3.9-main.2b2db7f",
69
- "@dxos/automerge": "0.3.9-main.2b2db7f",
70
- "@dxos/echo-typegen": "0.3.9-main.2b2db7f",
71
- "@dxos/react-client": "0.3.9-main.2b2db7f",
72
- "@dxos/echo-schema": "0.3.9-main.2b2db7f"
70
+ "@dxos/config": "0.3.9-main.2dc53cf",
71
+ "@dxos/echo-typegen": "0.3.9-main.2dc53cf",
72
+ "@dxos/react-client": "0.3.9-main.2dc53cf",
73
+ "@dxos/storybook-utils": "0.3.9-main.2dc53cf",
74
+ "@dxos/echo-schema": "0.3.9-main.2dc53cf",
75
+ "@dxos/automerge": "0.3.9-main.2dc53cf"
73
76
  },
74
77
  "peerDependencies": {
78
+ "@phosphor-icons/react": "^2.0.5",
75
79
  "react": "^18.2.0",
76
80
  "react-dom": "^18.2.0",
77
- "@dxos/react-client": "0.3.9-main.2b2db7f"
81
+ "@dxos/react-client": "0.3.9-main.2dc53cf"
78
82
  },
79
83
  "publishConfig": {
80
84
  "access": "public"
@@ -2,5 +2,5 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export { plugin } from './plugin';
5
+ export { plugin, reconcile } from './plugin';
6
6
  export { PatchSemaphore } from './PatchSemaphore';
@@ -8,8 +8,7 @@ import React, { useEffect, useRef, useState } from 'react';
8
8
 
9
9
  import { type Prop, next as automerge } from '@dxos/automerge/automerge';
10
10
 
11
- import { plugin as amgPlugin } from './automerge-plugin';
12
- import { reconcile } from './automerge-plugin/plugin';
11
+ import { plugin as amgPlugin, reconcile } from './automerge-plugin';
13
12
  import { Peer } from './demo';
14
13
 
15
14
  type EditorProps = {
@@ -11,12 +11,14 @@ import { TextObject, TextKind, useQuery, useSpace } from '@dxos/react-client/ech
11
11
  import { useIdentity } from '@dxos/react-client/halo';
12
12
  import { ClientDecorator, setupPeersInSpace, textGenerator, useDataGenerator } from '@dxos/react-client/testing';
13
13
  import { useId } from '@dxos/react-ui';
14
+ import { withTheme } from '@dxos/storybook-utils';
14
15
 
15
16
  import { Editor, type EditorProps } from './Editor';
16
17
  import { EditorDocument, types as schema } from '../../testing';
17
18
 
18
19
  export default {
19
20
  component: Editor,
21
+ decorators: [withTheme],
20
22
  };
21
23
 
22
24
  const Story = ({ spaceKey, ...params }: Pick<EditorProps, 'slots'> & { spaceKey: PublicKey }) => {
@@ -10,12 +10,14 @@ import { PublicKey } from '@dxos/react-client';
10
10
  import { TextKind } from '@dxos/react-client/echo';
11
11
  import { ClientDecorator, textGenerator, useDataGenerator } from '@dxos/react-client/testing';
12
12
  import { useId } from '@dxos/react-ui';
13
+ import { withTheme } from '@dxos/storybook-utils';
13
14
 
14
15
  import { MarkdownEditor } from './Markdown';
15
16
  import { Replicator, useYjsModel } from '../../testing';
16
17
 
17
18
  export default {
18
19
  component: MarkdownEditor,
20
+ decorators: [withTheme],
19
21
  };
20
22
 
21
23
  export const Default = {
@@ -15,7 +15,7 @@ import {
15
15
  import { languages } from '@codemirror/language-data';
16
16
  import { lintKeymap } from '@codemirror/lint';
17
17
  import { searchKeymap, highlightSelectionMatches } from '@codemirror/search';
18
- import { EditorState, StateField, type Text } from '@codemirror/state';
18
+ import { EditorState, type Extension, StateField, type Text } from '@codemirror/state';
19
19
  import { oneDarkHighlightStyle } from '@codemirror/theme-one-dark';
20
20
  import {
21
21
  keymap,
@@ -58,6 +58,7 @@ export type MarkdownEditorProps = {
58
58
  model?: EditorModel;
59
59
  slots?: EditorSlots;
60
60
  editorMode?: EditorMode;
61
+ extensions?: Extension[];
61
62
  onChange?: (content: string | Text) => void;
62
63
  };
63
64
 
@@ -68,7 +69,7 @@ export type MarkdownEditorRef = {
68
69
  };
69
70
 
70
71
  export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>(
71
- ({ model, slots = {}, editorMode, onChange }, forwardedRef) => {
72
+ ({ model, slots = {}, editorMode, extensions = [], onChange }, forwardedRef) => {
72
73
  const { id, content, provider, peer } = model ?? {};
73
74
  const { themeMode } = useThemeContext();
74
75
  const tabsterDOMAttribute = useFocusableGroup({ tabBehavior: 'limited' });
@@ -160,6 +161,9 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
160
161
 
161
162
  // Replication and awareness (incl. remote selection).
162
163
  ...(content instanceof YText ? [yCollab(content, provider?.awareness)] : []),
164
+
165
+ // Custom.
166
+ ...extensions,
163
167
  ],
164
168
  });
165
169
 
@@ -71,24 +71,28 @@ export const markdownTheme = {
71
71
  // color: '#ddd'
72
72
  // },
73
73
 
74
- '.dark & .cm-tooltip': {
74
+ '.cm-tooltip': {
75
+ backgroundColor: 'transparent',
75
76
  border: 'none',
76
- backgroundColor: tooltipBackground,
77
- },
78
- '.dark & .cm-tooltip .cm-tooltip-arrow:before': {
79
- borderTopColor: 'transparent',
80
- borderBottomColor: 'transparent',
81
- },
82
- '.dark & .cm-tooltip .cm-tooltip-arrow:after': {
83
- borderTopColor: tooltipBackground,
84
- borderBottomColor: tooltipBackground,
85
- },
86
- '.dark & .cm-tooltip-autocomplete': {
87
- '& > ul > li[aria-selected]': {
88
- backgroundColor: highlightBackground,
89
- color: ivory,
90
- },
91
77
  },
78
+ // '.dark & .cm-tooltip': {
79
+ // border: 'none',
80
+ // backgroundColor: tooltipBackground,
81
+ // },
82
+ // '.dark & .cm-tooltip .cm-tooltip-arrow:before': {
83
+ // borderTopColor: 'transparent',
84
+ // borderBottomColor: 'transparent',
85
+ // },
86
+ // '.dark & .cm-tooltip .cm-tooltip-arrow:after': {
87
+ // borderTopColor: tooltipBackground,
88
+ // borderBottomColor: tooltipBackground,
89
+ // },
90
+ // '.dark & .cm-tooltip-autocomplete': {
91
+ // '& > ul > li[aria-selected]': {
92
+ // backgroundColor: highlightBackground,
93
+ // color: ivory,
94
+ // },
95
+ // },
92
96
  '&.cm-focused': {
93
97
  outline: 'none',
94
98
  },
@@ -11,12 +11,14 @@ import { TextKind } from '@dxos/react-client/echo';
11
11
  import { ClientDecorator, textGenerator, useDataGenerator } from '@dxos/react-client/testing';
12
12
  import { useId } from '@dxos/react-ui';
13
13
  import { mx } from '@dxos/react-ui-theme';
14
+ import { withTheme } from '@dxos/storybook-utils';
14
15
 
15
16
  import { RichTextEditor, type RichTextEditorProps } from './RichText';
16
17
  import { Replicator, useYjsModel } from '../../testing';
17
18
 
18
19
  export default {
19
20
  component: RichTextEditor,
21
+ decorators: [withTheme],
20
22
  };
21
23
 
22
24
  export const Default = {
@@ -0,0 +1,83 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import '@dxosTheme';
6
+
7
+ import { HighlightStyle, StreamLanguage } from '@codemirror/language';
8
+ import { tags } from '@lezer/highlight';
9
+ import React, { useState } from 'react';
10
+
11
+ import { TextObject } from '@dxos/echo-schema';
12
+ import { fixedInsetFlexLayout, groupSurface, inputSurface, mx } from '@dxos/react-ui-theme';
13
+ import { withTheme } from '@dxos/storybook-utils';
14
+
15
+ import { TextEditor } from './TextEditor';
16
+ import { defaultHyperLinkTooltip, hyperlink } from './extensions';
17
+ import { useTextModel } from '../../model';
18
+
19
+ export const nameRegex = /\{([\w_]+)}/;
20
+
21
+ /**
22
+ * Simple Monaco language extension.
23
+ * https://github.com/codemirror/stream-parser/blob/main/test/test-stream-parser.ts
24
+ */
25
+ export const promptLanguage = StreamLanguage.define<{ count: number }>({
26
+ startState: () => ({ count: 0 }),
27
+
28
+ token: (stream, state) => {
29
+ state.count++;
30
+ if (stream.eatSpace()) {
31
+ return null;
32
+ }
33
+ if (stream.match(/^(<\w+>)/)) {
34
+ return 'tagName';
35
+ }
36
+ stream.next();
37
+ return null;
38
+ },
39
+ });
40
+
41
+ /**
42
+ * https://codemirror.net/examples/styling
43
+ * https://lezer.codemirror.net/docs/ref/#highlight
44
+ */
45
+ export const promptHighlightStyles = HighlightStyle.define([
46
+ {
47
+ tag: tags.tagName,
48
+ class: mx(
49
+ 'mr-1 p-1',
50
+ 'bg-neutral-100 dark:bg-neutral-900 text-black dark:text-white font-mono text-sm',
51
+ 'rounded border border-neutral-300 dark:border-neutral-700',
52
+ ),
53
+ },
54
+ ]);
55
+
56
+ const Story = () => {
57
+ const [item] = useState({
58
+ text: new TextObject(
59
+ '\n\n\nThis is all about [DXOS](https://dxos.org); read more [here](https://docs.dxos.org/guide/getting-started.html).\n\n\n',
60
+ ),
61
+ });
62
+
63
+ const model = useTextModel({ text: item.text });
64
+
65
+ return (
66
+ <div className={mx(fixedInsetFlexLayout, groupSurface, 'p-4 gap-4')}>
67
+ <TextEditor
68
+ model={model}
69
+ slots={{ root: { className: mx(inputSurface, 'p-2') } }}
70
+ extensions={[hyperlink, defaultHyperLinkTooltip]}
71
+ />
72
+ <pre>{JSON.stringify(model?.content?.toString(), null, 2)}</pre>
73
+ </div>
74
+ );
75
+ };
76
+
77
+ export default {
78
+ component: TextEditor,
79
+ decorators: [withTheme],
80
+ render: Story,
81
+ };
82
+
83
+ export const Default = {};
@@ -0,0 +1,130 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { closeBrackets } from '@codemirror/autocomplete';
6
+ import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
7
+ import { EditorState, type Extension } from '@codemirror/state';
8
+ import { oneDarkHighlightStyle } from '@codemirror/theme-one-dark';
9
+ import { EditorView, placeholder } from '@codemirror/view';
10
+ import React, {
11
+ type KeyboardEvent,
12
+ forwardRef,
13
+ useEffect,
14
+ useImperativeHandle,
15
+ useState,
16
+ useCallback,
17
+ type HTMLAttributes,
18
+ } from 'react';
19
+ import { type StyleSpec } from 'style-mod';
20
+ import { yCollab } from 'y-codemirror.next';
21
+
22
+ import { useThemeContext } from '@dxos/react-ui';
23
+ import { YText } from '@dxos/text-model';
24
+
25
+ import { defaultStyles } from './theme';
26
+ import { type EditorModel, type EditorSlots } from '../../model';
27
+
28
+ export type CursorInfo = {
29
+ from: number;
30
+ to: number;
31
+ line: number;
32
+ lines: number;
33
+ after?: string;
34
+ };
35
+
36
+ export type TextEditorRef = {
37
+ editor: HTMLDivElement | null;
38
+ state?: EditorState;
39
+ view?: EditorView;
40
+ };
41
+
42
+ export type TextEditorProps = {
43
+ model?: EditorModel;
44
+ extensions?: Extension[];
45
+ theme?: {
46
+ [selector: string]: StyleSpec;
47
+ };
48
+ slots?: EditorSlots;
49
+ onKeyDown?: (event: KeyboardEvent, info: CursorInfo) => void;
50
+ } & Pick<HTMLAttributes<HTMLDivElement>, 'onBlur' | 'onFocus'>;
51
+
52
+ /**
53
+ * Simple text editor.
54
+ */
55
+ export const TextEditor = forwardRef<TextEditorRef, TextEditorProps>(
56
+ ({ model, extensions = [], theme = defaultStyles, slots = {}, onKeyDown, ...props }, forwardedRef) => {
57
+ const { id, content } = model ?? {};
58
+ const { themeMode } = useThemeContext();
59
+
60
+ const [parent, setParent] = useState<HTMLDivElement | null>(null);
61
+ const [state, setState] = useState<EditorState>();
62
+ const [view, setView] = useState<EditorView>();
63
+
64
+ // TODO(burdon): The ref may be instantiated before the view is created.
65
+ useImperativeHandle(
66
+ forwardedRef,
67
+ () => {
68
+ return {
69
+ editor: parent,
70
+ state,
71
+ view,
72
+ };
73
+ },
74
+ [view],
75
+ );
76
+
77
+ useEffect(() => {
78
+ if (!parent) {
79
+ return;
80
+ }
81
+
82
+ view?.destroy();
83
+
84
+ const state = EditorState.create({
85
+ doc: content?.toString(),
86
+ extensions: [
87
+ bracketMatching(),
88
+ closeBrackets(),
89
+ placeholder(slots.editor?.placeholder ?? ''),
90
+ EditorView.lineWrapping,
91
+
92
+ // Themes.
93
+ EditorView.theme(theme),
94
+ ...(themeMode === 'dark'
95
+ ? [syntaxHighlighting(oneDarkHighlightStyle)]
96
+ : [syntaxHighlighting(defaultHighlightStyle)]),
97
+
98
+ // Replication.
99
+ ...(content instanceof YText ? [yCollab(content, undefined)] : []),
100
+
101
+ // Custom.
102
+ ...extensions,
103
+ ],
104
+ });
105
+
106
+ setState(state);
107
+ setView(new EditorView({ state, parent }));
108
+
109
+ return () => {
110
+ view?.destroy();
111
+ setView(undefined);
112
+ setState(undefined);
113
+ };
114
+ }, [parent, content, themeMode]);
115
+
116
+ const handleKeyDown = useCallback(
117
+ (event: KeyboardEvent) => {
118
+ if (view) {
119
+ const { head, from, to } = view.state.selection.ranges[0];
120
+ const { number } = view.state.doc.lineAt(head);
121
+ const after = view.state.sliceDoc(from);
122
+ onKeyDown?.(event, { from, to, line: number, lines: view.state.doc.lines, after });
123
+ }
124
+ },
125
+ [view],
126
+ );
127
+
128
+ return <div key={id} ref={setParent} {...slots.root} onKeyDown={handleKeyDown} {...props} />;
129
+ },
130
+ );