@dxos/plugin-preview 0.8.2-main.f081794 → 0.8.2-main.f11618f
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/index.mjs +289 -6
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +291 -4
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +289 -6
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/Preview.stories.d.ts +197 -0
- package/dist/types/src/Preview.stories.d.ts.map +1 -0
- package/dist/types/src/PreviewPlugin.d.ts.map +1 -1
- package/dist/types/src/components/ContactCard.d.ts +7 -0
- package/dist/types/src/components/ContactCard.d.ts.map +1 -0
- package/dist/types/src/components/OrganizationCard.d.ts +5 -0
- package/dist/types/src/components/OrganizationCard.d.ts.map +1 -0
- package/dist/types/src/components/ProjectCard.d.ts +5 -0
- package/dist/types/src/components/ProjectCard.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +4 -0
- package/dist/types/src/components/index.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +9 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +25 -0
- package/dist/types/src/types.d.ts.map +1 -0
- package/package.json +21 -10
- package/src/Preview.stories.tsx +139 -0
- package/src/PreviewPlugin.tsx +135 -9
- package/src/components/ContactCard.tsx +70 -0
- package/src/components/OrganizationCard.tsx +42 -0
- package/src/components/ProjectCard.tsx +20 -0
- package/src/components/index.ts +7 -0
- package/src/index.ts +2 -0
- package/src/translations.ts +15 -0
- package/src/types.ts +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Preview.stories.d.ts","sourceRoot":"","sources":["../../../src/Preview.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,aAAa,CAAC;AAErB,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQ9D,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,EAAE,CAAC;QAAE,OAAO,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC;CACd,CAAC;AAEF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAAU,CAoB1B,CAAC;AAEF,eAAe,IAAI,CAAC;AA2CpB,eAAO,MAAM,gBAAgB;;;sBA3E7B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4DA0H23+M,KAAM,qBAAqB;+BAlFzx+M,KAAM,eAAe,YAAW,KAAM,qBACjK;;;;4DAiF2+/M,KAAM,qBAAqB;+BA7D5+/M,KAAM,eAEjC,YAGC,KAAE,qBAAqB;;;;4DAwDukhN,KAAM,qBAAqB;+BA3BrnhN,KAAO,eAAc,YAE1B,KAEE,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAlBvB,CAAC;AAEF,eAAO,MAAM,cAAc;;;sBAnF3B,CAAA;;;;;CAyFC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;CAMjC,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;;;;CAM/B,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;CAM5B,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;CAM1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PreviewPlugin.d.ts","sourceRoot":"","sources":["../../../src/PreviewPlugin.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PreviewPlugin.d.ts","sourceRoot":"","sources":["../../../src/PreviewPlugin.tsx"],"names":[],"mappings":"AA+DA,eAAO,MAAM,aAAa,4CAqJtB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type Contact, type Organization } from '@dxos/schema';
|
|
3
|
+
import { type PreviewProps } from '../types';
|
|
4
|
+
export declare const ContactCard: ({ children, classNames, role, subject: { fullName, image, organization, emails }, onOrgClick, }: PreviewProps<Contact> & {
|
|
5
|
+
onOrgClick?: (org: Organization) => void;
|
|
6
|
+
}) => React.JSX.Element;
|
|
7
|
+
//# sourceMappingURL=ContactCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactCard.d.ts","sourceRoot":"","sources":["../../../../src/components/ContactCard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAE,KAAK,YAAY,EAAuE,MAAM,UAAU,CAAC;AAElH,eAAO,MAAM,WAAW,oGAMrB,YAAY,CAAC,OAAO,CAAC,GAAG;IAAE,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,CAAA;CAAE,sBAmDtE,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type Organization } from '@dxos/schema';
|
|
3
|
+
import { type PreviewProps } from '../types';
|
|
4
|
+
export declare const OrganizationCard: ({ children, classNames, subject: { name, image, description, website }, role, }: PreviewProps<Organization>) => React.JSX.Element;
|
|
5
|
+
//# sourceMappingURL=OrganizationCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OrganizationCard.d.ts","sourceRoot":"","sources":["../../../../src/components/OrganizationCard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,KAAK,YAAY,EAAuE,MAAM,UAAU,CAAC;AAElH,eAAO,MAAM,gBAAgB,oFAK1B,YAAY,CAAC,YAAY,CAAC,sBAwB5B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type Project } from '@dxos/schema';
|
|
3
|
+
import { type PreviewProps } from '../types';
|
|
4
|
+
export declare const ProjectCard: ({ classNames, role, subject: { name, image, description } }: PreviewProps<Project>) => React.JSX.Element;
|
|
5
|
+
//# sourceMappingURL=ProjectCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectCard.d.ts","sourceRoot":"","sources":["../../../../src/components/ProjectCard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,KAAK,YAAY,EAA0C,MAAM,UAAU,CAAC;AAErF,eAAO,MAAM,WAAW,gEAAiE,YAAY,CAAC,OAAO,CAAC,sBAQ7G,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAIA,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,QAAQ,CAAC;AACvB,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AAExB,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../../src/translations.ts"],"names":[],"mappings":";;;;;;;AAMA,wBAQE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type PropsWithChildren } from 'react';
|
|
2
|
+
import { type ThemedClassName } from '@dxos/react-ui';
|
|
3
|
+
export type PreviewProps<T extends object> = PropsWithChildren<ThemedClassName<{
|
|
4
|
+
subject: T;
|
|
5
|
+
role: string;
|
|
6
|
+
}>>;
|
|
7
|
+
/**
|
|
8
|
+
* <Card.Root>
|
|
9
|
+
* <Card.Header>
|
|
10
|
+
* <Card.Title>
|
|
11
|
+
* <Card.Action>
|
|
12
|
+
* </Card.Header>
|
|
13
|
+
* <Card.Body>
|
|
14
|
+
* <Card.Image>
|
|
15
|
+
* <Form />
|
|
16
|
+
* </Card.Body>
|
|
17
|
+
* </Card.Root>
|
|
18
|
+
*/
|
|
19
|
+
export declare const popoverCard = "popover-consistent-width rounded-lg overflow-hidden";
|
|
20
|
+
export declare const defaultCard = "";
|
|
21
|
+
export declare const kanbanCardWithoutPoster = "pbs-[--rail-action]";
|
|
22
|
+
export declare const previewTitle = "text-lg font-medium line-clamp-2";
|
|
23
|
+
export declare const previewProse = "pli-3 mlb-3";
|
|
24
|
+
export declare const previewChrome = "pli-1.5 mlb-1.5 [&_.dx-button]:pli-1.5 [&_.dx-button]:text-start [&_.dx-button]:is-full";
|
|
25
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI,iBAAiB,CAC5D,eAAe,CAAC;IACd,OAAO,EAAE,CAAC,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CACH,CAAC;AAQF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,wDAAwD,CAAC;AACjF,eAAO,MAAM,WAAW,KAAK,CAAC;AAC9B,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAC7D,eAAO,MAAM,YAAY,qCAAqC,CAAC;AAC/D,eAAO,MAAM,YAAY,gBAAgB,CAAC;AAC1C,eAAO,MAAM,aAAa,4FAA4F,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-preview",
|
|
3
|
-
"version": "0.8.2-main.
|
|
3
|
+
"version": "0.8.2-main.f11618f",
|
|
4
4
|
"description": "Preview plugin",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -23,21 +23,32 @@
|
|
|
23
23
|
"src"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@dxos/app-framework": "0.8.2-main.
|
|
27
|
-
"@dxos/
|
|
28
|
-
"@dxos/
|
|
29
|
-
"@dxos/
|
|
30
|
-
"@dxos/lit-ui": "0.8.2-main.
|
|
31
|
-
"@dxos/log": "0.8.2-main.
|
|
32
|
-
"@dxos/plugin-client": "0.8.2-main.
|
|
33
|
-
"@dxos/react-
|
|
26
|
+
"@dxos/app-framework": "0.8.2-main.f11618f",
|
|
27
|
+
"@dxos/client": "0.8.2-main.f11618f",
|
|
28
|
+
"@dxos/echo-schema": "0.8.2-main.f11618f",
|
|
29
|
+
"@dxos/async": "0.8.2-main.f11618f",
|
|
30
|
+
"@dxos/lit-ui": "0.8.2-main.f11618f",
|
|
31
|
+
"@dxos/log": "0.8.2-main.f11618f",
|
|
32
|
+
"@dxos/plugin-client": "0.8.2-main.f11618f",
|
|
33
|
+
"@dxos/react-client": "0.8.2-main.f11618f",
|
|
34
|
+
"@dxos/keys": "0.8.2-main.f11618f",
|
|
35
|
+
"@dxos/react-ui": "0.8.2-main.f11618f",
|
|
36
|
+
"@dxos/react-ui-editor": "0.8.2-main.f11618f",
|
|
37
|
+
"@dxos/react-ui-table": "0.8.2-main.f11618f",
|
|
38
|
+
"@dxos/react-ui-form": "0.8.2-main.f11618f",
|
|
39
|
+
"@dxos/schema": "0.8.2-main.f11618f",
|
|
40
|
+
"@dxos/util": "0.8.2-main.f11618f",
|
|
41
|
+
"@dxos/react-ui-theme": "0.8.2-main.f11618f"
|
|
34
42
|
},
|
|
35
43
|
"devDependencies": {
|
|
44
|
+
"effect": "3.13.3",
|
|
36
45
|
"react": "~18.2.0",
|
|
37
46
|
"react-dom": "~18.2.0",
|
|
38
|
-
"vite": "5.4.7"
|
|
47
|
+
"vite": "5.4.7",
|
|
48
|
+
"@dxos/random": "0.8.2-main.f11618f"
|
|
39
49
|
},
|
|
40
50
|
"peerDependencies": {
|
|
51
|
+
"effect": "3.13.3",
|
|
41
52
|
"react": "~18.2.0",
|
|
42
53
|
"react-dom": "~18.2.0"
|
|
43
54
|
},
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxos-theme';
|
|
6
|
+
|
|
7
|
+
import { type Meta } from '@storybook/react';
|
|
8
|
+
import React, { type FC } from 'react';
|
|
9
|
+
|
|
10
|
+
import { create } from '@dxos/echo-schema';
|
|
11
|
+
import { faker } from '@dxos/random';
|
|
12
|
+
import { makeRef } from '@dxos/react-client/echo';
|
|
13
|
+
import { Icon, Popover } from '@dxos/react-ui';
|
|
14
|
+
import { Contact, Organization, Project } from '@dxos/schema';
|
|
15
|
+
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
16
|
+
|
|
17
|
+
import { ContactCard, OrganizationCard, ProjectCard } from './components';
|
|
18
|
+
import translations from './translations';
|
|
19
|
+
|
|
20
|
+
faker.seed(1234);
|
|
21
|
+
|
|
22
|
+
type StoryProps = {
|
|
23
|
+
Component: FC<{ subject: any }>;
|
|
24
|
+
icon: string;
|
|
25
|
+
subject: any;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const meta: Meta<StoryProps> = {
|
|
29
|
+
title: 'plugins/plugin-preview/Preview',
|
|
30
|
+
render: ({ Component, icon, ...args }) => {
|
|
31
|
+
return (
|
|
32
|
+
<Popover.Root open>
|
|
33
|
+
<Popover.Content>
|
|
34
|
+
<Component {...args} />
|
|
35
|
+
<Popover.Arrow />
|
|
36
|
+
</Popover.Content>
|
|
37
|
+
<Popover.Trigger>
|
|
38
|
+
<Icon icon={icon} size={5} />
|
|
39
|
+
</Popover.Trigger>
|
|
40
|
+
</Popover.Root>
|
|
41
|
+
);
|
|
42
|
+
},
|
|
43
|
+
decorators: [withTheme, withLayout({ tooltips: true })],
|
|
44
|
+
parameters: {
|
|
45
|
+
layout: 'centered',
|
|
46
|
+
translations,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default meta;
|
|
51
|
+
|
|
52
|
+
const omitImage = ({ image, ...rest }: any) => rest;
|
|
53
|
+
|
|
54
|
+
const data = (() => {
|
|
55
|
+
const organization = create(Organization, {
|
|
56
|
+
name: faker.company.name(),
|
|
57
|
+
image:
|
|
58
|
+
'https://plus.unsplash.com/premium_photo-1672116452571-896980a801c8?q=80&w=2671&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
59
|
+
website: faker.internet.url(),
|
|
60
|
+
description: faker.lorem.paragraph(),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const contact = create(Contact, {
|
|
64
|
+
fullName: faker.person.fullName(),
|
|
65
|
+
image:
|
|
66
|
+
'https://plus.unsplash.com/premium_photo-1664536392779-049ba8fde933?q=80&w=2574&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
67
|
+
organization: makeRef(organization),
|
|
68
|
+
emails: [
|
|
69
|
+
{
|
|
70
|
+
label: 'Work',
|
|
71
|
+
value: faker.internet.email(),
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
label: 'Work',
|
|
75
|
+
value: faker.internet.email(),
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
label: 'Work',
|
|
79
|
+
value: faker.internet.email(),
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const project = create(Project, {
|
|
85
|
+
name: faker.person.fullName(),
|
|
86
|
+
image: 'https://dxos.network/dxos-logotype-blue.png',
|
|
87
|
+
description: faker.lorem.paragraph(),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return { organization, contact, project };
|
|
91
|
+
})();
|
|
92
|
+
|
|
93
|
+
export const ContactWithImage = {
|
|
94
|
+
args: {
|
|
95
|
+
Component: ContactCard,
|
|
96
|
+
icon: 'ph--user--regular',
|
|
97
|
+
subject: data.contact,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const ContactNoImage = {
|
|
102
|
+
args: {
|
|
103
|
+
Component: ContactCard,
|
|
104
|
+
icon: 'ph--user--regular',
|
|
105
|
+
subject: omitImage(data.contact),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const OrganizationWithImage = {
|
|
110
|
+
args: {
|
|
111
|
+
Component: OrganizationCard,
|
|
112
|
+
icon: 'ph--building-office--regular',
|
|
113
|
+
subject: data.organization,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export const OrganizationNoImage = {
|
|
118
|
+
args: {
|
|
119
|
+
Component: OrganizationCard,
|
|
120
|
+
icon: 'ph--building-office--regular',
|
|
121
|
+
subject: omitImage(data.organization),
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export const ProjectWithImage = {
|
|
126
|
+
args: {
|
|
127
|
+
Component: ProjectCard,
|
|
128
|
+
icon: 'ph--building--regular',
|
|
129
|
+
subject: data.project,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export const ProjectNoImage = {
|
|
134
|
+
args: {
|
|
135
|
+
Component: ProjectCard,
|
|
136
|
+
icon: 'ph--building--regular',
|
|
137
|
+
subject: omitImage(data.project),
|
|
138
|
+
},
|
|
139
|
+
};
|
package/src/PreviewPlugin.tsx
CHANGED
|
@@ -2,26 +2,48 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import React, { useCallback } from 'react';
|
|
6
|
+
|
|
5
7
|
import {
|
|
6
|
-
createIntent,
|
|
7
8
|
Capabilities,
|
|
8
|
-
contributes,
|
|
9
9
|
Events,
|
|
10
|
+
LayoutAction,
|
|
11
|
+
Surface,
|
|
12
|
+
contributes,
|
|
13
|
+
createIntent,
|
|
14
|
+
createSurface,
|
|
10
15
|
defineModule,
|
|
11
16
|
definePlugin,
|
|
12
|
-
|
|
17
|
+
useIntentDispatcher,
|
|
13
18
|
} from '@dxos/app-framework';
|
|
14
19
|
import { addEventListener } from '@dxos/async';
|
|
15
|
-
import { type Client } from '@dxos/client';
|
|
16
|
-
import {
|
|
17
|
-
|
|
20
|
+
import { type Client, resolveRef } from '@dxos/client';
|
|
21
|
+
import {
|
|
22
|
+
Filter,
|
|
23
|
+
fullyQualifiedId,
|
|
24
|
+
getSchema,
|
|
25
|
+
getSpace,
|
|
26
|
+
isEchoObject,
|
|
27
|
+
parseId,
|
|
28
|
+
type ReactiveEchoObject,
|
|
29
|
+
type Space,
|
|
30
|
+
} from '@dxos/client/echo';
|
|
31
|
+
import { isInstanceOf } from '@dxos/echo-schema';
|
|
18
32
|
import { DXN } from '@dxos/keys';
|
|
19
33
|
import { type DxRefTagActivate } from '@dxos/lit-ui';
|
|
20
34
|
import { log } from '@dxos/log';
|
|
21
|
-
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
35
|
+
import { ClientCapabilities, ClientEvents } from '@dxos/plugin-client';
|
|
36
|
+
import { useTranslation } from '@dxos/react-ui';
|
|
22
37
|
import { type PreviewLinkRef, type PreviewLinkTarget } from '@dxos/react-ui-editor';
|
|
38
|
+
import { Form } from '@dxos/react-ui-form';
|
|
39
|
+
import { TableType } from '@dxos/react-ui-table';
|
|
40
|
+
import { descriptionMessage } from '@dxos/react-ui-theme';
|
|
41
|
+
import { Contact, Organization, Project } from '@dxos/schema';
|
|
23
42
|
|
|
24
|
-
import {
|
|
43
|
+
import { ContactCard, OrganizationCard, ProjectCard } from './components';
|
|
44
|
+
import { meta, PREVIEW_PLUGIN } from './meta';
|
|
45
|
+
import translations from './translations';
|
|
46
|
+
import { kanbanCardWithoutPoster } from './types';
|
|
25
47
|
|
|
26
48
|
const customEventOptions = { capture: true, passive: false };
|
|
27
49
|
|
|
@@ -42,7 +64,17 @@ const handlePreviewLookup = async (
|
|
|
42
64
|
export const PreviewPlugin = () =>
|
|
43
65
|
definePlugin(meta, [
|
|
44
66
|
defineModule({
|
|
45
|
-
id: `${meta.id}/module/
|
|
67
|
+
id: `${meta.id}/module/translations`,
|
|
68
|
+
activatesOn: Events.SetupTranslations,
|
|
69
|
+
activate: () => contributes(Capabilities.Translations, translations),
|
|
70
|
+
}),
|
|
71
|
+
defineModule({
|
|
72
|
+
id: `${meta.id}/module/schema`,
|
|
73
|
+
activatesOn: ClientEvents.SetupSchema,
|
|
74
|
+
activate: () => [contributes(ClientCapabilities.Schema, [Contact, Organization])],
|
|
75
|
+
}),
|
|
76
|
+
defineModule({
|
|
77
|
+
id: `${meta.id}/module/preview-popover`,
|
|
46
78
|
activatesOn: Events.Startup,
|
|
47
79
|
activate: (context) => {
|
|
48
80
|
// TODO(wittjosiah): Factor out lookup handlers to other plugins to make not ECHO-specific.
|
|
@@ -84,4 +116,98 @@ export const PreviewPlugin = () =>
|
|
|
84
116
|
return contributes(Capabilities.Null, null, () => cleanup());
|
|
85
117
|
},
|
|
86
118
|
}),
|
|
119
|
+
defineModule({
|
|
120
|
+
id: `${meta.id}/module/react-surface`,
|
|
121
|
+
activatesOn: Events.SetupReactSurface,
|
|
122
|
+
activate: () =>
|
|
123
|
+
// TODO(wittjosiah): Factor out to lazy capabilities like other plugins.
|
|
124
|
+
contributes(Capabilities.ReactSurface, [
|
|
125
|
+
//
|
|
126
|
+
// Specific schema types.
|
|
127
|
+
//
|
|
128
|
+
createSurface({
|
|
129
|
+
id: `${PREVIEW_PLUGIN}/schema-popover`,
|
|
130
|
+
role: ['popover', 'card--kanban'],
|
|
131
|
+
filter: (data): data is { subject: Contact } => isInstanceOf(Contact, data.subject),
|
|
132
|
+
component: ({ data, role }) => {
|
|
133
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
134
|
+
const handleOrgClick = useCallback(
|
|
135
|
+
async (org: Organization) => {
|
|
136
|
+
const space = getSpace(org);
|
|
137
|
+
const tablesQuery = await space?.db.query(Filter.schema(TableType)).run();
|
|
138
|
+
const currentSpaceOrgTable = tablesQuery?.objects.find((table) => {
|
|
139
|
+
return table.view?.target?.query?.typename === Organization.typename;
|
|
140
|
+
});
|
|
141
|
+
await dispatch(
|
|
142
|
+
createIntent(LayoutAction.UpdatePopover, {
|
|
143
|
+
part: 'popover',
|
|
144
|
+
options: {
|
|
145
|
+
state: false,
|
|
146
|
+
anchorId: '',
|
|
147
|
+
},
|
|
148
|
+
}),
|
|
149
|
+
);
|
|
150
|
+
if (currentSpaceOrgTable) {
|
|
151
|
+
return dispatch(
|
|
152
|
+
createIntent(LayoutAction.Open, {
|
|
153
|
+
part: 'main',
|
|
154
|
+
subject: [fullyQualifiedId(currentSpaceOrgTable)],
|
|
155
|
+
options: { workspace: space?.id },
|
|
156
|
+
}),
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
[dispatch],
|
|
161
|
+
);
|
|
162
|
+
return (
|
|
163
|
+
<ContactCard subject={data.subject} onOrgClick={handleOrgClick} role={role}>
|
|
164
|
+
{role === 'popover' && <Surface role='related' data={data} />}
|
|
165
|
+
</ContactCard>
|
|
166
|
+
);
|
|
167
|
+
},
|
|
168
|
+
}),
|
|
169
|
+
createSurface({
|
|
170
|
+
id: `${PREVIEW_PLUGIN}/schema-popover`,
|
|
171
|
+
role: ['popover', 'card--kanban'],
|
|
172
|
+
filter: (data): data is { subject: Organization } => isInstanceOf(Organization, data.subject),
|
|
173
|
+
component: ({ data, role }) => (
|
|
174
|
+
<OrganizationCard subject={data.subject} role={role}>
|
|
175
|
+
{role === 'popover' && <Surface role='related' data={data} />}
|
|
176
|
+
</OrganizationCard>
|
|
177
|
+
),
|
|
178
|
+
}),
|
|
179
|
+
createSurface({
|
|
180
|
+
id: `${PREVIEW_PLUGIN}/schema-popover`,
|
|
181
|
+
role: ['popover', 'card--kanban'],
|
|
182
|
+
filter: (data): data is { subject: Project } => isInstanceOf(Project, data.subject),
|
|
183
|
+
component: ({ data, role }) => <ProjectCard subject={data.subject} role={role} />,
|
|
184
|
+
}),
|
|
185
|
+
|
|
186
|
+
//
|
|
187
|
+
// Fallback for any object.
|
|
188
|
+
//
|
|
189
|
+
createSurface({
|
|
190
|
+
id: `${PREVIEW_PLUGIN}/fallback-popover`,
|
|
191
|
+
role: ['popover', 'card--kanban'],
|
|
192
|
+
position: 'fallback',
|
|
193
|
+
filter: (data): data is { subject: ReactiveEchoObject<any> } => isEchoObject(data.subject),
|
|
194
|
+
component: ({ data, role }) => {
|
|
195
|
+
const schema = getSchema(data.subject);
|
|
196
|
+
const { t } = useTranslation(PREVIEW_PLUGIN);
|
|
197
|
+
if (!schema) {
|
|
198
|
+
return <p className={descriptionMessage}>{t('unable to create preview message')}</p>;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<Form
|
|
203
|
+
schema={schema}
|
|
204
|
+
values={data.subject}
|
|
205
|
+
readonly
|
|
206
|
+
{...(role === 'card--kanban' && { classNames: kanbanCardWithoutPoster })}
|
|
207
|
+
/>
|
|
208
|
+
);
|
|
209
|
+
},
|
|
210
|
+
}),
|
|
211
|
+
]),
|
|
212
|
+
}),
|
|
87
213
|
]);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { Fragment } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Icon, Avatar, Button } from '@dxos/react-ui';
|
|
8
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
9
|
+
import { type Contact, type Organization } from '@dxos/schema';
|
|
10
|
+
|
|
11
|
+
import { type PreviewProps, popoverCard, previewTitle, previewProse, previewChrome, defaultCard } from '../types';
|
|
12
|
+
|
|
13
|
+
export const ContactCard = ({
|
|
14
|
+
children,
|
|
15
|
+
classNames,
|
|
16
|
+
role,
|
|
17
|
+
subject: { fullName, image, organization, emails },
|
|
18
|
+
onOrgClick,
|
|
19
|
+
}: PreviewProps<Contact> & { onOrgClick?: (org: Organization) => void }) => {
|
|
20
|
+
const organizationName = organization && typeof organization === 'object' ? organization.target?.name : organization;
|
|
21
|
+
return (
|
|
22
|
+
<div role='none' className={mx(role === 'popover' ? popoverCard : defaultCard, classNames)}>
|
|
23
|
+
<Avatar.Root>
|
|
24
|
+
<div role='group' className={mx(previewProse, 'grid gap-3 grid-cols-[min-content_1fr]')}>
|
|
25
|
+
<Avatar.Content imgSrc={image} icon='ph--user--regular' size={16} hue='neutral' />
|
|
26
|
+
<div role='none' className='bs-min self-center'>
|
|
27
|
+
<Avatar.Label asChild>
|
|
28
|
+
<h2 className={previewTitle}>{fullName}</h2>
|
|
29
|
+
</Avatar.Label>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</Avatar.Root>
|
|
33
|
+
{organizationName && (
|
|
34
|
+
<div role='none' className={previewChrome}>
|
|
35
|
+
{typeof organization === 'object' && onOrgClick ? (
|
|
36
|
+
<Button variant='ghost' classNames='gap-2 text-start' onClick={() => onOrgClick(organization.target!)}>
|
|
37
|
+
<Icon icon='ph--buildings--regular' size={5} classNames='text-subdued' />
|
|
38
|
+
<span className='min-is-0 flex-1 truncate'>{organizationName}</span>
|
|
39
|
+
<Icon icon='ph--arrow-right--regular' />
|
|
40
|
+
</Button>
|
|
41
|
+
) : (
|
|
42
|
+
<p className='dx-button gap-2' data-variant='ghost'>
|
|
43
|
+
<Icon icon='ph--buildings--regular' size={5} classNames='text-subdued' />
|
|
44
|
+
<span className='min-is-0 flex-1 truncate'>{organizationName}</span>
|
|
45
|
+
</p>
|
|
46
|
+
)}
|
|
47
|
+
</div>
|
|
48
|
+
)}
|
|
49
|
+
<dl
|
|
50
|
+
className={mx(
|
|
51
|
+
previewProse,
|
|
52
|
+
'grid gap-2 grid-cols-[min-content_1fr] [&_dt]:text-subdued [&_dt]:pbs-0.5 [&_dd]:min-is-0',
|
|
53
|
+
)}
|
|
54
|
+
>
|
|
55
|
+
{emails?.length &&
|
|
56
|
+
emails.map(({ label, value }) => (
|
|
57
|
+
<Fragment key={value}>
|
|
58
|
+
<dt>
|
|
59
|
+
<Icon icon='ph--at--regular' size={5} />
|
|
60
|
+
</dt>
|
|
61
|
+
<dd key={value} className='break-words'>
|
|
62
|
+
{value}
|
|
63
|
+
</dd>
|
|
64
|
+
</Fragment>
|
|
65
|
+
))}
|
|
66
|
+
</dl>
|
|
67
|
+
{children}
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { Icon } from '@dxos/react-ui';
|
|
8
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
9
|
+
import { type Organization } from '@dxos/schema';
|
|
10
|
+
|
|
11
|
+
import { type PreviewProps, popoverCard, previewTitle, previewProse, previewChrome, defaultCard } from '../types';
|
|
12
|
+
|
|
13
|
+
export const OrganizationCard = ({
|
|
14
|
+
children,
|
|
15
|
+
classNames,
|
|
16
|
+
subject: { name, image, description, website },
|
|
17
|
+
role,
|
|
18
|
+
}: PreviewProps<Organization>) => {
|
|
19
|
+
return (
|
|
20
|
+
<div role='none' className={mx(role === 'popover' ? popoverCard : defaultCard, classNames)}>
|
|
21
|
+
{image ? (
|
|
22
|
+
<img className='aspect-video object-cover is-full bs-auto' src={image} alt={name} />
|
|
23
|
+
) : (
|
|
24
|
+
<div role='image' className='grid aspect-video place-items-center bg-input text-subdued'>
|
|
25
|
+
<Icon icon='ph--building-office--regular' size={10} />
|
|
26
|
+
</div>
|
|
27
|
+
)}
|
|
28
|
+
<h2 className={mx(previewTitle, previewProse)}>{name}</h2>
|
|
29
|
+
{description && <p className={mx(previewProse, 'line-clamp-2')}>{description}</p>}
|
|
30
|
+
{website && (
|
|
31
|
+
<div role='none' className={previewChrome}>
|
|
32
|
+
<a className='dx-button dx-focus-ring gap-2' href={website} target='_blank' rel='noreferrer'>
|
|
33
|
+
<Icon icon='ph--link--regular' size={5} classNames='text-subdued' />
|
|
34
|
+
<span className='grow'>{website}</span>
|
|
35
|
+
<Icon icon='ph--arrow-square-out--regular' />
|
|
36
|
+
</a>
|
|
37
|
+
</div>
|
|
38
|
+
)}
|
|
39
|
+
{children}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
8
|
+
import { type Project } from '@dxos/schema';
|
|
9
|
+
|
|
10
|
+
import { type PreviewProps, popoverCard, previewTitle, defaultCard } from '../types';
|
|
11
|
+
|
|
12
|
+
export const ProjectCard = ({ classNames, role, subject: { name, image, description } }: PreviewProps<Project>) => {
|
|
13
|
+
return (
|
|
14
|
+
<div role='none' className={mx(role === 'popover' ? popoverCard : defaultCard, classNames)}>
|
|
15
|
+
{image && <img className='is-full bs-auto' src={image} alt={name} />}
|
|
16
|
+
<h2 className={mx(previewTitle, 'pli-3 mlb-3')}>{name}</h2>
|
|
17
|
+
{description && <p className='pli-3 line-clamp-2 mlb-3'>{description}</p>}
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
package/src/index.ts
CHANGED