@thebes/cadmea 1.1.0 → 1.1.1
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/dist/index/index.js +1 -1
- package/dist/index/index.js.map +1 -1
- package/dist/index/server.js +1 -1
- package/dist/index/server.js.map +1 -1
- package/dist/tanstack-start/index.js +1 -1
- package/dist/tanstack-start/index.js.map +1 -1
- package/dist/tanstack-start/server.js +1 -1
- package/dist/tanstack-start/server.js.map +1 -1
- package/package.json +1 -1
package/dist/index/index.js
CHANGED
|
@@ -157,7 +157,7 @@ function CollectionEdit(props) {
|
|
|
157
157
|
})();
|
|
158
158
|
}
|
|
159
159
|
function renderInput(key, field, value, setField, ctx) {
|
|
160
|
-
const Widget = ctx.fieldWidgets?.[key];
|
|
160
|
+
const Widget = ctx.fieldWidgets?.[key] ?? ctx.fieldWidgets?.[key.slice(key.lastIndexOf(".") + 1)];
|
|
161
161
|
if (Widget) return createComponent(Widget, {
|
|
162
162
|
fieldKey: key,
|
|
163
163
|
value,
|
package/dist/index/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["CollectionConfig","FieldConfig","createEffect","createSignal","For","JSX","lazy","Show","Suspense","CollectionCapabilities","FieldWidgetProps","FieldWidget","props","Element","RichTextEditor","then","mod","default","editableFields","config","Object","entries","fields","filter","key","RelationshipOption","id","label","DraftActions","onSaveDraft","values","Record","Promise","onPublish","onPreview","saving","publishing","previewing","canPublish","canPreview","saveDraftLabel","publishLabel","previewLabel","CollectionEditProps","initialValues","onSubmit","submitLabel","error","onUploadFile","file","File","url","relationshipOptions","Partial","onDirtyChange","dirty","fieldWidgets","draftActions","capabilities","RenderContext","CollectionEdit","initialSnapshot","JSON","stringify","setValues","setField","value","prev","editablePayload","fromEntries","type","handleSubmit","event","SubmitEvent","preventDefault","ctx","versioned","versions","drafts","_el$","_tmpl$6","_el$3","firstChild","addEventListener","_$insert","_$createComponent","when","children","_el$2","_tmpl$","each","field","_el$0","_tmpl$8","_el$1","_$setAttribute","required","_tmpl$7","renderInput","fallback","canUpdate","_el$11","_tmpl$9","_tmpl$2","_$effect","disabled","_el$4","_tmpl$3","$$click","_el$6","_tmpl$4","_el$8","_tmpl$5","Widget","fieldKey","setValue","v","_el$13","_tmpl$0","$$input","e","currentTarget","_el$14","_tmpl$1","options","option","_el$15","_tmpl$10","_el$16","_tmpl$11","valueAsNumber","_el$17","_tmpl$12","formatDateValue","_el$18","_tmpl$13","checked","renderUploadInput","renderRelationshipInput","renderArrayInput","content","onChange","doc","uploading","setUploading","uploadError","setUploadError","handleFileChange","Event","HTMLInputElement","files","undefined","err","Error","message","_el$20","_tmpl$16","_el$22","_el$21","_tmpl$14","_el$24","_tmpl$15","_p$","_v$","_v$2","t","hasMany","relationTo","_el$25","_tmpl$17","_el$26","Number","_el$27","String","items","Array","isArray","updateItem","index","itemKey","itemValue","next","slice","addItem","removeItem","_","i","fieldsForItem","item","base","discriminator","variantValue","variantFields","variants","_el$28","_tmpl$18","_el$29","_el$30","_el$31","_tmpl$19","_el$32","itemField","inputId","_el$33","_el$34","date","Date","isNaN","getTime","toLocaleString","_$delegateEvents","CollectionConfig","FieldConfig","createSignal","For","Show","listableFields","config","excluded","Set","Object","entries","fields","filter","key","field","has","type","formatCellValue","value","undefined","Date","toLocaleDateString","String","rowId","row","Record","id","CollectionListProps","rows","onRowClick","page","pageSize","totalCount","onPageChange","sortField","sortDirection","onSortChange","direction","selectable","selectedIds","ReadonlySet","onSelectionChange","CollectionList","props","columns","selectMode","setSelectMode","toggleSelected","next","delete","add","handleRowActivate","_el$","_tmpl$7","_el$2","firstChild","_$insert","_$createComponent","when","children","_el$3","_tmpl$","$$click","v","_el$4","_tmpl$2","_el$5","_el$6","nextSibling","addEventListener","e","currentTarget","each","_el$16","_tmpl$8","_$effect","length","fallback","_el$17","_tmpl$9","_el$18","_el$20","_el$19","slug","_el$7","_tmpl$4","_el$8","_el$9","_el$1","_tmpl$3","_el$21","_el$22","_tmpl$1","_el$23","_tmpl$0","_el$24","stopPropagation","checked","_el$25","_tmpl$10","_$className","_el$10","_tmpl$5","_el$26","_tmpl$12","_el$27","_el$29","$$keydown","preventDefault","_el$28","_tmpl$11","_el$30","_tmpl$13","_el$31","_el$32","_$memo","_el$11","_tmpl$6","_el$12","_el$13","_el$14","_el$15","_p$","_v$","_v$2","disabled","t","_$delegateEvents","ImageCrop","ImageHotspot","createMemo","createSignal","Show","ImageWithHotspot","url","hotspot","crop","round2","n","Math","round","clamp01","min","max","parseImageHotspotValue","value","trimmed","trim","startsWith","JSON","parse","serializeImageHotspotValue","stringify","FieldWidgetProps","fieldKey","setValue","onUploadFile","file","File","Promise","ImageHotspotField","props","parsed","uploading","setUploading","error","setError","patch","next","Partial","current","handleFile","e","Event","currentTarget","HTMLInputElement","files","undefined","err","Error","message","handleImageClick","MouseEvent","HTMLImageElement","rect","getBoundingClientRect","x","clientX","left","width","y","clientY","top","height","right","bottom","setCrop","edge","raw","Number","_el$","_tmpl$3","_el$2","firstChild","addEventListener","_$insert","_$createComponent","when","children","_tmpl$","_el$4","_tmpl$2","_el$5","_tmpl$4","_el$6","_el$7","nextSibling","_el$8","_el$9","_el$0","_el$1","_el$10","$$click","hs","_el$11","_tmpl$5","_$effect","_p$","_v$3","_v$4","_$setStyleProperty","t","const","map","_el$12","_tmpl$6","_el$13","_el$14","$$input","_$setAttribute","_v$","_v$2","disabled","_$delegateEvents","createEffect","createSignal","For","JSX","onCleanup","Show","SearchPaletteResult","collection","id","label","SearchPaletteProps","onSearch","query","Promise","onSelect","result","DEBOUNCE_MS","capitalize","value","length","toUpperCase","slice","SearchPalette","props","Element","open","setOpen","setQuery","results","setResults","activeIndex","setActiveIndex","inputRef","HTMLInputElement","triggeredBy","HTMLElement","debounceTimer","ReturnType","setTimeout","latestQueryToken","close","focus","runSearch","token","trim","then","found","onInput","clearTimeout","selectResult","onGlobalKeyDown","event","KeyboardEvent","metaKey","ctrlKey","key","toLowerCase","preventDefault","document","activeElement","addEventListener","removeEventListener","onDialogKeyDown","i","Math","min","max","_$createComponent","when","children","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","_el$5","nextSibling","$$click","$$keydown","stopPropagation","$$input","currentTarget","_ref$","_$use","_$insert","fallback","_el$7","_tmpl$3","_el$6","_tmpl$","each","index","_el$8","_tmpl$4","_el$9","_el$0","_el$1","_$effect","classList","toggle","_$delegateEvents","EditRef","VISUAL_EDIT_MESSAGE","VisualEditingMessage","onCleanup","onMount","VisualEditingPaneProps","src","onEdit","ref","allowedOrigin","class","title","originOf","url","URL","origin","undefined","VisualEditingPane","props","expected","handler","event","MessageEvent","data","Partial","type","window","addEventListener","removeEventListener","_el$","_tmpl$","_$effect","_p$","_v$","_v$2","_v$3","e","_$setAttribute","t","a","_$className"],"sources":["../../src/CollectionEdit.tsx","../../src/CollectionList.tsx","../../src/ImageHotspotField.tsx","../../src/SearchPalette.tsx","../../src/VisualEditingPane.tsx"],"sourcesContent":["import type { CollectionConfig, FieldConfig } from \"@thebes/cadmus/cms\";\nimport {\n createEffect,\n createSignal,\n For,\n type JSX,\n lazy,\n Show,\n Suspense,\n} from \"solid-js\";\nimport type { CollectionCapabilities } from \"./capabilities.js\";\nimport type { FieldWidgetProps } from \"./ImageHotspotField.js\";\n\n/** A custom per-field editor, registered via `fieldWidgets`. */\nexport type FieldWidget = (props: FieldWidgetProps) => JSX.Element;\n\n// Dynamic import, not a static one — @tiptap/core + @tiptap/starter-kit\n// are a large dependency (pushed a consuming route's bundle from ~9KB to\n// ~800KB when statically imported, even for collections with zero\n// richText fields). Lazy-loading means only forms that actually render a\n// richText field pull this chunk in at runtime.\nconst RichTextEditor = lazy(() =>\n import(\"./RichTextEditor.js\").then((mod) => ({\n default: mod.RichTextEditor,\n })),\n);\n\n// Fields the generic form can actually render today. `id` is never\n// user-editable. `date` fields (e.g. createdAt) are server-defaulted and\n// shown read-only rather than editable in this step.\nfunction editableFields(config: CollectionConfig): [string, FieldConfig][] {\n return Object.entries(config.fields).filter(([key]) => key !== \"id\");\n}\n\nexport interface RelationshipOption {\n id: number;\n label: string;\n}\n\n/**\n * Replaces the generic \"Save\" button with \"Save draft\"/\"Publish\" when the\n * collection has `versions: { drafts: true }` — a separate privilege from\n * a plain update, matching `access.publish` in `@thebes/cadmus/cms`.\n * `onPublish` takes no values: publishing acts on whatever was last saved\n * as a draft (the consuming route tracks which version that is), not on\n * the live form state.\n */\nexport interface DraftActions {\n onSaveDraft: (values: Record<string, unknown>) => void | Promise<void>;\n onPublish?: () => void | Promise<void>;\n /**\n * Opens a live preview of the last saved draft (issue #28) — like\n * `onPublish`, acts on whatever was last saved as a draft, not the live\n * form state. Omit to not render the Preview button at all.\n */\n onPreview?: () => void | Promise<void>;\n saving?: boolean;\n publishing?: boolean;\n previewing?: boolean;\n /** Disables Publish — e.g. until a draft has been saved at least once. */\n canPublish?: boolean;\n /** Disables Preview — same gating as canPublish, a draft must exist first. */\n canPreview?: boolean;\n saveDraftLabel?: string;\n publishLabel?: string;\n previewLabel?: string;\n}\n\nexport interface CollectionEditProps {\n config: CollectionConfig;\n initialValues?: Record<string, unknown>;\n onSubmit: (values: Record<string, unknown>) => void | Promise<void>;\n submitLabel?: string;\n error?: string;\n /** Disables the Save button and shows a spinner in its place. */\n saving?: boolean;\n /**\n * Resolves an `upload` field's selected file to a stored URL. Required\n * if the collection has any `upload` fields — `CollectionEdit` never\n * talks to storage directly (stays agnostic of R2/cadmus/storage), so\n * the consuming route wires this to a server function that calls an\n * `ImageService`'s `upload()`.\n */\n onUploadFile?: (file: File) => Promise<{ url: string }>;\n /**\n * Options for `relationship` fields (hasMany:false only — see\n * RelationshipFieldConfig's `hasMany` caveat), keyed by the field's\n * `relationTo` collection slug. `CollectionEdit` can't query another\n * collection itself, so the consuming route fetches the related rows\n * and passes them in.\n */\n relationshipOptions?: Partial<Record<string, RelationshipOption[]>>;\n /**\n * Fired whenever the dirty (unsaved-changes) state changes — wire this\n * to a router-level navigation guard (e.g. `useBlocker` in the\n * consuming route) since `CollectionEdit` has no router access itself.\n */\n onDirtyChange?: (dirty: boolean) => void;\n /**\n * Per-field custom editor widgets (issue #17), keyed by field name. When a\n * field has a widget here, it's rendered instead of the generic input for\n * that field's type — e.g. `{ heroImage: ImageHotspotField }`. The widget\n * receives the field value, a setter, and `onUploadFile`.\n */\n fieldWidgets?: Record<string, FieldWidget>;\n /** Only rendered when `config.versions?.drafts` is also true. */\n draftActions?: DraftActions;\n /**\n * Hides the Save button when `canUpdate` is `false` — see issue #26's\n * RBAC-aware admin UI. Undefined (the default — most collections don't\n * wire this up) reads as \"allowed\", same as `@thebes/cadmus/cms`'s own\n * \"no access fn = allowed\" default.\n */\n capabilities?: CollectionCapabilities;\n}\n\ninterface RenderContext {\n onUploadFile?: (file: File) => Promise<{ url: string }>;\n relationshipOptions?: Partial<Record<string, RelationshipOption[]>>;\n fieldWidgets?: Record<string, FieldWidget>;\n}\n\nexport function CollectionEdit(props: CollectionEditProps) {\n const initialSnapshot = JSON.stringify(props.initialValues ?? {});\n const [values, setValues] = createSignal<Record<string, unknown>>(\n props.initialValues ?? {},\n );\n\n // Reported via `onDirtyChange` rather than tracked by the consuming\n // route itself — only this component sees every field edit as it\n // happens. A plain JSON.stringify comparison is enough: form values are\n // already plain JSON-shaped data (TipTap docs, array-field items), so\n // there's no Date/Map/Set edge case to special-case here.\n createEffect(() => {\n props.onDirtyChange?.(JSON.stringify(values()) !== initialSnapshot);\n });\n\n function setField(key: string, value: unknown) {\n setValues((prev) => ({ ...prev, [key]: value }));\n }\n\n // date fields are read-only — never include them in a submitted/draft payload\n function editablePayload(): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(values()).filter(\n ([key]) => props.config.fields[key]?.type !== \"date\",\n ),\n );\n }\n\n function handleSubmit(event: SubmitEvent) {\n event.preventDefault();\n void props.onSubmit(editablePayload());\n }\n\n const ctx: RenderContext = {\n onUploadFile: props.onUploadFile,\n relationshipOptions: props.relationshipOptions,\n fieldWidgets: props.fieldWidgets,\n };\n\n const versioned = () => props.config.versions?.drafts && props.draftActions;\n\n return (\n <form class=\"flex flex-col gap-4\" onSubmit={handleSubmit}>\n <Show when={props.error}>\n {/* role=\"alert\" so assistive tech announces submit failures the\n moment they appear, not only if the user happens to navigate to\n them. */}\n <p class=\"text-sm text-error\" role=\"alert\">\n {props.error}\n </p>\n </Show>\n <For each={editableFields(props.config)}>\n {([key, field]) => (\n <div class=\"form-control\">\n {/* The \" *\" stays inside the label's accessible name (it reads\n as \"required\" alongside each input's `required` attribute);\n the span only colors it, it does not change the text. */}\n <label class=\"label\" for={key}>\n {key}\n <Show when={field.required}>\n <span class=\"text-error\">{\" *\"}</span>\n </Show>\n </label>\n {renderInput(key, field, values()[key], setField, ctx)}\n </div>\n )}\n </For>\n {/* Bottom-anchored, full-width action bar — not a top toolbar, per\n issue #25's mobile-first note. */}\n <div class=\"bg-base-100 sticky bottom-0 flex gap-2 border-t py-3\">\n <Show\n when={versioned()}\n fallback={\n <Show when={props.capabilities?.canUpdate !== false}>\n <button\n type=\"submit\"\n class=\"btn btn-primary flex-1\"\n disabled={props.saving}\n >\n <Show\n when={props.saving}\n fallback={props.submitLabel ?? \"Save\"}\n >\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n </button>\n </Show>\n }\n >\n <button\n type=\"button\"\n class=\"btn flex-1\"\n disabled={props.draftActions?.saving}\n onClick={() =>\n void props.draftActions?.onSaveDraft(editablePayload())\n }\n >\n <Show\n when={props.draftActions?.saving}\n fallback={props.draftActions?.saveDraftLabel ?? \"Save draft\"}\n >\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n </button>\n <button\n type=\"button\"\n class=\"btn btn-primary flex-1\"\n disabled={\n !props.draftActions?.canPublish || props.draftActions?.publishing\n }\n onClick={() => void props.draftActions?.onPublish?.()}\n >\n <Show\n when={props.draftActions?.publishing}\n fallback={props.draftActions?.publishLabel ?? \"Publish\"}\n >\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n </button>\n <Show when={props.draftActions?.onPreview}>\n <button\n type=\"button\"\n class=\"btn btn-outline flex-1\"\n disabled={\n !props.draftActions?.canPreview ||\n props.draftActions?.previewing\n }\n onClick={() => void props.draftActions?.onPreview?.()}\n >\n <Show\n when={props.draftActions?.previewing}\n fallback={props.draftActions?.previewLabel ?? \"Preview\"}\n >\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n </button>\n </Show>\n </Show>\n </div>\n </form>\n );\n}\n\nfunction renderInput(\n key: string,\n field: FieldConfig,\n value: unknown,\n setField: (key: string, value: unknown) => void,\n ctx: RenderContext,\n) {\n // A registered custom widget wins over the generic type-based input (#17).\n const Widget = ctx.fieldWidgets?.[key];\n if (Widget) {\n return (\n <Widget\n fieldKey={key}\n value={value}\n setValue={(v) => setField(key, v)}\n onUploadFile={ctx.onUploadFile}\n />\n );\n }\n switch (field.type) {\n case \"text\":\n return (\n <input\n id={key}\n class=\"input\"\n type=\"text\"\n value={(value as string) ?? \"\"}\n required={field.required}\n onInput={(e) => setField(key, e.currentTarget.value)}\n />\n );\n case \"select\":\n return (\n <select\n id={key}\n class=\"select\"\n value={(value as string) ?? \"\"}\n required={field.required}\n onChange={(e) => setField(key, e.currentTarget.value)}\n >\n <For each={field.options}>\n {(option) => <option value={option}>{option}</option>}\n </For>\n </select>\n );\n case \"number\":\n return (\n <input\n id={key}\n class=\"input\"\n type=\"number\"\n value={(value as number) ?? \"\"}\n required={field.required}\n onInput={(e) => setField(key, e.currentTarget.valueAsNumber)}\n />\n );\n case \"date\":\n return (\n <input\n id={key}\n class=\"input\"\n type=\"text\"\n readOnly\n value={formatDateValue(value)}\n />\n );\n case \"checkbox\":\n return (\n <input\n id={key}\n class=\"checkbox\"\n type=\"checkbox\"\n checked={(value as boolean) ?? false}\n onChange={(e) => setField(key, e.currentTarget.checked)}\n />\n );\n case \"upload\":\n return renderUploadInput(key, field, value, setField, ctx);\n case \"relationship\":\n return renderRelationshipInput(key, field, value, setField, ctx);\n case \"array\":\n return renderArrayInput(key, field, value, setField, ctx);\n case \"richText\":\n return (\n <Suspense\n fallback={<span class=\"loading loading-spinner loading-sm\" />}\n >\n <RichTextEditor\n id={key}\n content={value as object | undefined}\n onChange={(doc) => setField(key, doc)}\n />\n </Suspense>\n );\n default:\n return null;\n }\n}\n\nfunction renderUploadInput(\n key: string,\n field: FieldConfig & { type: \"upload\" },\n value: unknown,\n setField: (key: string, value: unknown) => void,\n ctx: RenderContext,\n) {\n const [uploading, setUploading] = createSignal(false);\n const [uploadError, setUploadError] = createSignal<string>();\n\n async function handleFileChange(\n e: Event & { currentTarget: HTMLInputElement },\n ) {\n const file = e.currentTarget.files?.[0];\n if (!file) return;\n if (!ctx.onUploadFile) {\n setUploadError(\"No upload handler configured for this form.\");\n return;\n }\n setUploading(true);\n setUploadError(undefined);\n try {\n const { url } = await ctx.onUploadFile(file);\n setField(key, url);\n } catch (err) {\n setUploadError(err instanceof Error ? err.message : \"Upload failed\");\n } finally {\n setUploading(false);\n }\n }\n\n return (\n <div class=\"flex flex-col gap-2\">\n <Show when={value}>\n <p class=\"text-sm opacity-70 break-all\">{value as string}</p>\n </Show>\n <input\n id={key}\n class=\"file-input\"\n type=\"file\"\n required={field.required && !value}\n disabled={uploading()}\n onChange={handleFileChange}\n />\n <Show when={uploading()}>\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n <Show when={uploadError()}>\n <p class=\"text-sm text-error\">{uploadError()}</p>\n </Show>\n </div>\n );\n}\n\nfunction renderRelationshipInput(\n key: string,\n field: FieldConfig & { type: \"relationship\" },\n value: unknown,\n setField: (key: string, value: unknown) => void,\n ctx: RenderContext,\n) {\n // hasMany:true relationships are join-table-backed (no plain FK column\n // to bind a single <select> to) — not supported by this generic form\n // yet. See RelationshipFieldConfig's `hasMany` doc.\n if (field.hasMany) return null;\n\n const options = ctx.relationshipOptions?.[field.relationTo] ?? [];\n\n return (\n <select\n id={key}\n class=\"select\"\n value={value != null ? String(value) : \"\"}\n required={field.required}\n onChange={(e) =>\n setField(\n key,\n e.currentTarget.value === \"\" ? null : Number(e.currentTarget.value),\n )\n }\n >\n <option value=\"\">—</option>\n <For each={options}>\n {(option) => <option value={option.id}>{option.label}</option>}\n </For>\n </select>\n );\n}\n\nfunction renderArrayInput(\n key: string,\n field: FieldConfig & { type: \"array\" },\n value: unknown,\n setField: (key: string, value: unknown) => void,\n ctx: RenderContext,\n) {\n const items = () =>\n Array.isArray(value) ? (value as Record<string, unknown>[]) : [];\n\n function updateItem(index: number, itemKey: string, itemValue: unknown) {\n const next = items().slice();\n next[index] = { ...next[index], [itemKey]: itemValue };\n setField(key, next);\n }\n\n function addItem() {\n setField(key, [...items(), {}]);\n }\n\n function removeItem(index: number) {\n setField(\n key,\n items().filter((_, i) => i !== index),\n );\n }\n\n function fieldsForItem(\n item: Record<string, unknown>,\n ): [string, FieldConfig][] {\n const base = Object.entries(field.fields);\n const discriminator = field.discriminator;\n if (!discriminator) return base;\n\n const variantValue = item[discriminator.key];\n const variantFields =\n typeof variantValue === \"string\"\n ? discriminator.variants[variantValue]\n : undefined;\n return variantFields ? [...base, ...Object.entries(variantFields)] : base;\n }\n\n return (\n <div class=\"flex flex-col gap-3\">\n <For each={items()}>\n {(item, index) => (\n <div class=\"card bg-base-200 flex flex-col gap-2 p-3\">\n <For each={fieldsForItem(item)}>\n {([itemKey, itemField]) => {\n const inputId = `${key}.${index()}.${itemKey}`;\n return (\n <div class=\"form-control\">\n <label class=\"label\" for={inputId}>\n {itemKey}\n <Show when={itemField.required}>\n <span class=\"text-error\">{\" *\"}</span>\n </Show>\n </label>\n {renderInput(\n inputId,\n itemField,\n item[itemKey],\n (_, v) => updateItem(index(), itemKey, v),\n ctx,\n )}\n </div>\n );\n }}\n </For>\n <button\n type=\"button\"\n class=\"btn btn-error btn-outline btn-sm self-start\"\n onClick={() => removeItem(index())}\n >\n Remove\n </button>\n </div>\n )}\n </For>\n <button\n type=\"button\"\n class=\"btn btn-outline btn-sm self-start\"\n onClick={addItem}\n >\n Add {key}\n </button>\n </div>\n );\n}\n\nfunction formatDateValue(value: unknown): string {\n if (!value) return \"—\";\n const date = value instanceof Date ? value : new Date(value as string);\n return Number.isNaN(date.getTime()) ? \"—\" : date.toLocaleString();\n}\n","import type { CollectionConfig, FieldConfig } from \"@thebes/cadmus/cms\";\nimport { createSignal, For, Show } from \"solid-js\";\n\n// Field types that can be rendered as a plain table cell today.\n// `id` is intentionally excluded — it's never a useful list column.\n// `richText`/`array` are structured content, not a sensible table cell;\n// `relationship` has no resolved label available here (CollectionList\n// only receives raw row data, not the related collection's rows) so it'd\n// show a bare numeric id — excluded until that's worth solving.\nfunction listableFields(config: CollectionConfig): [string, FieldConfig][] {\n const excluded = new Set([\"richText\", \"array\", \"relationship\"]);\n return Object.entries(config.fields).filter(\n ([key, field]) => key !== \"id\" && !excluded.has(field.type),\n );\n}\n\nfunction formatCellValue(value: unknown): string {\n if (value === null || value === undefined) return \"—\";\n if (value instanceof Date) return value.toLocaleDateString();\n return String(value);\n}\n\nfunction rowId(row: Record<string, unknown>): number | undefined {\n return typeof row.id === \"number\" ? row.id : undefined;\n}\n\nexport interface CollectionListProps {\n config: CollectionConfig;\n rows: Record<string, unknown>[];\n onRowClick?: (row: Record<string, unknown>) => void;\n\n /**\n * 1-based current page. Omit (along with `pageSize`) to render without\n * the pagination bar entirely — list views with no `find()` paging\n * wired up yet still render correctly.\n */\n page?: number;\n pageSize?: number;\n /** Total row count across all pages — see `LocalApi.count()`. Enables\n * disabling \"Next\" exactly at the last page; omit to fall back to a\n * `rows.length < pageSize` heuristic. */\n totalCount?: number;\n onPageChange?: (page: number) => void;\n\n /** Field key currently sorted on. Omit to hide the sort control. */\n sortField?: string;\n sortDirection?: \"asc\" | \"desc\";\n onSortChange?: (field: string, direction: \"asc\" | \"desc\") => void;\n\n /** Shows the \"Select\" bulk-select mode toggle. */\n selectable?: boolean;\n selectedIds?: ReadonlySet<number>;\n onSelectionChange?: (selectedIds: Set<number>) => void;\n}\n\nexport function CollectionList(props: CollectionListProps) {\n const columns = () => listableFields(props.config);\n const [selectMode, setSelectMode] = createSignal(false);\n\n function toggleSelected(id: number) {\n const next = new Set(props.selectedIds ?? []);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n props.onSelectionChange?.(next);\n }\n\n function handleRowActivate(row: Record<string, unknown>) {\n if (selectMode()) {\n const id = rowId(row);\n if (id !== undefined) toggleSelected(id);\n return;\n }\n props.onRowClick?.(row);\n }\n\n return (\n <div class=\"flex flex-col gap-3\">\n <div class=\"flex flex-wrap items-center justify-between gap-2\">\n <Show when={props.selectable}>\n <button\n type=\"button\"\n class=\"btn btn-outline btn-sm\"\n onClick={() => setSelectMode((v) => !v)}\n >\n {selectMode() ? \"Done\" : \"Select\"}\n </button>\n </Show>\n {/* Dropdown picker, not clickable column headers — sort works the\n same on touch and desktop, see issue #25's mobile-first note. */}\n <Show when={props.onSortChange}>\n <div class=\"join\">\n <select\n aria-label=\"Sort by\"\n class=\"select select-sm join-item\"\n value={props.sortField ?? \"\"}\n onChange={(e) =>\n props.onSortChange?.(\n e.currentTarget.value,\n props.sortDirection ?? \"asc\",\n )\n }\n >\n <For each={columns()}>\n {([key]) => <option value={key}>{key}</option>}\n </For>\n </select>\n <select\n aria-label=\"Sort direction\"\n class=\"select select-sm join-item\"\n value={props.sortDirection ?? \"asc\"}\n onChange={(e) =>\n props.onSortChange?.(\n props.sortField ?? columns()[0]?.[0] ?? \"\",\n e.currentTarget.value as \"asc\" | \"desc\",\n )\n }\n >\n <option value=\"asc\">Ascending</option>\n <option value=\"desc\">Descending</option>\n </select>\n </div>\n </Show>\n </div>\n\n <Show\n when={props.rows.length > 0}\n fallback={<p class=\"text-sm opacity-70\">No {props.config.slug} yet.</p>}\n >\n {/* Table on desktop — hidden below md per the mobile-first card\n layout below, not the other way around. */}\n <table class=\"table hidden md:table\">\n <thead>\n <tr>\n <Show when={selectMode()}>\n <th />\n </Show>\n <For each={columns()}>{([key]) => <th>{key}</th>}</For>\n </tr>\n </thead>\n <tbody>\n <For each={props.rows}>\n {(row) => (\n <tr\n class={\n props.onRowClick || selectMode()\n ? \"cursor-pointer hover\"\n : undefined\n }\n onClick={() => handleRowActivate(row)}\n >\n <Show when={selectMode()}>\n <td>\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-sm\"\n onClick={(e) => e.stopPropagation()}\n checked={\n rowId(row) !== undefined &&\n (props.selectedIds?.has(rowId(row) as number) ??\n false)\n }\n onChange={() => {\n const id = rowId(row);\n if (id !== undefined) toggleSelected(id);\n }}\n />\n </td>\n </Show>\n <For each={columns()}>\n {([key]) => <td>{formatCellValue(row[key])}</td>}\n </For>\n </tr>\n )}\n </For>\n </tbody>\n </table>\n\n {/* Stacked card list on mobile/tablet — tap-to-select via an\n always-visible checkbox in select mode, never hover-revealed. */}\n <div class=\"flex flex-col gap-2 md:hidden\">\n <For each={props.rows}>\n {(row) => (\n // biome-ignore lint/a11y/useSemanticElements: a native <button> can't contain interactive content (the select-mode checkbox below); role=\"button\" + tabIndex/onKeyDown is the standard fallback.\n <div\n class=\"card bg-base-200 cursor-pointer p-3\"\n role=\"button\"\n tabIndex={0}\n onClick={() => handleRowActivate(row)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleRowActivate(row);\n }\n }}\n >\n <div class=\"flex items-start gap-3\">\n <Show when={selectMode()}>\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-sm mt-1\"\n onClick={(e) => e.stopPropagation()}\n checked={\n rowId(row) !== undefined &&\n (props.selectedIds?.has(rowId(row) as number) ?? false)\n }\n onChange={() => {\n const id = rowId(row);\n if (id !== undefined) toggleSelected(id);\n }}\n />\n </Show>\n <div class=\"flex flex-1 flex-col gap-1\">\n <For each={columns()}>\n {([key]) => (\n <div class=\"flex justify-between gap-2 text-sm\">\n <span class=\"opacity-60\">{key}</span>\n <span class=\"text-right\">\n {formatCellValue(row[key])}\n </span>\n </div>\n )}\n </For>\n </div>\n </div>\n </div>\n )}\n </For>\n </div>\n </Show>\n\n {/* Bottom-anchored prev/next bar — no page numbers, per issue #25's\n mobile-first note. Renders only when pagination is wired up. */}\n <Show when={props.page !== undefined && props.pageSize !== undefined}>\n <div class=\"bg-base-100 sticky bottom-0 flex items-center justify-between gap-2 border-t py-2\">\n <button\n type=\"button\"\n class=\"btn btn-sm\"\n disabled={(props.page ?? 1) <= 1}\n onClick={() => props.onPageChange?.((props.page ?? 1) - 1)}\n >\n Prev\n </button>\n <span class=\"text-sm opacity-70\">Page {props.page}</span>\n <button\n type=\"button\"\n class=\"btn btn-sm\"\n disabled={\n props.totalCount !== undefined\n ? (props.page ?? 1) * (props.pageSize ?? 0) >= props.totalCount\n : props.rows.length < (props.pageSize ?? 0)\n }\n onClick={() => props.onPageChange?.((props.page ?? 1) + 1)}\n >\n Next\n </button>\n </div>\n </Show>\n </div>\n );\n}\n","// Copyright (c) 2026 BowenLabs. All rights reserved.\n// Cadmea is MIT licensed. See LICENSE in the repo root.\n\nimport type { ImageCrop, ImageHotspot } from \"@thebes/cadmus/storage\";\nimport { createMemo, createSignal, Show } from \"solid-js\";\n\n/**\n * Image hotspot/crop editor widget (issue #17). A custom field widget for\n * `upload` image fields: upload an image, then click it to set the focal\n * point (hotspot) and optionally enter a crop region. Stores the value as a\n * JSON string `{ url, hotspot?, crop? }` in the same column (back-compatible\n * — a plain URL string still parses). Pair with `ImageService.render`'s\n * `hotspot`/`crop` args on the read side (see @thebes/cadmus-cloudflare-images).\n *\n * Register it via `createCollectionEditPage`/`CollectionEdit`'s `fieldWidgets`\n * option, keyed by the field name.\n */\n\nexport interface ImageWithHotspot {\n url: string;\n hotspot?: ImageHotspot;\n crop?: ImageCrop;\n}\n\nconst round2 = (n: number): number => Math.round(n * 100) / 100;\nconst clamp01 = (n: number): number => Math.min(1, Math.max(0, n));\n\n/**\n * Parse an upload-field value into `{ url, hotspot?, crop? }`. Accepts the\n * JSON object this widget writes, an already-parsed object, or a bare URL\n * string (legacy / non-hotspot uploads). Returns null for empty values.\n */\nexport function parseImageHotspotValue(\n value: unknown,\n): ImageWithHotspot | null {\n if (!value) return null;\n if (typeof value === \"object\") return value as ImageWithHotspot;\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (trimmed.startsWith(\"{\")) {\n try {\n return JSON.parse(trimmed) as ImageWithHotspot;\n } catch {\n // fall through to treating it as a plain URL\n }\n }\n return trimmed ? { url: trimmed } : null;\n }\n return null;\n}\n\n/** Serialize an {@link ImageWithHotspot} for storage in an upload field. */\nexport function serializeImageHotspotValue(value: ImageWithHotspot): string {\n return JSON.stringify(value);\n}\n\n/** Props every `fieldWidgets` widget receives from CollectionEdit. */\nexport interface FieldWidgetProps {\n fieldKey: string;\n value: unknown;\n setValue: (value: unknown) => void;\n onUploadFile?: (file: File) => Promise<{ url: string }>;\n}\n\nexport function ImageHotspotField(props: FieldWidgetProps) {\n const parsed = createMemo(() => parseImageHotspotValue(props.value));\n const [uploading, setUploading] = createSignal(false);\n const [error, setError] = createSignal<string>();\n\n const patch = (next: Partial<ImageWithHotspot>) => {\n const current = parsed() ?? { url: \"\" };\n props.setValue(serializeImageHotspotValue({ ...current, ...next }));\n };\n\n async function handleFile(e: Event & { currentTarget: HTMLInputElement }) {\n const file = e.currentTarget.files?.[0];\n if (!file) return;\n if (!props.onUploadFile) {\n setError(\"No upload handler configured for this form.\");\n return;\n }\n setUploading(true);\n setError(undefined);\n try {\n const { url } = await props.onUploadFile(file);\n patch({ url });\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Upload failed\");\n } finally {\n setUploading(false);\n }\n }\n\n function handleImageClick(\n e: MouseEvent & { currentTarget: HTMLImageElement },\n ) {\n const rect = e.currentTarget.getBoundingClientRect();\n const x = clamp01((e.clientX - rect.left) / rect.width);\n const y = clamp01((e.clientY - rect.top) / rect.height);\n patch({ hotspot: { x: round2(x), y: round2(y) } });\n }\n\n const crop = () => parsed()?.crop ?? { top: 0, right: 0, bottom: 0, left: 0 };\n const setCrop = (edge: keyof ImageCrop, raw: string) => {\n patch({ crop: { ...crop(), [edge]: clamp01(Number(raw) || 0) } });\n };\n\n return (\n <div class=\"flex flex-col gap-3\">\n <input\n id={props.fieldKey}\n class=\"file-input\"\n type=\"file\"\n accept=\"image/*\"\n disabled={uploading()}\n onChange={handleFile}\n />\n <Show when={uploading()}>\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n <Show when={error()}>\n <p class=\"text-sm text-error\">{error()}</p>\n </Show>\n\n <Show when={parsed()?.url}>\n {(url) => (\n <div class=\"flex flex-col gap-2\">\n <p class=\"text-xs opacity-60\">\n Click the image to set the focal point.\n </p>\n <div class=\"relative inline-block max-w-md\">\n {/* biome-ignore lint/a11y/noStaticElementInteractions: the image is the hotspot-picking surface */}\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: pointer-based focal-point picker; numeric inputs below are the keyboard-accessible path */}\n <img\n src={url()}\n alt=\"Set focal point\"\n class=\"block w-full cursor-crosshair rounded\"\n onClick={handleImageClick}\n />\n <Show when={parsed()?.hotspot}>\n {(hs) => (\n <span\n class=\"pointer-events-none absolute h-4 w-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white bg-[var(--accent,#56c6be)] shadow\"\n style={{\n left: `${hs().x * 100}%`,\n top: `${hs().y * 100}%`,\n }}\n />\n )}\n </Show>\n </div>\n\n <details class=\"text-sm\">\n <summary class=\"cursor-pointer opacity-70\">\n Crop (advanced)\n </summary>\n <div class=\"mt-2 grid grid-cols-4 gap-2\">\n {([\"top\", \"right\", \"bottom\", \"left\"] as const).map((edge) => (\n <label class=\"flex flex-col gap-1 text-xs\">\n <span class=\"capitalize opacity-70\">{edge}</span>\n <input\n class=\"input input-sm\"\n type=\"number\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n value={crop()[edge]}\n onInput={(e) => setCrop(edge, e.currentTarget.value)}\n />\n </label>\n ))}\n </div>\n </details>\n\n <p class=\"break-all text-xs opacity-50\">{url()}</p>\n </div>\n )}\n </Show>\n </div>\n );\n}\n","import {\n createEffect,\n createSignal,\n For,\n type JSX,\n onCleanup,\n Show,\n} from \"solid-js\";\n\nexport interface SearchPaletteResult {\n collection: string;\n id: number;\n label: string;\n}\n\nexport interface SearchPaletteProps {\n /** Runs a query against `LocalApi.search()` for every searchable collection — see `@thebes/cadmus/cms`'s `getCollectionsMeta`. */\n onSearch: (query: string) => Promise<SearchPaletteResult[]>;\n /** Navigates to the chosen result; the palette closes itself afterward. */\n onSelect: (result: SearchPaletteResult) => void;\n}\n\nconst DEBOUNCE_MS = 200;\n\nfunction capitalize(value: string): string {\n return value.length === 0 ? value : value[0].toUpperCase() + value.slice(1);\n}\n\n/**\n * Self-contained Cmd+K (Ctrl+K on non-Mac) search palette — issue #29.\n * Owns its own open/closed state and keyboard listener; the host app only\n * supplies `onSearch` (wired to a server function that fans out across\n * every collection with `search` configured) and `onSelect` (navigation).\n * Mirrors PanelNav's focus-trap-on-open / restore-focus-on-close pattern\n * rather than introducing a second one.\n */\nexport function SearchPalette(props: SearchPaletteProps): JSX.Element {\n const [open, setOpen] = createSignal(false);\n const [query, setQuery] = createSignal(\"\");\n const [results, setResults] = createSignal<SearchPaletteResult[]>([]);\n const [activeIndex, setActiveIndex] = createSignal(0);\n let inputRef: HTMLInputElement | undefined;\n let triggeredBy: HTMLElement | null = null;\n let debounceTimer: ReturnType<typeof setTimeout> | undefined;\n // Guards a result fetch that resolves after a newer one was already\n // kicked off (or after the palette closed) from clobbering fresher\n // results with stale ones.\n let latestQueryToken = 0;\n\n function close() {\n setOpen(false);\n setQuery(\"\");\n setResults([]);\n triggeredBy?.focus();\n }\n\n function runSearch(value: string) {\n const token = ++latestQueryToken;\n if (value.trim().length < 2) {\n setResults([]);\n return;\n }\n props.onSearch(value).then((found) => {\n if (token !== latestQueryToken) return;\n setResults(found);\n setActiveIndex(0);\n });\n }\n\n function onInput(value: string) {\n setQuery(value);\n clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => runSearch(value), DEBOUNCE_MS);\n }\n\n function selectResult(result: SearchPaletteResult | undefined) {\n if (!result) return;\n props.onSelect(result);\n close();\n }\n\n // Global Cmd+K / Ctrl+K listener — registered once, independent of\n // `open` (unlike PanelNav's Escape/Tab handling, which only needs to\n // exist while open).\n createEffect(() => {\n function onGlobalKeyDown(event: KeyboardEvent) {\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"k\") {\n event.preventDefault();\n triggeredBy = document.activeElement as HTMLElement | null;\n setOpen(true);\n }\n }\n document.addEventListener(\"keydown\", onGlobalKeyDown);\n onCleanup(() => document.removeEventListener(\"keydown\", onGlobalKeyDown));\n });\n\n createEffect(() => {\n if (open()) inputRef?.focus();\n });\n\n function onDialogKeyDown(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n close();\n return;\n }\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n setActiveIndex((i) => Math.min(i + 1, results().length - 1));\n return;\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault();\n setActiveIndex((i) => Math.max(i - 1, 0));\n return;\n }\n if (event.key === \"Enter\") {\n event.preventDefault();\n selectResult(results()[activeIndex()]);\n }\n }\n\n return (\n <Show when={open()}>\n <div\n aria-hidden=\"true\"\n class=\"fixed inset-0 z-50 flex items-start justify-center bg-[var(--color-backdrop)] px-4 pt-[15vh]\"\n onClick={close}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Search\"\n class=\"w-full max-w-lg overflow-hidden rounded-2xl border border-[var(--line)] bg-[var(--surface-strong)] shadow-2xl\"\n onClick={(event) => event.stopPropagation()}\n onKeyDown={onDialogKeyDown}\n >\n <div class=\"flex items-center gap-2 border-b border-[var(--line)] px-4 py-3\">\n <i\n class=\"ph ph-magnifying-glass text-lg text-[var(--sea-ink-soft)]\"\n aria-hidden=\"true\"\n />\n <input\n ref={inputRef}\n type=\"text\"\n value={query()}\n onInput={(event) => onInput(event.currentTarget.value)}\n placeholder=\"Search…\"\n aria-label=\"Search\"\n class=\"flex-1 bg-transparent text-base text-[var(--sea-ink)] outline-none placeholder:text-[var(--sea-ink-soft)]\"\n />\n <kbd class=\"rounded border border-[var(--chip-line)] bg-[var(--chip-bg)] px-1.5 py-0.5 text-xs text-[var(--sea-ink-soft)]\">\n Esc\n </kbd>\n </div>\n\n <Show\n when={results().length > 0}\n fallback={\n <p class=\"px-4 py-6 text-center text-sm text-[var(--sea-ink-soft)]\">\n {query().trim().length < 2\n ? \"Keep typing to search…\"\n : \"No results\"}\n </p>\n }\n >\n <ul class=\"max-h-80 overflow-y-auto py-2\">\n <For each={results()}>\n {(result, index) => (\n <li>\n <button\n type=\"button\"\n onClick={() => selectResult(result)}\n onMouseEnter={() => setActiveIndex(index())}\n class=\"flex w-full items-center justify-between gap-3 px-4 py-2 text-left text-sm text-[var(--sea-ink)] hover:bg-[var(--link-bg-hover)]\"\n classList={{\n \"bg-[var(--link-bg-hover)]\": activeIndex() === index(),\n }}\n >\n <span class=\"truncate\">{result.label}</span>\n <span class=\"shrink-0 text-xs text-[var(--sea-ink-soft)]\">\n {capitalize(result.collection)}\n </span>\n </button>\n </li>\n )}\n </For>\n </ul>\n </Show>\n </div>\n </div>\n </Show>\n );\n}\n","// Copyright (c) 2026 BowenLabs. All rights reserved.\n// Cadmea is MIT licensed. See LICENSE in the repo root.\n\nimport {\n type EditRef,\n VISUAL_EDIT_MESSAGE,\n type VisualEditingMessage,\n} from \"@thebes/cadmus/cms\";\nimport { onCleanup, onMount } from \"solid-js\";\n\n/**\n * Visual-editing preview pane (issue #15, studio side). Embeds the site's\n * preview in an iframe and listens for the click-to-edit `postMessage` that\n * `@thebes/cadmus/cms`'s `mountVisualEditing` posts from inside the preview.\n * On a click, it calls `onEdit(ref)` so the studio can navigate to that\n * field's editor (e.g. `/admin/<collection>/<id>`).\n *\n * The preview page must (a) tag editable regions with `editAttr(...)` and\n * (b) call `mountVisualEditing()` client-side. This component is the parent\n * half of that handshake.\n */\nexport interface VisualEditingPaneProps {\n /** URL of the preview route to embed. */\n src: string;\n /** Called when an editable region in the preview is clicked. */\n onEdit?: (ref: EditRef) => void;\n /**\n * Origin the preview is served from — messages from any other origin are\n * ignored (postMessage security). Defaults to `src`'s origin.\n */\n allowedOrigin?: string;\n /** Class for the iframe (size it via the consumer's layout). */\n class?: string;\n title?: string;\n}\n\nfunction originOf(url: string): string | undefined {\n try {\n return new URL(url).origin;\n } catch {\n return undefined;\n }\n}\n\nexport function VisualEditingPane(props: VisualEditingPaneProps) {\n onMount(() => {\n const expected = props.allowedOrigin ?? originOf(props.src);\n const handler = (event: MessageEvent) => {\n // Same-origin-only: drop messages from any other window/origin.\n if (expected && event.origin !== expected) return;\n const data = event.data as Partial<VisualEditingMessage> | null;\n if (data?.type === VISUAL_EDIT_MESSAGE && data.ref) {\n props.onEdit?.(data.ref);\n }\n };\n window.addEventListener(\"message\", handler);\n onCleanup(() => window.removeEventListener(\"message\", handler));\n });\n\n return (\n <iframe\n src={props.src}\n title={props.title ?? \"Preview\"}\n class={props.class ?? \"h-full w-full border-0\"}\n />\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["CollectionConfig","FieldConfig","createEffect","createSignal","For","JSX","lazy","Show","Suspense","CollectionCapabilities","FieldWidgetProps","FieldWidget","props","Element","RichTextEditor","then","mod","default","editableFields","config","Object","entries","fields","filter","key","RelationshipOption","id","label","DraftActions","onSaveDraft","values","Record","Promise","onPublish","onPreview","saving","publishing","previewing","canPublish","canPreview","saveDraftLabel","publishLabel","previewLabel","CollectionEditProps","initialValues","onSubmit","submitLabel","error","onUploadFile","file","File","url","relationshipOptions","Partial","onDirtyChange","dirty","fieldWidgets","draftActions","capabilities","RenderContext","CollectionEdit","initialSnapshot","JSON","stringify","setValues","setField","value","prev","editablePayload","fromEntries","type","handleSubmit","event","SubmitEvent","preventDefault","ctx","versioned","versions","drafts","_el$","_tmpl$6","_el$3","firstChild","addEventListener","_$insert","_$createComponent","when","children","_el$2","_tmpl$","each","field","_el$0","_tmpl$8","_el$1","_$setAttribute","required","_tmpl$7","renderInput","fallback","canUpdate","_el$11","_tmpl$9","_tmpl$2","_$effect","disabled","_el$4","_tmpl$3","$$click","_el$6","_tmpl$4","_el$8","_tmpl$5","Widget","slice","lastIndexOf","fieldKey","setValue","v","_el$13","_tmpl$0","$$input","e","currentTarget","_el$14","_tmpl$1","options","option","_el$15","_tmpl$10","_el$16","_tmpl$11","valueAsNumber","_el$17","_tmpl$12","formatDateValue","_el$18","_tmpl$13","checked","renderUploadInput","renderRelationshipInput","renderArrayInput","content","onChange","doc","uploading","setUploading","uploadError","setUploadError","handleFileChange","Event","HTMLInputElement","files","undefined","err","Error","message","_el$20","_tmpl$16","_el$22","_el$21","_tmpl$14","_el$24","_tmpl$15","_p$","_v$","_v$2","t","hasMany","relationTo","_el$25","_tmpl$17","_el$26","Number","_el$27","String","items","Array","isArray","updateItem","index","itemKey","itemValue","next","addItem","removeItem","_","i","fieldsForItem","item","base","discriminator","variantValue","variantFields","variants","_el$28","_tmpl$18","_el$29","_el$30","_el$31","_tmpl$19","_el$32","itemField","inputId","_el$33","_el$34","date","Date","isNaN","getTime","toLocaleString","_$delegateEvents","CollectionConfig","FieldConfig","createSignal","For","Show","listableFields","config","excluded","Set","Object","entries","fields","filter","key","field","has","type","formatCellValue","value","undefined","Date","toLocaleDateString","String","rowId","row","Record","id","CollectionListProps","rows","onRowClick","page","pageSize","totalCount","onPageChange","sortField","sortDirection","onSortChange","direction","selectable","selectedIds","ReadonlySet","onSelectionChange","CollectionList","props","columns","selectMode","setSelectMode","toggleSelected","next","delete","add","handleRowActivate","_el$","_tmpl$7","_el$2","firstChild","_$insert","_$createComponent","when","children","_el$3","_tmpl$","$$click","v","_el$4","_tmpl$2","_el$5","_el$6","nextSibling","addEventListener","e","currentTarget","each","_el$16","_tmpl$8","_$effect","length","fallback","_el$17","_tmpl$9","_el$18","_el$20","_el$19","slug","_el$7","_tmpl$4","_el$8","_el$9","_el$1","_tmpl$3","_el$21","_el$22","_tmpl$1","_el$23","_tmpl$0","_el$24","stopPropagation","checked","_el$25","_tmpl$10","_$className","_el$10","_tmpl$5","_el$26","_tmpl$12","_el$27","_el$29","$$keydown","preventDefault","_el$28","_tmpl$11","_el$30","_tmpl$13","_el$31","_el$32","_$memo","_el$11","_tmpl$6","_el$12","_el$13","_el$14","_el$15","_p$","_v$","_v$2","disabled","t","_$delegateEvents","ImageCrop","ImageHotspot","createMemo","createSignal","Show","ImageWithHotspot","url","hotspot","crop","round2","n","Math","round","clamp01","min","max","parseImageHotspotValue","value","trimmed","trim","startsWith","JSON","parse","serializeImageHotspotValue","stringify","FieldWidgetProps","fieldKey","setValue","onUploadFile","file","File","Promise","ImageHotspotField","props","parsed","uploading","setUploading","error","setError","patch","next","Partial","current","handleFile","e","Event","currentTarget","HTMLInputElement","files","undefined","err","Error","message","handleImageClick","MouseEvent","HTMLImageElement","rect","getBoundingClientRect","x","clientX","left","width","y","clientY","top","height","right","bottom","setCrop","edge","raw","Number","_el$","_tmpl$3","_el$2","firstChild","addEventListener","_$insert","_$createComponent","when","children","_tmpl$","_el$4","_tmpl$2","_el$5","_tmpl$4","_el$6","_el$7","nextSibling","_el$8","_el$9","_el$0","_el$1","_el$10","$$click","hs","_el$11","_tmpl$5","_$effect","_p$","_v$3","_v$4","_$setStyleProperty","t","const","map","_el$12","_tmpl$6","_el$13","_el$14","$$input","_$setAttribute","_v$","_v$2","disabled","_$delegateEvents","createEffect","createSignal","For","JSX","onCleanup","Show","SearchPaletteResult","collection","id","label","SearchPaletteProps","onSearch","query","Promise","onSelect","result","DEBOUNCE_MS","capitalize","value","length","toUpperCase","slice","SearchPalette","props","Element","open","setOpen","setQuery","results","setResults","activeIndex","setActiveIndex","inputRef","HTMLInputElement","triggeredBy","HTMLElement","debounceTimer","ReturnType","setTimeout","latestQueryToken","close","focus","runSearch","token","trim","then","found","onInput","clearTimeout","selectResult","onGlobalKeyDown","event","KeyboardEvent","metaKey","ctrlKey","key","toLowerCase","preventDefault","document","activeElement","addEventListener","removeEventListener","onDialogKeyDown","i","Math","min","max","_$createComponent","when","children","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","_el$5","nextSibling","$$click","$$keydown","stopPropagation","$$input","currentTarget","_ref$","_$use","_$insert","fallback","_el$7","_tmpl$3","_el$6","_tmpl$","each","index","_el$8","_tmpl$4","_el$9","_el$0","_el$1","_$effect","classList","toggle","_$delegateEvents","EditRef","VISUAL_EDIT_MESSAGE","VisualEditingMessage","onCleanup","onMount","VisualEditingPaneProps","src","onEdit","ref","allowedOrigin","class","title","originOf","url","URL","origin","undefined","VisualEditingPane","props","expected","handler","event","MessageEvent","data","Partial","type","window","addEventListener","removeEventListener","_el$","_tmpl$","_$effect","_p$","_v$","_v$2","_v$3","e","_$setAttribute","t","a","_$className"],"sources":["../../src/CollectionEdit.tsx","../../src/CollectionList.tsx","../../src/ImageHotspotField.tsx","../../src/SearchPalette.tsx","../../src/VisualEditingPane.tsx"],"sourcesContent":["import type { CollectionConfig, FieldConfig } from \"@thebes/cadmus/cms\";\nimport {\n createEffect,\n createSignal,\n For,\n type JSX,\n lazy,\n Show,\n Suspense,\n} from \"solid-js\";\nimport type { CollectionCapabilities } from \"./capabilities.js\";\nimport type { FieldWidgetProps } from \"./ImageHotspotField.js\";\n\n/** A custom per-field editor, registered via `fieldWidgets`. */\nexport type FieldWidget = (props: FieldWidgetProps) => JSX.Element;\n\n// Dynamic import, not a static one — @tiptap/core + @tiptap/starter-kit\n// are a large dependency (pushed a consuming route's bundle from ~9KB to\n// ~800KB when statically imported, even for collections with zero\n// richText fields). Lazy-loading means only forms that actually render a\n// richText field pull this chunk in at runtime.\nconst RichTextEditor = lazy(() =>\n import(\"./RichTextEditor.js\").then((mod) => ({\n default: mod.RichTextEditor,\n })),\n);\n\n// Fields the generic form can actually render today. `id` is never\n// user-editable. `date` fields (e.g. createdAt) are server-defaulted and\n// shown read-only rather than editable in this step.\nfunction editableFields(config: CollectionConfig): [string, FieldConfig][] {\n return Object.entries(config.fields).filter(([key]) => key !== \"id\");\n}\n\nexport interface RelationshipOption {\n id: number;\n label: string;\n}\n\n/**\n * Replaces the generic \"Save\" button with \"Save draft\"/\"Publish\" when the\n * collection has `versions: { drafts: true }` — a separate privilege from\n * a plain update, matching `access.publish` in `@thebes/cadmus/cms`.\n * `onPublish` takes no values: publishing acts on whatever was last saved\n * as a draft (the consuming route tracks which version that is), not on\n * the live form state.\n */\nexport interface DraftActions {\n onSaveDraft: (values: Record<string, unknown>) => void | Promise<void>;\n onPublish?: () => void | Promise<void>;\n /**\n * Opens a live preview of the last saved draft (issue #28) — like\n * `onPublish`, acts on whatever was last saved as a draft, not the live\n * form state. Omit to not render the Preview button at all.\n */\n onPreview?: () => void | Promise<void>;\n saving?: boolean;\n publishing?: boolean;\n previewing?: boolean;\n /** Disables Publish — e.g. until a draft has been saved at least once. */\n canPublish?: boolean;\n /** Disables Preview — same gating as canPublish, a draft must exist first. */\n canPreview?: boolean;\n saveDraftLabel?: string;\n publishLabel?: string;\n previewLabel?: string;\n}\n\nexport interface CollectionEditProps {\n config: CollectionConfig;\n initialValues?: Record<string, unknown>;\n onSubmit: (values: Record<string, unknown>) => void | Promise<void>;\n submitLabel?: string;\n error?: string;\n /** Disables the Save button and shows a spinner in its place. */\n saving?: boolean;\n /**\n * Resolves an `upload` field's selected file to a stored URL. Required\n * if the collection has any `upload` fields — `CollectionEdit` never\n * talks to storage directly (stays agnostic of R2/cadmus/storage), so\n * the consuming route wires this to a server function that calls an\n * `ImageService`'s `upload()`.\n */\n onUploadFile?: (file: File) => Promise<{ url: string }>;\n /**\n * Options for `relationship` fields (hasMany:false only — see\n * RelationshipFieldConfig's `hasMany` caveat), keyed by the field's\n * `relationTo` collection slug. `CollectionEdit` can't query another\n * collection itself, so the consuming route fetches the related rows\n * and passes them in.\n */\n relationshipOptions?: Partial<Record<string, RelationshipOption[]>>;\n /**\n * Fired whenever the dirty (unsaved-changes) state changes — wire this\n * to a router-level navigation guard (e.g. `useBlocker` in the\n * consuming route) since `CollectionEdit` has no router access itself.\n */\n onDirtyChange?: (dirty: boolean) => void;\n /**\n * Per-field custom editor widgets (issue #17), keyed by field name. When a\n * field has a widget here, it's rendered instead of the generic input for\n * that field's type — e.g. `{ heroImage: ImageHotspotField }`. The widget\n * receives the field value, a setter, and `onUploadFile`.\n */\n fieldWidgets?: Record<string, FieldWidget>;\n /** Only rendered when `config.versions?.drafts` is also true. */\n draftActions?: DraftActions;\n /**\n * Hides the Save button when `canUpdate` is `false` — see issue #26's\n * RBAC-aware admin UI. Undefined (the default — most collections don't\n * wire this up) reads as \"allowed\", same as `@thebes/cadmus/cms`'s own\n * \"no access fn = allowed\" default.\n */\n capabilities?: CollectionCapabilities;\n}\n\ninterface RenderContext {\n onUploadFile?: (file: File) => Promise<{ url: string }>;\n relationshipOptions?: Partial<Record<string, RelationshipOption[]>>;\n fieldWidgets?: Record<string, FieldWidget>;\n}\n\nexport function CollectionEdit(props: CollectionEditProps) {\n const initialSnapshot = JSON.stringify(props.initialValues ?? {});\n const [values, setValues] = createSignal<Record<string, unknown>>(\n props.initialValues ?? {},\n );\n\n // Reported via `onDirtyChange` rather than tracked by the consuming\n // route itself — only this component sees every field edit as it\n // happens. A plain JSON.stringify comparison is enough: form values are\n // already plain JSON-shaped data (TipTap docs, array-field items), so\n // there's no Date/Map/Set edge case to special-case here.\n createEffect(() => {\n props.onDirtyChange?.(JSON.stringify(values()) !== initialSnapshot);\n });\n\n function setField(key: string, value: unknown) {\n setValues((prev) => ({ ...prev, [key]: value }));\n }\n\n // date fields are read-only — never include them in a submitted/draft payload\n function editablePayload(): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(values()).filter(\n ([key]) => props.config.fields[key]?.type !== \"date\",\n ),\n );\n }\n\n function handleSubmit(event: SubmitEvent) {\n event.preventDefault();\n void props.onSubmit(editablePayload());\n }\n\n const ctx: RenderContext = {\n onUploadFile: props.onUploadFile,\n relationshipOptions: props.relationshipOptions,\n fieldWidgets: props.fieldWidgets,\n };\n\n const versioned = () => props.config.versions?.drafts && props.draftActions;\n\n return (\n <form class=\"flex flex-col gap-4\" onSubmit={handleSubmit}>\n <Show when={props.error}>\n {/* role=\"alert\" so assistive tech announces submit failures the\n moment they appear, not only if the user happens to navigate to\n them. */}\n <p class=\"text-sm text-error\" role=\"alert\">\n {props.error}\n </p>\n </Show>\n <For each={editableFields(props.config)}>\n {([key, field]) => (\n <div class=\"form-control\">\n {/* The \" *\" stays inside the label's accessible name (it reads\n as \"required\" alongside each input's `required` attribute);\n the span only colors it, it does not change the text. */}\n <label class=\"label\" for={key}>\n {key}\n <Show when={field.required}>\n <span class=\"text-error\">{\" *\"}</span>\n </Show>\n </label>\n {renderInput(key, field, values()[key], setField, ctx)}\n </div>\n )}\n </For>\n {/* Bottom-anchored, full-width action bar — not a top toolbar, per\n issue #25's mobile-first note. */}\n <div class=\"bg-base-100 sticky bottom-0 flex gap-2 border-t py-3\">\n <Show\n when={versioned()}\n fallback={\n <Show when={props.capabilities?.canUpdate !== false}>\n <button\n type=\"submit\"\n class=\"btn btn-primary flex-1\"\n disabled={props.saving}\n >\n <Show\n when={props.saving}\n fallback={props.submitLabel ?? \"Save\"}\n >\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n </button>\n </Show>\n }\n >\n <button\n type=\"button\"\n class=\"btn flex-1\"\n disabled={props.draftActions?.saving}\n onClick={() =>\n void props.draftActions?.onSaveDraft(editablePayload())\n }\n >\n <Show\n when={props.draftActions?.saving}\n fallback={props.draftActions?.saveDraftLabel ?? \"Save draft\"}\n >\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n </button>\n <button\n type=\"button\"\n class=\"btn btn-primary flex-1\"\n disabled={\n !props.draftActions?.canPublish || props.draftActions?.publishing\n }\n onClick={() => void props.draftActions?.onPublish?.()}\n >\n <Show\n when={props.draftActions?.publishing}\n fallback={props.draftActions?.publishLabel ?? \"Publish\"}\n >\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n </button>\n <Show when={props.draftActions?.onPreview}>\n <button\n type=\"button\"\n class=\"btn btn-outline flex-1\"\n disabled={\n !props.draftActions?.canPreview ||\n props.draftActions?.previewing\n }\n onClick={() => void props.draftActions?.onPreview?.()}\n >\n <Show\n when={props.draftActions?.previewing}\n fallback={props.draftActions?.previewLabel ?? \"Preview\"}\n >\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n </button>\n </Show>\n </Show>\n </div>\n </form>\n );\n}\n\nfunction renderInput(\n key: string,\n field: FieldConfig,\n value: unknown,\n setField: (key: string, value: unknown) => void,\n ctx: RenderContext,\n) {\n // A registered custom widget wins over the generic type-based input (#17).\n // Match by the full key, or by the trailing field name so a widget can\n // target a field nested inside an `array` item (whose key is a path like\n // `blocks.0.url`) without knowing the index.\n const Widget =\n ctx.fieldWidgets?.[key] ??\n ctx.fieldWidgets?.[key.slice(key.lastIndexOf(\".\") + 1)];\n if (Widget) {\n return (\n <Widget\n fieldKey={key}\n value={value}\n setValue={(v) => setField(key, v)}\n onUploadFile={ctx.onUploadFile}\n />\n );\n }\n switch (field.type) {\n case \"text\":\n return (\n <input\n id={key}\n class=\"input\"\n type=\"text\"\n value={(value as string) ?? \"\"}\n required={field.required}\n onInput={(e) => setField(key, e.currentTarget.value)}\n />\n );\n case \"select\":\n return (\n <select\n id={key}\n class=\"select\"\n value={(value as string) ?? \"\"}\n required={field.required}\n onChange={(e) => setField(key, e.currentTarget.value)}\n >\n <For each={field.options}>\n {(option) => <option value={option}>{option}</option>}\n </For>\n </select>\n );\n case \"number\":\n return (\n <input\n id={key}\n class=\"input\"\n type=\"number\"\n value={(value as number) ?? \"\"}\n required={field.required}\n onInput={(e) => setField(key, e.currentTarget.valueAsNumber)}\n />\n );\n case \"date\":\n return (\n <input\n id={key}\n class=\"input\"\n type=\"text\"\n readOnly\n value={formatDateValue(value)}\n />\n );\n case \"checkbox\":\n return (\n <input\n id={key}\n class=\"checkbox\"\n type=\"checkbox\"\n checked={(value as boolean) ?? false}\n onChange={(e) => setField(key, e.currentTarget.checked)}\n />\n );\n case \"upload\":\n return renderUploadInput(key, field, value, setField, ctx);\n case \"relationship\":\n return renderRelationshipInput(key, field, value, setField, ctx);\n case \"array\":\n return renderArrayInput(key, field, value, setField, ctx);\n case \"richText\":\n return (\n <Suspense\n fallback={<span class=\"loading loading-spinner loading-sm\" />}\n >\n <RichTextEditor\n id={key}\n content={value as object | undefined}\n onChange={(doc) => setField(key, doc)}\n />\n </Suspense>\n );\n default:\n return null;\n }\n}\n\nfunction renderUploadInput(\n key: string,\n field: FieldConfig & { type: \"upload\" },\n value: unknown,\n setField: (key: string, value: unknown) => void,\n ctx: RenderContext,\n) {\n const [uploading, setUploading] = createSignal(false);\n const [uploadError, setUploadError] = createSignal<string>();\n\n async function handleFileChange(\n e: Event & { currentTarget: HTMLInputElement },\n ) {\n const file = e.currentTarget.files?.[0];\n if (!file) return;\n if (!ctx.onUploadFile) {\n setUploadError(\"No upload handler configured for this form.\");\n return;\n }\n setUploading(true);\n setUploadError(undefined);\n try {\n const { url } = await ctx.onUploadFile(file);\n setField(key, url);\n } catch (err) {\n setUploadError(err instanceof Error ? err.message : \"Upload failed\");\n } finally {\n setUploading(false);\n }\n }\n\n return (\n <div class=\"flex flex-col gap-2\">\n <Show when={value}>\n <p class=\"text-sm opacity-70 break-all\">{value as string}</p>\n </Show>\n <input\n id={key}\n class=\"file-input\"\n type=\"file\"\n required={field.required && !value}\n disabled={uploading()}\n onChange={handleFileChange}\n />\n <Show when={uploading()}>\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n <Show when={uploadError()}>\n <p class=\"text-sm text-error\">{uploadError()}</p>\n </Show>\n </div>\n );\n}\n\nfunction renderRelationshipInput(\n key: string,\n field: FieldConfig & { type: \"relationship\" },\n value: unknown,\n setField: (key: string, value: unknown) => void,\n ctx: RenderContext,\n) {\n // hasMany:true relationships are join-table-backed (no plain FK column\n // to bind a single <select> to) — not supported by this generic form\n // yet. See RelationshipFieldConfig's `hasMany` doc.\n if (field.hasMany) return null;\n\n const options = ctx.relationshipOptions?.[field.relationTo] ?? [];\n\n return (\n <select\n id={key}\n class=\"select\"\n value={value != null ? String(value) : \"\"}\n required={field.required}\n onChange={(e) =>\n setField(\n key,\n e.currentTarget.value === \"\" ? null : Number(e.currentTarget.value),\n )\n }\n >\n <option value=\"\">—</option>\n <For each={options}>\n {(option) => <option value={option.id}>{option.label}</option>}\n </For>\n </select>\n );\n}\n\nfunction renderArrayInput(\n key: string,\n field: FieldConfig & { type: \"array\" },\n value: unknown,\n setField: (key: string, value: unknown) => void,\n ctx: RenderContext,\n) {\n const items = () =>\n Array.isArray(value) ? (value as Record<string, unknown>[]) : [];\n\n function updateItem(index: number, itemKey: string, itemValue: unknown) {\n const next = items().slice();\n next[index] = { ...next[index], [itemKey]: itemValue };\n setField(key, next);\n }\n\n function addItem() {\n setField(key, [...items(), {}]);\n }\n\n function removeItem(index: number) {\n setField(\n key,\n items().filter((_, i) => i !== index),\n );\n }\n\n function fieldsForItem(\n item: Record<string, unknown>,\n ): [string, FieldConfig][] {\n const base = Object.entries(field.fields);\n const discriminator = field.discriminator;\n if (!discriminator) return base;\n\n const variantValue = item[discriminator.key];\n const variantFields =\n typeof variantValue === \"string\"\n ? discriminator.variants[variantValue]\n : undefined;\n return variantFields ? [...base, ...Object.entries(variantFields)] : base;\n }\n\n return (\n <div class=\"flex flex-col gap-3\">\n <For each={items()}>\n {(item, index) => (\n <div class=\"card bg-base-200 flex flex-col gap-2 p-3\">\n <For each={fieldsForItem(item)}>\n {([itemKey, itemField]) => {\n const inputId = `${key}.${index()}.${itemKey}`;\n return (\n <div class=\"form-control\">\n <label class=\"label\" for={inputId}>\n {itemKey}\n <Show when={itemField.required}>\n <span class=\"text-error\">{\" *\"}</span>\n </Show>\n </label>\n {renderInput(\n inputId,\n itemField,\n item[itemKey],\n (_, v) => updateItem(index(), itemKey, v),\n ctx,\n )}\n </div>\n );\n }}\n </For>\n <button\n type=\"button\"\n class=\"btn btn-error btn-outline btn-sm self-start\"\n onClick={() => removeItem(index())}\n >\n Remove\n </button>\n </div>\n )}\n </For>\n <button\n type=\"button\"\n class=\"btn btn-outline btn-sm self-start\"\n onClick={addItem}\n >\n Add {key}\n </button>\n </div>\n );\n}\n\nfunction formatDateValue(value: unknown): string {\n if (!value) return \"—\";\n const date = value instanceof Date ? value : new Date(value as string);\n return Number.isNaN(date.getTime()) ? \"—\" : date.toLocaleString();\n}\n","import type { CollectionConfig, FieldConfig } from \"@thebes/cadmus/cms\";\nimport { createSignal, For, Show } from \"solid-js\";\n\n// Field types that can be rendered as a plain table cell today.\n// `id` is intentionally excluded — it's never a useful list column.\n// `richText`/`array` are structured content, not a sensible table cell;\n// `relationship` has no resolved label available here (CollectionList\n// only receives raw row data, not the related collection's rows) so it'd\n// show a bare numeric id — excluded until that's worth solving.\nfunction listableFields(config: CollectionConfig): [string, FieldConfig][] {\n const excluded = new Set([\"richText\", \"array\", \"relationship\"]);\n return Object.entries(config.fields).filter(\n ([key, field]) => key !== \"id\" && !excluded.has(field.type),\n );\n}\n\nfunction formatCellValue(value: unknown): string {\n if (value === null || value === undefined) return \"—\";\n if (value instanceof Date) return value.toLocaleDateString();\n return String(value);\n}\n\nfunction rowId(row: Record<string, unknown>): number | undefined {\n return typeof row.id === \"number\" ? row.id : undefined;\n}\n\nexport interface CollectionListProps {\n config: CollectionConfig;\n rows: Record<string, unknown>[];\n onRowClick?: (row: Record<string, unknown>) => void;\n\n /**\n * 1-based current page. Omit (along with `pageSize`) to render without\n * the pagination bar entirely — list views with no `find()` paging\n * wired up yet still render correctly.\n */\n page?: number;\n pageSize?: number;\n /** Total row count across all pages — see `LocalApi.count()`. Enables\n * disabling \"Next\" exactly at the last page; omit to fall back to a\n * `rows.length < pageSize` heuristic. */\n totalCount?: number;\n onPageChange?: (page: number) => void;\n\n /** Field key currently sorted on. Omit to hide the sort control. */\n sortField?: string;\n sortDirection?: \"asc\" | \"desc\";\n onSortChange?: (field: string, direction: \"asc\" | \"desc\") => void;\n\n /** Shows the \"Select\" bulk-select mode toggle. */\n selectable?: boolean;\n selectedIds?: ReadonlySet<number>;\n onSelectionChange?: (selectedIds: Set<number>) => void;\n}\n\nexport function CollectionList(props: CollectionListProps) {\n const columns = () => listableFields(props.config);\n const [selectMode, setSelectMode] = createSignal(false);\n\n function toggleSelected(id: number) {\n const next = new Set(props.selectedIds ?? []);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n props.onSelectionChange?.(next);\n }\n\n function handleRowActivate(row: Record<string, unknown>) {\n if (selectMode()) {\n const id = rowId(row);\n if (id !== undefined) toggleSelected(id);\n return;\n }\n props.onRowClick?.(row);\n }\n\n return (\n <div class=\"flex flex-col gap-3\">\n <div class=\"flex flex-wrap items-center justify-between gap-2\">\n <Show when={props.selectable}>\n <button\n type=\"button\"\n class=\"btn btn-outline btn-sm\"\n onClick={() => setSelectMode((v) => !v)}\n >\n {selectMode() ? \"Done\" : \"Select\"}\n </button>\n </Show>\n {/* Dropdown picker, not clickable column headers — sort works the\n same on touch and desktop, see issue #25's mobile-first note. */}\n <Show when={props.onSortChange}>\n <div class=\"join\">\n <select\n aria-label=\"Sort by\"\n class=\"select select-sm join-item\"\n value={props.sortField ?? \"\"}\n onChange={(e) =>\n props.onSortChange?.(\n e.currentTarget.value,\n props.sortDirection ?? \"asc\",\n )\n }\n >\n <For each={columns()}>\n {([key]) => <option value={key}>{key}</option>}\n </For>\n </select>\n <select\n aria-label=\"Sort direction\"\n class=\"select select-sm join-item\"\n value={props.sortDirection ?? \"asc\"}\n onChange={(e) =>\n props.onSortChange?.(\n props.sortField ?? columns()[0]?.[0] ?? \"\",\n e.currentTarget.value as \"asc\" | \"desc\",\n )\n }\n >\n <option value=\"asc\">Ascending</option>\n <option value=\"desc\">Descending</option>\n </select>\n </div>\n </Show>\n </div>\n\n <Show\n when={props.rows.length > 0}\n fallback={<p class=\"text-sm opacity-70\">No {props.config.slug} yet.</p>}\n >\n {/* Table on desktop — hidden below md per the mobile-first card\n layout below, not the other way around. */}\n <table class=\"table hidden md:table\">\n <thead>\n <tr>\n <Show when={selectMode()}>\n <th />\n </Show>\n <For each={columns()}>{([key]) => <th>{key}</th>}</For>\n </tr>\n </thead>\n <tbody>\n <For each={props.rows}>\n {(row) => (\n <tr\n class={\n props.onRowClick || selectMode()\n ? \"cursor-pointer hover\"\n : undefined\n }\n onClick={() => handleRowActivate(row)}\n >\n <Show when={selectMode()}>\n <td>\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-sm\"\n onClick={(e) => e.stopPropagation()}\n checked={\n rowId(row) !== undefined &&\n (props.selectedIds?.has(rowId(row) as number) ??\n false)\n }\n onChange={() => {\n const id = rowId(row);\n if (id !== undefined) toggleSelected(id);\n }}\n />\n </td>\n </Show>\n <For each={columns()}>\n {([key]) => <td>{formatCellValue(row[key])}</td>}\n </For>\n </tr>\n )}\n </For>\n </tbody>\n </table>\n\n {/* Stacked card list on mobile/tablet — tap-to-select via an\n always-visible checkbox in select mode, never hover-revealed. */}\n <div class=\"flex flex-col gap-2 md:hidden\">\n <For each={props.rows}>\n {(row) => (\n // biome-ignore lint/a11y/useSemanticElements: a native <button> can't contain interactive content (the select-mode checkbox below); role=\"button\" + tabIndex/onKeyDown is the standard fallback.\n <div\n class=\"card bg-base-200 cursor-pointer p-3\"\n role=\"button\"\n tabIndex={0}\n onClick={() => handleRowActivate(row)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleRowActivate(row);\n }\n }}\n >\n <div class=\"flex items-start gap-3\">\n <Show when={selectMode()}>\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-sm mt-1\"\n onClick={(e) => e.stopPropagation()}\n checked={\n rowId(row) !== undefined &&\n (props.selectedIds?.has(rowId(row) as number) ?? false)\n }\n onChange={() => {\n const id = rowId(row);\n if (id !== undefined) toggleSelected(id);\n }}\n />\n </Show>\n <div class=\"flex flex-1 flex-col gap-1\">\n <For each={columns()}>\n {([key]) => (\n <div class=\"flex justify-between gap-2 text-sm\">\n <span class=\"opacity-60\">{key}</span>\n <span class=\"text-right\">\n {formatCellValue(row[key])}\n </span>\n </div>\n )}\n </For>\n </div>\n </div>\n </div>\n )}\n </For>\n </div>\n </Show>\n\n {/* Bottom-anchored prev/next bar — no page numbers, per issue #25's\n mobile-first note. Renders only when pagination is wired up. */}\n <Show when={props.page !== undefined && props.pageSize !== undefined}>\n <div class=\"bg-base-100 sticky bottom-0 flex items-center justify-between gap-2 border-t py-2\">\n <button\n type=\"button\"\n class=\"btn btn-sm\"\n disabled={(props.page ?? 1) <= 1}\n onClick={() => props.onPageChange?.((props.page ?? 1) - 1)}\n >\n Prev\n </button>\n <span class=\"text-sm opacity-70\">Page {props.page}</span>\n <button\n type=\"button\"\n class=\"btn btn-sm\"\n disabled={\n props.totalCount !== undefined\n ? (props.page ?? 1) * (props.pageSize ?? 0) >= props.totalCount\n : props.rows.length < (props.pageSize ?? 0)\n }\n onClick={() => props.onPageChange?.((props.page ?? 1) + 1)}\n >\n Next\n </button>\n </div>\n </Show>\n </div>\n );\n}\n","// Copyright (c) 2026 BowenLabs. All rights reserved.\n// Cadmea is MIT licensed. See LICENSE in the repo root.\n\nimport type { ImageCrop, ImageHotspot } from \"@thebes/cadmus/storage\";\nimport { createMemo, createSignal, Show } from \"solid-js\";\n\n/**\n * Image hotspot/crop editor widget (issue #17). A custom field widget for\n * `upload` image fields: upload an image, then click it to set the focal\n * point (hotspot) and optionally enter a crop region. Stores the value as a\n * JSON string `{ url, hotspot?, crop? }` in the same column (back-compatible\n * — a plain URL string still parses). Pair with `ImageService.render`'s\n * `hotspot`/`crop` args on the read side (see @thebes/cadmus-cloudflare-images).\n *\n * Register it via `createCollectionEditPage`/`CollectionEdit`'s `fieldWidgets`\n * option, keyed by the field name.\n */\n\nexport interface ImageWithHotspot {\n url: string;\n hotspot?: ImageHotspot;\n crop?: ImageCrop;\n}\n\nconst round2 = (n: number): number => Math.round(n * 100) / 100;\nconst clamp01 = (n: number): number => Math.min(1, Math.max(0, n));\n\n/**\n * Parse an upload-field value into `{ url, hotspot?, crop? }`. Accepts the\n * JSON object this widget writes, an already-parsed object, or a bare URL\n * string (legacy / non-hotspot uploads). Returns null for empty values.\n */\nexport function parseImageHotspotValue(\n value: unknown,\n): ImageWithHotspot | null {\n if (!value) return null;\n if (typeof value === \"object\") return value as ImageWithHotspot;\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (trimmed.startsWith(\"{\")) {\n try {\n return JSON.parse(trimmed) as ImageWithHotspot;\n } catch {\n // fall through to treating it as a plain URL\n }\n }\n return trimmed ? { url: trimmed } : null;\n }\n return null;\n}\n\n/** Serialize an {@link ImageWithHotspot} for storage in an upload field. */\nexport function serializeImageHotspotValue(value: ImageWithHotspot): string {\n return JSON.stringify(value);\n}\n\n/** Props every `fieldWidgets` widget receives from CollectionEdit. */\nexport interface FieldWidgetProps {\n fieldKey: string;\n value: unknown;\n setValue: (value: unknown) => void;\n onUploadFile?: (file: File) => Promise<{ url: string }>;\n}\n\nexport function ImageHotspotField(props: FieldWidgetProps) {\n const parsed = createMemo(() => parseImageHotspotValue(props.value));\n const [uploading, setUploading] = createSignal(false);\n const [error, setError] = createSignal<string>();\n\n const patch = (next: Partial<ImageWithHotspot>) => {\n const current = parsed() ?? { url: \"\" };\n props.setValue(serializeImageHotspotValue({ ...current, ...next }));\n };\n\n async function handleFile(e: Event & { currentTarget: HTMLInputElement }) {\n const file = e.currentTarget.files?.[0];\n if (!file) return;\n if (!props.onUploadFile) {\n setError(\"No upload handler configured for this form.\");\n return;\n }\n setUploading(true);\n setError(undefined);\n try {\n const { url } = await props.onUploadFile(file);\n patch({ url });\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Upload failed\");\n } finally {\n setUploading(false);\n }\n }\n\n function handleImageClick(\n e: MouseEvent & { currentTarget: HTMLImageElement },\n ) {\n const rect = e.currentTarget.getBoundingClientRect();\n const x = clamp01((e.clientX - rect.left) / rect.width);\n const y = clamp01((e.clientY - rect.top) / rect.height);\n patch({ hotspot: { x: round2(x), y: round2(y) } });\n }\n\n const crop = () => parsed()?.crop ?? { top: 0, right: 0, bottom: 0, left: 0 };\n const setCrop = (edge: keyof ImageCrop, raw: string) => {\n patch({ crop: { ...crop(), [edge]: clamp01(Number(raw) || 0) } });\n };\n\n return (\n <div class=\"flex flex-col gap-3\">\n <input\n id={props.fieldKey}\n class=\"file-input\"\n type=\"file\"\n accept=\"image/*\"\n disabled={uploading()}\n onChange={handleFile}\n />\n <Show when={uploading()}>\n <span class=\"loading loading-spinner loading-sm\" />\n </Show>\n <Show when={error()}>\n <p class=\"text-sm text-error\">{error()}</p>\n </Show>\n\n <Show when={parsed()?.url}>\n {(url) => (\n <div class=\"flex flex-col gap-2\">\n <p class=\"text-xs opacity-60\">\n Click the image to set the focal point.\n </p>\n <div class=\"relative inline-block max-w-md\">\n {/* biome-ignore lint/a11y/noStaticElementInteractions: the image is the hotspot-picking surface */}\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: pointer-based focal-point picker; numeric inputs below are the keyboard-accessible path */}\n <img\n src={url()}\n alt=\"Set focal point\"\n class=\"block w-full cursor-crosshair rounded\"\n onClick={handleImageClick}\n />\n <Show when={parsed()?.hotspot}>\n {(hs) => (\n <span\n class=\"pointer-events-none absolute h-4 w-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white bg-[var(--accent,#56c6be)] shadow\"\n style={{\n left: `${hs().x * 100}%`,\n top: `${hs().y * 100}%`,\n }}\n />\n )}\n </Show>\n </div>\n\n <details class=\"text-sm\">\n <summary class=\"cursor-pointer opacity-70\">\n Crop (advanced)\n </summary>\n <div class=\"mt-2 grid grid-cols-4 gap-2\">\n {([\"top\", \"right\", \"bottom\", \"left\"] as const).map((edge) => (\n <label class=\"flex flex-col gap-1 text-xs\">\n <span class=\"capitalize opacity-70\">{edge}</span>\n <input\n class=\"input input-sm\"\n type=\"number\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n value={crop()[edge]}\n onInput={(e) => setCrop(edge, e.currentTarget.value)}\n />\n </label>\n ))}\n </div>\n </details>\n\n <p class=\"break-all text-xs opacity-50\">{url()}</p>\n </div>\n )}\n </Show>\n </div>\n );\n}\n","import {\n createEffect,\n createSignal,\n For,\n type JSX,\n onCleanup,\n Show,\n} from \"solid-js\";\n\nexport interface SearchPaletteResult {\n collection: string;\n id: number;\n label: string;\n}\n\nexport interface SearchPaletteProps {\n /** Runs a query against `LocalApi.search()` for every searchable collection — see `@thebes/cadmus/cms`'s `getCollectionsMeta`. */\n onSearch: (query: string) => Promise<SearchPaletteResult[]>;\n /** Navigates to the chosen result; the palette closes itself afterward. */\n onSelect: (result: SearchPaletteResult) => void;\n}\n\nconst DEBOUNCE_MS = 200;\n\nfunction capitalize(value: string): string {\n return value.length === 0 ? value : value[0].toUpperCase() + value.slice(1);\n}\n\n/**\n * Self-contained Cmd+K (Ctrl+K on non-Mac) search palette — issue #29.\n * Owns its own open/closed state and keyboard listener; the host app only\n * supplies `onSearch` (wired to a server function that fans out across\n * every collection with `search` configured) and `onSelect` (navigation).\n * Mirrors PanelNav's focus-trap-on-open / restore-focus-on-close pattern\n * rather than introducing a second one.\n */\nexport function SearchPalette(props: SearchPaletteProps): JSX.Element {\n const [open, setOpen] = createSignal(false);\n const [query, setQuery] = createSignal(\"\");\n const [results, setResults] = createSignal<SearchPaletteResult[]>([]);\n const [activeIndex, setActiveIndex] = createSignal(0);\n let inputRef: HTMLInputElement | undefined;\n let triggeredBy: HTMLElement | null = null;\n let debounceTimer: ReturnType<typeof setTimeout> | undefined;\n // Guards a result fetch that resolves after a newer one was already\n // kicked off (or after the palette closed) from clobbering fresher\n // results with stale ones.\n let latestQueryToken = 0;\n\n function close() {\n setOpen(false);\n setQuery(\"\");\n setResults([]);\n triggeredBy?.focus();\n }\n\n function runSearch(value: string) {\n const token = ++latestQueryToken;\n if (value.trim().length < 2) {\n setResults([]);\n return;\n }\n props.onSearch(value).then((found) => {\n if (token !== latestQueryToken) return;\n setResults(found);\n setActiveIndex(0);\n });\n }\n\n function onInput(value: string) {\n setQuery(value);\n clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => runSearch(value), DEBOUNCE_MS);\n }\n\n function selectResult(result: SearchPaletteResult | undefined) {\n if (!result) return;\n props.onSelect(result);\n close();\n }\n\n // Global Cmd+K / Ctrl+K listener — registered once, independent of\n // `open` (unlike PanelNav's Escape/Tab handling, which only needs to\n // exist while open).\n createEffect(() => {\n function onGlobalKeyDown(event: KeyboardEvent) {\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"k\") {\n event.preventDefault();\n triggeredBy = document.activeElement as HTMLElement | null;\n setOpen(true);\n }\n }\n document.addEventListener(\"keydown\", onGlobalKeyDown);\n onCleanup(() => document.removeEventListener(\"keydown\", onGlobalKeyDown));\n });\n\n createEffect(() => {\n if (open()) inputRef?.focus();\n });\n\n function onDialogKeyDown(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n close();\n return;\n }\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n setActiveIndex((i) => Math.min(i + 1, results().length - 1));\n return;\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault();\n setActiveIndex((i) => Math.max(i - 1, 0));\n return;\n }\n if (event.key === \"Enter\") {\n event.preventDefault();\n selectResult(results()[activeIndex()]);\n }\n }\n\n return (\n <Show when={open()}>\n <div\n aria-hidden=\"true\"\n class=\"fixed inset-0 z-50 flex items-start justify-center bg-[var(--color-backdrop)] px-4 pt-[15vh]\"\n onClick={close}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Search\"\n class=\"w-full max-w-lg overflow-hidden rounded-2xl border border-[var(--line)] bg-[var(--surface-strong)] shadow-2xl\"\n onClick={(event) => event.stopPropagation()}\n onKeyDown={onDialogKeyDown}\n >\n <div class=\"flex items-center gap-2 border-b border-[var(--line)] px-4 py-3\">\n <i\n class=\"ph ph-magnifying-glass text-lg text-[var(--sea-ink-soft)]\"\n aria-hidden=\"true\"\n />\n <input\n ref={inputRef}\n type=\"text\"\n value={query()}\n onInput={(event) => onInput(event.currentTarget.value)}\n placeholder=\"Search…\"\n aria-label=\"Search\"\n class=\"flex-1 bg-transparent text-base text-[var(--sea-ink)] outline-none placeholder:text-[var(--sea-ink-soft)]\"\n />\n <kbd class=\"rounded border border-[var(--chip-line)] bg-[var(--chip-bg)] px-1.5 py-0.5 text-xs text-[var(--sea-ink-soft)]\">\n Esc\n </kbd>\n </div>\n\n <Show\n when={results().length > 0}\n fallback={\n <p class=\"px-4 py-6 text-center text-sm text-[var(--sea-ink-soft)]\">\n {query().trim().length < 2\n ? \"Keep typing to search…\"\n : \"No results\"}\n </p>\n }\n >\n <ul class=\"max-h-80 overflow-y-auto py-2\">\n <For each={results()}>\n {(result, index) => (\n <li>\n <button\n type=\"button\"\n onClick={() => selectResult(result)}\n onMouseEnter={() => setActiveIndex(index())}\n class=\"flex w-full items-center justify-between gap-3 px-4 py-2 text-left text-sm text-[var(--sea-ink)] hover:bg-[var(--link-bg-hover)]\"\n classList={{\n \"bg-[var(--link-bg-hover)]\": activeIndex() === index(),\n }}\n >\n <span class=\"truncate\">{result.label}</span>\n <span class=\"shrink-0 text-xs text-[var(--sea-ink-soft)]\">\n {capitalize(result.collection)}\n </span>\n </button>\n </li>\n )}\n </For>\n </ul>\n </Show>\n </div>\n </div>\n </Show>\n );\n}\n","// Copyright (c) 2026 BowenLabs. All rights reserved.\n// Cadmea is MIT licensed. See LICENSE in the repo root.\n\nimport {\n type EditRef,\n VISUAL_EDIT_MESSAGE,\n type VisualEditingMessage,\n} from \"@thebes/cadmus/cms\";\nimport { onCleanup, onMount } from \"solid-js\";\n\n/**\n * Visual-editing preview pane (issue #15, studio side). Embeds the site's\n * preview in an iframe and listens for the click-to-edit `postMessage` that\n * `@thebes/cadmus/cms`'s `mountVisualEditing` posts from inside the preview.\n * On a click, it calls `onEdit(ref)` so the studio can navigate to that\n * field's editor (e.g. `/admin/<collection>/<id>`).\n *\n * The preview page must (a) tag editable regions with `editAttr(...)` and\n * (b) call `mountVisualEditing()` client-side. This component is the parent\n * half of that handshake.\n */\nexport interface VisualEditingPaneProps {\n /** URL of the preview route to embed. */\n src: string;\n /** Called when an editable region in the preview is clicked. */\n onEdit?: (ref: EditRef) => void;\n /**\n * Origin the preview is served from — messages from any other origin are\n * ignored (postMessage security). Defaults to `src`'s origin.\n */\n allowedOrigin?: string;\n /** Class for the iframe (size it via the consumer's layout). */\n class?: string;\n title?: string;\n}\n\nfunction originOf(url: string): string | undefined {\n try {\n return new URL(url).origin;\n } catch {\n return undefined;\n }\n}\n\nexport function VisualEditingPane(props: VisualEditingPaneProps) {\n onMount(() => {\n const expected = props.allowedOrigin ?? originOf(props.src);\n const handler = (event: MessageEvent) => {\n // Same-origin-only: drop messages from any other window/origin.\n if (expected && event.origin !== expected) return;\n const data = event.data as Partial<VisualEditingMessage> | null;\n if (data?.type === VISUAL_EDIT_MESSAGE && data.ref) {\n props.onEdit?.(data.ref);\n }\n };\n window.addEventListener(\"message\", handler);\n onCleanup(() => window.removeEventListener(\"message\", handler));\n });\n\n return (\n <iframe\n src={props.src}\n title={props.title ?? \"Preview\"}\n class={props.class ?? \"h-full w-full border-0\"}\n />\n );\n}\n"],"mappings":"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"}
|
package/dist/index/server.js
CHANGED
|
@@ -188,7 +188,7 @@ function CollectionEdit(props) {
|
|
|
188
188
|
})));
|
|
189
189
|
}
|
|
190
190
|
function renderInput(key, field, value, setField, ctx) {
|
|
191
|
-
const Widget = ctx.fieldWidgets?.[key];
|
|
191
|
+
const Widget = ctx.fieldWidgets?.[key] ?? ctx.fieldWidgets?.[key.slice(key.lastIndexOf(".") + 1)];
|
|
192
192
|
if (Widget) return createComponent(Widget, {
|
|
193
193
|
fieldKey: key,
|
|
194
194
|
value,
|