Generalize live field bindings and use them for Studio canvas gestures

This commit is contained in:
Timothy J. Aveni
2026-09-28 11:12:11 -07:00
parent 696023b4ba
commit 0ace71eae6
13 changed files with 1766 additions and 1586 deletions
+45
View File
@@ -615,6 +615,23 @@ const collectIdentityIndexes = (
);
}
}
if (member.kind === "value" && member.nativeField) {
const names = member.operations.map((o) => o.displayName);
if (
!isStorableType(member.valueType) ||
!names.includes("get") ||
names.some((n) => !["get", "set", "edit"].includes(n)) ||
(names.includes("set") && names.includes("edit"))
)
issue(
issues,
"invalid-state-binding",
memberPath,
"Fields require a storable value, a native getter and at most one setter or editor",
);
if (member.queryRead && member.queryRead.execution !== "native")
issue(issues, "invalid-query-contract", memberPath, "Fields cannot have package-backed query reads");
}
requireText(issues, member.id, `${memberPath}.id`, "Member ID");
requireText(issues, member.displayName, `${memberPath}.displayName`, "Member name");
if (memberIds.has(member.id)) {
@@ -1758,6 +1775,34 @@ const validateConformances = (
}
} else binding = entry.binding;
const member = operationEntry.member;
if (member.kind === "value" && member.nativeField) {
const primitive = { get: "read", set: "write", edit: "edit" }[operation.displayName];
const getter = member.operations.find((o) => o.displayName === "get");
let read: Binding | undefined;
try {
if (getter)
read = resolveForwardedBinding(
workspace,
conformance.atomId,
conformance.interfaceRevisionId,
getter.id,
).binding;
} catch {}
if (
binding.kind !== "state" ||
binding.primitive !== primitive ||
read?.kind !== "state" ||
read.primitive !== "read" ||
read.slotId !== binding.slotId
)
issue(
issues,
"invalid-state-binding",
bindingPath,
"Field operations must resolve to the same native state slot",
);
}
if (
member.kind === "value" &&
operation.displayName === "edit" &&