@manifest-editor/creator-api 2.2.1-next.0.eefc2e3 → 2.2.2-next.0.903673e

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.
Files changed (2) hide show
  1. package/README.md +122 -75
  2. package/package.json +3 -3
package/README.md CHANGED
@@ -1,79 +1,126 @@
1
- # Creator API
2
-
3
- - What do you want to create
4
- - The type + refined type
5
- - The fields you add
6
- - Static fields
7
- - Where is it valid to create
8
- - Parent type
9
- - Custom parent supports
10
- - Parent fields
11
- - Canvas specific: how does it affect the canvas
12
- - temporal
13
- - spatial
14
- - What can it export as:
15
- - Canvas
16
- - Annotation
17
- - Resource
18
- - Other
19
- - Does it replace resources? (e.g. choice)
20
- - Does it require canvas interaction
21
-
22
- Examples (cookbook)
23
-
24
- - Simple image
25
- - Simple audio
26
- - Simple video
27
- - Image with service
28
- - Cropped image (with service)
29
- - External HTML link
30
- - External PDF
31
- - External XML
32
- - External plaintext?
33
- - Commenting annotation on canvas
34
- - Tagging annotation at box
35
- - Creating range from canvas selection?
36
- - Creating choice from list of annotations
37
-
38
- The creation process is split into two parts:
39
-
40
- - The UI (e.g. the form that's presented to the user)
41
- - The building/creation process
42
-
43
- The creation process is intended to be dual purpose. This is not a great example, but here you can see that you can "call" other creators inside this creator. So they can become composable.
1
+ <p align="center">
2
+ <a href="https://github.com/digirati-co-uk/iiif-manifest-editor"><img src="https://raw.githubusercontent.com/digirati-co-uk/iiif-manifest-editor/main/apps/docs/content/img/logo.svg" width="360" alt="Manifest Editor"></a>
3
+ </p>
4
+ <p align="center">
5
+ <a href="https://www.npmjs.com/package/@manifest-editor/creator-api"><img src="https://img.shields.io/npm/v/%40manifest-editor%2Fcreator-api" alt="npm version"></a>
6
+ <a href="https://github.com/digirati-co-uk/iiif-manifest-editor/actions/workflows/build-test.yml"><img src="https://img.shields.io/github/actions/workflow/status/digirati-co-uk/iiif-manifest-editor/build-test.yml?branch=main&amp;label=build" alt="Build status"></a>
7
+ <a href="https://manifest-editor-docs.netlify.app/"><img src="https://img.shields.io/badge/docs-Manifest_Editor-blue" alt="Documentation"></a>
8
+ </p>
9
+
10
+ # @manifest-editor/creator-api
11
+
12
+ ## Getting started with Manifest Editor
13
+
14
+ For the complete editor, start with [`manifest-editor`](https://www.npmjs.com/package/manifest-editor) and its [installation and integration guide](https://github.com/digirati-co-uk/iiif-manifest-editor/tree/main/packages/manifest-editor#readme). It combines the editor UI, presets, creators, and editing APIs. This package is one part of that workspace.
15
+
16
+ ## About
17
+
18
+ Definitions and execution support for resource creators. A creator combines supported parent/resource types, creation logic, and an optional React form.
19
+
20
+ ## Quick start
21
+
22
+ ```sh
23
+ npm install @manifest-editor/creator-api @manifest-editor/creators
24
+ ```
25
+
26
+ ```ts
27
+ import { withInitialData } from "@manifest-editor/creator-api";
28
+ import { imageUrlCreator } from "@manifest-editor/creators";
29
+
30
+ export const prefilledImageCreator = withInitialData(imageUrlCreator, {
31
+ url: "https://example.org/image.jpg",
32
+ });
33
+ ```
34
+
35
+ Register the resulting definition in a custom preset’s `creators` array. This example configures a form; it does not create a resource until the creator is run.
36
+
37
+ ## Creation has two parts
38
+
39
+ A **definition** describes what can be created and where it is allowed. Its `render(ctx)` callback, when present, shows a form in the editor. The form calls `ctx.runCreate(payload)` when the user submits. Its separate `create(payload, ctx)` function builds the resources, so the same logic can be invoked programmatically without rendering the form.
40
+
41
+ The distinction matters: the render context and creation-function context are different types. `CreatorContext` supplies UI actions; `CreatorFunctionContext` supplies composition helpers, the Vault, parent/target information, and ID generation.
42
+
43
+ ### What a definition describes
44
+
45
+ | Field | Purpose |
46
+ | --- | --- |
47
+ | `id`, `label`, `summary`, `icon` | Registration and the creator picker. |
48
+ | `resourceType`, `resourceFields` | The kind of resource produced and its fields. |
49
+ | `supports` | Allowed parent types/properties, optional field maps, and custom eligibility checks. |
50
+ | `create` | Build one resource or an array of resources from a payload. |
51
+ | `render` | Optional React form. |
52
+ | `supportsResource` | Recognise supplied content, such as a URL, and offer an appropriate creator. |
53
+ | `sideEffects` | Follow-up actions after creation into a parent. |
54
+
55
+ `defineCreator()` preserves the definition's TypeScript information; it does not register or execute it. Pass definitions to `Creator` or register them in a shell preset. Keep IDs unique.
56
+
57
+ ## Define and run a creator
58
+
59
+ This headless example creates a Canvas and its AnnotationPage together, then links the Canvas to a Manifest:
44
60
 
45
61
  ```ts
46
- async function createThing(ctx) {
47
- const image = await ctx.create("@manifest-editor/create-image", {
48
- url: "https://example.org/image-1.jpg",
49
- });
50
-
51
- // If you want the underlying resource you just created.
52
- const previewResource = image.get();
53
-
54
- // Find a reference to an existing resource.
55
- const ref = ctx.ref("https://example.org/canvas-1");
56
-
57
- // Or you can create new resources that will be embedded.
58
- const image2 = ctx.embed({
59
- id: "https://example.org/image-2.jpg",
60
- type: "Image",
61
- height: 100,
62
- width: 200,
63
- });
64
-
65
- // And then it can be part of a bigger resource:
66
- // This cannot be a nested tree - it must be a flat resource with linked resources (like thumbnail) as
67
- // objects like `ctx.create()` or `ctx.embed()`. This makes sure that we can piece together the finaly
68
- // actions required in the last step.
69
- return {
70
- id: "https://example.org/image-3.jpg",
71
- type: "Image",
72
- height: ctx.data.height,
73
- width: ctx.data.width,
74
- thumbnail: [image],
75
- };
76
- }
62
+ import { Vault } from "@iiif/helpers";
63
+ import { Creator, defineCreator } from "@manifest-editor/creator-api";
64
+
65
+ const blankCanvas = defineCreator({
66
+ id: "example/blank-canvas",
67
+ label: "Blank canvas",
68
+ resourceType: "Canvas",
69
+ resourceFields: ["id", "type", "label", "width", "height", "items"],
70
+ supports: { parentTypes: ["Manifest"], parentFields: ["items"] },
71
+ create(data: { title: string }, ctx) {
72
+ const id = ctx.generateId("canvas");
73
+ const page = ctx.embed({
74
+ id: `${id}/page`, type: "AnnotationPage", items: [],
75
+ });
76
+ return {
77
+ id, type: "Canvas", label: { en: [data.title] },
78
+ width: 1000, height: 1000, items: [page],
79
+ };
80
+ },
81
+ });
82
+
83
+ const vault = new Vault();
84
+ const id = "https://example.org/manifest";
85
+ await vault.loadManifest(id, {
86
+ id, type: "Manifest", label: { en: ["Example"] }, items: [],
87
+ });
88
+ const creator = new Creator(vault, [blankCanvas]);
89
+ const reference = await creator.create(blankCanvas.id, { title: "Page one" }, {
90
+ parent: { resource: { id, type: "Manifest" }, property: "items" },
91
+ });
92
+ console.log(reference, vault.toPresentation3({ id, type: "Manifest" }));
77
93
  ```
78
94
 
79
- A "create" callback will be passed to the render, this is when this will be called and the resource will be created. Once created `edit()` will be called on the resource.
95
+ Install `@iiif/helpers` as well to run this example. `create()` returns a reference or array of references, not the original nested JSON. With a parent, it checks supported types and fields, imports the new resources, and links them into that parent's property. `start` and `target` are handled as single references; list properties use reference insertion, optionally at `parent.atIndex`.
96
+
97
+ Without a parent, creation still imports the resources but does not attach them to another resource. Supply `rootId` when your definition calls `ctx.generateId()` without a parent; otherwise it has no meaningful base identifier. Definition side effects run only when a parent is supplied.
98
+
99
+ ## Compose resources instead of duplicating them
100
+
101
+ Inside a creation function:
102
+
103
+ - `ctx.embed(data)` wraps a new resource for inclusion in the result graph.
104
+ - `ctx.ref(idOrReference)` refers to an existing resource; it does not fetch that resource.
105
+ - `await ctx.create(id, payload, options?)` invokes another registered creator and returns its resource wrapper(s). Nested creation is collected into the outer commit rather than committing immediately.
106
+ - `ctx.generateId(type, parent?)` builds an ID beneath a parent or configured root.
107
+ - `ctx.getParent()`, `ctx.getTarget()`, and selector helpers preserve the distinction between a source resource and a targeted region.
108
+ - `ctx.getPreviewVault()` provides the separate preview Vault.
109
+
110
+ `CreatorResource` keeps embedded resources and references separate while producing normalised Vault entities. Its `get()` returns the working resource; `ref()` produces a reference, preserving a `SpecificResource` wrapper when present. Prefer these helpers for explicit composition even though the implementation can also process nested resource objects.
111
+
112
+ ## Adapt the built-in forms
113
+
114
+ `withInitialData(definition, defaults, overrides?)` merges form defaults with invocation-specific initial data; the third argument wins over both. `withCustomRender(definition, render)` receives the current context and original renderer so you can wrap a form. Both return definitions for registration; neither runs creation.
115
+
116
+ The built-in definitions live in [`@manifest-editor/creators`](../creators). Typed definitions help authors, but the runtime `Creator.create(id, payload, options)` method still accepts an untyped payload. The fully inferred `useCreator(resource, property, id)` API shown in older design notes is not available.
117
+
118
+ ## API overview
119
+
120
+ - `Creator` and `CreatorResource`: creation execution and resource composition.
121
+ - `defineCreator`: typed creator definitions.
122
+ - `withInitialData`: supplies defaults to a creator form.
123
+ - `withCustomRender`: wraps or replaces a creator's UI.
124
+ - Creator context, payload, supported-parent, and resource types.
125
+
126
+ See the [source exports](https://github.com/digirati-co-uk/iiif-manifest-editor/tree/main/packages/creator-api/src) for the complete API and TypeScript definitions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manifest-editor/creator-api",
3
- "version": "2.2.1-next.0.eefc2e3",
3
+ "version": "2.2.2-next.0.903673e",
4
4
  "type": "module",
5
5
  "bugs": "https://github.com/digirati-co-uk/iiif-manifest-editor/issues",
6
6
  "repository": {
@@ -42,7 +42,7 @@
42
42
  "@iiif/parser": "4.0.1",
43
43
  "@iiif/presentation-3": "^2.2.3",
44
44
  "@iiif/presentation-3-normalized": "^0.9.7",
45
- "@manifest-editor/editor-api": "2.2.1-next.0.eefc2e3",
45
+ "@manifest-editor/editor-api": "2.2.2-next.0.903673e",
46
46
  "polygon-editor": "0.0.23",
47
47
  "react-iiif-vault": "4.0.0"
48
48
  },
@@ -54,5 +54,5 @@
54
54
  "publishConfig": {
55
55
  "access": "public"
56
56
  },
57
- "gitHead": "eefc2e321c6da5d194285621f4d26376088f2bb2"
57
+ "gitHead": "903673e7c35feed673fc100cb0efe34733057c91"
58
58
  }