@manifest-editor/shell 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5,24 +5,6 @@ var __publicField = (obj, key, value) => {
5
5
  return value;
6
6
  };
7
7
 
8
- // src/AppContext/AppContext.tsx
9
- import { createContext, useCallback, useContext, useEffect as useEffect2, useMemo } from "react";
10
-
11
- // ../../node_modules/.pnpm/tiny-invariant@1.3.3/node_modules/tiny-invariant/dist/esm/tiny-invariant.js
12
- var isProduction = false;
13
- var prefix = "Invariant failed";
14
- function invariant(condition, message) {
15
- if (condition) {
16
- return;
17
- }
18
- if (isProduction) {
19
- throw new Error(prefix);
20
- }
21
- var provided = typeof message === "function" ? message() : message;
22
- var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
23
- throw new Error(value);
24
- }
25
-
26
8
  // ../ui/madoc/use-local-storage.ts
27
9
  import { useEffect, useRef, useState } from "react";
28
10
  import mitt from "mitt";
@@ -96,33 +78,133 @@ function useLocalStorage(key, initialValue) {
96
78
  }
97
79
 
98
80
  // src/AppContext/AppContext.tsx
81
+ import {
82
+ createContext as createContext2,
83
+ useCallback as useCallback2,
84
+ useContext as useContext2,
85
+ useEffect as useEffect2,
86
+ useMemo as useMemo2
87
+ } from "react";
88
+
89
+ // ../../node_modules/.pnpm/tiny-invariant@1.3.3/node_modules/tiny-invariant/dist/esm/tiny-invariant.js
90
+ var isProduction = false;
91
+ var prefix = "Invariant failed";
92
+ function invariant(condition, message) {
93
+ if (condition) {
94
+ return;
95
+ }
96
+ if (isProduction) {
97
+ throw new Error(prefix);
98
+ }
99
+ var provided = typeof message === "function" ? message() : message;
100
+ var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
101
+ throw new Error(value);
102
+ }
103
+
104
+ // src/ConfigContext/ConfigContext.tsx
105
+ import { createContext, useCallback, useContext, useMemo, useState as useState2 } from "react";
99
106
  import { jsx } from "react/jsx-runtime";
100
- var PrimeAppReactContext = createContext(null);
101
- var AppReactContext = createContext(null);
102
- var AppStateReactContext = createContext({
107
+ var DEFAULT_CONFIG = {
108
+ previews: [],
109
+ behaviorPresets: [
110
+ "auto-advance",
111
+ "no-auto-advance",
112
+ "repeat",
113
+ "no-repeat",
114
+ "unordered",
115
+ "individuals",
116
+ "continuous",
117
+ "paged",
118
+ "non-paged",
119
+ "facing-pages",
120
+ "multi-part",
121
+ "together",
122
+ "sequence",
123
+ "thumbnail-nav",
124
+ "no-nav",
125
+ "hidden"
126
+ ],
127
+ defaultPreview: null,
128
+ editorConfig: {},
129
+ newTemplates: null,
130
+ i18n: {
131
+ advancedLanguageMode: false,
132
+ availableLanguages: ["en", "cy", "nl", "fr"],
133
+ defaultLanguage: "en"
134
+ },
135
+ editorFeatureFlags: {
136
+ enableMultiImageCanvases: true,
137
+ enableMultiMediaCanvases: true
138
+ },
139
+ uploadBackends: [],
140
+ export: {
141
+ baseIdentifier: null,
142
+ version: 3
143
+ }
144
+ };
145
+ var ConfigReactContext = createContext(DEFAULT_CONFIG);
146
+ var SaveConfigReactContext = createContext(() => {
147
+ });
148
+ function useConfig() {
149
+ return useContext(ConfigReactContext);
150
+ }
151
+ function useSaveConfig() {
152
+ return useContext(SaveConfigReactContext);
153
+ }
154
+ function ConfigProvider({
155
+ children,
156
+ config,
157
+ saveConfig
158
+ }) {
159
+ const [runtimeConfig, setRuntimeConfig] = useState2(null);
160
+ const resolvedConfig = useMemo(
161
+ () => ({
162
+ ...DEFAULT_CONFIG,
163
+ ...config || {},
164
+ ...runtimeConfig || {}
165
+ }),
166
+ [config, runtimeConfig]
167
+ );
168
+ const memoSaveConfig = useCallback(
169
+ (config2) => {
170
+ setRuntimeConfig(config2);
171
+ if (saveConfig) {
172
+ saveConfig(config2);
173
+ }
174
+ },
175
+ [config]
176
+ );
177
+ return /* @__PURE__ */ jsx(SaveConfigReactContext.Provider, { value: memoSaveConfig, children: /* @__PURE__ */ jsx(ConfigReactContext.Provider, { value: resolvedConfig, children }) });
178
+ }
179
+
180
+ // src/AppContext/AppContext.tsx
181
+ import { jsx as jsx2 } from "react/jsx-runtime";
182
+ var PrimeAppReactContext = createContext2(null);
183
+ var AppReactContext = createContext2(null);
184
+ var AppStateReactContext = createContext2({
103
185
  state: null,
104
186
  setState: () => {
105
187
  }
106
188
  });
107
189
  function useAppInstance() {
108
- const ctx = useContext(AppReactContext);
190
+ const ctx = useContext2(AppReactContext);
109
191
  invariant(ctx, "Hook useAppInstance must be used inside <AppProvider />");
110
192
  return ctx;
111
193
  }
112
194
  function useApp() {
113
- const app = useContext(PrimeAppReactContext);
195
+ const app = useContext2(PrimeAppReactContext);
114
196
  invariant(app, "Hook useApp must be used inside <AppProvider />");
115
197
  return app;
116
198
  }
117
199
  function useAppState() {
118
- return useContext(AppStateReactContext);
200
+ return useContext2(AppStateReactContext);
119
201
  }
120
202
  function AppStateProvider(props) {
121
203
  const [state, _setState, stateRef] = useLocalStorage(
122
204
  `app-state/${props.appId}/${props.instanceId}`,
123
205
  props.initialState || {}
124
206
  );
125
- const setState = useCallback((partial) => {
207
+ const setState = useCallback2((partial) => {
126
208
  const existing = stateRef.current ? JSON.parse(stateRef.current || "{}") : {};
127
209
  const partialState = (typeof partial === "function" ? partial(existing) : partial) || {};
128
210
  _setState({
@@ -135,8 +217,11 @@ function AppStateProvider(props) {
135
217
  setState(props.args);
136
218
  }
137
219
  }, [props.appId]);
138
- const ctx = useMemo(() => ({ state: state || {}, setState }), [setState, state]);
139
- return /* @__PURE__ */ jsx(AppStateReactContext.Provider, { value: ctx, children: props.children });
220
+ const ctx = useMemo2(
221
+ () => ({ state: state || {}, setState }),
222
+ [setState, state]
223
+ );
224
+ return /* @__PURE__ */ jsx2(AppStateReactContext.Provider, { value: ctx, children: props.children });
140
225
  }
141
226
  function AppProvider({
142
227
  instanceId,
@@ -146,17 +231,29 @@ function AppProvider({
146
231
  children,
147
232
  initialState
148
233
  }) {
149
- const ctx = useMemo(() => ({ instanceId, appId, args }), [instanceId, appId, args]);
150
- const _initialState = useMemo(() => initialState || {}, [instanceId]);
151
- return /* @__PURE__ */ jsx(PrimeAppReactContext.Provider, { value: definition, children: /* @__PURE__ */ jsx(AppReactContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(AppStateProvider, { instanceId: ctx.instanceId, appId: ctx.appId, args: ctx.args, initialState: _initialState, children }) }) });
234
+ const ctx = useMemo2(
235
+ () => ({ instanceId, appId, args }),
236
+ [instanceId, appId, args]
237
+ );
238
+ const _initialState = useMemo2(() => initialState || {}, [instanceId]);
239
+ return /* @__PURE__ */ jsx2(ConfigProvider, { config: definition.config || {}, children: /* @__PURE__ */ jsx2(PrimeAppReactContext.Provider, { value: definition, children: /* @__PURE__ */ jsx2(AppReactContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx2(
240
+ AppStateProvider,
241
+ {
242
+ instanceId: ctx.instanceId,
243
+ appId: ctx.appId,
244
+ args: ctx.args,
245
+ initialState: _initialState,
246
+ children
247
+ }
248
+ ) }) }) });
152
249
  }
153
250
 
154
251
  // src/AppContext/MultiAppContext.tsx
155
- import { createContext as createContext2, useContext as useContext2, useMemo as useMemo2 } from "react";
156
- import { jsx as jsx2 } from "react/jsx-runtime";
157
- var MultiAppContext = createContext2(null);
252
+ import { createContext as createContext3, useContext as useContext3, useMemo as useMemo3 } from "react";
253
+ import { jsx as jsx3 } from "react/jsx-runtime";
254
+ var MultiAppContext = createContext3(null);
158
255
  function useApps() {
159
- const ctx = useContext2(MultiAppContext);
256
+ const ctx = useContext3(MultiAppContext);
160
257
  invariant(ctx, "Hook useApps must be used inside <MultiAppProvider />");
161
258
  return ctx;
162
259
  }
@@ -186,7 +283,7 @@ function MultiAppProvider({
186
283
  changeApp({ id: collectionApp });
187
284
  }
188
285
  };
189
- const ctx = useMemo2(
286
+ const ctx = useMemo3(
190
287
  () => ({
191
288
  currentApp: currentApp || { id: defaultApp },
192
289
  initialApp: initialApp || { id: defaultApp },
@@ -200,14 +297,14 @@ function MultiAppProvider({
200
297
  if (!currentApp || !currentFullApp) {
201
298
  return null;
202
299
  }
203
- return /* @__PURE__ */ jsx2(
300
+ return /* @__PURE__ */ jsx3(
204
301
  AppProvider,
205
302
  {
206
303
  appId: currentApp.id,
207
304
  definition: currentFullApp,
208
305
  instanceId: currentApp.id + instanceId,
209
306
  args: currentApp.args,
210
- children: /* @__PURE__ */ jsx2(MultiAppContext.Provider, { value: ctx, children })
307
+ children: /* @__PURE__ */ jsx3(MultiAppContext.Provider, { value: ctx, children })
211
308
  }
212
309
  );
213
310
  }
@@ -284,11 +381,90 @@ var ContextButton = styled.button`
284
381
  letter-spacing: -0.42px;
285
382
  `;
286
383
 
384
+ // src/PreviewButton/PreviewButton.tsx
385
+ import { DownloadButton } from "@manifest-editor/components";
386
+
387
+ // ../ui/icons/CloseIcon.tsx
388
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
389
+ var CloseIcon = ({ height = 16 }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", height, viewBox: "0 0 24 24", width: "24px", fill: "#000000", children: [
390
+ /* @__PURE__ */ jsx4("path", { d: "M0 0h24v24H0z", fill: "none" }),
391
+ /* @__PURE__ */ jsx4("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" })
392
+ ] });
393
+
394
+ // ../ui/icons/DownIcon.tsx
395
+ import { jsx as jsx5 } from "react/jsx-runtime";
396
+ var DownIcon = ({ rotate = 0, ...props }) => /* @__PURE__ */ jsx5(
397
+ "svg",
398
+ {
399
+ version: "1.2",
400
+ xmlns: "http://www.w3.org/2000/svg",
401
+ overflow: "visible",
402
+ preserveAspectRatio: "none",
403
+ viewBox: "0 0 24 24",
404
+ width: "1em",
405
+ height: "1em",
406
+ style: {
407
+ fill: "rgba(0, 0, 0, 0.6)",
408
+ transform: `rotate(${rotate}deg)`,
409
+ transition: "transform 0.2s"
410
+ },
411
+ ...props,
412
+ children: /* @__PURE__ */ jsx5(
413
+ "path",
414
+ {
415
+ d: "M8.12 9.29 12 13.17l3.88-3.88a.996.996 0 1 1 1.41 1.41l-4.59 4.59a.996.996 0 0 1-1.41 0L6.7 10.7a.996.996 0 0 1 0-1.41c.39-.38 1.03-.39 1.42 0z",
416
+ fill: "currentColor"
417
+ }
418
+ )
419
+ }
420
+ );
421
+
422
+ // src/PreviewButton/PreviewButton.tsx
423
+ import useDropdownMenu from "react-accessible-dropdown-menu-hook";
424
+ import { useVault as useVault2 } from "react-iiif-vault";
425
+
426
+ // src/AppResourceProvider/AppResourceProvider.tsx
427
+ import { createContext as createContext4, useContext as useContext4 } from "react";
428
+ import { CollectionContext, ManifestContext, VaultProvider, useExistingVault } from "react-iiif-vault";
429
+ import { jsx as jsx6 } from "react/jsx-runtime";
430
+ var AppResourceReactProvider = createContext4(null);
431
+ var AppResourceInstanceReactProvider = createContext4(null);
432
+ function useAppResourceInstance() {
433
+ const ctx = useContext4(AppResourceInstanceReactProvider);
434
+ const resource = useContext4(AppResourceReactProvider);
435
+ const instanceId = ctx || resource?.id;
436
+ invariant(instanceId, "useResourceInstance can only be called from inside <ResourceProvider />");
437
+ return instanceId;
438
+ }
439
+ function useAppResource() {
440
+ const ctx = useContext4(AppResourceReactProvider);
441
+ invariant(ctx, "useResource can only be called from inside <ResourceProvider />");
442
+ return ctx;
443
+ }
444
+ function AppResourceInstanceProvider({ id, children }) {
445
+ if (!id) {
446
+ return children;
447
+ }
448
+ return /* @__PURE__ */ jsx6(AppResourceInstanceReactProvider.Provider, { value: id, children });
449
+ }
450
+ function AppResourceProvider({ resource, children }) {
451
+ const vault = useExistingVault();
452
+ let inner = children;
453
+ if (resource && resource.type === "Manifest") {
454
+ inner = /* @__PURE__ */ jsx6(VaultProvider, { vault: vault || void 0, children: /* @__PURE__ */ jsx6(ManifestContext, { manifest: resource.id || "", children }) });
455
+ }
456
+ if (resource && resource.type === "Collection") {
457
+ inner = /* @__PURE__ */ jsx6(VaultProvider, { vault: vault || void 0, children: /* @__PURE__ */ jsx6(CollectionContext, { collection: resource.id || "", children }) });
458
+ }
459
+ return /* @__PURE__ */ jsx6(AppResourceReactProvider.Provider, { value: resource, children: inner });
460
+ }
461
+
287
462
  // src/PreviewContext/PreviewContext.tsx
288
- import { createContext as createContext4, memo, useContext as useContext4, useEffect as useEffect3, useMemo as useMemo4, useReducer } from "react";
463
+ import { createContext as createContext5, memo, useContext as useContext5, useEffect as useEffect3, useMemo as useMemo5, useReducer } from "react";
289
464
 
290
465
  // src/PreviewContext/PreviewContext.hooks.ts
291
- import { useMemo as useMemo3 } from "react";
466
+ import { useMemo as useMemo4 } from "react";
467
+ import { useVault } from "react-iiif-vault";
292
468
 
293
469
  // src/PreviewContext/previews/ExternalManifestUrlPreview.ts
294
470
  var ExternalManifestUrlPreview = class {
@@ -461,51 +637,12 @@ var IIIFPreviewService = class {
461
637
  }
462
638
  };
463
639
 
464
- // src/PreviewContext/PreviewContext.hooks.ts
465
- import { useVault } from "react-iiif-vault";
466
-
467
- // src/AppResourceProvider/AppResourceProvider.tsx
468
- import { createContext as createContext3, useContext as useContext3 } from "react";
469
- import { CollectionContext, ManifestContext, VaultProvider, useExistingVault } from "react-iiif-vault";
470
- import { jsx as jsx3 } from "react/jsx-runtime";
471
- var AppResourceReactProvider = createContext3(null);
472
- var AppResourceInstanceReactProvider = createContext3(null);
473
- function useAppResourceInstance() {
474
- const ctx = useContext3(AppResourceInstanceReactProvider);
475
- const resource = useContext3(AppResourceReactProvider);
476
- const instanceId = ctx || resource?.id;
477
- invariant(instanceId, "useResourceInstance can only be called from inside <ResourceProvider />");
478
- return instanceId;
479
- }
480
- function useAppResource() {
481
- const ctx = useContext3(AppResourceReactProvider);
482
- invariant(ctx, "useResource can only be called from inside <ResourceProvider />");
483
- return ctx;
484
- }
485
- function AppResourceInstanceProvider({ id, children }) {
486
- if (!id) {
487
- return children;
488
- }
489
- return /* @__PURE__ */ jsx3(AppResourceInstanceReactProvider.Provider, { value: id, children });
490
- }
491
- function AppResourceProvider({ resource, children }) {
492
- const vault = useExistingVault();
493
- let inner = children;
494
- if (resource && resource.type === "Manifest") {
495
- inner = /* @__PURE__ */ jsx3(VaultProvider, { vault: vault || void 0, children: /* @__PURE__ */ jsx3(ManifestContext, { manifest: resource.id || "", children }) });
496
- }
497
- if (resource && resource.type === "Collection") {
498
- inner = /* @__PURE__ */ jsx3(VaultProvider, { vault: vault || void 0, children: /* @__PURE__ */ jsx3(CollectionContext, { collection: resource.id || "", children }) });
499
- }
500
- return /* @__PURE__ */ jsx3(AppResourceReactProvider.Provider, { value: resource, children: inner });
501
- }
502
-
503
640
  // src/PreviewContext/PreviewContext.hooks.ts
504
641
  function usePreviewActions(state, dispatch, handlers, previews, setPreviews) {
505
642
  const resource = useAppResource();
506
643
  const instanceId = useAppResourceInstance();
507
644
  const vault = useVault();
508
- const previewActions = useMemo3(
645
+ const previewActions = useMemo4(
509
646
  () => ({
510
647
  setPreview: (preview) => {
511
648
  if (!preview)
@@ -518,7 +655,7 @@ function usePreviewActions(state, dispatch, handlers, previews, setPreviews) {
518
655
  }),
519
656
  [setPreviews, instanceId]
520
657
  );
521
- const [handlerMap, providesMap] = useMemo3(() => {
658
+ const [handlerMap, providesMap] = useMemo4(() => {
522
659
  const map = {};
523
660
  const providesMap2 = {};
524
661
  for (const handler of handlers) {
@@ -572,8 +709,8 @@ function usePreviewActions(state, dispatch, handlers, previews, setPreviews) {
572
709
  async function selectPreview(id) {
573
710
  const selectedHandler = handlerMap[id];
574
711
  if (selectedHandler && instanceId) {
575
- await activatePreview(id);
576
712
  dispatch({ type: "selectPreview", payload: id });
713
+ await activatePreview(id);
577
714
  }
578
715
  }
579
716
  async function getPreviewLink() {
@@ -625,18 +762,18 @@ function usePreviewActions(state, dispatch, handlers, previews, setPreviews) {
625
762
  dispatch({ type: "activatePreview", payload: contextualPreview.id });
626
763
  } else {
627
764
  Object.assign(context, existing?.data || {});
628
- dispatch({ type: "activatePreview", payload: id });
765
+ dispatch({ type: "activatePreview", payload: existing.id });
629
766
  }
630
767
  }
631
768
  const created = await selectedHandler.createPreview(instanceId, resource, vault, context);
632
769
  if (created) {
633
770
  previewActions.setPreview(created);
634
- dispatch({ type: "activatePreview", payload: id });
771
+ dispatch({ type: "activatePreview", payload: created.id });
635
772
  }
636
773
  }
637
774
  }
638
775
  }
639
- return useMemo3(
776
+ return useMemo4(
640
777
  () => ({ selectPreview, deletePreview, focusPreview, activatePreview, updatePreviews, getPreviewLink }),
641
778
  // Dispatch has a stable identity.
642
779
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -644,7 +781,7 @@ function usePreviewActions(state, dispatch, handlers, previews, setPreviews) {
644
781
  );
645
782
  }
646
783
  function usePreviewHandlers(configs) {
647
- return useMemo3(() => {
784
+ return useMemo4(() => {
648
785
  const handlers = [];
649
786
  for (const config of configs) {
650
787
  switch (config.type) {
@@ -697,9 +834,9 @@ function getDefaultPreviewState() {
697
834
  }
698
835
 
699
836
  // src/PreviewContext/PreviewContext.tsx
700
- import { jsx as jsx4 } from "react/jsx-runtime";
701
- var PreviewReactContext = createContext4(null);
702
- var AvailablePreviewReactContext = createContext4([]);
837
+ import { jsx as jsx7 } from "react/jsx-runtime";
838
+ var PreviewReactContext = createContext5(null);
839
+ var AvailablePreviewReactContext = createContext5([]);
703
840
  var PreviewProvider = memo(function PreviewProvider2({
704
841
  children,
705
842
  configs = []
@@ -709,7 +846,7 @@ var PreviewProvider = memo(function PreviewProvider2({
709
846
  const [previews, setPreviews] = useLocalStorage(`preview-${instanceId}`, []);
710
847
  const [state, dispatch] = useReducer(previewContextReducer, void 0, getDefaultPreviewState);
711
848
  const actions = usePreviewActions(state, dispatch, handlers, previews, setPreviews);
712
- const context = useMemo4(
849
+ const context = useMemo5(
713
850
  () => ({ configs, actions, handlers, ...state }),
714
851
  [actions, configs, handlers, state]
715
852
  );
@@ -729,13 +866,13 @@ var PreviewProvider = memo(function PreviewProvider2({
729
866
  }
730
867
  }
731
868
  }, [instanceId]);
732
- return /* @__PURE__ */ jsx4(AvailablePreviewReactContext.Provider, { value: previews, children: /* @__PURE__ */ jsx4(PreviewReactContext.Provider, { value: context, children }) });
869
+ return /* @__PURE__ */ jsx7(AvailablePreviewReactContext.Provider, { value: previews, children: /* @__PURE__ */ jsx7(PreviewReactContext.Provider, { value: context, children }) });
733
870
  });
734
871
  function usePreviews() {
735
- return useContext4(AvailablePreviewReactContext);
872
+ return useContext5(AvailablePreviewReactContext);
736
873
  }
737
874
  function usePreviewContext() {
738
- const ctx = useContext4(PreviewReactContext);
875
+ const ctx = useContext5(PreviewReactContext);
739
876
  invariant(ctx, "usePreviewContext() can only be called from inside <PreviewProvider />");
740
877
  return ctx;
741
878
  }
@@ -945,134 +1082,16 @@ var ButtonEmpty = styled3.div`
945
1082
  `;
946
1083
 
947
1084
  // src/PreviewButton/PreviewButton.tsx
948
- import useDropdownMenu from "react-accessible-dropdown-menu-hook";
949
-
950
- // ../ui/icons/DownIcon.tsx
951
- import { jsx as jsx5 } from "react/jsx-runtime";
952
- var DownIcon = ({ rotate = 0, ...props }) => /* @__PURE__ */ jsx5(
953
- "svg",
954
- {
955
- version: "1.2",
956
- xmlns: "http://www.w3.org/2000/svg",
957
- overflow: "visible",
958
- preserveAspectRatio: "none",
959
- viewBox: "0 0 24 24",
960
- width: "1em",
961
- height: "1em",
962
- style: {
963
- fill: "rgba(0, 0, 0, 0.6)",
964
- transform: `rotate(${rotate}deg)`,
965
- transition: "transform 0.2s"
966
- },
967
- ...props,
968
- children: /* @__PURE__ */ jsx5(
969
- "path",
970
- {
971
- d: "M8.12 9.29 12 13.17l3.88-3.88a.996.996 0 1 1 1.41 1.41l-4.59 4.59a.996.996 0 0 1-1.41 0L6.7 10.7a.996.996 0 0 1 0-1.41c.39-.38 1.03-.39 1.42 0z",
972
- fill: "currentColor"
973
- }
974
- )
975
- }
976
- );
977
-
978
- // ../ui/icons/CloseIcon.tsx
979
- import { jsx as jsx6, jsxs } from "react/jsx-runtime";
980
- var CloseIcon = ({ height = 16 }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", height, viewBox: "0 0 24 24", width: "24px", fill: "#000000", children: [
981
- /* @__PURE__ */ jsx6("path", { d: "M0 0h24v24H0z", fill: "none" }),
982
- /* @__PURE__ */ jsx6("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" })
983
- ] });
984
-
985
- // src/PreviewButton/PreviewButton.tsx
986
- import { useVault as useVault2 } from "react-iiif-vault";
987
- import { DownloadButton } from "@manifest-editor/components";
988
-
989
- // src/ConfigContext/ConfigContext.tsx
990
- import { createContext as createContext5, useCallback as useCallback2, useContext as useContext5, useMemo as useMemo5, useState as useState2 } from "react";
991
- import { jsx as jsx7 } from "react/jsx-runtime";
992
- var DEFAULT_CONFIG = {
993
- previews: [],
994
- behaviorPresets: [
995
- "auto-advance",
996
- "no-auto-advance",
997
- "repeat",
998
- "no-repeat",
999
- "unordered",
1000
- "individuals",
1001
- "continuous",
1002
- "paged",
1003
- "non-paged",
1004
- "facing-pages",
1005
- "multi-part",
1006
- "together",
1007
- "sequence",
1008
- "thumbnail-nav",
1009
- "no-nav",
1010
- "hidden"
1011
- ],
1012
- defaultPreview: null,
1013
- editorConfig: {},
1014
- newTemplates: null,
1015
- i18n: {
1016
- advancedLanguageMode: false,
1017
- availableLanguages: ["en", "cy", "nl", "fr"],
1018
- defaultLanguage: "en"
1019
- },
1020
- editorFeatureFlags: {
1021
- enableMultiImageCanvases: true,
1022
- enableMultiMediaCanvases: true
1023
- },
1024
- uploadBackends: [],
1025
- export: {
1026
- baseIdentifier: null,
1027
- version: 3
1028
- }
1029
- };
1030
- var ConfigReactContext = createContext5(DEFAULT_CONFIG);
1031
- var SaveConfigReactContext = createContext5(() => {
1032
- });
1033
- function useConfig() {
1034
- return useContext5(ConfigReactContext);
1035
- }
1036
- function useSaveConfig() {
1037
- return useContext5(SaveConfigReactContext);
1038
- }
1039
- function ConfigProvider({
1040
- children,
1041
- config,
1042
- saveConfig
1043
- }) {
1044
- const [runtimeConfig, setRuntimeConfig] = useState2(null);
1045
- const resolvedConfig = useMemo5(
1046
- () => ({
1047
- ...DEFAULT_CONFIG,
1048
- ...config || {},
1049
- ...runtimeConfig || {}
1050
- }),
1051
- [config, runtimeConfig]
1052
- );
1053
- const memoSaveConfig = useCallback2(
1054
- (config2) => {
1055
- setRuntimeConfig(config2);
1056
- if (saveConfig) {
1057
- saveConfig(config2);
1058
- }
1059
- },
1060
- [config]
1061
- );
1062
- return /* @__PURE__ */ jsx7(SaveConfigReactContext.Provider, { value: memoSaveConfig, children: /* @__PURE__ */ jsx7(ConfigReactContext.Provider, { value: resolvedConfig, children }) });
1063
- }
1064
-
1065
- // src/PreviewButton/PreviewButton.tsx
1066
- import { Fragment, jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
1067
- function PreviewButton({ downloadEnabled, fileName }) {
1068
- const { active, configs, actions, selected } = usePreviewContext();
1069
- const vault = useVault2();
1070
- const config = useConfig();
1071
- const resource = useAppResource();
1072
- const configsToShow = configs.filter((c) => c.type === "external-manifest-preview");
1073
- const { isOpen, buttonProps, itemProps } = useDropdownMenu(configsToShow.length);
1074
- if (configsToShow.length === 0) {
1075
- return /* @__PURE__ */ jsx8(ButtonEmpty, { children: "Preview not available" });
1085
+ import { Fragment, jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
1086
+ function PreviewButton({ downloadEnabled, fileName }) {
1087
+ const { active, configs, actions, selected } = usePreviewContext();
1088
+ const vault = useVault2();
1089
+ const config = useConfig();
1090
+ const resource = useAppResource();
1091
+ const configsToShow = configs.filter((c) => c.type === "external-manifest-preview");
1092
+ const { isOpen, buttonProps, itemProps } = useDropdownMenu(configsToShow.length);
1093
+ if (configsToShow.length === 0) {
1094
+ return /* @__PURE__ */ jsx8(ButtonEmpty, { children: "Preview not available" });
1076
1095
  }
1077
1096
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
1078
1097
  downloadEnabled ? /* @__PURE__ */ jsx8("div", { className: "mr-4", children: /* @__PURE__ */ jsx8(
@@ -1098,9 +1117,7 @@ function PreviewButton({ downloadEnabled, fileName }) {
1098
1117
  if (defaultPreviewId) {
1099
1118
  const found = configs.find((c) => c.id === defaultPreviewId);
1100
1119
  if (found) {
1101
- console.log(found, { defaultPreviewId });
1102
1120
  actions.selectPreview(found.id);
1103
- actions.updatePreviews();
1104
1121
  return;
1105
1122
  }
1106
1123
  }
@@ -1116,7 +1133,15 @@ function PreviewButton({ downloadEnabled, fileName }) {
1116
1133
  const inactive = active.indexOf(config2.id) === -1;
1117
1134
  return /* @__PURE__ */ jsxs2(MenuItem, { ...itemProps[key], children: [
1118
1135
  /* @__PURE__ */ jsx8(MenuItemStatus, { $status: inactive ? "available" : config2.id === selected ? "active" : "configured" }),
1119
- /* @__PURE__ */ jsx8(MenuItemLabel, { onClick: () => actions.selectPreview(config2.id), children: config2.label }),
1136
+ /* @__PURE__ */ jsx8(
1137
+ MenuItemLabel,
1138
+ {
1139
+ onClick: () => {
1140
+ actions.selectPreview(config2.id);
1141
+ },
1142
+ children: config2.label
1143
+ }
1144
+ ),
1120
1145
  !inactive ? /* @__PURE__ */ jsx8(MenuItemClose, { onClick: () => actions.deletePreview(config2.id), children: /* @__PURE__ */ jsx8(CloseIcon, {}) }) : null
1121
1146
  ] }, config2.id);
1122
1147
  }) })
@@ -1158,17 +1183,432 @@ function AppMenuProvider({ children, menu }) {
1158
1183
  return /* @__PURE__ */ jsx10(ReactAppMenuContext.Provider, { value: menu, children });
1159
1184
  }
1160
1185
 
1186
+ // src/AtlasStore/AtlasStoreProvider.tsx
1187
+ import { createContext as createContext8, useContext as useContext8, useMemo as useMemo6 } from "react";
1188
+
1189
+ // src/AtlasStore/AtlasStore.ts
1190
+ import { createHelper } from "polygon-editor";
1191
+ import { createStore } from "zustand/vanilla";
1192
+
1193
+ // src/AtlasStore/polygon-to-bounding-box.ts
1194
+ function polygonToBoundingBox(polygon) {
1195
+ if (!polygon) {
1196
+ return null;
1197
+ }
1198
+ if (polygon.points.length > 2) {
1199
+ const x1 = Math.min(...polygon.points.map((p) => p[0]));
1200
+ const y1 = Math.min(...polygon.points.map((p) => p[1]));
1201
+ const x2 = Math.max(0, ...polygon.points.map((p) => p[0]));
1202
+ const y2 = Math.max(0, ...polygon.points.map((p) => p[1]));
1203
+ return {
1204
+ x: x1,
1205
+ y: y1,
1206
+ width: x2 - x1,
1207
+ height: y2 - y1
1208
+ };
1209
+ }
1210
+ return null;
1211
+ }
1212
+
1213
+ // src/AtlasStore/AtlasStore.ts
1214
+ function polygonToTarget(polygon) {
1215
+ if (!polygon)
1216
+ return null;
1217
+ return {
1218
+ type: "SvgSelector",
1219
+ value: `<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g><path d='M${polygon.points.map((p) => p.join(",")).join(" ")}${polygon.open ? "" : " Z"}' /></g></svg>`
1220
+ };
1221
+ }
1222
+ function requestToAnnotationResponse(request) {
1223
+ if (request.type === "polygon") {
1224
+ return {
1225
+ polygon: {
1226
+ points: request.points || [],
1227
+ open: request.open || false
1228
+ },
1229
+ requestType: "polygon",
1230
+ boundingBox: polygonToBoundingBox({
1231
+ points: request.points || [],
1232
+ open: false
1233
+ }),
1234
+ target: polygonToTarget({ points: request.points || [], open: false })
1235
+ };
1236
+ }
1237
+ const box = request.selector;
1238
+ if (box) {
1239
+ const points = [
1240
+ [box.x, box.y],
1241
+ [box.x + box.width, box.y],
1242
+ [box.x + box.width, box.y + box.height],
1243
+ [box.x, box.y + box.height]
1244
+ ];
1245
+ return {
1246
+ polygon: {
1247
+ points,
1248
+ open: false
1249
+ },
1250
+ requestType: request.type,
1251
+ boundingBox: box,
1252
+ target: polygonToTarget({ points, open: false })
1253
+ };
1254
+ }
1255
+ return {
1256
+ polygon: { points: [], open: false },
1257
+ requestType: request.type,
1258
+ boundingBox: null,
1259
+ target: null
1260
+ };
1261
+ }
1262
+ var defaultSlowState = {
1263
+ shapeId: null,
1264
+ noShape: true,
1265
+ transitioning: false,
1266
+ actionIntentType: null,
1267
+ transitionIntentType: null,
1268
+ selectedPoints: [],
1269
+ hasClosestLine: false,
1270
+ modifiers: {
1271
+ Alt: false,
1272
+ Shift: false,
1273
+ Meta: false,
1274
+ proximity: 0
1275
+ // default value.
1276
+ },
1277
+ showBoundingBox: false,
1278
+ currentModifiers: {},
1279
+ validIntentKeys: {},
1280
+ pointerInsideShape: false,
1281
+ closestPoint: null,
1282
+ transitionModifiers: null,
1283
+ selectedStamp: null,
1284
+ lineMode: false,
1285
+ lineBoxMode: false,
1286
+ drawMode: false,
1287
+ bezierLines: [],
1288
+ boxMode: false,
1289
+ fixedAspectRatio: false
1290
+ };
1291
+ function createAtlasStore({ events: events2 }) {
1292
+ const store = createStore((set, get) => {
1293
+ let runtime = null;
1294
+ const onSave = (input) => {
1295
+ set(
1296
+ (s) => s.tool.requestId ? { polygon: { ...input, id: s.tool.requestId } } : {
1297
+ polygon: { id: void 0, points: [], open: true }
1298
+ }
1299
+ );
1300
+ };
1301
+ const polygons = createHelper(null, onSave);
1302
+ return {
1303
+ mode: "explore",
1304
+ tool: {
1305
+ enabled: false,
1306
+ requestId: null,
1307
+ canvasId: null
1308
+ },
1309
+ requestType: null,
1310
+ history: polygons.history,
1311
+ polygon: null,
1312
+ validRequestIds: [],
1313
+ stableViewport: null,
1314
+ canvasRelativePositions: {},
1315
+ canvasViewports: {},
1316
+ polygons,
1317
+ polygonState: defaultSlowState,
1318
+ setToolCanvasId: (canvasId) => {
1319
+ set((state) => ({ tool: { ...state.tool, canvasId } }));
1320
+ },
1321
+ switchTool: {
1322
+ draw() {
1323
+ set({ mode: "sketch" });
1324
+ helper.stamps.clear();
1325
+ helper.draw.enable();
1326
+ },
1327
+ polygon() {
1328
+ set({ mode: "sketch" });
1329
+ helper.stamps.clear();
1330
+ helper.draw.disable();
1331
+ helper.modes.disableLineBoxMode();
1332
+ helper.modes.disableLineMode();
1333
+ },
1334
+ line() {
1335
+ set({ mode: "sketch" });
1336
+ helper.modes.enableLineMode();
1337
+ },
1338
+ lineBox() {
1339
+ set({ mode: "sketch" });
1340
+ helper.modes.enableLineBoxMode();
1341
+ },
1342
+ square() {
1343
+ set({ mode: "sketch" });
1344
+ helper.stamps.square();
1345
+ },
1346
+ triangle() {
1347
+ set({ mode: "sketch" });
1348
+ helper.stamps.triangle();
1349
+ },
1350
+ hexagon() {
1351
+ set({ mode: "sketch" });
1352
+ helper.stamps.hexagon();
1353
+ },
1354
+ circle() {
1355
+ set({ mode: "sketch" });
1356
+ helper.stamps.circle();
1357
+ },
1358
+ remove() {
1359
+ helper.key.down("Backspace");
1360
+ }
1361
+ },
1362
+ reset: () => {
1363
+ const state = get();
1364
+ if (state.tool.requestId) {
1365
+ state.cancelRequest(state.tool.requestId);
1366
+ }
1367
+ },
1368
+ setPolygonState: (state) => set({
1369
+ polygonState: typeof state === "function" ? state(get().polygonState) : state
1370
+ }),
1371
+ getRequestId: () => {
1372
+ const requestId = Math.random().toString(36).slice(2);
1373
+ set((state) => ({
1374
+ validRequestIds: [...state.validRequestIds, requestId]
1375
+ }));
1376
+ return {
1377
+ requestId,
1378
+ clear: () => {
1379
+ if (get().tool.requestId === requestId) {
1380
+ }
1381
+ set((state) => ({
1382
+ tool: state.tool.requestId === requestId ? { enabled: false, requestId: null, canvasId: null } : state.tool,
1383
+ validRequestIds: state.validRequestIds.filter((id) => id !== requestId)
1384
+ }));
1385
+ }
1386
+ };
1387
+ },
1388
+ cancelRequest: (requestId) => {
1389
+ set((state) => ({
1390
+ mode: "explore",
1391
+ tool: state.tool.requestId === requestId ? { enabled: false, requestId: null, canvasId: null } : state.tool,
1392
+ validRequestIds: state.validRequestIds.filter((id) => id !== requestId)
1393
+ }));
1394
+ events2.emit("atlas.request-cancelled", { id: requestId });
1395
+ },
1396
+ requestAnnotation: async (request, options) => {
1397
+ const response = requestToAnnotationResponse(request);
1398
+ try {
1399
+ const { points = [], open = true } = response.polygon || {};
1400
+ const { requestId, canvasId = null, toolId } = options;
1401
+ const state = get();
1402
+ const isValid = state.validRequestIds.includes(requestId);
1403
+ if (!isValid)
1404
+ return null;
1405
+ if (state.tool.enabled)
1406
+ return null;
1407
+ polygons.setShape({ id: requestId, points, open });
1408
+ if (request.type === "box") {
1409
+ polygons.modes.enableBoxMode();
1410
+ }
1411
+ if (request.type === "target") {
1412
+ polygons.modes.enableBoxMode();
1413
+ polygons.modes.lockAspectRatio();
1414
+ }
1415
+ events2.emit("atlas.annotation-request", { id: requestId });
1416
+ set({
1417
+ polygon: { id: requestId, points, open },
1418
+ mode: "sketch",
1419
+ requestType: request.type,
1420
+ tool: {
1421
+ enabled: true,
1422
+ requestId,
1423
+ canvasId
1424
+ }
1425
+ });
1426
+ if (toolId) {
1427
+ state.switchTool[toolId]?.();
1428
+ } else if (points.length === 0) {
1429
+ state.switchTool.square();
1430
+ }
1431
+ return new Promise((resolve) => {
1432
+ const cancelHandler = (e) => {
1433
+ if (e.id !== requestId)
1434
+ return;
1435
+ set({
1436
+ mode: "explore",
1437
+ tool: {
1438
+ requestId: null,
1439
+ enabled: false,
1440
+ canvasId: null
1441
+ }
1442
+ });
1443
+ events2.off("atlas.request-cancelled", cancelHandler);
1444
+ events2.off("atlas.annotation-completed", handler);
1445
+ resolve(null);
1446
+ };
1447
+ const handler = (e) => {
1448
+ if (e.id !== requestId)
1449
+ return;
1450
+ set({
1451
+ mode: "explore",
1452
+ tool: {
1453
+ requestId: null,
1454
+ enabled: false,
1455
+ canvasId: null
1456
+ }
1457
+ });
1458
+ events2.off("atlas.annotation-completed", handler);
1459
+ events2.off("atlas.request-cancelled", cancelHandler);
1460
+ resolve(e);
1461
+ };
1462
+ events2.on("atlas.request-cancelled", cancelHandler);
1463
+ events2.on("atlas.annotation-completed", handler);
1464
+ });
1465
+ } catch (err) {
1466
+ return null;
1467
+ }
1468
+ },
1469
+ completeRequest: (requestId) => {
1470
+ if (typeof requestId === "string" && requestId) {
1471
+ if (requestId !== get().tool.requestId) {
1472
+ return;
1473
+ }
1474
+ }
1475
+ const polygon = get().polygon;
1476
+ if (!polygon)
1477
+ return;
1478
+ events2.emit("atlas.annotation-completed", {
1479
+ id: polygon.id,
1480
+ polygon,
1481
+ requestType: get().requestType,
1482
+ target: polygonToTarget(polygon),
1483
+ canvasId: get().tool.canvasId,
1484
+ boundingBox: polygonToBoundingBox(polygon)
1485
+ });
1486
+ },
1487
+ setAtlasRuntime: (newRuntime) => {
1488
+ runtime = newRuntime;
1489
+ events2.emit("atlas.ready", { runtime: newRuntime });
1490
+ runtime.world.addLayoutSubscriber((ev, data) => {
1491
+ if (ev === "event-activation" || ev === "zoom-to" || ev === "go-home") {
1492
+ if (runtime?._lastGoodScale && !Number.isNaN(runtime._lastGoodScale)) {
1493
+ helper.setScale(1 / runtime._lastGoodScale);
1494
+ }
1495
+ }
1496
+ });
1497
+ },
1498
+ clearAtlasRuntime: () => {
1499
+ runtime = null;
1500
+ set({ stableViewport: null });
1501
+ },
1502
+ setCanvasRelativePosition: (canvasId, position) => {
1503
+ set((state) => ({
1504
+ canvasRelativePositions: {
1505
+ ...state.canvasRelativePositions,
1506
+ [canvasId]: position
1507
+ }
1508
+ }));
1509
+ },
1510
+ clearCanvasRelativePosition: (canvasId) => {
1511
+ set((state) => {
1512
+ const newPositions = { ...state.canvasRelativePositions };
1513
+ delete newPositions[canvasId];
1514
+ return { canvasRelativePositions: newPositions };
1515
+ });
1516
+ },
1517
+ changeMode: (mode) => {
1518
+ set({ mode });
1519
+ },
1520
+ // Navigation controls
1521
+ nudgeLeft: () => {
1522
+ },
1523
+ nudgeRight: () => {
1524
+ },
1525
+ nudgeUp: () => {
1526
+ },
1527
+ nudgeDown: () => {
1528
+ },
1529
+ zoomIn: () => {
1530
+ runtime?.world?.zoomIn();
1531
+ },
1532
+ zoomOut: () => {
1533
+ runtime?.world?.zoomOut();
1534
+ },
1535
+ goHome: () => {
1536
+ runtime?.world?.goHome();
1537
+ }
1538
+ };
1539
+ });
1540
+ const helper = store.getState().polygons;
1541
+ events2.on("atlas.annotation-request", () => {
1542
+ helper.clock.start((state, slowState, dt) => {
1543
+ events2.emit("atlas.polygon-render", { state, slowState, dt });
1544
+ }, store.getState().setPolygonState);
1545
+ });
1546
+ events2.on("atlas.annotation-completed", () => {
1547
+ helper.clock.stop();
1548
+ });
1549
+ events2.on("atlas.request-cancelled", () => {
1550
+ helper.clock.stop();
1551
+ });
1552
+ return store;
1553
+ }
1554
+
1555
+ // src/hooks/use-event.tsx
1556
+ import mitt2 from "mitt";
1557
+ import { createContext as createContext7, useContext as useContext7, useEffect as useEffect4 } from "react";
1558
+ import { jsx as jsx11 } from "react/jsx-runtime";
1559
+ var events = mitt2();
1560
+ var ReactEmitterContext = createContext7(events);
1561
+ function EventEmitterProvider({
1562
+ children,
1563
+ emitter
1564
+ }) {
1565
+ return /* @__PURE__ */ jsx11(ReactEmitterContext.Provider, { value: emitter, children });
1566
+ }
1567
+ function useEmitter() {
1568
+ return useContext7(ReactEmitterContext);
1569
+ }
1570
+ function useEvent(key, listener, deps = []) {
1571
+ const emitter = useContext7(ReactEmitterContext);
1572
+ useEffect4(() => {
1573
+ const handler = (data) => {
1574
+ listener(data);
1575
+ };
1576
+ emitter.on(key, handler);
1577
+ return () => {
1578
+ emitter.off(key, handler);
1579
+ };
1580
+ }, [emitter, key, ...deps]);
1581
+ }
1582
+
1583
+ // src/AtlasStore/AtlasStoreProvider.tsx
1584
+ import { jsx as jsx12 } from "react/jsx-runtime";
1585
+ var AtlasStoreReactContext = createContext8(null);
1586
+ function useAtlasStore() {
1587
+ return useContext8(AtlasStoreReactContext);
1588
+ }
1589
+ function AtlasStoreProvider({
1590
+ children
1591
+ }) {
1592
+ const emitter = useEmitter();
1593
+ const value = useMemo6(() => {
1594
+ return createAtlasStore({ events: emitter });
1595
+ }, []);
1596
+ return /* @__PURE__ */ jsx12(AtlasStoreReactContext.Provider, { value, children });
1597
+ }
1598
+
1161
1599
  // src/BaseCreator/BaseCreator.tsx
1162
- import { memo as memo3, Suspense, useEffect as useEffect7, useMemo as useMemo11, useRef as useRef3, useState as useState5 } from "react";
1163
- import { useVault as useVault4 } from "react-iiif-vault";
1164
1600
  import { toRef as toRef3 } from "@iiif/parser";
1601
+ import { CreatorGrid } from "@manifest-editor/components";
1602
+ import {
1603
+ matchBasedOnResource as matchBasedOnResource2
1604
+ } from "@manifest-editor/creator-api";
1165
1605
 
1166
1606
  // ../ui/madoc/components/icons/Spinner.tsx
1167
- import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
1607
+ import { jsx as jsx13, jsxs as jsxs4 } from "react/jsx-runtime";
1168
1608
  function Spinner(props) {
1169
- return /* @__PURE__ */ jsx11("svg", { width: "1em", height: "1em", viewBox: "0 0 42 42", xmlns: "http://www.w3.org/2000/svg", stroke: "#fff", ...props, children: /* @__PURE__ */ jsxs4("g", { transform: "translate(2 2)", strokeWidth: 5, fill: "none", fillRule: "evenodd", children: [
1170
- /* @__PURE__ */ jsx11("circle", { strokeOpacity: 0.5, cx: 18, cy: 18, r: 18 }),
1171
- /* @__PURE__ */ jsx11("path", { d: "M36 18c0-9.94-8.06-18-18-18", children: /* @__PURE__ */ jsx11(
1609
+ return /* @__PURE__ */ jsx13("svg", { width: "1em", height: "1em", viewBox: "0 0 42 42", xmlns: "http://www.w3.org/2000/svg", stroke: "#fff", ...props, children: /* @__PURE__ */ jsxs4("g", { transform: "translate(2 2)", strokeWidth: 5, fill: "none", fillRule: "evenodd", children: [
1610
+ /* @__PURE__ */ jsx13("circle", { strokeOpacity: 0.5, cx: 18, cy: 18, r: 18 }),
1611
+ /* @__PURE__ */ jsx13("path", { d: "M36 18c0-9.94-8.06-18-18-18", children: /* @__PURE__ */ jsx13(
1172
1612
  "animateTransform",
1173
1613
  {
1174
1614
  attributeName: "transform",
@@ -1182,137 +1622,19 @@ function Spinner(props) {
1182
1622
  ] }) });
1183
1623
  }
1184
1624
 
1185
- // src/highlighted-image-resources.ts
1186
- import { create } from "zustand";
1187
- import { useEffect as useEffect4, useMemo as useMemo6 } from "react";
1188
-
1189
- // src/helpers.ts
1190
- import { toRef } from "@iiif/parser";
1191
- async function getManifestNomalized(id) {
1192
- let responseData = void 0;
1193
- try {
1194
- await fetch(id).then((response) => {
1195
- return response.json().catch((err) => {
1196
- console.error(`'${err}' happened!`);
1197
- });
1198
- }).then((data) => {
1199
- responseData = { ...data };
1200
- });
1201
- } catch (error) {
1202
- console.log(error);
1203
- }
1204
- return responseData;
1205
- }
1206
- function createActionIdentity(type, property, parent) {
1207
- return `create_${type}_${property}_${toRef(parent)?.type || "unknown"}`;
1208
- }
1209
- function createDownload(data, fileName, fileType = "text/json") {
1210
- const blob = data instanceof Blob ? data : new Blob([data], { type: fileType });
1211
- const a = document.createElement("a");
1212
- a.download = fileName;
1213
- a.href = window.URL.createObjectURL(blob);
1214
- const clickEvt = new MouseEvent("click", {
1215
- view: window,
1216
- bubbles: true,
1217
- cancelable: true
1218
- });
1219
- a.dispatchEvent(clickEvt);
1220
- a.remove();
1221
- }
1222
- async function copyToClipboard(json) {
1223
- return navigator.clipboard.writeText(typeof json === "string" ? json : JSON.stringify(json, null, 2));
1224
- }
1225
- function randomId() {
1226
- return `${Math.random().toString(36).substr(2)}-${Date.now().toString(36)}`;
1227
- }
1228
- function mapApp(input, map) {
1229
- const { default: metadata, ...props } = input;
1230
- const app = {
1231
- metadata,
1232
- layout: {
1233
- leftPanels: [],
1234
- rightPanels: [],
1235
- centerPanels: [],
1236
- ...props
1237
- }
1238
- };
1239
- return map ? map(app) : app;
1240
- }
1241
-
1242
- // src/highlighted-image-resources.ts
1243
- var useHighlightedImageResource = create((set) => ({
1244
- regions: {},
1245
- resources: [],
1246
- setRegion: (id, region) => {
1247
- set((ex) => ({ ...ex.regions, regions: { [id]: region || null } }));
1248
- },
1249
- setHighlight: (id) => {
1250
- set({ resources: Array.isArray(id) ? id : [id] });
1251
- },
1252
- highlight: (id) => {
1253
- set((s) => {
1254
- if (s.resources.indexOf(id) !== -1) {
1255
- return s;
1256
- }
1257
- return { resources: [...s.resources, id] };
1258
- });
1259
- },
1260
- clearHighlight: (id) => {
1261
- set((s) => ({ resources: s.resources.filter((item) => item !== id) }));
1262
- }
1263
- }));
1264
- function useTemporaryHighlight(newValue) {
1265
- const id = useMemo6(() => randomId(), []);
1266
- const value = useHighlightedImageResource((s) => s.regions[id]);
1267
- const setRegion = useHighlightedImageResource((s) => s.setRegion);
1268
- useEffect4(() => {
1269
- if (value && newValue) {
1270
- if (value !== newValue && (value.x !== newValue.x || value.y !== newValue.y || value.width !== newValue.width || value.height !== newValue.height)) {
1271
- setRegion(id, newValue || null);
1272
- }
1273
- } else {
1274
- setRegion(id, newValue || null);
1275
- }
1276
- }, [value]);
1277
- useEffect4(() => {
1278
- return () => setRegion(id, null);
1279
- }, []);
1280
- }
1281
- function useHoverHighlightImageResource(id) {
1282
- const highlight = useHighlightedImageResource((s) => s.highlight);
1283
- const clear = useHighlightedImageResource((s) => s.clearHighlight);
1284
- useEffect4(() => {
1285
- return () => {
1286
- if (id) {
1287
- clear(id);
1288
- }
1289
- };
1290
- }, [clear, id]);
1291
- return useMemo6(() => {
1292
- return {
1293
- onMouseEnter() {
1294
- if (id) {
1295
- highlight(id);
1296
- }
1297
- },
1298
- onMouseLeave() {
1299
- if (id) {
1300
- clear(id);
1301
- }
1302
- }
1303
- };
1304
- }, [id, highlight, clear]);
1305
- }
1625
+ // src/BaseCreator/BaseCreator.tsx
1626
+ import { Suspense, memo as memo3, useEffect as useEffect8, useMemo as useMemo12, useRef as useRef3, useState as useState5 } from "react";
1627
+ import { useVault as useVault4 } from "react-iiif-vault";
1306
1628
 
1307
1629
  // src/Layout/Layout.context.tsx
1308
- import { createContext as createContext7, useContext as useContext7, useMemo as useMemo7 } from "react";
1309
- var LayoutActionsReactContext = createContext7(null);
1310
- var LayoutStateReactContext = createContext7(null);
1630
+ import { createContext as createContext9, useContext as useContext9, useMemo as useMemo7 } from "react";
1631
+ var LayoutActionsReactContext = createContext9(null);
1632
+ var LayoutStateReactContext = createContext9(null);
1311
1633
  function useLayoutState() {
1312
- return useContext7(LayoutStateReactContext);
1634
+ return useContext9(LayoutStateReactContext);
1313
1635
  }
1314
1636
  function useLayoutActions() {
1315
- return useContext7(LayoutActionsReactContext);
1637
+ return useContext9(LayoutActionsReactContext);
1316
1638
  }
1317
1639
  function useAvailableLayouts() {
1318
1640
  const app = useApp();
@@ -1321,22 +1643,22 @@ function useAvailableLayouts() {
1321
1643
  function useLayoutProvider() {
1322
1644
  const app = useApp();
1323
1645
  const layout = app.layout;
1324
- const actions = useContext7(LayoutActionsReactContext);
1325
- const state = useContext7(LayoutStateReactContext);
1646
+ const actions = useContext9(LayoutActionsReactContext);
1647
+ const state = useContext9(LayoutStateReactContext);
1326
1648
  return useMemo7(() => {
1327
1649
  return { actions, state, ...layout };
1328
1650
  }, [app, state]);
1329
1651
  }
1330
1652
 
1331
1653
  // src/Layout/components/ModularPanel.tsx
1332
- import styled8 from "styled-components";
1654
+ import styled6 from "styled-components";
1333
1655
 
1334
1656
  // ../ui/icons/StarIcon.tsx
1335
- import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
1657
+ import { jsx as jsx14, jsxs as jsxs5 } from "react/jsx-runtime";
1336
1658
  var StarIcon = (props) => /* @__PURE__ */ jsxs5("svg", { xmlns: "http://www.w3.org/2000/svg", height: "1em", width: "1em", viewBox: "0 0 24 24", ...props, children: [
1337
- /* @__PURE__ */ jsx12("path", { d: "M0 0h24v24H0z", fill: "none" }),
1338
- /* @__PURE__ */ jsx12("path", { d: "M0 0h24v24H0z", fill: "none" }),
1339
- /* @__PURE__ */ jsx12(
1659
+ /* @__PURE__ */ jsx14("path", { d: "M0 0h24v24H0z", fill: "none" }),
1660
+ /* @__PURE__ */ jsx14("path", { d: "M0 0h24v24H0z", fill: "none" }),
1661
+ /* @__PURE__ */ jsx14(
1340
1662
  "path",
1341
1663
  {
1342
1664
  d: "M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z",
@@ -1346,15 +1668,15 @@ var StarIcon = (props) => /* @__PURE__ */ jsxs5("svg", { xmlns: "http://www.w3.o
1346
1668
  ] });
1347
1669
 
1348
1670
  // ../ui/icons/BackIcon.tsx
1349
- import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
1671
+ import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
1350
1672
  var BackIcon = ({ style }) => /* @__PURE__ */ jsxs6("svg", { xmlns: "http://www.w3.org/2000/svg", height: "1rem", viewBox: "0 0 24 24", width: "1rem", fill: "#000000", style, children: [
1351
- /* @__PURE__ */ jsx13("path", { d: "M0 0h24v24H0z", fill: "none" }),
1352
- /* @__PURE__ */ jsx13("path", { d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" })
1673
+ /* @__PURE__ */ jsx15("path", { d: "M0 0h24v24H0z", fill: "none" }),
1674
+ /* @__PURE__ */ jsx15("path", { d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" })
1353
1675
  ] });
1354
1676
 
1355
1677
  // src/Layout/components/ModularPanel.tsx
1356
1678
  import { ErrorBoundary } from "react-error-boundary";
1357
- import { createContext as createContext8, useCallback as useCallback3, useContext as useContext8, useEffect as useEffect5, useMemo as useMemo8, useRef as useRef2, useState as useState4 } from "react";
1679
+ import { createContext as createContext10, useCallback as useCallback3, useContext as useContext10, useEffect as useEffect5, useMemo as useMemo8, useRef as useRef2, useState as useState4 } from "react";
1358
1680
 
1359
1681
  // ../ui/atoms/PaddedSidebarContainer.tsx
1360
1682
  import styled4 from "styled-components";
@@ -1365,70 +1687,16 @@ var PaddedSidebarContainer = styled4.div`
1365
1687
  overflow: visible;
1366
1688
  `;
1367
1689
 
1368
- // ../ui/madoc/components/callouts/ErrorMessage.tsx
1369
- import styled6 from "styled-components";
1370
-
1371
- // ../ui/madoc/components/callouts/BaseMessage.tsx
1372
- import styled5, { css as css2 } from "styled-components";
1373
- var BaseMessage = styled5.div`
1374
- background: #000;
1375
- color: #fff;
1376
- width: 100%;
1377
- padding: 0.5em 1em;
1378
- line-height: 1.9em;
1379
- display: flex;
1380
-
1381
- a {
1382
- color: #fff;
1383
- }
1384
-
1385
- svg {
1386
- fill: #fff;
1387
- margin: 0 0.5em;
1388
- vertical-align: text-bottom;
1389
- }
1390
-
1391
- ${(props) => props.$small && css2`
1392
- font-size: 0.75em;
1393
- padding: 0.25em 0.5em;
1394
- line-height: 1.6em;
1395
- `}
1396
-
1397
- ${(props) => props.$wide && css2`
1398
- margin-left: -2em;
1399
- margin-right: -2em;
1400
- width: auto;
1401
- svg {
1402
- height: 0.8em;
1403
- vertical-align: baseline;
1404
- }
1405
- `}
1406
-
1407
- ${(props) => props.$margin && css2`
1408
- margin-bottom: 1em;
1409
- `}
1410
-
1411
- ${(props) => props.$banner && css2`
1412
- border-radius: 5px;
1413
- box-shadow: 0 3px 15px 0 rgb(0 0 0 / 16%);
1414
- `}
1415
- `;
1416
-
1417
- // ../ui/madoc/components/callouts/ErrorMessage.tsx
1418
- var ErrorMessage = styled6(BaseMessage)`
1419
- background: #c74158;
1420
- color: #fff;
1421
- `;
1422
-
1423
1690
  // src/Layout/components/PanelError.tsx
1691
+ import { ErrorMessage } from "@manifest-editor/components";
1424
1692
  import { useState as useState3 } from "react";
1425
- import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
1693
+ import { jsx as jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
1426
1694
  function PanelError(props) {
1427
1695
  let error = props.error.toString();
1428
1696
  const [isFixing, setIsFixing] = useState3(false);
1429
1697
  return /* @__PURE__ */ jsxs7(PaddedSidebarContainer, { children: [
1430
- /* @__PURE__ */ jsx14(ErrorMessage, { $margin: true, children: error }),
1431
- /* @__PURE__ */ jsx14(CalltoButton, { onClick: props.resetErrorBoundary, children: "Try again" })
1698
+ /* @__PURE__ */ jsx16(ErrorMessage, { className: "mb-2", children: error }),
1699
+ /* @__PURE__ */ jsx16(CalltoButton, { onClick: props.resetErrorBoundary, children: "Try again" })
1432
1700
  ] });
1433
1701
  }
1434
1702
 
@@ -1455,12 +1723,12 @@ function renderHelper(htmlOrReact) {
1455
1723
  import { ReactVaultContext } from "react-iiif-vault";
1456
1724
 
1457
1725
  // ../ui/atoms/Dropdown.tsx
1458
- import styled7, { css as css3 } from "styled-components";
1459
- var Dropdown = styled7.div`
1726
+ import styled5, { css as css2 } from "styled-components";
1727
+ var Dropdown = styled5.div`
1460
1728
  position: relative;
1461
1729
  display: inline-block;
1462
1730
  `;
1463
- var DropdownContent = styled7.div`
1731
+ var DropdownContent = styled5.div`
1464
1732
  display: flex;
1465
1733
  flex-direction: column;
1466
1734
  position: absolute;
@@ -1476,7 +1744,7 @@ var DropdownContent = styled7.div`
1476
1744
  }
1477
1745
  }
1478
1746
  `;
1479
- var DropdownItem = styled7.button`
1747
+ var DropdownItem = styled5.button`
1480
1748
  padding: 0 ${(props) => props.theme.padding.small || "0.5rem"};
1481
1749
  color: ${(props) => props.theme.color.main || "none"};
1482
1750
  background-color: ${(props) => props.theme.color.white || "white"};
@@ -1495,7 +1763,7 @@ var DropdownItem = styled7.button`
1495
1763
  background-color: ${(props) => props.theme.color.lightgrey || "lightgrey"};
1496
1764
  }
1497
1765
 
1498
- ${(props) => props.$active && css3`
1766
+ ${(props) => props.$active && css2`
1499
1767
  background: #b84c74;
1500
1768
  color: #fff;
1501
1769
  &:hover {
@@ -1504,7 +1772,7 @@ var DropdownItem = styled7.button`
1504
1772
  }
1505
1773
  `}
1506
1774
  `;
1507
- var DropdownMenu = styled7.div`
1775
+ var DropdownMenu = styled5.div`
1508
1776
  display: none;
1509
1777
  flex-direction: column;
1510
1778
  position: absolute;
@@ -1528,18 +1796,18 @@ var DropdownMenu = styled7.div`
1528
1796
  }
1529
1797
  }
1530
1798
 
1531
- ${(props) => props.$open && css3`
1799
+ ${(props) => props.$open && css2`
1532
1800
  display: flex;
1533
1801
  `}
1534
1802
  `;
1535
- var DropdownLabel = styled7.div`
1803
+ var DropdownLabel = styled5.div`
1536
1804
  color: #999;
1537
1805
  text-transform: uppercase;
1538
1806
  font-weight: 600;
1539
1807
  padding: 0.7em;
1540
1808
  font-size: 0.875em;
1541
1809
  `;
1542
- var DropdownDivider = styled7.div`
1810
+ var DropdownDivider = styled5.div`
1543
1811
  height: 1px;
1544
1812
  margin: 0 0.5em;
1545
1813
  background: #eee;
@@ -1552,12 +1820,12 @@ import useDropdownMenu2 from "react-accessible-dropdown-menu-hook";
1552
1820
  var OverrideScrollbar = "ModularPanel_OverrideScrollbar";
1553
1821
 
1554
1822
  // src/Layout/components/ModularPanel.tsx
1555
- import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
1556
- var LayoutTitleReactContext = createContext8(null);
1823
+ import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
1824
+ var LayoutTitleReactContext = createContext10(null);
1557
1825
  function useSetCustomTitle() {
1558
- return useContext8(LayoutTitleReactContext);
1826
+ return useContext10(LayoutTitleReactContext);
1559
1827
  }
1560
- var ModularPanelWrapper = styled8.div`
1828
+ var ModularPanelWrapper = styled6.div`
1561
1829
  display: flex;
1562
1830
  flex-direction: column;
1563
1831
  position: relative;
@@ -1610,7 +1878,7 @@ var ModularPanelWrapper = styled8.div`
1610
1878
  transform: translateX(100%);
1611
1879
  }
1612
1880
  `;
1613
- var ModularPanelHeader = styled8.div`
1881
+ var ModularPanelHeader = styled6.div`
1614
1882
  background: #fff;
1615
1883
  display: flex;
1616
1884
  height: 2.8em;
@@ -1633,7 +1901,7 @@ var ModularPanelHeader = styled8.div`
1633
1901
  box-shadow: inset 0 -5px 10px 0 rgba(255, 255, 255, 0.5);
1634
1902
  }
1635
1903
  `;
1636
- var ModulePanelButton = styled8.button`
1904
+ var ModulePanelButton = styled6.button`
1637
1905
  border: none;
1638
1906
  background: transparent;
1639
1907
  padding: 0 0.4em;
@@ -1646,17 +1914,17 @@ var ModulePanelButton = styled8.button`
1646
1914
  font-size: 1.2em;
1647
1915
  }
1648
1916
  `;
1649
- var ModulePanelSpacer = styled8.div`
1917
+ var ModulePanelSpacer = styled6.div`
1650
1918
  flex: 1 1 0px;
1651
1919
  `;
1652
- var ModularPanelLabel = styled8.h2`
1920
+ var ModularPanelLabel = styled6.h2`
1653
1921
  font-size: 0.875em;
1654
1922
  flex: 1 1 0px;
1655
1923
  padding-left: 1em;
1656
1924
  text-align: center;
1657
1925
  align-self: center;
1658
1926
  `;
1659
- var ModularPanelContent = styled8.div`
1927
+ var ModularPanelContent = styled6.div`
1660
1928
  flex: 1 1 0px;
1661
1929
  display: flex;
1662
1930
 
@@ -1680,7 +1948,7 @@ function ModularPanel({
1680
1948
  style,
1681
1949
  noHeader
1682
1950
  }) {
1683
- const vault = useContext8(ReactVaultContext) || null;
1951
+ const vault = useContext10(ReactVaultContext) || null;
1684
1952
  const [didError, setDidError] = useState4(false);
1685
1953
  const appState = useAppState();
1686
1954
  const layout = useLayoutProvider();
@@ -1727,16 +1995,16 @@ function ModularPanel({
1727
1995
  if (!panel || !state.current) {
1728
1996
  return null;
1729
1997
  }
1730
- const backButton = panel.backAction || state.stack.length ? /* @__PURE__ */ jsx15(ModulePanelButton, { onClick: backAction, children: /* @__PURE__ */ jsx15(BackIcon, {}) }) : null;
1731
- const closeButton = /* @__PURE__ */ jsx15(ModulePanelButton, { onClick: close || actions.close, children: /* @__PURE__ */ jsx15(CloseIcon, {}) });
1732
- return /* @__PURE__ */ jsx15(LayoutTitleReactContext.Provider, { value: _setCustomTitle, children: /* @__PURE__ */ jsxs8(ModularPanelWrapper, { "data-state": transition, "data-flipped": isLeft, style, "data-header": !noHeader, children: [
1998
+ const backButton = panel.backAction || state.stack.length ? /* @__PURE__ */ jsx17(ModulePanelButton, { onClick: backAction, children: /* @__PURE__ */ jsx17(BackIcon, {}) }) : null;
1999
+ const closeButton = /* @__PURE__ */ jsx17(ModulePanelButton, { onClick: close || actions.close, children: /* @__PURE__ */ jsx17(CloseIcon, {}) });
2000
+ return /* @__PURE__ */ jsx17(LayoutTitleReactContext.Provider, { value: _setCustomTitle, children: /* @__PURE__ */ jsxs8(ModularPanelWrapper, { "data-state": transition, "data-flipped": isLeft, style, "data-header": !noHeader, children: [
1733
2001
  noHeader ? null : /* @__PURE__ */ jsxs8(ModularPanelHeader, { "data-tabs": !!tabs, "data-error": didError, children: [
1734
2002
  /* @__PURE__ */ jsxs8(Dropdown, { style: { display: "flex", height: "100%" }, children: [
1735
2003
  panel.renderBackAction ? panel.renderBackAction({ backAction, fallback: backButton }) : backButton,
1736
2004
  switchablePanels.length ? /* @__PURE__ */ jsxs8(DropdownMenu, { $open: isOpen, style: { left: "0.5em" }, children: [
1737
- /* @__PURE__ */ jsx15(DropdownLabel, { children: "All panels" }),
1738
- /* @__PURE__ */ jsx15(DropdownDivider, {}),
1739
- switchablePanels.map((newPanel, i) => /* @__PURE__ */ jsx15(
2005
+ /* @__PURE__ */ jsx17(DropdownLabel, { children: "All panels" }),
2006
+ /* @__PURE__ */ jsx17(DropdownDivider, {}),
2007
+ switchablePanels.map((newPanel, i) => /* @__PURE__ */ jsx17(
1740
2008
  DropdownItem,
1741
2009
  {
1742
2010
  ...itemProps[i],
@@ -1748,11 +2016,11 @@ function ModularPanel({
1748
2016
  ))
1749
2017
  ] }) : null
1750
2018
  ] }),
1751
- customTitle ? /* @__PURE__ */ jsx15(ModularPanelLabel, { children: customTitle }) : hideHeader ? /* @__PURE__ */ jsx15(ModulePanelSpacer, {}) : /* @__PURE__ */ jsx15(ModularPanelLabel, { children: panel.label }),
1752
- pinnable ? state.pinned ? /* @__PURE__ */ jsx15(ModulePanelButton, { onClick: pinActions.unpin, children: /* @__PURE__ */ jsx15(StarIcon, { fill: "orange" }) }) : /* @__PURE__ */ jsx15(ModulePanelButton, { onClick: () => pinActions.pin({ id: panel.id, state: state.state }), children: /* @__PURE__ */ jsx15(StarIcon, { fill: "#ddd" }) }) : null,
2019
+ customTitle ? /* @__PURE__ */ jsx17(ModularPanelLabel, { children: customTitle }) : hideHeader ? /* @__PURE__ */ jsx17(ModulePanelSpacer, {}) : /* @__PURE__ */ jsx17(ModularPanelLabel, { children: panel.label }),
2020
+ pinnable ? state.pinned ? /* @__PURE__ */ jsx17(ModulePanelButton, { onClick: pinActions.unpin, children: /* @__PURE__ */ jsx17(StarIcon, { fill: "orange" }) }) : /* @__PURE__ */ jsx17(ModulePanelButton, { onClick: () => pinActions.pin({ id: panel.id, state: state.state }), children: /* @__PURE__ */ jsx17(StarIcon, { fill: "#ddd" }) }) : null,
1753
2021
  panel.renderCloseAction ? panel.renderCloseAction({ closeAction: close || actions.close, fallback: closeButton }) : closeButton
1754
2022
  ] }),
1755
- /* @__PURE__ */ jsx15(ModularPanelContent, { className: OverrideScrollbar, children: /* @__PURE__ */ jsx15(
2023
+ /* @__PURE__ */ jsx17(ModularPanelContent, { className: OverrideScrollbar, children: /* @__PURE__ */ jsx17(
1756
2024
  ErrorBoundary,
1757
2025
  {
1758
2026
  onError: () => setDidError(true),
@@ -1767,18 +2035,193 @@ function ModularPanel({
1767
2035
  )
1768
2036
  )
1769
2037
  }
1770
- ) })
1771
- ] }) });
2038
+ ) })
2039
+ ] }) });
2040
+ }
2041
+
2042
+ // src/highlighted-image-resources.ts
2043
+ import { create } from "zustand";
2044
+ import { useEffect as useEffect6, useMemo as useMemo9 } from "react";
2045
+
2046
+ // src/helpers.ts
2047
+ import { toRef } from "@iiif/parser";
2048
+ async function getManifestNomalized(id) {
2049
+ let responseData = void 0;
2050
+ try {
2051
+ await fetch(id).then((response) => {
2052
+ return response.json().catch((err) => {
2053
+ console.error(`'${err}' happened!`);
2054
+ });
2055
+ }).then((data) => {
2056
+ responseData = { ...data };
2057
+ });
2058
+ } catch (error) {
2059
+ console.log(error);
2060
+ }
2061
+ return responseData;
2062
+ }
2063
+ function createActionIdentity(type, property, parent) {
2064
+ return `create_${type}_${property}_${toRef(parent)?.type || "unknown"}`;
2065
+ }
2066
+ function createDownload(data, fileName, fileType = "text/json") {
2067
+ const blob = data instanceof Blob ? data : new Blob([data], { type: fileType });
2068
+ const a = document.createElement("a");
2069
+ a.download = fileName;
2070
+ a.href = window.URL.createObjectURL(blob);
2071
+ const clickEvt = new MouseEvent("click", {
2072
+ view: window,
2073
+ bubbles: true,
2074
+ cancelable: true
2075
+ });
2076
+ a.dispatchEvent(clickEvt);
2077
+ a.remove();
2078
+ }
2079
+ async function copyToClipboard(json) {
2080
+ return navigator.clipboard.writeText(
2081
+ typeof json === "string" ? json : JSON.stringify(json, null, 2)
2082
+ );
2083
+ }
2084
+ function randomId() {
2085
+ return `${Math.random().toString(36).substr(2)}-${Date.now().toString(36)}`;
2086
+ }
2087
+ function mapApp(input, map) {
2088
+ const { default: metadata, ...props } = input;
2089
+ const app = {
2090
+ metadata,
2091
+ layout: {
2092
+ leftPanels: [],
2093
+ rightPanels: [],
2094
+ centerPanels: [],
2095
+ ...props
2096
+ }
2097
+ };
2098
+ return map ? map(app) : app;
2099
+ }
2100
+ function extendApp(app, metadata, extensions) {
2101
+ return {
2102
+ ...app,
2103
+ metadata,
2104
+ config: {
2105
+ ...app.config || {},
2106
+ ...extensions.config || {}
2107
+ },
2108
+ layout: {
2109
+ ...app.layout,
2110
+ leftPanels: [
2111
+ ...(app.layout.leftPanels || []).filter((panel) => {
2112
+ if (extensions?.leftPanelIds) {
2113
+ return extensions.leftPanelIds.includes(panel.id);
2114
+ }
2115
+ return true;
2116
+ }),
2117
+ ...extensions?.leftPanels || []
2118
+ ],
2119
+ annotations: [
2120
+ ...extensions?.annotations || [],
2121
+ ...app.layout.annotations || []
2122
+ ],
2123
+ canvasEditors: [
2124
+ ...extensions?.canvasEditors || [],
2125
+ ...app.layout.canvasEditors || []
2126
+ ],
2127
+ creators: [
2128
+ ...extensions?.creators || [],
2129
+ ...app.layout.creators || []
2130
+ ],
2131
+ editors: [
2132
+ //
2133
+ ...extensions?.editors || [],
2134
+ ...app.layout.editors || []
2135
+ ],
2136
+ rightPanels: [
2137
+ ...app.layout.rightPanels || [],
2138
+ ...extensions?.rightPanels || []
2139
+ ],
2140
+ centerPanels: [
2141
+ ...app.layout.centerPanels || [],
2142
+ ...extensions?.centerPanels || []
2143
+ ],
2144
+ modals: [
2145
+ ...app.layout.modals || [],
2146
+ ...extensions?.modalPanels || []
2147
+ ]
2148
+ }
2149
+ };
2150
+ }
2151
+
2152
+ // src/highlighted-image-resources.ts
2153
+ var useHighlightedImageResource = create((set) => ({
2154
+ regions: {},
2155
+ resources: [],
2156
+ setRegion: (id, region) => {
2157
+ set((ex) => ({ ...ex.regions, regions: { [id]: region || null } }));
2158
+ },
2159
+ setHighlight: (id) => {
2160
+ set({ resources: Array.isArray(id) ? id : [id] });
2161
+ },
2162
+ highlight: (id) => {
2163
+ set((s) => {
2164
+ if (s.resources.indexOf(id) !== -1) {
2165
+ return s;
2166
+ }
2167
+ return { resources: [...s.resources, id] };
2168
+ });
2169
+ },
2170
+ clearHighlight: (id) => {
2171
+ set((s) => ({ resources: s.resources.filter((item) => item !== id) }));
2172
+ }
2173
+ }));
2174
+ function useTemporaryHighlight(newValue) {
2175
+ const id = useMemo9(() => randomId(), []);
2176
+ const value = useHighlightedImageResource((s) => s.regions[id]);
2177
+ const setRegion = useHighlightedImageResource((s) => s.setRegion);
2178
+ useEffect6(() => {
2179
+ if (value && newValue) {
2180
+ if (value !== newValue && (value.x !== newValue.x || value.y !== newValue.y || value.width !== newValue.width || value.height !== newValue.height)) {
2181
+ setRegion(id, newValue || null);
2182
+ }
2183
+ } else {
2184
+ setRegion(id, newValue || null);
2185
+ }
2186
+ }, [value]);
2187
+ useEffect6(() => {
2188
+ return () => setRegion(id, null);
2189
+ }, []);
2190
+ }
2191
+ function useHoverHighlightImageResource(id) {
2192
+ const highlight = useHighlightedImageResource((s) => s.highlight);
2193
+ const clear = useHighlightedImageResource((s) => s.clearHighlight);
2194
+ useEffect6(() => {
2195
+ return () => {
2196
+ if (id) {
2197
+ clear(id);
2198
+ }
2199
+ };
2200
+ }, [clear, id]);
2201
+ return useMemo9(() => {
2202
+ return {
2203
+ onMouseEnter() {
2204
+ if (id) {
2205
+ highlight(id);
2206
+ }
2207
+ },
2208
+ onMouseLeave() {
2209
+ if (id) {
2210
+ clear(id);
2211
+ }
2212
+ }
2213
+ };
2214
+ }, [id, highlight, clear]);
1772
2215
  }
1773
2216
 
1774
2217
  // src/BaseCreator/BaseCreator.hooks.tsx
1775
- import { Creator } from "@manifest-editor/creator-api";
1776
- import { useCallback as useCallback4, useMemo as useMemo10 } from "react";
1777
- import { useVault as useVault3 } from "react-iiif-vault";
1778
2218
  import { toRef as toRef2 } from "@iiif/parser";
2219
+ import { Creator, matchBasedOnResource } from "@manifest-editor/creator-api";
2220
+ import { useCallback as useCallback4, useMemo as useMemo11 } from "react";
2221
+ import { useVault as useVault3 } from "react-iiif-vault";
1779
2222
 
1780
2223
  // src/PreviewVault/PreviewVault.tsx
1781
- import { createContext as createContext9, useContext as useContext9, useEffect as useEffect6, useMemo as useMemo9 } from "react";
2224
+ import { createContext as createContext11, useContext as useContext11, useEffect as useEffect7, useMemo as useMemo10 } from "react";
1782
2225
  import { Vault as Vault2 } from "@iiif/helpers/vault";
1783
2226
  import { VaultProvider as VaultProvider2 } from "react-iiif-vault";
1784
2227
 
@@ -1874,12 +2317,12 @@ function createPreviewVault(homepageCollectionId = "vault://homepage-collection.
1874
2317
  }
1875
2318
 
1876
2319
  // src/PreviewVault/PreviewVault.tsx
1877
- import { jsx as jsx16 } from "react/jsx-runtime";
2320
+ import { jsx as jsx18 } from "react/jsx-runtime";
1878
2321
  function usePreviewVault() {
1879
- return useContext9(PreviewVaultReactContext);
2322
+ return useContext11(PreviewVaultReactContext);
1880
2323
  }
1881
- var PreviewVaultReactContext = createContext9(new Vault2());
1882
- var PreviewVaultAddHistory = createContext9({
2324
+ var PreviewVaultReactContext = createContext11(new Vault2());
2325
+ var PreviewVaultAddHistory = createContext11({
1883
2326
  addHistory: (id, type) => {
1884
2327
  },
1885
2328
  clearHistory: () => {
@@ -1887,112 +2330,121 @@ var PreviewVaultAddHistory = createContext9({
1887
2330
  });
1888
2331
  var HOMEPAGE_COLLECTION = "manifest-editor://homepage-collection.json";
1889
2332
  function usePreviewHistory() {
1890
- return useContext9(PreviewVaultAddHistory);
2333
+ return useContext11(PreviewVaultAddHistory);
1891
2334
  }
1892
2335
  function PreviewVaultContext(props) {
1893
- const { vault, unsubscribe, addHistory, clearHistory } = useMemo9(() => {
2336
+ const { vault, unsubscribe, addHistory, clearHistory } = useMemo10(() => {
1894
2337
  return createPreviewVault(HOMEPAGE_COLLECTION);
1895
2338
  }, []);
1896
- useEffect6(() => {
2339
+ useEffect7(() => {
1897
2340
  return unsubscribe;
1898
2341
  }, []);
1899
- return /* @__PURE__ */ jsx16(PreviewVaultAddHistory.Provider, { value: { addHistory, clearHistory }, children: /* @__PURE__ */ jsx16(PreviewVaultReactContext.Provider, { value: vault, children: props.children }) });
2342
+ return /* @__PURE__ */ jsx18(PreviewVaultAddHistory.Provider, { value: { addHistory, clearHistory }, children: /* @__PURE__ */ jsx18(PreviewVaultReactContext.Provider, { value: vault, children: props.children }) });
1900
2343
  }
1901
2344
  function PreviewVaultBoundary({ children }) {
1902
2345
  const vault = usePreviewVault();
1903
- return /* @__PURE__ */ jsx16(VaultProvider2, { vault, children });
2346
+ return /* @__PURE__ */ jsx18(VaultProvider2, { vault, children });
1904
2347
  }
1905
2348
 
1906
2349
  // src/BaseCreator/BaseCreator.hooks.tsx
1907
- function matchBasedOnResource(resource, list, options) {
1908
- const supported = [];
1909
- if (list.length === 0) {
1910
- return [];
1911
- }
1912
- const parent = toRef2(resource.parent);
1913
- const property = resource.property;
1914
- for (const def of list) {
1915
- if (parent && property) {
1916
- if (def.supports.parentTypes) {
1917
- if (!def.supports.parentTypes.includes(parent.type)) {
1918
- continue;
1919
- }
1920
- }
1921
- if (def.supports.parentFields) {
1922
- if (!def.supports.parentFields.includes(property)) {
1923
- continue;
1924
- }
1925
- }
1926
- if (def.supports.parentFieldMap) {
1927
- const type = def.supports.parentFieldMap[parent.type];
1928
- if (!type || !type.includes(property)) {
1929
- continue;
1930
- }
1931
- }
1932
- if (def.supports.disallowPainting && resource.isPainting) {
1933
- continue;
1934
- }
1935
- if (def.supports.custom) {
1936
- const isValid = def.supports.custom({ property, resource: parent, atIndex: resource.index }, options.vault);
1937
- if (!isValid) {
1938
- continue;
1939
- }
1940
- }
1941
- if (!def.supports.initialData && Object.keys(resource.initialData || {}).length !== 0) {
1942
- continue;
1943
- }
1944
- if (def.resourceType !== resource.type) {
1945
- if (!(def.additionalTypes || []).includes(resource.type)) {
1946
- continue;
1947
- }
1948
- }
1949
- supported.push(def);
1950
- }
1951
- }
1952
- return supported;
1953
- }
1954
2350
  function useCreator(parent, property, type, target, options) {
1955
2351
  const vault = useVault3();
1956
2352
  const app = useApp();
1957
2353
  const { create: create2, edit } = useLayoutActions();
1958
- const supported = useMemo10(
1959
- () => matchBasedOnResource({ type, parent, index: 0, property }, app.layout.creators || [], { vault }),
2354
+ const supported = useMemo11(
2355
+ () => matchBasedOnResource(
2356
+ { type, parent, index: 0, property },
2357
+ app.layout.creators || [],
2358
+ { vault }
2359
+ ),
1960
2360
  [parent, property, app.layout.creators, type, vault]
1961
2361
  );
1962
2362
  const canCreate = parent && supported.length !== 0;
1963
2363
  const wrappedCreate = useCallback4(
1964
2364
  (index, initialData) => {
1965
2365
  if (parent) {
1966
- create2({ type, parent: toRef2(parent), property, index, target, initialData, ...options || {} });
2366
+ create2({
2367
+ type,
2368
+ parent: toRef2(parent),
2369
+ property,
2370
+ index,
2371
+ target,
2372
+ initialData,
2373
+ ...options || {}
2374
+ });
2375
+ }
2376
+ },
2377
+ [create2, parent, property, type, options, target]
2378
+ );
2379
+ const wrappedFilteredCreate = useCallback4(
2380
+ (filter, index, initialData) => {
2381
+ if (parent) {
2382
+ create2({
2383
+ type,
2384
+ filter,
2385
+ parent: toRef2(parent),
2386
+ property,
2387
+ index,
2388
+ target,
2389
+ initialData,
2390
+ ...options || {}
2391
+ });
1967
2392
  }
1968
2393
  },
1969
- [create2, parent, property, type]
2394
+ [create2, parent, property, type, options, target]
1970
2395
  );
1971
2396
  const wrappedEdit = useCallback4(
1972
2397
  (resource, index) => {
1973
- edit(resource, parent ? { parent: toRef2(parent), property, index } : void 0);
2398
+ edit(
2399
+ resource,
2400
+ parent ? { parent: toRef2(parent), property, index } : void 0
2401
+ );
1974
2402
  },
1975
2403
  [edit, parent, property]
1976
2404
  );
1977
- const buttonProps = useMemo10(() => {
2405
+ const wrappedCreator = useCallback4(
2406
+ (initialCreator, initialData) => {
2407
+ if (parent) {
2408
+ create2({
2409
+ type,
2410
+ initialCreator,
2411
+ parent: toRef2(parent),
2412
+ property,
2413
+ target,
2414
+ initialData,
2415
+ ...options || {}
2416
+ });
2417
+ }
2418
+ },
2419
+ [type, property, parent, target, create2, options]
2420
+ );
2421
+ const buttonProps = useMemo11(() => {
1978
2422
  return {
1979
2423
  "data-action-id": createActionIdentity(type, property, parent)
1980
2424
  };
1981
- }, []);
1982
- return [canCreate, { create: wrappedCreate, edit: wrappedEdit, buttonProps }];
2425
+ }, [type, property, parent]);
2426
+ return [
2427
+ canCreate,
2428
+ {
2429
+ create: wrappedCreate,
2430
+ edit: wrappedEdit,
2431
+ createFiltered: wrappedFilteredCreate,
2432
+ creator: wrappedCreator,
2433
+ buttonProps
2434
+ }
2435
+ ];
1983
2436
  }
1984
2437
  function useInlineCreator() {
1985
2438
  const vault = useVault3();
1986
2439
  const previewVault = usePreviewVault();
1987
2440
  const app = useApp();
1988
- return useMemo10(() => {
2441
+ return useMemo11(() => {
1989
2442
  return new Creator(vault, app.layout.creators || [], previewVault);
1990
2443
  }, [app.layout.creators, vault]);
1991
2444
  }
1992
2445
 
1993
2446
  // src/BaseCreator/BaseCreator.tsx
1994
- import { CreatorGrid } from "@manifest-editor/components";
1995
- import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
2447
+ import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs9 } from "react/jsx-runtime";
1996
2448
  var RenderCreator = memo3(function RenderCreator2(props) {
1997
2449
  const vault = useVault4();
1998
2450
  const { edit, modal } = useLayoutActions();
@@ -2028,12 +2480,12 @@ var RenderCreator = memo3(function RenderCreator2(props) {
2028
2480
  const validate = async () => {
2029
2481
  return true;
2030
2482
  };
2031
- useEffect7(() => {
2483
+ useEffect8(() => {
2032
2484
  if (!props.creator.render && !isCreating) {
2033
2485
  runCreate({});
2034
2486
  }
2035
2487
  }, [props.creator]);
2036
- useEffect7(() => {
2488
+ useEffect8(() => {
2037
2489
  if (isCreating) {
2038
2490
  modal.popStack();
2039
2491
  modal.close();
@@ -2043,9 +2495,9 @@ var RenderCreator = memo3(function RenderCreator2(props) {
2043
2495
  return null;
2044
2496
  }
2045
2497
  if (!props.creator.render) {
2046
- return /* @__PURE__ */ jsx17("div", { children: /* @__PURE__ */ jsx17(Button, { onClick: () => runCreate({}), children: "Create" }) });
2498
+ return /* @__PURE__ */ jsx19("div", { children: /* @__PURE__ */ jsx19(Button, { onClick: () => runCreate({}), children: "Create" }) });
2047
2499
  }
2048
- return /* @__PURE__ */ jsx17(Fragment2, { children: /* @__PURE__ */ jsx17(Suspense, { fallback: /* @__PURE__ */ jsx17(Spinner, {}), children: props.creator.render({
2500
+ return /* @__PURE__ */ jsx19(Fragment2, { children: /* @__PURE__ */ jsx19(Suspense, { fallback: /* @__PURE__ */ jsx19(Spinner, {}), children: props.creator.render({
2049
2501
  vault,
2050
2502
  runCreate,
2051
2503
  validate,
@@ -2055,31 +2507,39 @@ var RenderCreator = memo3(function RenderCreator2(props) {
2055
2507
  function BaseCreator(props) {
2056
2508
  const app = useApp();
2057
2509
  const vault = useVault4();
2058
- const [currentId, setCurrentId] = useState5("");
2510
+ const [currentId, setCurrentId] = useState5(
2511
+ props.resource.initialCreator || ""
2512
+ );
2059
2513
  const set = useSetCustomTitle();
2060
- const supported = useMemo11(
2061
- () => matchBasedOnResource(props.resource, app.layout.creators || [], { vault }),
2514
+ const supported = useMemo12(
2515
+ () => matchBasedOnResource2(props.resource, app.layout.creators || [], {
2516
+ vault
2517
+ }),
2062
2518
  [props.resource, app.layout.creators, vault]
2063
2519
  );
2064
2520
  if (supported.length === 1 && !currentId) {
2065
2521
  setCurrentId(supported[0].id);
2066
2522
  }
2067
2523
  const current = supported.find((t) => t.id === currentId);
2068
- useEffect7(() => {
2524
+ useEffect8(() => {
2069
2525
  if (current) {
2070
- set && set(current.label);
2526
+ set?.(current.label);
2071
2527
  }
2072
2528
  });
2073
2529
  if (supported.length === 0) {
2074
- return /* @__PURE__ */ jsx17("div", { children: "Not currently supported" });
2530
+ return /* @__PURE__ */ jsx19("div", { children: "Not currently supported" });
2075
2531
  }
2076
2532
  if (current) {
2533
+ const shouldHideModal = current.hiddenModal;
2534
+ if (shouldHideModal) {
2535
+ return /* @__PURE__ */ jsx19(RenderCreator, { creator: current, resource: props.resource });
2536
+ }
2077
2537
  return /* @__PURE__ */ jsxs9("div", { children: [
2078
- /* @__PURE__ */ jsx17("div", { className: "bg-me-gray-100 p-2", children: /* @__PURE__ */ jsx17(Button, { onClick: () => setCurrentId(""), children: "Back" }) }),
2079
- /* @__PURE__ */ jsx17("div", { className: "p-2 py-6", children: /* @__PURE__ */ jsx17(RenderCreator, { creator: current, resource: props.resource }) })
2538
+ /* @__PURE__ */ jsx19("div", { className: "bg-me-gray-100 p-2", children: /* @__PURE__ */ jsx19(Button, { onClick: () => setCurrentId(""), children: "Back" }) }),
2539
+ /* @__PURE__ */ jsx19("div", { className: "p-2 py-6", children: /* @__PURE__ */ jsx19(RenderCreator, { creator: current, resource: props.resource }) })
2080
2540
  ] });
2081
2541
  }
2082
- return /* @__PURE__ */ jsx17(
2542
+ return /* @__PURE__ */ jsx19(
2083
2543
  CreatorGrid,
2084
2544
  {
2085
2545
  label: "Select a type",
@@ -2095,22 +2555,23 @@ function BaseCreator(props) {
2095
2555
  }
2096
2556
 
2097
2557
  // src/BaseCreator/index.tsx
2098
- import { jsx as jsx18 } from "react/jsx-runtime";
2558
+ import { jsx as jsx20 } from "react/jsx-runtime";
2099
2559
  var baseCreator = {
2100
2560
  id: "@manifest-editor/creator",
2101
2561
  label: "Add content",
2102
2562
  options: { hideHeader: true, tabs: false },
2103
2563
  render(state) {
2104
- return /* @__PURE__ */ jsx18(BaseCreator, { resource: state });
2564
+ return /* @__PURE__ */ jsx20(BaseCreator, { resource: state });
2105
2565
  }
2106
2566
  };
2107
2567
 
2108
2568
  // src/BaseEditor/BaseEditor.tsx
2109
- import { useMemo as useMemo13, useEffect as useEffect9 } from "react";
2110
- import { useVault as useVault6 } from "react-iiif-vault";
2569
+ import { SidebarTabs } from "@manifest-editor/components";
2570
+ import { useContext as useContext13, useEffect as useEffect10, useMemo as useMemo14 } from "react";
2571
+ import { ResourceReactContext, useVault as useVault6 } from "react-iiif-vault";
2111
2572
 
2112
2573
  // src/EditingStack/EditingStack.tsx
2113
- import { createContext as createContext10, useCallback as useCallback5, useContext as useContext10, useEffect as useEffect8, useMemo as useMemo12, useReducer as useReducer2 } from "react";
2574
+ import { createContext as createContext12, useCallback as useCallback5, useContext as useContext12, useEffect as useEffect9, useMemo as useMemo13, useReducer as useReducer2 } from "react";
2114
2575
 
2115
2576
  // src/EditingStack/EditingStack.reducer.ts
2116
2577
  import { toRef as toRef4 } from "@iiif/parser";
@@ -2207,10 +2668,10 @@ function filterStack(newStackWithDuplicates, current) {
2207
2668
  import { EditorInstance } from "@manifest-editor/editor-api";
2208
2669
  import { useResourceContext, useVault as useVault5 } from "react-iiif-vault";
2209
2670
  import { toRef as toRef5 } from "@iiif/parser";
2210
- import { jsx as jsx19 } from "react/jsx-runtime";
2671
+ import { jsx as jsx21 } from "react/jsx-runtime";
2211
2672
  var defaultState = { stack: [], current: null, create: null };
2212
- var EditingStackContext = createContext10(defaultState);
2213
- var EditingStackActionsContext = createContext10({
2673
+ var EditingStackContext = createContext12(defaultState);
2674
+ var EditingStackActionsContext = createContext12({
2214
2675
  edit() {
2215
2676
  },
2216
2677
  close() {
@@ -2225,29 +2686,29 @@ var EditingStackActionsContext = createContext10({
2225
2686
  }
2226
2687
  });
2227
2688
  function useEditingStack() {
2228
- return useContext10(EditingStackActionsContext);
2689
+ return useContext12(EditingStackActionsContext);
2229
2690
  }
2230
2691
  function useEditingResource() {
2231
- return useContext10(EditingStackContext).current;
2692
+ return useContext12(EditingStackContext).current;
2232
2693
  }
2233
2694
  function useEditingResourceStack() {
2234
- return useContext10(EditingStackContext).stack;
2695
+ return useContext12(EditingStackContext).stack;
2235
2696
  }
2236
2697
  function useCreatingResource() {
2237
- return useContext10(EditingStackContext).create;
2698
+ return useContext12(EditingStackContext).create;
2238
2699
  }
2239
2700
  function useManifestEditor() {
2240
2701
  const { manifest } = useResourceContext();
2241
2702
  const vault = useVault5();
2242
2703
  const [key, invalidate] = useReducer2((i) => i + 1, 0);
2243
2704
  invariant(manifest, "Manifest not found");
2244
- const editor = useMemo12(() => {
2705
+ const editor = useMemo13(() => {
2245
2706
  return new EditorInstance({
2246
2707
  reference: { id: manifest, type: "Manifest" },
2247
2708
  vault
2248
2709
  });
2249
2710
  }, [manifest, vault]);
2250
- useEffect8(() => {
2711
+ useEffect9(() => {
2251
2712
  return editor.observe.start(invalidate);
2252
2713
  }, [editor]);
2253
2714
  editor.observe.key = `${key}`;
@@ -2259,13 +2720,13 @@ function useCollectionEditor() {
2259
2720
  const vault = useVault5();
2260
2721
  const [key, invalidate] = useReducer2((i) => i + 1, 0);
2261
2722
  invariant(collection, "Collection not found");
2262
- const editor = useMemo12(() => {
2723
+ const editor = useMemo13(() => {
2263
2724
  return new EditorInstance({
2264
2725
  reference: { id: collection, type: "Collection" },
2265
2726
  vault
2266
2727
  });
2267
2728
  }, [collection, vault]);
2268
- useEffect8(() => {
2729
+ useEffect9(() => {
2269
2730
  return editor.observe.start(invalidate);
2270
2731
  }, [editor]);
2271
2732
  editor.observe.key = `${key}`;
@@ -2276,14 +2737,14 @@ function useGenericEditor(ref, ctx = {}) {
2276
2737
  const vault = useVault5();
2277
2738
  const [key, invalidate] = useReducer2((i) => i + 1, 0);
2278
2739
  invariant(ref, "Resource not found");
2279
- const editor = useMemo12(() => {
2740
+ const editor = useMemo13(() => {
2280
2741
  return new EditorInstance({
2281
2742
  reference: toRef5(ref),
2282
2743
  vault,
2283
2744
  context: { resource: ref, parent: ctx.parent, index: ctx.index, parentProperty: ctx.parentProperty }
2284
2745
  });
2285
2746
  }, [ref, vault]);
2286
- useEffect8(() => {
2747
+ useEffect9(() => {
2287
2748
  return editor.observe.start(invalidate);
2288
2749
  }, [editor]);
2289
2750
  editor.observe.key = `${key}`;
@@ -2300,13 +2761,13 @@ function useEditor() {
2300
2761
  const vault = useVault5();
2301
2762
  const [key, invalidate] = useReducer2((i) => i + 1, 0);
2302
2763
  invariant(resource, "No resource selected");
2303
- const editor = useMemo12(() => {
2764
+ const editor = useMemo13(() => {
2304
2765
  return new EditorInstance({
2305
2766
  reference: resource.resource.source || resource.resource,
2306
2767
  vault
2307
2768
  });
2308
2769
  }, [resource, vault]);
2309
- useEffect8(() => {
2770
+ useEffect9(() => {
2310
2771
  return editor.observe.start(invalidate);
2311
2772
  }, [editor]);
2312
2773
  editor.observe.key = `${key}`;
@@ -2319,7 +2780,7 @@ function EditingStack(props) {
2319
2780
  const dispatch = useCallback5((action) => {
2320
2781
  _dispatch(action);
2321
2782
  }, []);
2322
- useEffect8(() => {
2783
+ useEffect9(() => {
2323
2784
  return vault.on("@iiif/REMOVE_REFERENCE", (payload) => {
2324
2785
  const action = payload.action;
2325
2786
  const parent = { id: action.payload.id, type: action.payload.type };
@@ -2343,21 +2804,20 @@ function EditingStack(props) {
2343
2804
  dispatch({ type: "create", payload: { resource: null } });
2344
2805
  };
2345
2806
  }, []);
2346
- const actions = useMemo12(() => {
2807
+ const actions = useMemo13(() => {
2347
2808
  return { edit, updateCurrent, close, back, create: create2 };
2348
2809
  }, []);
2349
2810
  const { instanceId } = useAppInstance();
2350
- return /* @__PURE__ */ jsx19(EditingStackActionsContext.Provider, { value: actions, children: /* @__PURE__ */ jsx19(EditingStackContext.Provider, { value: state, children: props.children }) }, instanceId);
2811
+ return /* @__PURE__ */ jsx21(EditingStackActionsContext.Provider, { value: actions, children: /* @__PURE__ */ jsx21(EditingStackContext.Provider, { value: state, children: props.children }) }, instanceId);
2351
2812
  }
2352
2813
 
2353
2814
  // src/BaseEditor/BaseEditor.tsx
2354
- import { SidebarTabs } from "@manifest-editor/components";
2355
- import { jsx as jsx20 } from "react/jsx-runtime";
2815
+ import { jsx as jsx22 } from "react/jsx-runtime";
2356
2816
  function BaseEditorBackButton({ fallback, backAction }) {
2357
2817
  const stack = useEditingResourceStack();
2358
2818
  const { back } = useEditingStack();
2359
2819
  if (stack.length) {
2360
- return /* @__PURE__ */ jsx20(ModulePanelButton, { onClick: back, children: /* @__PURE__ */ jsx20(BackIcon, {}) });
2820
+ return /* @__PURE__ */ jsx22(ModulePanelButton, { onClick: back, children: /* @__PURE__ */ jsx22(BackIcon, {}) });
2361
2821
  }
2362
2822
  return fallback;
2363
2823
  }
@@ -2365,20 +2825,22 @@ function BaseEditorCloseButton({ closeAction, fallback }) {
2365
2825
  const stack = useEditingResourceStack();
2366
2826
  const current = useEditingResource();
2367
2827
  if (current || stack.length) {
2368
- return /* @__PURE__ */ jsx20(
2828
+ return /* @__PURE__ */ jsx22(
2369
2829
  ModulePanelButton,
2370
2830
  {
2371
2831
  onClick: () => {
2372
2832
  closeAction();
2373
2833
  },
2374
- children: /* @__PURE__ */ jsx20(CloseIcon, {})
2834
+ children: /* @__PURE__ */ jsx22(CloseIcon, {})
2375
2835
  }
2376
2836
  );
2377
2837
  }
2378
2838
  return fallback;
2379
2839
  }
2380
2840
  function editBasedOnResource(resource, list, options, config) {
2381
- const filteredList = list.filter((l) => l.resourceType === resource.resource.source.type);
2841
+ const filteredList = list.filter(
2842
+ (l) => l.resourceType === resource.resource.source.type
2843
+ );
2382
2844
  if (filteredList.length === 0) {
2383
2845
  return null;
2384
2846
  }
@@ -2426,74 +2888,124 @@ function editBasedOnResource(resource, list, options, config) {
2426
2888
  }
2427
2889
  return null;
2428
2890
  }
2429
- function BaseEditor({ currentTab = void 0 }) {
2891
+ function BaseEditor({
2892
+ currentTab = void 0
2893
+ }) {
2430
2894
  const resource = useEditingResource();
2895
+ const currentResourceContext = useContext13(ResourceReactContext);
2431
2896
  const app = useApp();
2432
2897
  const vault = useVault6();
2433
2898
  const { change } = useLayoutActions();
2434
2899
  const set = useSetCustomTitle();
2435
2900
  const { editorConfig } = useConfig();
2436
2901
  const resourceConfig = (resource?.resource.source?.type ? editorConfig[resource?.resource.source?.type] : editorConfig.All) || {};
2437
- const match = useMemo13(() => {
2902
+ const newResourceContext = useMemo14(() => {
2903
+ const newCtx = { ...currentResourceContext };
2904
+ const id = resource?.resource.source.id;
2905
+ const type = resource?.resource.source.type;
2906
+ const mapping = {
2907
+ Collection: "collection",
2908
+ Manifest: "manifest",
2909
+ Range: "range",
2910
+ Canvas: "canvas",
2911
+ Annotation: "annotation",
2912
+ AnnotationPage: "annotationPage"
2913
+ };
2914
+ if (type && mapping[type]) {
2915
+ newCtx[mapping[type]] = id;
2916
+ }
2917
+ return newCtx;
2918
+ }, [resource, currentResourceContext]);
2919
+ function wrap(children) {
2920
+ if (!resource) {
2921
+ return children;
2922
+ }
2923
+ return /* @__PURE__ */ jsx22(ResourceReactContext.Provider, { value: newResourceContext, children });
2924
+ }
2925
+ const match = useMemo14(() => {
2438
2926
  if (!resource) {
2439
2927
  return null;
2440
2928
  }
2441
2929
  const editors = app.layout.editors || [];
2442
2930
  const resources = app.layout.resources || [];
2443
- const mappedResources = resources.map((resource2) => {
2444
- if (typeof resource2 === "string") {
2445
- return {
2446
- id: "@default/" + resource2,
2447
- label: resource2,
2448
- resourceType: resource2,
2449
- auto: true,
2450
- editors: editors.filter((e) => e.supports.resourceTypes.includes(resource2))
2451
- };
2931
+ const mappedResources = resources.map(
2932
+ (resource2) => {
2933
+ if (typeof resource2 === "string") {
2934
+ return {
2935
+ id: "@default/" + resource2,
2936
+ label: resource2,
2937
+ resourceType: resource2,
2938
+ auto: true,
2939
+ editors: editors.filter(
2940
+ (e) => e.supports.resourceTypes.includes(resource2)
2941
+ )
2942
+ };
2943
+ }
2944
+ return resource2;
2452
2945
  }
2453
- return resource2;
2454
- });
2455
- return editBasedOnResource(resource, mappedResources, { edit: true, vault }, resourceConfig);
2946
+ );
2947
+ return editBasedOnResource(
2948
+ resource,
2949
+ mappedResources,
2950
+ { edit: true, vault },
2951
+ resourceConfig
2952
+ );
2456
2953
  }, [resource, app]);
2457
- useEffect9(() => {
2954
+ useEffect10(() => {
2458
2955
  set(match?.label || "");
2459
2956
  });
2957
+ useEffect10(() => {
2958
+ const availableKeys = match?.editors.map((editor, key) => editor.id + key) || [];
2959
+ const currentKey = availableKeys.find((key) => key === currentTab);
2960
+ if (!currentKey) {
2961
+ change("@manifest-editor/editor", { currentTab: availableKeys[0] });
2962
+ }
2963
+ }, [match?.editors, currentTab, change]);
2460
2964
  if (!resource || !match) {
2461
2965
  return null;
2462
2966
  }
2463
2967
  if (resourceConfig.singleTab) {
2464
- const first = (match?.editors || []).find((editor) => editor.id === resourceConfig.singleTab);
2968
+ const first = (match?.editors || []).find(
2969
+ (editor) => editor.id === resourceConfig.singleTab
2970
+ );
2465
2971
  if (first) {
2466
- return /* @__PURE__ */ jsx20("div", { className: "w-full", children: first.component(resourceConfig) });
2972
+ return wrap(
2973
+ /* @__PURE__ */ jsx22("div", { className: "w-full", children: first.component(resourceConfig) })
2974
+ );
2467
2975
  }
2468
2976
  }
2469
- return /* @__PURE__ */ jsx20(
2470
- SidebarTabs,
2471
- {
2472
- menuId: resource.resource.source.id,
2473
- menu: (match?.editors || []).map((editor, key) => {
2474
- return {
2475
- id: editor.id + key,
2476
- label: editor.label,
2477
- renderComponent: () => editor.component(resourceConfig)
2478
- };
2479
- }),
2480
- selectedKey: currentTab,
2481
- onSelectionChange: (p) => change("@manifest-editor/editor", { currentTab: p })
2482
- },
2483
- resource.resource.source?.id
2977
+ return wrap(
2978
+ /* @__PURE__ */ jsx22(
2979
+ SidebarTabs,
2980
+ {
2981
+ menuId: resource.resource.source.id,
2982
+ menu: (match?.editors || []).map((editor, key) => {
2983
+ return {
2984
+ id: editor.id + key,
2985
+ label: editor.label,
2986
+ renderComponent: () => editor.component(resourceConfig)
2987
+ };
2988
+ }),
2989
+ selectedKey: currentTab,
2990
+ onSelectionChange: (p) => {
2991
+ change("@manifest-editor/editor", { currentTab: p });
2992
+ }
2993
+ },
2994
+ resource.resource.source?.id
2995
+ )
2484
2996
  );
2485
2997
  }
2486
2998
 
2487
2999
  // src/BaseEditor/index.tsx
2488
- import { jsx as jsx21 } from "react/jsx-runtime";
3000
+ import { jsx as jsx23 } from "react/jsx-runtime";
2489
3001
  var baseEditor = {
2490
3002
  id: "@manifest-editor/editor",
2491
3003
  label: "Editor",
2492
3004
  options: { hideHeader: true, tabs: true, minWidth: 400 },
2493
- renderBackAction: ({ backAction, fallback }) => /* @__PURE__ */ jsx21(BaseEditorBackButton, { backAction, fallback }),
2494
- renderCloseAction: ({ closeAction, fallback }) => /* @__PURE__ */ jsx21(BaseEditorCloseButton, { closeAction, fallback }),
3005
+ renderBackAction: ({ backAction, fallback }) => /* @__PURE__ */ jsx23(BaseEditorBackButton, { backAction, fallback }),
3006
+ renderCloseAction: ({ closeAction, fallback }) => /* @__PURE__ */ jsx23(BaseEditorCloseButton, { closeAction, fallback }),
2495
3007
  render({ currentTab }) {
2496
- return /* @__PURE__ */ jsx21(BaseEditor, { currentTab });
3008
+ return /* @__PURE__ */ jsx23(BaseEditor, { currentTab });
2497
3009
  }
2498
3010
  };
2499
3011
 
@@ -2501,7 +3013,7 @@ var baseEditor = {
2501
3013
  import { Sidebar, SidebarHeader, SidebarContent, Form, ActionButton } from "@manifest-editor/components";
2502
3014
 
2503
3015
  // src/hooks/use-decay-state.ts
2504
- import { useMemo as useMemo14, useRef as useRef4, useState as useState6 } from "react";
3016
+ import { useMemo as useMemo15, useRef as useRef4, useState as useState6 } from "react";
2505
3017
  function useDecayState(time) {
2506
3018
  const [active, _setActive] = useState6(false);
2507
3019
  const lastTimeout = useRef4();
@@ -2526,11 +3038,11 @@ function useDecayState(time) {
2526
3038
  }
2527
3039
  _setActive(true);
2528
3040
  }
2529
- return useMemo14(() => [active, { set, clear }], [active]);
3041
+ return useMemo15(() => [active, { set, clear }], [active]);
2530
3042
  }
2531
3043
 
2532
3044
  // src/ConfigContext/ConfigEditor.tsx
2533
- import { jsx as jsx22, jsxs as jsxs10 } from "react/jsx-runtime";
3045
+ import { jsx as jsx24, jsxs as jsxs10 } from "react/jsx-runtime";
2534
3046
  function ConfigEditor() {
2535
3047
  const previews = usePreviewContext();
2536
3048
  const config = useConfig();
@@ -2558,12 +3070,12 @@ function ConfigEditor() {
2558
3070
  saveState.clear();
2559
3071
  }
2560
3072
  return /* @__PURE__ */ jsxs10(Sidebar, { children: [
2561
- /* @__PURE__ */ jsx22(SidebarHeader, { title: "Workspace configuration" }),
2562
- isSaved ? /* @__PURE__ */ jsx22("div", { className: "bg-me-primary-500 text-white p-3 text-sm", children: "Changes saved" }) : null,
2563
- /* @__PURE__ */ jsx22(SidebarContent, { className: "p-4", children: /* @__PURE__ */ jsxs10(Form.Form, { onSubmit, className: "flex flex-col gap-3", children: [
3073
+ /* @__PURE__ */ jsx24(SidebarHeader, { title: "Workspace configuration" }),
3074
+ isSaved ? /* @__PURE__ */ jsx24("div", { className: "bg-me-primary-500 text-white p-3 text-sm", children: "Changes saved" }) : null,
3075
+ /* @__PURE__ */ jsx24(SidebarContent, { className: "p-4", children: /* @__PURE__ */ jsxs10(Form.Form, { onSubmit, className: "flex flex-col gap-3", children: [
2564
3076
  /* @__PURE__ */ jsxs10(Form.InputContainer, { children: [
2565
- /* @__PURE__ */ jsx22(Form.Label, { htmlFor: "defaultLanguage", children: "Default Language" }),
2566
- /* @__PURE__ */ jsx22(
3077
+ /* @__PURE__ */ jsx24(Form.Label, { htmlFor: "defaultLanguage", children: "Default Language" }),
3078
+ /* @__PURE__ */ jsx24(
2567
3079
  Form.Input,
2568
3080
  {
2569
3081
  type: "text",
@@ -2574,8 +3086,8 @@ function ConfigEditor() {
2574
3086
  )
2575
3087
  ] }),
2576
3088
  /* @__PURE__ */ jsxs10(Form.InputContainer, { children: [
2577
- /* @__PURE__ */ jsx22(Form.Label, { htmlFor: "availableLanguages", children: "Available Languages" }),
2578
- /* @__PURE__ */ jsx22(
3089
+ /* @__PURE__ */ jsx24(Form.Label, { htmlFor: "availableLanguages", children: "Available Languages" }),
3090
+ /* @__PURE__ */ jsx24(
2579
3091
  Form.Input,
2580
3092
  {
2581
3093
  type: "text",
@@ -2586,7 +3098,7 @@ function ConfigEditor() {
2586
3098
  )
2587
3099
  ] }),
2588
3100
  /* @__PURE__ */ jsxs10(Form.InputContainer, { horizontal: true, className: "my-3", children: [
2589
- /* @__PURE__ */ jsx22(
3101
+ /* @__PURE__ */ jsx24(
2590
3102
  Form.Input,
2591
3103
  {
2592
3104
  type: "checkbox",
@@ -2595,10 +3107,22 @@ function ConfigEditor() {
2595
3107
  defaultChecked: config.i18n?.advancedLanguageMode || false
2596
3108
  }
2597
3109
  ),
2598
- /* @__PURE__ */ jsx22(Form.Label, { htmlFor: "advancedLanguageMode", children: "Advanced Language Mode" })
3110
+ /* @__PURE__ */ jsx24(Form.Label, { htmlFor: "advancedLanguageMode", children: "Advanced Language Mode" })
2599
3111
  ] }),
2600
3112
  /* @__PURE__ */ jsxs10(Form.InputContainer, { horizontal: true, className: "my-3", children: [
2601
- /* @__PURE__ */ jsx22(
3113
+ /* @__PURE__ */ jsx24(
3114
+ Form.Input,
3115
+ {
3116
+ type: "checkbox",
3117
+ name: "textGranularityEnabled",
3118
+ id: "textGranularityEnabled",
3119
+ defaultChecked: config.i18n?.textGranularityEnabled || false
3120
+ }
3121
+ ),
3122
+ /* @__PURE__ */ jsx24(Form.Label, { htmlFor: "textGranularityEnabled", children: "Enable text granularity" })
3123
+ ] }),
3124
+ /* @__PURE__ */ jsxs10(Form.InputContainer, { horizontal: true, className: "my-3", children: [
3125
+ /* @__PURE__ */ jsx24(
2602
3126
  Form.Input,
2603
3127
  {
2604
3128
  type: "checkbox",
@@ -2607,16 +3131,16 @@ function ConfigEditor() {
2607
3131
  defaultChecked: config.export?.version === 2
2608
3132
  }
2609
3133
  ),
2610
- /* @__PURE__ */ jsx22(Form.Label, { htmlFor: "isVersion2", children: "Export Presentation 2 Manifests" })
3134
+ /* @__PURE__ */ jsx24(Form.Label, { htmlFor: "isVersion2", children: "Export Presentation 2 Manifests" })
2611
3135
  ] }),
2612
3136
  /* @__PURE__ */ jsxs10(Form.InputContainer, { children: [
2613
- /* @__PURE__ */ jsx22(Form.Label, { htmlFor: "defaultPreview", children: "Default preview" }),
2614
- /* @__PURE__ */ jsx22("div", { children: previews.configs.map((preview, key) => {
3137
+ /* @__PURE__ */ jsx24(Form.Label, { htmlFor: "defaultPreview", children: "Default preview" }),
3138
+ /* @__PURE__ */ jsx24("div", { children: previews.configs.map((preview, key) => {
2615
3139
  if (preview.type === "iiif-preview-service") {
2616
3140
  return null;
2617
3141
  }
2618
3142
  return /* @__PURE__ */ jsxs10(Form.InputContainer, { horizontal: true, children: [
2619
- /* @__PURE__ */ jsx22(
3143
+ /* @__PURE__ */ jsx24(
2620
3144
  Form.Input,
2621
3145
  {
2622
3146
  type: "radio",
@@ -2626,17 +3150,25 @@ function ConfigEditor() {
2626
3150
  defaultChecked: !config.defaultPreview ? key === 0 : config.defaultPreview === preview.id
2627
3151
  }
2628
3152
  ),
2629
- /* @__PURE__ */ jsx22("label", { htmlFor: preview.id, children: preview.label })
3153
+ /* @__PURE__ */ jsx24("label", { htmlFor: preview.id, children: preview.label })
2630
3154
  ] }, preview.id);
2631
3155
  }) })
2632
3156
  ] }),
2633
- /* @__PURE__ */ jsx22("div", { className: "mt-5", children: /* @__PURE__ */ jsx22(ActionButton, { type: "submit", children: "Save changes" }) })
3157
+ /* @__PURE__ */ jsx24(
3158
+ "a",
3159
+ {
3160
+ className: "text-sm text-me-primary-500 hover:underline hover:text-me-primary-600",
3161
+ href: window.location.pathname.includes("/exhibition") ? window.location.pathname.replace("/exhibition", "") || "/" : `${window.location.pathname}/exhibition`,
3162
+ children: window.location.pathname.includes("/exhibition") ? "Return to Manifest Editor" : "Go to Exhibition Editor"
3163
+ }
3164
+ ),
3165
+ /* @__PURE__ */ jsx24("div", { className: "mt-5", children: /* @__PURE__ */ jsx24(ActionButton, { type: "submit", children: "Save changes" }) })
2634
3166
  ] }) })
2635
3167
  ] });
2636
3168
  }
2637
3169
 
2638
3170
  // src/ExportPanel/ExportPanel.tsx
2639
- import { useMemo as useMemo16 } from "react";
3171
+ import { useMemo as useMemo17 } from "react";
2640
3172
  import { useManifest, useVault as useVault7 } from "react-iiif-vault";
2641
3173
 
2642
3174
  // ../ui/ui/CenterPanelContainer/CenterPanelContainer.module.css
@@ -2648,37 +3180,37 @@ var CenterPanelContainer_default = {
2648
3180
  };
2649
3181
 
2650
3182
  // ../ui/ui/CenterPanelContainer/CenterPanelContainer.tsx
2651
- import { jsx as jsx23, jsxs as jsxs11 } from "react/jsx-runtime";
3183
+ import { jsx as jsx25, jsxs as jsxs11 } from "react/jsx-runtime";
2652
3184
  function CenterPanelContainer(props) {
2653
3185
  return /* @__PURE__ */ jsxs11("div", { className: CenterPanelContainer_default.CenterPanelContainer, children: [
2654
3186
  props.title || props.close ? /* @__PURE__ */ jsxs11("div", { className: CenterPanelContainer_default.CenterPanelHeader, children: [
2655
- props.title ? /* @__PURE__ */ jsx23("h2", { className: CenterPanelContainer_default.CenterPanelTitle, children: props.title }) : null,
2656
- props.close ? /* @__PURE__ */ jsx23(Button, { className: CenterPanelContainer_default.CenterPanelClose, onClick: props.close, children: /* @__PURE__ */ jsx23(CloseIcon, {}) }) : null
3187
+ props.title ? /* @__PURE__ */ jsx25("h2", { className: CenterPanelContainer_default.CenterPanelTitle, children: props.title }) : null,
3188
+ props.close ? /* @__PURE__ */ jsx25(Button, { className: CenterPanelContainer_default.CenterPanelClose, onClick: props.close, children: /* @__PURE__ */ jsx25(CloseIcon, {}) }) : null
2657
3189
  ] }) : null,
2658
3190
  props.children
2659
3191
  ] });
2660
3192
  }
2661
3193
 
2662
3194
  // ../ui/atoms/Accordion.tsx
2663
- import styled9 from "styled-components";
3195
+ import styled7 from "styled-components";
2664
3196
  import {
2665
3197
  createRef,
2666
3198
  forwardRef,
2667
- useEffect as useEffect10,
3199
+ useEffect as useEffect11,
2668
3200
  useImperativeHandle,
2669
- useMemo as useMemo15,
3201
+ useMemo as useMemo16,
2670
3202
  useRef as useRef5,
2671
3203
  useState as useState7
2672
3204
  } from "react";
2673
- import { jsx as jsx24, jsxs as jsxs12 } from "react/jsx-runtime";
2674
- var AccordionContainer = styled9.div`
3205
+ import { jsx as jsx26, jsxs as jsxs12 } from "react/jsx-runtime";
3206
+ var AccordionContainer = styled7.div`
2675
3207
  flex: 1;
2676
3208
  display: flex;
2677
3209
  width: 100%;
2678
3210
  flex-direction: column;
2679
3211
  position: relative;
2680
3212
  `;
2681
- var ItemRow = styled9.div`
3213
+ var ItemRow = styled7.div`
2682
3214
  background: #fff;
2683
3215
  position: relative;
2684
3216
  border-bottom: 1px solid #d0d0d0;
@@ -2697,12 +3229,12 @@ var ItemRow = styled9.div`
2697
3229
  //justify-content: center;
2698
3230
  }
2699
3231
  `;
2700
- var ItemDescription = styled9.p`
3232
+ var ItemDescription = styled7.p`
2701
3233
  font-size: 0.9em;
2702
3234
  color: #777;
2703
3235
  font-weight: 400;
2704
3236
  `;
2705
- var ItemLabel = styled9.button`
3237
+ var ItemLabel = styled7.button`
2706
3238
  color: inherit;
2707
3239
  text-rendering: geometricPrecision;
2708
3240
  border: none;
@@ -2745,7 +3277,7 @@ var ItemLabel = styled9.button`
2745
3277
  }
2746
3278
  }
2747
3279
  `;
2748
- var ItemCollapse = styled9.div`
3280
+ var ItemCollapse = styled7.div`
2749
3281
  font-size: 1.4em;
2750
3282
  padding-right: 0.3em;
2751
3283
  display: flex;
@@ -2755,7 +3287,7 @@ var ItemCollapse = styled9.div`
2755
3287
  font-size: 2em;
2756
3288
  }
2757
3289
  `;
2758
- var ItemIcon = styled9.div`
3290
+ var ItemIcon = styled7.div`
2759
3291
  width: 2em;
2760
3292
  align-items: center;
2761
3293
  //padding-top: 0.5em;
@@ -2769,12 +3301,12 @@ var ItemIcon = styled9.div`
2769
3301
  color: #999;
2770
3302
  }
2771
3303
  `;
2772
- var ItemBodyInner = styled9.div`
3304
+ var ItemBodyInner = styled7.div`
2773
3305
  min-height: 0;
2774
3306
  overflow: visible;
2775
3307
  display: flex;
2776
3308
  `;
2777
- var ItemBodyPadding = styled9.div`
3309
+ var ItemBodyPadding = styled7.div`
2778
3310
  min-height: 0;
2779
3311
  overflow: visible;
2780
3312
  flex: 1;
@@ -2788,7 +3320,7 @@ var ItemBodyPadding = styled9.div`
2788
3320
  overflow-y: auto;
2789
3321
  }
2790
3322
  `;
2791
- var ItemBody = styled9.section`
3323
+ var ItemBody = styled7.section`
2792
3324
  display: grid;
2793
3325
  grid-template-rows: 0fr;
2794
3326
  overflow: hidden;
@@ -2817,7 +3349,7 @@ var ItemBody = styled9.section`
2817
3349
  box-shadow: inset 0px 2px 0px 0 rgba(0, 0, 0, 0.1);
2818
3350
  }
2819
3351
  `;
2820
- var ItemHeading = styled9.div`
3352
+ var ItemHeading = styled7.div`
2821
3353
  position: sticky;
2822
3354
  display: flex;
2823
3355
  top: 0;
@@ -2857,7 +3389,7 @@ var ItemHeading = styled9.div`
2857
3389
  var noop = () => void 0;
2858
3390
  var keyIdIndex = 0;
2859
3391
  function useId() {
2860
- return useMemo15(() => keyIdIndex++, []);
3392
+ return useMemo16(() => keyIdIndex++, []);
2861
3393
  }
2862
3394
  function useAccordionItems(itemsLength, singleMode = false) {
2863
3395
  const [elRefs, setElRefs] = useState7([]);
@@ -2929,7 +3461,7 @@ function useAccordionItems(itemsLength, singleMode = false) {
2929
3461
  }
2930
3462
  }
2931
3463
  };
2932
- useEffect10(() => {
3464
+ useEffect11(() => {
2933
3465
  setElRefs(
2934
3466
  (elRefs_) => Array(itemsLength).fill(0).map((_, i) => elRefs_[i] || createRef())
2935
3467
  );
@@ -3027,14 +3559,14 @@ var AccordionItem = forwardRef(function AccordionItem2(props, ref) {
3027
3559
  };
3028
3560
  return /* @__PURE__ */ jsxs12(ItemRow, { "data-large": props.large, "data-open": open, children: [
3029
3561
  /* @__PURE__ */ jsxs12(ItemHeading, { "data-open": open, children: [
3030
- props.icon ? /* @__PURE__ */ jsx24(ItemIcon, { onClick: toggle, children: props.icon }) : null,
3562
+ props.icon ? /* @__PURE__ */ jsx26(ItemIcon, { onClick: toggle, children: props.icon }) : null,
3031
3563
  /* @__PURE__ */ jsxs12(ItemLabel, { ref: btn, onClick: toggle, "aria-expanded": open, "aria-controls": `accordion-${id}`, children: [
3032
3564
  props.label,
3033
- props.description ? /* @__PURE__ */ jsx24(ItemDescription, { children: props.description }) : null
3565
+ props.description ? /* @__PURE__ */ jsx26(ItemDescription, { children: props.description }) : null
3034
3566
  ] }),
3035
- /* @__PURE__ */ jsx24(ItemCollapse, { onClick: toggle, children: /* @__PURE__ */ jsx24(DownIcon, { width: "1em", height: "1em", rotate: open ? 0 : 180 }) })
3567
+ /* @__PURE__ */ jsx26(ItemCollapse, { onClick: toggle, children: /* @__PURE__ */ jsx26(DownIcon, { width: "1em", height: "1em", rotate: open ? 0 : 180 }) })
3036
3568
  ] }),
3037
- /* @__PURE__ */ jsx24(
3569
+ /* @__PURE__ */ jsx26(
3038
3570
  ItemBody,
3039
3571
  {
3040
3572
  "aria-labelledby": `accordion-${id}`,
@@ -3046,7 +3578,7 @@ var AccordionItem = forwardRef(function AccordionItem2(props, ref) {
3046
3578
  $initial: !open,
3047
3579
  "data-scrolled": scrolled,
3048
3580
  hidden: !open,
3049
- children: /* @__PURE__ */ jsx24(ItemBodyInner, { children: /* @__PURE__ */ jsx24(
3581
+ children: /* @__PURE__ */ jsx26(ItemBodyInner, { children: /* @__PURE__ */ jsx26(
3050
3582
  ItemBodyPadding,
3051
3583
  {
3052
3584
  "data-max-height": !!maxHeight,
@@ -3061,18 +3593,18 @@ var AccordionItem = forwardRef(function AccordionItem2(props, ref) {
3061
3593
  });
3062
3594
  function Accordion(props) {
3063
3595
  const { getItemProps, onKeyDown } = useAccordionItems(props.items.length, props.singleMode);
3064
- return /* @__PURE__ */ jsx24(AccordionContainer, { onKeyDown, children: props.items.map((item, key) => /* @__PURE__ */ jsx24(AccordionItem, { overflow: props.overflow, maxHeight: props.maxHeight, ...item, ...getItemProps(key), children: item.children }, key)) });
3596
+ return /* @__PURE__ */ jsx26(AccordionContainer, { onKeyDown, children: props.items.map((item, key) => /* @__PURE__ */ jsx26(AccordionItem, { overflow: props.overflow, maxHeight: props.maxHeight, ...item, ...getItemProps(key), children: item.children }, key)) });
3065
3597
  }
3066
3598
 
3067
3599
  // ../ui/icons/DownloadIcon.tsx
3068
- import { jsx as jsx25 } from "react/jsx-runtime";
3600
+ import { jsx as jsx27 } from "react/jsx-runtime";
3069
3601
  function DownloadIcon() {
3070
- return /* @__PURE__ */ jsx25("svg", { xmlns: "http://www.w3.org/2000/svg", height: "48", viewBox: "0 -960 960 960", width: "48", children: /* @__PURE__ */ jsx25("path", { d: "M220-160q-24 0-42-18t-18-42v-143h60v143h520v-143h60v143q0 24-18 42t-42 18H220Zm260-153L287-506l43-43 120 120v-371h60v371l120-120 43 43-193 193Z" }) });
3602
+ return /* @__PURE__ */ jsx27("svg", { xmlns: "http://www.w3.org/2000/svg", height: "48", viewBox: "0 -960 960 960", width: "48", children: /* @__PURE__ */ jsx27("path", { d: "M220-160q-24 0-42-18t-18-42v-143h60v143h520v-143h60v143q0 24-18 42t-42 18H220Zm260-153L287-506l43-43 120 120v-371h60v371l120-120 43 43-193 193Z" }) });
3071
3603
  }
3072
3604
 
3073
3605
  // ../ui/atoms/ButtonRow.tsx
3074
- import styled10 from "styled-components";
3075
- var ButtonRow = styled10.div`
3606
+ import styled8 from "styled-components";
3607
+ var ButtonRow = styled8.div`
3076
3608
  padding: 0.3em;
3077
3609
 
3078
3610
  display: flex;
@@ -3097,18 +3629,18 @@ var ButtonRow = styled10.div`
3097
3629
  `;
3098
3630
 
3099
3631
  // src/ExportPanel/ExportPanel.tsx
3100
- import { jsx as jsx26, jsxs as jsxs13 } from "react/jsx-runtime";
3632
+ import { jsx as jsx28, jsxs as jsxs13 } from "react/jsx-runtime";
3101
3633
  function ExportPanel(props) {
3102
3634
  const manifest = useManifest();
3103
3635
  const vault = useVault7();
3104
3636
  const actions = useLayoutActions();
3105
- const version3 = useMemo16(() => {
3637
+ const version3 = useMemo17(() => {
3106
3638
  return JSON.stringify(vault.toPresentation3(manifest), null, 2);
3107
3639
  }, [manifest, vault]);
3108
- const version2 = useMemo16(() => {
3640
+ const version2 = useMemo17(() => {
3109
3641
  return JSON.stringify(vault.toPresentation2(manifest), null, 2);
3110
3642
  }, [manifest, vault]);
3111
- return /* @__PURE__ */ jsx26(CenterPanelContainer, { title: "Export manifest", close: actions.centerPanel.popStack, children: /* @__PURE__ */ jsx26("div", { style: { flex: 1, overflowY: "auto" }, children: /* @__PURE__ */ jsx26(
3643
+ return /* @__PURE__ */ jsx28(CenterPanelContainer, { title: "Export manifest", close: actions.centerPanel.popStack, children: /* @__PURE__ */ jsx28("div", { style: { flex: 1, overflowY: "auto" }, children: /* @__PURE__ */ jsx28(
3112
3644
  Accordion,
3113
3645
  {
3114
3646
  items: [
@@ -3119,12 +3651,12 @@ function ExportPanel(props) {
3119
3651
  large: true,
3120
3652
  initialOpen: true,
3121
3653
  overflow: true,
3122
- icon: /* @__PURE__ */ jsx26(Button, { onClick: () => createDownload(version3, "manifest.json"), children: /* @__PURE__ */ jsx26(DownloadIcon, {}) }),
3654
+ icon: /* @__PURE__ */ jsx28(Button, { onClick: () => createDownload(version3, "manifest.json"), children: /* @__PURE__ */ jsx28(DownloadIcon, {}) }),
3123
3655
  children: /* @__PURE__ */ jsxs13("div", { style: { maxWidth: "100%" }, children: [
3124
- /* @__PURE__ */ jsx26("pre", { style: { whiteSpace: "pre-wrap" }, children: JSON.stringify(vault.toPresentation3(manifest), null, 2) }),
3656
+ /* @__PURE__ */ jsx28("pre", { style: { whiteSpace: "pre-wrap" }, children: JSON.stringify(vault.toPresentation3(manifest), null, 2) }),
3125
3657
  /* @__PURE__ */ jsxs13(ButtonRow, { "data-sticky": "true", children: [
3126
- /* @__PURE__ */ jsx26(Button, { onClick: () => copyToClipboard(version3), children: "Copy to clipboard" }),
3127
- /* @__PURE__ */ jsx26(Button, { onClick: () => createDownload(version3, "manifest.json"), children: "Download" })
3658
+ /* @__PURE__ */ jsx28(Button, { onClick: () => copyToClipboard(version3), children: "Copy to clipboard" }),
3659
+ /* @__PURE__ */ jsx28(Button, { onClick: () => createDownload(version3, "manifest.json"), children: "Download" })
3128
3660
  ] })
3129
3661
  ] })
3130
3662
  },
@@ -3133,12 +3665,12 @@ function ExportPanel(props) {
3133
3665
  description: 'Download this version by clicking the "Download" button.',
3134
3666
  maxHeight: 400,
3135
3667
  large: true,
3136
- icon: /* @__PURE__ */ jsx26(Button, { onClick: () => createDownload(version2, "manifest.json"), children: /* @__PURE__ */ jsx26(DownloadIcon, {}) }),
3668
+ icon: /* @__PURE__ */ jsx28(Button, { onClick: () => createDownload(version2, "manifest.json"), children: /* @__PURE__ */ jsx28(DownloadIcon, {}) }),
3137
3669
  children: /* @__PURE__ */ jsxs13("div", { style: { maxWidth: "100%" }, children: [
3138
- /* @__PURE__ */ jsx26("pre", { style: { whiteSpace: "pre-wrap" }, children: JSON.stringify(vault.toPresentation2(manifest), null, 2) }),
3670
+ /* @__PURE__ */ jsx28("pre", { style: { whiteSpace: "pre-wrap" }, children: JSON.stringify(vault.toPresentation2(manifest), null, 2) }),
3139
3671
  /* @__PURE__ */ jsxs13(ButtonRow, { "data-sticky": "true", children: [
3140
- /* @__PURE__ */ jsx26(Button, { onClick: () => copyToClipboard(version2), children: "Copy to clipboard" }),
3141
- /* @__PURE__ */ jsx26(Button, { onClick: () => createDownload(version2, "manifest.json"), children: "Download" })
3672
+ /* @__PURE__ */ jsx28(Button, { onClick: () => copyToClipboard(version2), children: "Copy to clipboard" }),
3673
+ /* @__PURE__ */ jsx28(Button, { onClick: () => createDownload(version2, "manifest.json"), children: "Download" })
3142
3674
  ] })
3143
3675
  ] })
3144
3676
  }
@@ -3147,6 +3679,9 @@ function ExportPanel(props) {
3147
3679
  ) }) });
3148
3680
  }
3149
3681
 
3682
+ // src/Layout/Layout.tsx
3683
+ import { Modal, PanelSideMenu as PanelSideMenu2 } from "@manifest-editor/components";
3684
+
3150
3685
  // ../ui/ui/GhostBlocks/GhostBlocks.module.css
3151
3686
  var GhostBlocks_default = {
3152
3687
  ghostLoadingBlock: "GhostBlocks_ghostLoadingBlock",
@@ -3155,40 +3690,60 @@ var GhostBlocks_default = {
3155
3690
  };
3156
3691
 
3157
3692
  // ../ui/ui/GhostBlocks/GhostBlocks.tsx
3158
- import { Fragment as Fragment3, jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
3693
+ import { Fragment as Fragment3, jsx as jsx29, jsxs as jsxs14 } from "react/jsx-runtime";
3159
3694
  function GhostBlocks() {
3160
3695
  return /* @__PURE__ */ jsxs14(Fragment3, { children: [
3161
- /* @__PURE__ */ jsx27("div", { "data-header": "true", className: GhostBlocks_default.ghostLoadingBlock }),
3696
+ /* @__PURE__ */ jsx29("div", { "data-header": "true", className: GhostBlocks_default.ghostLoadingBlock }),
3162
3697
  /* @__PURE__ */ jsxs14("div", { className: GhostBlocks_default.ghostBlockList, children: [
3163
- /* @__PURE__ */ jsx27("div", { className: GhostBlocks_default.ghostLoadingBlock }),
3164
- /* @__PURE__ */ jsx27("div", { className: GhostBlocks_default.ghostLoadingBlock }),
3165
- /* @__PURE__ */ jsx27("div", { className: GhostBlocks_default.ghostLoadingBlock }),
3166
- /* @__PURE__ */ jsx27("div", { className: GhostBlocks_default.ghostLoadingBlock })
3698
+ /* @__PURE__ */ jsx29("div", { className: GhostBlocks_default.ghostLoadingBlock }),
3699
+ /* @__PURE__ */ jsx29("div", { className: GhostBlocks_default.ghostLoadingBlock }),
3700
+ /* @__PURE__ */ jsx29("div", { className: GhostBlocks_default.ghostLoadingBlock }),
3701
+ /* @__PURE__ */ jsx29("div", { className: GhostBlocks_default.ghostLoadingBlock })
3167
3702
  ] })
3168
3703
  ] });
3169
3704
  }
3170
3705
 
3171
3706
  // src/Layout/Layout.tsx
3172
- import { memo as memo4, useContext as useContext11, useLayoutEffect as useLayoutEffect3 } from "react";
3707
+ import { memo as memo4, useContext as useContext14, useLayoutEffect as useLayoutEffect3 } from "react";
3173
3708
  import { ReactVaultContext as ReactVaultContext2 } from "react-iiif-vault";
3174
3709
  import { Transition } from "react-transition-group";
3175
3710
  import equal from "shallowequal";
3176
3711
 
3712
+ // src/hooks/use-match-media.ts
3713
+ import { useState as useState8, useLayoutEffect } from "react";
3714
+ function useMatchMedia(queries, defaultValues = []) {
3715
+ const initialValues = defaultValues.length ? defaultValues : Array(queries.length).fill(false);
3716
+ if (typeof window === "undefined")
3717
+ return initialValues;
3718
+ const mediaQueryLists = queries.map((q) => window.matchMedia(q));
3719
+ const getValue2 = () => {
3720
+ const matchedQueries = mediaQueryLists.map((mql) => mql.matches);
3721
+ return matchedQueries;
3722
+ };
3723
+ const [value, setValue] = useState8(getValue2);
3724
+ useLayoutEffect(() => {
3725
+ const handler = () => setValue(getValue2);
3726
+ mediaQueryLists.forEach((mql) => mql.addListener(handler));
3727
+ return () => mediaQueryLists.forEach((mql) => mql.removeListener(handler));
3728
+ }, []);
3729
+ return value;
3730
+ }
3731
+
3177
3732
  // src/Layout/Layout.mobile.tsx
3178
- import styled11, { css as css5 } from "styled-components";
3179
- var Container2 = styled11.div`
3733
+ import styled9, { css as css4 } from "styled-components";
3734
+ var Container2 = styled9.div`
3180
3735
  position: relative;
3181
3736
  display: flex;
3182
3737
  flex: 1;
3183
3738
  overflow: hidden;
3184
3739
  flex-direction: column;
3185
3740
  `;
3186
- var CenterPanel = styled11.div`
3741
+ var CenterPanel = styled9.div`
3187
3742
  flex: 1;
3188
3743
  position: relative;
3189
3744
  z-index: 7;
3190
3745
  `;
3191
- var MobileBar = styled11.div`
3746
+ var MobileBar = styled9.div`
3192
3747
  display: flex;
3193
3748
  justify-content: space-around;
3194
3749
  width: 100%;
@@ -3197,7 +3752,7 @@ var MobileBar = styled11.div`
3197
3752
  padding: 0.5em;
3198
3753
  height: 3.4rem;
3199
3754
  `;
3200
- var LeftBarButton = styled11.button`
3755
+ var LeftBarButton = styled9.button`
3201
3756
  //background: red;
3202
3757
  padding: 0.5em 1em;
3203
3758
  width: 32%;
@@ -3206,7 +3761,7 @@ var LeftBarButton = styled11.button`
3206
3761
  border: none;
3207
3762
  background: #ffffff;
3208
3763
  `;
3209
- var PreviewBarButton = styled11.button`
3764
+ var PreviewBarButton = styled9.button`
3210
3765
  padding: 0.5em 1em;
3211
3766
  width: 32%;
3212
3767
 
@@ -3216,13 +3771,13 @@ var PreviewBarButton = styled11.button`
3216
3771
  border: 1px solid rgba(0, 0, 0, 0.21);
3217
3772
  color: #ffffff;
3218
3773
  `;
3219
- var DrawerContainer = styled11.div`
3774
+ var DrawerContainer = styled9.div`
3220
3775
  position: relative;
3221
3776
  width: 32%;
3222
3777
  margin: 0 0.75em;
3223
3778
  z-index: 9;
3224
3779
  `;
3225
- var DrawerButton = styled11.button`
3780
+ var DrawerButton = styled9.button`
3226
3781
  padding: 0.4em 1em 0.65em;
3227
3782
  position: absolute;
3228
3783
  width: 100%;
@@ -3242,7 +3797,7 @@ var DrawerButton = styled11.button`
3242
3797
  font-size: 1.8em;
3243
3798
  }
3244
3799
  `;
3245
- var DrawerBody = styled11.div`
3800
+ var DrawerBody = styled9.div`
3246
3801
  background: #fff;
3247
3802
  display: flex;
3248
3803
  position: absolute;
@@ -3259,7 +3814,7 @@ var DrawerBody = styled11.div`
3259
3814
  transition:
3260
3815
  0.3s transform ease-in-out,
3261
3816
  0.3s box-shadow;
3262
- ${(props) => props.$open && css5`
3817
+ ${(props) => props.$open && css4`
3263
3818
  box-shadow:
3264
3819
  0 -5px 15px 0 rgba(0, 0, 0, 0.1),
3265
3820
  0 -3px 5px 0 rgba(0, 0, 0, 0.1);
@@ -3273,7 +3828,7 @@ var DrawerBody = styled11.div`
3273
3828
  font-size: 1.1em;
3274
3829
  }
3275
3830
  `;
3276
- var LeftPanel = styled11.div`
3831
+ var LeftPanel = styled9.div`
3277
3832
  position: absolute;
3278
3833
  transform: translateX(-100%);
3279
3834
  background: #fff;
@@ -3283,11 +3838,11 @@ var LeftPanel = styled11.div`
3283
3838
  z-index: 10;
3284
3839
  overflow-y: auto;
3285
3840
  transition: 0.5s transform;
3286
- ${(props) => props.$open && css5`
3841
+ ${(props) => props.$open && css4`
3287
3842
  transform: translateX(0);
3288
3843
  `}
3289
3844
  `;
3290
- var Lightbox = styled11.div`
3845
+ var Lightbox = styled9.div`
3291
3846
  background: rgba(0, 0, 0, 0.4);
3292
3847
  pointer-events: none;
3293
3848
  position: absolute;
@@ -3299,15 +3854,15 @@ var Lightbox = styled11.div`
3299
3854
  opacity: 0;
3300
3855
  transition: opacity 0.5s;
3301
3856
 
3302
- ${(props) => props.$open && css5`
3857
+ ${(props) => props.$open && css4`
3303
3858
  pointer-events: visible;
3304
3859
  opacity: 1;
3305
3860
  `}
3306
3861
  `;
3307
3862
 
3308
3863
  // src/Layout/Layout.styles.ts
3309
- import styled12, { css as css6 } from "styled-components";
3310
- var OuterWrapper = styled12.div`
3864
+ import styled10, { css as css5 } from "styled-components";
3865
+ var OuterWrapper = styled10.div`
3311
3866
  display: flex;
3312
3867
  flex-direction: column;
3313
3868
  flex: 1;
@@ -3317,19 +3872,19 @@ var OuterWrapper = styled12.div`
3317
3872
  min-width: 0;
3318
3873
  overflow: hidden;
3319
3874
  `;
3320
- var Header2 = styled12.header`
3875
+ var Header2 = styled10.header`
3321
3876
  //box-shadow: 0 3px 2px 0 rgba(0, 0, 0, 0.04), 0 1px 0 0 rgba(0, 0, 0, 0.17);
3322
3877
  z-index: 200;
3323
3878
  `;
3324
- var Footer = styled12.div`
3879
+ var Footer = styled10.div`
3325
3880
  background: #fff;
3326
3881
  `;
3327
- var Main = styled12.div`
3882
+ var Main = styled10.div`
3328
3883
  display: flex;
3329
3884
  flex: 1 1 0;
3330
3885
  min-height: 0;
3331
3886
  `;
3332
- var LeftPanel2 = styled12.div`
3887
+ var LeftPanel2 = styled10.div`
3333
3888
  background: #fff;
3334
3889
  display: flex;
3335
3890
  flex-direction: column;
@@ -3337,29 +3892,29 @@ var LeftPanel2 = styled12.div`
3337
3892
  max-width: 720px;
3338
3893
  align-items: flex-end;
3339
3894
 
3340
- ${(props) => props.$motion ? css6`
3895
+ ${(props) => props.$motion ? css5`
3341
3896
  transition: max-width 400ms;
3342
3897
  ` : ""}
3343
3898
 
3344
3899
  ${(props) => {
3345
3900
  switch (props.$state) {
3346
3901
  case "entering":
3347
- return css6`
3902
+ return css5`
3348
3903
  max-width: ${props.$width};
3349
3904
  `;
3350
3905
  case "exiting":
3351
- return css6`
3906
+ return css5`
3352
3907
  max-width: 0;
3353
3908
  `;
3354
3909
  case "unmounted":
3355
3910
  case "exited":
3356
- return css6`
3911
+ return css5`
3357
3912
  max-width: 0;
3358
3913
  `;
3359
3914
  }
3360
3915
  }}
3361
3916
  `;
3362
- var CenterPanel2 = styled12.div`
3917
+ var CenterPanel2 = styled10.div`
3363
3918
  flex: 1 1 0;
3364
3919
  background: #e3e7f0;
3365
3920
  // background: #efefef;
@@ -3379,7 +3934,7 @@ var CenterPanel2 = styled12.div`
3379
3934
  min-width: 0;
3380
3935
  }
3381
3936
  `;
3382
- var RightPanel = styled12.div`
3937
+ var RightPanel = styled10.div`
3383
3938
  background: #fff;
3384
3939
  display: flex;
3385
3940
  flex-direction: column;
@@ -3391,22 +3946,22 @@ var RightPanel = styled12.div`
3391
3946
  ${(props) => {
3392
3947
  switch (props.$state) {
3393
3948
  case "entering":
3394
- return css6`
3949
+ return css5`
3395
3950
  max-width: ${props.$width};
3396
3951
  `;
3397
3952
  case "exiting":
3398
- return css6`
3953
+ return css5`
3399
3954
  max-width: 0;
3400
3955
  `;
3401
3956
  case "unmounted":
3402
3957
  case "exited":
3403
- return css6`
3958
+ return css5`
3404
3959
  max-width: 0;
3405
3960
  `;
3406
3961
  }
3407
3962
  }}
3408
3963
  `;
3409
- var PanelContainer = styled12.div`
3964
+ var PanelContainer = styled10.div`
3410
3965
  display: flex;
3411
3966
  flex: 1;
3412
3967
  height: 100%;
@@ -3417,14 +3972,14 @@ var PanelContainer = styled12.div`
3417
3972
  ${(props) => {
3418
3973
  switch (props.$menu) {
3419
3974
  case "top":
3420
- return css6`
3975
+ return css5`
3421
3976
  flex-direction: column;
3422
3977
  ${PanelMenu} {
3423
3978
  flex-direction: column;
3424
3979
  }
3425
3980
  `;
3426
3981
  case "left":
3427
- return css6`
3982
+ return css5`
3428
3983
  flex-direction: row;
3429
3984
  ${PanelMenu} {
3430
3985
  flex-direction: row;
@@ -3432,14 +3987,14 @@ var PanelContainer = styled12.div`
3432
3987
  `;
3433
3988
  default:
3434
3989
  case "bottom":
3435
- return css6`
3990
+ return css5`
3436
3991
  flex-direction: column-reverse;
3437
3992
  ${PanelMenu} {
3438
3993
  flex-direction: column;
3439
3994
  }
3440
3995
  `;
3441
3996
  case "right":
3442
- return css6`
3997
+ return css5`
3443
3998
  flex-direction: row-reverse;
3444
3999
  ${PanelMenu} {
3445
4000
  flex-direction: row;
@@ -3448,7 +4003,7 @@ var PanelContainer = styled12.div`
3448
4003
  }
3449
4004
  }}
3450
4005
  `;
3451
- var PanelSideMenu = styled12.div`
4006
+ var PanelSideMenu = styled10.div`
3452
4007
  background: #fff;
3453
4008
  border-top: 1px solid #e3e7f0;
3454
4009
  border-right: 1px solid #e3e7f0;
@@ -3459,7 +4014,7 @@ var PanelSideMenu = styled12.div`
3459
4014
  padding: 0.3em;
3460
4015
  gap: 0.3em; */
3461
4016
  `;
3462
- var PanelSideMenuItem = styled12.button`
4017
+ var PanelSideMenuItem = styled10.button`
3463
4018
  cursor: pointer;
3464
4019
  aspect-ratio: 1;
3465
4020
  width: 3em;
@@ -3487,17 +4042,17 @@ var PanelSideMenuItem = styled12.button`
3487
4042
  color: #999;
3488
4043
  }
3489
4044
  `;
3490
- var PanelMenu = styled12.div`
4045
+ var PanelMenu = styled10.div`
3491
4046
  display: flex;
3492
4047
  box-shadow:
3493
4048
  0 -3px 2px 0 rgba(0, 0, 0, 0.04),
3494
4049
  0 -1px 0 0 rgba(0, 0, 0, 0.17);
3495
4050
 
3496
- ${(props) => !props.$open && (props.$position === "top" || props.$position === "bottom") ? css6`
4051
+ ${(props) => !props.$open && (props.$position === "top" || props.$position === "bottom") ? css5`
3497
4052
  display: none;
3498
4053
  ` : ""}
3499
4054
  `;
3500
- var PanelContent = styled12.div`
4055
+ var PanelContent = styled10.div`
3501
4056
  display: flex;
3502
4057
  flex-direction: column;
3503
4058
  flex: 1;
@@ -3506,25 +4061,25 @@ var PanelContent = styled12.div`
3506
4061
  `;
3507
4062
 
3508
4063
  // src/Layout/components/HandleControls.tsx
3509
- import styled13 from "styled-components";
4064
+ import styled11 from "styled-components";
3510
4065
  import { forwardRef as forwardRef2 } from "react";
3511
4066
 
3512
4067
  // ../ui/icons/ResetIcon.tsx
3513
- import { jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
4068
+ import { jsx as jsx30, jsxs as jsxs15 } from "react/jsx-runtime";
3514
4069
  var ResetIcon = (props) => /* @__PURE__ */ jsxs15("svg", { xmlns: "http://www.w3.org/2000/svg", height: "1em", width: "1em", viewBox: "0 0 24 24", ...props, children: [
3515
- /* @__PURE__ */ jsx28("path", { d: "M0 0h24v24H0V0z", fill: "none" }),
3516
- /* @__PURE__ */ jsx28("path", { d: "M12 5V2L8 6l4 4V7c3.31 0 6 2.69 6 6 0 2.97-2.17 5.43-5 5.91v2.02c3.95-.49 7-3.85 7-7.93 0-4.42-3.58-8-8-8zM6 13c0-1.65.67-3.15 1.76-4.24L6.34 7.34A8.014 8.014 0 0 0 4 13c0 4.08 3.05 7.44 7 7.93v-2.02c-2.83-.48-5-2.94-5-5.91z" })
4070
+ /* @__PURE__ */ jsx30("path", { d: "M0 0h24v24H0V0z", fill: "none" }),
4071
+ /* @__PURE__ */ jsx30("path", { d: "M12 5V2L8 6l4 4V7c3.31 0 6 2.69 6 6 0 2.97-2.17 5.43-5 5.91v2.02c3.95-.49 7-3.85 7-7.93 0-4.42-3.58-8-8-8zM6 13c0-1.65.67-3.15 1.76-4.24L6.34 7.34A8.014 8.014 0 0 0 4 13c0 4.08 3.05 7.44 7 7.93v-2.02c-2.83-.48-5-2.94-5-5.91z" })
3517
4072
  ] });
3518
4073
 
3519
4074
  // src/Layout/components/HandleControls.tsx
3520
- import { jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
3521
- var HandleContainer = styled13.div`
4075
+ import { jsx as jsx31, jsxs as jsxs16 } from "react/jsx-runtime";
4076
+ var HandleContainer = styled11.div`
3522
4077
  position: relative;
3523
4078
  width: 1px;
3524
4079
  background: rgba(0, 0, 0, 0.2);
3525
4080
  z-index: 50;
3526
4081
  `;
3527
- var HandleControl = styled13(ButtonReset)`
4082
+ var HandleControl = styled11(ButtonReset)`
3528
4083
  transition:
3529
4084
  opacity 300ms,
3530
4085
  transform 300ms;
@@ -3537,7 +4092,7 @@ var HandleControl = styled13(ButtonReset)`
3537
4092
  outline: 2px solid salmon;
3538
4093
  }
3539
4094
  `;
3540
- var ResizeHandle = styled13(HandleControl)`
4095
+ var ResizeHandle = styled11(HandleControl)`
3541
4096
  position: relative;
3542
4097
  background: #fff;
3543
4098
  height: 40px;
@@ -3546,7 +4101,7 @@ var ResizeHandle = styled13(HandleControl)`
3546
4101
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
3547
4102
  user-select: none;
3548
4103
  `;
3549
- var IconControl = styled13(HandleControl)`
4104
+ var IconControl = styled11(HandleControl)`
3550
4105
  background: #fff;
3551
4106
  width: 30px;
3552
4107
  height: 30px;
@@ -3561,7 +4116,7 @@ var IconControl = styled13(HandleControl)`
3561
4116
  fill: #9999;
3562
4117
  }
3563
4118
  `;
3564
- var OpenControl = styled13(HandleControl)`
4119
+ var OpenControl = styled11(HandleControl)`
3565
4120
  position: relative;
3566
4121
  display: flex;
3567
4122
  opacity: 1;
@@ -3589,7 +4144,7 @@ var OpenControl = styled13(HandleControl)`
3589
4144
  font-size: 1.5em;
3590
4145
  }
3591
4146
  `;
3592
- var InnerHandleContainer = styled13.div`
4147
+ var InnerHandleContainer = styled11.div`
3593
4148
  background: rgba(0, 0, 0, 0);
3594
4149
  position: absolute;
3595
4150
  width: 21px;
@@ -3618,7 +4173,7 @@ var InnerHandleContainer = styled13.div`
3618
4173
  }
3619
4174
  }
3620
4175
  `;
3621
- var UnscaledContainer = styled13.div`
4176
+ var UnscaledContainer = styled11.div`
3622
4177
  background: rgba(0, 0, 0, 0);
3623
4178
  position: absolute;
3624
4179
  pointer-events: none;
@@ -3630,7 +4185,7 @@ var UnscaledContainer = styled13.div`
3630
4185
  `;
3631
4186
  var HandleControls = forwardRef2(function HandleControls2({ dir, open, actions, reset }, ref) {
3632
4187
  return /* @__PURE__ */ jsxs16(HandleContainer, { onClick: () => actions.open(), children: [
3633
- /* @__PURE__ */ jsx29(UnscaledContainer, { $open: open, $dir: dir, children: !open ? /* @__PURE__ */ jsx29(
4188
+ /* @__PURE__ */ jsx31(UnscaledContainer, { $open: open, $dir: dir, children: !open ? /* @__PURE__ */ jsx31(
3634
4189
  OpenControl,
3635
4190
  {
3636
4191
  $dir: dir,
@@ -3638,42 +4193,42 @@ var HandleControls = forwardRef2(function HandleControls2({ dir, open, actions,
3638
4193
  e.stopPropagation();
3639
4194
  actions.open();
3640
4195
  },
3641
- children: /* @__PURE__ */ jsx29(DownIcon, { rotate: dir === "right" ? 90 : 270 })
4196
+ children: /* @__PURE__ */ jsx31(DownIcon, { rotate: dir === "right" ? 90 : 270 })
3642
4197
  }
3643
4198
  ) : null }),
3644
4199
  /* @__PURE__ */ jsxs16(InnerHandleContainer, { ref, $open: open, $dir: dir, children: [
3645
- open ? /* @__PURE__ */ jsx29(
4200
+ open ? /* @__PURE__ */ jsx31(
3646
4201
  IconControl,
3647
4202
  {
3648
4203
  onClick: (e) => {
3649
4204
  e.stopPropagation();
3650
4205
  actions.close();
3651
4206
  },
3652
- children: /* @__PURE__ */ jsx29(CloseIcon, {})
4207
+ children: /* @__PURE__ */ jsx31(CloseIcon, {})
3653
4208
  }
3654
4209
  ) : null,
3655
- reset && open ? /* @__PURE__ */ jsx29(
4210
+ reset && open ? /* @__PURE__ */ jsx31(
3656
4211
  IconControl,
3657
4212
  {
3658
4213
  onClick: (e) => {
3659
4214
  e.stopPropagation();
3660
4215
  reset();
3661
4216
  },
3662
- children: /* @__PURE__ */ jsx29(ResetIcon, {})
4217
+ children: /* @__PURE__ */ jsx31(ResetIcon, {})
3663
4218
  }
3664
4219
  ) : null,
3665
- open ? /* @__PURE__ */ jsx29(ResizeHandle, {}) : null
4220
+ open ? /* @__PURE__ */ jsx31(ResizeHandle, {}) : null
3666
4221
  ] })
3667
4222
  ] });
3668
4223
  });
3669
4224
 
3670
4225
  // src/Layout/components/use-resize-layouts.tsx
3671
- import { useRef as useRef6, useState as useState8 } from "react";
4226
+ import { useRef as useRef6, useState as useState9 } from "react";
3672
4227
 
3673
4228
  // ../ui/madoc/use-event-handler.ts
3674
- import { useLayoutEffect } from "react";
4229
+ import { useLayoutEffect as useLayoutEffect2 } from "react";
3675
4230
  function useEventHandler(ref, name, callback, deps = []) {
3676
- useLayoutEffect(() => {
4231
+ useLayoutEffect2(() => {
3677
4232
  const current = ref.current;
3678
4233
  if (current) {
3679
4234
  current.addEventListener(name, callback);
@@ -3703,7 +4258,7 @@ function useResizeLayout(name, options = {}) {
3703
4258
  const otherDiv = useRef6(null);
3704
4259
  const resizer = useRef6(null);
3705
4260
  const newPct = useRef6(0.5);
3706
- const [isDragging, setIsDragging] = useState8(false);
4261
+ const [isDragging, setIsDragging] = useState9(false);
3707
4262
  const isEventDragging = useRef6(false);
3708
4263
  const isEventTimeout = useRef6(0);
3709
4264
  const startPos = useRef6({ x: 0, y: 0 });
@@ -3811,39 +4366,34 @@ function useResizeLayout(name, options = {}) {
3811
4366
  };
3812
4367
  }
3813
4368
 
3814
- // src/hooks/use-match-media.ts
3815
- import { useState as useState9, useLayoutEffect as useLayoutEffect2 } from "react";
3816
- function useMatchMedia(queries, defaultValues = []) {
3817
- const initialValues = defaultValues.length ? defaultValues : Array(queries.length).fill(false);
3818
- if (typeof window === "undefined")
3819
- return initialValues;
3820
- const mediaQueryLists = queries.map((q) => window.matchMedia(q));
3821
- const getValue2 = () => {
3822
- const matchedQueries = mediaQueryLists.map((mql) => mql.matches);
3823
- return matchedQueries;
3824
- };
3825
- const [value, setValue] = useState9(getValue2);
3826
- useLayoutEffect2(() => {
3827
- const handler = () => setValue(getValue2);
3828
- mediaQueryLists.forEach((mql) => mql.addListener(handler));
3829
- return () => mediaQueryLists.forEach((mql) => mql.removeListener(handler));
3830
- }, []);
3831
- return value;
3832
- }
3833
-
3834
4369
  // src/Layout/Layout.tsx
3835
- import { Modal, PanelSideMenu as PanelSideMenu2 } from "@manifest-editor/components";
3836
- import { Fragment as Fragment4, jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
4370
+ import { Fragment as Fragment4, jsx as jsx32, jsxs as jsxs17 } from "react/jsx-runtime";
3837
4371
  var Layout = memo4(function Layout2(props) {
3838
4372
  const appState = useAppState();
3839
4373
  const layout = useLayoutProvider();
3840
- const { vault: _vault } = useContext11(ReactVaultContext2);
4374
+ const { vault: _vault } = useContext14(ReactVaultContext2);
3841
4375
  const vault = _vault || void 0;
3842
- const { loading, state, leftPanels, centerPanels, rightPanels, modals = [], actions } = layout;
3843
- const leftPanel = leftPanels.find((panel) => panel.id === state.leftPanel.current);
3844
- const rightPanel = rightPanels.find((panel) => panel.id === state.rightPanel.current);
3845
- const centerPanel = centerPanels.find((panel) => panel.id === state.centerPanel.current);
3846
- const modalToRender = modals.find((panel) => panel.id === state.modal.current);
4376
+ const {
4377
+ loading,
4378
+ state,
4379
+ leftPanels,
4380
+ centerPanels,
4381
+ rightPanels,
4382
+ modals = [],
4383
+ actions
4384
+ } = layout;
4385
+ const leftPanel = leftPanels.find(
4386
+ (panel) => panel.id === state.leftPanel.current
4387
+ );
4388
+ const rightPanel = rightPanels.find(
4389
+ (panel) => panel.id === state.rightPanel.current
4390
+ );
4391
+ const centerPanel = centerPanels.find(
4392
+ (panel) => panel.id === state.centerPanel.current
4393
+ );
4394
+ const modalToRender = modals.find(
4395
+ (panel) => panel.id === state.modal.current
4396
+ );
3847
4397
  const enableMotion = true;
3848
4398
  const pinnedRightPanel = state.pinnedRightPanel.pinned ? rightPanels.find((panel) => panel.id === state.pinnedRightPanel.current) : void 0;
3849
4399
  const [mobile] = useMatchMedia(["(max-width: 1020px)"]);
@@ -3898,7 +4448,7 @@ var Layout = memo4(function Layout2(props) {
3898
4448
  if (loading) {
3899
4449
  return null;
3900
4450
  }
3901
- const renderLeftPanel = (transition) => /* @__PURE__ */ jsx30(
4451
+ const renderLeftPanel = (transition) => /* @__PURE__ */ jsx32(
3902
4452
  PanelContainer,
3903
4453
  {
3904
4454
  $menu: props.leftPanelMenuPosition || "bottom",
@@ -3908,8 +4458,8 @@ var Layout = memo4(function Layout2(props) {
3908
4458
  width: state.leftPanel.open || transition !== "exited" ? leftPanelResizer.widthB : void 0,
3909
4459
  minWidth: leftPanel?.options?.minWidth
3910
4460
  },
3911
- children: isLoading ? /* @__PURE__ */ jsx30(PanelContent, { children: /* @__PURE__ */ jsx30(GhostBlocks, {}) }) : /* @__PURE__ */ jsxs17(Fragment4, { children: [
3912
- props.leftPanelMenu ? /* @__PURE__ */ jsx30(
4461
+ children: isLoading ? /* @__PURE__ */ jsx32(PanelContent, { children: /* @__PURE__ */ jsx32(GhostBlocks, {}) }) : /* @__PURE__ */ jsxs17(Fragment4, { children: [
4462
+ props.leftPanelMenu ? /* @__PURE__ */ jsx32(
3913
4463
  PanelMenu,
3914
4464
  {
3915
4465
  $open: state.leftPanel.open && transition !== "exited",
@@ -3917,7 +4467,7 @@ var Layout = memo4(function Layout2(props) {
3917
4467
  children: props.leftPanelMenu
3918
4468
  }
3919
4469
  ) : null,
3920
- /* @__PURE__ */ jsx30(PanelContent, { children: state.leftPanel.open || transition !== "exited" ? /* @__PURE__ */ jsx30(Fragment4, { children: leftPanel ? /* @__PURE__ */ jsx30(
4470
+ /* @__PURE__ */ jsx32(PanelContent, { children: state.leftPanel.open || transition !== "exited" ? /* @__PURE__ */ jsx32(Fragment4, { children: leftPanel ? /* @__PURE__ */ jsx32(
3921
4471
  ModularPanel,
3922
4472
  {
3923
4473
  isLeft: true,
@@ -3935,7 +4485,7 @@ var Layout = memo4(function Layout2(props) {
3935
4485
  if (!modalToRender || state.modal.open === false) {
3936
4486
  return null;
3937
4487
  }
3938
- return /* @__PURE__ */ jsx30(Modal, { title: modalToRender.label, onClose: () => actions.modal.close(), children: renderHelper(
4488
+ return /* @__PURE__ */ jsx32(Modal, { title: modalToRender.label, onClose: () => actions.modal.close(), children: renderHelper(
3939
4489
  modalToRender.render(
3940
4490
  state.modal.state || modalToRender.defaultState || {},
3941
4491
  { ...layout, current: actions.modal, vault },
@@ -3944,8 +4494,26 @@ var Layout = memo4(function Layout2(props) {
3944
4494
  ) });
3945
4495
  };
3946
4496
  const renderCenterPanel = () => /* @__PURE__ */ jsxs17(PanelContainer, { $menu: props.centerPanelMenuPosition || "top", children: [
3947
- props.centerPanelMenu ? /* @__PURE__ */ jsx30(PanelMenu, { $open: state.centerPanel.open, $position: props.centerPanelMenuPosition || "top", children: props.centerPanelMenu }) : null,
3948
- /* @__PURE__ */ jsx30(PanelContent, { children: isLoading ? /* @__PURE__ */ jsx30("div", { style: { display: "flex", flex: 1, justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx30(Spinner, { stroke: "rgba(0,0,0,.3)", fontSize: "2em" }) }) : state.centerPanel.open ? centerPanel ? renderHelper(
4497
+ props.centerPanelMenu ? /* @__PURE__ */ jsx32(
4498
+ PanelMenu,
4499
+ {
4500
+ $open: state.centerPanel.open,
4501
+ $position: props.centerPanelMenuPosition || "top",
4502
+ children: props.centerPanelMenu
4503
+ }
4504
+ ) : null,
4505
+ /* @__PURE__ */ jsx32(PanelContent, { children: isLoading ? /* @__PURE__ */ jsx32(
4506
+ "div",
4507
+ {
4508
+ style: {
4509
+ display: "flex",
4510
+ flex: 1,
4511
+ justifyContent: "center",
4512
+ alignItems: "center"
4513
+ },
4514
+ children: /* @__PURE__ */ jsx32(Spinner, { stroke: "rgba(0,0,0,.3)", fontSize: "2em" })
4515
+ }
4516
+ ) : state.centerPanel.open ? centerPanel ? renderHelper(
3949
4517
  centerPanel.render(
3950
4518
  state.centerPanel.state || centerPanel.defaultState || {},
3951
4519
  { ...layout, current: actions.centerPanel, vault },
@@ -3953,7 +4521,7 @@ var Layout = memo4(function Layout2(props) {
3953
4521
  )
3954
4522
  ) : null : null })
3955
4523
  ] });
3956
- const renderRightPanel = (transition) => /* @__PURE__ */ jsx30(
4524
+ const renderRightPanel = (transition) => /* @__PURE__ */ jsx32(
3957
4525
  PanelContainer,
3958
4526
  {
3959
4527
  $menu: props.rightPanelMenuPosition || "bottom",
@@ -3963,10 +4531,17 @@ var Layout = memo4(function Layout2(props) {
3963
4531
  width: state.rightPanel.open || transition !== "exited" ? rightPanelResizer.widthB : void 0,
3964
4532
  minWidth: rightPanel?.options?.minWidth
3965
4533
  },
3966
- children: isLoading ? /* @__PURE__ */ jsx30(PanelContent, { children: /* @__PURE__ */ jsx30(GhostBlocks, {}) }) : /* @__PURE__ */ jsxs17(Fragment4, { children: [
3967
- props.rightPanelMenu ? /* @__PURE__ */ jsx30(PanelMenu, { $open: state.rightPanel.open, $position: props.rightPanelMenuPosition || "bottom", children: props.rightPanelMenu }) : null,
3968
- /* @__PURE__ */ jsx30(PanelContent, { children: state.rightPanel.open || transition !== "exited" ? /* @__PURE__ */ jsxs17(Fragment4, { children: [
3969
- showRightPanel ? /* @__PURE__ */ jsx30(
4534
+ children: isLoading ? /* @__PURE__ */ jsx32(PanelContent, { children: /* @__PURE__ */ jsx32(GhostBlocks, {}) }) : /* @__PURE__ */ jsxs17(Fragment4, { children: [
4535
+ props.rightPanelMenu ? /* @__PURE__ */ jsx32(
4536
+ PanelMenu,
4537
+ {
4538
+ $open: state.rightPanel.open,
4539
+ $position: props.rightPanelMenuPosition || "bottom",
4540
+ children: props.rightPanelMenu
4541
+ }
4542
+ ) : null,
4543
+ /* @__PURE__ */ jsx32(PanelContent, { children: state.rightPanel.open || transition !== "exited" ? /* @__PURE__ */ jsxs17(Fragment4, { children: [
4544
+ showRightPanel ? /* @__PURE__ */ jsx32(
3970
4545
  ModularPanel,
3971
4546
  {
3972
4547
  panel: rightPanel,
@@ -3976,7 +4551,7 @@ var Layout = memo4(function Layout2(props) {
3976
4551
  available: rightPanels
3977
4552
  }
3978
4553
  ) : null,
3979
- pinnedRightPanel ? /* @__PURE__ */ jsx30(
4554
+ pinnedRightPanel ? /* @__PURE__ */ jsx32(
3980
4555
  ModularPanel,
3981
4556
  {
3982
4557
  panel: pinnedRightPanel,
@@ -3993,21 +4568,21 @@ var Layout = memo4(function Layout2(props) {
3993
4568
  return /* @__PURE__ */ jsxs17(OuterWrapper, { children: [
3994
4569
  props.hideHeader ? null : /* @__PURE__ */ jsxs17(Header2, { children: [
3995
4570
  props.header || null,
3996
- props.menu ? /* @__PURE__ */ jsx30("menu", { children: props.menu }) : null
4571
+ props.menu ? /* @__PURE__ */ jsx32("menu", { children: props.menu }) : null
3997
4572
  ] }),
3998
- /* @__PURE__ */ jsx30(Main, { children: /* @__PURE__ */ jsxs17(Container2, { children: [
3999
- /* @__PURE__ */ jsx30(CenterPanel, { children: renderCenterPanel() }),
4573
+ /* @__PURE__ */ jsx32(Main, { children: /* @__PURE__ */ jsxs17(Container2, { children: [
4574
+ /* @__PURE__ */ jsx32(CenterPanel, { children: renderCenterPanel() }),
4000
4575
  /* @__PURE__ */ jsxs17(MobileBar, { children: [
4001
- leftPanels.length > 0 ? /* @__PURE__ */ jsx30(LeftBarButton, { onClick: actions.leftPanel.toggle, children: leftPanel?.label }) : null,
4002
- rightPanels.length > 0 ? /* @__PURE__ */ jsx30(DrawerContainer, { children: /* @__PURE__ */ jsxs17(DrawerButton, { onClick: actions.rightPanel.toggle, children: [
4003
- /* @__PURE__ */ jsx30(DownIcon, { rotate: 180 }),
4576
+ leftPanels.length > 0 ? /* @__PURE__ */ jsx32(LeftBarButton, { onClick: actions.leftPanel.toggle, children: leftPanel?.label }) : null,
4577
+ rightPanels.length > 0 ? /* @__PURE__ */ jsx32(DrawerContainer, { children: /* @__PURE__ */ jsxs17(DrawerButton, { onClick: actions.rightPanel.toggle, children: [
4578
+ /* @__PURE__ */ jsx32(DownIcon, { rotate: 180 }),
4004
4579
  rightPanel?.label
4005
4580
  ] }) }) : null,
4006
- /* @__PURE__ */ jsx30(PreviewBarButton, { children: "Preview" })
4581
+ /* @__PURE__ */ jsx32(PreviewBarButton, { children: "Preview" })
4007
4582
  ] }),
4008
- rightPanels.length > 0 ? /* @__PURE__ */ jsx30(DrawerBody, { $open: state.rightPanel.open, children: renderRightPanel() }) : null,
4009
- leftPanels.length > 0 ? /* @__PURE__ */ jsx30(LeftPanel, { $open: state.leftPanel.open, children: renderLeftPanel() }) : null,
4010
- leftPanels.length > 0 || rightPanels.length > 0 ? /* @__PURE__ */ jsx30(
4583
+ rightPanels.length > 0 ? /* @__PURE__ */ jsx32(DrawerBody, { $open: state.rightPanel.open, children: renderRightPanel() }) : null,
4584
+ leftPanels.length > 0 ? /* @__PURE__ */ jsx32(LeftPanel, { $open: state.leftPanel.open, children: renderLeftPanel() }) : null,
4585
+ leftPanels.length > 0 || rightPanels.length > 0 ? /* @__PURE__ */ jsx32(
4011
4586
  Lightbox,
4012
4587
  {
4013
4588
  $open: state.leftPanel.open || state.rightPanel.open,
@@ -4023,7 +4598,7 @@ var Layout = memo4(function Layout2(props) {
4023
4598
  return /* @__PURE__ */ jsxs17(OuterWrapper, { className: `manifest-editor ${props.className}`, children: [
4024
4599
  props.hideHeader ? null : /* @__PURE__ */ jsxs17(Header2, { children: [
4025
4600
  props.header || null,
4026
- props.menu ? /* @__PURE__ */ jsx30("menu", { children: props.menu }) : null
4601
+ props.menu ? /* @__PURE__ */ jsx32("menu", { children: props.menu }) : null
4027
4602
  ] }),
4028
4603
  /* @__PURE__ */ jsxs17(
4029
4604
  Main,
@@ -4033,7 +4608,7 @@ var Layout = memo4(function Layout2(props) {
4033
4608
  rightPanelResizer.refs.container.current = div;
4034
4609
  },
4035
4610
  children: [
4036
- leftPanels.length > 0 ? /* @__PURE__ */ jsx30(
4611
+ leftPanels.length > 0 ? /* @__PURE__ */ jsx32(
4037
4612
  PanelSideMenu2,
4038
4613
  {
4039
4614
  current: state.leftPanel.current,
@@ -4053,44 +4628,76 @@ var Layout = memo4(function Layout2(props) {
4053
4628
  open: state.leftPanel.open
4054
4629
  }
4055
4630
  ) : null,
4056
- leftPanels.length > 0 ? /* @__PURE__ */ jsx30(Transition, { in: state.leftPanel.open, timeout: enableMotion ? 400 : 0, unmountOnExit: false, children: (transition) => /* @__PURE__ */ jsxs17(Fragment4, { children: [
4057
- /* @__PURE__ */ jsx30(LeftPanel2, { $width: leftPanelResizer.widthB, $state: transition, $motion: enableMotion, children: renderLeftPanel(transition) }),
4058
- /* @__PURE__ */ jsx30(
4059
- HandleControls,
4060
- {
4061
- ref: leftPanelResizer.refs.resizer,
4062
- reset: resetLeftPanel,
4063
- dir: "left",
4064
- transition,
4065
- open: state.leftPanel.open || transition !== "exited",
4066
- actions: actions.leftPanel
4067
- }
4068
- )
4069
- ] }) }) : null,
4070
- /* @__PURE__ */ jsx30(CenterPanel2, { children: renderCenterPanel() }),
4071
- rightPanels.length > 0 ? /* @__PURE__ */ jsx30(Transition, { in: state.rightPanel.open, timeout: enableMotion ? 400 : 0, unmountOnExit: false, children: (transition) => /* @__PURE__ */ jsxs17(Fragment4, { children: [
4072
- /* @__PURE__ */ jsx30(
4073
- HandleControls,
4074
- {
4075
- ref: rightPanelResizer.refs.resizer,
4076
- dir: "right",
4077
- reset: resetRightPanel,
4078
- open: state.rightPanel.open,
4079
- actions: actions.rightPanel
4080
- }
4081
- ),
4082
- /* @__PURE__ */ jsx30(RightPanel, { $width: rightPanelResizer.widthB, $state: transition, $motion: enableMotion, children: renderRightPanel(transition) })
4083
- ] }) }) : null
4631
+ leftPanels.length > 0 ? /* @__PURE__ */ jsx32(
4632
+ Transition,
4633
+ {
4634
+ in: state.leftPanel.open,
4635
+ timeout: enableMotion ? 400 : 0,
4636
+ unmountOnExit: false,
4637
+ children: (transition) => /* @__PURE__ */ jsxs17(Fragment4, { children: [
4638
+ /* @__PURE__ */ jsx32(
4639
+ LeftPanel2,
4640
+ {
4641
+ $width: leftPanelResizer.widthB,
4642
+ $state: transition,
4643
+ $motion: enableMotion,
4644
+ children: renderLeftPanel(transition)
4645
+ }
4646
+ ),
4647
+ /* @__PURE__ */ jsx32(
4648
+ HandleControls,
4649
+ {
4650
+ ref: leftPanelResizer.refs.resizer,
4651
+ reset: resetLeftPanel,
4652
+ dir: "left",
4653
+ transition,
4654
+ open: state.leftPanel.open || transition !== "exited",
4655
+ actions: actions.leftPanel
4656
+ }
4657
+ )
4658
+ ] })
4659
+ }
4660
+ ) : null,
4661
+ /* @__PURE__ */ jsx32(CenterPanel2, { children: renderCenterPanel() }),
4662
+ rightPanels.length > 0 ? /* @__PURE__ */ jsx32(
4663
+ Transition,
4664
+ {
4665
+ in: state.rightPanel.open,
4666
+ timeout: enableMotion ? 400 : 0,
4667
+ unmountOnExit: false,
4668
+ children: (transition) => /* @__PURE__ */ jsxs17(Fragment4, { children: [
4669
+ /* @__PURE__ */ jsx32(
4670
+ HandleControls,
4671
+ {
4672
+ ref: rightPanelResizer.refs.resizer,
4673
+ dir: "right",
4674
+ reset: resetRightPanel,
4675
+ open: state.rightPanel.open,
4676
+ actions: actions.rightPanel
4677
+ }
4678
+ ),
4679
+ /* @__PURE__ */ jsx32(
4680
+ RightPanel,
4681
+ {
4682
+ $width: rightPanelResizer.widthB,
4683
+ $state: transition,
4684
+ $motion: enableMotion,
4685
+ children: renderRightPanel(transition)
4686
+ }
4687
+ )
4688
+ ] })
4689
+ }
4690
+ ) : null
4084
4691
  ]
4085
4692
  }
4086
4693
  ),
4087
- /* @__PURE__ */ jsx30(Footer, { children: props.footer || null }),
4088
- /* @__PURE__ */ jsx30(Fragment4, { children: renderModal() })
4694
+ /* @__PURE__ */ jsx32(Footer, { children: props.footer || null }),
4695
+ /* @__PURE__ */ jsx32(Fragment4, { children: renderModal() })
4089
4696
  ] });
4090
4697
  });
4091
4698
 
4092
4699
  // src/Layout/Layout.hooks.ts
4093
- import { useMemo as useMemo17 } from "react";
4700
+ import { useMemo as useMemo18 } from "react";
4094
4701
  function usePanelActions(panel, dispatch) {
4095
4702
  function popStack() {
4096
4703
  dispatch({ type: "popStack", panel, payload: void 0 });
@@ -4125,7 +4732,7 @@ function usePanelActions(panel, dispatch) {
4125
4732
  function unpin() {
4126
4733
  dispatch({ type: "unpin", panel, payload: void 0 });
4127
4734
  }
4128
- return useMemo17(
4735
+ return useMemo18(
4129
4736
  () => ({
4130
4737
  popStack,
4131
4738
  change,
@@ -4291,14 +4898,14 @@ function getDefaultLayoutState() {
4291
4898
  }
4292
4899
 
4293
4900
  // src/ResourceEditingContext/ResourceEditingContext.tsx
4294
- import { createContext as createContext11, useContext as useContext12, useMemo as useMemo18 } from "react";
4901
+ import { createContext as createContext13, useContext as useContext15, useMemo as useMemo19 } from "react";
4295
4902
  import { useVault as useVault8, useVaultSelector } from "react-iiif-vault";
4296
- import { jsx as jsx31 } from "react/jsx-runtime";
4297
- var ResourceEditingReactContext = createContext11({
4903
+ import { jsx as jsx33 } from "react/jsx-runtime";
4904
+ var ResourceEditingReactContext = createContext13({
4298
4905
  resource: null
4299
4906
  });
4300
4907
  function useEditingContext() {
4301
- return useContext12(ResourceEditingReactContext);
4908
+ return useContext15(ResourceEditingReactContext);
4302
4909
  }
4303
4910
  function useResource() {
4304
4911
  const vault = useVault8();
@@ -4319,10 +4926,10 @@ function ResourceEditingProvider({
4319
4926
  children
4320
4927
  }) {
4321
4928
  const { id, type } = resource || {};
4322
- return /* @__PURE__ */ jsx31(
4929
+ return /* @__PURE__ */ jsx33(
4323
4930
  ResourceEditingReactContext.Provider,
4324
4931
  {
4325
- value: useMemo18(
4932
+ value: useMemo19(
4326
4933
  () => ({
4327
4934
  // Current resource.
4328
4935
  resource: id && type ? { id, type } : null
@@ -4334,9 +4941,12 @@ function ResourceEditingProvider({
4334
4941
  );
4335
4942
  }
4336
4943
 
4944
+ // src/ShellContext/ShellContext.tsx
4945
+ import { ImageServiceLoader } from "@atlas-viewer/iiif-image-api";
4946
+
4337
4947
  // ../ui/atoms/ErrorBoundary.tsx
4338
4948
  import { Component } from "react";
4339
- import { jsx as jsx32 } from "react/jsx-runtime";
4949
+ import { jsx as jsx34 } from "react/jsx-runtime";
4340
4950
  var ErrorBoundary2 = class extends Component {
4341
4951
  constructor() {
4342
4952
  super(...arguments);
@@ -4353,19 +4963,21 @@ var ErrorBoundary2 = class extends Component {
4353
4963
  }
4354
4964
  render() {
4355
4965
  if (this.state.hasError) {
4356
- return /* @__PURE__ */ jsx32("h1", { children: "Sorry.. there was an error" });
4966
+ return /* @__PURE__ */ jsx34("h1", { children: "Sorry.. there was an error" });
4357
4967
  }
4358
4968
  return this.props.children;
4359
4969
  }
4360
4970
  };
4361
4971
 
4362
4972
  // src/ShellContext/ShellContext.tsx
4973
+ import { useMemo as useMemo21 } from "react";
4974
+ import { ImageServiceLoaderContext } from "react-iiif-vault";
4363
4975
  import { ThemeProvider } from "styled-components";
4364
4976
 
4365
4977
  // src/Layout/Layout.context-internal.tsx
4366
4978
  import { isSpecificResource } from "@iiif/parser";
4367
- import { memo as memo5, useMemo as useMemo19, useReducer as useReducer3 } from "react";
4368
- import { jsx as jsx33 } from "react/jsx-runtime";
4979
+ import { memo as memo5, useMemo as useMemo20, useReducer as useReducer3 } from "react";
4980
+ import { jsx as jsx35 } from "react/jsx-runtime";
4369
4981
  function parse(args, _state) {
4370
4982
  if (typeof args === "string") {
4371
4983
  return { id: args, state: _state };
@@ -4375,12 +4987,19 @@ function parse(args, _state) {
4375
4987
  var LayoutProvider = memo5(function LayoutProvider2(props) {
4376
4988
  const app = useApp();
4377
4989
  const available = app.layout;
4378
- const [state, dispatch] = useReducer3(layoutReducer, void 0, getDefaultLayoutState);
4990
+ const [state, dispatch] = useReducer3(
4991
+ layoutReducer,
4992
+ void 0,
4993
+ getDefaultLayoutState
4994
+ );
4379
4995
  const actions = {
4380
4996
  centerPanel: usePanelActions("centerPanel", dispatch),
4381
4997
  leftPanel: usePanelActions("leftPanel", dispatch),
4382
4998
  rightPanel: usePanelActions("rightPanel", dispatch),
4383
- pinnedRightPanel: usePanelActions("pinnedRightPanel", dispatch),
4999
+ pinnedRightPanel: usePanelActions(
5000
+ "pinnedRightPanel",
5001
+ dispatch
5002
+ ),
4384
5003
  modal: usePanelActions("modal", dispatch),
4385
5004
  editingStack: useEditingStack()
4386
5005
  };
@@ -4403,7 +5022,10 @@ var LayoutProvider = memo5(function LayoutProvider2(props) {
4403
5022
  const { id, state: state2, stacked } = parse(args, _state);
4404
5023
  const [found, actions2, pinnable] = find(id);
4405
5024
  if (pinnable && found.options?.openPinned) {
4406
- pinnable.pin({ id, state: { ...found.defaultState || {}, ...state2 || {} } });
5025
+ pinnable.pin({
5026
+ id,
5027
+ state: { ...found.defaultState || {}, ...state2 || {} }
5028
+ });
4407
5029
  } else {
4408
5030
  actions2.open({
4409
5031
  id,
@@ -4440,7 +5062,11 @@ var LayoutProvider = memo5(function LayoutProvider2(props) {
4440
5062
  const [, actions2] = find(id);
4441
5063
  actions2.toggle();
4442
5064
  }
4443
- function edit(resource, context = {}, { reset, property, stacked } = {}) {
5065
+ function edit(resource, context = {}, {
5066
+ reset,
5067
+ property,
5068
+ stacked
5069
+ } = {}) {
4444
5070
  const toEdit = {
4445
5071
  resource: isSpecificResource(resource) ? resource : {
4446
5072
  type: "SpecificResource",
@@ -4460,7 +5086,7 @@ var LayoutProvider = memo5(function LayoutProvider2(props) {
4460
5086
  }
4461
5087
  function create2(resource) {
4462
5088
  actions.editingStack.create(resource, {});
4463
- if (available.modals && available.modals.find((e) => e.id === "@manifest-editor/creator")) {
5089
+ if (available.modals?.find((e) => e.id === "@manifest-editor/creator")) {
4464
5090
  actions.modal.open({
4465
5091
  id: "@manifest-editor/creator",
4466
5092
  stacked: true,
@@ -4485,7 +5111,13 @@ var LayoutProvider = memo5(function LayoutProvider2(props) {
4485
5111
  edit,
4486
5112
  create: create2
4487
5113
  };
4488
- return /* @__PURE__ */ jsx33(LayoutActionsReactContext.Provider, { value: useMemo19(() => ({ ...actions, ...otherActions }), [available]), children: /* @__PURE__ */ jsx33(LayoutStateReactContext.Provider, { value: state, children: props.children }) });
5114
+ return /* @__PURE__ */ jsx35(
5115
+ LayoutActionsReactContext.Provider,
5116
+ {
5117
+ value: useMemo20(() => ({ ...actions, ...otherActions }), [available]),
5118
+ children: /* @__PURE__ */ jsx35(LayoutStateReactContext.Provider, { value: state, children: props.children })
5119
+ }
5120
+ );
4489
5121
  });
4490
5122
 
4491
5123
  // src/ShellContext/default-theme.ts
@@ -4534,13 +5166,11 @@ var defaultTheme = {
4534
5166
  };
4535
5167
 
4536
5168
  // src/ShellContext/ShellContext.tsx
4537
- import { ImageServiceLoaderContext } from "react-iiif-vault";
4538
- import { ImageServiceLoader } from "@atlas-viewer/iiif-image-api";
4539
- import { jsx as jsx34 } from "react/jsx-runtime";
5169
+ import { jsx as jsx36 } from "react/jsx-runtime";
4540
5170
  var previewConfigs = [
4541
5171
  {
4542
5172
  id: "universal-viewer",
4543
- config: { url: "https://uv-v4.netlify.app/#?iiifManifestId={manifestId}" },
5173
+ config: { url: "https://universalviewer.dev/#?iiifManifestId={manifestId}" },
4544
5174
  type: "external-manifest-preview",
4545
5175
  label: "Universal viewer"
4546
5176
  },
@@ -4581,17 +5211,32 @@ function ShellProvider({
4581
5211
  resource,
4582
5212
  editing
4583
5213
  }) {
4584
- return /* @__PURE__ */ jsx34(ErrorBoundary2, { children: /* @__PURE__ */ jsx34(ImageServiceLoaderContext.Provider, { value: imageServiceLoader, children: /* @__PURE__ */ jsx34(AppResourceProvider, { resource, children: /* @__PURE__ */ jsx34(PreviewVaultContext, { children: /* @__PURE__ */ jsx34(ThemeProvider, { theme: theme || defaultTheme, children: /* @__PURE__ */ jsx34(ConfigProvider, { config, saveConfig, children: /* @__PURE__ */ jsx34(EditingStack, { children: /* @__PURE__ */ jsx34(LayoutProvider, { children: /* @__PURE__ */ jsx34(PreviewProvider, { previews: previews || [], configs: config?.previews || previewConfigs, children }) }) }) }) }) }) }) }) });
5214
+ const existingConfig = useConfig();
5215
+ const mergedConfig = useMemo21(() => {
5216
+ return {
5217
+ ...existingConfig,
5218
+ ...config,
5219
+ previews: config?.previews || existingConfig.previews || previewConfigs
5220
+ };
5221
+ }, [existingConfig, config]);
5222
+ return /* @__PURE__ */ jsx36(ErrorBoundary2, { children: /* @__PURE__ */ jsx36(ImageServiceLoaderContext.Provider, { value: imageServiceLoader, children: /* @__PURE__ */ jsx36(AppResourceProvider, { resource, children: /* @__PURE__ */ jsx36(PreviewVaultContext, { children: /* @__PURE__ */ jsx36(ThemeProvider, { theme: theme || defaultTheme, children: /* @__PURE__ */ jsx36(ConfigProvider, { config: mergedConfig, saveConfig, children: /* @__PURE__ */ jsx36(EditingStack, { children: /* @__PURE__ */ jsx36(LayoutProvider, { children: /* @__PURE__ */ jsx36(
5223
+ PreviewProvider,
5224
+ {
5225
+ previews: previews || [],
5226
+ configs: mergedConfig.previews,
5227
+ children: /* @__PURE__ */ jsx36(AtlasStoreProvider, { children })
5228
+ }
5229
+ ) }) }) }) }) }) }) }) });
4585
5230
  }
4586
5231
 
4587
5232
  // src/TaskBridge/TaskBridge.tsx
4588
- import mitt2 from "mitt";
4589
- import { createContext as createContext12, useCallback as useCallback6, useContext as useContext13, useEffect as useEffect12, useMemo as useMemo20, useReducer as useReducer4 } from "react";
4590
- import { jsx as jsx35 } from "react/jsx-runtime";
5233
+ import mitt3 from "mitt";
5234
+ import { createContext as createContext14, useCallback as useCallback6, useContext as useContext16, useEffect as useEffect13, useMemo as useMemo22, useReducer as useReducer4 } from "react";
5235
+ import { jsx as jsx37 } from "react/jsx-runtime";
4591
5236
  var tempGlobalState = {};
4592
- var DispatchReactContext = createContext12("global");
5237
+ var DispatchReactContext = createContext14("global");
4593
5238
  function useCurrentDispatchId() {
4594
- return useContext13(DispatchReactContext);
5239
+ return useContext16(DispatchReactContext);
4595
5240
  }
4596
5241
  function createDeferred() {
4597
5242
  let res = void 0;
@@ -4605,14 +5250,14 @@ function createDeferred() {
4605
5250
  function useTask(name) {
4606
5251
  const id = useCurrentDispatchId();
4607
5252
  const [, invalidate] = useReducer4((r) => r + 1, 0);
4608
- const task = useMemo20(() => {
5253
+ const task = useMemo22(() => {
4609
5254
  if (!tempGlobalState[id]) {
4610
5255
  tempGlobalState[id] = {};
4611
5256
  }
4612
5257
  if (!tempGlobalState[id][name]) {
4613
5258
  tempGlobalState[id][name] = {
4614
5259
  name,
4615
- emitter: mitt2(),
5260
+ emitter: mitt3(),
4616
5261
  status: "idle",
4617
5262
  promise: Promise.resolve(),
4618
5263
  abort: new AbortController(),
@@ -4630,7 +5275,7 @@ function useTask(name) {
4630
5275
  }
4631
5276
  function useTaskEvent(task, name, _cb) {
4632
5277
  const cb = useCallback6(() => _cb(task), [_cb]);
4633
- useEffect12(() => {
5278
+ useEffect13(() => {
4634
5279
  const em = task.emitter;
4635
5280
  em.on(name, cb);
4636
5281
  return () => em.off(name, cb);
@@ -4679,12 +5324,12 @@ function useTaskRunner(name, onRun) {
4679
5324
  return [completeTask, taskDetails, rejectTask];
4680
5325
  }
4681
5326
  function TaskBridge({ children }) {
4682
- return /* @__PURE__ */ jsx35(DispatchReactContext.Provider, { value: useMemo20(() => `id-${Date.now()}`, []), children });
5327
+ return /* @__PURE__ */ jsx37(DispatchReactContext.Provider, { value: useMemo22(() => `id-${Date.now()}`, []), children });
4683
5328
  }
4684
5329
 
4685
5330
  // src/Universal/UniversalCopyPaste.tsx
4686
- import { useCallback as useCallback7, useMemo as useMemo21 } from "react";
4687
- import { jsx as jsx36 } from "react/jsx-runtime";
5331
+ import { useCallback as useCallback7, useMemo as useMemo23 } from "react";
5332
+ import { jsx as jsx38 } from "react/jsx-runtime";
4688
5333
  function analyse(t) {
4689
5334
  return false;
4690
5335
  }
@@ -4709,7 +5354,7 @@ function UniversalCopyTarget({
4709
5354
  const onPasteReference = _onPasteReference || onReference;
4710
5355
  const onPasteLink = _onPasteLink || onLink;
4711
5356
  const onPasteAnalysis = _onPasteAnalysis || onAnalysis;
4712
- const reference = useMemo21(() => {
5357
+ const reference = useMemo23(() => {
4713
5358
  return _ref;
4714
5359
  }, [_ref?.id, _ref?.type]);
4715
5360
  const onCopy = useCallback7(
@@ -4830,7 +5475,7 @@ function UniversalCopyTarget({
4830
5475
  e.dataTransfer.dropEffect = "copy";
4831
5476
  }
4832
5477
  }, []);
4833
- return /* @__PURE__ */ jsx36(
5478
+ return /* @__PURE__ */ jsx38(
4834
5479
  Component2,
4835
5480
  {
4836
5481
  onCopy,
@@ -5030,11 +5675,11 @@ async function getImageDimensions(url) {
5030
5675
  }
5031
5676
 
5032
5677
  // src/hooks/use-save-vault.ts
5033
- import { useEffect as useEffect13 } from "react";
5678
+ import { useEffect as useEffect14 } from "react";
5034
5679
  import { useDebounce } from "tiny-use-debounce";
5035
5680
  function useSaveVault(vault, saveChanges, saveInterval, enabled = true) {
5036
5681
  const debounceSaveChanges = useDebounce(saveChanges, saveInterval);
5037
- useEffect13(() => {
5682
+ useEffect14(() => {
5038
5683
  if (typeof window === "undefined") {
5039
5684
  return () => void 0;
5040
5685
  }
@@ -5044,24 +5689,156 @@ function useSaveVault(vault, saveChanges, saveInterval, enabled = true) {
5044
5689
  window.removeEventListener("beforeunload", saveChanges);
5045
5690
  };
5046
5691
  }, [saveChanges]);
5047
- useEffect13(() => {
5692
+ useEffect14(() => {
5048
5693
  if (vault && enabled) {
5049
5694
  return vault.subscribe(debounceSaveChanges, true);
5050
5695
  }
5051
5696
  }, [debounceSaveChanges, vault, enabled]);
5052
5697
  }
5698
+
5699
+ // src/hooks/use-svg-tools.tsx
5700
+ import { useMemo as useMemo24 } from "react";
5701
+ import { useStore } from "zustand";
5702
+ function useSvgTools() {
5703
+ const store = useAtlasStore();
5704
+ const switchTool = useStore(store, (s) => s.switchTool);
5705
+ const state = useStore(store, (s) => s.polygons.state.slowState);
5706
+ return useMemo24(
5707
+ () => ({
5708
+ // Draw tool.
5709
+ draw: {
5710
+ active: !state.lineMode && !state.selectedStamp && state.drawMode,
5711
+ enable: switchTool.draw
5712
+ },
5713
+ // Polygon.
5714
+ polygon: {
5715
+ active: !state.lineMode && !state.selectedStamp && !state.drawMode,
5716
+ enable: switchTool.polygon
5717
+ },
5718
+ // Line
5719
+ line: {
5720
+ active: state.lineMode && !state.lineBoxMode,
5721
+ enable: switchTool.line
5722
+ },
5723
+ // Line box.
5724
+ lineBox: {
5725
+ active: state.lineBoxMode,
5726
+ enable: switchTool.lineBox
5727
+ },
5728
+ // Square.
5729
+ square: {
5730
+ active: state.selectedStamp?.id === "square",
5731
+ enable: switchTool.square
5732
+ },
5733
+ // Triangle.
5734
+ triangle: {
5735
+ active: state.selectedStamp?.id === "triangle",
5736
+ enable: switchTool.triangle
5737
+ },
5738
+ // Hexagon.
5739
+ hexagon: {
5740
+ active: state.selectedStamp?.id === "hexagon",
5741
+ enable: switchTool.hexagon
5742
+ },
5743
+ // Circle
5744
+ circle: {
5745
+ active: state.selectedStamp?.id === "circle40",
5746
+ enable: switchTool.circle
5747
+ },
5748
+ // Delete
5749
+ remove: {
5750
+ active: state.showBoundingBox,
5751
+ enable: switchTool.remove
5752
+ }
5753
+ }),
5754
+ [state, switchTool]
5755
+ );
5756
+ }
5757
+
5758
+ // src/hooks/use-request-annotation.ts
5759
+ import { useCallback as useCallback8, useEffect as useEffect15, useState as useState10 } from "react";
5760
+ import { useStore as useStore2 } from "zustand";
5761
+ function useRequestAnnotation(opts) {
5762
+ const [id, setId] = useState10(0);
5763
+ const store = useAtlasStore();
5764
+ const { tool, getRequestId, requestAnnotation, completeRequest, cancelRequest } = useStore2(store, (s) => ({
5765
+ getRequestId: s.getRequestId,
5766
+ requestAnnotation: s.requestAnnotation,
5767
+ completeRequest: s.completeRequest,
5768
+ cancelRequest: s.cancelRequest,
5769
+ tool: s.tool
5770
+ }));
5771
+ const [isPending, setIsPending] = useState10(false);
5772
+ const [data, setData] = useState10(null);
5773
+ const [requestId, setRequestId] = useState10(null);
5774
+ const busy = tool.enabled && tool.requestId !== requestId;
5775
+ const mutateAsync = useCallback8(
5776
+ async (request, options) => {
5777
+ if (requestId) {
5778
+ setIsPending(true);
5779
+ const response = await requestAnnotation(request, {
5780
+ ...options,
5781
+ requestId
5782
+ });
5783
+ if (response) {
5784
+ opts?.onSuccess?.(response);
5785
+ setId((i) => i + 1);
5786
+ setIsPending(false);
5787
+ setData(response);
5788
+ return response;
5789
+ }
5790
+ const resp = {
5791
+ id: requestId,
5792
+ cancelled: true,
5793
+ ...requestToAnnotationResponse(request)
5794
+ };
5795
+ opts?.onSuccess?.(resp);
5796
+ setData(resp);
5797
+ setId((i) => i + 1);
5798
+ setIsPending(false);
5799
+ return resp;
5800
+ }
5801
+ return null;
5802
+ },
5803
+ [opts?.onSuccess, requestAnnotation, requestId]
5804
+ );
5805
+ const reset = useCallback8(() => {
5806
+ setData(null);
5807
+ setIsPending(false);
5808
+ }, []);
5809
+ useEffect15(() => {
5810
+ const request = getRequestId();
5811
+ setRequestId(request.requestId);
5812
+ return () => {
5813
+ request.clear();
5814
+ };
5815
+ }, [id]);
5816
+ return {
5817
+ id,
5818
+ busy,
5819
+ isPending,
5820
+ requestAnnotation: mutateAsync,
5821
+ cancelRequest: () => requestId ? cancelRequest(requestId) : void 0,
5822
+ completeRequest: () => requestId ? completeRequest(requestId) : void 0,
5823
+ reset,
5824
+ data
5825
+ };
5826
+ }
5053
5827
  export {
5054
5828
  AppHeader,
5055
5829
  AppMenuProvider,
5056
5830
  AppProvider,
5057
5831
  AppResourceInstanceProvider,
5058
5832
  AppResourceProvider,
5833
+ AtlasStoreProvider,
5834
+ AtlasStoreReactContext,
5059
5835
  BaseEditor,
5060
5836
  BaseEditorBackButton,
5061
5837
  BaseEditorCloseButton,
5062
5838
  ConfigEditor,
5063
5839
  ConfigProvider,
5064
5840
  EditingStack,
5841
+ EventEmitterProvider,
5065
5842
  ExportPanel,
5066
5843
  HOMEPAGE_COLLECTION,
5067
5844
  HandleContainer,
@@ -5079,7 +5856,9 @@ export {
5079
5856
  PreviewVaultBoundary,
5080
5857
  PreviewVaultContext,
5081
5858
  PrimeAppReactContext,
5859
+ ReactEmitterContext,
5082
5860
  ResourceEditingProvider,
5861
+ ResourceEditingReactContext,
5083
5862
  ShellProvider,
5084
5863
  TaskBridge,
5085
5864
  UniversalCopyTarget,
@@ -5089,10 +5868,12 @@ export {
5089
5868
  baseEditor,
5090
5869
  copyToClipboard,
5091
5870
  createActionIdentity,
5871
+ createAtlasStore,
5092
5872
  createDownload,
5093
5873
  createPreviewVault,
5094
5874
  detectMedia,
5095
5875
  editBasedOnResource,
5876
+ extendApp,
5096
5877
  getDefaultLayoutState,
5097
5878
  getDefaultPanelState,
5098
5879
  getFormat,
@@ -5101,10 +5882,11 @@ export {
5101
5882
  isPinnableState,
5102
5883
  layoutReducer,
5103
5884
  mapApp,
5104
- matchBasedOnResource,
5105
5885
  panelSizing,
5886
+ polygonToBoundingBox,
5106
5887
  randomId,
5107
5888
  renderHelper,
5889
+ requestToAnnotationResponse,
5108
5890
  useAnnotationPageEditor,
5109
5891
  useApp,
5110
5892
  useAppInstance,
@@ -5114,6 +5896,7 @@ export {
5114
5896
  useAppResourceInstance,
5115
5897
  useAppState,
5116
5898
  useApps,
5899
+ useAtlasStore,
5117
5900
  useAvailableLayouts,
5118
5901
  useCollectionEditor,
5119
5902
  useConfig,
@@ -5125,6 +5908,8 @@ export {
5125
5908
  useEditingResourceStack,
5126
5909
  useEditingStack,
5127
5910
  useEditor,
5911
+ useEmitter,
5912
+ useEvent,
5128
5913
  useGenericEditor,
5129
5914
  useHighlightedImageResource,
5130
5915
  useHoverHighlightImageResource,
@@ -5133,16 +5918,19 @@ export {
5133
5918
  useLayoutProvider,
5134
5919
  useLayoutState,
5135
5920
  useManifestEditor,
5921
+ useMatchMedia,
5136
5922
  useOptionalResource,
5137
5923
  usePanelActions,
5138
5924
  usePreviewContext,
5139
5925
  usePreviewHistory,
5140
5926
  usePreviewVault,
5141
5927
  usePreviews,
5928
+ useRequestAnnotation,
5142
5929
  useResource,
5143
5930
  useSaveConfig,
5144
5931
  useSaveVault,
5145
5932
  useSetCustomTitle,
5933
+ useSvgTools,
5146
5934
  useTask,
5147
5935
  useTaskDispatch,
5148
5936
  useTaskEvent,