Export template source from acfb7833556431786c1aa364ca03758c9bc8cc7d:quixos-instance/packages/web-studio-canvas-runtime
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import { QxReject, type ExactReference, type MutationKey } from "@quixos/camino-replica-core";
|
||||
import { generic, type Contexts, type PortableImplementation } from "./gen/qx.js";
|
||||
const position = (value: { readonly x: number; readonly y: number }) => {
|
||||
if (!Number.isFinite(value.x) || !Number.isFinite(value.y)) throw new QxReject("INVALID_POSITION");
|
||||
};
|
||||
const size = (value: { readonly width: number; readonly height: number }) => {
|
||||
if (!Number.isFinite(value.width) || !Number.isFinite(value.height) || value.width <= 0 || value.height <= 0)
|
||||
throw new QxReject("INVALID_SIZE");
|
||||
};
|
||||
const canPresent = async ({
|
||||
receiver,
|
||||
input,
|
||||
ports,
|
||||
}: {
|
||||
readonly receiver: ExactReference;
|
||||
readonly input: string;
|
||||
readonly ports: {
|
||||
readonly catalog: {
|
||||
presentations(): Promise<ReadonlyArray<{ readonly id: string; readonly atoms: readonly string[] }>>;
|
||||
};
|
||||
};
|
||||
}) => {
|
||||
const presentations = await ports.catalog.presentations();
|
||||
return presentations.some((p) => p.id === input && p.atoms.includes(receiver.expectation.id));
|
||||
};
|
||||
const place = async ({ receiver, input, ports }: Contexts["place"]) => {
|
||||
position(input.layout);
|
||||
size(input.layout);
|
||||
if (!(await ports.subject["canPresent.call"]({ receiver: input.subject, input: input.presentation })))
|
||||
throw new QxReject("INVALID_PRESENTATION");
|
||||
return ports.placement.create(
|
||||
{
|
||||
canvas: { ...receiver, expectation: { kind: "interface", id: "interface:org.quixos.web-studio.canvas@1" } },
|
||||
subject: input.subject,
|
||||
presentation: input.presentation,
|
||||
position: { x: input.layout.x, y: input.layout.y },
|
||||
size: { width: input.layout.width, height: input.layout.height },
|
||||
z: input.layout.z,
|
||||
},
|
||||
{ key: "placement" },
|
||||
);
|
||||
};
|
||||
export const createPlaced = async <Input>({
|
||||
input,
|
||||
ports,
|
||||
}: {
|
||||
input: {
|
||||
seed: Input;
|
||||
canvas: Contexts["place"]["receiver"];
|
||||
presentation: string;
|
||||
layout: Contexts["place"]["input"]["layout"];
|
||||
};
|
||||
ports: {
|
||||
factory: { "create.call"(input: Input, key: MutationKey): Promise<ExactReference> };
|
||||
canvas: {
|
||||
"place.call"(
|
||||
input: { receiver: ExactReference; input: Contexts["place"]["input"] },
|
||||
key: MutationKey,
|
||||
): Promise<Awaited<ReturnType<PortableImplementation["place"]>>>;
|
||||
};
|
||||
};
|
||||
}) => {
|
||||
const subject = await ports.factory["create.call"](input.seed, { key: "subject" });
|
||||
return ports.canvas["place.call"](
|
||||
{
|
||||
receiver: input.canvas,
|
||||
input: {
|
||||
subject: { ...subject, expectation: { kind: "interface", id: "interface:org.quixos.web-studio.placeable@1" } },
|
||||
presentation: input.presentation,
|
||||
layout: input.layout,
|
||||
},
|
||||
},
|
||||
{ key: "placement" },
|
||||
);
|
||||
};
|
||||
export const handlers: Omit<PortableImplementation, "createRoot"> = {
|
||||
...generic.canPresent(canPresent),
|
||||
...generic.createPlaced(createPlaced),
|
||||
createCanvas: ({ input, ports }) => ports.canvas.create({ name: input }, { key: "canvas" }),
|
||||
place,
|
||||
createAndPlace: async (context) => {
|
||||
const subject = await context.ports.canvas.create({ name: context.input.name }, { key: "canvas" });
|
||||
return place({
|
||||
...context,
|
||||
input: {
|
||||
subject: { ...subject, expectation: { kind: "interface", id: "interface:org.quixos.web-studio.placeable@1" } },
|
||||
presentation: context.input.presentation,
|
||||
layout: context.input.layout,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user