@jumoo/usync 17.5.1 → 17.5.2-prerelease.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/api/index.d.ts +1 -1
  2. package/dist/api/index.js +1 -1
  3. package/dist/api/sdk.gen.d.ts +2 -1
  4. package/dist/api/sdk.gen.js +7 -0
  5. package/dist/api/types.gen.d.ts +361 -0
  6. package/dist/api/types.gen.js +13 -0
  7. package/dist/components/index.d.ts +3 -0
  8. package/dist/components/index.js +3 -0
  9. package/dist/components/usync-content-preview.d.ts +27 -0
  10. package/dist/components/usync-content-preview.js +540 -0
  11. package/dist/components/usync-content-type-preview.d.ts +25 -0
  12. package/dist/components/usync-content-type-preview.js +548 -0
  13. package/dist/components/usync-data-type-preview.d.ts +21 -0
  14. package/dist/components/usync-data-type-preview.js +293 -0
  15. package/dist/components/usync-results-view.js +13 -5
  16. package/dist/dialogs/details-modal-element.d.ts +12 -1
  17. package/dist/dialogs/details-modal-element.js +139 -9
  18. package/dist/dialogs/details-modal-token.d.ts +10 -1
  19. package/dist/lang/files/da-dk.d.ts +37 -0
  20. package/dist/lang/files/da-dk.js +37 -0
  21. package/dist/lang/files/de-de.d.ts +37 -0
  22. package/dist/lang/files/de-de.js +37 -0
  23. package/dist/lang/files/en-us.d.ts +37 -0
  24. package/dist/lang/files/en-us.js +37 -0
  25. package/dist/lang/files/es-es.d.ts +37 -0
  26. package/dist/lang/files/es-es.js +37 -0
  27. package/dist/lang/files/fr-fr.d.ts +37 -0
  28. package/dist/lang/files/fr-fr.js +37 -0
  29. package/dist/lang/files/nl-nl.d.ts +37 -0
  30. package/dist/lang/files/nl-nl.js +37 -0
  31. package/dist/repository/SyncAction.respositoy.d.ts +8 -0
  32. package/dist/repository/SyncAction.respositoy.js +6 -0
  33. package/dist/repository/sources/SyncAction.source.d.ts +5 -0
  34. package/dist/repository/sources/SyncAction.source.js +5 -0
  35. package/dist/utils/preview/content-type-diff.d.ts +18 -0
  36. package/dist/utils/preview/content-type-diff.js +72 -0
  37. package/dist/utils/preview/content-type-layout.d.ts +39 -0
  38. package/dist/utils/preview/content-type-layout.js +100 -0
  39. package/package.json +1 -1
@@ -0,0 +1,540 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
8
+ if (kind === "m") throw new TypeError("Private method is not writable");
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
11
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
+ };
13
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
14
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
15
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
16
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
17
+ };
18
+ var _uSyncContentPreviewElement_instances, _uSyncContentPreviewElement_current, _uSyncContentPreviewElement_incoming, _uSyncContentPreviewElement_type, _uSyncContentPreviewElement_compositions, _uSyncContentPreviewElement_dataTypes, _uSyncContentPreviewElement_cultures, _uSyncContentPreviewElement_renderToolbar, _uSyncContentPreviewElement_renderSide, _uSyncContentPreviewElement_missingMessage, _uSyncContentPreviewElement_renderInfo, _uSyncContentPreviewElement_renderPublished, _uSyncContentPreviewElement_name, _uSyncContentPreviewElement_renderTabButton, _uSyncContentPreviewElement_renderTab, _uSyncContentPreviewElement_renderProperties, _uSyncContentPreviewElement_visibleTabs, _uSyncContentPreviewElement_tabProperties, _uSyncContentPreviewElement_datasetValue, _uSyncContentPreviewElement_value, _uSyncContentPreviewElement_valueStatus;
19
+ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
20
+ import { classMap, css, customElement, html, nothing, property, repeat, state, } from '@umbraco-cms/backoffice/external/lit';
21
+ import '@umbraco-cms/backoffice/components';
22
+ import { buildContentTypeLayout, } from '../utils/preview/content-type-layout.js';
23
+ import { deepEqual } from '../utils/diff/deep-equal.js';
24
+ /**
25
+ * Shows the current and incoming versions of a content or media item side by
26
+ * side, laid out the way the backoffice editor shows them, with every value
27
+ * rendered by its real property editor. Values that change are highlighted.
28
+ */
29
+ let uSyncContentPreviewElement = class uSyncContentPreviewElement extends UmbLitElement {
30
+ constructor() {
31
+ super(...arguments);
32
+ _uSyncContentPreviewElement_instances.add(this);
33
+ this._onlyChanges = false;
34
+ _uSyncContentPreviewElement_current.set(this, {});
35
+ _uSyncContentPreviewElement_incoming.set(this, {});
36
+ _uSyncContentPreviewElement_type.set(this, void 0);
37
+ _uSyncContentPreviewElement_compositions.set(this, new Map());
38
+ _uSyncContentPreviewElement_dataTypes.set(this, new Map());
39
+ _uSyncContentPreviewElement_cultures.set(this, []);
40
+ }
41
+ willUpdate(changed) {
42
+ if (!changed.has('preview') || !this.preview)
43
+ return;
44
+ const preview = this.preview;
45
+ const isMedia = preview.entityType === 'media';
46
+ __classPrivateFieldSet(this, _uSyncContentPreviewElement_current, {
47
+ item: (isMedia ? preview.currentMedia : preview.currentDocument) ?? undefined,
48
+ info: preview.currentInfo,
49
+ }, "f");
50
+ __classPrivateFieldSet(this, _uSyncContentPreviewElement_incoming, {
51
+ item: (isMedia ? preview.incomingMedia : preview.incomingDocument) ?? undefined,
52
+ info: preview.incomingInfo,
53
+ }, "f");
54
+ __classPrivateFieldSet(this, _uSyncContentPreviewElement_type, (isMedia ? preview.currentMediaType : preview.currentDocumentType) ?? undefined, "f");
55
+ const compositions = isMedia
56
+ ? preview.compositionMediaTypes
57
+ : preview.compositionDocumentTypes;
58
+ __classPrivateFieldSet(this, _uSyncContentPreviewElement_compositions, new Map(compositions.map((c) => [c.id, c])), "f");
59
+ __classPrivateFieldSet(this, _uSyncContentPreviewElement_dataTypes, new Map(preview.dataTypes.map((d) => [d.id, d])), "f");
60
+ __classPrivateFieldSet(this, _uSyncContentPreviewElement_cultures, [
61
+ ...new Set([__classPrivateFieldGet(this, _uSyncContentPreviewElement_current, "f").item, __classPrivateFieldGet(this, _uSyncContentPreviewElement_incoming, "f").item]
62
+ .flatMap((item) => item?.variants ?? [])
63
+ .map((v) => v.culture)
64
+ .filter((c) => !!c)),
65
+ ].sort(), "f");
66
+ this._culture = __classPrivateFieldGet(this, _uSyncContentPreviewElement_cultures, "f")[0];
67
+ this._activeTab = undefined;
68
+ }
69
+ render() {
70
+ if (!this.preview)
71
+ return nothing;
72
+ const tabs = __classPrivateFieldGet(this, _uSyncContentPreviewElement_type, "f")
73
+ ? __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_visibleTabs).call(this, buildContentTypeLayout(__classPrivateFieldGet(this, _uSyncContentPreviewElement_type, "f"), __classPrivateFieldGet(this, _uSyncContentPreviewElement_compositions, "f")))
74
+ : [];
75
+ // until a tab is picked, open on the first one with changes.
76
+ const active = tabs.find((t) => t.name === this._activeTab) ??
77
+ tabs.find((t) => __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_tabProperties).call(this, t).some((p) => __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_valueStatus).call(this, p.property))) ??
78
+ tabs[0];
79
+ return html `
80
+ <div class="sides">
81
+ ${__classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_renderToolbar).call(this)}
82
+ ${__classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_renderSide).call(this, 'current', __classPrivateFieldGet(this, _uSyncContentPreviewElement_current, "f"), tabs, active)}
83
+ ${__classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_renderSide).call(this, 'incoming', __classPrivateFieldGet(this, _uSyncContentPreviewElement_incoming, "f"), tabs, active)}
84
+ </div>
85
+ `;
86
+ }
87
+ };
88
+ _uSyncContentPreviewElement_current = new WeakMap();
89
+ _uSyncContentPreviewElement_incoming = new WeakMap();
90
+ _uSyncContentPreviewElement_type = new WeakMap();
91
+ _uSyncContentPreviewElement_compositions = new WeakMap();
92
+ _uSyncContentPreviewElement_dataTypes = new WeakMap();
93
+ _uSyncContentPreviewElement_cultures = new WeakMap();
94
+ _uSyncContentPreviewElement_instances = new WeakSet();
95
+ _uSyncContentPreviewElement_renderToolbar = function _uSyncContentPreviewElement_renderToolbar() {
96
+ if (__classPrivateFieldGet(this, _uSyncContentPreviewElement_cultures, "f").length < 2 && !(__classPrivateFieldGet(this, _uSyncContentPreviewElement_current, "f").item && __classPrivateFieldGet(this, _uSyncContentPreviewElement_incoming, "f").item))
97
+ return nothing;
98
+ return html `<div class="toolbar">
99
+ ${__classPrivateFieldGet(this, _uSyncContentPreviewElement_cultures, "f").length > 1
100
+ ? html `<uui-button-group
101
+ aria-label=${this.localize.termOrDefault('uSync_previewCulture', 'Language')}>
102
+ ${__classPrivateFieldGet(this, _uSyncContentPreviewElement_cultures, "f").map((culture) => html `<uui-button
103
+ look=${culture === this._culture ? 'primary' : 'secondary'}
104
+ compact
105
+ label=${culture}
106
+ @click=${() => (this._culture = culture)}></uui-button>`)}
107
+ </uui-button-group>`
108
+ : nothing}
109
+ ${
110
+ // there is only something to compare when the item is on both sides.
111
+ __classPrivateFieldGet(this, _uSyncContentPreviewElement_current, "f").item && __classPrivateFieldGet(this, _uSyncContentPreviewElement_incoming, "f").item
112
+ ? html `<uui-toggle
113
+ label=${this.localize.termOrDefault('uSync_previewOnlyChanges', 'Only show changes')}
114
+ ?checked=${this._onlyChanges}
115
+ @change=${(e) => (this._onlyChanges = e.target.checked)}></uui-toggle>`
116
+ : nothing}
117
+ </div>`;
118
+ };
119
+ _uSyncContentPreviewElement_renderSide = function _uSyncContentPreviewElement_renderSide(side, data, tabs, active) {
120
+ const headline = side === 'current'
121
+ ? this.localize.termOrDefault('uSync_previewCurrent', 'Current (this site)')
122
+ : this.localize.termOrDefault('uSync_previewIncoming', 'Incoming (uSync files)');
123
+ if (!data.item) {
124
+ return html `<div class="side ${side}">
125
+ <h4 class="side-headline">${headline}</h4>
126
+ <uui-box class="info"><p class="empty">${__classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_missingMessage).call(this, side)}</p></uui-box>
127
+ </div>`;
128
+ }
129
+ return html `
130
+ <div class="side ${side}">
131
+ <h4 class="side-headline">${headline}</h4>
132
+ ${__classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_renderInfo).call(this, data)}
133
+ ${tabs.length > 1 || (tabs.length === 1 && tabs[0].name)
134
+ ? html `<uui-tab-group>
135
+ ${tabs.map((tab) => __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_renderTabButton).call(this, tab, tab === active))}
136
+ </uui-tab-group>`
137
+ : html `<div></div>`}
138
+ ${active
139
+ ? __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_renderTab).call(this, data.item, active)
140
+ : html `<uui-box>
141
+ <p class="empty">
142
+ ${this._onlyChanges
143
+ ? this.localize.termOrDefault('uSync_previewNoValueChanges', 'No values change')
144
+ : this.localize.termOrDefault('uSync_previewNoProperties', 'No properties')}
145
+ </p>
146
+ </uui-box>`}
147
+ </div>
148
+ `;
149
+ };
150
+ _uSyncContentPreviewElement_missingMessage = function _uSyncContentPreviewElement_missingMessage(side) {
151
+ if (side === 'current') {
152
+ return this.localize.termOrDefault('uSync_previewNotInSite', 'This item does not exist in the site yet');
153
+ }
154
+ return this.preview?.isDelete
155
+ ? this.localize.termOrDefault('uSync_previewDeleted', 'This item will be deleted or renamed by the import')
156
+ : this.localize.termOrDefault('uSync_previewFailed', 'The incoming item could not be built for the preview');
157
+ };
158
+ _uSyncContentPreviewElement_renderInfo = function _uSyncContentPreviewElement_renderInfo(data) {
159
+ const item = data.item;
160
+ const info = data.info;
161
+ const other = data === __classPrivateFieldGet(this, _uSyncContentPreviewElement_current, "f") ? __classPrivateFieldGet(this, _uSyncContentPreviewElement_incoming, "f") : __classPrivateFieldGet(this, _uSyncContentPreviewElement_current, "f");
162
+ const both = !!other.item;
163
+ const changed = (field) => {
164
+ if (!both)
165
+ return { changed: false };
166
+ const mine = field === 'name' ? __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_name).call(this, item) : info?.[field];
167
+ const theirs = field === 'name' ? __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_name).call(this, other.item) : other.info?.[field];
168
+ return { changed: !deepEqual(mine, theirs) };
169
+ };
170
+ const icon = 'documentType' in item ? item.documentType.icon : item.mediaType.icon;
171
+ return html `
172
+ <uui-box class="info">
173
+ <div slot="headline" class="headline">
174
+ <umb-icon name=${icon}></umb-icon>
175
+ <span class=${classMap(changed('name'))}>${__classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_name).call(this, item)}</span>
176
+ </div>
177
+ <dl class="meta">
178
+ <dt>${this.localize.termOrDefault('uSync_previewParent', 'Parent')}</dt>
179
+ <dd>
180
+ <span class=${classMap(changed('parent'))}
181
+ >${info?.parent ?? this.localize.termOrDefault('uSync_previewRoot', '(root)')}</span
182
+ >
183
+ </dd>
184
+ ${info?.template !== undefined && this.preview?.entityType === 'document'
185
+ ? html `<dt>
186
+ ${this.localize.termOrDefault('uSync_previewTemplate', 'Template')}
187
+ </dt>
188
+ <dd>
189
+ <span class=${classMap(changed('template'))}
190
+ >${info?.template ?? '-'}</span
191
+ >
192
+ </dd>`
193
+ : nothing}
194
+ <dt>${this.localize.termOrDefault('uSync_previewSortOrder', 'Sort order')}</dt>
195
+ <dd>
196
+ <span class=${classMap(changed('sortOrder'))}>${info?.sortOrder ?? '-'}</span>
197
+ </dd>
198
+ ${info?.published.length
199
+ ? html `<dt>
200
+ ${this.localize.termOrDefault('uSync_previewPublished', 'Published')}
201
+ </dt>
202
+ <dd>
203
+ <span class=${classMap({ tags: true, ...changed('published') })}>
204
+ ${info.published.map((p) => __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_renderPublished).call(this, p.culture, p.published))}
205
+ </span>
206
+ </dd>`
207
+ : nothing}
208
+ </dl>
209
+ ${info?.trashed
210
+ ? html `<uui-tag color="danger" look="secondary"
211
+ >${this.localize.termOrDefault('uSync_previewTrashed', 'In the recycle bin')}</uui-tag
212
+ >`
213
+ : nothing}
214
+ </uui-box>
215
+ `;
216
+ };
217
+ _uSyncContentPreviewElement_renderPublished = function _uSyncContentPreviewElement_renderPublished(culture, published) {
218
+ const label = published
219
+ ? this.localize.termOrDefault('uSync_previewPublished', 'Published')
220
+ : this.localize.termOrDefault('uSync_previewNotPublished', 'Not published');
221
+ return html `<uui-tag
222
+ size="s"
223
+ look=${published ? 'primary' : 'secondary'}
224
+ color=${published ? 'positive' : 'default'}
225
+ >${culture ? `${culture}: ` : ''}${label}</uui-tag
226
+ >`;
227
+ };
228
+ _uSyncContentPreviewElement_name = function _uSyncContentPreviewElement_name(item) {
229
+ const variant = item.variants.find((v) => (v.culture ?? undefined) === this._culture) ??
230
+ item.variants[0];
231
+ return variant?.name ?? '';
232
+ };
233
+ _uSyncContentPreviewElement_renderTabButton = function _uSyncContentPreviewElement_renderTabButton(tab, active) {
234
+ const changed = __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_tabProperties).call(this, tab).some((p) => __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_valueStatus).call(this, p.property));
235
+ const label = tab.name || this.localize.termOrDefault('uSync_previewGenericTab', 'Generic');
236
+ return html `<uui-tab
237
+ label=${label}
238
+ ?active=${active}
239
+ @click=${() => (this._activeTab = tab.name)}>
240
+ <span class="tab-label">
241
+ ${label} ${changed ? html `<span class="dot changed"></span>` : nothing}
242
+ </span>
243
+ </uui-tab>`;
244
+ };
245
+ _uSyncContentPreviewElement_renderTab = function _uSyncContentPreviewElement_renderTab(item, tab) {
246
+ // inert rather than readonly: editors are shown as an editor would see them,
247
+ // but nothing in the preview can be changed.
248
+ return html `
249
+ <umb-property-dataset .value=${__classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_datasetValue).call(this, item)} inert>
250
+ ${tab.properties.length ? html `<uui-box>${__classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_renderProperties).call(this, tab.properties)}</uui-box>` : nothing}
251
+ ${repeat(tab.groups, (group) => group.name, (group) => html `<uui-box headline=${group.name}
252
+ >${__classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_renderProperties).call(this, group.properties)}</uui-box
253
+ >`)}
254
+ </umb-property-dataset>
255
+ `;
256
+ };
257
+ _uSyncContentPreviewElement_renderProperties = function _uSyncContentPreviewElement_renderProperties(properties) {
258
+ return repeat(properties, (entry) => entry.property.id, ({ property: p }) => {
259
+ const dataType = __classPrivateFieldGet(this, _uSyncContentPreviewElement_dataTypes, "f").get(p.dataType.id);
260
+ const status = __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_valueStatus).call(this, p);
261
+ return html `<div class="property ${status ?? ''}">
262
+ ${dataType
263
+ ? html `<umb-property
264
+ .alias=${p.alias}
265
+ .label=${p.name}
266
+ .description=${p.description ?? ''}
267
+ .propertyEditorUiAlias=${dataType.editorUiAlias}
268
+ .config=${dataType.values}
269
+ .appearance=${p.appearance}></umb-property>`
270
+ : html `<p class="empty">${p.name}</p>`}
271
+ </div>`;
272
+ });
273
+ };
274
+ _uSyncContentPreviewElement_visibleTabs = function _uSyncContentPreviewElement_visibleTabs(tabs) {
275
+ if (!this._onlyChanges)
276
+ return tabs;
277
+ const keep = (properties) => properties.filter((p) => __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_valueStatus).call(this, p.property));
278
+ return tabs
279
+ .map((tab) => ({
280
+ ...tab,
281
+ properties: keep(tab.properties),
282
+ groups: tab.groups
283
+ .map((group) => ({ ...group, properties: keep(group.properties) }))
284
+ .filter((group) => group.properties.length > 0),
285
+ }))
286
+ .filter((tab) => tab.properties.length > 0 || tab.groups.length > 0);
287
+ };
288
+ _uSyncContentPreviewElement_tabProperties = function _uSyncContentPreviewElement_tabProperties(tab) {
289
+ return [...tab.properties, ...tab.groups.flatMap((g) => g.properties)];
290
+ };
291
+ _uSyncContentPreviewElement_datasetValue = function _uSyncContentPreviewElement_datasetValue(item) {
292
+ return item.values
293
+ .filter((v) => !v.segment && (!v.culture || v.culture === this._culture))
294
+ .map((v) => ({ alias: v.alias, value: v.value }));
295
+ };
296
+ _uSyncContentPreviewElement_value = function _uSyncContentPreviewElement_value(item, p) {
297
+ const culture = p.variesByCulture ? this._culture : undefined;
298
+ return item?.values.find((v) => v.alias === p.alias && !v.segment && (v.culture ?? undefined) === culture)?.value;
299
+ };
300
+ _uSyncContentPreviewElement_valueStatus = function _uSyncContentPreviewElement_valueStatus(p) {
301
+ const current = __classPrivateFieldGet(this, _uSyncContentPreviewElement_current, "f").item;
302
+ const incoming = __classPrivateFieldGet(this, _uSyncContentPreviewElement_incoming, "f").item;
303
+ if (!current || !incoming)
304
+ return undefined;
305
+ const before = __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_value).call(this, current, p);
306
+ const after = __classPrivateFieldGet(this, _uSyncContentPreviewElement_instances, "m", _uSyncContentPreviewElement_value).call(this, incoming, p);
307
+ if (deepEqual(normalise(before), normalise(after)))
308
+ return undefined;
309
+ if (isEmpty(before))
310
+ return 'added';
311
+ if (isEmpty(after))
312
+ return 'removed';
313
+ return 'changed';
314
+ };
315
+ uSyncContentPreviewElement.styles = css `
316
+ :host {
317
+ display: block;
318
+ container-type: inline-size;
319
+ }
320
+
321
+ /* the toolbar shares the headline row with the incoming side, on the right. */
322
+ .toolbar {
323
+ grid-column: 2;
324
+ grid-row: 1;
325
+ justify-self: end;
326
+ align-self: center;
327
+ z-index: 1;
328
+ display: flex;
329
+ flex-wrap: wrap;
330
+ align-items: center;
331
+ gap: var(--uui-size-space-4);
332
+ }
333
+
334
+ /* the two sides share rows (headline, info, tabs, content), so the
335
+ tab bars and properties line up even when the info boxes differ. */
336
+ .sides {
337
+ display: grid;
338
+ grid-template-columns: 1fr 1fr;
339
+ grid-template-rows: auto auto auto 1fr;
340
+ gap: var(--uui-size-space-4) var(--uui-size-space-5);
341
+ }
342
+
343
+ .side {
344
+ display: grid;
345
+ grid-row: span 4;
346
+ grid-template-rows: subgrid;
347
+ align-items: start;
348
+ min-width: 0;
349
+ }
350
+
351
+ .side.current {
352
+ grid-column: 1;
353
+ grid-row: 1 / span 4;
354
+ }
355
+
356
+ .side.incoming {
357
+ grid-column: 2;
358
+ grid-row: 1 / span 4;
359
+ }
360
+
361
+ .side > .info:not(:last-child) {
362
+ align-self: stretch;
363
+ }
364
+
365
+ @container (max-width: 760px) {
366
+ .sides {
367
+ grid-template-columns: 1fr;
368
+ grid-template-rows: none;
369
+ row-gap: var(--uui-size-layout-1);
370
+ }
371
+
372
+ .side,
373
+ .side.current,
374
+ .side.incoming,
375
+ .toolbar {
376
+ grid-column: 1;
377
+ grid-row: auto;
378
+ }
379
+
380
+ .side {
381
+ display: flex;
382
+ flex-direction: column;
383
+ align-items: stretch;
384
+ gap: var(--uui-size-space-4);
385
+ }
386
+
387
+ .side > .side-headline {
388
+ align-self: auto;
389
+ }
390
+ }
391
+
392
+ umb-property-dataset {
393
+ display: flex;
394
+ flex-direction: column;
395
+ gap: var(--uui-size-space-4);
396
+ min-width: 0;
397
+ }
398
+
399
+ .side-headline {
400
+ align-self: center;
401
+ margin: 0;
402
+ font-size: var(--uui-type-small-size);
403
+ text-transform: uppercase;
404
+ letter-spacing: 0.04em;
405
+ color: var(--uui-color-text-alt);
406
+ }
407
+
408
+ .headline {
409
+ display: flex;
410
+ align-items: center;
411
+ gap: var(--uui-size-space-3);
412
+ }
413
+
414
+ .meta {
415
+ display: grid;
416
+ grid-template-columns: max-content 1fr;
417
+ align-items: center;
418
+ gap: var(--uui-size-space-2) var(--uui-size-space-5);
419
+ margin: 0 0 var(--uui-size-space-2);
420
+ }
421
+
422
+ .meta dt {
423
+ font-weight: 700;
424
+ }
425
+
426
+ .tags {
427
+ display: inline-flex;
428
+ flex-wrap: wrap;
429
+ gap: var(--uui-size-space-2);
430
+ }
431
+
432
+ .meta dd {
433
+ display: flex;
434
+ flex-wrap: wrap;
435
+ gap: var(--uui-size-space-2);
436
+ margin: 0;
437
+ }
438
+
439
+ /* a changed field gets a soft highlight, spread with a shadow so the text doesn't move. */
440
+ .changed:not(.property):not(.dot) {
441
+ background: color-mix(in srgb, var(--uui-color-warning) 35%, transparent);
442
+ border-radius: var(--uui-border-radius);
443
+ box-shadow: 0 0 0 var(--uui-size-space-1)
444
+ color-mix(in srgb, var(--uui-color-warning) 35%, transparent);
445
+ }
446
+
447
+ uui-tab-group {
448
+ --uui-tab-divider: var(--uui-color-border);
449
+ border-bottom: 1px solid var(--uui-color-border);
450
+ }
451
+
452
+ .tab-label {
453
+ display: inline-flex;
454
+ align-items: center;
455
+ gap: var(--uui-size-space-2);
456
+ white-space: nowrap;
457
+ }
458
+
459
+ .dot {
460
+ display: inline-block;
461
+ width: 8px;
462
+ height: 8px;
463
+ border-radius: 50%;
464
+ }
465
+
466
+ .dot.changed {
467
+ background: var(--uui-color-warning);
468
+ }
469
+
470
+ /* marked with an inset bar rather than a border, so the content doesn't shift. */
471
+ .property.added {
472
+ box-shadow: inset 3px 0 0 var(--uui-color-positive);
473
+ background: color-mix(in srgb, var(--uui-color-positive) 6%, transparent);
474
+ }
475
+
476
+ .property.removed {
477
+ box-shadow: inset 3px 0 0 var(--uui-color-danger);
478
+ background: color-mix(in srgb, var(--uui-color-danger) 6%, transparent);
479
+ }
480
+
481
+ .property.changed {
482
+ box-shadow: inset 3px 0 0 var(--uui-color-warning);
483
+ background: color-mix(in srgb, var(--uui-color-warning) 10%, transparent);
484
+ }
485
+
486
+ /* properties run edge to edge in their box, like the backoffice editor. */
487
+ .property {
488
+ padding: 0 var(--uui-size-space-5);
489
+ margin: 0 calc(-1 * var(--uui-size-space-5));
490
+ }
491
+
492
+ .property:first-child {
493
+ margin-top: calc(-1 * var(--uui-size-space-5));
494
+ }
495
+
496
+ .property:last-child {
497
+ margin-bottom: calc(-1 * var(--uui-size-space-5));
498
+ }
499
+
500
+ .property + .property {
501
+ border-top: 1px solid var(--uui-color-divider);
502
+ }
503
+
504
+ /* umb-property pads itself for a full workspace, tighten it up here. */
505
+ umb-property {
506
+ --uui-size-layout-1: var(--uui-size-space-4);
507
+ }
508
+
509
+ .empty {
510
+ margin: 0;
511
+ color: var(--uui-color-text-alt);
512
+ }
513
+ `;
514
+ __decorate([
515
+ property({ type: Object })
516
+ ], uSyncContentPreviewElement.prototype, "preview", void 0);
517
+ __decorate([
518
+ state()
519
+ ], uSyncContentPreviewElement.prototype, "_activeTab", void 0);
520
+ __decorate([
521
+ state()
522
+ ], uSyncContentPreviewElement.prototype, "_culture", void 0);
523
+ __decorate([
524
+ state()
525
+ ], uSyncContentPreviewElement.prototype, "_onlyChanges", void 0);
526
+ uSyncContentPreviewElement = __decorate([
527
+ customElement('usync-content-preview')
528
+ ], uSyncContentPreviewElement);
529
+ export { uSyncContentPreviewElement };
530
+ /** values that mean "nothing set" compare as equal */
531
+ function normalise(value) {
532
+ return isEmpty(value) ? undefined : value;
533
+ }
534
+ function isEmpty(value) {
535
+ return (value === undefined ||
536
+ value === null ||
537
+ value === '' ||
538
+ (Array.isArray(value) && value.length === 0));
539
+ }
540
+ export default uSyncContentPreviewElement;
@@ -0,0 +1,25 @@
1
+ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
2
+ import { type PropertyValues, nothing } from '@umbraco-cms/backoffice/external/lit';
3
+ import '@umbraco-cms/backoffice/components';
4
+ import type { SyncItemPreviewResponse } from '../api';
5
+ /**
6
+ * Shows the current and incoming versions of a document, media or member
7
+ * type side by side, laid out the way the backoffice editor shows them, with
8
+ * every property rendered by its real property editor. Added, removed and
9
+ * changed tabs, groups and properties are highlighted.
10
+ */
11
+ export declare class uSyncContentTypePreviewElement extends UmbLitElement {
12
+ #private;
13
+ preview?: SyncItemPreviewResponse;
14
+ /** the tab shown on both sides (by name, so it lines up when ids differ) */
15
+ private _activeTab?;
16
+ protected willUpdate(changed: PropertyValues<this>): void;
17
+ render(): typeof nothing | import("lit-html").TemplateResult<1>;
18
+ static styles: import("lit").CSSResult;
19
+ }
20
+ export default uSyncContentTypePreviewElement;
21
+ declare global {
22
+ interface HTMLElementTagNameMap {
23
+ 'usync-content-type-preview': uSyncContentTypePreviewElement;
24
+ }
25
+ }