@dxos/plugin-preview 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/chunk-CEWM5LJG.mjs +17 -0
- package/dist/lib/browser/chunk-CEWM5LJG.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +11 -7
- package/dist/lib/browser/index.mjs.map +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{preview-popover-MAIBTJKJ.mjs → preview-popover-RKHENTFP.mjs} +9 -13
- package/dist/lib/browser/preview-popover-RKHENTFP.mjs.map +7 -0
- package/dist/lib/browser/react-surface-3AR3BFLF.mjs +515 -0
- package/dist/lib/browser/react-surface-3AR3BFLF.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-Q5MUNELK.mjs +19 -0
- package/dist/lib/node-esm/chunk-Q5MUNELK.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +11 -7
- package/dist/lib/node-esm/index.mjs.map +2 -2
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{preview-popover-LZGHYW23.mjs → preview-popover-TZKX67EY.mjs} +9 -13
- package/dist/lib/node-esm/preview-popover-TZKX67EY.mjs.map +7 -0
- package/dist/lib/node-esm/react-surface-L37JR7U2.mjs +516 -0
- package/dist/lib/node-esm/react-surface-L37JR7U2.mjs.map +7 -0
- package/dist/types/src/PreviewPlugin.d.ts +1 -1
- package/dist/types/src/PreviewPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/preview-popover.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/cards/ContactCard.d.ts +5 -0
- package/dist/types/src/cards/ContactCard.d.ts.map +1 -0
- package/dist/types/src/{components → cards}/OrganizationCard.d.ts +1 -1
- package/dist/types/src/cards/OrganizationCard.d.ts.map +1 -0
- package/dist/types/src/cards/ProjectCard.d.ts +5 -0
- package/dist/types/src/cards/ProjectCard.d.ts.map +1 -0
- package/dist/types/src/cards/TaskCard.d.ts +5 -0
- package/dist/types/src/cards/TaskCard.d.ts.map +1 -0
- package/dist/types/src/cards/index.d.ts +5 -0
- package/dist/types/src/cards/index.d.ts.map +1 -0
- package/dist/types/src/components/CardComponents.d.ts +16 -0
- package/dist/types/src/components/CardComponents.d.ts.map +1 -0
- package/dist/types/src/components/CardSubjectMenu.d.ts +3 -5
- package/dist/types/src/components/CardSubjectMenu.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +2 -3
- package/dist/types/src/components/index.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/stories/Card.stories.d.ts +7 -1
- package/dist/types/src/stories/Card.stories.d.ts.map +1 -1
- package/dist/types/src/stories/testing.d.ts +2 -1
- package/dist/types/src/stories/testing.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +6 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +5 -2
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -32
- package/src/PreviewPlugin.tsx +22 -23
- package/src/capabilities/preview-popover.ts +7 -12
- package/src/capabilities/react-surface.tsx +61 -76
- package/src/cards/ContactCard.tsx +65 -0
- package/src/cards/OrganizationCard.tsx +25 -0
- package/src/cards/ProjectCard.tsx +24 -0
- package/src/cards/TaskCard.tsx +46 -0
- package/src/cards/index.ts +8 -0
- package/src/components/CardComponents.tsx +67 -0
- package/src/components/CardSubjectMenu.tsx +60 -25
- package/src/components/index.ts +2 -3
- package/src/meta.ts +6 -3
- package/src/stories/Card.stories.tsx +12 -9
- package/src/stories/testing.tsx +24 -13
- package/src/translations.ts +6 -0
- package/src/types.ts +6 -2
- package/dist/lib/browser/chunk-Z73ENKLE.mjs +0 -14
- package/dist/lib/browser/chunk-Z73ENKLE.mjs.map +0 -7
- package/dist/lib/browser/preview-popover-MAIBTJKJ.mjs.map +0 -7
- package/dist/lib/browser/react-surface-F5B3N276.mjs +0 -380
- package/dist/lib/browser/react-surface-F5B3N276.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2ORSL4GJ.mjs +0 -16
- package/dist/lib/node-esm/chunk-2ORSL4GJ.mjs.map +0 -7
- package/dist/lib/node-esm/preview-popover-LZGHYW23.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-4TLL7CWP.mjs +0 -381
- package/dist/lib/node-esm/react-surface-4TLL7CWP.mjs.map +0 -7
- package/dist/types/src/components/ContactCard.d.ts +0 -7
- package/dist/types/src/components/ContactCard.d.ts.map +0 -1
- package/dist/types/src/components/OrganizationCard.d.ts.map +0 -1
- package/dist/types/src/components/ProjectCard.d.ts +0 -5
- package/dist/types/src/components/ProjectCard.d.ts.map +0 -1
- package/src/components/ContactCard.tsx +0 -76
- package/src/components/OrganizationCard.tsx +0 -44
- package/src/components/ProjectCard.tsx +0 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-preview",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.ae835ea",
|
|
4
4
|
"description": "Preview plugin",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -24,43 +24,43 @@
|
|
|
24
24
|
"src"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@effect-rx/rx-react": "0.
|
|
27
|
+
"@effect-rx/rx-react": "0.42.4",
|
|
28
28
|
"@preact-signals/safe-react": "^0.9.0",
|
|
29
|
-
"@dxos/app-
|
|
30
|
-
"@dxos/app-
|
|
31
|
-
"@dxos/
|
|
32
|
-
"@dxos/echo": "0.8.4-main.
|
|
33
|
-
"@dxos/keys": "0.8.4-main.
|
|
34
|
-
"@dxos/
|
|
35
|
-
"@dxos/
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/plugin-
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/react-client": "0.8.4-main.
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/react-ui-editor": "0.8.4-main.
|
|
44
|
-
"@dxos/react-ui-
|
|
45
|
-
"@dxos/react-ui-
|
|
46
|
-
"@dxos/react-ui-stack": "0.8.4-main.
|
|
47
|
-
"@dxos/react-ui-theme": "0.8.4-main.
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/
|
|
50
|
-
"@dxos/
|
|
29
|
+
"@dxos/app-graph": "0.8.4-main.ae835ea",
|
|
30
|
+
"@dxos/app-framework": "0.8.4-main.ae835ea",
|
|
31
|
+
"@dxos/async": "0.8.4-main.ae835ea",
|
|
32
|
+
"@dxos/echo": "0.8.4-main.ae835ea",
|
|
33
|
+
"@dxos/keys": "0.8.4-main.ae835ea",
|
|
34
|
+
"@dxos/lit-ui": "0.8.4-main.ae835ea",
|
|
35
|
+
"@dxos/plugin-attention": "0.8.4-main.ae835ea",
|
|
36
|
+
"@dxos/client": "0.8.4-main.ae835ea",
|
|
37
|
+
"@dxos/plugin-client": "0.8.4-main.ae835ea",
|
|
38
|
+
"@dxos/plugin-deck": "0.8.4-main.ae835ea",
|
|
39
|
+
"@dxos/log": "0.8.4-main.ae835ea",
|
|
40
|
+
"@dxos/react-client": "0.8.4-main.ae835ea",
|
|
41
|
+
"@dxos/react-ui": "0.8.4-main.ae835ea",
|
|
42
|
+
"@dxos/plugin-space": "0.8.4-main.ae835ea",
|
|
43
|
+
"@dxos/react-ui-editor": "0.8.4-main.ae835ea",
|
|
44
|
+
"@dxos/react-ui-menu": "0.8.4-main.ae835ea",
|
|
45
|
+
"@dxos/react-ui-table": "0.8.4-main.ae835ea",
|
|
46
|
+
"@dxos/react-ui-stack": "0.8.4-main.ae835ea",
|
|
47
|
+
"@dxos/react-ui-theme": "0.8.4-main.ae835ea",
|
|
48
|
+
"@dxos/schema": "0.8.4-main.ae835ea",
|
|
49
|
+
"@dxos/util": "0.8.4-main.ae835ea",
|
|
50
|
+
"@dxos/react-ui-form": "0.8.4-main.ae835ea"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"effect": "3.
|
|
54
|
-
"react": "~
|
|
55
|
-
"react-dom": "~
|
|
56
|
-
"vite": "7.1.
|
|
57
|
-
"@dxos/
|
|
58
|
-
"@dxos/
|
|
53
|
+
"effect": "3.18.3",
|
|
54
|
+
"react": "~19.2.0",
|
|
55
|
+
"react-dom": "~19.2.0",
|
|
56
|
+
"vite": "7.1.9",
|
|
57
|
+
"@dxos/storybook-utils": "0.8.4-main.ae835ea",
|
|
58
|
+
"@dxos/random": "0.8.4-main.ae835ea"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"effect": "^3.13.3",
|
|
62
|
-
"react": "
|
|
63
|
-
"react-dom": "
|
|
62
|
+
"react": "^19.0.0",
|
|
63
|
+
"react-dom": "^19.0.0"
|
|
64
64
|
},
|
|
65
65
|
"publishConfig": {
|
|
66
66
|
"access": "public"
|
package/src/PreviewPlugin.tsx
CHANGED
|
@@ -10,26 +10,25 @@ import { PreviewPopover, ReactSurface } from './capabilities';
|
|
|
10
10
|
import { meta } from './meta';
|
|
11
11
|
import { translations } from './translations';
|
|
12
12
|
|
|
13
|
-
export const PreviewPlugin = () =>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
]);
|
|
13
|
+
export const PreviewPlugin = definePlugin(meta, () => [
|
|
14
|
+
defineModule({
|
|
15
|
+
id: `${meta.id}/module/translations`,
|
|
16
|
+
activatesOn: Events.SetupTranslations,
|
|
17
|
+
activate: () => contributes(Capabilities.Translations, translations),
|
|
18
|
+
}),
|
|
19
|
+
defineModule({
|
|
20
|
+
id: `${meta.id}/module/schema`,
|
|
21
|
+
activatesOn: ClientEvents.SetupSchema,
|
|
22
|
+
activate: () => [contributes(ClientCapabilities.Schema, [DataType.Person, DataType.Organization])],
|
|
23
|
+
}),
|
|
24
|
+
defineModule({
|
|
25
|
+
id: `${meta.id}/module/preview-popover`,
|
|
26
|
+
activatesOn: Events.Startup,
|
|
27
|
+
activate: PreviewPopover,
|
|
28
|
+
}),
|
|
29
|
+
defineModule({
|
|
30
|
+
id: `${meta.id}/module/react-surface`,
|
|
31
|
+
activatesOn: Events.SetupReactSurface,
|
|
32
|
+
activate: ReactSurface,
|
|
33
|
+
}),
|
|
34
|
+
]);
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
import { Capabilities, LayoutAction, type PluginContext, contributes, createIntent } from '@dxos/app-framework';
|
|
6
6
|
import { addEventListener } from '@dxos/async';
|
|
7
|
-
import { type Client
|
|
7
|
+
import { type Client } from '@dxos/client';
|
|
8
8
|
import { type Space, parseId } from '@dxos/client/echo';
|
|
9
9
|
import { DXN } from '@dxos/keys';
|
|
10
|
-
import { type DxRefTagActivate } from '@dxos/lit-ui';
|
|
11
10
|
import { log } from '@dxos/log';
|
|
12
11
|
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
12
|
+
import { DX_ANCHOR_ACTIVATE, type DxAnchorActivate } from '@dxos/react-ui';
|
|
13
13
|
import { type PreviewLinkRef, type PreviewLinkTarget } from '@dxos/react-ui-editor';
|
|
14
14
|
|
|
15
15
|
const customEventOptions = { capture: true, passive: false };
|
|
@@ -20,21 +20,16 @@ const handlePreviewLookup = async (
|
|
|
20
20
|
{ ref, label }: PreviewLinkRef,
|
|
21
21
|
): Promise<PreviewLinkTarget | null> => {
|
|
22
22
|
try {
|
|
23
|
-
const
|
|
24
|
-
if (!dxn) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const object = await resolveRef(client, dxn, defaultSpace);
|
|
23
|
+
const object = await defaultSpace.db.ref(DXN.parse(ref)).load();
|
|
29
24
|
return { label, object };
|
|
30
|
-
} catch
|
|
25
|
+
} catch {
|
|
31
26
|
return null;
|
|
32
27
|
}
|
|
33
28
|
};
|
|
34
29
|
|
|
35
30
|
export default (context: PluginContext) => {
|
|
36
31
|
// TODO(wittjosiah): Factor out lookup handlers to other plugins to make not ECHO-specific.
|
|
37
|
-
const
|
|
32
|
+
const handleDxAnchorActivate = async ({ refId, label, trigger }: DxAnchorActivate) => {
|
|
38
33
|
const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
|
|
39
34
|
const client = context.getCapability(ClientCapabilities.Client);
|
|
40
35
|
const [layout] = context.getCapabilities(Capabilities.Layout);
|
|
@@ -62,8 +57,8 @@ export default (context: PluginContext) => {
|
|
|
62
57
|
if (document.defaultView) {
|
|
63
58
|
cleanup = addEventListener(
|
|
64
59
|
document.defaultView,
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
DX_ANCHOR_ACTIVATE as any,
|
|
61
|
+
handleDxAnchorActivate,
|
|
67
62
|
customEventOptions,
|
|
68
63
|
);
|
|
69
64
|
} else {
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Effect } from 'effect';
|
|
6
5
|
import React, { useCallback } from 'react';
|
|
7
6
|
|
|
8
7
|
import {
|
|
@@ -15,20 +14,17 @@ import {
|
|
|
15
14
|
useIntentDispatcher,
|
|
16
15
|
} from '@dxos/app-framework';
|
|
17
16
|
import { fullyQualifiedId, getSchema, getSpace } from '@dxos/client/echo';
|
|
18
|
-
import {
|
|
19
|
-
import { type JsonPath, setValue } from '@dxos/echo
|
|
20
|
-
import {
|
|
21
|
-
import { ATTENDABLE_PATH_SEPARATOR, DeckAction } from '@dxos/plugin-deck/types';
|
|
22
|
-
import { useQuery, useSpace } from '@dxos/react-client/echo';
|
|
17
|
+
import { Obj } from '@dxos/echo';
|
|
18
|
+
import { type JsonPath, setValue } from '@dxos/echo/internal';
|
|
19
|
+
import { useActiveSpace } from '@dxos/plugin-space';
|
|
23
20
|
import { useTranslation } from '@dxos/react-ui';
|
|
24
21
|
import { Form } from '@dxos/react-ui-form';
|
|
25
22
|
import { Card } from '@dxos/react-ui-stack';
|
|
26
|
-
import { Table } from '@dxos/react-ui-table/types';
|
|
27
23
|
import { descriptionMessage, mx } from '@dxos/react-ui-theme';
|
|
28
24
|
import { DataType, type ProjectionModel } from '@dxos/schema';
|
|
29
25
|
|
|
30
|
-
import { ContactCard, OrganizationCard, ProjectCard } from '../
|
|
31
|
-
import {
|
|
26
|
+
import { ContactCard, OrganizationCard, ProjectCard, TaskCard } from '../cards';
|
|
27
|
+
import { meta } from '../meta';
|
|
32
28
|
|
|
33
29
|
export default () =>
|
|
34
30
|
contributes(Capabilities.ReactSurface, [
|
|
@@ -36,103 +32,76 @@ export default () =>
|
|
|
36
32
|
// Specific schema types.
|
|
37
33
|
//
|
|
38
34
|
createSurface({
|
|
39
|
-
id: `${
|
|
35
|
+
id: `${meta.id}/schema-popover--contact`,
|
|
40
36
|
role: ['card--popover', 'card--intrinsic', 'card--transclusion', 'card--extrinsic', 'card'],
|
|
41
37
|
filter: (data): data is { subject: DataType.Person } => Obj.instanceOf(DataType.Person, data.subject),
|
|
42
38
|
component: ({ data, role }) => {
|
|
43
|
-
const { dispatch } = useIntentDispatcher();
|
|
39
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
44
40
|
const space = getSpace(data.subject);
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Obj.instanceOf(Table.Table, view.presentation.target),
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
// TODO(wittjosiah): Generalized way of handling related objects navigation.
|
|
62
|
-
const handleOrgClick = useCallback(
|
|
63
|
-
(org: DataType.Organization) =>
|
|
64
|
-
Effect.gen(function* () {
|
|
65
|
-
const view = currentSpaceOrgs.includes(org) ? currentSpaceOrgTable : defaultSpaceOrgTable;
|
|
66
|
-
yield* dispatch(
|
|
67
|
-
createIntent(LayoutAction.UpdatePopover, {
|
|
68
|
-
part: 'popover',
|
|
69
|
-
options: {
|
|
70
|
-
state: false,
|
|
71
|
-
anchorId: '',
|
|
72
|
-
},
|
|
73
|
-
}),
|
|
74
|
-
);
|
|
75
|
-
if (view) {
|
|
76
|
-
const id = fullyQualifiedId(view);
|
|
77
|
-
yield* dispatch(
|
|
78
|
-
createIntent(LayoutAction.Open, {
|
|
79
|
-
part: 'main',
|
|
80
|
-
subject: [id],
|
|
81
|
-
options: { workspace: space?.id },
|
|
82
|
-
}),
|
|
83
|
-
);
|
|
84
|
-
yield* dispatch(
|
|
85
|
-
createIntent(DeckAction.ChangeCompanion, {
|
|
86
|
-
primary: id,
|
|
87
|
-
companion: [id, 'selected-objects'].join(ATTENDABLE_PATH_SEPARATOR),
|
|
88
|
-
}),
|
|
89
|
-
);
|
|
90
|
-
yield* dispatch(
|
|
91
|
-
createIntent(AttentionAction.Select, {
|
|
92
|
-
contextId: id,
|
|
93
|
-
selection: { mode: 'multi', ids: [org.id] },
|
|
94
|
-
}),
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
}).pipe(Effect.runPromise),
|
|
98
|
-
[dispatch, currentSpaceOrgs, currentSpaceOrgTable, defaultSpaceOrgTable],
|
|
41
|
+
const activeSpace = useActiveSpace();
|
|
42
|
+
const handleSelect = useCallback(
|
|
43
|
+
(org: Obj.Any) =>
|
|
44
|
+
dispatch(
|
|
45
|
+
createIntent(LayoutAction.Open, {
|
|
46
|
+
part: 'main',
|
|
47
|
+
subject: [fullyQualifiedId(org)],
|
|
48
|
+
options: {
|
|
49
|
+
workspace: space?.id,
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
),
|
|
53
|
+
[dispatch],
|
|
99
54
|
);
|
|
100
55
|
|
|
101
56
|
return (
|
|
102
|
-
<ContactCard role={role} subject={data.subject}
|
|
57
|
+
<ContactCard role={role} subject={data.subject} activeSpace={activeSpace} onSelect={handleSelect}>
|
|
103
58
|
{role === 'card--popover' && <Surface role='related' data={data} />}
|
|
104
59
|
</ContactCard>
|
|
105
60
|
);
|
|
106
61
|
},
|
|
107
62
|
}),
|
|
108
63
|
createSurface({
|
|
109
|
-
id: `${
|
|
64
|
+
id: `${meta.id}/schema-popover--organization`,
|
|
110
65
|
role: ['card--popover', 'card--intrinsic', 'card--transclusion', 'card--extrinsic', 'card'],
|
|
111
66
|
filter: (data): data is { subject: DataType.Organization } => Obj.instanceOf(DataType.Organization, data.subject),
|
|
112
|
-
component: ({ data, role }) =>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
67
|
+
component: ({ data, role }) => {
|
|
68
|
+
const activeSpace = useActiveSpace();
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<OrganizationCard role={role} subject={data.subject} activeSpace={activeSpace}>
|
|
72
|
+
{role === 'card--popover' && <Surface role='related' data={data} />}
|
|
73
|
+
</OrganizationCard>
|
|
74
|
+
);
|
|
75
|
+
},
|
|
117
76
|
}),
|
|
118
77
|
createSurface({
|
|
119
|
-
id: `${
|
|
78
|
+
id: `${meta.id}/schema-popover--project`,
|
|
120
79
|
role: ['card--popover', 'card--intrinsic', 'card--transclusion', 'card--extrinsic', 'card'],
|
|
121
80
|
filter: (data): data is { subject: DataType.Project } => Obj.instanceOf(DataType.Project, data.subject),
|
|
122
|
-
component: ({ data, role }) =>
|
|
81
|
+
component: ({ data, role }) => {
|
|
82
|
+
const activeSpace = useActiveSpace();
|
|
83
|
+
|
|
84
|
+
return <ProjectCard subject={data.subject} role={role} activeSpace={activeSpace} />;
|
|
85
|
+
},
|
|
86
|
+
}),
|
|
87
|
+
createSurface({
|
|
88
|
+
id: `${meta.id}/schema-popover--task`,
|
|
89
|
+
role: ['card--popover', 'card--intrinsic', 'card--transclusion', 'card--extrinsic', 'card'],
|
|
90
|
+
filter: (data): data is { subject: DataType.Task } => Obj.instanceOf(DataType.Task, data.subject),
|
|
91
|
+
component: ({ data, role }) => <TaskCard subject={data.subject} role={role} />,
|
|
123
92
|
}),
|
|
124
93
|
|
|
125
94
|
//
|
|
126
95
|
// Fallback for any object.
|
|
127
96
|
//
|
|
128
97
|
createSurface({
|
|
129
|
-
id: `${
|
|
98
|
+
id: `${meta.id}/fallback-popover`,
|
|
130
99
|
role: ['card--popover', 'card--intrinsic', 'card--transclusion', 'card--extrinsic', 'card'],
|
|
131
100
|
position: 'fallback',
|
|
132
101
|
filter: (data): data is { subject: Obj.Any; projection?: ProjectionModel } => Obj.isObject(data.subject),
|
|
133
102
|
component: ({ data, role }) => {
|
|
134
103
|
const schema = getSchema(data.subject);
|
|
135
|
-
const { t } = useTranslation(
|
|
104
|
+
const { t } = useTranslation(meta.id);
|
|
136
105
|
if (!schema) {
|
|
137
106
|
// TODO(burdon): Use Alert.
|
|
138
107
|
return <p className={mx(descriptionMessage)}>{t('unable to create preview message')}</p>;
|
|
@@ -161,4 +130,20 @@ export default () =>
|
|
|
161
130
|
);
|
|
162
131
|
},
|
|
163
132
|
}),
|
|
133
|
+
|
|
134
|
+
createSurface({
|
|
135
|
+
id: `${meta.id}/section`,
|
|
136
|
+
role: ['section'],
|
|
137
|
+
position: 'fallback',
|
|
138
|
+
filter: (data): data is { subject: Obj.Any } => Obj.isObject(data.subject),
|
|
139
|
+
component: ({ data }) => {
|
|
140
|
+
return (
|
|
141
|
+
<div role='none' className='flex justify-center'>
|
|
142
|
+
<div role='none' className='card-max-width'>
|
|
143
|
+
<Surface role='card' data={data} limit={1} />
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
147
|
+
},
|
|
148
|
+
}),
|
|
164
149
|
]);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { Fragment } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Avatar, Icon } from '@dxos/react-ui';
|
|
8
|
+
import { Card, cardHeading, cardText } from '@dxos/react-ui-stack';
|
|
9
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
10
|
+
import { type DataType } from '@dxos/schema';
|
|
11
|
+
|
|
12
|
+
import { CardRow, CardSubjectMenu, gridRow } from '../components';
|
|
13
|
+
import { type PreviewProps } from '../types';
|
|
14
|
+
|
|
15
|
+
// TODO(burdon): Rename PersonCard.
|
|
16
|
+
export const ContactCard = ({ children, role, subject, activeSpace, onSelect }: PreviewProps<DataType.Person>) => {
|
|
17
|
+
const { fullName, image, organization: { target: organization } = {}, emails } = subject;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Card.SurfaceRoot role={role}>
|
|
21
|
+
<Avatar.Root>
|
|
22
|
+
<Card.Text role='group' classNames={mx('grid gap-2 grid-cols-[1fr_min-content]')}>
|
|
23
|
+
<div role='none' className={mx(gridRow, 'grid-rows-2')}>
|
|
24
|
+
{activeSpace ? <CardSubjectMenu subject={subject} activeSpace={activeSpace} /> : <div />}
|
|
25
|
+
<Avatar.Label asChild>
|
|
26
|
+
<h2 className={mx(cardHeading, 'grow truncate')}>{fullName}</h2>
|
|
27
|
+
</Avatar.Label>
|
|
28
|
+
</div>
|
|
29
|
+
<Avatar.Content
|
|
30
|
+
imgSrc={image}
|
|
31
|
+
icon='ph--user--regular'
|
|
32
|
+
size={16}
|
|
33
|
+
classNames='text-subdued'
|
|
34
|
+
hue='neutral'
|
|
35
|
+
variant='square'
|
|
36
|
+
/>
|
|
37
|
+
</Card.Text>
|
|
38
|
+
</Avatar.Root>
|
|
39
|
+
{organization?.name && (
|
|
40
|
+
<CardRow
|
|
41
|
+
icon='ph--buildings--regular'
|
|
42
|
+
label={organization.name}
|
|
43
|
+
onClick={onSelect ? () => onSelect(organization) : undefined}
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
{emails?.length && (
|
|
47
|
+
<dl className={mx(cardText, gridRow, '[&_dt]:text-subdued [&_dt]:pbs-0.5 [&_dd]:min-is-0')}>
|
|
48
|
+
{emails?.length &&
|
|
49
|
+
emails.map(({ label, value }) => (
|
|
50
|
+
<Fragment key={value}>
|
|
51
|
+
<dt>
|
|
52
|
+
<span className='sr-only'>{label}</span>
|
|
53
|
+
<Icon icon='ph--at--regular' size={5} />
|
|
54
|
+
</dt>
|
|
55
|
+
<dd key={value} className='col-span-2 break-words'>
|
|
56
|
+
{value}
|
|
57
|
+
</dd>
|
|
58
|
+
</Fragment>
|
|
59
|
+
))}
|
|
60
|
+
</dl>
|
|
61
|
+
)}
|
|
62
|
+
{children}
|
|
63
|
+
</Card.SurfaceRoot>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { Card } from '@dxos/react-ui-stack';
|
|
8
|
+
import { type DataType } from '@dxos/schema';
|
|
9
|
+
|
|
10
|
+
import { CardHeader, CardLink } from '../components';
|
|
11
|
+
import { type PreviewProps } from '../types';
|
|
12
|
+
|
|
13
|
+
export const OrganizationCard = ({ children, subject, role, activeSpace }: PreviewProps<DataType.Organization>) => {
|
|
14
|
+
const { name, image, description, website } = subject;
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Card.SurfaceRoot role={role}>
|
|
18
|
+
<Card.Poster alt={name ?? ''} {...(image ? { image } : { icon: 'ph--building-office--regular' })} />
|
|
19
|
+
<CardHeader label={name} subject={subject} activeSpace={activeSpace} />
|
|
20
|
+
{description && <Card.Text classNames='line-clamp-2'>{description}</Card.Text>}
|
|
21
|
+
{website && <CardLink label={website} href={website} />}
|
|
22
|
+
{children}
|
|
23
|
+
</Card.SurfaceRoot>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { Obj } from '@dxos/echo';
|
|
8
|
+
import { Card } from '@dxos/react-ui-stack';
|
|
9
|
+
import { type DataType } from '@dxos/schema';
|
|
10
|
+
|
|
11
|
+
import { CardHeader } from '../components';
|
|
12
|
+
import { type PreviewProps } from '../types';
|
|
13
|
+
|
|
14
|
+
export const ProjectCard = ({ subject, role, activeSpace }: PreviewProps<DataType.Project>) => {
|
|
15
|
+
const { name, image, description } = subject;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Card.SurfaceRoot role={role}>
|
|
19
|
+
{image && <Card.Poster image={image} alt={Obj.getLabel(subject) ?? ''} aspect='auto' />}
|
|
20
|
+
<CardHeader label={name} subject={subject} activeSpace={activeSpace} />
|
|
21
|
+
{description && <Card.Text classNames='line-clamp-2'>{description}</Card.Text>}
|
|
22
|
+
</Card.SurfaceRoot>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as SchemaAST from 'effect/SchemaAST';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { type PropertyMetaAnnotation, PropertyMetaAnnotationId } from '@dxos/echo/internal';
|
|
9
|
+
import { Card, cardNoSpacing, cardSpacing } from '@dxos/react-ui-stack';
|
|
10
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
11
|
+
import { DataType } from '@dxos/schema';
|
|
12
|
+
|
|
13
|
+
import { CardSubjectMenu } from '../components';
|
|
14
|
+
import { type PreviewProps } from '../types';
|
|
15
|
+
|
|
16
|
+
// TODO(thure): Should this move upstream as a helper? Is there an easier way to get options?
|
|
17
|
+
const getActiveStatusOption = (status?: string) => {
|
|
18
|
+
const properties = SchemaAST.getPropertySignatures(DataType.Task.ast);
|
|
19
|
+
const statusProperty = properties.find((p) => p.name === 'status');
|
|
20
|
+
const statusMeta = SchemaAST.getAnnotation<PropertyMetaAnnotation>(PropertyMetaAnnotationId)(
|
|
21
|
+
// TODO(thure): Typescript asserts `.type` doesn’t have `.types`, but in runtime it does.
|
|
22
|
+
(statusProperty!.type as any).types[0],
|
|
23
|
+
);
|
|
24
|
+
const options = // TODO(thure): Typescript asserts `statusMeta` doesn’t have `.value`, but in runtime it does.
|
|
25
|
+
(statusMeta as any).value.singleSelect.options as { id: string; title: string; color: string }[];
|
|
26
|
+
return options.find(({ id }) => id === status);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const TaskCard = ({ subject, role, activeSpace }: PreviewProps<DataType.Task>) => {
|
|
30
|
+
const { title, status } = subject;
|
|
31
|
+
const statusOption = getActiveStatusOption(status);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Card.SurfaceRoot role={role}>
|
|
35
|
+
<div role='none' className={mx('flex items-center gap-2', cardSpacing)}>
|
|
36
|
+
<Card.Heading classNames={[cardNoSpacing, 'min-is-0 flex-1 truncate']}>{title}</Card.Heading>
|
|
37
|
+
{statusOption && (
|
|
38
|
+
<span className='dx-tag' data-hue={statusOption.color}>
|
|
39
|
+
{statusOption.title}
|
|
40
|
+
</span>
|
|
41
|
+
)}
|
|
42
|
+
<CardSubjectMenu subject={subject} activeSpace={activeSpace} />
|
|
43
|
+
</div>
|
|
44
|
+
</Card.SurfaceRoot>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { Button, Icon } from '@dxos/react-ui';
|
|
8
|
+
import { Card, cardNoSpacing, cardSpacing } from '@dxos/react-ui-stack';
|
|
9
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
10
|
+
|
|
11
|
+
import { type PreviewProps } from '../types';
|
|
12
|
+
|
|
13
|
+
import { CardSubjectMenu } from './CardSubjectMenu';
|
|
14
|
+
|
|
15
|
+
export const gridRow = 'is-full grid grid-cols-[1.5rem_1fr_min-content] gap-2 items-center';
|
|
16
|
+
|
|
17
|
+
// TODO(burdon): Standardize card grid for common rows.
|
|
18
|
+
|
|
19
|
+
export const CardHeader = ({ label, subject, activeSpace }: { label?: string } & PreviewProps) => {
|
|
20
|
+
return (
|
|
21
|
+
<div role='none' className={mx('flex items-center gap-2', cardSpacing)}>
|
|
22
|
+
<Card.Heading classNames={cardNoSpacing}>{label}</Card.Heading>
|
|
23
|
+
<CardSubjectMenu subject={subject} activeSpace={activeSpace} />
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const CardRow = ({ icon, label, onClick }: { icon: string; label: string; onClick?: () => void }) => {
|
|
29
|
+
if (!onClick) {
|
|
30
|
+
return (
|
|
31
|
+
<Card.Chrome>
|
|
32
|
+
<p data-variant='ghost' className={mx(gridRow, 'dx-button')}>
|
|
33
|
+
<Icon icon={icon} size={5} classNames='text-subdued' />
|
|
34
|
+
<span className='min-is-0 flex-1 truncate col-span-2'>{label}</span>
|
|
35
|
+
</p>
|
|
36
|
+
</Card.Chrome>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Card.Chrome>
|
|
42
|
+
<Button variant='ghost' classNames={mx(gridRow, 'text-start')} onClick={onClick}>
|
|
43
|
+
<Icon icon={icon} size={5} classNames='text-subdued' />
|
|
44
|
+
<span className='min-is-0 flex-1 truncate'>{label}</span>
|
|
45
|
+
<Icon icon='ph--arrow-right--regular' />
|
|
46
|
+
</Button>
|
|
47
|
+
</Card.Chrome>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const CardLink = ({ label, href }: { label: string; href: string }) => {
|
|
52
|
+
return (
|
|
53
|
+
<Card.Chrome>
|
|
54
|
+
<a
|
|
55
|
+
className={mx(gridRow, 'dx-button dx-focus-ring')}
|
|
56
|
+
data-variant='ghost'
|
|
57
|
+
href={href}
|
|
58
|
+
target='_blank'
|
|
59
|
+
rel='noreferrer'
|
|
60
|
+
>
|
|
61
|
+
<Icon icon='ph--link--regular' size={5} classNames='text-subdued' />
|
|
62
|
+
<span className='min-is-0 flex-1 truncate'>{label}</span>
|
|
63
|
+
<Icon icon='ph--arrow-square-out--regular' />
|
|
64
|
+
</a>
|
|
65
|
+
</Card.Chrome>
|
|
66
|
+
);
|
|
67
|
+
};
|