@preprio/toolkit 0.5.0-rc.11 → 0.5.0-rc.12
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/README.md +7 -0
- package/dist/astro/index.cjs +31 -2
- package/dist/astro/index.js +31 -2
- package/dist/{chunk-KD3GK6TO.js → chunk-CABGJW5X.js} +30 -1
- package/dist/{chunk-URXSDJOU.js → chunk-H3AFUPYD.js} +9 -0
- package/dist/{chunk-AOHA5INA.js → chunk-HVTNUCF7.js} +1 -1
- package/dist/{chunk-IPMB32AZ.js → chunk-LWUSRWFE.js} +2 -2
- package/dist/{chunk-6423Q744.js → chunk-M7FT7XXV.js} +63 -16
- package/dist/{chunk-QSXIHRH4.js → chunk-TJ7VALNA.js} +1 -1
- package/dist/index.cjs +101 -16
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -6
- package/dist/{live-preview-DLXGXRE5.js → live-preview-SFBGATWC.js} +3 -3
- package/dist/nextjs/components.cjs +71 -15
- package/dist/nextjs/components.js +3 -3
- package/dist/nextjs/index.cjs +31 -2
- package/dist/nextjs/index.js +31 -2
- package/dist/nextjs/live-action.js +3 -3
- package/dist/nextjs/live.cjs +30 -1
- package/dist/nextjs/live.js +1 -1
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.js +1 -1
- package/dist/nuxt/{live-preview-2RCU35W5.js → live-preview-XMQQZHMZ.js} +30 -1
- package/dist/nuxt/live.cjs +30 -1
- package/dist/nuxt/live.js +1 -1
- package/dist/react/components.cjs +71 -15
- package/dist/react/components.js +71 -15
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/dist/sveltekit/{live-preview-2RCU35W5.js → live-preview-XMQQZHMZ.js} +30 -1
- package/dist/sveltekit/live.cjs +30 -1
- package/dist/sveltekit/live.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -840,6 +840,13 @@ The rest is about rendering:
|
|
|
840
840
|
- Prepr images are click-to-edit inside the editor without any markup: the
|
|
841
841
|
toolkit matches image URLs (also through image optimizers like
|
|
842
842
|
`/_next/image`) to the open item's assets.
|
|
843
|
+
- **A removed image stays until the editor picks another or saves.** The
|
|
844
|
+
page keeps rendering it, faded to 20% opacity, so the layout does not
|
|
845
|
+
shift while the editor chooses a replacement. It stays click-to-edit and
|
|
846
|
+
opens its field. A newly picked image replaces it; after a save the page
|
|
847
|
+
renders stored content, so an empty state you render for a missing image
|
|
848
|
+
shows only then. In a field with several images, a removed one keeps its
|
|
849
|
+
place when the query selects the assets' `_id`.
|
|
843
850
|
- **Set the attributes yourself only where that does not reach:**
|
|
844
851
|
- Data you fetch in the browser without those helpers: run it through
|
|
845
852
|
`annotateEditLinks(result, query)` from `@preprio/toolkit`, or mark the
|
package/dist/astro/index.cjs
CHANGED
|
@@ -31,7 +31,7 @@ __export(astro_exports, {
|
|
|
31
31
|
module.exports = __toCommonJS(astro_exports);
|
|
32
32
|
|
|
33
33
|
// src/version.ts
|
|
34
|
-
var VERSION = "0.5.0-rc.
|
|
34
|
+
var VERSION = "0.5.0-rc.12";
|
|
35
35
|
|
|
36
36
|
// src/core/features.ts
|
|
37
37
|
function isEnabled(config) {
|
|
@@ -490,8 +490,32 @@ function shapeLike(template, incoming) {
|
|
|
490
490
|
}
|
|
491
491
|
return out;
|
|
492
492
|
}
|
|
493
|
+
function isAsset(value) {
|
|
494
|
+
return isPlainObject(value) && (typeof value.url === "string" || value.__typename === "Asset");
|
|
495
|
+
}
|
|
496
|
+
function hasId(list, entry) {
|
|
497
|
+
return entry._id !== void 0 && list.some((c) => isPlainObject(c) && c._id === entry._id);
|
|
498
|
+
}
|
|
499
|
+
function isAssetValue(value) {
|
|
500
|
+
return Array.isArray(value) ? value.length > 0 && value.every(isAsset) : isAsset(value);
|
|
501
|
+
}
|
|
502
|
+
function keepRemovedAssets(current, next) {
|
|
503
|
+
const listed = /* @__PURE__ */ new Set();
|
|
504
|
+
for (const entry of next) {
|
|
505
|
+
if (isPlainObject(entry) && entry._id !== void 0) listed.add(entry._id);
|
|
506
|
+
}
|
|
507
|
+
let out = next;
|
|
508
|
+
current.forEach((entry, position) => {
|
|
509
|
+
if (!isPlainObject(entry) || entry._id === void 0) return;
|
|
510
|
+
if (listed.has(entry._id)) return;
|
|
511
|
+
if (out === next) out = [...next];
|
|
512
|
+
out.splice(Math.min(position, out.length), 0, entry);
|
|
513
|
+
});
|
|
514
|
+
return out;
|
|
515
|
+
}
|
|
493
516
|
function mergeStructured(current, incoming) {
|
|
494
517
|
if (incoming === null || Array.isArray(incoming) && !incoming.length) {
|
|
518
|
+
if (isAssetValue(current)) return current;
|
|
495
519
|
if (Array.isArray(current)) return current.length ? [] : current;
|
|
496
520
|
return null;
|
|
497
521
|
}
|
|
@@ -499,13 +523,18 @@ function mergeStructured(current, incoming) {
|
|
|
499
523
|
if (current === null || current === void 0) return incoming;
|
|
500
524
|
if (Array.isArray(current)) {
|
|
501
525
|
const template = current.find(isPlainObject);
|
|
502
|
-
|
|
526
|
+
const next = list.map((entry) => {
|
|
503
527
|
const match = current.find(
|
|
504
528
|
(c) => isPlainObject(c) && c._id !== void 0 && c._id === entry._id
|
|
505
529
|
);
|
|
506
530
|
if (isPlainObject(match)) return mergeObject(match, entry);
|
|
507
531
|
return isPlainObject(template) ? shapeLike(template, entry) : entry;
|
|
508
532
|
});
|
|
533
|
+
if (!isAssetValue(current) || list.some((entry) => !hasId(current, entry))) {
|
|
534
|
+
return next;
|
|
535
|
+
}
|
|
536
|
+
const kept = keepRemovedAssets(current, next);
|
|
537
|
+
return kept.length === current.length && kept.every((entry, i) => entry === current[i]) ? current : kept;
|
|
509
538
|
}
|
|
510
539
|
if (isPlainObject(current)) return mergeObject(current, list[0]);
|
|
511
540
|
return current;
|
package/dist/astro/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = "0.5.0-rc.
|
|
2
|
+
var VERSION = "0.5.0-rc.12";
|
|
3
3
|
|
|
4
4
|
// src/core/features.ts
|
|
5
5
|
function isEnabled(config) {
|
|
@@ -462,8 +462,32 @@ function shapeLike(template, incoming) {
|
|
|
462
462
|
}
|
|
463
463
|
return out;
|
|
464
464
|
}
|
|
465
|
+
function isAsset(value) {
|
|
466
|
+
return isPlainObject(value) && (typeof value.url === "string" || value.__typename === "Asset");
|
|
467
|
+
}
|
|
468
|
+
function hasId(list, entry) {
|
|
469
|
+
return entry._id !== void 0 && list.some((c) => isPlainObject(c) && c._id === entry._id);
|
|
470
|
+
}
|
|
471
|
+
function isAssetValue(value) {
|
|
472
|
+
return Array.isArray(value) ? value.length > 0 && value.every(isAsset) : isAsset(value);
|
|
473
|
+
}
|
|
474
|
+
function keepRemovedAssets(current, next) {
|
|
475
|
+
const listed = /* @__PURE__ */ new Set();
|
|
476
|
+
for (const entry of next) {
|
|
477
|
+
if (isPlainObject(entry) && entry._id !== void 0) listed.add(entry._id);
|
|
478
|
+
}
|
|
479
|
+
let out = next;
|
|
480
|
+
current.forEach((entry, position) => {
|
|
481
|
+
if (!isPlainObject(entry) || entry._id === void 0) return;
|
|
482
|
+
if (listed.has(entry._id)) return;
|
|
483
|
+
if (out === next) out = [...next];
|
|
484
|
+
out.splice(Math.min(position, out.length), 0, entry);
|
|
485
|
+
});
|
|
486
|
+
return out;
|
|
487
|
+
}
|
|
465
488
|
function mergeStructured(current, incoming) {
|
|
466
489
|
if (incoming === null || Array.isArray(incoming) && !incoming.length) {
|
|
490
|
+
if (isAssetValue(current)) return current;
|
|
467
491
|
if (Array.isArray(current)) return current.length ? [] : current;
|
|
468
492
|
return null;
|
|
469
493
|
}
|
|
@@ -471,13 +495,18 @@ function mergeStructured(current, incoming) {
|
|
|
471
495
|
if (current === null || current === void 0) return incoming;
|
|
472
496
|
if (Array.isArray(current)) {
|
|
473
497
|
const template = current.find(isPlainObject);
|
|
474
|
-
|
|
498
|
+
const next = list.map((entry) => {
|
|
475
499
|
const match = current.find(
|
|
476
500
|
(c) => isPlainObject(c) && c._id !== void 0 && c._id === entry._id
|
|
477
501
|
);
|
|
478
502
|
if (isPlainObject(match)) return mergeObject(match, entry);
|
|
479
503
|
return isPlainObject(template) ? shapeLike(template, entry) : entry;
|
|
480
504
|
});
|
|
505
|
+
if (!isAssetValue(current) || list.some((entry) => !hasId(current, entry))) {
|
|
506
|
+
return next;
|
|
507
|
+
}
|
|
508
|
+
const kept = keepRemovedAssets(current, next);
|
|
509
|
+
return kept.length === current.length && kept.every((entry, i) => entry === current[i]) ? current : kept;
|
|
481
510
|
}
|
|
482
511
|
if (isPlainObject(current)) return mergeObject(current, list[0]);
|
|
483
512
|
return current;
|
|
@@ -101,8 +101,32 @@ function shapeLike(template, incoming) {
|
|
|
101
101
|
}
|
|
102
102
|
return out;
|
|
103
103
|
}
|
|
104
|
+
function isAsset(value) {
|
|
105
|
+
return isPlainObject(value) && (typeof value.url === "string" || value.__typename === "Asset");
|
|
106
|
+
}
|
|
107
|
+
function hasId(list, entry) {
|
|
108
|
+
return entry._id !== void 0 && list.some((c) => isPlainObject(c) && c._id === entry._id);
|
|
109
|
+
}
|
|
110
|
+
function isAssetValue(value) {
|
|
111
|
+
return Array.isArray(value) ? value.length > 0 && value.every(isAsset) : isAsset(value);
|
|
112
|
+
}
|
|
113
|
+
function keepRemovedAssets(current, next) {
|
|
114
|
+
const listed = /* @__PURE__ */ new Set();
|
|
115
|
+
for (const entry of next) {
|
|
116
|
+
if (isPlainObject(entry) && entry._id !== void 0) listed.add(entry._id);
|
|
117
|
+
}
|
|
118
|
+
let out = next;
|
|
119
|
+
current.forEach((entry, position) => {
|
|
120
|
+
if (!isPlainObject(entry) || entry._id === void 0) return;
|
|
121
|
+
if (listed.has(entry._id)) return;
|
|
122
|
+
if (out === next) out = [...next];
|
|
123
|
+
out.splice(Math.min(position, out.length), 0, entry);
|
|
124
|
+
});
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
104
127
|
function mergeStructured(current, incoming) {
|
|
105
128
|
if (incoming === null || Array.isArray(incoming) && !incoming.length) {
|
|
129
|
+
if (isAssetValue(current)) return current;
|
|
106
130
|
if (Array.isArray(current)) return current.length ? [] : current;
|
|
107
131
|
return null;
|
|
108
132
|
}
|
|
@@ -110,13 +134,18 @@ function mergeStructured(current, incoming) {
|
|
|
110
134
|
if (current === null || current === void 0) return incoming;
|
|
111
135
|
if (Array.isArray(current)) {
|
|
112
136
|
const template = current.find(isPlainObject);
|
|
113
|
-
|
|
137
|
+
const next = list.map((entry) => {
|
|
114
138
|
const match = current.find(
|
|
115
139
|
(c) => isPlainObject(c) && c._id !== void 0 && c._id === entry._id
|
|
116
140
|
);
|
|
117
141
|
if (isPlainObject(match)) return mergeObject(match, entry);
|
|
118
142
|
return isPlainObject(template) ? shapeLike(template, entry) : entry;
|
|
119
143
|
});
|
|
144
|
+
if (!isAssetValue(current) || list.some((entry) => !hasId(current, entry))) {
|
|
145
|
+
return next;
|
|
146
|
+
}
|
|
147
|
+
const kept = keepRemovedAssets(current, next);
|
|
148
|
+
return kept.length === current.length && kept.every((entry, i) => entry === current[i]) ? current : kept;
|
|
120
149
|
}
|
|
121
150
|
if (isPlainObject(current)) return mergeObject(current, list[0]);
|
|
122
151
|
return current;
|
|
@@ -239,6 +239,7 @@ function createIframeBridge(store, options = {}) {
|
|
|
239
239
|
const onReferences = options.onReferences;
|
|
240
240
|
const onAssets = options.onAssets;
|
|
241
241
|
const onAllowNavigation = options.onAllowNavigation;
|
|
242
|
+
const onItemChanged = options.onItemChanged;
|
|
242
243
|
let parentOrigin = null;
|
|
243
244
|
const onKeyDown = (event) => {
|
|
244
245
|
const key = event.key.toLowerCase();
|
|
@@ -329,6 +330,14 @@ function createIframeBridge(store, options = {}) {
|
|
|
329
330
|
debug.warn("allowNavigation handler failed", error);
|
|
330
331
|
}
|
|
331
332
|
}
|
|
333
|
+
if (data?.event === "prepr:itemChanged") {
|
|
334
|
+
if (typeof data.itemId !== "string" || !data.itemId) return;
|
|
335
|
+
try {
|
|
336
|
+
onItemChanged?.(data.itemId);
|
|
337
|
+
} catch (error) {
|
|
338
|
+
debug.warn("itemChanged handler failed", error);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
332
341
|
};
|
|
333
342
|
return {
|
|
334
343
|
start() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isAllowedEditorOrigin
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-H3AFUPYD.js";
|
|
4
4
|
import {
|
|
5
5
|
indexSnapshot,
|
|
6
6
|
isLiveFieldChange,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
parseListEntries,
|
|
9
9
|
patchSnapshot,
|
|
10
10
|
syncListSnapshot
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-CABGJW5X.js";
|
|
12
12
|
import {
|
|
13
13
|
createScopedLogger,
|
|
14
14
|
getTrustedParentOrigin,
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
ALL_FEATURES_ENABLED,
|
|
3
3
|
VERSION,
|
|
4
4
|
resolveFeatures
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-HVTNUCF7.js";
|
|
6
6
|
import {
|
|
7
7
|
createIframeBridge,
|
|
8
8
|
isLocale,
|
|
9
9
|
t
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-H3AFUPYD.js";
|
|
11
11
|
import {
|
|
12
12
|
createScopedLogger,
|
|
13
13
|
initDebugLogger,
|
|
@@ -2193,6 +2193,7 @@ var ABSOLUTE_HTTP = /^https?:\/\//i;
|
|
|
2193
2193
|
var SOURCE_URL_ATTRIBUTES = ["src", "data-src"];
|
|
2194
2194
|
var SOURCE_SET_ATTRIBUTES = ["srcset", "data-srcset"];
|
|
2195
2195
|
var ASSET_ATTR = "data-prepr-asset";
|
|
2196
|
+
var REMOVED_ATTR = "data-prepr-removed";
|
|
2196
2197
|
var ASSET_SOURCE_ATTRIBUTES = [
|
|
2197
2198
|
...SOURCE_URL_ATTRIBUTES,
|
|
2198
2199
|
...SOURCE_SET_ATTRIBUTES
|
|
@@ -2202,7 +2203,8 @@ var TAG_ATTRIBUTES = [
|
|
|
2202
2203
|
"data-prepr-id",
|
|
2203
2204
|
"data-prepr-field",
|
|
2204
2205
|
"data-prepr-entry-id",
|
|
2205
|
-
ASSET_ATTR
|
|
2206
|
+
ASSET_ATTR,
|
|
2207
|
+
REMOVED_ATTR
|
|
2206
2208
|
];
|
|
2207
2209
|
function decodeSegment(segment) {
|
|
2208
2210
|
try {
|
|
@@ -2321,11 +2323,22 @@ function besideOtherItem(img, isCurrentItem) {
|
|
|
2321
2323
|
return false;
|
|
2322
2324
|
}
|
|
2323
2325
|
function tagAssetImages(index, itemId, keys, options = {}) {
|
|
2324
|
-
const { isCurrentItem } = options;
|
|
2326
|
+
const { isCurrentItem, removed } = options;
|
|
2327
|
+
let showsRemoved = false;
|
|
2325
2328
|
for (const img of document.getElementsByTagName("img")) {
|
|
2326
2329
|
const ours = img.hasAttribute(ASSET_ATTR);
|
|
2327
|
-
|
|
2328
|
-
|
|
2330
|
+
let match = index.size ? matchAsset(img, index, keys) : void 0;
|
|
2331
|
+
let isRemoved = false;
|
|
2332
|
+
if (!match && removed?.size) {
|
|
2333
|
+
match = matchAsset(img, removed, keys);
|
|
2334
|
+
isRemoved = match !== void 0;
|
|
2335
|
+
}
|
|
2336
|
+
if (!ours && img.hasAttribute("data-prepr-encoded")) {
|
|
2337
|
+
const mark = isRemoved && (!isCurrentItem || isCurrentItem(img));
|
|
2338
|
+
setIfChanged(img, REMOVED_ATTR, mark ? "" : null);
|
|
2339
|
+
showsRemoved || (showsRemoved = mark);
|
|
2340
|
+
continue;
|
|
2341
|
+
}
|
|
2329
2342
|
const asset = match && isCurrentItem && besideOtherItem(img, isCurrentItem) ? void 0 : match;
|
|
2330
2343
|
if (!asset) {
|
|
2331
2344
|
if (ours) untagAssetImage(img);
|
|
@@ -2336,10 +2349,14 @@ function tagAssetImages(index, itemId, keys, options = {}) {
|
|
|
2336
2349
|
setIfChanged(img, "data-prepr-id", itemId);
|
|
2337
2350
|
setIfChanged(img, "data-prepr-field", asset.field);
|
|
2338
2351
|
setIfChanged(img, "data-prepr-entry-id", asset.entryId ?? null);
|
|
2352
|
+
setIfChanged(img, REMOVED_ATTR, isRemoved ? "" : null);
|
|
2353
|
+
showsRemoved || (showsRemoved = isRemoved);
|
|
2339
2354
|
}
|
|
2355
|
+
return showsRemoved;
|
|
2340
2356
|
}
|
|
2341
2357
|
function untagAssetImages() {
|
|
2342
2358
|
document.querySelectorAll(`img[${ASSET_ATTR}]`).forEach(untagAssetImage);
|
|
2359
|
+
document.querySelectorAll(`img[${REMOVED_ATTR}]`).forEach((img) => img.removeAttribute(REMOVED_ATTR));
|
|
2343
2360
|
}
|
|
2344
2361
|
|
|
2345
2362
|
// src/core/visual-editor/navigation-guard.ts
|
|
@@ -2515,11 +2532,13 @@ var CHROME_SELECTOR = "header, footer, nav, [role=banner], [role=contentinfo], [
|
|
|
2515
2532
|
var SECTIONING_SELECTOR = "article, aside, main, nav, section";
|
|
2516
2533
|
var PLAIN_HEADER_FOOTER = "header:not([role]), footer:not([role])";
|
|
2517
2534
|
var CURSOR_STYLE_MARKER = "data-prepr-visual-editor";
|
|
2518
|
-
var
|
|
2535
|
+
var REMOVED_STYLES = `img[${REMOVED_ATTR}]{opacity:.2!important;transition:opacity .2s ease}@media (prefers-reduced-motion:reduce){img[${REMOVED_ATTR}]{transition:none}}`;
|
|
2536
|
+
var CURSOR_STYLES = `${ENCODED_SELECTOR2}{cursor:pointer}html[data-prepr-ve-suspended] ${ENCODED_SELECTOR2}{cursor:auto}${REMOVED_STYLES}`;
|
|
2519
2537
|
var SUSPENDED_ATTR = "data-prepr-ve-suspended";
|
|
2520
2538
|
var FIND_RETRY_MS = 150;
|
|
2521
2539
|
var FIND_RETRIES = 6;
|
|
2522
2540
|
var MAX_CACHED_KEYS = 2e3;
|
|
2541
|
+
var SAVED_FADE_MS = 1e4;
|
|
2523
2542
|
var LAYOUT_MUTATIONS = {
|
|
2524
2543
|
childList: true,
|
|
2525
2544
|
subtree: true,
|
|
@@ -2562,6 +2581,9 @@ function createVisualEditor(opts) {
|
|
|
2562
2581
|
let guardEnabled = false;
|
|
2563
2582
|
let assetIndex = /* @__PURE__ */ new Map();
|
|
2564
2583
|
const assetKeys = /* @__PURE__ */ new Map();
|
|
2584
|
+
const removedAssets = /* @__PURE__ */ new Map();
|
|
2585
|
+
let saved = false;
|
|
2586
|
+
let savedTimeout = null;
|
|
2565
2587
|
const guard = createNavigationGuard({
|
|
2566
2588
|
onBlocked: (href) => opts.onNavigationBlocked?.(href),
|
|
2567
2589
|
showsEditedContent: () => showsEditedContent()
|
|
@@ -2760,15 +2782,32 @@ function createVisualEditor(opts) {
|
|
|
2760
2782
|
const el = block !== void 0 ? nthListItem(found, block) ?? found : found;
|
|
2761
2783
|
select(el, found, block);
|
|
2762
2784
|
}
|
|
2785
|
+
const hasAssets = () => assetIndex.size > 0 || removedAssets.size > 0;
|
|
2763
2786
|
function tagAssets() {
|
|
2764
2787
|
if (assetKeys.size > MAX_CACHED_KEYS) assetKeys.clear();
|
|
2765
|
-
tagAssetImages(assetIndex, currentItemId, assetKeys, {
|
|
2766
|
-
isCurrentItem: (el) => isCurrentItem(el)
|
|
2788
|
+
const showsRemoved = tagAssetImages(assetIndex, currentItemId, assetKeys, {
|
|
2789
|
+
isCurrentItem: (el) => isCurrentItem(el),
|
|
2790
|
+
removed: removedAssets
|
|
2767
2791
|
});
|
|
2792
|
+
if (saved && !showsRemoved) forgetRemoved();
|
|
2793
|
+
}
|
|
2794
|
+
function forgetRemoved() {
|
|
2795
|
+
saved = false;
|
|
2796
|
+
if (savedTimeout) clearTimeout(savedTimeout);
|
|
2797
|
+
savedTimeout = null;
|
|
2798
|
+
if (!removedAssets.size) return;
|
|
2799
|
+
removedAssets.clear();
|
|
2800
|
+
if (running) tagAssets();
|
|
2801
|
+
}
|
|
2802
|
+
function itemSaved() {
|
|
2803
|
+
if (!removedAssets.size) return;
|
|
2804
|
+
saved = true;
|
|
2805
|
+
if (savedTimeout) clearTimeout(savedTimeout);
|
|
2806
|
+
savedTimeout = setTimeout(forgetRemoved, SAVED_FADE_MS);
|
|
2768
2807
|
}
|
|
2769
2808
|
const handleLayoutFrame = () => {
|
|
2770
2809
|
mutationFrame = null;
|
|
2771
|
-
if (
|
|
2810
|
+
if (hasAssets()) tagAssets();
|
|
2772
2811
|
reselect();
|
|
2773
2812
|
const hovered = overlay.getHoverTarget();
|
|
2774
2813
|
if (hovered && !hovered.isConnected) {
|
|
@@ -2780,7 +2819,7 @@ function createVisualEditor(opts) {
|
|
|
2780
2819
|
};
|
|
2781
2820
|
const handleMutations = () => {
|
|
2782
2821
|
if (mutationFrame !== null) return;
|
|
2783
|
-
if (!selection && !overlay.getHoverTarget() && !
|
|
2822
|
+
if (!selection && !overlay.getHoverTarget() && !hasAssets()) return;
|
|
2784
2823
|
mutationFrame = requestAnimationFrame(handleLayoutFrame);
|
|
2785
2824
|
};
|
|
2786
2825
|
function injectCursorStyles() {
|
|
@@ -2821,7 +2860,7 @@ function createVisualEditor(opts) {
|
|
|
2821
2860
|
});
|
|
2822
2861
|
mutationObserver = new MutationObserver(handleMutations);
|
|
2823
2862
|
mutationObserver.observe(document.body, LAYOUT_MUTATIONS);
|
|
2824
|
-
if (
|
|
2863
|
+
if (hasAssets()) tagAssets();
|
|
2825
2864
|
syncGuard();
|
|
2826
2865
|
debug7.log("visual editor started");
|
|
2827
2866
|
}
|
|
@@ -2897,18 +2936,24 @@ function createVisualEditor(opts) {
|
|
|
2897
2936
|
});
|
|
2898
2937
|
}
|
|
2899
2938
|
function setCurrentItem(itemId, referenceList, componentIds) {
|
|
2939
|
+
if (itemId !== currentItemId) forgetRemoved();
|
|
2900
2940
|
currentItemId = itemId;
|
|
2901
2941
|
if (referenceList) setReferences(referenceList, componentIds);
|
|
2902
2942
|
else if (componentIds) ownComponents = new Set(componentIds);
|
|
2903
|
-
if (running &&
|
|
2943
|
+
if (running && hasAssets()) tagAssets();
|
|
2904
2944
|
const selected = overlay.getSelectedTarget();
|
|
2905
2945
|
const owner = selected ? encodedFrom(selected) : null;
|
|
2906
2946
|
if (owner && !isCurrentItem(owner)) clearSelection();
|
|
2907
2947
|
}
|
|
2908
2948
|
function setAssets(assets) {
|
|
2909
|
-
const hadAssets =
|
|
2910
|
-
|
|
2911
|
-
|
|
2949
|
+
const hadAssets = hasAssets();
|
|
2950
|
+
const next = createAssetIndex(assets);
|
|
2951
|
+
for (const [key, asset] of assetIndex) {
|
|
2952
|
+
if (!next.has(key)) removedAssets.set(key, asset);
|
|
2953
|
+
}
|
|
2954
|
+
for (const key of next.keys()) removedAssets.delete(key);
|
|
2955
|
+
assetIndex = next;
|
|
2956
|
+
if (running && (hadAssets || hasAssets())) tagAssets();
|
|
2912
2957
|
}
|
|
2913
2958
|
function setReferences(referenceList, componentIds) {
|
|
2914
2959
|
if (componentIds) ownComponents = new Set(componentIds);
|
|
@@ -2934,6 +2979,7 @@ function createVisualEditor(opts) {
|
|
|
2934
2979
|
setCurrentItem,
|
|
2935
2980
|
setReferences,
|
|
2936
2981
|
setAssets,
|
|
2982
|
+
itemSaved,
|
|
2937
2983
|
setLocale,
|
|
2938
2984
|
focusField,
|
|
2939
2985
|
setNavigationGuard,
|
|
@@ -3091,6 +3137,7 @@ function createPreprPreview(opts = {}) {
|
|
|
3091
3137
|
},
|
|
3092
3138
|
onAssets: (assets) => visualEditor?.setAssets(assets),
|
|
3093
3139
|
onAllowNavigation: (href) => visualEditor?.allowNavigation(href),
|
|
3140
|
+
onItemChanged: () => visualEditor?.itemSaved(),
|
|
3094
3141
|
onReferences: (referencedIds, componentIds) => visualEditor?.setReferences(referencedIds, componentIds),
|
|
3095
3142
|
// The editor selecting a field scrolls the matching element into view. The
|
|
3096
3143
|
// lookup relies on the attributes the stega scan writes, so it finds
|