@dxos/plugin-markdown 0.8.4-main.28f8d3d → 0.8.4-main.406dc2a
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-IMCR4A4V.mjs → MarkdownCard-AGWOTODZ.mjs} +21 -18
- package/dist/lib/browser/MarkdownCard-AGWOTODZ.mjs.map +7 -0
- package/dist/lib/browser/{MarkdownContainer-VGJPHMVG.mjs → MarkdownContainer-MV2UNAUV.mjs} +64 -93
- package/dist/lib/browser/MarkdownContainer-MV2UNAUV.mjs.map +7 -0
- package/dist/lib/browser/{anchor-sort-AJKRIWFD.mjs → anchor-sort-YWJI3BKT.mjs} +5 -5
- package/dist/lib/browser/{anchor-sort-AJKRIWFD.mjs.map → anchor-sort-YWJI3BKT.mjs.map} +1 -1
- package/dist/lib/browser/{app-graph-serializer-OIS3MZX2.mjs → app-graph-serializer-KYDFCUOW.mjs} +8 -9
- package/dist/lib/browser/app-graph-serializer-KYDFCUOW.mjs.map +7 -0
- package/dist/lib/browser/blueprint-definition-BHRMFZAC.mjs +11 -0
- package/dist/lib/browser/blueprint-definition-BHRMFZAC.mjs.map +7 -0
- package/dist/lib/browser/{chunk-JMBQG2ZC.mjs → chunk-6KU5DKP7.mjs} +6 -5
- package/dist/lib/browser/chunk-6KU5DKP7.mjs.map +7 -0
- package/dist/lib/browser/chunk-HBBEHOP3.mjs +106 -0
- package/dist/lib/browser/chunk-HBBEHOP3.mjs.map +7 -0
- package/dist/lib/browser/{chunk-MVL4K3OD.mjs → chunk-O6XUPW6S.mjs} +4 -3
- package/dist/lib/browser/chunk-O6XUPW6S.mjs.map +7 -0
- package/dist/lib/browser/{chunk-IKPZHFTW.mjs → chunk-ODB2PTBP.mjs} +2 -4
- package/dist/lib/browser/{chunk-IKPZHFTW.mjs.map → chunk-ODB2PTBP.mjs.map} +3 -3
- package/dist/lib/browser/{chunk-LMJPXTPL.mjs → chunk-OY6CGPOO.mjs} +2 -2
- package/dist/lib/browser/{chunk-JTIGSUMB.mjs → chunk-XMT6PMU5.mjs} +11 -12
- package/dist/lib/browser/chunk-XMT6PMU5.mjs.map +7 -0
- package/dist/lib/browser/chunk-Z5PDJNBV.mjs +22 -0
- package/dist/lib/browser/chunk-Z5PDJNBV.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +31 -16
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-BLLHRSTQ.mjs → intent-resolver-XHVCZZHU.mjs} +20 -18
- package/dist/lib/browser/intent-resolver-XHVCZZHU.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-NL3BZR6H.mjs → react-surface-3A2GO3BN.mjs} +38 -31
- package/dist/lib/browser/react-surface-3A2GO3BN.mjs.map +7 -0
- package/dist/lib/browser/{settings-Z7ZV7SLC.mjs → settings-XY265Y2Q.mjs} +5 -5
- package/dist/lib/browser/{settings-Z7ZV7SLC.mjs.map → settings-XY265Y2Q.mjs.map} +1 -1
- package/dist/lib/browser/{state-ORTZIEJU.mjs → state-6QODXCSZ.mjs} +5 -5
- package/dist/lib/browser/{state-ORTZIEJU.mjs.map → state-6QODXCSZ.mjs.map} +1 -1
- package/dist/lib/browser/toolkit-YA65QX2S.mjs +76 -0
- package/dist/lib/browser/toolkit-YA65QX2S.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +2 -2
- package/dist/lib/node-esm/{MarkdownCard-JV2YDV3M.mjs → MarkdownCard-B2IWTFOC.mjs} +21 -18
- package/dist/lib/node-esm/MarkdownCard-B2IWTFOC.mjs.map +7 -0
- package/dist/lib/node-esm/{MarkdownContainer-BJRNCXJZ.mjs → MarkdownContainer-J2R3DLCQ.mjs} +64 -93
- package/dist/lib/node-esm/MarkdownContainer-J2R3DLCQ.mjs.map +7 -0
- package/dist/lib/node-esm/{anchor-sort-N7WEA5E3.mjs → anchor-sort-FCRYL2FX.mjs} +5 -5
- package/dist/lib/node-esm/{anchor-sort-N7WEA5E3.mjs.map → anchor-sort-FCRYL2FX.mjs.map} +1 -1
- package/dist/lib/node-esm/{app-graph-serializer-Q3B44VFB.mjs → app-graph-serializer-FAUQM3BH.mjs} +8 -9
- package/dist/lib/node-esm/app-graph-serializer-FAUQM3BH.mjs.map +7 -0
- package/dist/lib/node-esm/blueprint-definition-XYFKMIDR.mjs +12 -0
- package/dist/lib/node-esm/blueprint-definition-XYFKMIDR.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-7RDNIMTF.mjs +24 -0
- package/dist/lib/node-esm/chunk-7RDNIMTF.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-AYWAYBAY.mjs → chunk-CB2R4YIY.mjs} +2 -2
- package/dist/lib/node-esm/chunk-FVI7LPC3.mjs +107 -0
- package/dist/lib/node-esm/chunk-FVI7LPC3.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-KIRZFVX5.mjs → chunk-FWZKC6X5.mjs} +11 -12
- package/dist/lib/node-esm/chunk-FWZKC6X5.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-H4I2FGDZ.mjs → chunk-VCG2U522.mjs} +2 -4
- package/dist/lib/node-esm/{chunk-H4I2FGDZ.mjs.map → chunk-VCG2U522.mjs.map} +3 -3
- package/dist/lib/node-esm/{chunk-Z4XQ6C3D.mjs → chunk-XO3IEQJE.mjs} +4 -3
- package/dist/lib/node-esm/chunk-XO3IEQJE.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-JDMMLOB6.mjs → chunk-ZBXV4ON7.mjs} +6 -5
- package/dist/lib/node-esm/chunk-ZBXV4ON7.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +31 -16
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-NHPUPSWK.mjs → intent-resolver-7A2EXGZQ.mjs} +20 -18
- package/dist/lib/node-esm/intent-resolver-7A2EXGZQ.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-XJ6ODCBE.mjs → react-surface-RCLL5WVQ.mjs} +38 -31
- package/dist/lib/node-esm/react-surface-RCLL5WVQ.mjs.map +7 -0
- package/dist/lib/node-esm/{settings-UCXEWBCT.mjs → settings-H3UDD3KO.mjs} +5 -5
- package/dist/lib/node-esm/{settings-UCXEWBCT.mjs.map → settings-H3UDD3KO.mjs.map} +1 -1
- package/dist/lib/node-esm/{state-47WSZG54.mjs → state-W3PECOJX.mjs} +5 -5
- package/dist/lib/node-esm/{state-47WSZG54.mjs.map → state-W3PECOJX.mjs.map} +1 -1
- package/dist/lib/node-esm/toolkit-HSIKUGNK.mjs +77 -0
- package/dist/lib/node-esm/toolkit-HSIKUGNK.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/anchor-sort.d.ts +2 -2
- package/dist/types/src/capabilities/app-graph-serializer.d.ts +1 -1
- package/dist/types/src/capabilities/artifact-definition.d.ts +0 -8
- package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts +5 -0
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +11 -8
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/settings.d.ts +1 -1
- package/dist/types/src/capabilities/state.d.ts +2 -2
- package/dist/types/src/capabilities/toolkit.d.ts +4 -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 +5 -38
- package/dist/types/src/components/MarkdownCard/MarkdownCard.stories.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownContainer.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownContainer.stories.d.ts +51 -5
- package/dist/types/src/components/MarkdownContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts +5 -5
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts +111 -13
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownSettings/MarkdownSettings.d.ts.map +1 -1
- 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/Toolbar.stories.d.ts +45 -8
- package/dist/types/src/components/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions.d.ts +0 -2
- package/dist/types/src/extensions.d.ts.map +1 -1
- package/dist/types/src/functions/diff.d.ts +6 -0
- package/dist/types/src/functions/diff.d.ts.map +1 -0
- package/dist/types/src/functions/index.d.ts +3 -0
- package/dist/types/src/functions/index.d.ts.map +1 -0
- package/dist/types/src/functions/open.d.ts +7 -0
- package/dist/types/src/functions/open.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/meta.d.ts +0 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Markdown.d.ts +7 -5
- package/dist/types/src/types/Markdown.d.ts.map +1 -1
- package/dist/types/src/types/MarkdownAction.d.ts +6 -14
- package/dist/types/src/types/MarkdownAction.d.ts.map +1 -1
- package/dist/types/src/types/types.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 +55 -52
- package/src/MarkdownPlugin.tsx +100 -86
- package/src/capabilities/app-graph-serializer.ts +3 -3
- package/src/capabilities/artifact-definition.ts +9 -16
- package/src/capabilities/blueprint-definition.ts +39 -0
- package/src/capabilities/index.ts +3 -0
- package/src/capabilities/intent-resolver.ts +11 -11
- package/src/capabilities/toolkit.ts +49 -0
- package/src/components/MarkdownCard/MarkdownCard.stories.tsx +8 -11
- package/src/components/MarkdownCard/MarkdownCard.tsx +17 -16
- package/src/components/MarkdownContainer.stories.tsx +46 -37
- package/src/components/MarkdownContainer.tsx +16 -14
- package/src/components/MarkdownEditor/MarkdownEditor.stories.tsx +19 -16
- package/src/components/MarkdownEditor/MarkdownEditor.tsx +47 -48
- package/src/components/MarkdownSettings/MarkdownSettings.tsx +77 -74
- package/src/components/Suggestions.stories.tsx +36 -38
- package/src/components/Toolbar.stories.tsx +20 -14
- package/src/extensions.tsx +4 -32
- package/src/functions/diff.ts +37 -0
- package/src/functions/index.ts +6 -0
- package/src/functions/open.ts +32 -0
- package/src/hooks/useSelectCurrentThread.tsx +2 -2
- package/src/meta.ts +0 -3
- package/src/translations.ts +1 -0
- package/src/types/Markdown.ts +6 -3
- package/src/types/MarkdownAction.ts +4 -6
- package/src/types/types.ts +1 -0
- package/src/util.tsx +8 -2
- package/dist/lib/browser/MarkdownCard-IMCR4A4V.mjs.map +0 -7
- package/dist/lib/browser/MarkdownContainer-VGJPHMVG.mjs.map +0 -7
- package/dist/lib/browser/app-graph-serializer-OIS3MZX2.mjs.map +0 -7
- package/dist/lib/browser/chunk-JHH7VL52.mjs +0 -18
- package/dist/lib/browser/chunk-JHH7VL52.mjs.map +0 -7
- package/dist/lib/browser/chunk-JMBQG2ZC.mjs.map +0 -7
- package/dist/lib/browser/chunk-JTIGSUMB.mjs.map +0 -7
- package/dist/lib/browser/chunk-MVL4K3OD.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-BLLHRSTQ.mjs.map +0 -7
- package/dist/lib/browser/react-surface-NL3BZR6H.mjs.map +0 -7
- package/dist/lib/node-esm/MarkdownCard-JV2YDV3M.mjs.map +0 -7
- package/dist/lib/node-esm/MarkdownContainer-BJRNCXJZ.mjs.map +0 -7
- package/dist/lib/node-esm/app-graph-serializer-Q3B44VFB.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-H6TITL7A.mjs +0 -20
- package/dist/lib/node-esm/chunk-H6TITL7A.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-JDMMLOB6.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-KIRZFVX5.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-Z4XQ6C3D.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-NHPUPSWK.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-XJ6ODCBE.mjs.map +0 -7
- /package/dist/lib/browser/{chunk-LMJPXTPL.mjs.map → chunk-OY6CGPOO.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-AYWAYBAY.mjs.map → chunk-CB2R4YIY.mjs.map} +0 -0
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Function from 'effect/Function';
|
|
6
6
|
import React, { useCallback } from 'react';
|
|
7
7
|
|
|
8
8
|
import { LayoutAction, chain, createIntent, useIntentDispatcher } from '@dxos/app-framework';
|
|
9
9
|
import { Obj } from '@dxos/echo';
|
|
10
10
|
import { type PreviewProps } from '@dxos/plugin-preview';
|
|
11
11
|
import { fullyQualifiedId } from '@dxos/react-client/echo';
|
|
12
|
-
import {
|
|
12
|
+
import { IconButton, useTranslation } from '@dxos/react-ui';
|
|
13
13
|
import { Card } from '@dxos/react-ui-stack';
|
|
14
14
|
import { DataType } from '@dxos/schema';
|
|
15
15
|
|
|
16
16
|
import { meta } from '../../meta';
|
|
17
17
|
import { Markdown } from '../../types';
|
|
18
|
-
import {
|
|
18
|
+
import { getContentSnippet, getFallbackName } from '../../util';
|
|
19
19
|
|
|
20
20
|
// TODO(burdon): Factor out.
|
|
21
21
|
const getTitle = (subject: Markdown.Document | DataType.Text, fallback: string) => {
|
|
@@ -29,9 +29,9 @@ const getTitle = (subject: Markdown.Document | DataType.Text, fallback: string)
|
|
|
29
29
|
// TODO(burdon): Factor out.
|
|
30
30
|
const getSnippet = (subject: Markdown.Document | DataType.Text, fallback: string) => {
|
|
31
31
|
if (Obj.instanceOf(Markdown.Document, subject)) {
|
|
32
|
-
return
|
|
32
|
+
return Obj.getDescription(subject) || getContentSnippet(subject.content?.target?.content ?? fallback);
|
|
33
33
|
} else if (Obj.instanceOf(DataType.Text, subject)) {
|
|
34
|
-
return
|
|
34
|
+
return getContentSnippet(subject.content ?? fallback);
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
37
|
|
|
@@ -46,7 +46,7 @@ export const MarkdownCard = ({ subject, role }: MarkdownCardProps) => {
|
|
|
46
46
|
const handleNavigate = useCallback(
|
|
47
47
|
() =>
|
|
48
48
|
dispatch(
|
|
49
|
-
pipe(
|
|
49
|
+
Function.pipe(
|
|
50
50
|
createIntent(LayoutAction.UpdatePopover, {
|
|
51
51
|
part: 'popover',
|
|
52
52
|
subject: null,
|
|
@@ -60,16 +60,17 @@ export const MarkdownCard = ({ subject, role }: MarkdownCardProps) => {
|
|
|
60
60
|
|
|
61
61
|
return (
|
|
62
62
|
<Card.SurfaceRoot role={role}>
|
|
63
|
-
<Card.Heading
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
<Card.Heading classNames='flex items-center'>
|
|
64
|
+
{getTitle(subject, t('fallback title'))}
|
|
65
|
+
<span className='grow' />
|
|
66
|
+
<IconButton
|
|
67
|
+
iconOnly
|
|
68
|
+
icon='ph--arrow-right--regular'
|
|
69
|
+
label={t('navigate to document label')}
|
|
70
|
+
onClick={handleNavigate}
|
|
71
|
+
/>
|
|
72
|
+
</Card.Heading>
|
|
73
|
+
{snippet && <Card.Text classNames='line-clamp-3 text-sm text-description'>{snippet}</Card.Text>}
|
|
73
74
|
</Card.SurfaceRoot>
|
|
74
75
|
);
|
|
75
76
|
};
|
|
@@ -2,28 +2,34 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@
|
|
6
|
-
|
|
7
|
-
import { type Meta } from '@storybook/react-vite';
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
6
|
import React, { useMemo } from 'react';
|
|
9
7
|
|
|
10
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
type Capabilities,
|
|
10
|
+
IntentPlugin,
|
|
11
|
+
LayoutAction,
|
|
12
|
+
SettingsPlugin,
|
|
13
|
+
Surface,
|
|
14
|
+
createIntent,
|
|
15
|
+
useIntentDispatcher,
|
|
16
|
+
} from '@dxos/app-framework';
|
|
11
17
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
12
|
-
import {
|
|
13
|
-
import { Query, Type } from '@dxos/echo';
|
|
18
|
+
import { Obj, Query } from '@dxos/echo';
|
|
14
19
|
import { AttentionPlugin } from '@dxos/plugin-attention';
|
|
15
20
|
import { ClientPlugin } from '@dxos/plugin-client';
|
|
16
21
|
import { GraphPlugin } from '@dxos/plugin-graph';
|
|
17
22
|
import { PreviewPlugin } from '@dxos/plugin-preview';
|
|
18
|
-
import {
|
|
23
|
+
import { SpacePlugin } from '@dxos/plugin-space';
|
|
19
24
|
import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
|
|
20
25
|
import { ThemePlugin } from '@dxos/plugin-theme';
|
|
21
26
|
import { faker } from '@dxos/random';
|
|
22
27
|
import { useQuery, useSpace } from '@dxos/react-client/echo';
|
|
28
|
+
import { useAsyncEffect } from '@dxos/react-ui';
|
|
29
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
23
30
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
24
31
|
import { DataType } from '@dxos/schema';
|
|
25
|
-
import {
|
|
26
|
-
import { withLayout } from '@dxos/storybook-utils';
|
|
32
|
+
import { type ValueGenerator, createObjectFactory } from '@dxos/schema/testing';
|
|
27
33
|
|
|
28
34
|
import { MarkdownPlugin } from '../MarkdownPlugin';
|
|
29
35
|
import { translations } from '../translations';
|
|
@@ -34,67 +40,70 @@ faker.seed(1);
|
|
|
34
40
|
const generator: ValueGenerator = faker as any;
|
|
35
41
|
|
|
36
42
|
const DefaultStory = () => {
|
|
43
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
37
44
|
const space = useSpace();
|
|
38
45
|
const [doc] = useQuery(space, Query.type(Markdown.Document));
|
|
39
46
|
const data = useMemo(() => ({ subject: doc }), [doc]);
|
|
40
47
|
|
|
41
|
-
|
|
48
|
+
useAsyncEffect(async () => {
|
|
49
|
+
if (space) {
|
|
50
|
+
await dispatch(createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: space.id }));
|
|
51
|
+
}
|
|
52
|
+
}, [space, dispatch]);
|
|
53
|
+
|
|
54
|
+
return <Surface role='article' data={data} limit={1} />;
|
|
42
55
|
};
|
|
43
56
|
|
|
44
|
-
const meta
|
|
57
|
+
const meta = {
|
|
45
58
|
title: 'plugins/plugin-markdown/MarkdownContainer',
|
|
46
59
|
render: DefaultStory,
|
|
47
60
|
decorators: [
|
|
61
|
+
withTheme,
|
|
48
62
|
withPluginManager({
|
|
49
63
|
plugins: [
|
|
50
|
-
AttentionPlugin(),
|
|
51
|
-
ThemePlugin({ tx: defaultTx }),
|
|
52
|
-
StorybookLayoutPlugin(),
|
|
53
64
|
ClientPlugin({
|
|
54
|
-
types: [Markdown.Document, DataType.Text,
|
|
65
|
+
types: [Markdown.Document, DataType.Text, DataType.Person, DataType.Organization],
|
|
55
66
|
onClientInitialized: async ({ client }) => {
|
|
56
67
|
await client.halo.createIdentity();
|
|
57
68
|
await client.spaces.waitUntilReady();
|
|
58
69
|
await client.spaces.default.waitUntilReady();
|
|
59
70
|
const space = client.spaces.default;
|
|
60
|
-
const
|
|
71
|
+
const queue = space.queues.create();
|
|
72
|
+
const alice = Obj.make(DataType.Person, { fullName: 'Alice' });
|
|
73
|
+
const acme = Obj.make(DataType.Organization, { name: 'ACME' });
|
|
74
|
+
await queue.append([alice, acme]);
|
|
75
|
+
const doc = Markdown.makeDocument({
|
|
76
|
+
name: 'Test',
|
|
77
|
+
content: `# Test\n\n})\n\n})`,
|
|
78
|
+
});
|
|
61
79
|
space.db.add(doc);
|
|
62
80
|
const createObjects = createObjectFactory(space.db, generator);
|
|
63
|
-
await createObjects([{ type:
|
|
81
|
+
await createObjects([{ type: DataType.Organization, count: 10 }]);
|
|
64
82
|
await space.db.flush({ indexes: true });
|
|
65
83
|
},
|
|
66
84
|
}),
|
|
67
|
-
SpacePlugin(),
|
|
68
|
-
|
|
85
|
+
SpacePlugin({}),
|
|
86
|
+
GraphPlugin(),
|
|
69
87
|
IntentPlugin(),
|
|
88
|
+
SettingsPlugin(),
|
|
89
|
+
// UI
|
|
90
|
+
ThemePlugin({ tx: defaultTx }),
|
|
91
|
+
AttentionPlugin(),
|
|
70
92
|
MarkdownPlugin(),
|
|
71
93
|
PreviewPlugin(),
|
|
72
|
-
|
|
73
|
-
],
|
|
74
|
-
capabilities: [
|
|
75
|
-
// NOTE: Editor only queries for object form schemas when linking.
|
|
76
|
-
contributes(SpaceCapabilities.ObjectForm, {
|
|
77
|
-
objectSchema: Testing.Contact,
|
|
78
|
-
getIntent: () => todo(),
|
|
79
|
-
}),
|
|
80
|
-
contributes(Capabilities.Metadata, {
|
|
81
|
-
id: Type.getTypename(Testing.Contact),
|
|
82
|
-
metadata: {
|
|
83
|
-
icon: 'ph--user--regular',
|
|
84
|
-
},
|
|
85
|
-
}),
|
|
94
|
+
StorybookLayoutPlugin({}),
|
|
86
95
|
],
|
|
87
96
|
}),
|
|
88
|
-
withLayout({ fullscreen: true }),
|
|
89
97
|
],
|
|
90
98
|
parameters: {
|
|
91
|
-
|
|
99
|
+
layout: 'fullscreen',
|
|
92
100
|
controls: { disable: true },
|
|
101
|
+
translations,
|
|
93
102
|
},
|
|
94
|
-
}
|
|
103
|
+
} satisfies Meta<typeof Capabilities>;
|
|
95
104
|
|
|
96
105
|
export default meta;
|
|
97
106
|
|
|
98
|
-
type Story =
|
|
107
|
+
type Story = StoryObj<typeof meta>;
|
|
99
108
|
|
|
100
109
|
export const Default: Story = {};
|
|
@@ -10,12 +10,13 @@ import { Capabilities, Surface, useAppGraph, useCapabilities, usePluginManager }
|
|
|
10
10
|
import { DXN, Filter, Obj, Query, Type } from '@dxos/echo';
|
|
11
11
|
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
12
12
|
import { SpaceCapabilities } from '@dxos/plugin-space';
|
|
13
|
-
import {
|
|
13
|
+
import { useClient } from '@dxos/react-client';
|
|
14
|
+
import { fullyQualifiedId, getSpace } from '@dxos/react-client/echo';
|
|
14
15
|
import { toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
15
16
|
import { type SelectionManager } from '@dxos/react-ui-attention';
|
|
16
17
|
import {
|
|
17
|
-
type
|
|
18
|
-
type
|
|
18
|
+
type PopoverMenuGroup,
|
|
19
|
+
type PopoverMenuItem,
|
|
19
20
|
type PreviewLinkRef,
|
|
20
21
|
type PreviewOptions,
|
|
21
22
|
insertAtCursor,
|
|
@@ -94,8 +95,9 @@ export const MarkdownContainer = ({
|
|
|
94
95
|
),
|
|
95
96
|
[objectForms, schemaWhiteList],
|
|
96
97
|
);
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
|
|
99
|
+
const handleLinkQuery = useCallback(
|
|
100
|
+
async (query?: string): Promise<PopoverMenuGroup[]> => {
|
|
99
101
|
const name = query?.startsWith('@') ? query.slice(1).toLowerCase() : (query?.toLowerCase() ?? '');
|
|
100
102
|
const results = await space?.db.query(Query.select(filter)).run();
|
|
101
103
|
// TODO(wittjosiah): Use `Obj.Any` type.
|
|
@@ -114,7 +116,7 @@ export const MarkdownContainer = ({
|
|
|
114
116
|
results?.objects
|
|
115
117
|
.filter((object) => toLocalizedString(getLabel(object), t).toLowerCase().includes(name))
|
|
116
118
|
// TODO(wittjosiah): Remove `any` type.
|
|
117
|
-
.map((object: any):
|
|
119
|
+
.map((object: any): PopoverMenuItem => {
|
|
118
120
|
const metadata = resolve(Obj.getTypename(object)!);
|
|
119
121
|
const label = toLocalizedString(getLabel(object), t);
|
|
120
122
|
return {
|
|
@@ -122,7 +124,7 @@ export const MarkdownContainer = ({
|
|
|
122
124
|
label,
|
|
123
125
|
icon: metadata.icon,
|
|
124
126
|
onSelect: (view, head) => {
|
|
125
|
-
const link = `[${label}]
|
|
127
|
+
const link = `[${label}](${Obj.getDXN(object)})`;
|
|
126
128
|
if (query?.startsWith('@')) {
|
|
127
129
|
insertAtLineStart(view, head, `!${link}\n`);
|
|
128
130
|
} else {
|
|
@@ -136,6 +138,7 @@ export const MarkdownContainer = ({
|
|
|
136
138
|
[filter, resolve, space],
|
|
137
139
|
);
|
|
138
140
|
|
|
141
|
+
// TODO(burdon): Reconcile variants.
|
|
139
142
|
const editor = doc ? (
|
|
140
143
|
<DocumentEditor
|
|
141
144
|
id={fullyQualifiedId(object)}
|
|
@@ -146,7 +149,7 @@ export const MarkdownContainer = ({
|
|
|
146
149
|
settings={settings}
|
|
147
150
|
scrollPastEnd={scrollPastEnd}
|
|
148
151
|
onViewModeChange={onViewModeChange}
|
|
149
|
-
onLinkQuery={space ?
|
|
152
|
+
onLinkQuery={space ? handleLinkQuery : undefined}
|
|
150
153
|
/>
|
|
151
154
|
) : text ? (
|
|
152
155
|
<MarkdownEditor
|
|
@@ -159,10 +162,9 @@ export const MarkdownContainer = ({
|
|
|
159
162
|
inputMode={settings.editorInputMode}
|
|
160
163
|
scrollPastEnd={scrollPastEnd}
|
|
161
164
|
onViewModeChange={onViewModeChange}
|
|
162
|
-
onLinkQuery={space ?
|
|
165
|
+
onLinkQuery={space ? handleLinkQuery : undefined}
|
|
163
166
|
/>
|
|
164
167
|
) : (
|
|
165
|
-
// TODO(burdon): Normalize with above.
|
|
166
168
|
<MarkdownEditor
|
|
167
169
|
id={id}
|
|
168
170
|
role={role}
|
|
@@ -173,7 +175,7 @@ export const MarkdownContainer = ({
|
|
|
173
175
|
inputMode={settings.editorInputMode}
|
|
174
176
|
scrollPastEnd={scrollPastEnd}
|
|
175
177
|
onViewModeChange={onViewModeChange}
|
|
176
|
-
onLinkQuery={space ?
|
|
178
|
+
onLinkQuery={space ? handleLinkQuery : undefined}
|
|
177
179
|
/>
|
|
178
180
|
);
|
|
179
181
|
|
|
@@ -190,9 +192,9 @@ export const MarkdownContainer = ({
|
|
|
190
192
|
// TODO(wittjosiah): This shouldn't be "card" but "block".
|
|
191
193
|
// It's not a preview card but an interactive embedded object.
|
|
192
194
|
const PreviewBlock = ({ link, el }: { link: PreviewLinkRef; el: HTMLElement }) => {
|
|
193
|
-
const
|
|
194
|
-
const
|
|
195
|
-
const
|
|
195
|
+
const client = useClient();
|
|
196
|
+
const dxn = DXN.parse(link.ref);
|
|
197
|
+
const subject = client.graph.ref(dxn).target;
|
|
196
198
|
const data = useMemo(() => ({ subject }), [subject]);
|
|
197
199
|
|
|
198
200
|
return createPortal(<Surface role='card--transclusion' data={data} limit={1} />, el);
|
|
@@ -2,17 +2,16 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@
|
|
6
|
-
|
|
7
|
-
import { type Meta } from '@storybook/react-vite';
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
6
|
import React, { useMemo } from 'react';
|
|
9
7
|
|
|
10
8
|
import { IntentPlugin } from '@dxos/app-framework';
|
|
11
9
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
12
10
|
import { createDocAccessor, createObject } from '@dxos/react-client/echo';
|
|
11
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
13
12
|
import { withAttention } from '@dxos/react-ui-attention/testing';
|
|
14
13
|
import { automerge, translations as editorTranslations } from '@dxos/react-ui-editor';
|
|
15
|
-
import {
|
|
14
|
+
import { Stack, StackItem } from '@dxos/react-ui-stack';
|
|
16
15
|
|
|
17
16
|
import { translations } from '../../translations';
|
|
18
17
|
|
|
@@ -28,33 +27,37 @@ type StoryProps = MarkdownEditorProps & {
|
|
|
28
27
|
const DefaultStory = ({ content = '# Test', toolbar }: StoryProps) => {
|
|
29
28
|
const doc = useMemo(() => createObject({ content }), [content]); // TODO(burdon): Remove dependency on createObject.
|
|
30
29
|
const extensions = useMemo(() => [automerge(createDocAccessor(doc, ['content']))], [doc]);
|
|
31
|
-
return
|
|
30
|
+
return (
|
|
31
|
+
<Stack orientation='horizontal' rail={false}>
|
|
32
|
+
<StackItem.Root item={{ id: 'story' }}>
|
|
33
|
+
<MarkdownEditor id='test' initialValue={doc.content} extensions={extensions} toolbar={toolbar} />
|
|
34
|
+
</StackItem.Root>
|
|
35
|
+
</Stack>
|
|
36
|
+
);
|
|
32
37
|
};
|
|
33
38
|
|
|
34
|
-
const meta
|
|
39
|
+
const meta = {
|
|
35
40
|
title: 'plugins/plugin-markdown/MarkdownEditor',
|
|
36
|
-
component: MarkdownEditor,
|
|
41
|
+
component: MarkdownEditor as any,
|
|
37
42
|
render: DefaultStory,
|
|
38
|
-
decorators: [
|
|
39
|
-
withPluginManager({ plugins: [IntentPlugin()] }),
|
|
40
|
-
withAttention,
|
|
41
|
-
withTheme,
|
|
42
|
-
withLayout({ fullscreen: true }),
|
|
43
|
-
],
|
|
43
|
+
decorators: [withTheme, withPluginManager({ plugins: [IntentPlugin()] }), withAttention],
|
|
44
44
|
parameters: {
|
|
45
|
+
layout: 'fullscreen',
|
|
45
46
|
translations: [...translations, ...editorTranslations],
|
|
46
47
|
},
|
|
47
|
-
}
|
|
48
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
48
49
|
|
|
49
50
|
export default meta;
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
type Story = StoryObj<typeof meta>;
|
|
53
|
+
|
|
54
|
+
export const Default: Story = {
|
|
52
55
|
args: {
|
|
53
56
|
content,
|
|
54
57
|
},
|
|
55
58
|
};
|
|
56
59
|
|
|
57
|
-
export const WithToolbar = {
|
|
60
|
+
export const WithToolbar: Story = {
|
|
58
61
|
args: {
|
|
59
62
|
toolbar: true,
|
|
60
63
|
content,
|
|
@@ -8,10 +8,8 @@ import { useDropzone } from 'react-dropzone';
|
|
|
8
8
|
|
|
9
9
|
import { type FileInfo } from '@dxos/app-framework';
|
|
10
10
|
import { invariant } from '@dxos/invariant';
|
|
11
|
-
import { toLocalizedString, useThemeContext, useTranslation } from '@dxos/react-ui';
|
|
11
|
+
import { Domino, toLocalizedString, useThemeContext, useTranslation } from '@dxos/react-ui';
|
|
12
12
|
import {
|
|
13
|
-
CommandMenu,
|
|
14
|
-
type CommandMenuGroup,
|
|
15
13
|
type DNDOptions,
|
|
16
14
|
type EditorInputMode,
|
|
17
15
|
type EditorSelectionState,
|
|
@@ -19,29 +17,29 @@ import {
|
|
|
19
17
|
EditorToolbar,
|
|
20
18
|
type EditorToolbarActionGraphProps,
|
|
21
19
|
type EditorViewMode,
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
type PopoverMenuGroup,
|
|
21
|
+
PopoverMenuProvider,
|
|
22
|
+
type UsePopoverMenuProps,
|
|
24
23
|
type UseTextEditorProps,
|
|
25
24
|
addLink,
|
|
26
|
-
coreSlashCommands,
|
|
27
25
|
createBasicExtensions,
|
|
28
|
-
createElement,
|
|
29
26
|
createMarkdownExtensions,
|
|
30
27
|
createThemeExtensions,
|
|
31
28
|
dropFile,
|
|
32
29
|
editorGutter,
|
|
33
30
|
editorSlots,
|
|
34
|
-
|
|
31
|
+
filterMenuGroups,
|
|
32
|
+
formattingCommands,
|
|
35
33
|
linkSlashCommands,
|
|
36
34
|
processEditorPayload,
|
|
37
35
|
stackItemContentEditorClassNames,
|
|
38
|
-
useCommandMenu,
|
|
39
36
|
useEditorToolbarState,
|
|
40
37
|
useFormattingState,
|
|
38
|
+
usePopoverMenu,
|
|
41
39
|
useTextEditor,
|
|
42
40
|
} from '@dxos/react-ui-editor';
|
|
43
41
|
import { StackItem } from '@dxos/react-ui-stack';
|
|
44
|
-
import { isNonNullable,
|
|
42
|
+
import { isNonNullable, isTruthy } from '@dxos/util';
|
|
45
43
|
|
|
46
44
|
import { useSelectCurrentThread } from '../../hooks';
|
|
47
45
|
import { meta } from '../../meta';
|
|
@@ -53,16 +51,16 @@ export type MarkdownEditorProps = {
|
|
|
53
51
|
toolbar?: boolean;
|
|
54
52
|
inputMode?: EditorInputMode;
|
|
55
53
|
scrollPastEnd?: boolean;
|
|
56
|
-
slashCommandGroups?:
|
|
54
|
+
slashCommandGroups?: PopoverMenuGroup[];
|
|
57
55
|
customActions?: EditorToolbarActionGraphProps['customActions'];
|
|
58
56
|
// TODO(wittjosiah): Generalize custom toolbar actions (e.g. comment, upload, etc.)
|
|
59
57
|
viewMode?: EditorViewMode;
|
|
60
58
|
editorStateStore?: EditorStateStore;
|
|
61
59
|
onViewModeChange?: (id: string, mode: EditorViewMode) => void;
|
|
62
|
-
onLinkQuery?: (query?: string) => Promise<
|
|
60
|
+
onLinkQuery?: (query?: string) => Promise<PopoverMenuGroup[]>;
|
|
63
61
|
onFileUpload?: (file: File) => Promise<FileInfo | undefined>;
|
|
64
|
-
} & Pick<UseTextEditorProps, 'initialValue' | 'extensions'> &
|
|
65
|
-
Partial<Pick<MarkdownPluginState, 'extensionProviders'
|
|
62
|
+
} & (Pick<UseTextEditorProps, 'initialValue' | 'extensions'> &
|
|
63
|
+
Partial<Pick<MarkdownPluginState, 'extensionProviders'>>);
|
|
66
64
|
|
|
67
65
|
/**
|
|
68
66
|
* Base markdown editor component.
|
|
@@ -70,66 +68,67 @@ export type MarkdownEditorProps = {
|
|
|
70
68
|
* This allows it to be used as a common editor for markdown content on arbitrary backends (e.g. files).
|
|
71
69
|
*/
|
|
72
70
|
export const MarkdownEditor = ({
|
|
73
|
-
extensions:
|
|
71
|
+
extensions: extensionsParam,
|
|
74
72
|
slashCommandGroups,
|
|
75
73
|
onLinkQuery,
|
|
76
74
|
...props
|
|
77
75
|
}: MarkdownEditorProps) => {
|
|
78
76
|
const { t } = useTranslation();
|
|
79
|
-
const viewRef = useRef<EditorView>();
|
|
77
|
+
const viewRef = useRef<EditorView>(null);
|
|
80
78
|
|
|
81
|
-
const getMenu = useCallback(
|
|
82
|
-
(
|
|
79
|
+
const getMenu = useCallback<NonNullable<UsePopoverMenuProps['getMenu']>>(
|
|
80
|
+
({ text, trigger }) => {
|
|
83
81
|
switch (trigger) {
|
|
84
|
-
case '@':
|
|
85
|
-
return onLinkQuery?.(
|
|
82
|
+
case '@': {
|
|
83
|
+
return onLinkQuery?.(text) ?? [];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
86
|
case '/':
|
|
87
|
-
default:
|
|
88
|
-
return
|
|
89
|
-
|
|
87
|
+
default: {
|
|
88
|
+
return filterMenuGroups([formattingCommands, linkSlashCommands, ...(slashCommandGroups ?? [])], (item) =>
|
|
89
|
+
text ? toLocalizedString(item.label, t).toLowerCase().includes(text.toLowerCase()) : true,
|
|
90
90
|
);
|
|
91
|
+
}
|
|
91
92
|
}
|
|
92
93
|
},
|
|
93
94
|
[onLinkQuery, slashCommandGroups],
|
|
94
95
|
);
|
|
95
96
|
|
|
96
|
-
const options = useMemo<
|
|
97
|
+
const options = useMemo<UsePopoverMenuProps>(() => {
|
|
97
98
|
const trigger = onLinkQuery ? ['/', '@'] : ['/'];
|
|
98
99
|
return {
|
|
99
100
|
viewRef,
|
|
100
101
|
trigger,
|
|
101
102
|
placeholder: {
|
|
102
103
|
delay: 3_000,
|
|
103
|
-
content: () =>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
104
|
+
content: () =>
|
|
105
|
+
Domino.of('div')
|
|
106
|
+
.children(
|
|
107
|
+
Domino.of('span').text('Press'),
|
|
108
|
+
...trigger.map((text) =>
|
|
109
|
+
Domino.of('span')
|
|
110
|
+
.classNames('mx-1 px-1.5 pt-[1px] pb-[2px] border border-separator rounded-sm')
|
|
111
|
+
.text(text),
|
|
112
|
+
),
|
|
113
|
+
Domino.of('span').text('for commands.'),
|
|
114
|
+
)
|
|
115
|
+
.build(),
|
|
115
116
|
},
|
|
116
117
|
getMenu,
|
|
117
118
|
};
|
|
118
|
-
}, [getMenu]);
|
|
119
|
-
|
|
120
|
-
const { commandMenu, groupsRef, currentItem, onSelect, ...refPopoverProps } = useCommandMenu(options);
|
|
119
|
+
}, [onLinkQuery, getMenu]);
|
|
121
120
|
|
|
122
|
-
const
|
|
121
|
+
const { groupsRef, extension, ...commandMenuProps } = usePopoverMenu(options);
|
|
122
|
+
const extensions = useMemo(() => [extensionsParam, extension].filter(isTruthy), [extensionsParam, extension]);
|
|
123
123
|
|
|
124
124
|
return (
|
|
125
|
-
<
|
|
125
|
+
<PopoverMenuProvider view={viewRef.current} groups={groupsRef.current} {...commandMenuProps}>
|
|
126
126
|
<MarkdownEditorImpl ref={viewRef} {...props} extensions={extensions} />
|
|
127
|
-
|
|
128
|
-
</RefPopover>
|
|
127
|
+
</PopoverMenuProvider>
|
|
129
128
|
);
|
|
130
129
|
};
|
|
131
130
|
|
|
132
|
-
const MarkdownEditorImpl = forwardRef<EditorView |
|
|
131
|
+
const MarkdownEditorImpl = forwardRef<EditorView | null, MarkdownEditorProps>(
|
|
133
132
|
(
|
|
134
133
|
{
|
|
135
134
|
id,
|
|
@@ -187,13 +186,13 @@ const MarkdownEditorImpl = forwardRef<EditorView | undefined, MarkdownEditorProp
|
|
|
187
186
|
scrollPastEnd: role === 'section' ? false : scrollPastEnd,
|
|
188
187
|
search: true,
|
|
189
188
|
}),
|
|
190
|
-
createMarkdownExtensions(
|
|
189
|
+
createMarkdownExtensions(),
|
|
191
190
|
createThemeExtensions({ themeMode, syntaxHighlighting: true, slots: editorSlots }),
|
|
192
191
|
editorGutter,
|
|
193
192
|
role !== 'section' && onFileUpload && dropFile({ onDrop: handleDrop }),
|
|
194
193
|
providerExtensions,
|
|
195
194
|
extensions,
|
|
196
|
-
].filter(
|
|
195
|
+
].filter(isTruthy),
|
|
197
196
|
...(role !== 'section' && {
|
|
198
197
|
id,
|
|
199
198
|
scrollTo,
|
|
@@ -206,7 +205,7 @@ const MarkdownEditorImpl = forwardRef<EditorView | undefined, MarkdownEditorProp
|
|
|
206
205
|
[id, formattingObserver, viewMode, themeMode, extensions, providerExtensions],
|
|
207
206
|
);
|
|
208
207
|
|
|
209
|
-
useImperativeHandle(forwardedRef, () => editorView, [editorView]);
|
|
208
|
+
useImperativeHandle<EditorView | null, EditorView | null>(forwardedRef, () => editorView, [editorView]);
|
|
210
209
|
useTest(editorView);
|
|
211
210
|
useSelectCurrentThread(editorView, id);
|
|
212
211
|
|
|
@@ -285,7 +284,7 @@ const MarkdownEditorImpl = forwardRef<EditorView | undefined, MarkdownEditorProp
|
|
|
285
284
|
|
|
286
285
|
// Expose editor view for playwright tests.
|
|
287
286
|
// TODO(wittjosiah): Find a better way to expose this or find a way to limit it to test runs.
|
|
288
|
-
const useTest = (view
|
|
287
|
+
const useTest = (view: EditorView | null) => {
|
|
289
288
|
useEffect(() => {
|
|
290
289
|
const composer = (window as any).composer;
|
|
291
290
|
if (composer) {
|