@dxos/plugin-preview 0.8.2-main.f11618f → 0.8.2-staging.42af850

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/lib/browser/chunk-B2VK6GFP.mjs +28 -0
  2. package/dist/lib/browser/chunk-B2VK6GFP.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +20 -312
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/preview-popover-S3OY3CFZ.mjs +65 -0
  7. package/dist/lib/browser/preview-popover-S3OY3CFZ.mjs.map +7 -0
  8. package/dist/lib/browser/react-surface-XDHP6EN7.mjs +285 -0
  9. package/dist/lib/browser/react-surface-XDHP6EN7.mjs.map +7 -0
  10. package/dist/lib/node/chunk-VFSOM2B4.cjs +55 -0
  11. package/dist/lib/node/chunk-VFSOM2B4.cjs.map +7 -0
  12. package/dist/lib/node/index.cjs +22 -316
  13. package/dist/lib/node/index.cjs.map +4 -4
  14. package/dist/lib/node/meta.json +1 -1
  15. package/dist/lib/node/preview-popover-GPBOHU5E.cjs +84 -0
  16. package/dist/lib/node/preview-popover-GPBOHU5E.cjs.map +7 -0
  17. package/dist/lib/node/react-surface-CPAQ7ZYR.cjs +297 -0
  18. package/dist/lib/node/react-surface-CPAQ7ZYR.cjs.map +7 -0
  19. package/dist/lib/node-esm/chunk-PYKIS3N7.mjs +30 -0
  20. package/dist/lib/node-esm/chunk-PYKIS3N7.mjs.map +7 -0
  21. package/dist/lib/node-esm/index.mjs +20 -313
  22. package/dist/lib/node-esm/index.mjs.map +4 -4
  23. package/dist/lib/node-esm/meta.json +1 -1
  24. package/dist/lib/node-esm/preview-popover-EQAEYYDT.mjs +67 -0
  25. package/dist/lib/node-esm/preview-popover-EQAEYYDT.mjs.map +7 -0
  26. package/dist/lib/node-esm/react-surface-QJRHN4PN.mjs +286 -0
  27. package/dist/lib/node-esm/react-surface-QJRHN4PN.mjs.map +7 -0
  28. package/dist/types/src/Preview.stories.d.ts +22 -78
  29. package/dist/types/src/Preview.stories.d.ts.map +1 -1
  30. package/dist/types/src/PreviewPlugin.d.ts.map +1 -1
  31. package/dist/types/src/capabilities/index.d.ts +3 -0
  32. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  33. package/dist/types/src/capabilities/preview-popover.d.ts +4 -0
  34. package/dist/types/src/capabilities/preview-popover.d.ts.map +1 -0
  35. package/dist/types/src/capabilities/react-surface.d.ts +4 -0
  36. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  37. package/dist/types/src/components/ContactCard.d.ts +3 -3
  38. package/dist/types/src/components/ContactCard.d.ts.map +1 -1
  39. package/dist/types/src/components/OrganizationCard.d.ts +2 -2
  40. package/dist/types/src/components/OrganizationCard.d.ts.map +1 -1
  41. package/dist/types/src/components/ProjectCard.d.ts +2 -2
  42. package/dist/types/src/components/ProjectCard.d.ts.map +1 -1
  43. package/dist/types/src/types.d.ts +1 -1
  44. package/dist/types/src/types.d.ts.map +1 -1
  45. package/dist/types/tsconfig.tsbuildinfo +1 -1
  46. package/package.json +23 -20
  47. package/src/Preview.stories.tsx +11 -5
  48. package/src/PreviewPlugin.tsx +7 -185
  49. package/src/capabilities/index.ts +8 -0
  50. package/src/capabilities/preview-popover.ts +65 -0
  51. package/src/capabilities/react-surface.tsx +126 -0
  52. package/src/components/ContactCard.tsx +2 -2
  53. package/src/components/OrganizationCard.tsx +10 -4
  54. package/src/components/ProjectCard.tsx +6 -2
  55. package/src/types.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-preview",
3
- "version": "0.8.2-main.f11618f",
3
+ "version": "0.8.2-staging.42af850",
4
4
  "description": "Preview plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -23,32 +23,35 @@
23
23
  "src"
24
24
  ],
25
25
  "dependencies": {
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"
26
+ "@preact-signals/safe-react": "^0.9.0",
27
+ "effect": "3.14.21",
28
+ "@dxos/app-framework": "0.8.2-staging.42af850",
29
+ "@dxos/async": "0.8.2-staging.42af850",
30
+ "@dxos/client": "0.8.2-staging.42af850",
31
+ "@dxos/echo": "0.8.2-staging.42af850",
32
+ "@dxos/echo-schema": "0.8.2-staging.42af850",
33
+ "@dxos/keys": "0.8.2-staging.42af850",
34
+ "@dxos/lit-ui": "0.8.2-staging.42af850",
35
+ "@dxos/plugin-client": "0.8.2-staging.42af850",
36
+ "@dxos/log": "0.8.2-staging.42af850",
37
+ "@dxos/react-client": "0.8.2-staging.42af850",
38
+ "@dxos/react-ui": "0.8.2-staging.42af850",
39
+ "@dxos/react-ui-form": "0.8.2-staging.42af850",
40
+ "@dxos/react-ui-editor": "0.8.2-staging.42af850",
41
+ "@dxos/react-ui-theme": "0.8.2-staging.42af850",
42
+ "@dxos/schema": "0.8.2-staging.42af850",
43
+ "@dxos/react-ui-table": "0.8.2-staging.42af850",
44
+ "@dxos/util": "0.8.2-staging.42af850"
42
45
  },
43
46
  "devDependencies": {
44
- "effect": "3.13.3",
47
+ "effect": "3.14.21",
45
48
  "react": "~18.2.0",
46
49
  "react-dom": "~18.2.0",
47
50
  "vite": "5.4.7",
48
- "@dxos/random": "0.8.2-main.f11618f"
51
+ "@dxos/random": "0.8.2-staging.42af850"
49
52
  },
50
53
  "peerDependencies": {
51
- "effect": "3.13.3",
54
+ "effect": "^3.13.3",
52
55
  "react": "~18.2.0",
53
56
  "react-dom": "~18.2.0"
54
57
  },
@@ -11,7 +11,7 @@ import { create } from '@dxos/echo-schema';
11
11
  import { faker } from '@dxos/random';
12
12
  import { makeRef } from '@dxos/react-client/echo';
13
13
  import { Icon, Popover } from '@dxos/react-ui';
14
- import { Contact, Organization, Project } from '@dxos/schema';
14
+ import { DataType } from '@dxos/schema';
15
15
  import { withTheme, withLayout } from '@dxos/storybook-utils';
16
16
 
17
17
  import { ContactCard, OrganizationCard, ProjectCard } from './components';
@@ -40,7 +40,7 @@ const meta: Meta<StoryProps> = {
40
40
  </Popover.Root>
41
41
  );
42
42
  },
43
- decorators: [withTheme, withLayout({ tooltips: true })],
43
+ decorators: [withTheme, withLayout()],
44
44
  parameters: {
45
45
  layout: 'centered',
46
46
  translations,
@@ -52,7 +52,7 @@ export default meta;
52
52
  const omitImage = ({ image, ...rest }: any) => rest;
53
53
 
54
54
  const data = (() => {
55
- const organization = create(Organization, {
55
+ const organization = create(DataType.Organization, {
56
56
  name: faker.company.name(),
57
57
  image:
58
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',
@@ -60,7 +60,7 @@ const data = (() => {
60
60
  description: faker.lorem.paragraph(),
61
61
  });
62
62
 
63
- const contact = create(Contact, {
63
+ const contact = create(DataType.Person, {
64
64
  fullName: faker.person.fullName(),
65
65
  image:
66
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',
@@ -81,7 +81,7 @@ const data = (() => {
81
81
  ],
82
82
  });
83
83
 
84
- const project = create(Project, {
84
+ const project = create(DataType.Project, {
85
85
  name: faker.person.fullName(),
86
86
  image: 'https://dxos.network/dxos-logotype-blue.png',
87
87
  description: faker.lorem.paragraph(),
@@ -95,6 +95,7 @@ export const ContactWithImage = {
95
95
  Component: ContactCard,
96
96
  icon: 'ph--user--regular',
97
97
  subject: data.contact,
98
+ role: 'popover',
98
99
  },
99
100
  };
100
101
 
@@ -103,6 +104,7 @@ export const ContactNoImage = {
103
104
  Component: ContactCard,
104
105
  icon: 'ph--user--regular',
105
106
  subject: omitImage(data.contact),
107
+ role: 'popover',
106
108
  },
107
109
  };
108
110
 
@@ -111,6 +113,7 @@ export const OrganizationWithImage = {
111
113
  Component: OrganizationCard,
112
114
  icon: 'ph--building-office--regular',
113
115
  subject: data.organization,
116
+ role: 'popover',
114
117
  },
115
118
  };
116
119
 
@@ -119,6 +122,7 @@ export const OrganizationNoImage = {
119
122
  Component: OrganizationCard,
120
123
  icon: 'ph--building-office--regular',
121
124
  subject: omitImage(data.organization),
125
+ role: 'popover',
122
126
  },
123
127
  };
124
128
 
@@ -127,6 +131,7 @@ export const ProjectWithImage = {
127
131
  Component: ProjectCard,
128
132
  icon: 'ph--building--regular',
129
133
  subject: data.project,
134
+ role: 'popover',
130
135
  },
131
136
  };
132
137
 
@@ -135,5 +140,6 @@ export const ProjectNoImage = {
135
140
  Component: ProjectCard,
136
141
  icon: 'ph--building--regular',
137
142
  subject: omitImage(data.project),
143
+ role: 'popover',
138
144
  },
139
145
  };
@@ -2,64 +2,13 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback } from 'react';
6
-
7
- import {
8
- Capabilities,
9
- Events,
10
- LayoutAction,
11
- Surface,
12
- contributes,
13
- createIntent,
14
- createSurface,
15
- defineModule,
16
- definePlugin,
17
- useIntentDispatcher,
18
- } from '@dxos/app-framework';
19
- import { addEventListener } from '@dxos/async';
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';
32
- import { DXN } from '@dxos/keys';
33
- import { type DxRefTagActivate } from '@dxos/lit-ui';
34
- import { log } from '@dxos/log';
5
+ import { Capabilities, Events, contributes, defineModule, definePlugin } from '@dxos/app-framework';
35
6
  import { ClientCapabilities, ClientEvents } from '@dxos/plugin-client';
36
- import { useTranslation } from '@dxos/react-ui';
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';
7
+ import { DataType } from '@dxos/schema';
42
8
 
43
- import { ContactCard, OrganizationCard, ProjectCard } from './components';
44
- import { meta, PREVIEW_PLUGIN } from './meta';
9
+ import { PreviewPopover, ReactSurface } from './capabilities';
10
+ import { meta } from './meta';
45
11
  import translations from './translations';
46
- import { kanbanCardWithoutPoster } from './types';
47
-
48
- const customEventOptions = { capture: true, passive: false };
49
-
50
- const handlePreviewLookup = async (
51
- client: Client,
52
- defaultSpace: Space,
53
- { ref, label }: PreviewLinkRef,
54
- ): Promise<PreviewLinkTarget | null> => {
55
- const dxn = DXN.parse(ref);
56
- if (!dxn) {
57
- return null;
58
- }
59
-
60
- const object = await resolveRef(client, dxn, defaultSpace);
61
- return { label, object };
62
- };
63
12
 
64
13
  export const PreviewPlugin = () =>
65
14
  definePlugin(meta, [
@@ -71,143 +20,16 @@ export const PreviewPlugin = () =>
71
20
  defineModule({
72
21
  id: `${meta.id}/module/schema`,
73
22
  activatesOn: ClientEvents.SetupSchema,
74
- activate: () => [contributes(ClientCapabilities.Schema, [Contact, Organization])],
23
+ activate: () => [contributes(ClientCapabilities.Schema, [DataType.Person, DataType.Organization])],
75
24
  }),
76
25
  defineModule({
77
26
  id: `${meta.id}/module/preview-popover`,
78
27
  activatesOn: Events.Startup,
79
- activate: (context) => {
80
- // TODO(wittjosiah): Factor out lookup handlers to other plugins to make not ECHO-specific.
81
- const handleDxRefTagActivate = async ({ ref, label, trigger }: DxRefTagActivate) => {
82
- const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
83
- const client = context.requestCapability(ClientCapabilities.Client);
84
- const [layout] = context.requestCapabilities(Capabilities.Layout);
85
- const { spaceId } = parseId(layout.workspace);
86
- const space = (spaceId && client.spaces.get(spaceId)) ?? client.spaces.default;
87
- const result = await handlePreviewLookup(client, space, { ref, label });
88
- if (!result) {
89
- return;
90
- }
91
-
92
- await dispatch(
93
- createIntent(LayoutAction.UpdatePopover, {
94
- part: 'popover',
95
- subject: result.object,
96
- options: {
97
- state: true,
98
- variant: 'virtual',
99
- anchor: trigger,
100
- },
101
- }),
102
- );
103
- };
104
-
105
- if (!document.defaultView) {
106
- log.warn('No default view found');
107
- return [];
108
- }
109
-
110
- const cleanup = addEventListener(
111
- document.defaultView,
112
- 'dx-ref-tag-activate',
113
- handleDxRefTagActivate,
114
- customEventOptions,
115
- );
116
- return contributes(Capabilities.Null, null, () => cleanup());
117
- },
28
+ activate: PreviewPopover,
118
29
  }),
119
30
  defineModule({
120
31
  id: `${meta.id}/module/react-surface`,
121
32
  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
- ]),
33
+ activate: ReactSurface,
212
34
  }),
213
35
  ]);
@@ -0,0 +1,8 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { lazy } from '@dxos/app-framework';
6
+
7
+ export const PreviewPopover = lazy(() => import('./preview-popover'));
8
+ export const ReactSurface = lazy(() => import('./react-surface'));
@@ -0,0 +1,65 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Capabilities, LayoutAction, contributes, createIntent, type PluginContext } from '@dxos/app-framework';
6
+ import { addEventListener } from '@dxos/async';
7
+ import { type Client, resolveRef } from '@dxos/client';
8
+ import { parseId, type Space } from '@dxos/client/echo';
9
+ import { DXN } from '@dxos/keys';
10
+ import { type DxRefTagActivate } from '@dxos/lit-ui';
11
+ import { log } from '@dxos/log';
12
+ import { ClientCapabilities } from '@dxos/plugin-client';
13
+ import { type PreviewLinkRef, type PreviewLinkTarget } from '@dxos/react-ui-editor';
14
+
15
+ const customEventOptions = { capture: true, passive: false };
16
+
17
+ const handlePreviewLookup = async (
18
+ client: Client,
19
+ defaultSpace: Space,
20
+ { ref, label }: PreviewLinkRef,
21
+ ): Promise<PreviewLinkTarget | null> => {
22
+ const dxn = DXN.parse(ref);
23
+ if (!dxn) {
24
+ return null;
25
+ }
26
+
27
+ const object = await resolveRef(client, dxn, defaultSpace);
28
+ return { label, object };
29
+ };
30
+
31
+ export default (context: PluginContext) => {
32
+ // TODO(wittjosiah): Factor out lookup handlers to other plugins to make not ECHO-specific.
33
+ const handleDxRefTagActivate = async ({ refId, label, trigger }: DxRefTagActivate) => {
34
+ const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
35
+ const client = context.getCapability(ClientCapabilities.Client);
36
+ const [layout] = context.getCapabilities(Capabilities.Layout);
37
+ const { spaceId } = parseId(layout.workspace);
38
+ const space = (spaceId && client.spaces.get(spaceId)) ?? client.spaces.default;
39
+ const result = await handlePreviewLookup(client, space, { ref: refId, label });
40
+ if (!result) {
41
+ return;
42
+ }
43
+
44
+ await dispatch(
45
+ createIntent(LayoutAction.UpdatePopover, {
46
+ part: 'popover',
47
+ subject: result.object,
48
+ options: {
49
+ state: true,
50
+ variant: 'virtual',
51
+ anchor: trigger,
52
+ },
53
+ }),
54
+ );
55
+ };
56
+
57
+ let cleanup: () => void;
58
+ if (document.defaultView) {
59
+ cleanup = addEventListener(document.defaultView, 'dx-ref-tag-activate', handleDxRefTagActivate, customEventOptions);
60
+ } else {
61
+ log.warn('No default view found');
62
+ }
63
+
64
+ return contributes(Capabilities.Null, null, () => cleanup());
65
+ };
@@ -0,0 +1,126 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback } from 'react';
6
+
7
+ import {
8
+ Capabilities,
9
+ LayoutAction,
10
+ Surface,
11
+ contributes,
12
+ createIntent,
13
+ createSurface,
14
+ useIntentDispatcher,
15
+ } from '@dxos/app-framework';
16
+ import { Filter, fullyQualifiedId, getSchema, getSpace, isEchoObject, type AnyLiveObject } from '@dxos/client/echo';
17
+ import { isInstanceOf, type JsonPath, setValue } from '@dxos/echo-schema';
18
+ import { useTranslation } from '@dxos/react-ui';
19
+ import { Form } from '@dxos/react-ui-form';
20
+ import { TableType } from '@dxos/react-ui-table';
21
+ import { descriptionMessage } from '@dxos/react-ui-theme';
22
+ import { DataType } from '@dxos/schema';
23
+
24
+ import { ContactCard, OrganizationCard, ProjectCard } from '../components';
25
+ import { PREVIEW_PLUGIN } from '../meta';
26
+ import { kanbanCardWithoutPoster } from '../types';
27
+
28
+ export default () =>
29
+ contributes(Capabilities.ReactSurface, [
30
+ //
31
+ // Specific schema types.
32
+ //
33
+ createSurface({
34
+ id: `${PREVIEW_PLUGIN}/schema-popover--contact`,
35
+ role: ['popover', 'card--kanban', 'card'],
36
+ filter: (data): data is { subject: DataType.Person } => isInstanceOf(DataType.Person, data.subject),
37
+ component: ({ data, role }) => {
38
+ const { dispatchPromise: dispatch } = useIntentDispatcher();
39
+ const handleOrgClick = useCallback(
40
+ async (org: DataType.Organization) => {
41
+ const space = getSpace(org);
42
+ const tablesQuery = await space?.db.query(Filter.type(TableType)).run();
43
+ const currentSpaceOrgTable = tablesQuery?.objects.find((table) => {
44
+ return table.view?.target?.query?.typename === DataType.Organization.typename;
45
+ });
46
+ await dispatch(
47
+ createIntent(LayoutAction.UpdatePopover, {
48
+ part: 'popover',
49
+ options: {
50
+ state: false,
51
+ anchorId: '',
52
+ },
53
+ }),
54
+ );
55
+ if (currentSpaceOrgTable) {
56
+ return dispatch(
57
+ createIntent(LayoutAction.Open, {
58
+ part: 'main',
59
+ subject: [fullyQualifiedId(currentSpaceOrgTable)],
60
+ options: { workspace: space?.id },
61
+ }),
62
+ );
63
+ }
64
+ },
65
+ [dispatch],
66
+ );
67
+ return (
68
+ <ContactCard subject={data.subject} onOrgClick={handleOrgClick} role={role}>
69
+ {role === 'popover' && <Surface role='related' data={data} />}
70
+ </ContactCard>
71
+ );
72
+ },
73
+ }),
74
+ createSurface({
75
+ id: `${PREVIEW_PLUGIN}/schema-popover--organization`,
76
+ role: ['popover', 'card--kanban', 'card'],
77
+ filter: (data): data is { subject: DataType.Organization } => isInstanceOf(DataType.Organization, data.subject),
78
+ component: ({ data, role }) => (
79
+ <OrganizationCard subject={data.subject} role={role}>
80
+ {role === 'popover' && <Surface role='related' data={data} />}
81
+ </OrganizationCard>
82
+ ),
83
+ }),
84
+ createSurface({
85
+ id: `${PREVIEW_PLUGIN}/schema-popover--project`,
86
+ role: ['popover', 'card--kanban', 'card'],
87
+ filter: (data): data is { subject: DataType.Project } => isInstanceOf(DataType.Project, data.subject),
88
+ component: ({ data, role }) => <ProjectCard subject={data.subject} role={role} />,
89
+ }),
90
+
91
+ //
92
+ // Fallback for any object.
93
+ //
94
+ createSurface({
95
+ id: `${PREVIEW_PLUGIN}/fallback-popover`,
96
+ role: ['popover', 'card--kanban', 'card'],
97
+ position: 'fallback',
98
+ filter: (data): data is { subject: AnyLiveObject<any> } => isEchoObject(data.subject),
99
+ component: ({ data, role }) => {
100
+ const schema = getSchema(data.subject);
101
+ const { t } = useTranslation(PREVIEW_PLUGIN);
102
+ if (!schema) {
103
+ return <p className={descriptionMessage}>{t('unable to create preview message')}</p>;
104
+ }
105
+
106
+ const handleSave = useCallback((values: any, { changed }: { changed: Record<string, boolean> }) => {
107
+ const changedPaths = Object.keys(changed).filter((path) => changed[path]);
108
+ for (const path of changedPaths) {
109
+ const value = values[path];
110
+ setValue(data.subject, path as JsonPath, value);
111
+ }
112
+ }, []);
113
+
114
+ return (
115
+ <Form
116
+ schema={schema}
117
+ values={data.subject}
118
+ readonly={role === 'popover'}
119
+ onSave={handleSave}
120
+ autoSave
121
+ {...(role === 'card--kanban' && { classNames: kanbanCardWithoutPoster })}
122
+ />
123
+ );
124
+ },
125
+ }),
126
+ ]);
@@ -6,7 +6,7 @@ import React, { Fragment } from 'react';
6
6
 
7
7
  import { Icon, Avatar, Button } from '@dxos/react-ui';
8
8
  import { mx } from '@dxos/react-ui-theme';
9
- import { type Contact, type Organization } from '@dxos/schema';
9
+ import { type DataType } from '@dxos/schema';
10
10
 
11
11
  import { type PreviewProps, popoverCard, previewTitle, previewProse, previewChrome, defaultCard } from '../types';
12
12
 
@@ -16,7 +16,7 @@ export const ContactCard = ({
16
16
  role,
17
17
  subject: { fullName, image, organization, emails },
18
18
  onOrgClick,
19
- }: PreviewProps<Contact> & { onOrgClick?: (org: Organization) => void }) => {
19
+ }: PreviewProps<DataType.Person> & { onOrgClick?: (org: DataType.Organization) => void }) => {
20
20
  const organizationName = organization && typeof organization === 'object' ? organization.target?.name : organization;
21
21
  return (
22
22
  <div role='none' className={mx(role === 'popover' ? popoverCard : defaultCard, classNames)}>
@@ -6,7 +6,7 @@ import React from 'react';
6
6
 
7
7
  import { Icon } from '@dxos/react-ui';
8
8
  import { mx } from '@dxos/react-ui-theme';
9
- import { type Organization } from '@dxos/schema';
9
+ import { type DataType } from '@dxos/schema';
10
10
 
11
11
  import { type PreviewProps, popoverCard, previewTitle, previewProse, previewChrome, defaultCard } from '../types';
12
12
 
@@ -15,13 +15,13 @@ export const OrganizationCard = ({
15
15
  classNames,
16
16
  subject: { name, image, description, website },
17
17
  role,
18
- }: PreviewProps<Organization>) => {
18
+ }: PreviewProps<DataType.Organization>) => {
19
19
  return (
20
20
  <div role='none' className={mx(role === 'popover' ? popoverCard : defaultCard, classNames)}>
21
21
  {image ? (
22
22
  <img className='aspect-video object-cover is-full bs-auto' src={image} alt={name} />
23
23
  ) : (
24
- <div role='image' className='grid aspect-video place-items-center bg-input text-subdued'>
24
+ <div role='image' className='grid aspect-video place-items-center bg-inputSurface text-subdued'>
25
25
  <Icon icon='ph--building-office--regular' size={10} />
26
26
  </div>
27
27
  )}
@@ -29,7 +29,13 @@ export const OrganizationCard = ({
29
29
  {description && <p className={mx(previewProse, 'line-clamp-2')}>{description}</p>}
30
30
  {website && (
31
31
  <div role='none' className={previewChrome}>
32
- <a className='dx-button dx-focus-ring gap-2' href={website} target='_blank' rel='noreferrer'>
32
+ <a
33
+ className='dx-button dx-focus-ring gap-2'
34
+ data-variant='ghost'
35
+ href={website}
36
+ target='_blank'
37
+ rel='noreferrer'
38
+ >
33
39
  <Icon icon='ph--link--regular' size={5} classNames='text-subdued' />
34
40
  <span className='grow'>{website}</span>
35
41
  <Icon icon='ph--arrow-square-out--regular' />
@@ -5,11 +5,15 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { mx } from '@dxos/react-ui-theme';
8
- import { type Project } from '@dxos/schema';
8
+ import { type DataType } from '@dxos/schema';
9
9
 
10
10
  import { type PreviewProps, popoverCard, previewTitle, defaultCard } from '../types';
11
11
 
12
- export const ProjectCard = ({ classNames, role, subject: { name, image, description } }: PreviewProps<Project>) => {
12
+ export const ProjectCard = ({
13
+ classNames,
14
+ role,
15
+ subject: { name, image, description },
16
+ }: PreviewProps<DataType.Project>) => {
13
17
  return (
14
18
  <div role='none' className={mx(role === 'popover' ? popoverCard : defaultCard, classNames)}>
15
19
  {image && <img className='is-full bs-auto' src={image} alt={name} />}
package/src/types.ts CHANGED
@@ -32,7 +32,7 @@ export type PreviewProps<T extends object> = PropsWithChildren<
32
32
  * </Card.Body>
33
33
  * </Card.Root>
34
34
  */
35
- export const popoverCard = 'popover-consistent-width rounded-lg overflow-hidden';
35
+ export const popoverCard = 'popover-card-width rounded-lg overflow-hidden';
36
36
  export const defaultCard = '';
37
37
  export const kanbanCardWithoutPoster = 'pbs-[--rail-action]';
38
38
  export const previewTitle = 'text-lg font-medium line-clamp-2';