@dxos/plugin-masonry 0.8.4-main.406dc2a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/README.md +15 -0
- package/dist/lib/browser/chunk-VRZWIUS7.mjs +87 -0
- package/dist/lib/browser/chunk-VRZWIUS7.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +86 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/intent-resolver-YK7KRGIJ.mjs +31 -0
- package/dist/lib/browser/intent-resolver-YK7KRGIJ.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/lib/browser/react-surface-R2TDTTUL.mjs +112 -0
- package/dist/lib/browser/react-surface-R2TDTTUL.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-Z4PPM6OA.mjs +88 -0
- package/dist/lib/node-esm/chunk-Z4PPM6OA.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +87 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/intent-resolver-VVQIEZTT.mjs +32 -0
- package/dist/lib/node-esm/intent-resolver-VVQIEZTT.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/react-surface-YTC42VZ3.mjs +113 -0
- package/dist/lib/node-esm/react-surface-YTC42VZ3.mjs.map +7 -0
- package/dist/types/src/MasonryPlugin.d.ts +2 -0
- package/dist/types/src/MasonryPlugin.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +3 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +4 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/components/MasonryContainer.d.ts +7 -0
- package/dist/types/src/components/MasonryContainer.d.ts.map +1 -0
- package/dist/types/src/components/MasonryContainer.stories.d.ts +15 -0
- package/dist/types/src/components/MasonryContainer.stories.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +3 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +3 -0
- package/dist/types/src/meta.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +17 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/dist/types/src/types/Masonry.d.ts +27 -0
- package/dist/types/src/types/Masonry.d.ts.map +1 -0
- package/dist/types/src/types/MasonryAction.d.ts +23 -0
- package/dist/types/src/types/MasonryAction.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +3 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +64 -0
- package/src/MasonryPlugin.tsx +61 -0
- package/src/capabilities/index.ts +8 -0
- package/src/capabilities/intent-resolver.ts +25 -0
- package/src/capabilities/react-surface.tsx +25 -0
- package/src/components/MasonryContainer.stories.tsx +83 -0
- package/src/components/MasonryContainer.tsx +69 -0
- package/src/index.ts +7 -0
- package/src/meta.ts +14 -0
- package/src/translations.ts +25 -0
- package/src/types/Masonry.ts +50 -0
- package/src/types/MasonryAction.ts +29 -0
- package/src/types/index.ts +6 -0
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dxos/plugin-masonry",
|
|
3
|
+
"version": "0.8.4-main.406dc2a",
|
|
4
|
+
"description": "Masonry DXOS Surface plugin",
|
|
5
|
+
"homepage": "https://dxos.org",
|
|
6
|
+
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "DXOS.org",
|
|
9
|
+
"sideEffects": true,
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"source": "./src/index.ts",
|
|
14
|
+
"types": "./dist/types/src/index.d.ts",
|
|
15
|
+
"browser": "./dist/lib/browser/index.mjs",
|
|
16
|
+
"node": "./dist/lib/node-esm/index.mjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"types": "dist/types/src/index.d.ts",
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"src"
|
|
23
|
+
],
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@preact-signals/safe-react": "^0.9.0",
|
|
26
|
+
"@preact/signals-core": "^1.12.1",
|
|
27
|
+
"@preact/signals-react": "^3.3.0",
|
|
28
|
+
"@dxos/app-framework": "0.8.4-main.406dc2a",
|
|
29
|
+
"@dxos/echo": "0.8.4-main.406dc2a",
|
|
30
|
+
"@dxos/effect": "0.8.4-main.406dc2a",
|
|
31
|
+
"@dxos/plugin-client": "0.8.4-main.406dc2a",
|
|
32
|
+
"@dxos/plugin-search": "0.8.4-main.406dc2a",
|
|
33
|
+
"@dxos/react-client": "0.8.4-main.406dc2a",
|
|
34
|
+
"@dxos/plugin-space": "0.8.4-main.406dc2a",
|
|
35
|
+
"@dxos/react-ui": "0.8.4-main.406dc2a",
|
|
36
|
+
"@dxos/react-ui-form": "0.8.4-main.406dc2a",
|
|
37
|
+
"@dxos/react-ui-masonry": "0.8.4-main.406dc2a",
|
|
38
|
+
"@dxos/react-ui-stack": "0.8.4-main.406dc2a",
|
|
39
|
+
"@dxos/schema": "0.8.4-main.406dc2a"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/react": "~19.2.2",
|
|
43
|
+
"@types/react-dom": "~19.2.1",
|
|
44
|
+
"effect": "3.18.3",
|
|
45
|
+
"react": "~19.2.0",
|
|
46
|
+
"react-dom": "~19.2.0",
|
|
47
|
+
"vite": "7.1.9",
|
|
48
|
+
"@dxos/plugin-preview": "0.8.4-main.406dc2a",
|
|
49
|
+
"@dxos/random": "0.8.4-main.406dc2a",
|
|
50
|
+
"@dxos/react-ui-theme": "0.8.4-main.406dc2a",
|
|
51
|
+
"@dxos/plugin-theme": "0.8.4-main.406dc2a",
|
|
52
|
+
"@dxos/storybook-utils": "0.8.4-main.406dc2a"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"effect": "^3.13.3",
|
|
56
|
+
"react": "^19.0.0",
|
|
57
|
+
"react-dom": "^19.0.0",
|
|
58
|
+
"@dxos/react-ui-theme": "0.8.4-main.406dc2a",
|
|
59
|
+
"@dxos/react-ui": "0.8.4-main.406dc2a"
|
|
60
|
+
},
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Capabilities, Events, contributes, createIntent, defineModule, definePlugin } from '@dxos/app-framework';
|
|
6
|
+
import { ClientEvents } from '@dxos/plugin-client';
|
|
7
|
+
import { SpaceCapabilities } from '@dxos/plugin-space';
|
|
8
|
+
import { defineObjectForm } from '@dxos/plugin-space/types';
|
|
9
|
+
|
|
10
|
+
import { IntentResolver, ReactSurface } from './capabilities';
|
|
11
|
+
import { meta } from './meta';
|
|
12
|
+
import { translations } from './translations';
|
|
13
|
+
import { Masonry, MasonryAction } from './types';
|
|
14
|
+
|
|
15
|
+
export const MasonryPlugin = definePlugin(meta, () => [
|
|
16
|
+
defineModule({
|
|
17
|
+
id: `${meta.id}/module/translations`,
|
|
18
|
+
activatesOn: Events.SetupTranslations,
|
|
19
|
+
activate: () => contributes(Capabilities.Translations, translations),
|
|
20
|
+
}),
|
|
21
|
+
defineModule({
|
|
22
|
+
id: `${meta.id}/module/react-surface`,
|
|
23
|
+
activatesOn: Events.SetupReactSurface,
|
|
24
|
+
activate: ReactSurface,
|
|
25
|
+
}),
|
|
26
|
+
defineModule({
|
|
27
|
+
id: `${meta.id}/module/metadata`,
|
|
28
|
+
activatesOn: Events.SetupMetadata,
|
|
29
|
+
activate: () =>
|
|
30
|
+
contributes(Capabilities.Metadata, {
|
|
31
|
+
id: Masonry.Masonry.typename,
|
|
32
|
+
metadata: {
|
|
33
|
+
icon: 'ph--wall--regular',
|
|
34
|
+
},
|
|
35
|
+
}),
|
|
36
|
+
}),
|
|
37
|
+
defineModule({
|
|
38
|
+
id: `${meta.id}/module/object-form`,
|
|
39
|
+
activatesOn: ClientEvents.SetupSchema,
|
|
40
|
+
activate: () =>
|
|
41
|
+
contributes(
|
|
42
|
+
SpaceCapabilities.ObjectForm,
|
|
43
|
+
defineObjectForm({
|
|
44
|
+
objectSchema: Masonry.Masonry,
|
|
45
|
+
formSchema: MasonryAction.MasonryProps,
|
|
46
|
+
hidden: true,
|
|
47
|
+
getIntent: (props, options) => createIntent(MasonryAction.CreateMasonry, { ...props, space: options.space }),
|
|
48
|
+
}),
|
|
49
|
+
),
|
|
50
|
+
}),
|
|
51
|
+
defineModule({
|
|
52
|
+
id: `${meta.id}/module/react-surface`,
|
|
53
|
+
activatesOn: Events.SetupReactSurface,
|
|
54
|
+
activate: ReactSurface,
|
|
55
|
+
}),
|
|
56
|
+
defineModule({
|
|
57
|
+
id: `${meta.id}/module/intent-resolver`,
|
|
58
|
+
activatesOn: Events.SetupIntentResolver,
|
|
59
|
+
activate: IntentResolver,
|
|
60
|
+
}),
|
|
61
|
+
]);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Capabilities, type PluginContext, contributes, createResolver } from '@dxos/app-framework';
|
|
6
|
+
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
7
|
+
|
|
8
|
+
import { Masonry, MasonryAction } from '../types';
|
|
9
|
+
|
|
10
|
+
export default (context: PluginContext) =>
|
|
11
|
+
contributes(Capabilities.IntentResolver, [
|
|
12
|
+
createResolver({
|
|
13
|
+
intent: MasonryAction.CreateMasonry,
|
|
14
|
+
resolve: async ({ space, name, typename }) => {
|
|
15
|
+
const client = context.getCapability(ClientCapabilities.Client);
|
|
16
|
+
const { view } = await Masonry.makeView({
|
|
17
|
+
client,
|
|
18
|
+
space,
|
|
19
|
+
name,
|
|
20
|
+
typename,
|
|
21
|
+
});
|
|
22
|
+
return { data: { object: view } };
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
]);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { Capabilities, contributes, createSurface } from '@dxos/app-framework';
|
|
8
|
+
import { Obj } from '@dxos/echo';
|
|
9
|
+
import { DataType } from '@dxos/schema';
|
|
10
|
+
|
|
11
|
+
import { MasonryContainer } from '../components/MasonryContainer';
|
|
12
|
+
import { meta } from '../meta';
|
|
13
|
+
import { Masonry } from '../types';
|
|
14
|
+
|
|
15
|
+
export default () =>
|
|
16
|
+
contributes(Capabilities.ReactSurface, [
|
|
17
|
+
createSurface({
|
|
18
|
+
id: meta.id,
|
|
19
|
+
role: ['article', 'section'],
|
|
20
|
+
filter: (data): data is { subject: DataType.View } =>
|
|
21
|
+
Obj.instanceOf(DataType.View, data.subject) &&
|
|
22
|
+
Obj.instanceOf(Masonry.Masonry, data.subject.presentation?.target),
|
|
23
|
+
component: ({ data, role }) => <MasonryContainer view={data.subject} role={role} />,
|
|
24
|
+
}),
|
|
25
|
+
]);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React, { useEffect, useState } from 'react';
|
|
7
|
+
|
|
8
|
+
import { IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
|
|
9
|
+
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
10
|
+
import { ClientPlugin } from '@dxos/plugin-client';
|
|
11
|
+
import { PreviewPlugin } from '@dxos/plugin-preview';
|
|
12
|
+
import { SpacePlugin } from '@dxos/plugin-space';
|
|
13
|
+
import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
|
|
14
|
+
import { ThemePlugin } from '@dxos/plugin-theme';
|
|
15
|
+
import { faker } from '@dxos/random';
|
|
16
|
+
import { Filter, useQuery, useSpaces } from '@dxos/react-client/echo';
|
|
17
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
18
|
+
import { defaultTx } from '@dxos/react-ui-theme';
|
|
19
|
+
import { DataType } from '@dxos/schema';
|
|
20
|
+
import { createObjectFactory } from '@dxos/schema/testing';
|
|
21
|
+
|
|
22
|
+
import { Masonry } from '../types';
|
|
23
|
+
|
|
24
|
+
import { MasonryContainer } from './MasonryContainer';
|
|
25
|
+
|
|
26
|
+
faker.seed(0);
|
|
27
|
+
|
|
28
|
+
const StorybookMasonry = () => {
|
|
29
|
+
const spaces = useSpaces();
|
|
30
|
+
const space = spaces[spaces.length - 1];
|
|
31
|
+
const views = useQuery(space, Filter.type(DataType.View));
|
|
32
|
+
const [view, setView] = useState<DataType.View>();
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (views.length && !view) {
|
|
35
|
+
const view = views[0];
|
|
36
|
+
setView(view);
|
|
37
|
+
}
|
|
38
|
+
}, [views]);
|
|
39
|
+
|
|
40
|
+
return view ? <MasonryContainer view={view} role='story' /> : null;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const meta = {
|
|
44
|
+
title: 'plugins/plugin-masonry/Masonry',
|
|
45
|
+
component: StorybookMasonry,
|
|
46
|
+
render: () => <StorybookMasonry />,
|
|
47
|
+
decorators: [
|
|
48
|
+
withTheme,
|
|
49
|
+
withPluginManager({
|
|
50
|
+
plugins: [
|
|
51
|
+
ClientPlugin({
|
|
52
|
+
types: [DataType.Organization, DataType.View, Masonry.Masonry],
|
|
53
|
+
onClientInitialized: async ({ client }) => {
|
|
54
|
+
await client.halo.createIdentity();
|
|
55
|
+
const space = await client.spaces.create();
|
|
56
|
+
await space.waitUntilReady();
|
|
57
|
+
|
|
58
|
+
const { view } = await Masonry.makeView({ space, client, typename: DataType.Organization.typename });
|
|
59
|
+
space.db.add(view);
|
|
60
|
+
|
|
61
|
+
const factory = createObjectFactory(space.db, faker as any);
|
|
62
|
+
await factory([{ type: DataType.Organization, count: 64 }]);
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
SpacePlugin({}),
|
|
66
|
+
IntentPlugin(),
|
|
67
|
+
SettingsPlugin(),
|
|
68
|
+
ThemePlugin({ tx: defaultTx }),
|
|
69
|
+
PreviewPlugin(),
|
|
70
|
+
StorybookLayoutPlugin({}),
|
|
71
|
+
],
|
|
72
|
+
}),
|
|
73
|
+
],
|
|
74
|
+
parameters: {
|
|
75
|
+
layout: 'fullscreen',
|
|
76
|
+
},
|
|
77
|
+
} satisfies Meta;
|
|
78
|
+
|
|
79
|
+
export default meta;
|
|
80
|
+
|
|
81
|
+
type Story = StoryObj<typeof meta>;
|
|
82
|
+
|
|
83
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Surface } from '@dxos/app-framework';
|
|
8
|
+
import { Filter, Type } from '@dxos/echo';
|
|
9
|
+
import { EchoSchema, type TypedObject } from '@dxos/echo/internal';
|
|
10
|
+
import { useGlobalFilteredObjects } from '@dxos/plugin-search';
|
|
11
|
+
import { useClient } from '@dxos/react-client';
|
|
12
|
+
import { getSpace, useQuery } from '@dxos/react-client/echo';
|
|
13
|
+
import { Masonry } from '@dxos/react-ui-masonry';
|
|
14
|
+
import { type DataType, ProjectionModel, getTypenameFromQuery } from '@dxos/schema';
|
|
15
|
+
|
|
16
|
+
const Item = ({ data }: { data: any }) => {
|
|
17
|
+
return <Surface role='card' limit={1} data={{ subject: data }} />;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const MasonryContainer = ({ view, role }: { view: DataType.View; role: string }) => {
|
|
21
|
+
const client = useClient();
|
|
22
|
+
const space = getSpace(view);
|
|
23
|
+
const typename = view.query ? getTypenameFromQuery(view.query.ast) : undefined;
|
|
24
|
+
|
|
25
|
+
const [cardSchema, setCardSchema] = useState<TypedObject<any, any>>();
|
|
26
|
+
const [projection, setProjection] = useState<ProjectionModel>();
|
|
27
|
+
|
|
28
|
+
const jsonSchema = useMemo(() => {
|
|
29
|
+
if (!cardSchema) return undefined;
|
|
30
|
+
return cardSchema instanceof EchoSchema ? cardSchema.jsonSchema : Type.toJsonSchema(cardSchema);
|
|
31
|
+
}, [cardSchema]);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const staticSchema = client.graph.schemaRegistry.schemas.find((schema) => Type.getTypename(schema) === typename);
|
|
35
|
+
if (staticSchema) {
|
|
36
|
+
setCardSchema(() => staticSchema as TypedObject<any, any>);
|
|
37
|
+
}
|
|
38
|
+
if (!staticSchema && typename && space) {
|
|
39
|
+
const query = space.db.schemaRegistry.query({ typename });
|
|
40
|
+
const unsubscribe = query.subscribe(
|
|
41
|
+
() => {
|
|
42
|
+
const [schema] = query.results;
|
|
43
|
+
if (schema) {
|
|
44
|
+
setCardSchema(schema);
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{ fire: true },
|
|
48
|
+
);
|
|
49
|
+
return unsubscribe;
|
|
50
|
+
}
|
|
51
|
+
}, [typename, space]);
|
|
52
|
+
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (jsonSchema) {
|
|
55
|
+
setProjection(new ProjectionModel(jsonSchema, view.projection));
|
|
56
|
+
}
|
|
57
|
+
}, [view.projection, JSON.stringify(jsonSchema)]);
|
|
58
|
+
|
|
59
|
+
const objects = useQuery(space, cardSchema ? Filter.type(cardSchema) : Filter.nothing());
|
|
60
|
+
const filteredObjects = useGlobalFilteredObjects(objects);
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Masonry.Root
|
|
64
|
+
items={filteredObjects}
|
|
65
|
+
render={Item as any}
|
|
66
|
+
classNames='is-full max-is-full bs-full max-bs-full overflow-y-auto p-4'
|
|
67
|
+
/>
|
|
68
|
+
);
|
|
69
|
+
};
|
package/src/index.ts
ADDED
package/src/meta.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type PluginMeta } from '@dxos/app-framework';
|
|
6
|
+
|
|
7
|
+
export const meta: PluginMeta = {
|
|
8
|
+
id: 'dxos.org/plugin/masonry',
|
|
9
|
+
name: 'Masonry',
|
|
10
|
+
description: 'Masonry displays items from a View query in a responsive grid.',
|
|
11
|
+
icon: 'ph--wall--regular',
|
|
12
|
+
source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-masonry',
|
|
13
|
+
screenshots: [],
|
|
14
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Resource } from '@dxos/react-ui';
|
|
6
|
+
|
|
7
|
+
import { meta } from './meta';
|
|
8
|
+
import { Masonry } from './types';
|
|
9
|
+
|
|
10
|
+
export const translations = [
|
|
11
|
+
{
|
|
12
|
+
'en-US': {
|
|
13
|
+
[Masonry.Masonry.typename]: {
|
|
14
|
+
'typename label': 'Masonry',
|
|
15
|
+
'typename label_zero': 'Masonries',
|
|
16
|
+
'typename label_one': 'Masonry',
|
|
17
|
+
'typename label_other': 'Masonries',
|
|
18
|
+
'object name placeholder': 'New masonry',
|
|
19
|
+
},
|
|
20
|
+
[meta.id]: {
|
|
21
|
+
'plugin name': 'Masonry',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
] as const satisfies Resource[];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
|
+
|
|
7
|
+
import { Obj, Type } from '@dxos/echo';
|
|
8
|
+
import { type JsonSchemaType, ViewAnnotation, toEffectSchema } from '@dxos/echo/internal';
|
|
9
|
+
import { type CreateViewFromSpaceProps, type DataType, createViewFromSpace } from '@dxos/schema';
|
|
10
|
+
|
|
11
|
+
export const Masonry = Schema.Struct({
|
|
12
|
+
arrangement: Schema.Array(
|
|
13
|
+
Schema.Struct({
|
|
14
|
+
ids: Schema.Array(Type.ObjectId),
|
|
15
|
+
hidden: Schema.optional(Schema.Boolean),
|
|
16
|
+
}).pipe(Schema.mutable),
|
|
17
|
+
).pipe(Schema.mutable, Schema.optional),
|
|
18
|
+
// TODO(wittjosiah): Consider Masonry supporting not being just a view but referencing arbitrary data directly.
|
|
19
|
+
}).pipe(
|
|
20
|
+
Type.Obj({
|
|
21
|
+
typename: 'dxos.org/type/Masonry',
|
|
22
|
+
version: '0.1.0',
|
|
23
|
+
}),
|
|
24
|
+
ViewAnnotation.set(true),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
export type Masonry = Schema.Schema.Type<typeof Masonry>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Make a masonry object.
|
|
31
|
+
*/
|
|
32
|
+
export const make = (props: Obj.MakeProps<typeof Masonry> = {}) => Obj.make(Masonry, props);
|
|
33
|
+
|
|
34
|
+
export type MakeViewProps = Omit<CreateViewFromSpaceProps, 'presentation'>;
|
|
35
|
+
|
|
36
|
+
export const makeView = async ({
|
|
37
|
+
...props
|
|
38
|
+
}: MakeViewProps): Promise<{
|
|
39
|
+
jsonSchema: JsonSchemaType;
|
|
40
|
+
view: DataType.View;
|
|
41
|
+
schema: ReturnType<typeof toEffectSchema>;
|
|
42
|
+
}> => {
|
|
43
|
+
const masonry = Obj.make(Masonry, {});
|
|
44
|
+
const { jsonSchema, view } = await createViewFromSpace({ ...props, presentation: masonry });
|
|
45
|
+
|
|
46
|
+
// Preset sizes.
|
|
47
|
+
const schema = toEffectSchema(jsonSchema);
|
|
48
|
+
|
|
49
|
+
return { jsonSchema, schema, view };
|
|
50
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
|
+
|
|
7
|
+
import { SpaceSchema } from '@dxos/react-client/echo';
|
|
8
|
+
import { DataType, TypenameAnnotationId } from '@dxos/schema';
|
|
9
|
+
|
|
10
|
+
import { meta } from '../meta';
|
|
11
|
+
|
|
12
|
+
const MASONRY_ACTION = `${meta.id}/action`;
|
|
13
|
+
|
|
14
|
+
export const MasonryProps = Schema.Struct({
|
|
15
|
+
name: Schema.optional(Schema.String),
|
|
16
|
+
typename: Schema.optional(
|
|
17
|
+
Schema.String.annotations({
|
|
18
|
+
[TypenameAnnotationId]: ['used-static', 'dynamic'],
|
|
19
|
+
title: 'Select card record type (leave empty to start fresh)',
|
|
20
|
+
}),
|
|
21
|
+
),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export class CreateMasonry extends Schema.TaggedClass<CreateMasonry>()(`${MASONRY_ACTION}/create`, {
|
|
25
|
+
input: Schema.extend(Schema.Struct({ space: SpaceSchema }), MasonryProps),
|
|
26
|
+
output: Schema.Struct({
|
|
27
|
+
object: DataType.View,
|
|
28
|
+
}),
|
|
29
|
+
}) {}
|