Export template source from be30143a326d5d7d7b0cbabea5bc5ac0301ef5b9:quixos-instance/packages/web-studio-canvas-runtime
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
node_modules/
|
||||
dist/
|
||||
src/gen/
|
||||
.quixos/
|
||||
result
|
||||
.yarn/cache/
|
||||
.yarn/install-state.gz
|
||||
.yarn/unplugged/
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"monorepoCommit": "be30143a326d5d7d7b0cbabea5bc5ac0301ef5b9",
|
||||
"sourcePath": "quixos-instance/packages/web-studio-canvas-runtime"
|
||||
}
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
+24
@@ -0,0 +1,24 @@
|
||||
enableScripts: true
|
||||
|
||||
generateDefaultNix: false
|
||||
|
||||
individualNixPackaging: true
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
supportedArchitectures:
|
||||
os:
|
||||
- current
|
||||
- linux
|
||||
cpu:
|
||||
- current
|
||||
- x64
|
||||
- arm64
|
||||
libc:
|
||||
- current
|
||||
- glibc
|
||||
|
||||
plugins:
|
||||
- checksum: 271de9a785321a37c564b8e2a6b5cd689850b20572d5fee8ec0a6b8e7a5d4cfb59e533524af2b4a537e00da12828abd062eaec6978556e3dd9149a020db2591b
|
||||
path: .yarn/plugins/yarn-plugin-nixify.cjs
|
||||
spec: "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/yarn-plugin-nixify-patched/raw/commit/4528fdd20b30d869262443b3f044549810e75fb8/dist/yarn-plugin-nixify.js"
|
||||
@@ -0,0 +1,43 @@
|
||||
# Studio graph capabilities
|
||||
|
||||
This system package implements ordinary Canvas/Placement/Placeable interfaces.
|
||||
It owns no database, web server, Worker, page session, or special presentation
|
||||
object per rendered subject. The workspace binds storage and relationship edges.
|
||||
The checked component is an independent consumer of the same public contracts.
|
||||
|
||||
- `Canvas.create` creates an initialized canvas. The server entry factory uses the
|
||||
workspace host's idempotent root protocol, without a second package-local cache.
|
||||
- `Canvas.place` validates the requested renderer through the subject's portable
|
||||
`Placeable.canPresent` contract and creates one placement with both relationships.
|
||||
- `Canvas.createAndPlace` is an example compound factory: child canvas creation,
|
||||
renderer validation and placement creation share one transaction. An invalid
|
||||
renderer rolls back the child, too. Other domains can compose their own creation
|
||||
ports in exactly this way; there is no frontend business reducer.
|
||||
- `position` and `size` are separate whole-record registers. Concurrent move and
|
||||
resize survive independently; concurrent moves resolve in server acceptance
|
||||
order without mixing one move's x coordinate with another move's y coordinate.
|
||||
- `remove` is explicitly server-only. Deletion needs the full incoming-reference
|
||||
graph; a partial replica cannot safely predict all deletion restrictions and
|
||||
cascades. Removing a placement preserves its subject. The interface does not
|
||||
advertise a portable delete or keep a hidden archive in the canvas query.
|
||||
|
||||
The generic `canPresent<atom Subject>` implementation reads the explicitly granted
|
||||
`reflection catalog [presentations]` port. This exposes only immutable checked
|
||||
presentation IDs, subject contracts and their conforming atoms. It does not expose
|
||||
live object inventory or private state. The dispatcher verifies the concrete
|
||||
receiver; reference expectations supplied by a caller are not conformance proof.
|
||||
A changed presentation catalog participates in the consuming execution group's
|
||||
reuse digest. Unrelated modules do not acquire that dependency.
|
||||
|
||||
Queries have explicit prototype bounds: 100 canvases in navigation and 200
|
||||
placements per open canvas. Title-only cards use their own small input projection.
|
||||
A selected/new placement can retain `PlacementInputs` even if a list excludes it.
|
||||
A larger Studio should add explicit windows or pagination rather than silently
|
||||
pretend these bounded queries cover an arbitrarily large workspace.
|
||||
|
||||
`tools/local-first/studio.nix` builds the source snapshot through the checked
|
||||
artifact builder and tests the generic workspace host. Run
|
||||
`nix build .#checks.x86_64-linux.camino-studio-capabilities` at the monorepo root.
|
||||
These are unpublished fixture resource pins; normal independently retained source
|
||||
assembly and scaffolding are qualified in WI-12. The old checkedServer/Yarn and
|
||||
migration recipes were removed, rather than presenting them as a compatible path.
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component:studio:canvas-card" = {
|
||||
entry = "src/canvas-card.tsx";
|
||||
export = "CanvasCard";
|
||||
};
|
||||
}
|
||||
Generated
+108
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"helpers": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1790852599,
|
||||
"narHash": "sha256-MdNtZpcsoguLPSCpAy9Naz6fkVPrftbZQbz1Aj7Zm9A=",
|
||||
"ref": "refs/tags/quixos-reachability/91679e8cc82133093cb0b4f9e519cbb39a5bba4f",
|
||||
"rev": "91679e8cc82133093cb0b4f9e519cbb39a5bba4f",
|
||||
"revCount": 54,
|
||||
"type": "git",
|
||||
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
|
||||
},
|
||||
"original": {
|
||||
"ref": "refs/tags/quixos-reachability/91679e8cc82133093cb0b4f9e519cbb39a5bba4f",
|
||||
"rev": "91679e8cc82133093cb0b4f9e519cbb39a5bba4f",
|
||||
"type": "git",
|
||||
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1783776592,
|
||||
"narHash": "sha256-UgCQzxeWI75XM8G+hPrPh+MKzEPjG3SpAj7dtqSbksA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e7a3ca8092b61ff85b6a45bf863ea2b2d6a661b3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"protocol": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1791261504,
|
||||
"narHash": "sha256-QSk9DWR7n5KL6cMHzmSKKXNIyaFA0s8Nu+wXjhhlENI=",
|
||||
"ref": "refs/tags/quixos-reachability/5b44c8154dc038efd87cf1cbdd2c00b66bfd4f87",
|
||||
"rev": "5b44c8154dc038efd87cf1cbdd2c00b66bfd4f87",
|
||||
"revCount": 184,
|
||||
"type": "git",
|
||||
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git"
|
||||
},
|
||||
"original": {
|
||||
"ref": "refs/tags/quixos-reachability/5b44c8154dc038efd87cf1cbdd2c00b66bfd4f87",
|
||||
"rev": "5b44c8154dc038efd87cf1cbdd2c00b66bfd4f87",
|
||||
"type": "git",
|
||||
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"protocol",
|
||||
"flake-utils"
|
||||
],
|
||||
"helpers": "helpers",
|
||||
"nixpkgs": [
|
||||
"protocol",
|
||||
"nixpkgs"
|
||||
],
|
||||
"protocol": "protocol"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
inputs.protocol.url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git?ref=refs/tags/quixos-reachability/5b44c8154dc038efd87cf1cbdd2c00b66bfd4f87&rev=5b44c8154dc038efd87cf1cbdd2c00b66bfd4f87";
|
||||
inputs.nixpkgs.follows = "protocol/nixpkgs";
|
||||
inputs.flake-utils.follows = "protocol/flake-utils";
|
||||
inputs.helpers = {
|
||||
url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git?ref=refs/tags/quixos-reachability/91679e8cc82133093cb0b4f9e519cbb39a5bba4f&rev=91679e8cc82133093cb0b4f9e519cbb39a5bba4f";
|
||||
flake = false;
|
||||
};
|
||||
outputs =
|
||||
{
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
helpers,
|
||||
...
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
camino = import (helpers + "/quixos-package-helpers.nix");
|
||||
in
|
||||
{
|
||||
quixosPackages.checkedArtifacts =
|
||||
context:
|
||||
let
|
||||
pkgs = camino.packageSet { inherit nixpkgs system context; };
|
||||
dependencies =
|
||||
if builtins.pathExists ./yarn-project.nix then
|
||||
camino.mkCaminoYarnDependencies {
|
||||
inherit pkgs;
|
||||
src = ./.;
|
||||
}
|
||||
else
|
||||
null;
|
||||
in
|
||||
camino.assembleCaminoPackage {
|
||||
inherit pkgs context;
|
||||
artifacts = [
|
||||
(camino.mkCaminoTypeScriptPackage {
|
||||
inherit pkgs context dependencies;
|
||||
src = ./.;
|
||||
entry = "src/server.ts";
|
||||
entries.browser = "src/browser.ts";
|
||||
})
|
||||
(camino.mkCaminoReactPackage {
|
||||
inherit pkgs context dependencies;
|
||||
src = ./.;
|
||||
modules = import ./components.nix;
|
||||
})
|
||||
];
|
||||
};
|
||||
devShells.default = camino.mkCaminoYarnShell { inherit pkgs; };
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "@quixos/web-studio-canvas-runtime",
|
||||
"private": true,
|
||||
"type": "module"
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
symbol JavaScript id "target:org.quixos.execution.javascript@1";
|
||||
import interface WebStudioFactory;
|
||||
import interface WebStudioSearchable;
|
||||
import interface StandaloneView;
|
||||
import interface WebStudioCanvas;
|
||||
import interface WebStudioCanvasPlacement;
|
||||
import interface WebStudioPlaceable;
|
||||
external atom WebStudioCanvas id "atom:org.quixos.web-studio:canvas";
|
||||
external atom WebStudioCanvasPlacement id "atom:org.quixos.web-studio:canvas-placement";
|
||||
type Position=record {x:double;y:double;};
|
||||
type Size=record {width:double;height:double;};
|
||||
type Layout=record {x:double;y:double;width:double;height:double;z:int32;};
|
||||
type PlacementSeed=record {canvas:interface-ref<WebStudioCanvas>;subject:interface-ref<WebStudioPlaceable>;presentation:string;position:Position;size:Size;z:int32;};
|
||||
package WebStudioCanvasRuntime id "package:org.quixos.web-studio:canvas-runtime" revision "package:org.quixos.web-studio:canvas-runtime@1" {
|
||||
function createPlaced<value Input, object Result implements WebStudioPlaceable> id "studio:create-placed" : record {canvas:interface-ref<WebStudioCanvas>;seed:Input;presentation:string;layout:Layout;} -> atom-ref<WebStudioCanvasPlacement> execution transaction targets [JavaScript,server] requires {
|
||||
interface factory id "factory" : WebStudioFactory<Input,Result> using [create.call];
|
||||
interface canvas id "canvas" : WebStudioCanvas using [place.call] from input;
|
||||
};
|
||||
function createCanvas id "studio:create-canvas" : string -> atom-ref<WebStudioCanvas> execution transaction targets [JavaScript,server] requires {creation canvas id "canvas" : WebStudioCanvas input record {name:string;};};
|
||||
function createRoot id "studio:create-root" : unit -> atom-ref<WebStudioCanvas> execution transaction targets [server] requires {creation canvas id "canvas" : WebStudioCanvas input record {name:string;};};
|
||||
operation canPresent<object Subject> id "studio:can-present" : string -> bool mode call execution snapshot targets [JavaScript,server] receiver object Subject requires {reflection catalog id "catalog" [presentations];};
|
||||
operation place id "studio:place" : record {subject:interface-ref<WebStudioPlaceable>;presentation:string;layout:Layout;} -> atom-ref<WebStudioCanvasPlacement> mode call execution transaction targets [JavaScript,server] receiver any requires {
|
||||
interface subject id "subject" : WebStudioPlaceable using [canPresent.call] from input;
|
||||
creation placement id "placement" : WebStudioCanvasPlacement input PlacementSeed;
|
||||
};
|
||||
operation createAndPlace id "studio:create-and-place" : record {name:string;presentation:string;layout:Layout;} -> atom-ref<WebStudioCanvasPlacement> mode call execution transaction targets [JavaScript,server] receiver any requires {
|
||||
interface subject id "subject" : WebStudioPlaceable using [canPresent.call] from input;
|
||||
creation canvas id "canvas" : WebStudioCanvas input record {name:string;};
|
||||
creation placement id "placement" : WebStudioCanvasPlacement input PlacementSeed;
|
||||
};
|
||||
module CanvasCard id "component:studio:canvas-card" implements StandaloneView<interface WebStudioCanvas>.render;
|
||||
query TitleInputs id "studio:title-inputs" root WebStudioCanvas document "queries/title-inputs.graphql" operation "TitleInputs" {replica;}
|
||||
query TitleView id "studio:title-view" root WebStudioCanvas document "queries/title-view.graphql" operation "TitleView" {local from TitleInputs;watch;}
|
||||
query CanvasIndexInputs id "studio:canvas-index-inputs" root workspace WebStudioCanvas document "queries/canvas-index-inputs.graphql" operation "CanvasIndexInputs" {replica;}
|
||||
query CanvasIndex id "studio:canvas-index" root workspace WebStudioCanvas document "queries/canvas-index.graphql" operation "CanvasIndex" {local from CanvasIndexInputs;watch;}
|
||||
query PlaceableInputs id "studio:placeable-inputs" root WebStudioPlaceable document "queries/placeable-inputs.graphql" operation "PlaceableInputs" {replica;}
|
||||
query PlaceableView id "studio:placeable-view" root WebStudioPlaceable document "queries/placeable-view.graphql" operation "PlaceableView" {local from PlaceableInputs;watch;}
|
||||
query PlacementInputs id "studio:placement-inputs" root WebStudioCanvasPlacement document "queries/placement-inputs.graphql" operation "PlacementInputs" {replica;}
|
||||
query CanvasInputs id "studio:canvas-inputs" root WebStudioCanvas document "queries/canvas-inputs.graphql" operation "CanvasInputs" {replica;max rows 200;}
|
||||
query CanvasView id "studio:canvas-view" root WebStudioCanvas document "queries/canvas-view.graphql" operation "CanvasView" {local from CanvasInputs;max rows 200;watch;}
|
||||
query SearchInputs id "studio:search-inputs" root workspace WebStudioSearchable document "queries/search-inputs.graphql" operation "SearchInputs" {replica;}
|
||||
query Search id "studio:search" root workspace WebStudioSearchable document "queries/search.graphql" operation "Search" {local from SearchInputs;watch;}
|
||||
query LabelInputs id "studio:label-inputs" root workspace WebStudioSearchable document "queries/label-inputs.graphql" operation "LabelInputs" {replica;}
|
||||
query Labels id "studio:labels" root workspace WebStudioSearchable document "queries/labels.graphql" operation "Labels" {local from LabelInputs;watch;}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
query CanvasIndexInputs { root { objects(all: 100) { entries { node { _camino {ref} name } } } } }
|
||||
@@ -0,0 +1 @@
|
||||
query CanvasIndex { root { availableObjects(all: 100) { entries { node { _camino {ref} name } } } } }
|
||||
@@ -0,0 +1 @@
|
||||
query CanvasInputs { root { name placements(all: 200) { entries { key node { _camino {ref} position {x y} size {width height} z presentation subject { _camino {ref} } } } } } }
|
||||
@@ -0,0 +1 @@
|
||||
query CanvasView { root { name placements(all: 200) { entries { key node { _camino {ref} position {x y} size {width height} z presentation subject { _camino {ref} } } } } } }
|
||||
@@ -0,0 +1 @@
|
||||
query LabelInputs($refs: [QxRef_WebStudioSearchable!]!) { root { objects(all: 100, where: {_camino: {ref: {in: $refs}}}) { entries { node { _camino {ref} title } } } } }
|
||||
@@ -0,0 +1 @@
|
||||
query Labels($refs: [QxRef_WebStudioSearchable!]!) { root { objects(all: 100, where: {_camino: {ref: {in: $refs}}}) { entries { node { _camino {ref} title } } } } }
|
||||
@@ -0,0 +1 @@
|
||||
query PlaceableInputs { root { _camino { ref } } }
|
||||
@@ -0,0 +1 @@
|
||||
query PlaceableView { root { _camino { ref } } }
|
||||
@@ -0,0 +1 @@
|
||||
query PlacementInputs { root { _camino {ref} position {x y} size {width height} z presentation subject { _camino {ref} } canvas { _camino {ref} name } } }
|
||||
@@ -0,0 +1 @@
|
||||
query SearchInputs($text: String!, $after: Cursor) { root { objects(first: 30, after: $after, where: {or: [{title: {containsInsensitive: $text}}, {searchText: {containsInsensitive: $text}}]}, orderBy: {title: ASC}) { entries { node { _camino {ref} title } } pageInfo {hasNextPage endCursor} } } }
|
||||
@@ -0,0 +1 @@
|
||||
query Search($text: String!, $after: Cursor) { root { objects(first: 30, after: $after, where: {or: [{title: {containsInsensitive: $text}}, {searchText: {containsInsensitive: $text}}]}, orderBy: {title: ASC}) { entries { node { _camino {ref} title } } pageInfo {hasNextPage endCursor} } } }
|
||||
@@ -0,0 +1 @@
|
||||
query TitleInputs { root { name } }
|
||||
@@ -0,0 +1 @@
|
||||
query TitleView { root { name } }
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"backend": "execution",
|
||||
"queryFrontends": ["react"]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
quixos-lock version 1 {
|
||||
quixos source { repository "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos.git"; commit "be30143a326d5d7d7b0cbabea5bc5ac0301ef5b9"; }
|
||||
interface WebStudioFactory source { repository "https://repos.quixos.org/quixos-studio/interface-web-studio-factory.git"; commit "a4136d9bfd765db6b2de2188ef2caf341e0f7a61"; }
|
||||
interface WebStudioSearchable source { repository "https://repos.quixos.org/quixos-studio/interface-web-studio-searchable.git"; commit "b51116e6d320fc4dcd79f0d067124adf6a8e919f"; }
|
||||
interface StandaloneView source { repository "https://repos.quixos.org/quixos-studio/interface-react-standalone-view.git"; commit "67b00f7ff8df87a477e12c5668c42684d8fa1708"; }
|
||||
interface WebStudioCanvas source { repository "https://repos.quixos.org/quixos-studio/interface-web-studio-canvas.git"; commit "fb076e2d0d48080f76b88b2ffa4edeb4c37a7342"; }
|
||||
interface WebStudioCanvasPlacement source { repository "https://repos.quixos.org/quixos-studio/interface-web-studio-canvas-placement.git"; commit "8bee874e37700fc860f066f11946efc82a1f521d"; }
|
||||
interface WebStudioPlaceable source { repository "https://repos.quixos.org/quixos-studio/interface-web-studio-placeable.git"; commit "a998ebd982f7b61946156a0fa7038bc1295c3afc"; }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"modules": {
|
||||
"CanvasCard": {
|
||||
"inputs": [
|
||||
{
|
||||
"name": "body",
|
||||
"query": "TitleView",
|
||||
"root": {
|
||||
"from": "input",
|
||||
"path": ["subject"]
|
||||
},
|
||||
"arguments": {
|
||||
"record": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { createRegistry } from "./gen/qx.js";
|
||||
import { handlers } from "./portable.js";
|
||||
export const registry = createRegistry(handlers);
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { Modules } from "./gen/client.js";
|
||||
export const CanvasCard: Modules["CanvasCard"] = ({ input }) => <p>{input.body.root.name}</p>;
|
||||
@@ -0,0 +1,80 @@
|
||||
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 }: Contexts["canPresent"]) => {
|
||||
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,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import { createRegistry } from "./gen/qx.js";
|
||||
import { handlers } from "./portable.js";
|
||||
// The workspace entry protocol owns stable birth identity and idempotency.
|
||||
export const registry = createRegistry({
|
||||
...handlers,
|
||||
createRoot: ({ ports }) => ports.canvas.create({ name: "Workspace" }, { key: "canvas" }),
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"target": "ES2024",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"jsx": "react-jsx",
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx"]
|
||||
}
|
||||
Reference in New Issue
Block a user