@dxos/plugin-markdown 0.8.4-main.5ea62a8 → 0.8.4-main.ae835ea
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/MarkdownCard-SLM6QZYC.mjs +12 -0
- package/dist/lib/browser/MarkdownContainer-UZFQC6XY.mjs +15 -0
- package/dist/lib/browser/{anchor-sort-E33BSTYF.mjs → anchor-sort-4XPPLMZS.mjs} +5 -5
- package/dist/lib/browser/{anchor-sort-E33BSTYF.mjs.map → anchor-sort-4XPPLMZS.mjs.map} +1 -1
- package/dist/lib/browser/{app-graph-serializer-OX62DNPT.mjs → app-graph-serializer-QQFV4K6P.mjs} +8 -8
- package/dist/lib/browser/app-graph-serializer-QQFV4K6P.mjs.map +7 -0
- package/dist/lib/browser/blueprint-definition-BC5R3T72.mjs +11 -0
- package/dist/lib/browser/blueprint-definition-BC5R3T72.mjs.map +7 -0
- package/dist/lib/browser/{chunk-LAVZ2W6X.mjs → chunk-2LLVTQCK.mjs} +6 -5
- package/dist/lib/browser/chunk-2LLVTQCK.mjs.map +7 -0
- package/dist/lib/browser/{MarkdownCard-JLUQITYK.mjs → chunk-3VILQLA4.mjs} +46 -31
- package/dist/lib/browser/chunk-3VILQLA4.mjs.map +7 -0
- package/dist/lib/browser/chunk-5AYTOIUF.mjs +822 -0
- package/dist/lib/browser/chunk-5AYTOIUF.mjs.map +7 -0
- package/dist/lib/browser/{chunk-Z7P6JGGW.mjs → chunk-A3CQYGCN.mjs} +7 -4
- package/dist/lib/browser/{chunk-Z7P6JGGW.mjs.map → chunk-A3CQYGCN.mjs.map} +2 -2
- package/dist/lib/browser/{chunk-ODB2PTBP.mjs → chunk-BQTYJOFB.mjs} +4 -4
- package/dist/lib/browser/chunk-BQTYJOFB.mjs.map +7 -0
- package/dist/lib/browser/chunk-GLEYXJX3.mjs +22 -0
- package/dist/lib/browser/{chunk-D7UYVHL6.mjs.map → chunk-GLEYXJX3.mjs.map} +3 -3
- package/dist/lib/browser/{chunk-OY6CGPOO.mjs → chunk-IBCHVMZW.mjs} +2 -2
- package/dist/lib/browser/{chunk-OY6CGPOO.mjs.map → chunk-IBCHVMZW.mjs.map} +2 -2
- package/dist/lib/browser/{chunk-ZVVKLB5L.mjs → chunk-JAETS5LE.mjs} +33 -48
- package/dist/lib/browser/chunk-JAETS5LE.mjs.map +7 -0
- package/dist/lib/browser/{chunk-BEE7VQPU.mjs → chunk-UKTCPHLI.mjs} +9 -8
- package/dist/lib/browser/chunk-UKTCPHLI.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +21 -13
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-WDDH56JC.mjs → intent-resolver-VQGMBNXZ.mjs} +7 -7
- package/dist/lib/browser/intent-resolver-VQGMBNXZ.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-LN2XK2UN.mjs → react-surface-WOMJOPJE.mjs} +52 -50
- package/dist/lib/browser/react-surface-WOMJOPJE.mjs.map +7 -0
- package/dist/lib/browser/{settings-AABBTB4Q.mjs → settings-LBXJHVBU.mjs} +5 -5
- package/dist/lib/browser/{settings-AABBTB4Q.mjs.map → settings-LBXJHVBU.mjs.map} +1 -1
- package/dist/lib/browser/{state-FTHQQX7V.mjs → state-BTUKVZHY.mjs} +5 -5
- package/dist/lib/browser/{state-FTHQQX7V.mjs.map → state-BTUKVZHY.mjs.map} +1 -1
- package/dist/lib/browser/toolkit-YPIVDB4A.mjs +66 -0
- package/dist/lib/browser/toolkit-YPIVDB4A.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +2 -2
- package/dist/lib/node-esm/MarkdownCard-MCWEFW4F.mjs +13 -0
- package/dist/lib/node-esm/MarkdownCard-MCWEFW4F.mjs.map +7 -0
- package/dist/lib/node-esm/MarkdownContainer-KAQOK7K5.mjs +16 -0
- package/dist/lib/node-esm/MarkdownContainer-KAQOK7K5.mjs.map +7 -0
- package/dist/lib/node-esm/{anchor-sort-ALP2NH24.mjs → anchor-sort-4SXYVYXT.mjs} +5 -5
- package/dist/lib/node-esm/{anchor-sort-ALP2NH24.mjs.map → anchor-sort-4SXYVYXT.mjs.map} +1 -1
- package/dist/lib/node-esm/{app-graph-serializer-56TD3BMX.mjs → app-graph-serializer-KBVRLQN2.mjs} +8 -8
- package/dist/lib/node-esm/app-graph-serializer-KBVRLQN2.mjs.map +7 -0
- package/dist/lib/node-esm/blueprint-definition-FPNOTEYC.mjs +12 -0
- package/dist/lib/node-esm/blueprint-definition-FPNOTEYC.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-2Q4WCKWT.mjs +823 -0
- package/dist/lib/node-esm/chunk-2Q4WCKWT.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-Y422WR6A.mjs → chunk-DOB2MJAX.mjs} +33 -48
- package/dist/lib/node-esm/chunk-DOB2MJAX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-GGKPPGWA.mjs +24 -0
- package/dist/lib/node-esm/{chunk-JPXFCBC4.mjs.map → chunk-GGKPPGWA.mjs.map} +3 -3
- package/dist/lib/node-esm/{chunk-CB2R4YIY.mjs → chunk-GMMVSXQ6.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-CB2R4YIY.mjs.map → chunk-GMMVSXQ6.mjs.map} +2 -2
- package/dist/lib/node-esm/{chunk-FXILAQ5F.mjs → chunk-JELROKGD.mjs} +9 -8
- package/dist/lib/node-esm/chunk-JELROKGD.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-O6EXWGGS.mjs → chunk-QH4MC5BE.mjs} +6 -5
- package/dist/lib/node-esm/chunk-QH4MC5BE.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-VCG2U522.mjs → chunk-SHAMSMKQ.mjs} +4 -4
- package/dist/lib/node-esm/chunk-SHAMSMKQ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-J7A6TUB2.mjs → chunk-SJ2QRGPM.mjs} +7 -4
- package/dist/lib/node-esm/{chunk-J7A6TUB2.mjs.map → chunk-SJ2QRGPM.mjs.map} +2 -2
- package/dist/lib/node-esm/{MarkdownCard-XL5EVSJ7.mjs → chunk-YYSASY7X.mjs} +46 -31
- package/dist/lib/node-esm/chunk-YYSASY7X.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +21 -13
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-2I5HKCUU.mjs → intent-resolver-Q4XVI5EX.mjs} +7 -7
- package/dist/lib/node-esm/intent-resolver-Q4XVI5EX.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-DJGGKYBD.mjs → react-surface-FAMZTAXK.mjs} +52 -50
- package/dist/lib/node-esm/react-surface-FAMZTAXK.mjs.map +7 -0
- package/dist/lib/node-esm/{settings-CXGR6DH4.mjs → settings-2YRA67H6.mjs} +5 -5
- package/dist/lib/node-esm/{settings-CXGR6DH4.mjs.map → settings-2YRA67H6.mjs.map} +1 -1
- package/dist/lib/node-esm/{state-NWMQ3XAI.mjs → state-K6EH7SRZ.mjs} +5 -5
- package/dist/lib/node-esm/{state-NWMQ3XAI.mjs.map → state-K6EH7SRZ.mjs.map} +1 -1
- package/dist/lib/node-esm/toolkit-36BFLIR3.mjs +67 -0
- package/dist/lib/node-esm/toolkit-36BFLIR3.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +2 -2
- package/dist/types/src/MarkdownPlugin.d.ts +1 -1
- package/dist/types/src/MarkdownPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts +1 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +1 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/toolkit.d.ts +20 -0
- package/dist/types/src/capabilities/toolkit.d.ts.map +1 -0
- package/dist/types/src/components/MarkdownCard/MarkdownCard.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownCard/MarkdownCard.stories.d.ts +0 -1
- package/dist/types/src/components/MarkdownCard/MarkdownCard.stories.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownContainer.d.ts +8 -12
- package/dist/types/src/components/MarkdownContainer.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownContainer.stories.d.ts +7 -4
- package/dist/types/src/components/MarkdownContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/FileUpload.d.ts +11 -0
- package/dist/types/src/components/MarkdownEditor/FileUpload.d.ts.map +1 -0
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts +42 -23
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts +5 -110
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/MarkdownEditorContent.d.ts +26 -0
- package/dist/types/src/components/MarkdownEditor/MarkdownEditorContent.d.ts.map +1 -0
- package/dist/types/src/components/MarkdownEditor/MarkdownEditorToolbar.d.ts +12 -0
- package/dist/types/src/components/MarkdownEditor/MarkdownEditorToolbar.d.ts.map +1 -0
- package/dist/types/src/components/Suggestions.stories.d.ts +1 -2
- package/dist/types/src/components/Suggestions.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +3 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/functions/diff.d.ts.map +1 -1
- package/dist/types/src/functions/index.d.ts +0 -1
- package/dist/types/src/functions/index.d.ts.map +1 -1
- package/dist/types/src/functions/open.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +3 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useExtensions.d.ts +21 -0
- package/dist/types/src/hooks/useExtensions.d.ts.map +1 -0
- package/dist/types/src/hooks/useLinkQuery.d.ts +4 -0
- package/dist/types/src/hooks/useLinkQuery.d.ts.map +1 -0
- package/dist/types/src/hooks/usePopoverMenuOptions.d.ts +9 -0
- package/dist/types/src/hooks/usePopoverMenuOptions.d.ts.map +1 -0
- package/dist/types/src/hooks/useSelectCurrentThread.d.ts +1 -1
- package/dist/types/src/hooks/useSelectCurrentThread.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +3 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Markdown.d.ts +6 -4
- package/dist/types/src/types/Markdown.d.ts.map +1 -1
- package/dist/types/src/types/MarkdownAction.d.ts +3 -2
- package/dist/types/src/types/MarkdownAction.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +1 -1
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +58 -55
- package/src/MarkdownPlugin.tsx +100 -93
- package/src/capabilities/app-graph-serializer.ts +2 -2
- package/src/capabilities/artifact-definition.ts +4 -3
- package/src/capabilities/blueprint-definition.ts +5 -5
- package/src/capabilities/capabilities.ts +1 -0
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/intent-resolver.ts +2 -1
- package/src/capabilities/react-surface.tsx +35 -57
- package/src/capabilities/toolkit.ts +53 -0
- package/src/components/MarkdownCard/MarkdownCard.stories.tsx +3 -6
- package/src/components/MarkdownCard/MarkdownCard.tsx +42 -32
- package/src/components/MarkdownContainer.stories.tsx +75 -38
- package/src/components/MarkdownContainer.tsx +84 -218
- package/src/components/MarkdownEditor/FileUpload.tsx +63 -0
- package/src/components/MarkdownEditor/MarkdownEditor.stories.tsx +56 -35
- package/src/components/MarkdownEditor/MarkdownEditor.tsx +220 -272
- package/src/components/MarkdownEditor/MarkdownEditorContent.tsx +134 -0
- package/src/components/MarkdownEditor/MarkdownEditorToolbar.tsx +63 -0
- package/src/components/Suggestions.stories.tsx +28 -27
- package/src/components/index.ts +3 -1
- package/src/functions/diff.ts +4 -2
- package/src/functions/index.ts +0 -1
- package/src/functions/open.ts +4 -2
- package/src/hooks/index.ts +3 -0
- package/src/{extensions.tsx → hooks/useExtensions.tsx} +56 -114
- package/src/hooks/useLinkQuery.ts +82 -0
- package/src/hooks/usePopoverMenuOptions.ts +71 -0
- package/src/hooks/useSelectCurrentThread.tsx +2 -2
- package/src/meta.ts +3 -3
- package/src/translations.ts +3 -0
- package/src/types/Markdown.ts +6 -4
- package/src/types/MarkdownAction.ts +1 -1
- package/src/util.tsx +9 -2
- package/dist/lib/browser/MarkdownCard-JLUQITYK.mjs.map +0 -7
- package/dist/lib/browser/MarkdownContainer-7M37DXAD.mjs +0 -781
- package/dist/lib/browser/MarkdownContainer-7M37DXAD.mjs.map +0 -7
- package/dist/lib/browser/app-graph-serializer-OX62DNPT.mjs.map +0 -7
- package/dist/lib/browser/blueprint-definition-Z3RQGWUD.mjs +0 -11
- package/dist/lib/browser/chunk-BEE7VQPU.mjs.map +0 -7
- package/dist/lib/browser/chunk-D7UYVHL6.mjs +0 -20
- package/dist/lib/browser/chunk-LAVZ2W6X.mjs.map +0 -7
- package/dist/lib/browser/chunk-ODB2PTBP.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZVVKLB5L.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-WDDH56JC.mjs.map +0 -7
- package/dist/lib/browser/react-surface-LN2XK2UN.mjs.map +0 -7
- package/dist/lib/node-esm/MarkdownCard-XL5EVSJ7.mjs.map +0 -7
- package/dist/lib/node-esm/MarkdownContainer-K3BPAGWO.mjs +0 -782
- package/dist/lib/node-esm/MarkdownContainer-K3BPAGWO.mjs.map +0 -7
- package/dist/lib/node-esm/app-graph-serializer-56TD3BMX.mjs.map +0 -7
- package/dist/lib/node-esm/blueprint-definition-735OAX33.mjs +0 -12
- package/dist/lib/node-esm/chunk-FXILAQ5F.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-JPXFCBC4.mjs +0 -22
- package/dist/lib/node-esm/chunk-O6EXWGGS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-VCG2U522.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-Y422WR6A.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-2I5HKCUU.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-DJGGKYBD.mjs.map +0 -7
- package/dist/types/src/components/Toolbar.stories.d.ts +0 -48
- package/dist/types/src/components/Toolbar.stories.d.ts.map +0 -1
- package/dist/types/src/extensions.d.ts +0 -24
- package/dist/types/src/extensions.d.ts.map +0 -1
- package/dist/types/src/functions/create.d.ts +0 -12
- package/dist/types/src/functions/create.d.ts.map +0 -1
- package/src/components/Toolbar.stories.tsx +0 -118
- package/src/functions/create.ts +0 -23
- /package/dist/lib/browser/{blueprint-definition-Z3RQGWUD.mjs.map → MarkdownCard-SLM6QZYC.mjs.map} +0 -0
- /package/dist/lib/{node-esm/blueprint-definition-735OAX33.mjs.map → browser/MarkdownContainer-UZFQC6XY.mjs.map} +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type EditorView } from '@codemirror/view';
|
|
6
|
+
import React, { useCallback, useState } from 'react';
|
|
7
|
+
|
|
8
|
+
import { type FileInfo } from '@dxos/app-framework';
|
|
9
|
+
import { invariant } from '@dxos/invariant';
|
|
10
|
+
import { type ThemedClassName } from '@dxos/react-ui';
|
|
11
|
+
import { EditorToolbar, type EditorToolbarProps, type EditorViewMode } from '@dxos/react-ui-editor';
|
|
12
|
+
|
|
13
|
+
import { FileUpload, type FileUploadAction } from './FileUpload';
|
|
14
|
+
|
|
15
|
+
export type MarkdownEditorToolbarProps = ThemedClassName<
|
|
16
|
+
{
|
|
17
|
+
id: string;
|
|
18
|
+
editorView?: EditorView;
|
|
19
|
+
onFileUpload?: (file: File) => Promise<FileInfo | undefined>;
|
|
20
|
+
} & Pick<EditorToolbarProps, 'role' | 'state' | 'customActions' | 'onViewModeChange'>
|
|
21
|
+
>;
|
|
22
|
+
|
|
23
|
+
export const MarkdownEditorToolbar = ({
|
|
24
|
+
classNames,
|
|
25
|
+
id,
|
|
26
|
+
role,
|
|
27
|
+
state,
|
|
28
|
+
editorView,
|
|
29
|
+
customActions,
|
|
30
|
+
onFileUpload,
|
|
31
|
+
onViewModeChange,
|
|
32
|
+
}: MarkdownEditorToolbarProps) => {
|
|
33
|
+
const [upload, setUpload] = useState<FileUploadAction | null>(null);
|
|
34
|
+
const handleRef = useCallback((next: FileUploadAction) => setUpload(() => next), []);
|
|
35
|
+
|
|
36
|
+
const handleViewModeChange = useCallback((mode: EditorViewMode) => onViewModeChange?.(mode), [onViewModeChange]);
|
|
37
|
+
|
|
38
|
+
const getView = useCallback(() => {
|
|
39
|
+
invariant(editorView);
|
|
40
|
+
return editorView;
|
|
41
|
+
}, [editorView]);
|
|
42
|
+
|
|
43
|
+
if (!editorView) {
|
|
44
|
+
return <div />;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
<EditorToolbar
|
|
50
|
+
classNames={classNames}
|
|
51
|
+
attendableId={id}
|
|
52
|
+
role={role}
|
|
53
|
+
state={state}
|
|
54
|
+
customActions={customActions}
|
|
55
|
+
getView={getView}
|
|
56
|
+
onImageUpload={upload ?? undefined}
|
|
57
|
+
onViewModeChange={handleViewModeChange}
|
|
58
|
+
/>
|
|
59
|
+
|
|
60
|
+
{onFileUpload && <FileUpload ref={handleRef} editorView={editorView} onFileUpload={onFileUpload} />}
|
|
61
|
+
</>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
@@ -2,24 +2,19 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta } from '@storybook/react-vite';
|
|
8
|
-
import
|
|
6
|
+
import * as Function from 'effect/Function';
|
|
7
|
+
import * as Match from 'effect/Match';
|
|
8
|
+
import * as Option from 'effect/Option';
|
|
9
|
+
import * as Schema from 'effect/Schema';
|
|
9
10
|
import React, { type FC, useEffect, useMemo, useState } from 'react';
|
|
10
11
|
|
|
11
|
-
import {
|
|
12
|
-
Capabilities,
|
|
13
|
-
IntentPlugin,
|
|
14
|
-
SettingsPlugin,
|
|
15
|
-
contributes,
|
|
16
|
-
useCapability,
|
|
17
|
-
useIntentDispatcher,
|
|
18
|
-
} from '@dxos/app-framework';
|
|
12
|
+
import { Capabilities, IntentPlugin, SettingsPlugin, useCapability, useIntentDispatcher } from '@dxos/app-framework';
|
|
19
13
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
20
14
|
import { Obj, Ref, Type } from '@dxos/echo';
|
|
21
15
|
import { invariant } from '@dxos/invariant';
|
|
22
16
|
import { ClientPlugin } from '@dxos/plugin-client';
|
|
17
|
+
import { GraphPlugin } from '@dxos/plugin-graph';
|
|
23
18
|
import { PreviewPlugin } from '@dxos/plugin-preview';
|
|
24
19
|
import { SpacePlugin } from '@dxos/plugin-space';
|
|
25
20
|
import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
|
|
@@ -27,11 +22,12 @@ import { ThemePlugin } from '@dxos/plugin-theme';
|
|
|
27
22
|
import { faker } from '@dxos/random';
|
|
28
23
|
import { createDocAccessor, fullyQualifiedId, toCursorRange, useQueue, useSpace } from '@dxos/react-client/echo';
|
|
29
24
|
import { IconButton, Toolbar } from '@dxos/react-ui';
|
|
30
|
-
import {
|
|
25
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
26
|
+
import { type EditorSelection, type Range, useTextEditor } from '@dxos/react-ui-editor';
|
|
31
27
|
import { StackItem } from '@dxos/react-ui-stack';
|
|
32
28
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
33
29
|
import { DataType } from '@dxos/schema';
|
|
34
|
-
import {
|
|
30
|
+
import { render } from '@dxos/storybook-utils';
|
|
35
31
|
|
|
36
32
|
import { MarkdownCapabilities } from '../capabilities';
|
|
37
33
|
import { MarkdownPlugin } from '../MarkdownPlugin';
|
|
@@ -83,7 +79,7 @@ const TestChat: FC<{ doc: Markdown.Document; content: string }> = ({ doc, conten
|
|
|
83
79
|
|
|
84
80
|
const text = await doc.content.load();
|
|
85
81
|
const accessor = createDocAccessor(text, ['content']);
|
|
86
|
-
const cursor = pipe(
|
|
82
|
+
const cursor = Function.pipe(
|
|
87
83
|
editorState.getState(fullyQualifiedId(doc))?.selection,
|
|
88
84
|
Option.fromNullable,
|
|
89
85
|
Option.map(selectionToRange),
|
|
@@ -133,7 +129,7 @@ const DefaultStory = ({ document, chat }: { document: string; chat: string }) =>
|
|
|
133
129
|
content: document.replaceAll(/\[(\w+)\]/g, (_, label) => {
|
|
134
130
|
const obj = space.db.add(Obj.make(TestItem, { title: label, description: faker.lorem.paragraph() }));
|
|
135
131
|
const dxn = Ref.make(obj).dxn.toString();
|
|
136
|
-
return `[${label}]
|
|
132
|
+
return `[${label}](${dxn})`;
|
|
137
133
|
}),
|
|
138
134
|
}),
|
|
139
135
|
);
|
|
@@ -142,45 +138,50 @@ const DefaultStory = ({ document, chat }: { document: string; chat: string }) =>
|
|
|
142
138
|
}, [space]);
|
|
143
139
|
|
|
144
140
|
if (!space || !doc) {
|
|
145
|
-
return
|
|
141
|
+
return null;
|
|
146
142
|
}
|
|
147
143
|
|
|
144
|
+
// TODO(burdon): Layout issue.
|
|
148
145
|
return (
|
|
149
|
-
|
|
146
|
+
<div className='grid grid-cols-2 bs-full overflow-hidden'>
|
|
150
147
|
<MarkdownContainer id={doc.id} object={doc} settings={settings} editorStateStore={editorState} />
|
|
151
148
|
<TestChat doc={doc} content={chat} />
|
|
152
|
-
|
|
149
|
+
</div>
|
|
153
150
|
);
|
|
154
151
|
};
|
|
155
152
|
|
|
156
|
-
// TODO(burdon): Make consistent.
|
|
157
153
|
const storybook: Meta<typeof DefaultStory> = {
|
|
158
154
|
title: 'plugins/plugin-markdown/Suggestions',
|
|
159
|
-
render: DefaultStory,
|
|
155
|
+
render: render(DefaultStory),
|
|
160
156
|
decorators: [
|
|
157
|
+
withTheme,
|
|
161
158
|
withPluginManager({
|
|
162
159
|
plugins: [
|
|
163
|
-
ThemePlugin({ tx: defaultTx }),
|
|
164
|
-
StorybookLayoutPlugin(),
|
|
165
160
|
ClientPlugin({
|
|
166
161
|
types: [Markdown.Document, TestItem],
|
|
167
162
|
onClientInitialized: async ({ client }) => {
|
|
168
163
|
await client.halo.createIdentity();
|
|
169
164
|
},
|
|
170
165
|
}),
|
|
171
|
-
SpacePlugin(),
|
|
172
|
-
|
|
166
|
+
SpacePlugin({}),
|
|
167
|
+
GraphPlugin(),
|
|
173
168
|
IntentPlugin(),
|
|
169
|
+
SettingsPlugin(),
|
|
170
|
+
|
|
171
|
+
// UI
|
|
172
|
+
ThemePlugin({ tx: defaultTx }),
|
|
174
173
|
MarkdownPlugin(),
|
|
175
174
|
PreviewPlugin(),
|
|
175
|
+
StorybookLayoutPlugin({}),
|
|
176
176
|
],
|
|
177
|
-
capabilities: [contributes(MarkdownCapabilities.Extensions, [() => command()])],
|
|
178
177
|
}),
|
|
179
|
-
withLayout({ fullscreen: true, classNames: 'grid grid-cols-2' }),
|
|
180
178
|
],
|
|
181
179
|
parameters: {
|
|
180
|
+
layout: 'fullscreen',
|
|
181
|
+
controls: {
|
|
182
|
+
disable: true,
|
|
183
|
+
},
|
|
182
184
|
translations,
|
|
183
|
-
controls: { disable: true },
|
|
184
185
|
},
|
|
185
186
|
};
|
|
186
187
|
|
package/src/components/index.ts
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import { lazy } from 'react';
|
|
6
6
|
|
|
7
|
+
export * from './MarkdownCard';
|
|
8
|
+
export * from './MarkdownContainer';
|
|
7
9
|
export * from './MarkdownSettings';
|
|
8
10
|
|
|
9
|
-
export const MarkdownContainer = lazy(() => import('./MarkdownContainer'));
|
|
10
11
|
export const MarkdownCard = lazy(() => import('./MarkdownCard'));
|
|
12
|
+
export const MarkdownContainer = lazy(() => import('./MarkdownContainer'));
|
package/src/functions/diff.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
6
7
|
|
|
7
8
|
import { ArtifactId, applyDiffs } from '@dxos/assistant';
|
|
8
9
|
import { createDocAccessor } from '@dxos/echo-db';
|
|
@@ -13,7 +14,8 @@ import { Markdown } from '../types';
|
|
|
13
14
|
|
|
14
15
|
// TODO(wittjosiah): Reconcile with ThreadAction.AddProposal.
|
|
15
16
|
export default defineFunction({
|
|
16
|
-
|
|
17
|
+
key: 'dxos.org/function/markdown/diff',
|
|
18
|
+
name: 'Diff',
|
|
17
19
|
description: trim`
|
|
18
20
|
Applies a set of diffs to the markdown document.
|
|
19
21
|
`,
|
package/src/functions/index.ts
CHANGED
package/src/functions/open.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
6
7
|
|
|
7
8
|
import { ArtifactId } from '@dxos/assistant';
|
|
8
9
|
import { DatabaseService, defineFunction } from '@dxos/functions';
|
|
@@ -10,7 +11,8 @@ import { DatabaseService, defineFunction } from '@dxos/functions';
|
|
|
10
11
|
import { Markdown } from '../types';
|
|
11
12
|
|
|
12
13
|
export default defineFunction({
|
|
13
|
-
|
|
14
|
+
key: 'dxos.org/function/markdown/open',
|
|
15
|
+
name: 'Open',
|
|
14
16
|
description: 'Opens and reads the contents of a new markdown document.',
|
|
15
17
|
inputSchema: Schema.Struct({
|
|
16
18
|
id: ArtifactId.annotations({
|
package/src/hooks/index.ts
CHANGED
|
@@ -6,21 +6,16 @@ import { type ViewUpdate } from '@codemirror/view';
|
|
|
6
6
|
import React, { type AnchorHTMLAttributes, type ReactNode, useMemo } from 'react';
|
|
7
7
|
import { createRoot } from 'react-dom/client';
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
LayoutAction,
|
|
11
|
-
type PromiseIntentDispatcher,
|
|
12
|
-
createIntent,
|
|
13
|
-
useCapabilities,
|
|
14
|
-
useIntentDispatcher,
|
|
15
|
-
} from '@dxos/app-framework';
|
|
9
|
+
import { LayoutAction, type PromiseIntentDispatcher, createIntent, useIntentDispatcher } from '@dxos/app-framework';
|
|
16
10
|
import { debounceAndThrottle } from '@dxos/async';
|
|
11
|
+
import { Obj } from '@dxos/echo';
|
|
17
12
|
import { invariant } from '@dxos/invariant';
|
|
18
|
-
import {
|
|
13
|
+
import { createDocAccessor, fullyQualifiedId } from '@dxos/react-client/echo';
|
|
14
|
+
import { getSpace } from '@dxos/react-client/echo';
|
|
19
15
|
import { useIdentity } from '@dxos/react-client/halo';
|
|
20
16
|
import { Icon, ThemeProvider } from '@dxos/react-ui';
|
|
21
17
|
import { type SelectionManager } from '@dxos/react-ui-attention';
|
|
22
18
|
import {
|
|
23
|
-
type AutocompleteResult,
|
|
24
19
|
Cursor,
|
|
25
20
|
type EditorStateStore,
|
|
26
21
|
EditorView,
|
|
@@ -29,7 +24,6 @@ import {
|
|
|
29
24
|
InputModeExtensions,
|
|
30
25
|
type PreviewOptions,
|
|
31
26
|
type RenderCallback,
|
|
32
|
-
autocomplete,
|
|
33
27
|
createDataExtensions,
|
|
34
28
|
decorateMarkdown,
|
|
35
29
|
documentId,
|
|
@@ -42,20 +36,19 @@ import {
|
|
|
42
36
|
typewriter,
|
|
43
37
|
} from '@dxos/react-ui-editor';
|
|
44
38
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
45
|
-
import {
|
|
46
|
-
import {
|
|
39
|
+
import { DataType } from '@dxos/schema';
|
|
40
|
+
import { isTruthy } from '@dxos/util';
|
|
41
|
+
|
|
42
|
+
import { Markdown } from '../types';
|
|
43
|
+
import { setFallbackName } from '../util';
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
import { type Markdown } from './types';
|
|
50
|
-
import { setFallbackName } from './util';
|
|
45
|
+
export type DocumentType = Markdown.Document | DataType.Text | { id: string; text: string };
|
|
51
46
|
|
|
52
|
-
type ExtensionsOptions = {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
text?: DataType.Text;
|
|
47
|
+
export type ExtensionsOptions = {
|
|
48
|
+
id: string;
|
|
49
|
+
object?: DocumentType;
|
|
56
50
|
dispatch?: PromiseIntentDispatcher;
|
|
57
|
-
|
|
58
|
-
settings: Markdown.Settings;
|
|
51
|
+
settings?: Markdown.Settings;
|
|
59
52
|
selectionManager?: SelectionManager;
|
|
60
53
|
viewMode?: EditorViewMode;
|
|
61
54
|
editorStateStore?: EditorStateStore;
|
|
@@ -64,9 +57,8 @@ type ExtensionsOptions = {
|
|
|
64
57
|
|
|
65
58
|
// TODO(burdon): Merge with createBaseExtensions below.
|
|
66
59
|
export const useExtensions = ({
|
|
67
|
-
document,
|
|
68
60
|
id,
|
|
69
|
-
|
|
61
|
+
object,
|
|
70
62
|
settings,
|
|
71
63
|
selectionManager,
|
|
72
64
|
viewMode,
|
|
@@ -75,93 +67,66 @@ export const useExtensions = ({
|
|
|
75
67
|
}: ExtensionsOptions): Extension[] => {
|
|
76
68
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
77
69
|
const identity = useIdentity();
|
|
78
|
-
const space = getSpace(
|
|
70
|
+
const space = getSpace(object);
|
|
71
|
+
|
|
72
|
+
let target: Obj.Any | undefined;
|
|
73
|
+
if (Obj.instanceOf(Markdown.Document, object)) {
|
|
74
|
+
target = (object as Markdown.Document).content.target;
|
|
75
|
+
} else if (Obj.instanceOf(DataType.Text, object)) {
|
|
76
|
+
target = object;
|
|
77
|
+
}
|
|
79
78
|
|
|
80
79
|
// TODO(wittjosiah): Autocomplete is not working and this query is causing performance issues.
|
|
81
80
|
// TODO(burdon): Unsubscribe.
|
|
82
81
|
// const query = space?.db.query(Filter.type(DocumentType));
|
|
83
82
|
// query?.subscribe();
|
|
83
|
+
|
|
84
84
|
const baseExtensions = useMemo(
|
|
85
85
|
() =>
|
|
86
86
|
createBaseExtensions({
|
|
87
|
-
document,
|
|
88
87
|
id,
|
|
89
|
-
|
|
88
|
+
object,
|
|
90
89
|
settings,
|
|
91
90
|
selectionManager,
|
|
92
91
|
viewMode,
|
|
93
92
|
previewOptions,
|
|
94
93
|
dispatch,
|
|
95
|
-
// query,
|
|
96
94
|
}),
|
|
97
95
|
[
|
|
98
|
-
document,
|
|
99
96
|
id,
|
|
100
|
-
|
|
97
|
+
object,
|
|
101
98
|
viewMode,
|
|
102
99
|
dispatch,
|
|
103
100
|
previewOptions,
|
|
104
101
|
settings,
|
|
105
|
-
settings
|
|
106
|
-
settings
|
|
107
|
-
settings
|
|
108
|
-
settings
|
|
109
|
-
settings
|
|
102
|
+
settings?.debug,
|
|
103
|
+
settings?.editorInputMode,
|
|
104
|
+
settings?.folding,
|
|
105
|
+
settings?.numberedHeadings,
|
|
106
|
+
settings?.typewriter,
|
|
110
107
|
selectionManager,
|
|
111
108
|
],
|
|
112
109
|
);
|
|
113
110
|
|
|
114
|
-
const extensionProviders = useCapabilities(MarkdownCapabilities.Extensions);
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
// External extensions from other plugins.
|
|
118
|
-
//
|
|
119
|
-
const pluginExtensions = useMemo<Extension[]>(() => {
|
|
120
|
-
if (!document) {
|
|
121
|
-
return [];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return extensionProviders.flat().reduce((acc: Extension[], provider) => {
|
|
125
|
-
const extension = typeof provider === 'function' ? provider({ document }) : provider;
|
|
126
|
-
if (extension) {
|
|
127
|
-
acc.push(extension);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return acc;
|
|
131
|
-
}, []);
|
|
132
|
-
}, [extensionProviders, document]);
|
|
133
|
-
|
|
134
|
-
//
|
|
135
|
-
// Basic plugins.
|
|
136
|
-
//
|
|
137
111
|
return useMemo<Extension[]>(
|
|
138
112
|
() =>
|
|
139
113
|
[
|
|
114
|
+
// TODO(burdon): Pass this in?
|
|
140
115
|
// NOTE: Data extensions must be first so that automerge is updated before other extensions compute their state.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
space,
|
|
146
|
-
identity,
|
|
147
|
-
}),
|
|
148
|
-
text &&
|
|
149
|
-
id &&
|
|
150
|
-
createDataExtensions({
|
|
151
|
-
id,
|
|
152
|
-
text: createDocAccessor(text, ['content']),
|
|
153
|
-
space,
|
|
154
|
-
identity,
|
|
155
|
-
}),
|
|
156
|
-
selectionState(editorStateStore),
|
|
157
|
-
document &&
|
|
116
|
+
target && createDataExtensions({ id, text: createDocAccessor(target, ['content']), space, identity }),
|
|
117
|
+
|
|
118
|
+
// TODO(burdon): Reconcile with effect in parent.
|
|
119
|
+
Obj.instanceOf(Markdown.Document, object) &&
|
|
158
120
|
listener({
|
|
159
|
-
onChange: (text) =>
|
|
121
|
+
onChange: ({ text }) => {
|
|
122
|
+
setFallbackName(object as Markdown.Document, text);
|
|
123
|
+
},
|
|
160
124
|
}),
|
|
125
|
+
|
|
161
126
|
baseExtensions,
|
|
162
|
-
|
|
163
|
-
].filter(
|
|
164
|
-
[
|
|
127
|
+
selectionState(editorStateStore),
|
|
128
|
+
].filter(isTruthy),
|
|
129
|
+
[identity, space, id, object, target, baseExtensions],
|
|
165
130
|
);
|
|
166
131
|
};
|
|
167
132
|
|
|
@@ -169,20 +134,19 @@ export const useExtensions = ({
|
|
|
169
134
|
* Create extension instances for editor.
|
|
170
135
|
*/
|
|
171
136
|
const createBaseExtensions = ({
|
|
172
|
-
document,
|
|
173
137
|
id,
|
|
138
|
+
object,
|
|
174
139
|
dispatch,
|
|
175
140
|
settings,
|
|
176
141
|
selectionManager,
|
|
177
|
-
query,
|
|
178
142
|
viewMode,
|
|
179
143
|
previewOptions,
|
|
180
144
|
}: ExtensionsOptions): Extension[] => {
|
|
181
145
|
const extensions: Extension[] = [
|
|
182
146
|
selectionManager && selectionChange(selectionManager),
|
|
183
|
-
settings
|
|
184
|
-
settings
|
|
185
|
-
].filter(
|
|
147
|
+
settings?.editorInputMode && InputModeExtensions[settings.editorInputMode],
|
|
148
|
+
settings?.folding && folding(),
|
|
149
|
+
].filter(isTruthy);
|
|
186
150
|
|
|
187
151
|
//
|
|
188
152
|
// Markdown
|
|
@@ -193,17 +157,18 @@ const createBaseExtensions = ({
|
|
|
193
157
|
formattingKeymap(),
|
|
194
158
|
decorateMarkdown({
|
|
195
159
|
selectionChangeDelay: 100,
|
|
196
|
-
numberedHeadings: settings
|
|
160
|
+
numberedHeadings: settings?.numberedHeadings ? { from: 2 } : undefined,
|
|
197
161
|
// TODO(wittjosiah): For internal links, consider ignoring the link text and rendering the label of the object being linked to.
|
|
162
|
+
// TODO(burdon): Create dx-tag.
|
|
198
163
|
renderLinkButton:
|
|
199
|
-
dispatch && (
|
|
164
|
+
dispatch && (object || id)
|
|
200
165
|
? createLinkRenderer((id: string) => {
|
|
201
166
|
void dispatch(
|
|
202
167
|
createIntent(LayoutAction.Open, {
|
|
203
168
|
part: 'main',
|
|
204
169
|
subject: [id],
|
|
205
170
|
options: {
|
|
206
|
-
pivotId:
|
|
171
|
+
pivotId: object ? fullyQualifiedId(object) : id,
|
|
207
172
|
},
|
|
208
173
|
}),
|
|
209
174
|
);
|
|
@@ -216,31 +181,7 @@ const createBaseExtensions = ({
|
|
|
216
181
|
);
|
|
217
182
|
}
|
|
218
183
|
|
|
219
|
-
|
|
220
|
-
// Autocomplete object links.
|
|
221
|
-
//
|
|
222
|
-
if (query) {
|
|
223
|
-
extensions.push(
|
|
224
|
-
autocomplete({
|
|
225
|
-
onSearch: (text: string) => {
|
|
226
|
-
// TODO(burdon): Specify filter (e.g., stack).
|
|
227
|
-
return query.objects
|
|
228
|
-
.map<AutocompleteResult | undefined>((object) =>
|
|
229
|
-
object.name?.length && object.id !== document?.id
|
|
230
|
-
? {
|
|
231
|
-
label: object.name,
|
|
232
|
-
// TODO(burdon): Factor out URL builder.
|
|
233
|
-
apply: `[${object.name}](/${fullyQualifiedId(object)})`,
|
|
234
|
-
}
|
|
235
|
-
: undefined,
|
|
236
|
-
)
|
|
237
|
-
.filter(isNotFalsy);
|
|
238
|
-
},
|
|
239
|
-
}),
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (settings.debug) {
|
|
184
|
+
if (settings?.debug) {
|
|
244
185
|
const items = settings.typewriter?.split(/[,\n]/) ?? '';
|
|
245
186
|
if (items) {
|
|
246
187
|
extensions.push(typewriter({ items }));
|
|
@@ -250,7 +191,7 @@ const createBaseExtensions = ({
|
|
|
250
191
|
return extensions;
|
|
251
192
|
};
|
|
252
193
|
|
|
253
|
-
|
|
194
|
+
const selectionChange = (selectionManager: SelectionManager) => {
|
|
254
195
|
return EditorView.updateListener.of(
|
|
255
196
|
debounceAndThrottle((update: ViewUpdate) => {
|
|
256
197
|
if (update.selectionSet) {
|
|
@@ -263,6 +204,7 @@ export const selectionChange = (selectionManager: SelectionManager) => {
|
|
|
263
204
|
to: cursorConverter.toCursor(range.to),
|
|
264
205
|
}))
|
|
265
206
|
.filter(({ from, to }) => to > from);
|
|
207
|
+
|
|
266
208
|
selectionManager.updateMultiRange(id, ranges);
|
|
267
209
|
}
|
|
268
210
|
}, 100),
|
|
@@ -321,8 +263,8 @@ const renderLinkTooltip: RenderCallback<{ url: string }> = (el, { url }) => {
|
|
|
321
263
|
);
|
|
322
264
|
};
|
|
323
265
|
|
|
324
|
-
// TODO(burdon):
|
|
325
|
-
|
|
266
|
+
// TODO(burdon): REMOVE.
|
|
267
|
+
const renderRoot = <T extends Element>(root: T, node: ReactNode): T => {
|
|
326
268
|
createRoot(root).render(<ThemeProvider tx={defaultTx}>{node}</ThemeProvider>);
|
|
327
269
|
return root;
|
|
328
270
|
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useCallback, useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Capabilities, useCapabilities, usePluginManager } from '@dxos/app-framework';
|
|
8
|
+
import { Filter, Obj, Query, Type } from '@dxos/echo';
|
|
9
|
+
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
10
|
+
import { SpaceCapabilities } from '@dxos/plugin-space';
|
|
11
|
+
import { type Space } from '@dxos/react-client/echo';
|
|
12
|
+
import { toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
13
|
+
import { type PopoverMenuGroup, type PopoverMenuItem, insertAtCursor, insertAtLineStart } from '@dxos/react-ui-editor';
|
|
14
|
+
|
|
15
|
+
export const useLinkQuery = (space: Space | undefined) => {
|
|
16
|
+
const { t } = useTranslation();
|
|
17
|
+
|
|
18
|
+
const manager = usePluginManager();
|
|
19
|
+
const resolve = useCallback(
|
|
20
|
+
(typename: string) =>
|
|
21
|
+
manager.context.getCapabilities(Capabilities.Metadata).find(({ id }) => id === typename)?.metadata ?? {},
|
|
22
|
+
[manager],
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const objectForms = useCapabilities(SpaceCapabilities.ObjectForm);
|
|
26
|
+
const schemaWhiteList = useCapabilities(ClientCapabilities.SchemaWhiteList);
|
|
27
|
+
const filter = useMemo(
|
|
28
|
+
() =>
|
|
29
|
+
Filter.or(
|
|
30
|
+
...objectForms.map((form) => Filter.type(form.objectSchema)),
|
|
31
|
+
...schemaWhiteList.flat().map((schema) => Filter.typename(Type.getTypename(schema))),
|
|
32
|
+
),
|
|
33
|
+
[objectForms, schemaWhiteList],
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const handleLinkQuery = useCallback(
|
|
37
|
+
async (query?: string): Promise<PopoverMenuGroup[]> => {
|
|
38
|
+
const name = query?.startsWith('@') ? query.slice(1).toLowerCase() : (query?.toLowerCase() ?? '');
|
|
39
|
+
const results = await space?.db.query(Query.select(filter)).run();
|
|
40
|
+
|
|
41
|
+
// TODO(wittjosiah): Use `Obj.Any` type.
|
|
42
|
+
const getLabel = (object: any) => {
|
|
43
|
+
const label = Obj.getLabel(object);
|
|
44
|
+
if (label) {
|
|
45
|
+
return label;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// TODO(wittjosiah): Remove metadata labels.
|
|
49
|
+
const type = Obj.getTypename(object)!;
|
|
50
|
+
const metadata = resolve(type);
|
|
51
|
+
return metadata.label?.(object) || ['object name placeholder', { ns: type, default: 'New object' }];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const items =
|
|
55
|
+
results?.objects
|
|
56
|
+
.filter((object) => toLocalizedString(getLabel(object), t).toLowerCase().includes(name))
|
|
57
|
+
// TODO(wittjosiah): Remove `any` type.
|
|
58
|
+
.map((object: any): PopoverMenuItem => {
|
|
59
|
+
const metadata = resolve(Obj.getTypename(object)!);
|
|
60
|
+
const label = toLocalizedString(getLabel(object), t);
|
|
61
|
+
return {
|
|
62
|
+
id: object.id,
|
|
63
|
+
label,
|
|
64
|
+
icon: metadata.icon,
|
|
65
|
+
onSelect: (view, head) => {
|
|
66
|
+
const link = `[${label}](${Obj.getDXN(object)})`;
|
|
67
|
+
if (query?.startsWith('@')) {
|
|
68
|
+
insertAtLineStart(view, head, `!${link}\n`);
|
|
69
|
+
} else {
|
|
70
|
+
insertAtCursor(view, head, `${link} `);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}) ?? [];
|
|
75
|
+
|
|
76
|
+
return [{ id: 'echo', items }];
|
|
77
|
+
},
|
|
78
|
+
[space, filter, resolve],
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return handleLinkQuery;
|
|
82
|
+
};
|