@dxos/plugin-markdown 0.6.8-main.046e6cf → 0.6.8-staging.77f93a3

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 (36) hide show
  1. package/dist/lib/browser/{DocumentEditor-VMHFHWOQ.mjs → DocumentEditor-DJ4K24MQ.mjs} +3 -3
  2. package/dist/lib/browser/{MarkdownEditor-KYUQ45PC.mjs → MarkdownEditor-KQWSKW2I.mjs} +2 -2
  3. package/dist/lib/browser/{chunk-6ZL2GJCQ.mjs → chunk-4UK23TZF.mjs} +6 -19
  4. package/dist/lib/browser/chunk-4UK23TZF.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-PZDW7KVZ.mjs → chunk-E5LKC775.mjs} +44 -18
  6. package/dist/lib/browser/chunk-E5LKC775.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +5 -5
  8. package/dist/lib/browser/index.mjs.map +2 -2
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/node/{DocumentEditor-CUKHGS5R.cjs → DocumentEditor-2YZ2DBYL.cjs} +7 -7
  11. package/dist/lib/node/{DocumentEditor-CUKHGS5R.cjs.map → DocumentEditor-2YZ2DBYL.cjs.map} +2 -2
  12. package/dist/lib/node/{MarkdownEditor-GGFCD26C.cjs → MarkdownEditor-O4FJQIFS.cjs} +7 -7
  13. package/dist/lib/node/{MarkdownEditor-GGFCD26C.cjs.map → MarkdownEditor-O4FJQIFS.cjs.map} +2 -2
  14. package/dist/lib/node/{chunk-IUQ2SKGY.cjs → chunk-DJ352NAA.cjs} +10 -23
  15. package/dist/lib/node/chunk-DJ352NAA.cjs.map +7 -0
  16. package/dist/lib/node/{chunk-TO3FCKT7.cjs → chunk-JSS2PWPA.cjs} +44 -18
  17. package/dist/lib/node/chunk-JSS2PWPA.cjs.map +7 -0
  18. package/dist/lib/node/index.cjs +12 -12
  19. package/dist/lib/node/index.cjs.map +2 -2
  20. package/dist/lib/node/meta.json +1 -1
  21. package/dist/types/src/components/DocumentEditor.d.ts.map +1 -1
  22. package/dist/types/src/components/MarkdownEditor.d.ts +2 -3
  23. package/dist/types/src/components/MarkdownEditor.d.ts.map +1 -1
  24. package/dist/types/src/components/MarkdownEditor.stories.d.ts +1 -1
  25. package/dist/types/src/components/index.d.ts +1 -1
  26. package/dist/types/src/components/index.d.ts.map +1 -1
  27. package/package.json +28 -28
  28. package/src/MarkdownPlugin.tsx +1 -1
  29. package/src/components/DocumentEditor.tsx +9 -12
  30. package/src/components/MarkdownEditor.tsx +36 -23
  31. package/dist/lib/browser/chunk-6ZL2GJCQ.mjs.map +0 -7
  32. package/dist/lib/browser/chunk-PZDW7KVZ.mjs.map +0 -7
  33. package/dist/lib/node/chunk-IUQ2SKGY.cjs.map +0 -7
  34. package/dist/lib/node/chunk-TO3FCKT7.cjs.map +0 -7
  35. /package/dist/lib/browser/{DocumentEditor-VMHFHWOQ.mjs.map → DocumentEditor-DJ4K24MQ.mjs.map} +0 -0
  36. /package/dist/lib/browser/{MarkdownEditor-KYUQ45PC.mjs.map → MarkdownEditor-KQWSKW2I.mjs.map} +0 -0
@@ -2,16 +2,17 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { type EditorView } from '@codemirror/view';
6
- import React, { useMemo, useEffect } from 'react';
5
+ import { EditorView } from '@codemirror/view';
6
+ import React, { useMemo, useEffect, useCallback } from 'react';
7
7
 
8
8
  import {
9
+ type FileInfo,
9
10
  LayoutAction,
11
+ type LayoutCoordinate,
10
12
  useResolvePlugin,
11
13
  useIntentResolver,
12
14
  parseLayoutPlugin,
13
- type FileInfo,
14
- type LayoutCoordinate,
15
+ useIntentDispatcher,
15
16
  } from '@dxos/app-framework';
16
17
  import { parseAttentionPlugin } from '@dxos/plugin-attention';
17
18
  import { useThemeContext, useTranslation } from '@dxos/react-ui';
@@ -27,7 +28,6 @@ import {
27
28
  createThemeExtensions,
28
29
  dropFile,
29
30
  processAction,
30
- scrollThreadIntoView,
31
31
  useActionHandler,
32
32
  useCommentState,
33
33
  useCommentClickListener,
@@ -35,6 +35,8 @@ import {
35
35
  useTextEditor,
36
36
  editorContent,
37
37
  editorGutter,
38
+ Cursor,
39
+ setSelection,
38
40
  } from '@dxos/react-ui-editor';
39
41
  import { sectionToolbarLayout } from '@dxos/react-ui-stack';
40
42
  import { textBlockWidth, focusRing, mx } from '@dxos/react-ui-theme';
@@ -59,9 +61,8 @@ export type MarkdownEditorProps = {
59
61
  toolbar?: boolean;
60
62
  viewMode?: EditorViewMode;
61
63
  onViewModeChange?: (id: string, mode: EditorViewMode) => void;
62
- onCommentSelect?: (id: string) => void;
63
64
  onFileUpload?: (file: File) => Promise<FileInfo | undefined>;
64
- } & Pick<UseTextEditorProps, 'initialValue' | 'selection' | 'scrollTo' | 'extensions'> &
65
+ } & Pick<UseTextEditorProps, 'initialValue' | 'scrollTo' | 'selection' | 'extensions'> &
65
66
  Partial<Pick<MarkdownPluginState, 'extensionProviders'>>;
66
67
 
67
68
  export const MarkdownEditor = ({
@@ -70,17 +71,17 @@ export const MarkdownEditor = ({
70
71
  initialValue,
71
72
  extensions,
72
73
  extensionProviders,
73
- scrollTo,
74
74
  scrollPastEnd,
75
+ scrollTo,
75
76
  selection,
76
77
  toolbar,
77
78
  viewMode,
78
- onCommentSelect,
79
79
  onFileUpload,
80
80
  onViewModeChange,
81
81
  }: MarkdownEditorProps) => {
82
82
  const { t } = useTranslation(MARKDOWN_PLUGIN);
83
83
  const { themeMode } = useThemeContext();
84
+ const dispatch = useIntentDispatcher();
84
85
  const attentionPlugin = useResolvePlugin(parseAttentionPlugin);
85
86
  const layoutPlugin = useResolvePlugin(parseLayoutPlugin);
86
87
  const attended = Array.from(attentionPlugin?.provides.attention?.attended ?? []);
@@ -92,23 +93,35 @@ export const MarkdownEditor = ({
92
93
 
93
94
  // TODO(Zan): Move these into thread plugin as well?
94
95
  const [commentsState, commentObserver] = useCommentState();
95
- const commentClickObserver = useCommentClickListener((id) => {
96
- onCommentSelect?.(id);
97
- });
96
+ const onCommentClick = useCallback(() => {
97
+ void dispatch({ action: LayoutAction.SET_LAYOUT, data: { element: 'complementary', state: true } });
98
+ }, [dispatch]);
99
+ const commentClickObserver = useCommentClickListener(onCommentClick);
98
100
 
99
- // Focus comment.
101
+ // Focus the space that references the comment.
100
102
  useIntentResolver(MARKDOWN_PLUGIN, ({ action, data }) => {
101
103
  switch (action) {
104
+ // TODO(burdon): Use fully qualified ids everywhere.
102
105
  case LayoutAction.SCROLL_INTO_VIEW: {
103
- if (editorView) {
104
- // TODO(Zan): Try catch this. Fails when thread plugin not present?
105
- scrollThreadIntoView(editorView, data?.id);
106
- if (data?.id === id) {
107
- editorView.scrollDOM
108
- .closest('[data-attendable-id]')
109
- ?.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'start' });
106
+ if (editorView && data?.id === id && data?.cursor) {
107
+ // TODO(burdon): We need typed intents.
108
+ const range = Cursor.getRangeFromCursor(editorView.state, data.cursor);
109
+ if (range?.from) {
110
+ const selection = editorView.state.selection.main.from !== range.from ? { anchor: range.from } : undefined;
111
+ const effects = [
112
+ // NOTE: This does not use the DOM scrollIntoView function.
113
+ EditorView.scrollIntoView(range.from, { y: 'start', yMargin: 96 }),
114
+ ];
115
+ if (selection) {
116
+ // Update the editor selection to get bi-directional highlighting.
117
+ effects.push(setSelection.of({ current: id }));
118
+ }
119
+
120
+ editorView.dispatch({
121
+ effects,
122
+ selection: selection ? { anchor: range.from } : undefined,
123
+ });
110
124
  }
111
- return undefined;
112
125
  }
113
126
  break;
114
127
  }
@@ -140,8 +153,8 @@ export const MarkdownEditor = ({
140
153
  ].filter(nonNullable),
141
154
  ...(role !== 'section' && {
142
155
  id,
143
- selection,
144
156
  scrollTo,
157
+ selection,
145
158
  // TODO(wittjosiah): Autofocus based on layout is racey.
146
159
  autoFocus: layoutPlugin?.provides.layout ? layoutPlugin?.provides.layout.scrollIntoView === id : true,
147
160
  moveToEndOfLine: true,
@@ -183,7 +196,7 @@ export const MarkdownEditor = ({
183
196
  })}
184
197
  >
185
198
  {toolbar && (
186
- <div role='none' className={mx('flex shrink-0 justify-center', attentionFragment)}>
199
+ <div role='none' className={mx('flex shrink-0 justify-center overflow-x-auto', attentionFragment)}>
187
200
  <Toolbar.Root
188
201
  classNames={
189
202
  role === 'section'
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/components/DocumentEditor.tsx", "../../../src/util.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { EditorView } from '@codemirror/view';\nimport React, { useEffect, useMemo } from 'react';\n\nimport { useResolvePlugin, parseFileManagerPlugin, useIntentDispatcher } from '@dxos/app-framework';\nimport { createDocAccessor, fullyQualifiedId, getSpace } from '@dxos/react-client/echo';\nimport { useIdentity } from '@dxos/react-client/halo';\nimport {\n createDataExtensions,\n listener,\n localStorageStateStoreAdapter,\n state,\n type Extension,\n} from '@dxos/react-ui-editor';\n\nimport MarkdownEditor, { type MarkdownEditorProps } from './MarkdownEditor';\nimport { createBaseExtensions } from '../extensions';\nimport { type DocumentType, type MarkdownPluginState, type MarkdownSettingsProps } from '../types';\nimport { getFallbackName, setFallbackName } from '../util';\n\ntype DocumentEditorProps = {\n document: DocumentType;\n settings: MarkdownSettingsProps;\n} & Omit<MarkdownEditorProps, 'id' | 'inputMode' | 'toolbar' | 'extensions'> &\n Pick<MarkdownPluginState, 'extensionProviders'>;\n\n/**\n * Editor for a `DocumentType`.\n */\nconst DocumentEditor = ({\n document: doc,\n extensionProviders = [],\n viewMode,\n settings,\n ...props\n}: DocumentEditorProps) => {\n const space = getSpace(doc);\n const identity = useIdentity();\n const dispatch = useIntentDispatcher();\n\n const baseExtensions = useMemo(() => {\n // TODO(wittjosiah): Autocomplete is not working and this query is causing performance issues.\n // const query = space?.db.query(Filter.schema(DocumentType));\n // query?.subscribe();\n return createBaseExtensions({\n viewMode,\n settings,\n document: doc,\n dispatch,\n // query,\n });\n }, [doc, viewMode, dispatch, settings, settings.folding, settings.numberedHeadings]);\n\n const providerExtensions = useMemo(\n () =>\n extensionProviders.reduce((acc: Extension[], provider) => {\n const provided = typeof provider === 'function' ? provider({ document: doc }) : provider;\n acc.push(...provided);\n return acc;\n }, []),\n [extensionProviders],\n );\n\n const extensions = useMemo(\n () => [\n // NOTE: Data extensions must be first so that automerge is updated before other extensions compute their state.\n createDataExtensions({\n id: doc.id,\n text: doc.content && createDocAccessor(doc.content, ['content']),\n space,\n identity,\n }),\n state(localStorageStateStoreAdapter),\n listener({\n onChange: (text) => {\n setFallbackName(doc, text);\n },\n }),\n providerExtensions,\n baseExtensions,\n ],\n [doc, doc.content, space, baseExtensions, providerExtensions, identity],\n );\n\n const initialValue = useMemo(() => doc.content?.content, [doc.content]);\n\n // Migrate gradually to `fallbackName`.\n useEffect(() => {\n if (!doc.fallbackName && doc.content?.content) {\n doc.fallbackName = getFallbackName(doc.content.content);\n }\n }, [doc, doc.content]);\n\n const { scrollTo /*, selection */ } = useMemo(() => {\n const { scrollTo, selection } = localStorageStateStoreAdapter.getState(doc.id) ?? {};\n return {\n scrollTo: scrollTo?.from ? EditorView.scrollIntoView(scrollTo.from, { y: 'start', yMargin: 0 }) : undefined,\n selection,\n };\n }, [doc]);\n\n const fileManagerPlugin = useResolvePlugin(parseFileManagerPlugin);\n\n const handleFileUpload = useMemo(() => {\n if (space === undefined) {\n return undefined;\n }\n\n if (fileManagerPlugin?.provides.file.upload === undefined) {\n return undefined;\n }\n\n return async (file: File) => {\n return fileManagerPlugin?.provides?.file?.upload?.(file, space);\n };\n }, [fileManagerPlugin, space]);\n\n return (\n <MarkdownEditor\n id={fullyQualifiedId(doc)}\n initialValue={initialValue}\n extensions={extensions}\n scrollTo={scrollTo}\n // TODO(wittjosiah): Ensure selection is within the document.\n // selection={selection}\n onFileUpload={handleFileUpload}\n inputMode={settings.editorInputMode}\n toolbar={settings.toolbar}\n viewMode={viewMode}\n {...props}\n />\n );\n};\n\nexport default DocumentEditor;\n\nexport type DocumentEditor = typeof DocumentEditor;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Plugin } from '@dxos/app-framework';\nimport { debounce } from '@dxos/async';\nimport { type TypedObjectSerializer } from '@dxos/plugin-space/types';\nimport { create, createEchoObject, isEchoObject, loadObjectReferences } from '@dxos/react-client/echo';\n\nimport { DocumentType, type MarkdownProperties, type MarkdownExtensionProvides, TextType } from './types';\n\nexport const isMarkdownProperties = (data: unknown): data is MarkdownProperties =>\n isEchoObject(data)\n ? true\n : data && typeof data === 'object'\n ? 'title' in data && typeof data.title === 'string'\n : false;\n\ntype MarkdownExtensionPlugin = Plugin<MarkdownExtensionProvides>;\n\nexport const markdownExtensionPlugins = (plugins: Plugin[]): MarkdownExtensionPlugin[] => {\n return (plugins as MarkdownExtensionPlugin[]).filter((plugin) => Boolean(plugin.provides?.markdown));\n};\n\nconst nonTitleChars = /[^\\w ]/g;\n\nexport const getFallbackName = (content: string) => {\n return content.substring(0, 31).split('\\n')[0].replaceAll(nonTitleChars, '').trim();\n};\n\nexport const setFallbackName = debounce((doc: DocumentType, content: string) => {\n const name = getFallbackName(content);\n if (doc.fallbackName !== name) {\n doc.fallbackName = name;\n }\n}, 200);\n\nexport const serializer: TypedObjectSerializer<DocumentType> = {\n serialize: async ({ object }): Promise<string> => {\n const content = await loadObjectReferences(object, (doc) => doc.content);\n return JSON.stringify({ name: object.name, content: content.content });\n },\n\n deserialize: async ({ content: serialized }) => {\n const { name, content } = JSON.parse(serialized);\n return createEchoObject(create(DocumentType, { name, content: create(TextType, { content }), threads: [] }));\n },\n};\n"],
5
- "mappings": "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",
6
- "names": ["EditorView", "React", "useEffect", "useMemo", "useResolvePlugin", "parseFileManagerPlugin", "useIntentDispatcher", "createDocAccessor", "fullyQualifiedId", "getSpace", "useIdentity", "createDataExtensions", "listener", "localStorageStateStoreAdapter", "state", "debounce", "create", "createEchoObject", "isEchoObject", "loadObjectReferences", "isMarkdownProperties", "data", "isEchoObject", "title", "markdownExtensionPlugins", "plugins", "filter", "plugin", "Boolean", "provides", "markdown", "nonTitleChars", "getFallbackName", "content", "substring", "split", "replaceAll", "trim", "setFallbackName", "debounce", "doc", "name", "fallbackName", "serializer", "serialize", "object", "loadObjectReferences", "JSON", "stringify", "deserialize", "serialized", "parse", "createEchoObject", "create", "DocumentType", "TextType", "threads", "DocumentEditor", "document", "doc", "extensionProviders", "viewMode", "settings", "props", "space", "getSpace", "identity", "useIdentity", "dispatch", "useIntentDispatcher", "baseExtensions", "useMemo", "createBaseExtensions", "folding", "numberedHeadings", "providerExtensions", "reduce", "acc", "provider", "provided", "push", "extensions", "createDataExtensions", "id", "text", "content", "createDocAccessor", "state", "localStorageStateStoreAdapter", "listener", "onChange", "setFallbackName", "initialValue", "useEffect", "fallbackName", "getFallbackName", "scrollTo", "selection", "getState", "from", "EditorView", "scrollIntoView", "y", "yMargin", "undefined", "fileManagerPlugin", "useResolvePlugin", "parseFileManagerPlugin", "handleFileUpload", "provides", "file", "upload", "MarkdownEditor", "fullyQualifiedId", "onFileUpload", "inputMode", "editorInputMode", "toolbar"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/components/MarkdownEditor.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\nimport React, { useMemo, useEffect } from 'react';\n\nimport {\n LayoutAction,\n useResolvePlugin,\n useIntentResolver,\n parseLayoutPlugin,\n type FileInfo,\n type LayoutCoordinate,\n} from '@dxos/app-framework';\nimport { parseAttentionPlugin } from '@dxos/plugin-attention';\nimport { useThemeContext, useTranslation } from '@dxos/react-ui';\nimport {\n type Action,\n type DNDOptions,\n type EditorViewMode,\n type EditorInputMode,\n type UseTextEditorProps,\n Toolbar,\n createBasicExtensions,\n createMarkdownExtensions,\n createThemeExtensions,\n dropFile,\n processAction,\n scrollThreadIntoView,\n useActionHandler,\n useCommentState,\n useCommentClickListener,\n useFormattingState,\n useTextEditor,\n editorContent,\n editorGutter,\n} from '@dxos/react-ui-editor';\nimport { sectionToolbarLayout } from '@dxos/react-ui-stack';\nimport { textBlockWidth, focusRing, mx } from '@dxos/react-ui-theme';\nimport { nonNullable } from '@dxos/util';\n\nimport { MARKDOWN_PLUGIN } from '../meta';\nimport type { MarkdownPluginState } from '../types';\n\nconst attentionFragment = mx(\n 'group-focus-within/editor:attention-surface group-[[aria-current]]/editor:attention-surface',\n 'group-focus-within/editor:separator-separator',\n);\n\nconst DEFAULT_VIEW_MODE: EditorViewMode = 'preview';\n\nexport type MarkdownEditorProps = {\n id: string;\n coordinate?: LayoutCoordinate;\n inputMode?: EditorInputMode;\n role?: string;\n scrollPastEnd?: boolean;\n toolbar?: boolean;\n viewMode?: EditorViewMode;\n onViewModeChange?: (id: string, mode: EditorViewMode) => void;\n onCommentSelect?: (id: string) => void;\n onFileUpload?: (file: File) => Promise<FileInfo | undefined>;\n} & Pick<UseTextEditorProps, 'initialValue' | 'selection' | 'scrollTo' | 'extensions'> &\n Partial<Pick<MarkdownPluginState, 'extensionProviders'>>;\n\nexport const MarkdownEditor = ({\n id,\n role = 'article',\n initialValue,\n extensions,\n extensionProviders,\n scrollTo,\n scrollPastEnd,\n selection,\n toolbar,\n viewMode,\n onCommentSelect,\n onFileUpload,\n onViewModeChange,\n}: MarkdownEditorProps) => {\n const { t } = useTranslation(MARKDOWN_PLUGIN);\n const { themeMode } = useThemeContext();\n const attentionPlugin = useResolvePlugin(parseAttentionPlugin);\n const layoutPlugin = useResolvePlugin(parseLayoutPlugin);\n const attended = Array.from(attentionPlugin?.provides.attention?.attended ?? []);\n const isDirectlyAttended = attended.length === 1 && attended[0] === id;\n const [formattingState, formattingObserver] = useFormattingState();\n\n // Extensions from other plugins.\n const providerExtensions = useMemo(() => extensionProviders?.map((provider) => provider({})), [extensionProviders]);\n\n // TODO(Zan): Move these into thread plugin as well?\n const [commentsState, commentObserver] = useCommentState();\n const commentClickObserver = useCommentClickListener((id) => {\n onCommentSelect?.(id);\n });\n\n // Focus comment.\n useIntentResolver(MARKDOWN_PLUGIN, ({ action, data }) => {\n switch (action) {\n case LayoutAction.SCROLL_INTO_VIEW: {\n if (editorView) {\n // TODO(Zan): Try catch this. Fails when thread plugin not present?\n scrollThreadIntoView(editorView, data?.id);\n if (data?.id === id) {\n editorView.scrollDOM\n .closest('[data-attendable-id]')\n ?.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'start' });\n }\n return undefined;\n }\n break;\n }\n }\n });\n\n const {\n parentRef,\n view: editorView,\n focusAttributes,\n } = useTextEditor(\n () => ({\n initialValue,\n extensions: [\n formattingObserver,\n commentObserver,\n commentClickObserver,\n createBasicExtensions({\n readonly: viewMode === 'readonly',\n placeholder: t('editor placeholder'),\n scrollPastEnd: role === 'section' ? false : scrollPastEnd,\n }),\n createMarkdownExtensions({ themeMode }),\n createThemeExtensions({ themeMode, slots: { content: { className: editorContent } } }),\n editorGutter,\n role !== 'section' && onFileUpload ? dropFile({ onDrop: handleDrop }) : [],\n providerExtensions,\n extensions,\n ].filter(nonNullable),\n ...(role !== 'section' && {\n id,\n selection,\n scrollTo,\n // TODO(wittjosiah): Autofocus based on layout is racey.\n autoFocus: layoutPlugin?.provides.layout ? layoutPlugin?.provides.layout.scrollIntoView === id : true,\n moveToEndOfLine: true,\n }),\n }),\n [id, initialValue, formattingObserver, viewMode, themeMode, extensions, providerExtensions],\n );\n\n useTest(editorView);\n\n // Toolbar handler.\n const handleToolbarAction = useActionHandler(editorView);\n const handleAction = (action: Action) => {\n if (action.type === 'view-mode') {\n onViewModeChange?.(id, action.data);\n }\n\n handleToolbarAction?.(action);\n };\n\n // Drag files.\n const handleDrop: DNDOptions['onDrop'] = async (view, { files }) => {\n const file = files[0];\n const info = file && onFileUpload ? await onFileUpload(file) : undefined;\n if (info) {\n processAction(view, { type: 'image', data: info.url });\n }\n };\n\n return (\n <div\n role='none'\n // TODO(burdon): Move role logic out of here (see sheet, table, sketch, etc.)\n {...(role === 'section'\n ? { className: 'flex flex-col' }\n : {\n className: 'contents group/editor',\n ...(isDirectlyAttended && { 'aria-current': 'location' }),\n })}\n >\n {toolbar && (\n <div role='none' className={mx('flex shrink-0 justify-center', attentionFragment)}>\n <Toolbar.Root\n classNames={\n role === 'section'\n ? ['z-[2] group-focus-within/section:visible', !attended && 'invisible', sectionToolbarLayout]\n : [\n textBlockWidth,\n 'group-focus-within/editor:separator-separator group-[[aria-current]]/editor:separator-separator',\n ]\n }\n state={formattingState && { ...formattingState, ...commentsState }}\n onAction={handleAction}\n >\n <Toolbar.Markdown />\n {onFileUpload && <Toolbar.Custom onUpload={onFileUpload} />}\n <Toolbar.Separator />\n <Toolbar.View mode={viewMode ?? DEFAULT_VIEW_MODE} />\n <Toolbar.Actions />\n </Toolbar.Root>\n </div>\n )}\n <div\n role='none'\n ref={parentRef}\n data-testid='composer.markdownRoot'\n data-toolbar={toolbar ? 'enabled' : 'disabled'}\n className={\n // TODO(burdon): Factor out margin for focus.\n role === 'section'\n ? mx('flex flex-col flex-1 min-bs-[12rem] mt-[2px]', focusRing)\n : mx(\n 'flex is-full bs-full overflow-hidden',\n focusRing,\n attentionFragment,\n 'focus-visible:ring-inset',\n 'data-[toolbar=disabled]:pbs-2 data-[toolbar=disabled]:row-span-2',\n )\n }\n {...focusAttributes}\n />\n </div>\n );\n};\n\n// Expose editor view for playwright tests.\n// TODO(wittjosiah): Find a better way to expose this or find a way to limit it to test runs.\nconst useTest = (view?: EditorView) => {\n useEffect(() => {\n const composer = (window as any).composer;\n if (composer) {\n composer.editorView = view;\n }\n }, [view]);\n};\n\nexport default MarkdownEditor;\n"],
5
- "mappings": "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",
6
- "names": ["React", "useMemo", "useEffect", "LayoutAction", "useResolvePlugin", "useIntentResolver", "parseLayoutPlugin", "parseAttentionPlugin", "useThemeContext", "useTranslation", "Toolbar", "createBasicExtensions", "createMarkdownExtensions", "createThemeExtensions", "dropFile", "processAction", "scrollThreadIntoView", "useActionHandler", "useCommentState", "useCommentClickListener", "useFormattingState", "useTextEditor", "editorContent", "editorGutter", "sectionToolbarLayout", "textBlockWidth", "focusRing", "mx", "nonNullable", "attentionFragment", "mx", "DEFAULT_VIEW_MODE", "MarkdownEditor", "id", "role", "initialValue", "extensions", "extensionProviders", "scrollTo", "scrollPastEnd", "selection", "toolbar", "viewMode", "onCommentSelect", "onFileUpload", "onViewModeChange", "t", "useTranslation", "MARKDOWN_PLUGIN", "themeMode", "useThemeContext", "attentionPlugin", "useResolvePlugin", "parseAttentionPlugin", "layoutPlugin", "parseLayoutPlugin", "attended", "Array", "from", "provides", "attention", "isDirectlyAttended", "length", "formattingState", "formattingObserver", "useFormattingState", "providerExtensions", "useMemo", "map", "provider", "commentsState", "commentObserver", "useCommentState", "commentClickObserver", "useCommentClickListener", "useIntentResolver", "action", "data", "LayoutAction", "SCROLL_INTO_VIEW", "editorView", "scrollThreadIntoView", "scrollDOM", "closest", "scrollIntoView", "behavior", "inline", "block", "undefined", "parentRef", "view", "focusAttributes", "useTextEditor", "createBasicExtensions", "readonly", "placeholder", "createMarkdownExtensions", "createThemeExtensions", "slots", "content", "className", "editorContent", "editorGutter", "dropFile", "onDrop", "handleDrop", "filter", "nonNullable", "autoFocus", "layout", "moveToEndOfLine", "useTest", "handleToolbarAction", "useActionHandler", "handleAction", "type", "files", "file", "info", "processAction", "url", "div", "Toolbar", "Root", "classNames", "sectionToolbarLayout", "textBlockWidth", "state", "onAction", "Markdown", "Custom", "onUpload", "Separator", "View", "mode", "Actions", "ref", "data-testid", "data-toolbar", "focusRing", "useEffect", "composer", "window"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/components/DocumentEditor.tsx", "../../../src/util.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { EditorView } from '@codemirror/view';\nimport React, { useEffect, useMemo } from 'react';\n\nimport { useResolvePlugin, parseFileManagerPlugin, useIntentDispatcher } from '@dxos/app-framework';\nimport { createDocAccessor, fullyQualifiedId, getSpace } from '@dxos/react-client/echo';\nimport { useIdentity } from '@dxos/react-client/halo';\nimport {\n createDataExtensions,\n listener,\n localStorageStateStoreAdapter,\n state,\n type Extension,\n} from '@dxos/react-ui-editor';\n\nimport MarkdownEditor, { type MarkdownEditorProps } from './MarkdownEditor';\nimport { createBaseExtensions } from '../extensions';\nimport { type DocumentType, type MarkdownPluginState, type MarkdownSettingsProps } from '../types';\nimport { getFallbackName, setFallbackName } from '../util';\n\ntype DocumentEditorProps = {\n document: DocumentType;\n settings: MarkdownSettingsProps;\n} & Omit<MarkdownEditorProps, 'id' | 'inputMode' | 'toolbar' | 'extensions'> &\n Pick<MarkdownPluginState, 'extensionProviders'>;\n\n/**\n * Editor for a `DocumentType`.\n */\nconst DocumentEditor = ({\n document: doc,\n extensionProviders = [],\n viewMode,\n settings,\n ...props\n}: DocumentEditorProps) => {\n const space = getSpace(doc);\n const identity = useIdentity();\n const dispatch = useIntentDispatcher();\n\n const baseExtensions = useMemo(() => {\n // TODO(wittjosiah): Autocomplete is not working and this query is causing performance issues.\n // const query = space?.db.query(Filter.schema(DocumentType));\n // query?.subscribe();\n return createBaseExtensions({\n viewMode,\n settings,\n document: doc,\n dispatch,\n // query,\n });\n }, [doc, viewMode, dispatch, settings, settings.folding, settings.numberedHeadings]);\n\n const providerExtensions = useMemo(\n () =>\n extensionProviders.reduce((acc: Extension[], provider) => {\n const provided = typeof provider === 'function' ? provider({ document: doc }) : provider;\n acc.push(...provided);\n return acc;\n }, []),\n [extensionProviders],\n );\n\n const extensions = useMemo(\n () => [\n // NOTE: Data extensions must be first so that automerge is updated before other extensions compute their state.\n createDataExtensions({\n id: doc.id,\n text: doc.content && createDocAccessor(doc.content, ['content']),\n space,\n identity,\n }),\n state(localStorageStateStoreAdapter),\n listener({\n onChange: (text) => {\n setFallbackName(doc, text);\n },\n }),\n providerExtensions,\n baseExtensions,\n ],\n [doc, doc.content, space, baseExtensions, providerExtensions, identity],\n );\n\n const initialValue = useMemo(() => doc.content?.content, [doc.content]);\n\n // Migrate gradually to `fallbackName`.\n useEffect(() => {\n if (!doc.fallbackName && doc.content?.content) {\n doc.fallbackName = getFallbackName(doc.content.content);\n }\n }, [doc, doc.content]);\n\n const { scrollTo /*, selection */ } = useMemo(() => {\n const { scrollTo, selection } = localStorageStateStoreAdapter.getState(doc.id) ?? {};\n return {\n scrollTo: scrollTo?.from ? EditorView.scrollIntoView(scrollTo.from, { y: 'start', yMargin: 0 }) : undefined,\n selection,\n };\n }, [doc]);\n\n const fileManagerPlugin = useResolvePlugin(parseFileManagerPlugin);\n\n const handleFileUpload = useMemo(() => {\n if (space === undefined) {\n return undefined;\n }\n\n if (fileManagerPlugin?.provides.file.upload === undefined) {\n return undefined;\n }\n\n return async (file: File) => {\n return fileManagerPlugin?.provides?.file?.upload?.(file, space);\n };\n }, [fileManagerPlugin, space]);\n\n return (\n <MarkdownEditor\n id={fullyQualifiedId(doc)}\n initialValue={initialValue}\n extensions={extensions}\n scrollTo={scrollTo}\n // TODO(wittjosiah): Ensure selection is within the document.\n // selection={selection}\n onFileUpload={handleFileUpload}\n inputMode={settings.editorInputMode}\n toolbar={settings.toolbar}\n viewMode={viewMode}\n {...props}\n />\n );\n};\n\nexport default DocumentEditor;\n\nexport type DocumentEditor = typeof DocumentEditor;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Plugin } from '@dxos/app-framework';\nimport { debounce } from '@dxos/async';\nimport { type TypedObjectSerializer } from '@dxos/plugin-space/types';\nimport { create, createEchoObject, isEchoObject, loadObjectReferences } from '@dxos/react-client/echo';\n\nimport { DocumentType, type MarkdownProperties, type MarkdownExtensionProvides, TextType } from './types';\n\nexport const isMarkdownProperties = (data: unknown): data is MarkdownProperties =>\n isEchoObject(data)\n ? true\n : data && typeof data === 'object'\n ? 'title' in data && typeof data.title === 'string'\n : false;\n\ntype MarkdownExtensionPlugin = Plugin<MarkdownExtensionProvides>;\n\nexport const markdownExtensionPlugins = (plugins: Plugin[]): MarkdownExtensionPlugin[] => {\n return (plugins as MarkdownExtensionPlugin[]).filter((plugin) => Boolean(plugin.provides?.markdown));\n};\n\nconst nonTitleChars = /[^\\w ]/g;\n\nexport const getFallbackName = (content: string) => {\n return content.substring(0, 31).split('\\n')[0].replaceAll(nonTitleChars, '').trim();\n};\n\nexport const setFallbackName = debounce((doc: DocumentType, content: string) => {\n const name = getFallbackName(content);\n if (doc.fallbackName !== name) {\n doc.fallbackName = name;\n }\n}, 200);\n\nexport const serializer: TypedObjectSerializer<DocumentType> = {\n serialize: async ({ object }): Promise<string> => {\n const content = await loadObjectReferences(object, (doc) => doc.content);\n return JSON.stringify({ name: object.name, content: content.content });\n },\n\n deserialize: async ({ content: serialized }) => {\n const { name, content } = JSON.parse(serialized);\n return createEchoObject(create(DocumentType, { name, content: create(TextType, { content }), threads: [] }));\n },\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,kBAA2B;AAC3B,mBAA0C;AAE1C,2BAA8E;AAC9E,kBAA8D;AAC9D,kBAA4B;AAC5B,6BAMO;ACXP,mBAAyB;AAEzB,IAAAA,eAA6E;AAItE,IAAMC,uBAAuB,CAACC,aACnCC,2BAAaD,IAAAA,IACT,OACAA,QAAQ,OAAOA,SAAS,WACtB,WAAWA,QAAQ,OAAOA,KAAKE,UAAU,WACzC;AAID,IAAMC,2BAA2B,CAACC,YAAAA;AACvC,SAAQA,QAAsCC,OAAO,CAACC,WAAWC,QAAQD,OAAOE,UAAUC,QAAAA,CAAAA;AAC5F;AAEA,IAAMC,gBAAgB;AAEf,IAAMC,kBAAkB,CAACC,YAAAA;AAC9B,SAAOA,QAAQC,UAAU,GAAG,EAAA,EAAIC,MAAM,IAAA,EAAM,CAAA,EAAGC,WAAWL,eAAe,EAAA,EAAIM,KAAI;AACnF;AAEO,IAAMC,sBAAkBC,uBAAS,CAACC,KAAmBP,YAAAA;AAC1D,QAAMQ,OAAOT,gBAAgBC,OAAAA;AAC7B,MAAIO,IAAIE,iBAAiBD,MAAM;AAC7BD,QAAIE,eAAeD;EACrB;AACF,GAAG,GAAA;AAEI,IAAME,aAAkD;EAC7DC,WAAW,OAAO,EAAEC,OAAM,MAAE;AAC1B,UAAMZ,UAAU,UAAMa,mCAAqBD,QAAQ,CAACL,QAAQA,IAAIP,OAAO;AACvE,WAAOc,KAAKC,UAAU;MAAEP,MAAMI,OAAOJ;MAAMR,SAASA,QAAQA;IAAQ,CAAA;EACtE;EAEAgB,aAAa,OAAO,EAAEhB,SAASiB,WAAU,MAAE;AACzC,UAAM,EAAET,MAAMR,QAAO,IAAKc,KAAKI,MAAMD,UAAAA;AACrC,eAAOE,mCAAiBC,qBAAOC,oCAAc;MAAEb;MAAMR,aAASoB,qBAAOE,gCAAU;QAAEtB;MAAQ,CAAA;MAAIuB,SAAS,CAAA;IAAG,CAAA,CAAA;EAC3G;AACF;ADfA,IAAMC,iBAAiB,CAAC,EACtBC,UAAUlB,KACVmB,qBAAqB,CAAA,GACrBC,UACAC,UACA,GAAGC,MAAAA,MACiB;AACpB,QAAMC,YAAQC,sBAASxB,GAAAA;AACvB,QAAMyB,eAAWC,yBAAAA;AACjB,QAAMC,eAAWC,0CAAAA;AAEjB,QAAMC,qBAAiBC,sBAAQ,MAAA;AAI7B,eAAOC,4CAAqB;MAC1BX;MACAC;MACAH,UAAUlB;MACV2B;IAEF,CAAA;EACF,GAAG;IAAC3B;IAAKoB;IAAUO;IAAUN;IAAUA,SAASW;IAASX,SAASY;GAAiB;AAEnF,QAAMC,yBAAqBJ,sBACzB,MACEX,mBAAmBgB,OAAO,CAACC,KAAkBC,aAAAA;AAC3C,UAAMC,WAAW,OAAOD,aAAa,aAAaA,SAAS;MAAEnB,UAAUlB;IAAI,CAAA,IAAKqC;AAChFD,QAAIG,KAAI,GAAID,QAAAA;AACZ,WAAOF;EACT,GAAG,CAAA,CAAE,GACP;IAACjB;GAAmB;AAGtB,QAAMqB,iBAAaV,sBACjB,MAAM;;QAEJW,6CAAqB;MACnBC,IAAI1C,IAAI0C;MACRC,MAAM3C,IAAIP,eAAWmD,+BAAkB5C,IAAIP,SAAS;QAAC;OAAU;MAC/D8B;MACAE;IACF,CAAA;QACAoB,8BAAMC,oDAAAA;QACNC,iCAAS;MACPC,UAAU,CAACL,SAAAA;AACT7C,wBAAgBE,KAAK2C,IAAAA;MACvB;IACF,CAAA;IACAT;IACAL;KAEF;IAAC7B;IAAKA,IAAIP;IAAS8B;IAAOM;IAAgBK;IAAoBT;GAAS;AAGzE,QAAMwB,mBAAenB,sBAAQ,MAAM9B,IAAIP,SAASA,SAAS;IAACO,IAAIP;GAAQ;AAGtEyD,8BAAU,MAAA;AACR,QAAI,CAAClD,IAAIE,gBAAgBF,IAAIP,SAASA,SAAS;AAC7CO,UAAIE,eAAeV,gBAAgBQ,IAAIP,QAAQA,OAAO;IACxD;EACF,GAAG;IAACO;IAAKA,IAAIP;GAAQ;AAErB,QAAM;IAAE0D;;EAAuB,QAAOrB,sBAAQ,MAAA;AAC5C,UAAM,EAAEqB,UAAAA,WAAUC,UAAS,IAAKN,qDAA8BO,SAASrD,IAAI0C,EAAE,KAAK,CAAC;AACnF,WAAO;MACLS,UAAUA,WAAUG,OAAOC,uBAAWC,eAAeL,UAASG,MAAM;QAAEG,GAAG;QAASC,SAAS;MAAE,CAAA,IAAKC;MAClGP;IACF;EACF,GAAG;IAACpD;GAAI;AAER,QAAM4D,wBAAoBC,uCAAiBC,2CAAAA;AAE3C,QAAMC,uBAAmBjC,sBAAQ,MAAA;AAC/B,QAAIP,UAAUoC,QAAW;AACvB,aAAOA;IACT;AAEA,QAAIC,mBAAmBvE,SAAS2E,KAAKC,WAAWN,QAAW;AACzD,aAAOA;IACT;AAEA,WAAO,OAAOK,SAAAA;AACZ,aAAOJ,mBAAmBvE,UAAU2E,MAAMC,SAASD,MAAMzC,KAAAA;IAC3D;EACF,GAAG;IAACqC;IAAmBrC;GAAM;AAE7B,SACE,6BAAA2C,QAAA,cAACC,8CAAAA;IACCzB,QAAI0B,8BAAiBpE,GAAAA;IACrBiD;IACAT;IACAW;;;IAGAkB,cAAcN;IACdO,WAAWjD,SAASkD;IACpBC,SAASnD,SAASmD;IAClBpD;IACC,GAAGE;;AAGV;AAEA,IAAA,yBAAeL;",
6
- "names": ["import_echo", "isMarkdownProperties", "data", "isEchoObject", "title", "markdownExtensionPlugins", "plugins", "filter", "plugin", "Boolean", "provides", "markdown", "nonTitleChars", "getFallbackName", "content", "substring", "split", "replaceAll", "trim", "setFallbackName", "debounce", "doc", "name", "fallbackName", "serializer", "serialize", "object", "loadObjectReferences", "JSON", "stringify", "deserialize", "serialized", "parse", "createEchoObject", "create", "DocumentType", "TextType", "threads", "DocumentEditor", "document", "extensionProviders", "viewMode", "settings", "props", "space", "getSpace", "identity", "useIdentity", "dispatch", "useIntentDispatcher", "baseExtensions", "useMemo", "createBaseExtensions", "folding", "numberedHeadings", "providerExtensions", "reduce", "acc", "provider", "provided", "push", "extensions", "createDataExtensions", "id", "text", "createDocAccessor", "state", "localStorageStateStoreAdapter", "listener", "onChange", "initialValue", "useEffect", "scrollTo", "selection", "getState", "from", "EditorView", "scrollIntoView", "y", "yMargin", "undefined", "fileManagerPlugin", "useResolvePlugin", "parseFileManagerPlugin", "handleFileUpload", "file", "upload", "React", "MarkdownEditor", "fullyQualifiedId", "onFileUpload", "inputMode", "editorInputMode", "toolbar"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/components/MarkdownEditor.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\nimport React, { useMemo, useEffect } from 'react';\n\nimport {\n LayoutAction,\n useResolvePlugin,\n useIntentResolver,\n parseLayoutPlugin,\n type FileInfo,\n type LayoutCoordinate,\n} from '@dxos/app-framework';\nimport { parseAttentionPlugin } from '@dxos/plugin-attention';\nimport { useThemeContext, useTranslation } from '@dxos/react-ui';\nimport {\n type Action,\n type DNDOptions,\n type EditorViewMode,\n type EditorInputMode,\n type UseTextEditorProps,\n Toolbar,\n createBasicExtensions,\n createMarkdownExtensions,\n createThemeExtensions,\n dropFile,\n processAction,\n scrollThreadIntoView,\n useActionHandler,\n useCommentState,\n useCommentClickListener,\n useFormattingState,\n useTextEditor,\n editorContent,\n editorGutter,\n} from '@dxos/react-ui-editor';\nimport { sectionToolbarLayout } from '@dxos/react-ui-stack';\nimport { textBlockWidth, focusRing, mx } from '@dxos/react-ui-theme';\nimport { nonNullable } from '@dxos/util';\n\nimport { MARKDOWN_PLUGIN } from '../meta';\nimport type { MarkdownPluginState } from '../types';\n\nconst attentionFragment = mx(\n 'group-focus-within/editor:attention-surface group-[[aria-current]]/editor:attention-surface',\n 'group-focus-within/editor:separator-separator',\n);\n\nconst DEFAULT_VIEW_MODE: EditorViewMode = 'preview';\n\nexport type MarkdownEditorProps = {\n id: string;\n coordinate?: LayoutCoordinate;\n inputMode?: EditorInputMode;\n role?: string;\n scrollPastEnd?: boolean;\n toolbar?: boolean;\n viewMode?: EditorViewMode;\n onViewModeChange?: (id: string, mode: EditorViewMode) => void;\n onCommentSelect?: (id: string) => void;\n onFileUpload?: (file: File) => Promise<FileInfo | undefined>;\n} & Pick<UseTextEditorProps, 'initialValue' | 'selection' | 'scrollTo' | 'extensions'> &\n Partial<Pick<MarkdownPluginState, 'extensionProviders'>>;\n\nexport const MarkdownEditor = ({\n id,\n role = 'article',\n initialValue,\n extensions,\n extensionProviders,\n scrollTo,\n scrollPastEnd,\n selection,\n toolbar,\n viewMode,\n onCommentSelect,\n onFileUpload,\n onViewModeChange,\n}: MarkdownEditorProps) => {\n const { t } = useTranslation(MARKDOWN_PLUGIN);\n const { themeMode } = useThemeContext();\n const attentionPlugin = useResolvePlugin(parseAttentionPlugin);\n const layoutPlugin = useResolvePlugin(parseLayoutPlugin);\n const attended = Array.from(attentionPlugin?.provides.attention?.attended ?? []);\n const isDirectlyAttended = attended.length === 1 && attended[0] === id;\n const [formattingState, formattingObserver] = useFormattingState();\n\n // Extensions from other plugins.\n const providerExtensions = useMemo(() => extensionProviders?.map((provider) => provider({})), [extensionProviders]);\n\n // TODO(Zan): Move these into thread plugin as well?\n const [commentsState, commentObserver] = useCommentState();\n const commentClickObserver = useCommentClickListener((id) => {\n onCommentSelect?.(id);\n });\n\n // Focus comment.\n useIntentResolver(MARKDOWN_PLUGIN, ({ action, data }) => {\n switch (action) {\n case LayoutAction.SCROLL_INTO_VIEW: {\n if (editorView) {\n // TODO(Zan): Try catch this. Fails when thread plugin not present?\n scrollThreadIntoView(editorView, data?.id);\n if (data?.id === id) {\n editorView.scrollDOM\n .closest('[data-attendable-id]')\n ?.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'start' });\n }\n return undefined;\n }\n break;\n }\n }\n });\n\n const {\n parentRef,\n view: editorView,\n focusAttributes,\n } = useTextEditor(\n () => ({\n initialValue,\n extensions: [\n formattingObserver,\n commentObserver,\n commentClickObserver,\n createBasicExtensions({\n readonly: viewMode === 'readonly',\n placeholder: t('editor placeholder'),\n scrollPastEnd: role === 'section' ? false : scrollPastEnd,\n }),\n createMarkdownExtensions({ themeMode }),\n createThemeExtensions({ themeMode, slots: { content: { className: editorContent } } }),\n editorGutter,\n role !== 'section' && onFileUpload ? dropFile({ onDrop: handleDrop }) : [],\n providerExtensions,\n extensions,\n ].filter(nonNullable),\n ...(role !== 'section' && {\n id,\n selection,\n scrollTo,\n // TODO(wittjosiah): Autofocus based on layout is racey.\n autoFocus: layoutPlugin?.provides.layout ? layoutPlugin?.provides.layout.scrollIntoView === id : true,\n moveToEndOfLine: true,\n }),\n }),\n [id, initialValue, formattingObserver, viewMode, themeMode, extensions, providerExtensions],\n );\n\n useTest(editorView);\n\n // Toolbar handler.\n const handleToolbarAction = useActionHandler(editorView);\n const handleAction = (action: Action) => {\n if (action.type === 'view-mode') {\n onViewModeChange?.(id, action.data);\n }\n\n handleToolbarAction?.(action);\n };\n\n // Drag files.\n const handleDrop: DNDOptions['onDrop'] = async (view, { files }) => {\n const file = files[0];\n const info = file && onFileUpload ? await onFileUpload(file) : undefined;\n if (info) {\n processAction(view, { type: 'image', data: info.url });\n }\n };\n\n return (\n <div\n role='none'\n // TODO(burdon): Move role logic out of here (see sheet, table, sketch, etc.)\n {...(role === 'section'\n ? { className: 'flex flex-col' }\n : {\n className: 'contents group/editor',\n ...(isDirectlyAttended && { 'aria-current': 'location' }),\n })}\n >\n {toolbar && (\n <div role='none' className={mx('flex shrink-0 justify-center', attentionFragment)}>\n <Toolbar.Root\n classNames={\n role === 'section'\n ? ['z-[2] group-focus-within/section:visible', !attended && 'invisible', sectionToolbarLayout]\n : [\n textBlockWidth,\n 'group-focus-within/editor:separator-separator group-[[aria-current]]/editor:separator-separator',\n ]\n }\n state={formattingState && { ...formattingState, ...commentsState }}\n onAction={handleAction}\n >\n <Toolbar.Markdown />\n {onFileUpload && <Toolbar.Custom onUpload={onFileUpload} />}\n <Toolbar.Separator />\n <Toolbar.View mode={viewMode ?? DEFAULT_VIEW_MODE} />\n <Toolbar.Actions />\n </Toolbar.Root>\n </div>\n )}\n <div\n role='none'\n ref={parentRef}\n data-testid='composer.markdownRoot'\n data-toolbar={toolbar ? 'enabled' : 'disabled'}\n className={\n // TODO(burdon): Factor out margin for focus.\n role === 'section'\n ? mx('flex flex-col flex-1 min-bs-[12rem] mt-[2px]', focusRing)\n : mx(\n 'flex is-full bs-full overflow-hidden',\n focusRing,\n attentionFragment,\n 'focus-visible:ring-inset',\n 'data-[toolbar=disabled]:pbs-2 data-[toolbar=disabled]:row-span-2',\n )\n }\n {...focusAttributes}\n />\n </div>\n );\n};\n\n// Expose editor view for playwright tests.\n// TODO(wittjosiah): Find a better way to expose this or find a way to limit it to test runs.\nconst useTest = (view?: EditorView) => {\n useEffect(() => {\n const composer = (window as any).composer;\n if (composer) {\n composer.editorView = view;\n }\n }, [view]);\n};\n\nexport default MarkdownEditor;\n"],
5
- "mappings": "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",
6
- "names": ["attentionFragment", "mx", "DEFAULT_VIEW_MODE", "MarkdownEditor", "id", "role", "initialValue", "extensions", "extensionProviders", "scrollTo", "scrollPastEnd", "selection", "toolbar", "viewMode", "onCommentSelect", "onFileUpload", "onViewModeChange", "t", "useTranslation", "MARKDOWN_PLUGIN", "themeMode", "useThemeContext", "attentionPlugin", "useResolvePlugin", "parseAttentionPlugin", "layoutPlugin", "parseLayoutPlugin", "attended", "Array", "from", "provides", "attention", "isDirectlyAttended", "length", "formattingState", "formattingObserver", "useFormattingState", "providerExtensions", "useMemo", "map", "provider", "commentsState", "commentObserver", "useCommentState", "commentClickObserver", "useCommentClickListener", "useIntentResolver", "action", "data", "LayoutAction", "SCROLL_INTO_VIEW", "editorView", "scrollThreadIntoView", "scrollDOM", "closest", "scrollIntoView", "behavior", "inline", "block", "undefined", "parentRef", "view", "focusAttributes", "useTextEditor", "createBasicExtensions", "readonly", "placeholder", "createMarkdownExtensions", "createThemeExtensions", "slots", "content", "className", "editorContent", "editorGutter", "dropFile", "onDrop", "handleDrop", "filter", "nonNullable", "autoFocus", "layout", "moveToEndOfLine", "useTest", "handleToolbarAction", "useActionHandler", "handleAction", "type", "files", "file", "info", "processAction", "url", "React", "div", "Toolbar", "Root", "classNames", "sectionToolbarLayout", "textBlockWidth", "state", "onAction", "Markdown", "Custom", "onUpload", "Separator", "View", "mode", "Actions", "ref", "data-testid", "data-toolbar", "focusRing", "useEffect", "composer", "window"]
7
- }