@manifest-editor/creators 1.3.0 → 1.4.0

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 (36) hide show
  1. package/README.md +49 -0
  2. package/dist/chunk-AVISJS46.js +50 -0
  3. package/dist/chunk-ES62IRNT.js +50 -0
  4. package/dist/chunk-KLSWX2QF.js +38 -0
  5. package/dist/chunk-PFQB3PNW.js +47 -0
  6. package/dist/chunk-S3JO5Y3Z.js +50 -0
  7. package/dist/iiif-browser-form.lazy-3INAWCE5.js +54 -0
  8. package/dist/iiif-browser-form.lazy-4NX7YPGK.js +57 -0
  9. package/dist/iiif-browser-form.lazy-4X5LD2U4.js +51 -0
  10. package/dist/iiif-browser-form.lazy-5TF74M2Q.js +48 -0
  11. package/dist/iiif-browser-form.lazy-BHX6TGDY.js +58 -0
  12. package/dist/iiif-browser-form.lazy-C72INDSJ.js +57 -0
  13. package/dist/iiif-browser-form.lazy-DKKTAIO5.js +59 -0
  14. package/dist/iiif-browser-form.lazy-DPRO7R2W.js +59 -0
  15. package/dist/iiif-browser-form.lazy-EREIP6PZ.js +58 -0
  16. package/dist/iiif-browser-form.lazy-FQDZQ3UW.js +58 -0
  17. package/dist/iiif-browser-form.lazy-G7TCZSC2.js +58 -0
  18. package/dist/iiif-browser-form.lazy-HZ3M2DXT.js +57 -0
  19. package/dist/iiif-browser-form.lazy-I7KTYV3O.js +57 -0
  20. package/dist/iiif-browser-form.lazy-JMT72BLP.js +59 -0
  21. package/dist/iiif-browser-form.lazy-JX4S6NGX.js +48 -0
  22. package/dist/iiif-browser-form.lazy-KTB4BQBM.js +59 -0
  23. package/dist/iiif-browser-form.lazy-O35TC45U.js +49 -0
  24. package/dist/iiif-browser-form.lazy-OMDV43NQ.js +51 -0
  25. package/dist/iiif-browser-form.lazy-OXQVZ3GS.js +59 -0
  26. package/dist/iiif-browser-form.lazy-XORWZFSW.js +49 -0
  27. package/dist/index.cjs +1028 -537
  28. package/dist/index.d.cts +367 -21
  29. package/dist/index.d.ts +367 -21
  30. package/dist/index.js +954 -489
  31. package/dist/manifest-browser-form.lazy-FI4GGCPX.js +6 -0
  32. package/dist/manifest-browser-form.lazy-HJJKFMR6.js +6 -0
  33. package/dist/manifest-browser-form.lazy-MYI26AX4.js +6 -0
  34. package/dist/manifest-browser-form.lazy-XVYSAQAW.js +6 -0
  35. package/dist/manifest-browser-form.lazy-YYKOYF7R.js +6 -0
  36. package/package.json +12 -11
package/dist/index.cjs CHANGED
@@ -36,49 +36,63 @@ __export(iiif_browser_form_lazy_exports, {
36
36
  default: () => IIIFBrowserCreatorForm
37
37
  });
38
38
  function IIIFBrowserCreatorForm(props) {
39
- const vault = (0, import_shell3.usePreviewVault)();
40
- const output = (0, import_react7.useMemo)(() => {
39
+ const vault = (0, import_react8.useMemo)(() => new import_helpers4.Vault(), []);
40
+ const output = (0, import_react8.useMemo)(() => {
41
41
  return [
42
42
  {
43
43
  type: "callback",
44
44
  label: "Select",
45
- supportedTypes: [
46
- "Canvas",
47
- "CanvasList",
48
- "CanvasRegion",
49
- "ImageService",
50
- "ImageServiceRegion"
51
- ],
45
+ supportedTypes: ["Canvas", "CanvasList", "CanvasRegion", "ImageService", "ImageServiceRegion"],
52
46
  cb: (resource) => props.runCreate({ output: resource }),
53
- format: { type: "content-state" }
47
+ format: {
48
+ type: "custom",
49
+ format: (resource, parent, vault2) => {
50
+ const resourcesAsArray = Array.isArray(resource) ? resource : [{ ...resource, parent }];
51
+ const resources = [];
52
+ for (const resource2 of resourcesAsArray) {
53
+ resources.push({ resource: vault2.get(resource2), parent: resource2.parent, selector: resource2.selector });
54
+ }
55
+ return resources;
56
+ }
57
+ }
54
58
  }
55
59
  ];
56
60
  }, [props.runCreate]);
57
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_shell3.PreviewVaultBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
61
+ const navigationOptions = (0, import_react8.useMemo)(() => {
62
+ return {
63
+ canCropImage: true,
64
+ canSelectCanvas: true,
65
+ canSelectManifest: false,
66
+ canSelectCollection: false,
67
+ // @todo fix the output so this one works.
68
+ multiSelect: true
69
+ };
70
+ }, []);
71
+ const uiOptions = (0, import_react8.useMemo)(() => {
72
+ return {
73
+ buttonClassName: "bg-me-primary-500 text-white hover:bg-me-primary-600"
74
+ };
75
+ }, []);
76
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_shell3.PreviewVaultBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
58
77
  import_iiif_browser2.IIIFBrowser,
59
78
  {
79
+ ui: uiOptions,
60
80
  vault,
61
81
  className: "iiif-browser border-none border-t rounded-none h-[70vh] min-h-[60vh] max-h-full max-w-full",
62
82
  output,
63
- navigation: {
64
- canCropImage: true,
65
- canSelectCanvas: true,
66
- canSelectManifest: false,
67
- canSelectCollection: false,
68
- // @todo fix the output so this one works.
69
- multiSelect: false
70
- }
83
+ navigation: navigationOptions
71
84
  }
72
85
  ) });
73
86
  }
74
- var import_shell3, import_iiif_browser2, import_react7, import_jsx_runtime27;
87
+ var import_helpers4, import_shell3, import_iiif_browser2, import_react8, import_jsx_runtime29;
75
88
  var init_iiif_browser_form_lazy = __esm({
76
89
  "src/ContentResource/IIIFBrowserCreator/iiif-browser-form.lazy.tsx"() {
77
90
  "use strict";
91
+ import_helpers4 = require("@iiif/helpers");
78
92
  import_shell3 = require("@manifest-editor/shell");
79
93
  import_iiif_browser2 = require("iiif-browser");
80
- import_react7 = require("react");
81
- import_jsx_runtime27 = require("react/jsx-runtime");
94
+ import_react8 = require("react");
95
+ import_jsx_runtime29 = require("react/jsx-runtime");
82
96
  }
83
97
  });
84
98
 
@@ -88,48 +102,100 @@ __export(manifest_browser_form_lazy_exports, {
88
102
  default: () => ManifestBrowserCreatorForm
89
103
  });
90
104
  function ManifestBrowserCreatorForm(props) {
91
- const vault = (0, import_shell4.usePreviewVault)();
92
- const { addHistory, clearHistory } = (0, import_shell4.usePreviewHistory)();
93
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_jsx_runtime38.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_shell4.PreviewVaultBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
94
- import_iiif_browser3.IIIFExplorer,
105
+ const vault = (0, import_react13.useMemo)(() => new import_helpers6.Vault(), []);
106
+ const output = (0, import_react13.useMemo)(() => {
107
+ return [
108
+ {
109
+ type: "callback",
110
+ label: "Select",
111
+ supportedTypes: ["Manifest", "Collection"],
112
+ cb: (resource) => props.runCreate({ output: resource }),
113
+ format: { type: "content-state" }
114
+ }
115
+ ];
116
+ }, [props.runCreate]);
117
+ const navigationOptions = (0, import_react13.useMemo)(() => {
118
+ return {
119
+ canCropImage: false,
120
+ canSelectCanvas: false,
121
+ canSelectManifest: true,
122
+ canSelectCollection: true,
123
+ // @todo fix the output so this one works.
124
+ multiSelect: false
125
+ };
126
+ }, []);
127
+ const uiOptions = (0, import_react13.useMemo)(() => {
128
+ return {
129
+ buttonClassName: "bg-me-primary-500 text-white hover:bg-me-primary-600"
130
+ };
131
+ }, []);
132
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_shell4.PreviewVaultBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
133
+ import_iiif_browser3.IIIFBrowser,
95
134
  {
96
- window: false,
97
- hideHeader: true,
98
- outputTypes: ["Manifest", "Collection"],
135
+ debug: true,
136
+ ui: uiOptions,
99
137
  vault,
100
- output: { type: "content-state" },
101
- homepageCollection: import_shell4.HOMEPAGE_COLLECTION,
102
- clearHomepageCollection: clearHistory,
103
- onHistory: addHistory,
104
- outputTargets: [
105
- {
106
- type: "callback",
107
- label: "Select",
108
- cb: (resource) => props.runCreate({ output: resource })
109
- }
110
- ],
111
- allowRemoveEntry: true
138
+ className: "iiif-browser border-none border-t rounded-none h-[70vh] min-h-[60vh] max-h-full max-w-full",
139
+ output,
140
+ navigation: navigationOptions
112
141
  }
113
- ) }) });
142
+ ) });
114
143
  }
115
- var import_iiif_browser3, import_shell4, import_jsx_runtime38;
144
+ var import_helpers6, import_shell4, import_iiif_browser3, import_react13, import_jsx_runtime43;
116
145
  var init_manifest_browser_form_lazy = __esm({
117
146
  "src/Manifest/ManifestBrowserCreator/manifest-browser-form.lazy.tsx"() {
118
147
  "use strict";
119
- import_iiif_browser3 = require("@manifest-editor/iiif-browser");
148
+ import_helpers6 = require("@iiif/helpers");
120
149
  import_shell4 = require("@manifest-editor/shell");
121
- import_jsx_runtime38 = require("react/jsx-runtime");
150
+ import_iiif_browser3 = require("iiif-browser");
151
+ import_react13 = require("react");
152
+ import_jsx_runtime43 = require("react/jsx-runtime");
122
153
  }
123
154
  });
124
155
 
125
156
  // src/index.ts
126
157
  var src_exports = {};
127
158
  __export(src_exports, {
159
+ CreateAudioAnnotationForm: () => CreateAudioAnnotationForm,
160
+ CreateCaptionedImageAnnotation: () => CreateCaptionedImageAnnotation,
161
+ CreateHTMLAnnotation: () => CreateHTMLAnnotation,
162
+ CreateHTMLBodyForm: () => CreateHTMLBodyForm,
163
+ CreateImageServerForm: () => CreateImageServerForm,
164
+ CreateImageServiceAnnotationForm: () => CreateImageServiceAnnotationForm,
165
+ CreateImageUrlAnnotationForm: () => CreateImageUrlAnnotationForm,
166
+ CreateImageUrlForm: () => CreateImageUrlForm,
167
+ CreateImageUrlListForm: () => CreateImageUrlListForm,
168
+ CreatePlaintextForm: () => CreatePlaintextForm,
169
+ CreateThumbnailForm: () => CreateThumbnailForm,
170
+ CreateVideoAnnotationForm: () => CreateVideoAnnotationForm,
171
+ CreateWebPageForm: () => CreateWebPageForm,
172
+ IIIFBrowserCreatorForm: () => IIIFBrowserCreatorForm2,
173
+ ManifestBrowserCreatorForm: () => ManifestBrowserCreatorForm2,
174
+ YouTubeForm: () => YouTubeForm,
128
175
  allCreators: () => allCreators,
129
176
  audioAnnotation: () => audioAnnotation,
130
177
  captionedImageAnnotation: () => captionedImageAnnotation,
178
+ createAudioAnnotation: () => createAudioAnnotation,
179
+ createCaptionedImageAnnotation: () => createCaptionedImageAnnotation,
180
+ createFromIIIFBrowserOutput: () => createFromIIIFBrowserOutput,
181
+ createFromManifestBrowserOutput: () => createFromManifestBrowserOutput,
182
+ createHtmlAnnotation: () => createHtmlAnnotation,
183
+ createHtmlBody: () => createHtmlBody,
184
+ createImageServer: () => createImageServer,
185
+ createImageServiceAnnotation: () => createImageServiceAnnotation,
186
+ createImageUrl: () => createImageUrl,
187
+ createImageUrlAnnotation: () => createImageUrlAnnotation,
188
+ createImageUrlList: () => createImageUrlList,
189
+ createImageUrlListAnnotation: () => createImageUrlListAnnotation,
190
+ createNoBodyAnnotation: () => createNoBodyAnnotation,
191
+ createPlaintext: () => createPlaintext,
192
+ createThumbnail: () => createThumbnail,
193
+ createVideoAnnotation: () => createVideoAnnotation,
194
+ createWebPage: () => createWebPage,
195
+ createYoutubeBody: () => createYoutubeBody,
131
196
  emptyAnnotationPage: () => emptyAnnotationPage,
132
197
  emptyCanvas: () => emptyCanvas,
198
+ getYouTubeId: () => getYouTubeId,
133
199
  htmlAnnotation: () => htmlAnnotation,
134
200
  htmlBodyCreator: () => htmlBodyCreator,
135
201
  iiifBrowserCreator: () => iiifBrowserCreator,
@@ -137,30 +203,27 @@ __export(src_exports, {
137
203
  imageServiceCreator: () => imageServiceCreator,
138
204
  imageUrlAnnotation: () => imageUrlAnnotation,
139
205
  imageUrlCreator: () => imageUrlCreator,
206
+ imageUrlListAnnotation: () => imageUrlListAnnotation,
207
+ imageUrlListCreator: () => imageUrlListCreator,
140
208
  internalCanvas: () => internalCanvas,
141
209
  manifestBrowserCreator: () => manifestBrowserCreator,
142
210
  noBodyAnnotation: () => noBodyAnnotation,
143
211
  plaintextCreator: () => plaintextCreator,
212
+ validateYouTube: () => validateYouTube,
144
213
  videoAnnotation: () => videoAnnotation,
145
214
  webPageCreator: () => webPageCreator,
146
215
  youTubeBodyCreator: () => youTubeBodyCreator
147
216
  });
148
217
  module.exports = __toCommonJS(src_exports);
149
218
 
150
- // src/Annotation/AudioAnnotation/create-audio-annotation.tsx
151
- var import_react2 = require("react");
152
-
153
- // ../ui/atoms/PaddedSidebarContainer.tsx
154
- var import_styled_components = __toESM(require("styled-components"), 1);
155
- var PaddedSidebarContainer = import_styled_components.default.div`
156
- padding: 0 0.7em;
157
- margin: 0.7em 0;
158
- flex: 1;
159
- overflow: visible;
160
- `;
219
+ // src/Annotation/AudioAnnotation/index.tsx
220
+ var import_components2 = require("@manifest-editor/components");
221
+ var import_creator_api = require("@manifest-editor/creator-api");
161
222
 
162
223
  // src/Annotation/AudioAnnotation/create-audio-annotation.tsx
224
+ var import_helpers = require("@iiif/helpers");
163
225
  var import_components = require("@manifest-editor/components");
226
+ var import_editors = require("@manifest-editor/editors");
164
227
 
165
228
  // ../ui/ui/MediaControls/MediaControls.tsx
166
229
  var import_react_iiif_vault = require("react-iiif-vault");
@@ -213,14 +276,14 @@ var VolumeOffIcon = ({ title, ...props }) => /* @__PURE__ */ (0, import_jsx_runt
213
276
  ] });
214
277
 
215
278
  // ../ui/ui/MediaControls/MediaControls.styles.ts
216
- var import_styled_components2 = __toESM(require("styled-components"), 1);
217
- var AudioPlayerContainer = import_styled_components2.default.div`
279
+ var import_styled_components = __toESM(require("styled-components"), 1);
280
+ var AudioPlayerContainer = import_styled_components.default.div`
218
281
  background: #ededed; // Not in variable.
219
282
  display: flex;
220
283
  padding: 0.5em;
221
284
  align-items: center;
222
285
  `;
223
- var BaseButton = import_styled_components2.default.button`
286
+ var BaseButton = import_styled_components.default.button`
224
287
  cursor: pointer;
225
288
  padding: 0.75em 1.5em;
226
289
  font-size: 0.938em;
@@ -232,7 +295,7 @@ var BaseButton = import_styled_components2.default.button`
232
295
  vertical-align: top;
233
296
  white-space: nowrap;
234
297
  `;
235
- var PlayButton = (0, import_styled_components2.default)(BaseButton)`
298
+ var PlayButton = (0, import_styled_components.default)(BaseButton)`
236
299
  width: 2em;
237
300
  height: 2em;
238
301
  overflow: hidden;
@@ -247,19 +310,19 @@ var PlayButton = (0, import_styled_components2.default)(BaseButton)`
247
310
  color: #999;
248
311
  }
249
312
  `;
250
- var TimeDisplay = import_styled_components2.default.div`
313
+ var TimeDisplay = import_styled_components.default.div`
251
314
  margin: 0 1em;
252
315
  font-size: 0.85em;
253
316
  color: #000;
254
317
  `;
255
- var ProgressContainer = import_styled_components2.default.div`
318
+ var ProgressContainer = import_styled_components.default.div`
256
319
  flex: 1 1 0px;
257
320
  height: 6px;
258
321
  display: flex;
259
322
  position: relative;
260
323
  padding: 15px 0;
261
324
  `;
262
- var ProgressCurrent = import_styled_components2.default.div`
325
+ var ProgressCurrent = import_styled_components.default.div`
263
326
  background: #d85680;
264
327
  height: 6px;
265
328
  pointer-events: none;
@@ -269,7 +332,7 @@ var ProgressCurrent = import_styled_components2.default.div`
269
332
  border-radius: 3px;
270
333
  transition: width 200ms;
271
334
  `;
272
- var ProgressBackground = import_styled_components2.default.div`
335
+ var ProgressBackground = import_styled_components.default.div`
273
336
  position: absolute;
274
337
  top: 13px;
275
338
  left: 0;
@@ -279,7 +342,7 @@ var ProgressBackground = import_styled_components2.default.div`
279
342
  pointer-events: none;
280
343
  background: #fff;
281
344
  `;
282
- var SoundButton = (0, import_styled_components2.default)(BaseButton)`
345
+ var SoundButton = (0, import_styled_components.default)(BaseButton)`
283
346
  width: 2em;
284
347
  height: 2em;
285
348
  overflow: hidden;
@@ -289,21 +352,21 @@ var SoundButton = (0, import_styled_components2.default)(BaseButton)`
289
352
  padding: 0;
290
353
  margin: 0;
291
354
  `;
292
- var SoundContainer = import_styled_components2.default.div`
355
+ var SoundContainer = import_styled_components.default.div`
293
356
  display: flex;
294
357
  align-items: center;
295
358
  `;
296
- var VolumeContainer = import_styled_components2.default.div`
359
+ var VolumeContainer = import_styled_components.default.div`
297
360
  width: 0;
298
361
  overflow: hidden;
299
362
  transition: width 500ms;
300
363
  color: #4a473f; // Not in colours
301
364
 
302
- ${(props) => props.$isOpen && import_styled_components2.css`
365
+ ${(props) => props.$isOpen && import_styled_components.css`
303
366
  width: 150px;
304
367
  `}
305
368
  `;
306
- var VolumeSlider = import_styled_components2.default.input.attrs({ type: "range" })`
369
+ var VolumeSlider = import_styled_components.default.input.attrs({ type: "range" })`
307
370
  width: 120px;
308
371
  margin: 0 15px;
309
372
  `;
@@ -311,25 +374,36 @@ var VolumeSlider = import_styled_components2.default.input.attrs({ type: "range"
311
374
  // ../ui/madoc/components/icons/Spinner.tsx
312
375
  var import_jsx_runtime2 = require("react/jsx-runtime");
313
376
  function Spinner(props) {
314
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "1em", height: "1em", viewBox: "0 0 42 42", xmlns: "http://www.w3.org/2000/svg", stroke: "#fff", ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { transform: "translate(2 2)", strokeWidth: 5, fill: "none", fillRule: "evenodd", children: [
315
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { strokeOpacity: 0.5, cx: 18, cy: 18, r: 18 }),
316
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M36 18c0-9.94-8.06-18-18-18", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
317
- "animateTransform",
318
- {
319
- attributeName: "transform",
320
- type: "rotate",
321
- from: "0 18 18",
322
- to: "360 18 18",
323
- dur: "1s",
324
- repeatCount: "indefinite"
325
- }
326
- ) })
327
- ] }) });
377
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
378
+ "svg",
379
+ {
380
+ width: "1em",
381
+ height: "1em",
382
+ viewBox: "0 0 42 42",
383
+ xmlns: "http://www.w3.org/2000/svg",
384
+ stroke: "currentColor",
385
+ ...props,
386
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { transform: "translate(2 2)", strokeWidth: 5, fill: "none", fillRule: "evenodd", children: [
387
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { strokeOpacity: 0.5, cx: 18, cy: 18, r: 18 }),
388
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M36 18c0-9.94-8.06-18-18-18", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
389
+ "animateTransform",
390
+ {
391
+ attributeName: "transform",
392
+ type: "rotate",
393
+ from: "0 18 18",
394
+ to: "360 18 18",
395
+ dur: "1s",
396
+ repeatCount: "indefinite"
397
+ }
398
+ ) })
399
+ ] })
400
+ }
401
+ );
328
402
  }
329
403
 
330
404
  // ../ui/atoms/VisuallHidden/VisuallHidden.tsx
331
- var import_styled_components3 = __toESM(require("styled-components"), 1);
332
- var visuallyHidden = import_styled_components3.css`
405
+ var import_styled_components2 = __toESM(require("styled-components"), 1);
406
+ var visuallyHidden = import_styled_components2.css`
333
407
  clip: rect(1px, 1px, 1px, 1px);
334
408
  clip-path: inset(50%);
335
409
  height: 1px;
@@ -339,7 +413,7 @@ var visuallyHidden = import_styled_components3.css`
339
413
  padding: 0;
340
414
  position: absolute;
341
415
  `;
342
- var VisuallyHiddenLabel = import_styled_components3.default.label`
416
+ var VisuallyHiddenLabel = import_styled_components2.default.label`
343
417
  ${visuallyHidden}
344
418
  `;
345
419
 
@@ -431,93 +505,18 @@ function MediaControls(props) {
431
505
  ] });
432
506
  }
433
507
 
434
- // src/Annotation/AudioAnnotation/create-audio-annotation.tsx
435
- var import_react_iiif_vault2 = require("react-iiif-vault");
436
- var import_helpers = require("@iiif/helpers");
437
- var import_editors = require("@manifest-editor/editors");
438
-
439
- // ../ui/atoms/Button.tsx
440
- var import_styled_components4 = __toESM(require("styled-components"), 1);
441
- var ButtonReset = import_styled_components4.default.button`
442
- border: none;
443
- outline: none;
444
- background-color: transparent;
445
- margin: 0;
446
- padding: 0;
447
- font-size: inherit;
448
- color: inherit;
449
- cursor: pointer;
450
- &:hover {
451
- color: inherit;
452
- }
453
- `;
454
- var Button = import_styled_components4.default.button`
455
- padding: 0.5rem 1rem;
456
- color: ${(props) => props.theme.color.main || "none"};
457
- background-color: ${(props) => props.theme.color.white || "white"};
458
- border-radius: inherit;
459
- border: none;
460
- cursor: pointer;
461
- display: flex;
462
- align-items: center;
463
- font-size: 0.85em;
464
- :disabled {
465
- opacity: 0.65;
466
- cursor: not-allowed;
467
- }
468
-
469
- &:hover {
470
- background: #eee;
471
- }
472
- `;
473
- var SmallButton = (0, import_styled_components4.default)(Button)`
474
- padding: 0.25em ${(props) => props.theme.padding.xs || "0.4em"};
475
- height: unset;
476
- background: none;
477
- `;
478
- var SecondaryButton = (0, import_styled_components4.default)(Button)`
479
- {
480
- padding: 0 ${(props) => props.theme.padding.medium || "1rem"};
481
- color: ${(props) => props.theme.color.main || "#B84C74;"};
482
- background-color: ${(props) => props.theme.color.white || "white"};
483
- border: 1px solid ${(props) => props.theme.color.main || "#B84C74;"};
484
- border-radius: 0.25rem;
485
- cursor: pointer;
486
- height: 2rem;
487
- display: flex;
488
- align-items: center;
489
- white-space: nowrap;
490
- font-size: 0.75rem;
491
-
492
- :disabled {
493
- opacity: 0.65;
494
- cursor: not-allowed;
495
- }
496
- }
497
- `;
498
- var CalltoButton = (0, import_styled_components4.default)(Button)`
499
- padding: 0 ${(props) => props.theme.padding.medium || "1rem"};
500
- color: ${(props) => props.theme.color.white || "white"};
501
- background-color: ${(props) => props.theme.color.main || "#B84C74;"};
502
- border: 1px solid #eee;
503
- border-radius: 0.25rem;
504
- cursor: pointer;
505
- justify-content: center;
506
- display: flex;
507
- align-items: center;
508
- &:hover {
509
- background-color: ${(props) => props.theme.color.mainHover || "#B84C74;"};
510
- }
511
- `;
512
- var ButtonGroup = import_styled_components4.default.div`
513
- display: flex;
514
- flex-direction: row;
515
- flex-wrap: wrap;
516
- align-items: flex-start;
517
- justify-content: ${(props) => props.$right ? "flex-end" : "flex-start"};
508
+ // ../ui/atoms/PaddedSidebarContainer.tsx
509
+ var import_styled_components3 = __toESM(require("styled-components"), 1);
510
+ var PaddedSidebarContainer = import_styled_components3.default.div`
511
+ padding: 0 0.7em;
512
+ margin: 0.7em 0;
513
+ flex: 1;
514
+ overflow: visible;
518
515
  `;
519
516
 
520
517
  // src/Annotation/AudioAnnotation/create-audio-annotation.tsx
518
+ var import_react2 = require("react");
519
+ var import_react_iiif_vault2 = require("react-iiif-vault");
521
520
  var import_jsx_runtime4 = require("react/jsx-runtime");
522
521
  async function createAudioAnnotation(data, ctx) {
523
522
  const annotation = {
@@ -525,7 +524,7 @@ async function createAudioAnnotation(data, ctx) {
525
524
  type: "Annotation"
526
525
  };
527
526
  const targetType = ctx.options.targetType;
528
- const body = await ctx.embed({
527
+ const body = ctx.embed({
529
528
  id: data.url,
530
529
  type: "Sound",
531
530
  format: "audio/mp4",
@@ -542,12 +541,18 @@ async function createAudioAnnotation(data, ctx) {
542
541
  }
543
542
  if (targetType === "Canvas") {
544
543
  const canvasId = ctx.generateId("canvas");
545
- const pageId = ctx.generateId("annotation-page", { id: canvasId, type: "Canvas" });
544
+ const pageId = ctx.generateId("annotation-page", {
545
+ id: canvasId,
546
+ type: "Canvas"
547
+ });
546
548
  const annotationResource = ctx.embed({
547
549
  ...annotation,
548
550
  motivation: "painting",
549
551
  body,
550
- target: { type: "SpecificResource", source: { id: canvasId, type: "Canvas" } }
552
+ target: {
553
+ type: "SpecificResource",
554
+ source: { id: canvasId, type: "Canvas" }
555
+ }
551
556
  });
552
557
  const page = ctx.embed({
553
558
  id: pageId,
@@ -585,7 +590,7 @@ function CreateAudioAnnotationForm(props) {
585
590
  }, [url]);
586
591
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PaddedSidebarContainer, { children: [
587
592
  error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_components.ErrorMessage, { children: error }) : null,
588
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_editors.InputContainer, { children: [
593
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_editors.InputContainer, { $wide: true, children: [
589
594
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_editors.InputLabel, { htmlFor: "audio-url", children: "URL" }),
590
595
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_editors.Input, { type: "text", id: "audio-url", value: url, onChange: (e) => setUrl(e.target.value) })
591
596
  ] }),
@@ -598,28 +603,27 @@ function CreateAudioAnnotationForm(props) {
598
603
  fields: label,
599
604
  onSave: (e) => setLabel(e.toInternationalString())
600
605
  },
601
- url + "__" + duration
606
+ `${url}__${duration}`
602
607
  ) }) : null,
603
608
  url && !error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_iiif_vault2.CanvasPanel.AudioHTML, { media: { url, duration, type: "Sound" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
604
609
  MediaControls,
605
610
  {
606
611
  onError: (error2) => setError(error2),
607
- onDuration: (duration2) => setDuration(duration2)
612
+ onDuration: (duration2) => setDuration(~~duration2)
608
613
  },
609
- url + "__" + duration
610
- ) }, url + "__" + duration) : null,
614
+ `${url}__${duration}`
615
+ ) }, `${url}__${duration}`) : null,
611
616
  duration && !error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_editors.FormFieldWrapper, { children: [
612
617
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_editors.InputLabel, { htmlFor: "duration", children: "Duration" }),
613
618
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_editors.Input, { type: "number", id: "duration", value: duration, onChange: (e) => setDuration(e.target.valueAsNumber) })
614
619
  ] }) : null,
615
- url && !error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { onClick: onSubmit, children: "Add audio" })
620
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_components.ActionButton, { primary: true, large: true, type: "button", onPress: onSubmit, isDisabled: !url || !!error, children: "Add audio" })
616
621
  ] });
617
622
  }
618
623
 
619
624
  // src/Annotation/AudioAnnotation/index.tsx
620
- var import_components2 = require("@manifest-editor/components");
621
625
  var import_jsx_runtime5 = require("react/jsx-runtime");
622
- var audioAnnotation = {
626
+ var audioAnnotation = (0, import_creator_api.defineCreator)({
623
627
  id: "@manifest-editor/audio-annotation",
624
628
  create: createAudioAnnotation,
625
629
  label: "Audio",
@@ -639,12 +643,14 @@ var audioAnnotation = {
639
643
  staticFields: {
640
644
  type: "Annotation"
641
645
  }
642
- };
646
+ });
643
647
 
644
648
  // src/Annotation/CaptionedImageAnnotation/index.tsx
645
- var import_components3 = require("@manifest-editor/components");
649
+ var import_components4 = require("@manifest-editor/components");
650
+ var import_creator_api2 = require("@manifest-editor/creator-api");
646
651
 
647
652
  // src/Annotation/CaptionedImageAnnotation/create-captioned-image-annotation.tsx
653
+ var import_components3 = require("@manifest-editor/components");
648
654
  var import_editors2 = require("@manifest-editor/editors");
649
655
  var import_react3 = require("react");
650
656
  var import_jsx_runtime6 = require("react/jsx-runtime");
@@ -747,18 +753,18 @@ function CreateCaptionedImageAnnotation(props) {
747
753
  }
748
754
  )
749
755
  ] }),
750
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { type: "submit", children: "Create" })
756
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_components3.ActionButton, { primary: true, large: true, type: "submit", children: "Create" })
751
757
  ] }) });
752
758
  }
753
759
 
754
760
  // src/Annotation/CaptionedImageAnnotation/index.tsx
755
761
  var import_jsx_runtime7 = require("react/jsx-runtime");
756
- var captionedImageAnnotation = {
762
+ var captionedImageAnnotation = (0, import_creator_api2.defineCreator)({
757
763
  id: "@manifest-editor/captioned-image-annotation",
758
764
  create: createCaptionedImageAnnotation,
759
765
  label: "Captioned image",
760
766
  summary: "Add an image from a URL with caption",
761
- icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_components3.AddImageIcon, {}),
767
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_components4.AddImageIcon, {}),
762
768
  render(ctx) {
763
769
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CreateCaptionedImageAnnotation, { ...ctx });
764
770
  },
@@ -773,11 +779,17 @@ var captionedImageAnnotation = {
773
779
  staticFields: {
774
780
  type: "Annotation"
775
781
  }
776
- };
782
+ });
783
+
784
+ // src/Annotation/HTMLAnnotation/index.tsx
785
+ var import_components6 = require("@manifest-editor/components");
786
+ var import_creator_api3 = require("@manifest-editor/creator-api");
777
787
 
778
788
  // src/Annotation/HTMLAnnotation/create-html-annotation.tsx
779
- var import_react4 = require("react");
789
+ var import_helpers2 = require("@iiif/helpers");
790
+ var import_components5 = require("@manifest-editor/components");
780
791
  var import_editors3 = require("@manifest-editor/editors");
792
+ var import_react4 = require("react");
781
793
  var import_jsx_runtime8 = require("react/jsx-runtime");
782
794
  async function createHtmlAnnotation(data, ctx) {
783
795
  const annotation = {
@@ -842,37 +854,34 @@ async function createHtmlAnnotation(data, ctx) {
842
854
  }
843
855
  function CreateHTMLAnnotation(props) {
844
856
  const [body, setBody] = (0, import_react4.useState)({ en: [""] });
857
+ const isEmpty = (0, import_helpers2.getValue)(body).trim() === "";
845
858
  const onSubmit = () => {
846
859
  props.runCreate({
847
860
  body
848
861
  });
849
862
  };
850
863
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(PaddedSidebarContainer, { children: [
851
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_editors3.InputContainer, { children: [
852
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_editors3.InputLabel, { children: "HTML Body" }),
853
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
854
- import_editors3.LanguageFieldEditor,
855
- {
856
- focusId: "html-content",
857
- label: "HTML Content",
858
- fields: body,
859
- onSave: (e) => setBody(e.toInternationalString())
860
- }
861
- )
862
- ] }),
863
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { onClick: () => onSubmit(), children: "Create" })
864
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
865
+ import_editors3.LanguageFieldEditor,
866
+ {
867
+ focusId: "html-content",
868
+ label: "HTML Content",
869
+ fields: body,
870
+ onSave: (e) => setBody(e.toInternationalString())
871
+ }
872
+ ),
873
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components5.ActionButton, { primary: true, large: true, type: "button", onPress: onSubmit, isDisabled: isEmpty, children: "Create" })
864
874
  ] });
865
875
  }
866
876
 
867
877
  // src/Annotation/HTMLAnnotation/index.tsx
868
- var import_components4 = require("@manifest-editor/components");
869
878
  var import_jsx_runtime9 = require("react/jsx-runtime");
870
- var htmlAnnotation = {
879
+ var htmlAnnotation = (0, import_creator_api3.defineCreator)({
871
880
  id: "@manifest-editor/html-annotation",
872
881
  create: createHtmlAnnotation,
873
882
  label: "HTML",
874
883
  summary: "HTML annotation",
875
- icon: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_components4.HTMLIcon, {}),
884
+ icon: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_components6.HTMLIcon, {}),
876
885
  render(ctx) {
877
886
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CreateHTMLAnnotation, { ...ctx });
878
887
  },
@@ -887,7 +896,11 @@ var htmlAnnotation = {
887
896
  staticFields: {
888
897
  type: "Annotation"
889
898
  }
890
- };
899
+ });
900
+
901
+ // src/Annotation/ImageServiceAnnotation/index.tsx
902
+ var import_components8 = require("@manifest-editor/components");
903
+ var import_creator_api5 = require("@manifest-editor/creator-api");
891
904
 
892
905
  // src/side-effects/reposition-multiple-images.ts
893
906
  var import_image_3 = require("@iiif/parser/image-3");
@@ -912,7 +925,7 @@ var repositionMultipleImages = {
912
925
  if (!annoPage) {
913
926
  return;
914
927
  }
915
- if (annoPage.items.length < 2) {
928
+ if (annoPage.items.length < 2 && !canvas.behavior.includes("multi-image")) {
916
929
  return;
917
930
  }
918
931
  const bodies = vault.get(fullAnno.body);
@@ -923,10 +936,18 @@ var repositionMultipleImages = {
923
936
  if (imageService) {
924
937
  if (imageService.width && imageService.height) {
925
938
  if (imageService.width !== body.width) {
926
- vault.modifyEntityField({ id: body.id, type: "ContentResource" }, "width", imageService.width);
939
+ vault.modifyEntityField(
940
+ { id: body.id, type: "ContentResource" },
941
+ "width",
942
+ imageService.width
943
+ );
927
944
  }
928
945
  if (imageService.height !== body.height) {
929
- vault.modifyEntityField({ id: body.id, type: "ContentResource" }, "height", imageService.height);
946
+ vault.modifyEntityField(
947
+ { id: body.id, type: "ContentResource" },
948
+ "height",
949
+ imageService.height
950
+ );
930
951
  }
931
952
  }
932
953
  }
@@ -970,6 +991,9 @@ var resizeResourceToEmptyCanvas = {
970
991
  if (!canvas.items) {
971
992
  return;
972
993
  }
994
+ if (canvas.behavior.includes("multi-image")) {
995
+ return;
996
+ }
973
997
  const annoPage = vault.get(canvas.items[0]);
974
998
  if (!annoPage) {
975
999
  return;
@@ -1027,6 +1051,9 @@ var resizeToFitService = {
1027
1051
  if (!canvas.items) {
1028
1052
  return;
1029
1053
  }
1054
+ if (canvas.behavior.includes("multi-image")) {
1055
+ return;
1056
+ }
1030
1057
  const annoPage = vault.get(canvas.items[0]);
1031
1058
  if (!annoPage) {
1032
1059
  return;
@@ -1042,10 +1069,18 @@ var resizeToFitService = {
1042
1069
  if (imageService) {
1043
1070
  if (imageService.width && imageService.height) {
1044
1071
  if (imageService.width !== body.width) {
1045
- vault.modifyEntityField({ id: body.id, type: "ContentResource" }, "width", imageService.width);
1072
+ vault.modifyEntityField(
1073
+ { id: body.id, type: "ContentResource" },
1074
+ "width",
1075
+ imageService.width
1076
+ );
1046
1077
  }
1047
1078
  if (imageService.height !== body.height) {
1048
- vault.modifyEntityField({ id: body.id, type: "ContentResource" }, "height", imageService.height);
1079
+ vault.modifyEntityField(
1080
+ { id: body.id, type: "ContentResource" },
1081
+ "height",
1082
+ imageService.height
1083
+ );
1049
1084
  }
1050
1085
  }
1051
1086
  }
@@ -1053,12 +1088,26 @@ var resizeToFitService = {
1053
1088
  }
1054
1089
  };
1055
1090
 
1091
+ // src/Annotation/ImageServiceAnnotation/create-service-annotation.tsx
1092
+ var import_creator_api4 = require("@manifest-editor/creator-api");
1093
+
1056
1094
  // src/ContentResource/ImageServiceCreator/create-image-service.tsx
1057
1095
  var import_image_32 = require("@iiif/parser/image-3");
1096
+ var import_components7 = require("@manifest-editor/components");
1058
1097
  var import_editors5 = require("@manifest-editor/editors");
1098
+ var import_react5 = require("react");
1099
+ var import_react_error_boundary = require("react-error-boundary");
1100
+ var import_react_iiif_vault3 = require("react-iiif-vault");
1059
1101
  var import_jsx_runtime10 = require("react/jsx-runtime");
1060
1102
  async function createImageServer(data, ctx) {
1061
- const request = (0, import_image_32.createImageServiceRequest)(data.service);
1103
+ const service = { ...data.service };
1104
+ if (service["@id"]) {
1105
+ service.id = service["@id"];
1106
+ }
1107
+ if (service["@type"]) {
1108
+ service.type = service["@type"];
1109
+ }
1110
+ const request = (0, import_image_32.createImageServiceRequest)(service);
1062
1111
  const imageId = (0, import_image_32.imageServiceRequestToString)({
1063
1112
  identifier: request.identifier,
1064
1113
  server: request.server,
@@ -1083,37 +1132,64 @@ async function createImageServer(data, ctx) {
1083
1132
  id: imageId,
1084
1133
  type: "Image",
1085
1134
  format: data.format || "image/jpeg",
1086
- height: data.height || data.service.height,
1087
- width: data.width || data.service.width,
1135
+ height: data.height || service.height,
1136
+ width: data.width || service.width,
1088
1137
  service: data.embedService === false ? void 0 : [data.service]
1089
1138
  });
1090
1139
  return resource;
1091
1140
  }
1141
+ function getCanonicalUrl(url) {
1142
+ return url.endsWith("default.jpg") ? (0, import_image_32.imageServiceRequestToString)({
1143
+ ...(0, import_image_32.parseImageServiceRequest)(url),
1144
+ type: "info"
1145
+ }) : (0, import_image_32.canonicalServiceUrl)(url);
1146
+ }
1092
1147
  function CreateImageServerForm(props) {
1148
+ const [url, setUrl] = (0, import_react5.useState)("");
1093
1149
  const onSubmit = (e) => {
1094
1150
  e.preventDefault();
1095
1151
  const data = new FormData(e.target);
1096
1152
  const formData = Object.fromEntries(data.entries());
1097
- const url = formData.url;
1098
- if (url) {
1099
- const canon = (0, import_image_32.canonicalServiceUrl)(url);
1100
- fetch(canon).then((r) => r.json()).then((service) => {
1101
- if (service["@id"]) {
1102
- service.id = service["@id"];
1103
- }
1104
- if (service["@type"]) {
1105
- service.type = service["@type"];
1106
- }
1153
+ const url2 = formData.url;
1154
+ if (url2) {
1155
+ const info = getCanonicalUrl(url2);
1156
+ if (!info) {
1157
+ throw new Error("Invalid image service request");
1158
+ }
1159
+ fetch(info).then((r) => r.json()).then((service) => {
1107
1160
  props.runCreate({ url: formData.url, service });
1108
1161
  });
1109
1162
  }
1110
1163
  };
1111
1164
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PaddedSidebarContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit, children: [
1112
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_editors5.InputContainer, { $wide: true, children: [
1165
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex gap-2 items-center", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_editors5.InputContainer, { $wide: true, children: [
1113
1166
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_editors5.InputLabel, { htmlFor: "id", children: "Link to image service" }),
1114
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_editors5.Input, { id: "url", name: "url", defaultValue: "" })
1115
- ] }),
1116
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "submit", children: "Create" })
1167
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1168
+ import_editors5.Input,
1169
+ {
1170
+ id: "url",
1171
+ name: "url",
1172
+ defaultValue: "",
1173
+ onPaste: (e) => {
1174
+ const text = e.clipboardData.getData("text/plain");
1175
+ setUrl(text ? getCanonicalUrl(text) : "");
1176
+ },
1177
+ onBlur: (e) => setUrl(e.currentTarget.value ? getCanonicalUrl(e.currentTarget.value) : "")
1178
+ }
1179
+ )
1180
+ ] }) }),
1181
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative flex z-0 my-5 h-96 min-h-0 min-w-0 overflow-hidden bg-gray-200 rounded items-center justify-center", children: url.trim() ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_error_boundary.ErrorBoundary, { fallbackRender: () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { children: "Invalid service" }), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1182
+ import_react_iiif_vault3.ImageService,
1183
+ {
1184
+ src: url,
1185
+ fluid: true,
1186
+ errorFallback: () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { children: "Invalid service" }),
1187
+ background: "rgb(229,231,235)",
1188
+ className: "h-full w-full",
1189
+ containerProps: { className: "w-full h-full z-10" }
1190
+ }
1191
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-grey-600", children: "Preview" }) }),
1192
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_components7.ActionButton, { primary: true, large: true, type: "submit", isDisabled: !url, children: "Create" }) })
1117
1193
  ] }) });
1118
1194
  }
1119
1195
 
@@ -1125,7 +1201,8 @@ async function createImageServiceAnnotation(data, ctx) {
1125
1201
  type: "Annotation"
1126
1202
  };
1127
1203
  const targetType = ctx.options.targetType;
1128
- const resource = await ctx.create("@manifest-editor/image-service-creator", data, {
1204
+ const createImage = (0, import_creator_api4.creatorHelper)(ctx, "Annotation", "body", "@manifest-editor/image-service-creator");
1205
+ const resource = await createImage(data, {
1129
1206
  parent: { resource: annotation, property: "body" }
1130
1207
  });
1131
1208
  if (targetType === "Annotation") {
@@ -1138,24 +1215,39 @@ async function createImageServiceAnnotation(data, ctx) {
1138
1215
  }
1139
1216
  if (targetType === "Canvas") {
1140
1217
  const canvasId = ctx.generateId("canvas");
1141
- const pageId = ctx.generateId("annotation-page", { id: canvasId, type: "Canvas" });
1218
+ const pageId = ctx.generateId("annotation-page", {
1219
+ id: canvasId,
1220
+ type: "Canvas"
1221
+ });
1142
1222
  const annotationResource = ctx.embed({
1143
1223
  ...annotation,
1144
1224
  motivation: "painting",
1145
1225
  body: [resource],
1146
- target: { type: "SpecificResource", source: { id: canvasId, type: "Canvas" } }
1226
+ target: {
1227
+ type: "SpecificResource",
1228
+ source: { id: canvasId, type: "Canvas" }
1229
+ }
1147
1230
  });
1148
1231
  const page = ctx.embed({
1149
1232
  id: pageId,
1150
1233
  type: "AnnotationPage",
1151
1234
  items: [annotationResource]
1152
1235
  });
1236
+ let thumbnail = void 0;
1237
+ if (data.service?.sizes) {
1238
+ const createThumbnail2 = (0, import_creator_api4.creatorHelper)(ctx, "Canvas", "thumbnail", "@manifest-editor/thumbnail-image");
1239
+ thumbnail = await createThumbnail2({
1240
+ service: data.service,
1241
+ width: data.thumbnailSize || 400
1242
+ });
1243
+ }
1153
1244
  return ctx.embed({
1154
1245
  id: canvasId,
1155
1246
  type: "Canvas",
1156
1247
  label: data.label || { en: ["Untitled canvas"] },
1157
1248
  height: resource.resource.height || 1e3,
1158
1249
  width: resource.resource.width || 1e3,
1250
+ thumbnail: thumbnail ? [thumbnail] : void 0,
1159
1251
  items: [page]
1160
1252
  });
1161
1253
  }
@@ -1165,16 +1257,15 @@ function CreateImageServiceAnnotationForm(props) {
1165
1257
  }
1166
1258
 
1167
1259
  // src/Annotation/ImageServiceAnnotation/index.tsx
1168
- var import_components5 = require("@manifest-editor/components");
1169
1260
  var import_jsx_runtime12 = require("react/jsx-runtime");
1170
- var imageServiceAnnotation = {
1261
+ var imageServiceAnnotation = (0, import_creator_api5.defineCreator)({
1171
1262
  id: "@manifest-editor/image-service-annotation",
1172
1263
  create: createImageServiceAnnotation,
1173
1264
  label: "IIIF Image",
1174
1265
  dependencies: ["@manifest-editor/image-service-creator"],
1175
1266
  summary: "IIIF Image service",
1176
1267
  tags: ["image", "image-service"],
1177
- icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components5.IIIFLogo, { style: { padding: 10 } }),
1268
+ icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.IIIFLogo, { style: { padding: 10 } }),
1178
1269
  render(ctx) {
1179
1270
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CreateImageServiceAnnotationForm, { ...ctx });
1180
1271
  },
@@ -1189,9 +1280,17 @@ var imageServiceAnnotation = {
1189
1280
  staticFields: {
1190
1281
  type: "Annotation"
1191
1282
  }
1192
- };
1283
+ });
1284
+
1285
+ // src/Annotation/ImageUrlAnnotation/index.tsx
1286
+ var import_components10 = require("@manifest-editor/components");
1287
+ var import_creator_api7 = require("@manifest-editor/creator-api");
1288
+
1289
+ // src/Annotation/ImageUrlAnnotation/create-image-url-annotation.tsx
1290
+ var import_creator_api6 = require("@manifest-editor/creator-api");
1193
1291
 
1194
1292
  // src/ContentResource/ImageUrlCreator/create-image-url.tsx
1293
+ var import_components9 = require("@manifest-editor/components");
1195
1294
  var import_editors6 = require("@manifest-editor/editors");
1196
1295
  var import_shell = require("@manifest-editor/shell");
1197
1296
  var import_jsx_runtime13 = require("react/jsx-runtime");
@@ -1226,7 +1325,7 @@ function CreateImageUrlForm(props) {
1226
1325
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_editors6.InputLabel, { htmlFor: "id", children: "Link to Image" }),
1227
1326
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_editors6.Input, { id: "url", name: "url", defaultValue: "" })
1228
1327
  ] }),
1229
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { type: "submit", children: "Create" })
1328
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.ActionButton, { primary: true, large: true, type: "submit", children: "Create" })
1230
1329
  ] }) });
1231
1330
  }
1232
1331
 
@@ -1238,25 +1337,32 @@ async function createImageUrlAnnotation(data, ctx) {
1238
1337
  type: "Annotation"
1239
1338
  };
1240
1339
  const targetType = ctx.options.targetType;
1241
- const resource = await ctx.create("@manifest-editor/image-url-creator", data, {
1340
+ const createImage = (0, import_creator_api6.creatorHelper)(ctx, "Annotation", "body", "@manifest-editor/image-url-creator");
1341
+ const resource = await createImage(data, {
1242
1342
  parent: { resource: annotation, property: "body" }
1243
1343
  });
1244
1344
  if (targetType === "Annotation") {
1245
- return {
1345
+ return ctx.embed({
1246
1346
  ...annotation,
1247
1347
  body: [resource],
1248
1348
  motivation: data.motivation || "painting",
1249
1349
  target: ctx.getTarget()
1250
- };
1350
+ });
1251
1351
  }
1252
1352
  if (targetType === "Canvas") {
1253
1353
  const canvasId = ctx.generateId("canvas");
1254
- const pageId = ctx.generateId("annotation-page", { id: canvasId, type: "Canvas" });
1354
+ const pageId = ctx.generateId("annotation-page", {
1355
+ id: canvasId,
1356
+ type: "Canvas"
1357
+ });
1255
1358
  const annotationResource = ctx.embed({
1256
1359
  ...annotation,
1257
1360
  motivation: "painting",
1258
1361
  body: [resource],
1259
- target: { type: "SpecificResource", source: { id: canvasId, type: "Canvas" } }
1362
+ target: {
1363
+ type: "SpecificResource",
1364
+ source: { id: canvasId, type: "Canvas" }
1365
+ }
1260
1366
  });
1261
1367
  const page = ctx.embed({
1262
1368
  id: pageId,
@@ -1272,22 +1378,22 @@ async function createImageUrlAnnotation(data, ctx) {
1272
1378
  items: [page]
1273
1379
  });
1274
1380
  }
1381
+ throw new Error("Unsupported target type");
1275
1382
  }
1276
1383
  function CreateImageUrlAnnotationForm(props) {
1277
1384
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CreateImageUrlForm, { ...props });
1278
1385
  }
1279
1386
 
1280
1387
  // src/Annotation/ImageUrlAnnotation/index.tsx
1281
- var import_components6 = require("@manifest-editor/components");
1282
1388
  var import_jsx_runtime15 = require("react/jsx-runtime");
1283
- var imageUrlAnnotation = {
1389
+ var imageUrlAnnotation = (0, import_creator_api7.defineCreator)({
1284
1390
  id: "@manifest-editor/image-url-annotation",
1285
1391
  create: createImageUrlAnnotation,
1286
1392
  label: "Image",
1287
1393
  dependencies: ["@manifest-editor/image-url-creator"],
1288
1394
  summary: "Image from URL",
1289
1395
  tags: ["image"],
1290
- icon: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_components6.AddImageIcon, {}),
1396
+ icon: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_components10.AddImageIcon, {}),
1291
1397
  render(ctx) {
1292
1398
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CreateImageUrlAnnotationForm, { ...ctx });
1293
1399
  },
@@ -1302,17 +1408,89 @@ var imageUrlAnnotation = {
1302
1408
  staticFields: {
1303
1409
  type: "Annotation"
1304
1410
  }
1305
- };
1411
+ });
1306
1412
 
1307
- // src/Annotation/NoBodyAnnotation/index.tsx
1308
- var import_components7 = require("@manifest-editor/components");
1413
+ // src/Annotation/ImageUrlListAnnotation/index.tsx
1414
+ var import_components12 = require("@manifest-editor/components");
1415
+ var import_creator_api10 = require("@manifest-editor/creator-api");
1416
+
1417
+ // src/ContentResource/ImageUrlListCreator/create-image-url-list.tsx
1418
+ var import_components11 = require("@manifest-editor/components");
1419
+ var import_creator_api8 = require("@manifest-editor/creator-api");
1309
1420
  var import_jsx_runtime16 = require("react/jsx-runtime");
1310
- var noBodyAnnotation = {
1421
+ async function createImageUrlList(payload, ctx) {
1422
+ const items = [];
1423
+ const createImage = (0, import_creator_api8.creatorHelper)(ctx, "Annotation", "body", "@manifest-editor/image-url-creator");
1424
+ for (const image of payload.images) {
1425
+ items.push(await createImage(image, ctx.options));
1426
+ }
1427
+ return items;
1428
+ }
1429
+ function CreateImageUrlListForm(props) {
1430
+ const onSubmit = (e) => {
1431
+ e.preventDefault();
1432
+ const data = new FormData(e.target);
1433
+ const formData = Object.fromEntries(data.entries());
1434
+ if (formData.urls) {
1435
+ props.runCreate({ images: formData.urls.split("\n").map((url) => ({ url })) });
1436
+ }
1437
+ };
1438
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PaddedSidebarContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_components11.Form.Form, { onSubmit, children: [
1439
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_components11.Form.InputContainer, { className: "mb-4", children: [
1440
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Form.Label, { children: "Enter a list of URLs (one per line)" }),
1441
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Form.TextArea, { name: "urls", rows: "10" })
1442
+ ] }),
1443
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.ActionButton, { primary: true, large: true, type: "submit", children: "Create" })
1444
+ ] }) });
1445
+ }
1446
+
1447
+ // src/Annotation/ImageUrlListAnnotation/create-image-url-list-annotation.tsx
1448
+ var import_creator_api9 = require("@manifest-editor/creator-api");
1449
+ async function createImageUrlListAnnotation(payload, ctx) {
1450
+ const items = [];
1451
+ const createAnnotation = (0, import_creator_api9.creatorHelper)(ctx, "AnnotationPage", "items", "@manifest-editor/image-url-annotation");
1452
+ for (const image of payload.images) {
1453
+ items.push(await createAnnotation(image, ctx.options));
1454
+ }
1455
+ return items;
1456
+ }
1457
+
1458
+ // src/Annotation/ImageUrlListAnnotation/index.tsx
1459
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1460
+ var imageUrlListAnnotation = (0, import_creator_api10.defineCreator)({
1461
+ id: "@manifest-editor/image-url-list-annotation",
1462
+ create: createImageUrlListAnnotation,
1463
+ label: "List of Images",
1464
+ dependencies: ["@manifest-editor/image-url-annotation"],
1465
+ summary: "List of Images from URLs",
1466
+ tags: ["image"],
1467
+ icon: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_components12.ImageListIcon, {}),
1468
+ render(ctx) {
1469
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CreateImageUrlListForm, { ...ctx });
1470
+ },
1471
+ resourceType: "Annotation",
1472
+ resourceFields: ["id", "type", "motivation", "body", "target"],
1473
+ additionalTypes: ["Canvas"],
1474
+ supports: {
1475
+ parentTypes: ["AnnotationPage", "Manifest"],
1476
+ parentFields: ["items"]
1477
+ },
1478
+ sideEffects: [resizeToFitService, resizeResourceToEmptyCanvas, repositionMultipleImages],
1479
+ staticFields: {
1480
+ type: "Annotation"
1481
+ }
1482
+ });
1483
+
1484
+ // src/Annotation/NoBodyAnnotation/index.tsx
1485
+ var import_components13 = require("@manifest-editor/components");
1486
+ var import_creator_api11 = require("@manifest-editor/creator-api");
1487
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1488
+ var noBodyAnnotation = (0, import_creator_api11.defineCreator)({
1311
1489
  id: "@manifest-editor/no-body-annotation",
1312
1490
  create: createNoBodyAnnotation,
1313
1491
  label: "Annotation without body",
1314
1492
  summary: "Add an annotation that only has motivation and target",
1315
- icon: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components7.EmptyCanvasIcon, {}),
1493
+ icon: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_components13.EmptyCanvasIcon, {}),
1316
1494
  resourceType: "Annotation",
1317
1495
  resourceFields: ["id", "type", "motivation", "target"],
1318
1496
  supports: {
@@ -1325,7 +1503,7 @@ var noBodyAnnotation = {
1325
1503
  staticFields: {
1326
1504
  type: "Annotation"
1327
1505
  }
1328
- };
1506
+ });
1329
1507
  function createNoBodyAnnotation(data, ctx) {
1330
1508
  return ctx.embed({
1331
1509
  id: ctx.generateId("annotation"),
@@ -1336,15 +1514,18 @@ function createNoBodyAnnotation(data, ctx) {
1336
1514
  });
1337
1515
  }
1338
1516
 
1517
+ // src/Annotation/VideoAnnotation/index.tsx
1518
+ var import_components15 = require("@manifest-editor/components");
1519
+ var import_creator_api12 = require("@manifest-editor/creator-api");
1520
+
1339
1521
  // src/Annotation/VideoAnnotation/create-video-annotation.tsx
1340
- var import_helpers2 = require("@iiif/helpers");
1522
+ var import_helpers3 = require("@iiif/helpers");
1523
+ var import_components14 = require("@manifest-editor/components");
1341
1524
  var import_editors7 = require("@manifest-editor/editors");
1342
- var import_components8 = require("@manifest-editor/components");
1343
- var import_react5 = require("react");
1344
1525
 
1345
1526
  // ../ui/ui/VideoPlayer/VideoPlayer.tsx
1346
- var import_react_iiif_vault3 = require("react-iiif-vault");
1347
- var import_jsx_runtime17 = require("react/jsx-runtime");
1527
+ var import_react_iiif_vault4 = require("react-iiif-vault");
1528
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1348
1529
  function VideoPlayer({
1349
1530
  media,
1350
1531
  onError,
@@ -1352,9 +1533,9 @@ function VideoPlayer({
1352
1533
  onDuration,
1353
1534
  onDimensions
1354
1535
  }) {
1355
- const [{ element, currentTime, progress }, state, actions] = (0, import_react_iiif_vault3.useSimpleMediaPlayer)({ duration });
1356
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1357
- import_react_iiif_vault3.MediaPlayerProvider,
1536
+ const [{ element, currentTime, progress }, state, actions] = (0, import_react_iiif_vault4.useSimpleMediaPlayer)({ duration });
1537
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1538
+ import_react_iiif_vault4.MediaPlayerProvider,
1358
1539
  {
1359
1540
  element,
1360
1541
  state,
@@ -1362,7 +1543,7 @@ function VideoPlayer({
1362
1543
  currentTime,
1363
1544
  progress,
1364
1545
  children: [
1365
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1546
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1366
1547
  "div",
1367
1548
  {
1368
1549
  style: {
@@ -1370,24 +1551,25 @@ function VideoPlayer({
1370
1551
  aspectRatio: `${media.width}/${media.height}`,
1371
1552
  position: "relative"
1372
1553
  },
1373
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_iiif_vault3.CanvasPanel.VideoHTML, { element, media, playPause: actions.playPause })
1554
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_iiif_vault4.CanvasPanel.VideoHTML, { element, media, playPause: actions.playPause })
1374
1555
  }
1375
1556
  ),
1376
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MediaControls, { onError, onDuration, onDimensions })
1557
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MediaControls, { onError, onDuration, onDimensions })
1377
1558
  ]
1378
1559
  }
1379
1560
  );
1380
1561
  }
1381
1562
 
1382
1563
  // src/Annotation/VideoAnnotation/create-video-annotation.tsx
1383
- var import_jsx_runtime18 = require("react/jsx-runtime");
1564
+ var import_react6 = require("react");
1565
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1384
1566
  async function createVideoAnnotation(data, ctx) {
1385
1567
  const annotation = {
1386
1568
  id: ctx.generateId("annotation"),
1387
1569
  type: "Annotation"
1388
1570
  };
1389
1571
  const targetType = ctx.options.targetType;
1390
- const body = await ctx.embed({
1572
+ const body = ctx.embed({
1391
1573
  id: data.url,
1392
1574
  type: "Video",
1393
1575
  format: "video/mp4",
@@ -1398,7 +1580,7 @@ async function createVideoAnnotation(data, ctx) {
1398
1580
  if (targetType === "Annotation") {
1399
1581
  return ctx.embed({
1400
1582
  ...annotation,
1401
- label: (0, import_helpers2.getValue)(data.label) && data.label,
1583
+ label: (0, import_helpers3.getValue)(data.label) && data.label,
1402
1584
  motivation: data.motivation || ctx.options.initialData?.motivation || "painting",
1403
1585
  body,
1404
1586
  target: ctx.getTarget()
@@ -1406,12 +1588,18 @@ async function createVideoAnnotation(data, ctx) {
1406
1588
  }
1407
1589
  if (targetType === "Canvas") {
1408
1590
  const canvasId = ctx.generateId("canvas");
1409
- const pageId = ctx.generateId("annotation-page", { id: canvasId, type: "Canvas" });
1591
+ const pageId = ctx.generateId("annotation-page", {
1592
+ id: canvasId,
1593
+ type: "Canvas"
1594
+ });
1410
1595
  const annotationResource = ctx.embed({
1411
1596
  ...annotation,
1412
1597
  motivation: "painting",
1413
1598
  body,
1414
- target: { type: "SpecificResource", source: { id: canvasId, type: "Canvas" } }
1599
+ target: {
1600
+ type: "SpecificResource",
1601
+ source: { id: canvasId, type: "Canvas" }
1602
+ }
1415
1603
  });
1416
1604
  const page = ctx.embed({
1417
1605
  id: pageId,
@@ -1430,12 +1618,12 @@ async function createVideoAnnotation(data, ctx) {
1430
1618
  }
1431
1619
  }
1432
1620
  function CreateVideoAnnotationForm(props) {
1433
- const [url, setUrl] = (0, import_react5.useState)("");
1434
- const [duration, setDuration] = (0, import_react5.useState)(0);
1435
- const [width, setWidth] = (0, import_react5.useState)(0);
1436
- const [height, setHeight] = (0, import_react5.useState)(0);
1437
- const [error, setError] = (0, import_react5.useState)("");
1438
- const [label, setLabel] = (0, import_react5.useState)({ en: [""] });
1621
+ const [url, setUrl] = (0, import_react6.useState)("");
1622
+ const [duration, setDuration] = (0, import_react6.useState)(0);
1623
+ const [width, setWidth] = (0, import_react6.useState)(0);
1624
+ const [height, setHeight] = (0, import_react6.useState)(0);
1625
+ const [error, setError] = (0, import_react6.useState)("");
1626
+ const [label, setLabel] = (0, import_react6.useState)({ en: [""] });
1439
1627
  const onSubmit = () => {
1440
1628
  props.runCreate({
1441
1629
  url,
@@ -1445,7 +1633,7 @@ function CreateVideoAnnotationForm(props) {
1445
1633
  height
1446
1634
  });
1447
1635
  };
1448
- (0, import_react5.useEffect)(() => {
1636
+ (0, import_react6.useEffect)(() => {
1449
1637
  setError("");
1450
1638
  setDuration(0);
1451
1639
  if (url) {
@@ -1453,13 +1641,13 @@ function CreateVideoAnnotationForm(props) {
1453
1641
  setLabel({ en: [labelFromUrl || ""] });
1454
1642
  }
1455
1643
  }, [url]);
1456
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(PaddedSidebarContainer, { children: [
1457
- error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_components8.ErrorMessage, { children: error }) : null,
1458
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_editors7.InputContainer, { children: [
1459
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_editors7.InputLabel, { htmlFor: "video-url", children: "URL" }),
1460
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_editors7.Input, { type: "text", id: "video-url", value: url, onChange: (e) => setUrl(e.target.value) })
1644
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(PaddedSidebarContainer, { children: [
1645
+ error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_components14.ErrorMessage, { children: error }) : null,
1646
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_editors7.InputContainer, { $wide: true, children: [
1647
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_editors7.InputLabel, { htmlFor: "video-url", children: "URL" }),
1648
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_editors7.Input, { type: "text", id: "video-url", value: url, onChange: (e) => setUrl(e.target.value) })
1461
1649
  ] }),
1462
- url && !error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1650
+ url && !error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1463
1651
  import_editors7.LanguageFieldEditor,
1464
1652
  {
1465
1653
  containerId: "label",
@@ -1468,9 +1656,9 @@ function CreateVideoAnnotationForm(props) {
1468
1656
  fields: label,
1469
1657
  onSave: (e) => setLabel(e.toInternationalString())
1470
1658
  },
1471
- url + "__" + duration
1659
+ `${url}__${duration}`
1472
1660
  ) }) : null,
1473
- url && !error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1661
+ url && !error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "mb-4 bg-black", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1474
1662
  VideoPlayer,
1475
1663
  {
1476
1664
  duration,
@@ -1488,8 +1676,8 @@ function CreateVideoAnnotationForm(props) {
1488
1676
  setHeight(h || 0);
1489
1677
  }
1490
1678
  }
1491
- ) : null,
1492
- !error && (duration || width || height) ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_editors7.InputContainer, { $wide: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1679
+ ) }) : null,
1680
+ !error && (duration || width || height) ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_editors7.InputContainer, { $wide: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1493
1681
  import_editors7.DimensionsTriplet,
1494
1682
  {
1495
1683
  widthId: "width",
@@ -1503,21 +1691,20 @@ function CreateVideoAnnotationForm(props) {
1503
1691
  changeDuration: (v) => setDuration(v)
1504
1692
  }
1505
1693
  ) }) : null,
1506
- url && !error && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Button, { onClick: onSubmit, children: "Add video" })
1694
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_components14.ActionButton, { primary: true, large: true, type: "button", onPress: onSubmit, isDisabled: !url || !!error, children: "Add video" })
1507
1695
  ] });
1508
1696
  }
1509
1697
 
1510
1698
  // src/Annotation/VideoAnnotation/index.tsx
1511
- var import_components9 = require("@manifest-editor/components");
1512
- var import_jsx_runtime19 = require("react/jsx-runtime");
1513
- var videoAnnotation = {
1699
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1700
+ var videoAnnotation = (0, import_creator_api12.defineCreator)({
1514
1701
  id: "@manifest-editor/video-annotation",
1515
1702
  create: createVideoAnnotation,
1516
1703
  label: "Video",
1517
1704
  summary: "Video annotation",
1518
- icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_components9.VideoIcon, {}),
1705
+ icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_components15.VideoIcon, {}),
1519
1706
  render(ctx) {
1520
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CreateVideoAnnotationForm, { ...ctx });
1707
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CreateVideoAnnotationForm, { ...ctx });
1521
1708
  },
1522
1709
  resourceType: "Annotation",
1523
1710
  resourceFields: ["id", "type", "motivation", "body", "target"],
@@ -1530,11 +1717,14 @@ var videoAnnotation = {
1530
1717
  staticFields: {
1531
1718
  type: "Annotation"
1532
1719
  }
1533
- };
1720
+ });
1721
+
1722
+ // src/AnnotationPage/EmptyAnnotationPage/index.tsx
1723
+ var import_creator_api13 = require("@manifest-editor/creator-api");
1534
1724
 
1535
1725
  // ../ui/icons/ThumbnailStripIcon.tsx
1536
- var import_jsx_runtime20 = require("react/jsx-runtime");
1537
- var ThumbnailStripIcon = () => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1726
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1727
+ var ThumbnailStripIcon = () => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1538
1728
  "svg",
1539
1729
  {
1540
1730
  xmlns: "http://www.w3.org/2000/svg",
@@ -1543,21 +1733,28 @@ var ThumbnailStripIcon = () => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1543
1733
  width: "24px",
1544
1734
  fill: "#000000",
1545
1735
  transform: "scale(-1, 1)",
1546
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("g", { children: [
1547
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("rect", { fill: "none", height: "24", width: "24" }),
1548
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("path", { d: "M16,20H2V4h14V20z M18,8h4V4h-4V8z M18,20h4v-4h-4V20z M18,14h4v-4h-4V14z" })
1736
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("g", { children: [
1737
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("rect", { fill: "none", height: "24", width: "24" }),
1738
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M16,20H2V4h14V20z M18,8h4V4h-4V8z M18,20h4v-4h-4V20z M18,14h4v-4h-4V14z" })
1549
1739
  ] })
1550
1740
  }
1551
1741
  );
1552
1742
 
1553
1743
  // src/AnnotationPage/EmptyAnnotationPage/index.tsx
1554
- var import_jsx_runtime21 = require("react/jsx-runtime");
1555
- var emptyAnnotationPage = {
1744
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1745
+ var emptyAnnotationPage = (0, import_creator_api13.defineCreator)({
1556
1746
  id: "@manifest-editor/empty-annotation-page",
1557
- create: createEmptyAnnotationPage,
1747
+ create: (data, ctx) => {
1748
+ return ctx.embed({
1749
+ id: ctx.generateId("annotations"),
1750
+ label: data.label,
1751
+ type: "AnnotationPage",
1752
+ items: []
1753
+ });
1754
+ },
1558
1755
  label: "Empty annotation page",
1559
1756
  summary: "AnnotationPage with nothing",
1560
- icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ThumbnailStripIcon, {}),
1757
+ icon: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ThumbnailStripIcon, {}),
1561
1758
  resourceType: "AnnotationPage",
1562
1759
  resourceFields: ["id", "type", "items"],
1563
1760
  supports: {
@@ -1568,51 +1765,45 @@ var emptyAnnotationPage = {
1568
1765
  Range: ["annotations"]
1569
1766
  }
1570
1767
  }
1571
- };
1572
- async function createEmptyAnnotationPage(data, ctx) {
1573
- return ctx.embed({
1574
- id: ctx.generateId("annotations"),
1575
- label: data.label,
1576
- type: "AnnotationPage",
1577
- items: []
1578
- });
1579
- }
1768
+ });
1580
1769
 
1581
1770
  // src/Canvas/EmptyCanvas/index.tsx
1582
- var import_components10 = require("@manifest-editor/components");
1583
- var import_jsx_runtime22 = require("react/jsx-runtime");
1584
- var emptyCanvas = {
1771
+ var import_components16 = require("@manifest-editor/components");
1772
+ var import_creator_api14 = require("@manifest-editor/creator-api");
1773
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1774
+ var emptyCanvas = (0, import_creator_api14.defineCreator)({
1585
1775
  id: "@manifest-editor/empty-canvas",
1586
- create: createEmptyCanvas,
1776
+ create: (data, ctx) => {
1777
+ const canvasId = ctx.generateId("canvas");
1778
+ const page = ctx.embed({
1779
+ id: ctx.generateId("annotation-page", { id: canvasId, type: "Canvas" }),
1780
+ type: "AnnotationPage",
1781
+ items: []
1782
+ });
1783
+ return {
1784
+ id: canvasId,
1785
+ type: "Canvas",
1786
+ label: data.label || { en: [""] },
1787
+ height: data.height || 1e3,
1788
+ width: data.width || 1e3,
1789
+ items: [page]
1790
+ };
1791
+ },
1587
1792
  label: "Empty canvas",
1588
1793
  summary: "No content",
1589
- icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_components10.EmptyCanvasIcon, {}),
1794
+ icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_components16.EmptyCanvasIcon, {}),
1590
1795
  resourceType: "Canvas",
1591
1796
  resourceFields: ["id", "type", "label", "height", "width", "items"],
1592
1797
  supports: {
1593
1798
  parentTypes: ["Manifest"],
1594
1799
  parentFields: ["items"]
1595
1800
  }
1596
- };
1597
- async function createEmptyCanvas(data, ctx) {
1598
- const canvasId = ctx.generateId("canvas");
1599
- const page = ctx.embed({
1600
- id: ctx.generateId("annotation-page", { id: canvasId, type: "Canvas" }),
1601
- type: "AnnotationPage",
1602
- items: []
1603
- });
1604
- return {
1605
- id: canvasId,
1606
- type: "Canvas",
1607
- label: data.label || { en: [""] },
1608
- height: data.height || 1e3,
1609
- width: data.width || 1e3,
1610
- items: [page]
1611
- };
1612
- }
1801
+ });
1613
1802
 
1614
1803
  // src/Canvas/InternalCanvas/index.tsx
1615
- var import_react_iiif_vault4 = require("react-iiif-vault");
1804
+ var import_creator_api15 = require("@manifest-editor/creator-api");
1805
+ var import_iiif_browser = require("@manifest-editor/iiif-browser");
1806
+ var import_react_iiif_vault5 = require("react-iiif-vault");
1616
1807
 
1617
1808
  // ../../node_modules/.pnpm/tiny-invariant@1.3.3/node_modules/tiny-invariant/dist/esm/tiny-invariant.js
1618
1809
  var isProduction = false;
@@ -1630,27 +1821,26 @@ function invariant(condition, message) {
1630
1821
  }
1631
1822
 
1632
1823
  // src/Canvas/InternalCanvas/index.tsx
1633
- var import_iiif_browser = require("@manifest-editor/iiif-browser");
1634
- var import_jsx_runtime23 = require("react/jsx-runtime");
1635
- var internalCanvas = {
1824
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1825
+ var internalCanvas = (0, import_creator_api15.defineCreator)({
1636
1826
  id: "@manifest-editor/internal-canvas",
1637
1827
  create: createInternalCanvas,
1638
1828
  label: "Internal canvas link",
1639
1829
  summary: "Canvas from the same manifest",
1640
- icon: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ThumbnailStripIcon, {}),
1830
+ icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ThumbnailStripIcon, {}),
1641
1831
  resourceType: "Canvas",
1642
1832
  resourceFields: ["id", "type", "label"],
1643
1833
  supports: {
1644
1834
  parentTypes: ["Manifest"],
1645
1835
  parentFields: ["start"]
1646
1836
  },
1647
- render: (ctx) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(InternalCanvas, { ...ctx })
1648
- };
1837
+ render: (ctx) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(InternalCanvas, { ...ctx })
1838
+ });
1649
1839
  function InternalCanvas(props) {
1650
- const manifest = (0, import_react_iiif_vault4.useManifest)();
1651
- const vault = (0, import_react_iiif_vault4.useVault)();
1840
+ const manifest = (0, import_react_iiif_vault5.useManifest)();
1841
+ const vault = (0, import_react_iiif_vault5.useVault)();
1652
1842
  invariant(manifest, "Manifest is not loaded");
1653
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1843
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1654
1844
  import_iiif_browser.IIIFExplorer,
1655
1845
  {
1656
1846
  vault,
@@ -1676,11 +1866,22 @@ async function createInternalCanvas(data, ctx) {
1676
1866
  return ctx.embed({ id: data.id, type: "Canvas" });
1677
1867
  }
1678
1868
 
1869
+ // src/ContentResource/HTMLBodyCreator/index.tsx
1870
+ var import_creator_api16 = require("@manifest-editor/creator-api");
1871
+
1872
+ // ../ui/icons/TextFormatIcon.tsx
1873
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1874
+ var TextFormatIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", height: "1em", width: "1em", ...props, children: [
1875
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("path", { d: "M0 0h24v24H0z", fill: "none" }),
1876
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("path", { d: "M5 17v2h14v-2H5zm4.5-4.2h5l.9 2.2h2.1L12.75 4h-1.5L6.5 15h2.1l.9-2.2zM12 5.98 13.87 11h-3.74L12 5.98z" })
1877
+ ] });
1878
+
1679
1879
  // src/ContentResource/HTMLBodyCreator/create-html-body.tsx
1880
+ var import_components17 = require("@manifest-editor/components");
1680
1881
  var import_editors8 = require("@manifest-editor/editors");
1681
1882
  var import_shell2 = require("@manifest-editor/shell");
1682
- var import_react6 = require("react");
1683
- var import_jsx_runtime24 = require("react/jsx-runtime");
1883
+ var import_react7 = require("react");
1884
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1684
1885
  async function createHtmlBody(data, ctx) {
1685
1886
  return ctx.embed({
1686
1887
  id: ctx.generateId(`html/${data.language}`),
@@ -1692,18 +1893,18 @@ async function createHtmlBody(data, ctx) {
1692
1893
  }
1693
1894
  function CreateHTMLBodyForm(props) {
1694
1895
  const { i18n } = (0, import_shell2.useConfig)();
1695
- const [body, setBodyValue] = (0, import_react6.useState)("<p></p>");
1696
- const [language, setLang] = (0, import_react6.useState)(i18n.defaultLanguage);
1896
+ const [body, setBodyValue] = (0, import_react7.useState)("<p></p>");
1897
+ const [language, setLang] = (0, import_react7.useState)(i18n.defaultLanguage);
1697
1898
  const onSubmit = () => {
1698
1899
  props.runCreate({
1699
1900
  language,
1700
1901
  body
1701
1902
  });
1702
1903
  };
1703
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(PaddedSidebarContainer, { children: [
1704
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_editors8.InputContainer, { children: [
1705
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_editors8.InputLabel, { children: "HTML Body" }),
1706
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1904
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(PaddedSidebarContainer, { children: [
1905
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_editors8.InputContainer, { children: [
1906
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_editors8.InputLabel, { children: "HTML Body" }),
1907
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1707
1908
  import_editors8.RichTextLanguageField,
1708
1909
  {
1709
1910
  value: body,
@@ -1714,27 +1915,20 @@ function CreateHTMLBodyForm(props) {
1714
1915
  }
1715
1916
  )
1716
1917
  ] }),
1717
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { onClick: () => onSubmit(), children: "Create" })
1918
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_components17.ActionButton, { primary: true, large: true, type: "button", onPress: onSubmit, children: "Create" })
1718
1919
  ] });
1719
1920
  }
1720
1921
 
1721
- // ../ui/icons/TextFormatIcon.tsx
1722
- var import_jsx_runtime25 = require("react/jsx-runtime");
1723
- var TextFormatIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", height: "1em", width: "1em", ...props, children: [
1724
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M0 0h24v24H0z", fill: "none" }),
1725
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M5 17v2h14v-2H5zm4.5-4.2h5l.9 2.2h2.1L12.75 4h-1.5L6.5 15h2.1l.9-2.2zM12 5.98 13.87 11h-3.74L12 5.98z" })
1726
- ] });
1727
-
1728
1922
  // src/ContentResource/HTMLBodyCreator/index.tsx
1729
- var import_jsx_runtime26 = require("react/jsx-runtime");
1730
- var htmlBodyCreator = {
1923
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1924
+ var htmlBodyCreator = (0, import_creator_api16.defineCreator)({
1731
1925
  id: "@manifest-editor/html-body-creator",
1732
1926
  create: createHtmlBody,
1733
1927
  label: "HTML Body",
1734
1928
  summary: "Add HTML annotation body",
1735
- icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TextFormatIcon, {}),
1929
+ icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TextFormatIcon, {}),
1736
1930
  render(ctx) {
1737
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CreateHTMLBodyForm, { ...ctx });
1931
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(CreateHTMLBodyForm, { ...ctx });
1738
1932
  },
1739
1933
  resourceType: "ContentResource",
1740
1934
  resourceFields: ["id", "language", "type", "format", "value"],
@@ -1746,118 +1940,165 @@ var htmlBodyCreator = {
1746
1940
  type: "TextualBody",
1747
1941
  format: "text/html"
1748
1942
  }
1749
- };
1943
+ });
1750
1944
 
1751
1945
  // src/ContentResource/IIIFBrowserCreator/index.tsx
1752
- var import_components11 = require("@manifest-editor/components");
1946
+ var import_components18 = require("@manifest-editor/components");
1947
+ var import_creator_api17 = require("@manifest-editor/creator-api");
1753
1948
 
1754
1949
  // src/ContentResource/IIIFBrowserCreator/iiif-browser-creator.tsx
1755
- var import_helpers3 = require("@iiif/helpers");
1756
- var import_react8 = require("react");
1950
+ var import_helpers5 = require("@iiif/helpers");
1951
+ var import_image_33 = require("@iiif/parser/image-3");
1952
+ var import_react9 = require("react");
1953
+ function croppedRegion(imageServiceId, region, size) {
1954
+ return `${imageServiceId}/${Math.floor(region.x)},${Math.floor(region.y)},${Math.floor(region.width)},${Math.floor(
1955
+ region.height
1956
+ )}/${size}/0/default.jpg`;
1957
+ }
1757
1958
  async function createFromIIIFBrowserOutput(data, ctx) {
1758
1959
  const targetType = ctx.options.targetType;
1759
- if (Array.isArray(data.output)) {
1760
- throw new Error("Multiple items not yet supported");
1761
- }
1762
- const contentState = (0, import_helpers3.normaliseContentState)(
1763
- typeof data.output === "string" ? (0, import_helpers3.parseContentState)(data.output) : data.output
1764
- );
1765
- if (!contentState.target || contentState.target.length === 0) {
1766
- throw new Error("No target found in content state");
1767
- }
1768
- const target = contentState.target[0];
1769
- const type = target.source.type;
1770
- const previewVault = ctx.getPreviewVault();
1771
- if (targetType === "Canvas" || targetType === "Annotation") {
1772
- if (type === "Canvas") {
1773
- const canvasId = target.source.id;
1774
- const manifestId = target.source.partOf?.find(
1775
- (t) => t.type === "Manifest"
1776
- );
1777
- invariant(manifestId, "Could not load external resource without partOf");
1778
- const manifest = await previewVault.loadManifest(manifestId);
1779
- invariant(manifest, "Manifest not found");
1780
- const canvasRef = manifest.items.find((item) => item.id === canvasId);
1781
- invariant(canvasRef, "Canvas not found");
1782
- const canvas = previewVault.get(canvasRef);
1783
- if (targetType === "Canvas" && target.selector?.type !== "BoxSelector") {
1784
- return ctx.embed(previewVault.toPresentation3(canvas));
1785
- }
1786
- const annotationPage = previewVault.get(canvas.items[0]);
1787
- const annotation = previewVault.get(annotationPage.items[0]);
1788
- if (targetType === "Annotation" || targetType === "Canvas") {
1789
- const fullAnnotation = previewVault.toPresentation3(annotation);
1790
- if (fullAnnotation?.body?.service) {
1791
- const width = fullAnnotation?.body.width;
1792
- const height = fullAnnotation?.body.height;
1793
- const service = Array.isArray(fullAnnotation?.body?.service) ? fullAnnotation?.body?.service[0] : fullAnnotation?.body?.service;
1794
- if (!service.width || !service.height) {
1795
- service.width = width;
1796
- service.height = height;
1960
+ const resources = data.output;
1961
+ const returnResources = [];
1962
+ for (const { resource, selector, parent } of resources) {
1963
+ const type = resource.type;
1964
+ const previewVault = new import_helpers5.Vault();
1965
+ if (targetType === "Canvas" || targetType === "Annotation" || targetType === "ContentResource") {
1966
+ if (type === "Canvas") {
1967
+ const canvasId = resource.id;
1968
+ const manifestId = parent?.type === "Manifest" ? parent.id : void 0;
1969
+ invariant(manifestId, "Could not find Manifest");
1970
+ const manifest = await previewVault.loadManifest(manifestId);
1971
+ invariant(manifest, "Manifest not found");
1972
+ const canvasRef = manifest.items.find((item) => item.id === canvasId);
1973
+ invariant(canvasRef, "Canvas not found");
1974
+ const canvas = previewVault.get(canvasRef);
1975
+ if (targetType === "Canvas" && selector?.type !== "BoxSelector") {
1976
+ const fullCanvas = previewVault.toPresentation3(canvas);
1977
+ if (!fullCanvas.label) {
1978
+ fullCanvas.label = { en: ["Untitled canvas"] };
1797
1979
  }
1980
+ returnResources.push(ctx.embed(fullCanvas));
1981
+ continue;
1798
1982
  }
1799
- if (target.selector && target.selector.type === "BoxSelector") {
1800
- const selector = {
1801
- "@context": "http://iiif.io/api/annex/openannotation/context.json",
1802
- type: "iiif:ImageApiSelector",
1803
- region: [
1804
- ~~target.selector.spatial.x,
1805
- ~~target.selector.spatial.y,
1806
- ~~target.selector.spatial.width,
1807
- ~~target.selector.spatial.height
1808
- ].join(",")
1809
- };
1810
- fullAnnotation.body = {
1811
- id: ctx.generateId("SpecificResource", annotation),
1812
- type: "SpecificResource",
1813
- source: fullAnnotation.body,
1814
- selector
1815
- };
1816
- if (targetType === "Canvas") {
1817
- const canvasId2 = ctx.generateId("Canvas", annotation);
1818
- fullAnnotation.target = canvasId2;
1819
- const pageId = ctx.generateId("Page", annotation);
1820
- const annotationPage2 = ctx.embed({
1821
- id: pageId,
1822
- type: "AnnotationPage",
1823
- items: [fullAnnotation]
1824
- });
1825
- return ctx.embed({
1826
- id: canvasId2,
1827
- type: "Canvas",
1828
- width: ~~target.selector.spatial.width,
1829
- height: ~~target.selector.spatial.height,
1830
- items: [annotationPage2]
1831
- });
1983
+ const annotationPage = previewVault.get(canvas.items[0]);
1984
+ const annotation = previewVault.get(annotationPage.items[0]);
1985
+ if (targetType === "Annotation" || targetType === "Canvas" || targetType === "ContentResource") {
1986
+ const fullAnnotation = previewVault.toPresentation3(annotation);
1987
+ fullAnnotation.id = ctx.generateId("Annotation");
1988
+ let service = null;
1989
+ const dimensions = { width: 0, height: 0 };
1990
+ if (fullAnnotation?.body?.service) {
1991
+ const width = fullAnnotation?.body.width;
1992
+ const height = fullAnnotation?.body.height;
1993
+ service = (0, import_image_33.getImageServices)(fullAnnotation?.body)[0];
1994
+ if (service && (!service.width || !service.height)) {
1995
+ service.width = width;
1996
+ service.height = height;
1997
+ }
1998
+ dimensions.width = width;
1999
+ dimensions.height = height;
2000
+ if (data.trackSize) {
2001
+ data.trackSize(dimensions);
2002
+ }
1832
2003
  }
1833
- return ctx.embed({
1834
- ...fullAnnotation,
1835
- target: ctx.getTarget()
1836
- });
2004
+ if (selector?.type === "BoxSelector") {
2005
+ const imageApiSelector = {
2006
+ "@context": "http://iiif.io/api/annex/openannotation/context.json",
2007
+ type: "iiif:ImageApiSelector",
2008
+ region: [
2009
+ ~~selector.spatial.x,
2010
+ ~~selector.spatial.y,
2011
+ ~~selector.spatial.width,
2012
+ ~~selector.spatial.height
2013
+ ].join(",")
2014
+ };
2015
+ const newBody = { ...fullAnnotation.body };
2016
+ let thumbnailId = "";
2017
+ if (service) {
2018
+ const id = service.id || service["@id"] || "";
2019
+ if (id) {
2020
+ newBody.id = croppedRegion(id, selector.spatial, "max");
2021
+ thumbnailId = croppedRegion(id, selector.spatial, "512,");
2022
+ }
2023
+ }
2024
+ fullAnnotation.body = {
2025
+ id: ctx.generateId("SpecificResource", annotation),
2026
+ type: "SpecificResource",
2027
+ source: newBody,
2028
+ selector: imageApiSelector
2029
+ };
2030
+ if (data.trackSize) {
2031
+ data.trackSize({
2032
+ width: ~~selector.spatial.width,
2033
+ height: ~~selector.spatial.height
2034
+ });
2035
+ }
2036
+ if (targetType === "ContentResource") {
2037
+ returnResources.push(fullAnnotation.body);
2038
+ continue;
2039
+ }
2040
+ if (targetType === "Canvas") {
2041
+ const canvasId2 = ctx.generateId("Canvas", annotation);
2042
+ fullAnnotation.target = canvasId2;
2043
+ const pageId = ctx.generateId("Page", annotation);
2044
+ const annotationPage2 = ctx.embed({
2045
+ id: pageId,
2046
+ type: "AnnotationPage",
2047
+ items: [fullAnnotation]
2048
+ });
2049
+ returnResources.push(
2050
+ ctx.embed({
2051
+ id: canvasId2,
2052
+ type: "Canvas",
2053
+ label: { en: ["Untitled canvas"] },
2054
+ width: ~~selector.spatial.width,
2055
+ height: ~~selector.spatial.height,
2056
+ thumbnail: thumbnailId ? [
2057
+ ctx.embed({
2058
+ id: thumbnailId,
2059
+ type: "Image",
2060
+ format: "image/jpeg",
2061
+ width: 512,
2062
+ height: Math.round(selector.spatial.height / selector.spatial.width * 512)
2063
+ })
2064
+ ] : void 0,
2065
+ items: [annotationPage2]
2066
+ })
2067
+ );
2068
+ continue;
2069
+ }
2070
+ returnResources.push(
2071
+ ctx.embed({
2072
+ ...fullAnnotation,
2073
+ target: ctx.getTarget()
2074
+ })
2075
+ );
2076
+ continue;
2077
+ }
2078
+ returnResources.push(
2079
+ ctx.embed({
2080
+ ...previewVault.toPresentation3(annotation),
2081
+ target: ctx.getTarget()
2082
+ })
2083
+ );
1837
2084
  }
1838
- return ctx.embed({
1839
- ...previewVault.toPresentation3(annotation),
1840
- target: ctx.getTarget()
1841
- });
1842
2085
  }
1843
2086
  }
1844
2087
  }
1845
- throw new Error("Not yet supported.");
2088
+ return returnResources;
1846
2089
  }
1847
- var IIIFBrowserCreatorForm2 = (0, import_react8.lazy)(
1848
- () => Promise.resolve().then(() => (init_iiif_browser_form_lazy(), iiif_browser_form_lazy_exports))
1849
- );
2090
+ var IIIFBrowserCreatorForm2 = (0, import_react9.lazy)(() => Promise.resolve().then(() => (init_iiif_browser_form_lazy(), iiif_browser_form_lazy_exports)));
1850
2091
 
1851
2092
  // src/ContentResource/IIIFBrowserCreator/index.tsx
1852
- var import_jsx_runtime28 = require("react/jsx-runtime");
1853
- var iiifBrowserCreator = {
2093
+ var import_jsx_runtime30 = require("react/jsx-runtime");
2094
+ var iiifBrowserCreator = (0, import_creator_api17.defineCreator)({
1854
2095
  id: "@manifest-editor/iiif-browser-creator",
1855
2096
  create: createFromIIIFBrowserOutput,
1856
2097
  label: "IIIF Browser",
1857
2098
  summary: "Browse IIIF Resources",
1858
- icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_components11.IIIFBrowserIcon, {}),
2099
+ icon: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_components18.IIIFBrowserIcon, {}),
1859
2100
  render(ctx) {
1860
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(IIIFBrowserCreatorForm2, { ...ctx });
2101
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IIIFBrowserCreatorForm2, { ...ctx });
1861
2102
  },
1862
2103
  hiddenModal: true,
1863
2104
  tags: ["image", "image-service"],
@@ -1866,52 +2107,49 @@ var iiifBrowserCreator = {
1866
2107
  additionalTypes: ["Annotation", "Canvas"],
1867
2108
  supports: {
1868
2109
  parentTypes: ["Annotation", "Manifest", "AnnotationPage"],
2110
+ parentFields: ["body", "items"],
1869
2111
  parentFieldMap: {
1870
2112
  Annotation: ["body"],
1871
2113
  Manifest: ["items"],
1872
2114
  AnnotationPage: ["items"]
1873
2115
  }
1874
2116
  },
1875
- sideEffects: [
1876
- resizeToFitService,
1877
- resizeResourceToEmptyCanvas,
1878
- repositionMultipleImages
1879
- ],
2117
+ sideEffects: [resizeToFitService, resizeResourceToEmptyCanvas, repositionMultipleImages],
1880
2118
  staticFields: {}
1881
- };
2119
+ });
1882
2120
 
1883
2121
  // src/ContentResource/ImageServiceCreator/index.tsx
1884
- var import_jsx_runtime29 = require("react/jsx-runtime");
1885
- var imageServiceCreator = {
2122
+ var import_components19 = require("@manifest-editor/components");
2123
+ var import_creator_api18 = require("@manifest-editor/creator-api");
2124
+ var import_jsx_runtime31 = require("react/jsx-runtime");
2125
+ var imageServiceCreator = (0, import_creator_api18.defineCreator)({
1886
2126
  id: "@manifest-editor/image-service-creator",
1887
2127
  create: createImageServer,
1888
2128
  label: "Image Service",
1889
2129
  summary: "Add an image from Image Service",
1890
- icon: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TextFormatIcon, {}),
2130
+ icon: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_components19.IIIFLogo, { style: { padding: 10 } }),
1891
2131
  render(ctx) {
1892
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(CreateImageServerForm, { ...ctx });
2132
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(CreateImageServerForm, { ...ctx });
1893
2133
  },
1894
2134
  resourceType: "ContentResource",
1895
2135
  resourceFields: ["id", "type", "height", "width", "format", "service"],
1896
2136
  supports: {
1897
2137
  parentFields: ["logo", "body", "thumbnail"]
1898
- },
1899
- staticFields: {
1900
- type: "Image"
1901
2138
  }
1902
- };
2139
+ });
1903
2140
 
1904
2141
  // src/ContentResource/ImageUrlCreator/index.tsx
1905
- var import_components12 = require("@manifest-editor/components");
1906
- var import_jsx_runtime30 = require("react/jsx-runtime");
1907
- var imageUrlCreator = {
2142
+ var import_components20 = require("@manifest-editor/components");
2143
+ var import_creator_api19 = require("@manifest-editor/creator-api");
2144
+ var import_jsx_runtime32 = require("react/jsx-runtime");
2145
+ var imageUrlCreator = (0, import_creator_api19.defineCreator)({
1908
2146
  id: "@manifest-editor/image-url-creator",
1909
2147
  create: createImageUrl,
1910
2148
  label: "Image",
1911
2149
  summary: "Image from a URL",
1912
- icon: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_components12.AddImageIcon, {}),
2150
+ icon: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_components20.AddImageIcon, {}),
1913
2151
  render(ctx) {
1914
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(CreateImageUrlForm, { ...ctx });
2152
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CreateImageUrlForm, { ...ctx });
1915
2153
  },
1916
2154
  resourceType: "ContentResource",
1917
2155
  resourceFields: ["format"],
@@ -1921,12 +2159,39 @@ var imageUrlCreator = {
1921
2159
  staticFields: {
1922
2160
  type: "Image"
1923
2161
  }
1924
- };
2162
+ });
2163
+
2164
+ // src/ContentResource/ImageUrlListCreator/index.tsx
2165
+ var import_components21 = require("@manifest-editor/components");
2166
+ var import_creator_api20 = require("@manifest-editor/creator-api");
2167
+ var import_jsx_runtime33 = require("react/jsx-runtime");
2168
+ var imageUrlListCreator = (0, import_creator_api20.defineCreator)({
2169
+ id: "@manifest-editor/image-url-list",
2170
+ label: "Image URL List",
2171
+ summary: "Image from a list of URLs",
2172
+ create: createImageUrlList,
2173
+ icon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_components21.ImageListIcon, {}),
2174
+ render(ctx) {
2175
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CreateImageUrlListForm, { ...ctx });
2176
+ },
2177
+ resourceType: "ContentResource",
2178
+ resourceFields: ["format"],
2179
+ supports: {
2180
+ parentFields: ["logo", "body", "thumbnail"]
2181
+ },
2182
+ staticFields: {
2183
+ type: "Image"
2184
+ }
2185
+ });
2186
+
2187
+ // src/ContentResource/PlaintextCreator/index.tsx
2188
+ var import_creator_api21 = require("@manifest-editor/creator-api");
1925
2189
 
1926
2190
  // src/ContentResource/PlaintextCreator/create-plaintext.tsx
2191
+ var import_components22 = require("@manifest-editor/components");
1927
2192
  var import_editors9 = require("@manifest-editor/editors");
1928
- var import_react9 = require("react");
1929
- var import_jsx_runtime31 = require("react/jsx-runtime");
2193
+ var import_react10 = require("react");
2194
+ var import_jsx_runtime34 = require("react/jsx-runtime");
1930
2195
  async function createPlaintext(data, ctx) {
1931
2196
  return ctx.embed({
1932
2197
  id: data.url,
@@ -1936,7 +2201,9 @@ async function createPlaintext(data, ctx) {
1936
2201
  });
1937
2202
  }
1938
2203
  function CreatePlaintextForm(props) {
1939
- const [label, setLabel] = (0, import_react9.useState)({ en: ["View as text"] });
2204
+ const [label, setLabel] = (0, import_react10.useState)({
2205
+ en: ["View as text"]
2206
+ });
1940
2207
  const onSubmit = (e) => {
1941
2208
  e.preventDefault();
1942
2209
  const data = new FormData(e.target);
@@ -1945,8 +2212,8 @@ function CreatePlaintextForm(props) {
1945
2212
  props.runCreate({ url: formData.url, label });
1946
2213
  }
1947
2214
  };
1948
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(PaddedSidebarContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("form", { onSubmit, children: [
1949
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2215
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(PaddedSidebarContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("form", { onSubmit, children: [
2216
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1950
2217
  import_editors9.LanguageFieldEditor,
1951
2218
  {
1952
2219
  focusId: "label",
@@ -1955,24 +2222,24 @@ function CreatePlaintextForm(props) {
1955
2222
  onSave: (e) => setLabel(e.toInternationalString())
1956
2223
  }
1957
2224
  ),
1958
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_editors9.InputContainer, { $wide: true, children: [
1959
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_editors9.InputLabel, { htmlFor: "id", children: "Link to plaintext" }),
1960
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_editors9.Input, { id: "url", name: "url", defaultValue: "" })
2225
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_editors9.InputContainer, { $wide: true, children: [
2226
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_editors9.InputLabel, { htmlFor: "id", children: "Link to plaintext" }),
2227
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_editors9.Input, { id: "url", name: "url", defaultValue: "" })
1961
2228
  ] }),
1962
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Button, { type: "submit", children: "Create" })
2229
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_components22.ActionButton, { primary: true, large: true, type: "submit", children: "Create" })
1963
2230
  ] }) });
1964
2231
  }
1965
2232
 
1966
2233
  // src/ContentResource/PlaintextCreator/index.tsx
1967
- var import_jsx_runtime32 = require("react/jsx-runtime");
1968
- var plaintextCreator = {
2234
+ var import_jsx_runtime35 = require("react/jsx-runtime");
2235
+ var plaintextCreator = (0, import_creator_api21.defineCreator)({
1969
2236
  id: "@manifest-editor/plaintext-creator",
1970
2237
  create: createPlaintext,
1971
2238
  label: "Plaintext",
1972
2239
  summary: "Add link to an plaintext",
1973
- icon: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TextFormatIcon, {}),
2240
+ icon: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TextFormatIcon, {}),
1974
2241
  render(ctx) {
1975
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CreatePlaintextForm, { ...ctx });
2242
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(CreatePlaintextForm, { ...ctx });
1976
2243
  },
1977
2244
  resourceType: "ContentResource",
1978
2245
  resourceFields: ["label", "format"],
@@ -1982,12 +2249,223 @@ var plaintextCreator = {
1982
2249
  staticFields: {
1983
2250
  format: "text/plain"
1984
2251
  }
1985
- };
2252
+ });
1986
2253
 
1987
- // src/ContentResource/WebPageCreator/create-web-page.tsx
2254
+ // src/ContentResource/ThumbnailCreator/index.tsx
2255
+ var import_components24 = require("@manifest-editor/components");
2256
+ var import_creator_api22 = require("@manifest-editor/creator-api");
2257
+
2258
+ // src/ContentResource/ThumbnailCreator/create-thumbnail.tsx
2259
+ var import_components23 = require("@manifest-editor/components");
1988
2260
  var import_editors10 = require("@manifest-editor/editors");
1989
- var import_react10 = require("react");
1990
- var import_jsx_runtime33 = require("react/jsx-runtime");
2261
+ var import_react11 = require("react");
2262
+
2263
+ // src/ContentResource/ThumbnailCreator/thumbnail-helpers.ts
2264
+ var import_image_34 = require("@iiif/parser/image-3");
2265
+ function serviceImageAtSize(service, size) {
2266
+ if (service["@id"]) {
2267
+ service.id = service["@id"];
2268
+ }
2269
+ if (service["@type"]) {
2270
+ service.type = service["@type"];
2271
+ }
2272
+ const request = (0, import_image_34.createImageServiceRequest)(service);
2273
+ return (0, import_image_34.imageServiceRequestToString)({
2274
+ identifier: request.identifier,
2275
+ server: request.server,
2276
+ scheme: request.scheme,
2277
+ type: "image",
2278
+ size: {
2279
+ max: false,
2280
+ confined: false,
2281
+ upscaled: false,
2282
+ width: size.width,
2283
+ height: size.height
2284
+ },
2285
+ format: "jpg",
2286
+ // This isn't how it should be modelled, always full,
2287
+ // region: data.selector ? data.selector : { full: true },
2288
+ region: { full: true },
2289
+ rotation: { angle: 0 },
2290
+ quality: "default",
2291
+ prefix: request.prefix,
2292
+ originalPath: request.originalPath
2293
+ });
2294
+ }
2295
+ function getCanonicalUrl2(url) {
2296
+ return url.endsWith("default.jpg") ? (0, import_image_34.imageServiceRequestToString)({
2297
+ ...(0, import_image_34.parseImageServiceRequest)(url),
2298
+ type: "info"
2299
+ }) : (0, import_image_34.canonicalServiceUrl)(url);
2300
+ }
2301
+
2302
+ // src/ContentResource/ThumbnailCreator/create-thumbnail.tsx
2303
+ var import_jsx_runtime36 = require("react/jsx-runtime");
2304
+ async function createThumbnail(data, ctx) {
2305
+ const service = { ...data.service };
2306
+ const sizes = service.sizes;
2307
+ if (service["@id"]) {
2308
+ service.id = service["@id"];
2309
+ }
2310
+ if (service["@type"]) {
2311
+ service.type = service["@type"];
2312
+ }
2313
+ if (data.thumbnailUrl) {
2314
+ return ctx.embed({
2315
+ id: data.thumbnailUrl,
2316
+ type: "Image",
2317
+ format: "image/jpeg",
2318
+ width: data.width,
2319
+ height: data.height
2320
+ });
2321
+ }
2322
+ if (sizes) {
2323
+ const thumbnailSize = data.width || 400;
2324
+ let bestMatch = null;
2325
+ for (const size of sizes) {
2326
+ if (!bestMatch || Math.abs(size.width - thumbnailSize) < Math.abs(bestMatch.width - thumbnailSize)) {
2327
+ bestMatch = { width: size.width, height: size.height };
2328
+ }
2329
+ }
2330
+ if (bestMatch) {
2331
+ const imageId = serviceImageAtSize(service, bestMatch);
2332
+ return ctx.embed({
2333
+ id: imageId,
2334
+ type: "Image",
2335
+ format: "image/jpeg",
2336
+ width: bestMatch.width,
2337
+ height: bestMatch.height
2338
+ });
2339
+ }
2340
+ }
2341
+ return null;
2342
+ }
2343
+ function CreateThumbnailForm(props) {
2344
+ const [url, setUrl] = (0, import_react11.useState)("");
2345
+ const [service, setService] = (0, import_react11.useState)(null);
2346
+ const [selectedSize, setSelectedSize] = (0, import_react11.useState)({ width: 0, height: 0 });
2347
+ const previewUrl = (0, import_react11.useMemo)(() => {
2348
+ if (!service)
2349
+ return null;
2350
+ if (!selectedSize.width || !selectedSize.height)
2351
+ return null;
2352
+ return serviceImageAtSize(service, selectedSize);
2353
+ }, [selectedSize, service]);
2354
+ const onSubmit = (e) => {
2355
+ e.preventDefault();
2356
+ const data = new FormData(e.target);
2357
+ const formData = Object.fromEntries(data.entries());
2358
+ const url2 = formData.url;
2359
+ if (url2) {
2360
+ const info = getCanonicalUrl2(url2);
2361
+ if (!info) {
2362
+ throw new Error("Invalid image service request");
2363
+ }
2364
+ fetch(info).then((r) => r.json()).then((service2) => {
2365
+ setService(service2);
2366
+ const size0 = service2.sizes?.[0];
2367
+ if (size0) {
2368
+ setSelectedSize(size0);
2369
+ }
2370
+ });
2371
+ }
2372
+ };
2373
+ if (service) {
2374
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(PaddedSidebarContainer, { children: [
2375
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mb-4", children: [
2376
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "mb-2", children: service["@id"] || service.id }),
2377
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex gap-2 mb-4", children: service.sizes?.map((size) => {
2378
+ const isSelected = size.width === selectedSize.width;
2379
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
2380
+ import_components23.ActionButton,
2381
+ {
2382
+ primary: isSelected,
2383
+ isDisabled: isSelected,
2384
+ large: true,
2385
+ onPress: () => setSelectedSize(size),
2386
+ children: [
2387
+ size.width,
2388
+ "x",
2389
+ size.height
2390
+ ]
2391
+ },
2392
+ size.width
2393
+ );
2394
+ }) }),
2395
+ previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("img", { src: previewUrl, alt: "preview of selected resource" }) : null
2396
+ ] }),
2397
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
2398
+ import_components23.ActionButton,
2399
+ {
2400
+ primary: true,
2401
+ large: true,
2402
+ isDisabled: !previewUrl,
2403
+ onPress: () => {
2404
+ if (!service)
2405
+ return;
2406
+ props.runCreate({ service, width: selectedSize.width, height: selectedSize.height });
2407
+ },
2408
+ children: "Add thumbnail"
2409
+ }
2410
+ )
2411
+ ] });
2412
+ }
2413
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(PaddedSidebarContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("form", { onSubmit, children: [
2414
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex gap-2 items-center", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_editors10.InputContainer, { $wide: true, children: [
2415
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_editors10.InputLabel, { htmlFor: "id", children: "Link to image service" }),
2416
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
2417
+ import_editors10.Input,
2418
+ {
2419
+ id: "url",
2420
+ name: "url",
2421
+ defaultValue: "",
2422
+ onPaste: (e) => {
2423
+ const text = e.clipboardData.getData("text/plain");
2424
+ setUrl(text ? getCanonicalUrl2(text) : "");
2425
+ },
2426
+ onBlur: (e) => setUrl(e.currentTarget.value ? getCanonicalUrl2(e.currentTarget.value) : "")
2427
+ }
2428
+ )
2429
+ ] }) }),
2430
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_components23.ActionButton, { primary: true, large: true, type: "submit", isDisabled: !url, children: "Select size" }) })
2431
+ ] }) });
2432
+ }
2433
+
2434
+ // src/ContentResource/ThumbnailCreator/index.tsx
2435
+ var import_jsx_runtime37 = require("react/jsx-runtime");
2436
+ var thumbnailCreator = (0, import_creator_api22.defineCreator)({
2437
+ id: "@manifest-editor/thumbnail-image",
2438
+ create: createThumbnail,
2439
+ label: "Thumbnail from service",
2440
+ summary: "Add thumbnail from an image service",
2441
+ icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_components24.ScaledImageIcon, {}),
2442
+ render(ctx) {
2443
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CreateThumbnailForm, { ...ctx });
2444
+ },
2445
+ resourceType: "ContentResource",
2446
+ resourceFields: ["id", "type", "format"],
2447
+ supports: {
2448
+ parentFields: ["thumbnail"]
2449
+ }
2450
+ });
2451
+
2452
+ // src/ContentResource/WebPageCreator/index.tsx
2453
+ var import_creator_api23 = require("@manifest-editor/creator-api");
2454
+
2455
+ // ../ui/icons/LinkIcon.tsx
2456
+ var import_jsx_runtime38 = require("react/jsx-runtime");
2457
+ function LinkIcon() {
2458
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 0 24 24", width: "24px", fill: "#000000", children: [
2459
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("path", { d: "M0 0h24v24H0z", fill: "none" }),
2460
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("path", { d: "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" })
2461
+ ] });
2462
+ }
2463
+
2464
+ // src/ContentResource/WebPageCreator/create-web-page.tsx
2465
+ var import_components25 = require("@manifest-editor/components");
2466
+ var import_editors11 = require("@manifest-editor/editors");
2467
+ var import_react12 = require("react");
2468
+ var import_jsx_runtime39 = require("react/jsx-runtime");
1991
2469
  async function createWebPage(data, ctx) {
1992
2470
  return ctx.embed({
1993
2471
  id: data.url,
@@ -1997,7 +2475,7 @@ async function createWebPage(data, ctx) {
1997
2475
  });
1998
2476
  }
1999
2477
  function CreateWebPageForm(props) {
2000
- const [label, setLabel] = (0, import_react10.useState)({ en: [""] });
2478
+ const [label, setLabel] = (0, import_react12.useState)({ en: [""] });
2001
2479
  const onSubmit = (e) => {
2002
2480
  e.preventDefault();
2003
2481
  const data = new FormData(e.target);
@@ -2006,9 +2484,9 @@ function CreateWebPageForm(props) {
2006
2484
  props.runCreate({ url: formData.url, label });
2007
2485
  }
2008
2486
  };
2009
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(PaddedSidebarContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("form", { onSubmit, children: [
2010
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
2011
- import_editors10.LanguageFieldEditor,
2487
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(PaddedSidebarContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("form", { onSubmit, children: [
2488
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
2489
+ import_editors11.LanguageFieldEditor,
2012
2490
  {
2013
2491
  focusId: "label",
2014
2492
  label: "Label",
@@ -2016,52 +2494,48 @@ function CreateWebPageForm(props) {
2016
2494
  onSave: (e) => setLabel(e.toInternationalString())
2017
2495
  }
2018
2496
  ),
2019
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_editors10.InputContainer, { $wide: true, children: [
2020
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_editors10.InputLabel, { htmlFor: "id", children: "Link" }),
2021
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_editors10.Input, { id: "url", name: "url", defaultValue: "" })
2497
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_editors11.InputContainer, { $wide: true, children: [
2498
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_editors11.InputLabel, { htmlFor: "id", children: "Link" }),
2499
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_editors11.Input, { id: "url", name: "url", defaultValue: "" })
2022
2500
  ] }),
2023
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Button, { type: "submit", children: "Create link" })
2501
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_components25.ActionButton, { primary: true, large: true, type: "submit", children: "Create link" })
2024
2502
  ] }) });
2025
2503
  }
2026
2504
 
2027
- // ../ui/icons/LinkIcon.tsx
2028
- var import_jsx_runtime34 = require("react/jsx-runtime");
2029
- function LinkIcon() {
2030
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 0 24 24", width: "24px", fill: "#000000", children: [
2031
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("path", { d: "M0 0h24v24H0z", fill: "none" }),
2032
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("path", { d: "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" })
2033
- ] });
2034
- }
2035
-
2036
2505
  // src/ContentResource/WebPageCreator/index.tsx
2037
- var import_jsx_runtime35 = require("react/jsx-runtime");
2038
- var webPageCreator = {
2506
+ var import_jsx_runtime40 = require("react/jsx-runtime");
2507
+ var webPageCreator = (0, import_creator_api23.defineCreator)({
2039
2508
  id: "@manifest-editor/web-page-creator",
2040
2509
  create: createWebPage,
2041
2510
  label: "Web page",
2042
2511
  summary: "Add link to an external web page",
2043
- icon: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(LinkIcon, {}),
2512
+ icon: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(LinkIcon, {}),
2044
2513
  render(ctx) {
2045
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(CreateWebPageForm, { ...ctx });
2514
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(CreateWebPageForm, { ...ctx });
2046
2515
  },
2047
2516
  resourceType: "ContentResource",
2048
2517
  resourceFields: ["label", "format"],
2049
2518
  supports: {
2050
2519
  parentFields: ["seeAlso", "rendering", "homepage"]
2051
2520
  }
2052
- };
2521
+ });
2053
2522
 
2054
2523
  // src/ContentResource/YouTubeCreator/index.tsx
2055
- var import_components13 = require("@manifest-editor/components");
2524
+ var import_components27 = require("@manifest-editor/components");
2525
+ var import_creator_api24 = require("@manifest-editor/creator-api");
2056
2526
 
2057
2527
  // src/ContentResource/YouTubeCreator/create-youtube-body.tsx
2058
- var import_editors11 = require("@manifest-editor/editors");
2059
- var import_jsx_runtime36 = require("react/jsx-runtime");
2528
+ var import_components26 = require("@manifest-editor/components");
2529
+ var import_editors12 = require("@manifest-editor/editors");
2530
+ var import_jsx_runtime41 = require("react/jsx-runtime");
2060
2531
  var ytRegex = /^.*(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/|shorts\/)|(?:(?:watch)?\?vi?=|&vi?=))([^#&?]*).*/;
2061
2532
  function getYouTubeId(url) {
2062
2533
  const id = (url || "").match(ytRegex);
2063
2534
  return id ? id[1] : null;
2064
2535
  }
2536
+ function validateYouTube(data) {
2537
+ return !!getYouTubeId(data.youtubeUrl);
2538
+ }
2065
2539
  async function createYoutubeBody(data, ctx) {
2066
2540
  const id = getYouTubeId(data.youtubeUrl);
2067
2541
  const body = ctx.embed({
@@ -2131,27 +2605,27 @@ function YouTubeForm(props) {
2131
2605
  props.runCreate({ youtubeUrl: formData.youtubeUrl });
2132
2606
  }
2133
2607
  };
2134
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(PaddedSidebarContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("form", { onSubmit, children: [
2135
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_editors11.InputContainer, { $wide: true, children: [
2136
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_editors11.InputLabel, { htmlFor: "id", children: "Link to YouTube" }),
2137
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_editors11.Input, { id: "youtubeUrl", name: "youtubeUrl", defaultValue: "" })
2608
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(PaddedSidebarContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("form", { onSubmit, children: [
2609
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_editors12.InputContainer, { $wide: true, children: [
2610
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_editors12.InputLabel, { htmlFor: "id", children: "Link to YouTube" }),
2611
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_editors12.Input, { id: "youtubeUrl", name: "youtubeUrl", defaultValue: "" })
2138
2612
  ] }),
2139
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Button, { type: "submit", children: "Create" })
2613
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_components26.ActionButton, { primary: true, large: true, type: "submit", children: "Create" })
2140
2614
  ] }) });
2141
2615
  }
2142
2616
 
2143
2617
  // src/ContentResource/YouTubeCreator/index.tsx
2144
- var import_jsx_runtime37 = require("react/jsx-runtime");
2145
- var youTubeBodyCreator = {
2618
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2619
+ var youTubeBodyCreator = (0, import_creator_api24.defineCreator)({
2146
2620
  id: "@manifest-editor/youtube",
2147
2621
  create: createYoutubeBody,
2148
2622
  label: "YouTube",
2149
2623
  summary: "Embed YouTube",
2150
- icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_components13.YouTubeIcon, {}),
2624
+ icon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_components27.YouTubeIcon, {}),
2151
2625
  resourceType: "ContentResource",
2152
2626
  additionalTypes: ["Canvas", "Annotation"],
2153
2627
  resourceFields: ["id", "type", "service"],
2154
- render: (ctx) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(YouTubeForm, { ...ctx }),
2628
+ render: (ctx) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(YouTubeForm, { ...ctx }),
2155
2629
  supports: {
2156
2630
  parentTypes: ["Annotation", "Manifest", "AnnotationPage"],
2157
2631
  parentFieldMap: {
@@ -2163,38 +2637,53 @@ var youTubeBodyCreator = {
2163
2637
  staticFields: {
2164
2638
  type: "Video"
2165
2639
  }
2166
- };
2640
+ });
2641
+
2642
+ // src/Manifest/ManifestBrowserCreator/index.tsx
2643
+ var import_components28 = require("@manifest-editor/components");
2644
+ var import_creator_api25 = require("@manifest-editor/creator-api");
2167
2645
 
2168
2646
  // src/Manifest/ManifestBrowserCreator/manifest-browser-creator.tsx
2169
- var import_helpers4 = require("@iiif/helpers");
2170
- var import_react11 = require("react");
2647
+ var import_helpers7 = require("@iiif/helpers");
2648
+ var import_react14 = require("react");
2171
2649
  async function createFromManifestBrowserOutput(data, ctx) {
2172
2650
  const targetType = ctx.options.targetType;
2173
2651
  if (Array.isArray(data.output)) {
2174
2652
  throw new Error("Multiple items not yet supported");
2175
2653
  }
2176
- const contentState = (0, import_helpers4.normaliseContentState)(
2177
- typeof data.output === "string" ? (0, import_helpers4.parseContentState)(data.output) : data.output
2654
+ const contentState = (0, import_helpers7.normaliseContentState)(
2655
+ typeof data.output === "string" ? (0, import_helpers7.parseContentState)(data.output) : data.output
2178
2656
  );
2179
2657
  const target = contentState.target[0];
2180
2658
  const previewVault = ctx.getPreviewVault();
2659
+ const thumbnails = (0, import_helpers7.createThumbnailHelper)(previewVault);
2181
2660
  if (!target) {
2182
2661
  throw new Error("No target found in content state");
2183
2662
  }
2184
2663
  if (targetType === "Manifest") {
2185
2664
  const manifestId = target.source.id;
2186
2665
  invariant(manifestId, "Could not find Manifest ID");
2187
- const manifest = await previewVault.get(manifestId);
2666
+ const manifest = await previewVault.loadManifest(manifestId);
2667
+ const thumbnail = await thumbnails.getBestThumbnailAtSize(manifest, { width: 256, height: 256 }, false);
2668
+ invariant(manifest, "Manifest not found");
2188
2669
  return ctx.embed({
2189
2670
  id: target.source.id,
2190
2671
  type: "Manifest",
2191
- label: manifest.label
2672
+ label: manifest.label,
2673
+ summary: manifest.summary,
2674
+ thumbnail: thumbnail?.best ? [
2675
+ {
2676
+ id: thumbnail.best.id,
2677
+ type: "Image"
2678
+ }
2679
+ ] : void 0
2192
2680
  });
2193
2681
  }
2194
2682
  if (targetType === "Collection") {
2195
2683
  const collectionId = target.source.id;
2196
2684
  invariant(collectionId, "Could not find Manifest ID");
2197
- const collection = await previewVault.get(collectionId);
2685
+ const collection = await previewVault.loadManifest(collectionId);
2686
+ invariant(collection, "Collection not found");
2198
2687
  return ctx.embed({
2199
2688
  id: target.source.id,
2200
2689
  type: "Collection",
@@ -2203,20 +2692,19 @@ async function createFromManifestBrowserOutput(data, ctx) {
2203
2692
  }
2204
2693
  throw new Error("Not yet supported.");
2205
2694
  }
2206
- var ManifestBrowserCreatorForm2 = (0, import_react11.lazy)(() => Promise.resolve().then(() => (init_manifest_browser_form_lazy(), manifest_browser_form_lazy_exports)));
2695
+ var ManifestBrowserCreatorForm2 = (0, import_react14.lazy)(() => Promise.resolve().then(() => (init_manifest_browser_form_lazy(), manifest_browser_form_lazy_exports)));
2207
2696
 
2208
2697
  // src/Manifest/ManifestBrowserCreator/index.tsx
2209
2698
  init_manifest_browser_form_lazy();
2210
- var import_components14 = require("@manifest-editor/components");
2211
- var import_jsx_runtime39 = require("react/jsx-runtime");
2212
- var manifestBrowserCreator = {
2699
+ var import_jsx_runtime44 = require("react/jsx-runtime");
2700
+ var manifestBrowserCreator = (0, import_creator_api25.defineCreator)({
2213
2701
  id: "@manifest-editor/manifest-browser-creator",
2214
2702
  create: createFromManifestBrowserOutput,
2215
2703
  label: "IIIF Browser",
2216
2704
  summary: "Browse IIIF Resources",
2217
- icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_components14.IIIFBrowserIcon, {}),
2705
+ icon: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_components28.IIIFBrowserIcon, {}),
2218
2706
  render(ctx) {
2219
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ManifestBrowserCreatorForm, { ...ctx });
2707
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ManifestBrowserCreatorForm, { ...ctx });
2220
2708
  },
2221
2709
  resourceType: "Manifest",
2222
2710
  resourceFields: ["id", "label"],
@@ -2229,7 +2717,7 @@ var manifestBrowserCreator = {
2229
2717
  },
2230
2718
  sideEffects: [],
2231
2719
  staticFields: {}
2232
- };
2720
+ });
2233
2721
 
2234
2722
  // src/index.ts
2235
2723
  var allCreators = [
@@ -2250,5 +2738,8 @@ var allCreators = [
2250
2738
  emptyAnnotationPage,
2251
2739
  noBodyAnnotation,
2252
2740
  internalCanvas,
2253
- captionedImageAnnotation
2741
+ captionedImageAnnotation,
2742
+ imageUrlListCreator,
2743
+ imageUrlListAnnotation,
2744
+ thumbnailCreator
2254
2745
  ];