/** * EntityFields — generic field renderer for the entity editor. * * Renders the fields defined in the core `ENTITY_FIELDS` registry for the * entity's kind. Field values live at the top level for characters/notes and * inside the `fields` record for world items; `getFieldValue`/`setFieldValue` * abstract that away so the renderer is kind-agnostic. */ import React from "react"; import type { Entity, FieldDef } from "@pubscript/core"; import { ENTITY_FIELDS } from "@pubscript/core"; /** A short display label for an entity, regardless of kind. */ export function entityLabel(e: Entity): string { if ("body" in e) { return e.body.trim().slice(0, 40) || "(untitled note)"; } return e.name; } /** Read a field value from an entity, regardless of where it is stored. */ export function getFieldValue(e: Entity, key: string): string | string[] { if ("fields" in e) { if (key === "name") return e.name; const v = e.fields[key]; if (Array.isArray(v)) return v; return typeof v === "string" ? v : ""; } const v = (e as unknown as Record)[key]; if (Array.isArray(v)) return v; return typeof v === "string" ? v : ""; } /** Return a copy of `e` with `key` set to `value`. */ export function setFieldValue(e: Entity, key: string, value: string | string[]): Entity { if ("fields" in e) { if (key === "name" && typeof value === "string") { return { ...e, name: value }; } return { ...e, fields: { ...e.fields, [key]: value } }; } return { ...e, [key]: value }; } /** The field definitions for an entity's kind. */ export function fieldsFor(e: Entity): FieldDef[] { const kind = "fields" in e ? e.kind : "body" in e ? "note" : "character"; return ENTITY_FIELDS[kind]?.fields ?? []; } interface EntityFieldsProps { entity: Entity; onChange: (patch: Partial) => void; /** All entities in the book, used to resolve `link` field references. */ entities?: Entity[]; } function renderFieldControl( field: FieldDef, value: string | string[], onChange: (v: string | string[]) => void, currentEntityId: string, entities?: Entity[], ) { switch (field.type) { case "textarea": return (