@dxos/plugin-preview 0.9.0 → 0.9.1-main.c7dcc2e112

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 (50) hide show
  1. package/dist/lib/neutral/capabilities/index.mjs +2 -2
  2. package/dist/lib/neutral/chunk-SXDHWUBO.mjs +32 -0
  3. package/dist/lib/neutral/chunk-SXDHWUBO.mjs.map +7 -0
  4. package/dist/lib/neutral/index.mjs +1 -1
  5. package/dist/lib/neutral/meta.json +1 -1
  6. package/dist/lib/neutral/meta.mjs +1 -1
  7. package/dist/lib/neutral/plugin.mjs +1 -1
  8. package/dist/lib/neutral/{preview-popover-FLMYMFCH.mjs → preview-popover-KTNVSMHZ.mjs} +4 -4
  9. package/dist/lib/neutral/preview-popover-KTNVSMHZ.mjs.map +7 -0
  10. package/dist/lib/neutral/{react-surface-FE7E2JP7.mjs → react-surface-6SBWLXAY.mjs} +69 -47
  11. package/dist/lib/neutral/react-surface-6SBWLXAY.mjs.map +7 -0
  12. package/dist/lib/neutral/translations.mjs +1 -1
  13. package/dist/lib/neutral/translations.mjs.map +3 -3
  14. package/dist/types/dx.config.d.ts +28 -0
  15. package/dist/types/dx.config.d.ts.map +1 -0
  16. package/dist/types/src/capabilities/index.d.ts +2 -2
  17. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  18. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  19. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  20. package/dist/types/src/cards/FormCard.d.ts +2 -2
  21. package/dist/types/src/cards/FormCard.d.ts.map +1 -1
  22. package/dist/types/src/cards/JsonCard.d.ts.map +1 -1
  23. package/dist/types/src/cards/OrganizationCard.d.ts.map +1 -1
  24. package/dist/types/src/cards/PersonCard.d.ts.map +1 -1
  25. package/dist/types/src/cards/ProjectCard.d.ts.map +1 -1
  26. package/dist/types/src/meta.d.ts +28 -2
  27. package/dist/types/src/meta.d.ts.map +1 -1
  28. package/dist/types/src/stories/Card.stories.d.ts +4 -6
  29. package/dist/types/src/stories/Card.stories.d.ts.map +1 -1
  30. package/dist/types/src/stories/testing.d.ts +2 -1
  31. package/dist/types/src/stories/testing.d.ts.map +1 -1
  32. package/dist/types/tsconfig.tsbuildinfo +1 -1
  33. package/dx.config.ts +21 -0
  34. package/package.json +25 -24
  35. package/src/PreviewPlugin.test.ts +1 -1
  36. package/src/capabilities/preview-popover.ts +3 -3
  37. package/src/capabilities/react-surface.tsx +15 -18
  38. package/src/cards/FormCard.tsx +17 -6
  39. package/src/cards/JsonCard.tsx +23 -8
  40. package/src/cards/OrganizationCard.tsx +1 -5
  41. package/src/cards/PersonCard.tsx +26 -21
  42. package/src/cards/ProjectCard.tsx +5 -1
  43. package/src/meta.ts +3 -14
  44. package/src/stories/Card.stories.tsx +16 -35
  45. package/src/stories/testing.tsx +5 -0
  46. package/src/translations.ts +1 -1
  47. package/dist/lib/neutral/chunk-QOM5APM7.mjs +0 -23
  48. package/dist/lib/neutral/chunk-QOM5APM7.mjs.map +0 -7
  49. package/dist/lib/neutral/preview-popover-FLMYMFCH.mjs.map +0 -7
  50. package/dist/lib/neutral/react-surface-FE7E2JP7.mjs.map +0 -7
package/dx.config.ts ADDED
@@ -0,0 +1,21 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Config2 } from '@dxos/app-framework/config';
6
+ import { trim } from '@dxos/util';
7
+
8
+ export default Config2.make({
9
+ plugin: {
10
+ key: 'org.dxos.plugin.preview',
11
+ name: 'Preview',
12
+ author: 'DXOS',
13
+ description: trim`
14
+ Rich preview panel for viewing object content without opening full editors.
15
+ Quick peek at documents, images, and data with inline rendering.
16
+ `,
17
+ icon: { key: 'ph--eye--regular' },
18
+ source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-preview',
19
+ tags: ['system'],
20
+ },
21
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-preview",
3
- "version": "0.9.0",
3
+ "version": "0.9.1-main.c7dcc2e112",
4
4
  "description": "Preview plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -65,38 +65,39 @@
65
65
  "types": "dist/types/src/index.d.ts",
66
66
  "files": [
67
67
  "dist",
68
+ "dx.config.ts",
68
69
  "src"
69
70
  ],
70
71
  "dependencies": {
71
- "@dxos/app-framework": "0.9.0",
72
- "@dxos/app-toolkit": "0.9.0",
73
- "@dxos/client": "0.9.0",
74
- "@dxos/echo": "0.9.0",
75
- "@dxos/echo-react": "0.9.0",
76
- "@dxos/keys": "0.9.0",
77
- "@dxos/log": "0.9.0",
78
- "@dxos/plugin-client": "0.9.0",
79
- "@dxos/react-ui": "0.9.0",
80
- "@dxos/react-ui-form": "0.9.0",
81
- "@dxos/effect": "0.9.0",
82
- "@dxos/react-ui-mosaic": "0.9.0",
83
- "@dxos/react-ui-syntax-highlighter": "0.9.0",
84
- "@dxos/schema": "0.9.0",
85
- "@dxos/types": "0.9.0",
86
- "@dxos/ui-editor": "0.9.0",
87
- "@dxos/util": "0.9.0",
88
- "@dxos/async": "0.9.0"
72
+ "@dxos/async": "0.9.1-main.c7dcc2e112",
73
+ "@dxos/app-framework": "0.9.1-main.c7dcc2e112",
74
+ "@dxos/app-toolkit": "0.9.1-main.c7dcc2e112",
75
+ "@dxos/client": "0.9.1-main.c7dcc2e112",
76
+ "@dxos/effect": "0.9.1-main.c7dcc2e112",
77
+ "@dxos/echo": "0.9.1-main.c7dcc2e112",
78
+ "@dxos/echo-react": "0.9.1-main.c7dcc2e112",
79
+ "@dxos/log": "0.9.1-main.c7dcc2e112",
80
+ "@dxos/keys": "0.9.1-main.c7dcc2e112",
81
+ "@dxos/react-ui": "0.9.1-main.c7dcc2e112",
82
+ "@dxos/react-ui-syntax-highlighter": "0.9.1-main.c7dcc2e112",
83
+ "@dxos/schema": "0.9.1-main.c7dcc2e112",
84
+ "@dxos/react-ui-mosaic": "0.9.1-main.c7dcc2e112",
85
+ "@dxos/types": "0.9.1-main.c7dcc2e112",
86
+ "@dxos/ui-editor": "0.9.1-main.c7dcc2e112",
87
+ "@dxos/util": "0.9.1-main.c7dcc2e112",
88
+ "@dxos/react-ui-form": "0.9.1-main.c7dcc2e112",
89
+ "@dxos/plugin-client": "0.9.1-main.c7dcc2e112"
89
90
  },
90
91
  "devDependencies": {
91
92
  "effect": "3.21.3",
92
93
  "react": "~19.2.3",
93
94
  "react-dom": "~19.2.3",
94
95
  "vite": "^8.0.16",
95
- "@dxos/echo-react": "0.9.0",
96
- "@dxos/plugin-testing": "0.9.0",
97
- "@dxos/random": "0.9.0",
98
- "@dxos/storybook-utils": "0.9.0",
99
- "@dxos/react-ui-components": "0.9.0"
96
+ "@dxos/plugin-testing": "0.9.1-main.c7dcc2e112",
97
+ "@dxos/random": "0.9.1-main.c7dcc2e112",
98
+ "@dxos/echo-react": "0.9.1-main.c7dcc2e112",
99
+ "@dxos/react-ui-components": "0.9.1-main.c7dcc2e112",
100
+ "@dxos/storybook-utils": "0.9.1-main.c7dcc2e112"
100
101
  },
101
102
  "peerDependencies": {
102
103
  "effect": "3.21.3",
@@ -11,7 +11,7 @@ import { PreviewPlugin } from '#plugin';
11
11
 
12
12
  import { meta } from './meta';
13
13
 
14
- const moduleId = (name: string) => `${meta.id}.module.${name}`;
14
+ const moduleId = (name: string) => `${meta.profile.key}.module.${name}`;
15
15
 
16
16
  describe('PreviewPlugin', () => {
17
17
  test('modules activate on the expected events', { timeout: 10_000 }, async ({ expect }) => {
@@ -5,7 +5,7 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
7
  import { Capabilities, Capability } from '@dxos/app-framework';
8
- import { AppCapabilities, LayoutOperation, getPersonalSpace, getSpaceIdFromPath } from '@dxos/app-toolkit';
8
+ import { AppCapabilities, AppSpace, LayoutOperation, Paths } from '@dxos/app-toolkit';
9
9
  import { addEventListener } from '@dxos/async';
10
10
  import { type Client } from '@dxos/client';
11
11
  import { type Space } from '@dxos/client/echo';
@@ -74,8 +74,8 @@ export default Capability.makeModule(
74
74
  // would crash inside Atom's identity check (`'~atom/Serializable' in undefined`). When layout
75
75
  // isn't available, fall through to the personal-space default.
76
76
  const [layoutAtom] = capabilities.getAll(AppCapabilities.Layout);
77
- const spaceId = layoutAtom && getSpaceIdFromPath(registry.get(layoutAtom).workspace);
78
- const space = (spaceId && client.spaces.get(spaceId)) ?? getPersonalSpace(client);
77
+ const spaceId = layoutAtom && Paths.getSpaceIdFromPath(registry.get(layoutAtom).workspace);
78
+ const space = (spaceId && client.spaces.get(spaceId)) ?? AppSpace.getPersonalSpace(client);
79
79
  if (!space) {
80
80
  return;
81
81
  }
@@ -10,7 +10,7 @@ import { Surface } from '@dxos/app-framework/ui';
10
10
  import { AppSurface } from '@dxos/app-toolkit/ui';
11
11
  import { Obj, Type } from '@dxos/echo';
12
12
  import { Card } from '@dxos/react-ui';
13
- import { Expando, type ProjectionModel } from '@dxos/schema';
13
+ import { Expando } from '@dxos/schema';
14
14
  import { Organization, Person, Pipeline, Task } from '@dxos/types';
15
15
 
16
16
  import { ExpandoCard, FormCard, JsonCard, OrganizationCard, PersonCard, ProjectCard, TaskCard } from '../cards';
@@ -26,7 +26,7 @@ export default Capability.makeModule(() =>
26
26
  Surface.create<{ subject: Person.Person }>({
27
27
  id: 'schemaPopoverContact',
28
28
  position: 'first',
29
- filter: AppSurface.object(AppSurface.Card, Person.Person),
29
+ filter: AppSurface.object(AppSurface.CardContent, Person.Person),
30
30
  component: ({ data, role }) => {
31
31
  return (
32
32
  <>
@@ -39,7 +39,7 @@ export default Capability.makeModule(() =>
39
39
  Surface.create({
40
40
  id: 'schemaPopoverOrganization',
41
41
  position: 'first',
42
- filter: AppSurface.object(AppSurface.Card, Organization.Organization),
42
+ filter: AppSurface.object(AppSurface.CardContent, Organization.Organization),
43
43
  component: ({ data, role }) => {
44
44
  return (
45
45
  <>
@@ -52,7 +52,7 @@ export default Capability.makeModule(() =>
52
52
  Surface.create({
53
53
  id: 'schemaPopoverProject',
54
54
  position: 'first',
55
- filter: AppSurface.object(AppSurface.Card, Pipeline.Pipeline),
55
+ filter: AppSurface.object(AppSurface.CardContent, Pipeline.Pipeline),
56
56
  component: ({ data, role }) => {
57
57
  return <ProjectCard role={role} subject={data.subject} />;
58
58
  },
@@ -60,14 +60,14 @@ export default Capability.makeModule(() =>
60
60
  Surface.create({
61
61
  id: 'schemaPopoverTask',
62
62
  position: 'first',
63
- filter: AppSurface.object(AppSurface.Card, Task.Task),
63
+ filter: AppSurface.object(AppSurface.CardContent, Task.Task),
64
64
  component: ({ data, role }) => {
65
65
  return <TaskCard role={role} subject={data.subject} />;
66
66
  },
67
67
  }),
68
68
  Surface.create<AppSurface.ObjectCardData<Expando.Expando>>({
69
69
  id: 'schemaPopoverExpando',
70
- filter: AppSurface.object(AppSurface.Card, Expando.Expando),
70
+ filter: AppSurface.object(AppSurface.CardContent, Expando.Expando),
71
71
  component: ({ data, role }) => {
72
72
  return <ExpandoCard role={role} subject={data.subject} ignorePaths={data.ignorePaths} />;
73
73
  },
@@ -75,19 +75,18 @@ export default Capability.makeModule(() =>
75
75
 
76
76
  Surface.create({
77
77
  id: 'schemaPopoverDynamicType',
78
- role: 'card--content',
79
- filter: (data): data is { subject: Obj.Unknown } => {
80
- if (!Obj.isObject(data.subject)) {
78
+ filter: AppSurface.subject(AppSurface.CardContent, (subject): subject is Obj.Unknown => {
79
+ if (!Obj.isObject(subject)) {
81
80
  return false;
82
81
  }
83
- const type = Obj.getType(data.subject);
82
+ const type = Obj.getType(subject);
84
83
  if (type) {
85
84
  return Type.getDatabase(type) != null;
86
85
  }
87
86
  // Obj.getType fails for database-registered schemas (DXN mismatch); fall back to typename query.
88
87
  try {
89
- const db = Obj.getDatabase(data.subject);
90
- const typename = Obj.getTypename(data.subject);
88
+ const db = Obj.getDatabase(subject);
89
+ const typename = Obj.getTypename(subject);
91
90
  return (
92
91
  !!db &&
93
92
  !!typename &&
@@ -99,7 +98,7 @@ export default Capability.makeModule(() =>
99
98
  } catch {
100
99
  return false;
101
100
  }
102
- },
101
+ }),
103
102
  component: ({ data, role }) => {
104
103
  // Dynamic/mutable schemas render an editable, full-layout form;
105
104
  // FormCard handles both static and runtime schema resolution internally.
@@ -113,9 +112,8 @@ export default Capability.makeModule(() =>
113
112
 
114
113
  Surface.create({
115
114
  id: 'fallbackPopover',
116
- role: 'card--content',
117
115
  position: 'last',
118
- filter: (data): data is { subject: Obj.Unknown; projection?: ProjectionModel } => Obj.isObject(data.subject),
116
+ filter: AppSurface.subject(AppSurface.CardContent, Obj.isObject),
119
117
  component: ({ data, role }) => {
120
118
  return <FormCard role={role} subject={data.subject} projection={data.projection} />;
121
119
  },
@@ -123,9 +121,8 @@ export default Capability.makeModule(() =>
123
121
 
124
122
  Surface.create({
125
123
  id: 'fallbackJson',
126
- role: 'card--content',
124
+ filter: Surface.makeFilter(AppSurface.CardContent),
127
125
  position: 'last',
128
- filter: (data): data is Record<string, unknown> => true,
129
126
  component: ({ data }) => {
130
127
  return <JsonCard data={data} />;
131
128
  },
@@ -140,7 +137,7 @@ export default Capability.makeModule(() =>
140
137
  <div className='flex w-full justify-center'>
141
138
  <div className='py-2 dx-card-min-width dx-card-max-width'>
142
139
  <Card.Root>
143
- <Surface.Surface type={AppSurface.Card} data={data} limit={1} />
140
+ <Surface.Surface type={AppSurface.CardContent} data={data} limit={1} />
144
141
  </Card.Root>
145
142
  </div>
146
143
  </div>
@@ -11,7 +11,7 @@ import { useType } from '@dxos/echo-react';
11
11
  import { type AnyProperties } from '@dxos/echo/internal';
12
12
  import { SchemaEx } from '@dxos/effect';
13
13
  import { Card, Icon, useTranslation } from '@dxos/react-ui';
14
- import { Form, type FormUpdateMeta, type Presentation, getFormProperties, omitId } from '@dxos/react-ui-form';
14
+ import { Form, type FormUpdateMeta, type FormPresentation, getFormProperties, omitId } from '@dxos/react-ui-form';
15
15
  import { type ProjectionModel } from '@dxos/schema';
16
16
 
17
17
  import { meta } from '#meta';
@@ -19,7 +19,7 @@ import { meta } from '#meta';
19
19
  export type FormCardProps = AppSurface.ObjectCardProps & {
20
20
  projection?: ProjectionModel;
21
21
  readonly?: boolean;
22
- layout?: Presentation;
22
+ layout?: FormPresentation;
23
23
  };
24
24
 
25
25
  /**
@@ -29,18 +29,29 @@ export type FormCardProps = AppSurface.ObjectCardProps & {
29
29
  * schema looked up via `useType`.
30
30
  */
31
31
  export const FormCard = ({ subject, projection, readonly = true, layout }: FormCardProps) => {
32
- const { t } = useTranslation(meta.id);
32
+ const { t } = useTranslation(meta.profile.key);
33
33
  // Readonly cards default to the `static` presentation — plain DOM, undefined values
34
34
  // omitted — which reads as a preview rather than a form. Editable cards keep the
35
35
  // `compact` form layout. Callers can override either via the explicit `layout` prop.
36
- const resolvedLayout: Presentation = layout ?? (readonly ? 'static' : 'compact');
36
+ const resolvedLayout: FormPresentation = layout ?? (readonly ? 'static' : 'compact');
37
37
 
38
38
  // Try the static schema first; fall back to the runtime/database schema for
39
39
  // dynamic types whose schema isn't reachable via `Obj.getSchema` (DXN mismatch).
40
40
  const staticType = Obj.getType(subject);
41
41
  const db = Obj.getDatabase(subject);
42
- // Obj.getTypeURI throws for corrupted objects; only evaluate it on the fallback path.
43
- const runtimeType = useType(db, staticType ? undefined : Obj.getTypeURI(subject));
42
+ // `Obj.getTypeURI` throws on corrupted objects that are missing a type; swallow that
43
+ // and fall through to the "unable to create preview" path rather than crashing the card.
44
+ const fallbackTypeUri = useMemo(() => {
45
+ if (staticType) {
46
+ return undefined;
47
+ }
48
+ try {
49
+ return Obj.getTypeURI(subject);
50
+ } catch {
51
+ return undefined;
52
+ }
53
+ }, [staticType, subject]);
54
+ const runtimeType = useType(db, fallbackTypeUri);
44
55
  const schema = useMemo((): Schema.Schema.AnyNoContext | undefined => {
45
56
  const resolvedType = runtimeType ?? staticType;
46
57
  return resolvedType ? omitId(Type.getSchema(resolvedType)) : undefined;
@@ -2,18 +2,33 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React from 'react';
5
+ import React, { useState } from 'react';
6
6
 
7
- import { Card } from '@dxos/react-ui';
7
+ import { Card, ToggleIconButton } from '@dxos/react-ui';
8
8
  import { JsonHighlighter } from '@dxos/react-ui-syntax-highlighter';
9
9
 
10
10
  export const JsonCard = ({ data }: { data: unknown }) => {
11
+ const [open, setOpen] = useState(false);
12
+ // JSON.stringify throws on circular references / unsupported values (e.g. BigInt); keep the card stable.
13
+ let collapsedLength = 0;
14
+ try {
15
+ collapsedLength = JSON.stringify(data)?.length ?? 0;
16
+ } catch {}
11
17
  return (
12
- <Card.Body>
13
- <span />
14
- {/* TODO(wittjosiah): Span whole row. */}
15
- <JsonHighlighter data={data} />
16
- <span />
17
- </Card.Body>
18
+ <Card.Row>
19
+ <Card.Block>
20
+ <ToggleIconButton
21
+ variant='ghost'
22
+ icon='ph--caret-right--regular'
23
+ iconOnly
24
+ active={open}
25
+ onClick={() => setOpen(!open)}
26
+ label='Toggle JSON'
27
+ />
28
+ </Card.Block>
29
+ {(open && <JsonHighlighter data={data} classNames='py-1.5 col-span-full text-xs overflow-auto' />) || (
30
+ <Card.Text variant='description'>{collapsedLength}</Card.Text>
31
+ )}
32
+ </Card.Row>
18
33
  );
19
34
  };
@@ -13,11 +13,7 @@ export const OrganizationCard = ({ subject }: AppSurface.ObjectCardProps<Organiz
13
13
 
14
14
  return (
15
15
  <Card.Body>
16
- <Card.Poster
17
- alt={name ?? ''}
18
- {...(image ? { image } : { icon: 'ph--building-office--regular' })}
19
- classNames={!image && 'opacity-50'}
20
- />
16
+ {image && <Card.Poster alt={name ?? ''} image={image} />}
21
17
  {description && (
22
18
  <Card.Row>
23
19
  <Card.Text variant='description'>{description}</Card.Text>
@@ -6,12 +6,12 @@ import * as Effect from 'effect/Effect';
6
6
  import React, { useCallback } from 'react';
7
7
 
8
8
  import { useOperationInvoker } from '@dxos/app-framework/ui';
9
- import { LayoutOperation, getObjectPathFromObject, getSpacePath } from '@dxos/app-toolkit';
9
+ import { LayoutOperation, Paths } from '@dxos/app-toolkit';
10
10
  import { type AppSurface } from '@dxos/app-toolkit/ui';
11
11
  import { Obj } from '@dxos/echo';
12
12
  import { EffectEx } from '@dxos/effect';
13
13
  import { Avatar } from '@dxos/react-ui';
14
- import { Card } from '@dxos/react-ui';
14
+ import { Card, Icon } from '@dxos/react-ui';
15
15
  import { type Person } from '@dxos/types';
16
16
 
17
17
  export const PersonCard = ({ subject }: AppSurface.ObjectCardProps<Person.Person>) => {
@@ -24,42 +24,47 @@ export const PersonCard = ({ subject }: AppSurface.ObjectCardProps<Person.Person
24
24
  }
25
25
 
26
26
  return Effect.gen(function* () {
27
- const organizationPath = getObjectPathFromObject(organization);
27
+ const organizationPath = Paths.getObjectPathFromObject(organization);
28
28
  const db = Obj.getDatabase(organization);
29
29
  yield* invoke(LayoutOperation.UpdatePopover, { state: false, anchorId: '' });
30
30
  yield* invoke(LayoutOperation.Open, {
31
31
  subject: [organizationPath],
32
- workspace: db ? getSpacePath(db.spaceId) : undefined,
32
+ workspace: db ? Paths.getSpacePath(db.spaceId) : undefined,
33
33
  });
34
34
  }).pipe(EffectEx.runAndForwardErrors);
35
35
  }, [invoke, organization]);
36
36
 
37
37
  return (
38
38
  <Card.Body>
39
- <Avatar.Root>
40
- {image && (
41
- <Card.Row className='py-1'>
39
+ {image && (
40
+ <Card.Row>
41
+ <Avatar.Root>
42
42
  <Avatar.Content
43
43
  imgSrc={image}
44
44
  icon='ph--user--regular'
45
45
  size={20}
46
- classNames={!image && 'opacity-50'}
46
+ classNames={[!image && 'opacity-50']}
47
47
  hue='neutral'
48
48
  variant='square'
49
49
  />
50
- </Card.Row>
51
- )}
52
- {organization?.name && (
53
- <Card.Action icon='ph--buildings--regular' label={organization.name} onClick={handleOrganizationClick} />
54
- )}
55
- {emails.map(({ value }) => (
56
- <Card.Row key={value} icon='ph--at--regular'>
57
- <Card.Text truncate className='text-primary-text'>
58
- {value}
59
- </Card.Text>
60
- </Card.Row>
61
- ))}
62
- </Avatar.Root>
50
+ </Avatar.Root>
51
+ </Card.Row>
52
+ )}
53
+ {organization?.name && (
54
+ <Card.Action icon='ph--buildings--regular' label={organization.name} onClick={handleOrganizationClick} />
55
+ )}
56
+ {emails.length > 0 && (
57
+ <Card.Row>
58
+ <Card.Block>
59
+ <Icon icon='ph--at--regular' />
60
+ </Card.Block>
61
+ <Card.Text truncate className='text-sky-text text-sm'>
62
+ {emails.map(({ value }) => (
63
+ <div key={value}>{value}</div>
64
+ ))}
65
+ </Card.Text>
66
+ </Card.Row>
67
+ )}
63
68
  </Card.Body>
64
69
  );
65
70
  };
@@ -16,7 +16,11 @@ export const ProjectCard = ({ subject }: AppSurface.ObjectCardProps<Pipeline.Pip
16
16
  <Card.Body>
17
17
  {image && <Card.Poster image={image} alt={Obj.getLabel(subject) ?? ''} aspect='auto' />}
18
18
  {/* <CardHeader label={name} subject={subject} db={db} /> */}
19
- {description && <Card.Text variant='description'>{description}</Card.Text>}
19
+ {description && (
20
+ <Card.Row>
21
+ <Card.Text variant='description'>{description}</Card.Text>
22
+ </Card.Row>
23
+ )}
20
24
  </Card.Body>
21
25
  );
22
26
  };
package/src/meta.ts CHANGED
@@ -3,18 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Plugin } from '@dxos/app-framework';
6
- import { DXN } from '@dxos/keys';
7
- import { trim } from '@dxos/util';
8
6
 
9
- export const meta = Plugin.makeMeta({
10
- key: DXN.make('org.dxos.plugin.preview'),
11
- name: 'Preview',
12
- author: 'DXOS',
13
- description: trim`
14
- Rich preview panel for viewing object content without opening full editors.
15
- Quick peek at documents, images, and data with inline rendering.
16
- `,
17
- icon: 'ph--eye--regular',
18
- source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-preview',
19
- tags: ['system'],
20
- });
7
+ import config from '../dx.config';
8
+
9
+ export const meta = Plugin.getMetaFromConfig(config);
@@ -3,19 +3,17 @@
3
3
  //
4
4
 
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
- import React from 'react';
7
6
 
8
7
  import { withPluginManager } from '@dxos/app-framework/testing';
9
8
  import { corePlugins } from '@dxos/plugin-testing';
10
9
  import { random } from '@dxos/random';
11
- import { Card } from '@dxos/react-ui';
12
10
  import { withLayout, withTheme } from '@dxos/react-ui/testing';
13
11
  import { type Expando } from '@dxos/schema';
14
12
  import { type Organization, type Person, type Pipeline, type Task } from '@dxos/types';
15
13
 
16
14
  import { translations } from '#translations';
17
15
 
18
- import { ExpandoCard, FormCard, JsonCard, OrganizationCard, PersonCard, ProjectCard, TaskCard } from '../cards';
16
+ import { ExpandoCard, FormCard, OrganizationCard, PersonCard, ProjectCard, TaskCard } from '../cards';
19
17
  import {
20
18
  DefaultStory,
21
19
  createExpando,
@@ -114,6 +112,13 @@ export const _Person: StoryObj<typeof DefaultStory<Person.Person>> = {
114
112
  },
115
113
  };
116
114
 
115
+ export const _PersonNoImage: StoryObj<typeof DefaultStory<Person.Person>> = {
116
+ args: {
117
+ Component: PersonCard,
118
+ createObject: createPerson,
119
+ },
120
+ };
121
+
117
122
  export const _Organization: StoryObj<typeof DefaultStory<Organization.Organization>> = {
118
123
  args: {
119
124
  Component: OrganizationCard,
@@ -122,7 +127,14 @@ export const _Organization: StoryObj<typeof DefaultStory<Organization.Organizati
122
127
  },
123
128
  };
124
129
 
125
- export const _Project: StoryObj<typeof DefaultStory<Pipeline.Pipeline>> = {
130
+ export const _OrganizationNoImage: StoryObj<typeof DefaultStory<Organization.Organization>> = {
131
+ args: {
132
+ Component: OrganizationCard,
133
+ createObject: createOrganization,
134
+ },
135
+ };
136
+
137
+ export const _Pipeline: StoryObj<typeof DefaultStory<Pipeline.Pipeline>> = {
126
138
  args: {
127
139
  Component: ProjectCard,
128
140
  createObject: createProject,
@@ -144,34 +156,3 @@ export const _Expando: StoryObj<typeof DefaultStory<Expando.Expando>> = {
144
156
  createObject: createExpando,
145
157
  },
146
158
  };
147
-
148
- export const _Json = {
149
- render: () => {
150
- const data = {
151
- subject: {
152
- id: random.string.uuid(),
153
- name: random.person.fullName(),
154
- email: random.internet.email(),
155
- tags: [random.lorem.word(), random.lorem.word(), random.lorem.word()],
156
- nested: {
157
- count: random.number.int({ max: 100 }),
158
- active: random.datatype.boolean(),
159
- },
160
- },
161
- };
162
-
163
- return (
164
- <div className='flex justify-center p-16'>
165
- <div className='dx-card-min-width dx-card-max-width'>
166
- <Card.Root>
167
- <Card.Header>
168
- <Card.IconBlock />
169
- <Card.Title>JSON</Card.Title>
170
- </Card.Header>
171
- <JsonCard data={data} />
172
- </Card.Root>
173
- </div>
174
- </div>
175
- );
176
- },
177
- };
@@ -14,10 +14,13 @@ import { CardContainer, type CardContainerProps } from '@dxos/react-ui-mosaic/te
14
14
  import { Expando } from '@dxos/schema';
15
15
  import { Organization, Person, Pipeline, Task } from '@dxos/types';
16
16
 
17
+ import { JsonCard } from '../cards';
18
+
17
19
  export type DefaultStoryProps<T extends Obj.Any, P extends {} = {}> = {
18
20
  Component: FC<AppSurface.ObjectCardProps<T> & P>;
19
21
  createObject: () => T;
20
22
  image?: boolean;
23
+ json?: boolean;
21
24
  componentProps?: P;
22
25
  };
23
26
 
@@ -25,6 +28,7 @@ export const DefaultStory = <T extends Obj.Any, P extends {} = {}>({
25
28
  Component,
26
29
  createObject,
27
30
  image,
31
+ json,
28
32
  componentProps,
29
33
  }: DefaultStoryProps<T, P>) => {
30
34
  const object = useMemo(() => createObject(), [createObject]);
@@ -48,6 +52,7 @@ export const DefaultStory = <T extends Obj.Any, P extends {} = {}>({
48
52
  subject={image ? object : omitImage(object)}
49
53
  {...(componentProps ?? ({} as P))}
50
54
  />
55
+ {json && <JsonCard data={object} />}
51
56
  </Card.Root>
52
57
  </CardContainer>
53
58
  </div>
@@ -9,7 +9,7 @@ import { meta } from '#meta';
9
9
  export const translations = [
10
10
  {
11
11
  'en-US': {
12
- [meta.id]: {
12
+ [meta.profile.key]: {
13
13
  'unable-to-create-preview.message': 'No preview',
14
14
  'todo.label': 'To do',
15
15
  'in-progress.label': 'In progress',
@@ -1,23 +0,0 @@
1
- // src/meta.ts
2
- import { Plugin } from "@dxos/app-framework";
3
- import { DXN } from "@dxos/keys";
4
- import { trim } from "@dxos/util";
5
- var meta = Plugin.makeMeta({
6
- key: DXN.make("org.dxos.plugin.preview"),
7
- name: "Preview",
8
- author: "DXOS",
9
- description: trim`
10
- Rich preview panel for viewing object content without opening full editors.
11
- Quick peek at documents, images, and data with inline rendering.
12
- `,
13
- icon: "ph--eye--regular",
14
- source: "https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-preview",
15
- tags: [
16
- "system"
17
- ]
18
- });
19
-
20
- export {
21
- meta
22
- };
23
- //# sourceMappingURL=chunk-QOM5APM7.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/meta.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\nimport { DXN } from '@dxos/keys';\nimport { trim } from '@dxos/util';\n\nexport const meta = Plugin.makeMeta({\n key: DXN.make('org.dxos.plugin.preview'),\n name: 'Preview',\n author: 'DXOS',\n description: trim`\n Rich preview panel for viewing object content without opening full editors.\n Quick peek at documents, images, and data with inline rendering.\n `,\n icon: 'ph--eye--regular',\n source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-preview',\n tags: ['system'],\n});\n"],
5
- "mappings": ";AAIA,SAASA,cAAc;AACvB,SAASC,WAAW;AACpB,SAASC,YAAY;AAEd,IAAMC,OAAOH,OAAOI,SAAS;EAClCC,KAAKJ,IAAIK,KAAK,yBAAA;EACdC,MAAM;EACNC,QAAQ;EACRC,aAAaP;;;;EAIbQ,MAAM;EACNC,QAAQ;EACRC,MAAM;IAAC;;AACT,CAAA;",
6
- "names": ["Plugin", "DXN", "trim", "meta", "makeMeta", "key", "make", "name", "author", "description", "icon", "source", "tags"]
7
- }