@jumoo/usync 18.2.0 → 18.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENCE +372 -372
  2. package/README.md +16 -10
  3. package/dist/api/index.d.ts +2 -2
  4. package/dist/api/index.js +1 -1
  5. package/dist/api/sdk.gen.d.ts +2 -1
  6. package/dist/api/sdk.gen.js +5 -0
  7. package/dist/api/types.gen.d.ts +37 -0
  8. package/dist/components/usync-action-box.js +71 -71
  9. package/dist/components/usync-change-detail.js +409 -409
  10. package/dist/components/usync-change-view.js +49 -49
  11. package/dist/components/usync-content-preview.d.ts +27 -0
  12. package/dist/components/usync-content-preview.js +532 -0
  13. package/dist/components/usync-content-type-preview.d.ts +25 -0
  14. package/dist/components/usync-content-type-preview.js +530 -0
  15. package/dist/components/usync-data-type-preview.d.ts +21 -0
  16. package/dist/components/usync-data-type-preview.js +295 -0
  17. package/dist/components/usync-progress-box.js +113 -113
  18. package/dist/components/usync-result-row.js +65 -65
  19. package/dist/components/usync-results-group-view.js +63 -63
  20. package/dist/components/usync-results-view.js +77 -69
  21. package/dist/components/usync-sync-file-info-view.js +10 -10
  22. package/dist/constants.js +1 -1
  23. package/dist/dialogs/details-modal-element.d.ts +15 -0
  24. package/dist/dialogs/details-modal-element.js +260 -50
  25. package/dist/dialogs/details-modal-token.d.ts +10 -1
  26. package/dist/dialogs/error-modal-element.js +22 -22
  27. package/dist/dialogs/legacy-modal-element.js +22 -22
  28. package/dist/dialogs/single-import-modal.element.js +31 -31
  29. package/dist/exports.d.ts +1 -0
  30. package/dist/exports.js +1 -0
  31. package/dist/icons/svg/logo.js +20 -20
  32. package/dist/lang/files/da-dk.d.ts +37 -0
  33. package/dist/lang/files/da-dk.js +49 -12
  34. package/dist/lang/files/de-de.d.ts +37 -0
  35. package/dist/lang/files/de-de.js +49 -12
  36. package/dist/lang/files/en-us.d.ts +50 -0
  37. package/dist/lang/files/en-us.js +62 -12
  38. package/dist/lang/files/es-es.d.ts +37 -0
  39. package/dist/lang/files/es-es.js +49 -12
  40. package/dist/lang/files/fr-fr.d.ts +37 -0
  41. package/dist/lang/files/fr-fr.js +49 -12
  42. package/dist/lang/files/nl-nl.d.ts +37 -0
  43. package/dist/lang/files/nl-nl.js +49 -12
  44. package/dist/manifests.js +2 -0
  45. package/dist/preview/index.d.ts +1 -0
  46. package/dist/preview/index.js +1 -0
  47. package/dist/preview/manifest.d.ts +2 -0
  48. package/dist/preview/manifest.js +22 -0
  49. package/dist/preview/types.d.ts +72 -0
  50. package/dist/preview/types.js +2 -0
  51. package/dist/repository/SyncAction.respositoy.d.ts +13 -0
  52. package/dist/repository/SyncAction.respositoy.js +6 -0
  53. package/dist/repository/sources/SyncAction.source.d.ts +10 -0
  54. package/dist/repository/sources/SyncAction.source.js +6 -1
  55. package/dist/signalr/signalr.context.js +73 -26
  56. package/dist/tree/usync.menu-element.js +8 -8
  57. package/dist/utils/preview/content-type-diff.d.ts +18 -0
  58. package/dist/utils/preview/content-type-diff.js +72 -0
  59. package/dist/utils/preview/content-type-layout.d.ts +39 -0
  60. package/dist/utils/preview/content-type-layout.js +100 -0
  61. package/dist/workspace/components/usync-action-button.js +53 -53
  62. package/dist/workspace/components/usync-file-picker.element.js +33 -33
  63. package/dist/workspace/components/usync-file-upload.element.js +25 -25
  64. package/dist/workspace/dialogs/import-modal.element.js +22 -22
  65. package/dist/workspace/views/addons/addons.element.js +97 -97
  66. package/dist/workspace/views/default/default.element.js +186 -186
  67. package/dist/workspace/views/legacy/legacy.element.js +81 -81
  68. package/dist/workspace/views/settings/components/usyncSettingItem.element.js +38 -38
  69. package/dist/workspace/views/settings/settings.element.js +124 -124
  70. package/dist/workspace/workspace.element.js +16 -16
  71. package/package.json +77 -77
@@ -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
+ }
@@ -0,0 +1,530 @@
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 _uSyncContentTypePreviewElement_instances, _uSyncContentTypePreviewElement_sides, _uSyncContentTypePreviewElement_compositions, _uSyncContentTypePreviewElement_dataTypes, _uSyncContentTypePreviewElement_newDataTypes, _uSyncContentTypePreviewElement_newCompositions, _uSyncContentTypePreviewElement_diff, _uSyncContentTypePreviewElement_renderSide, _uSyncContentTypePreviewElement_missingMessage, _uSyncContentTypePreviewElement_renderInfo, _uSyncContentTypePreviewElement_renderTabButton, _uSyncContentTypePreviewElement_tabStatus, _uSyncContentTypePreviewElement_renderTab, _uSyncContentTypePreviewElement_ownStatus, _uSyncContentTypePreviewElement_renderProperties, _uSyncContentTypePreviewElement_renderBadge;
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 { getPreviewModel } from '../preview/types.js';
23
+ import { buildContentTypeLayout, compositionIds, } from '../utils/preview/content-type-layout.js';
24
+ import { diffContentTypes, } from '../utils/preview/content-type-diff.js';
25
+ const KIND_LABELS = {
26
+ 'document-type': ['uSync_previewDocumentType', 'Document type'],
27
+ 'media-type': ['uSync_previewMediaType', 'Media type'],
28
+ 'member-type': ['uSync_previewMemberType', 'Member type'],
29
+ };
30
+ /**
31
+ * Shows the current and incoming versions of a document, media or member
32
+ * type side by side, laid out the way the backoffice editor shows them, with
33
+ * every property rendered by its real property editor. Added, removed and
34
+ * changed tabs, groups and properties are highlighted.
35
+ */
36
+ let uSyncContentTypePreviewElement = class uSyncContentTypePreviewElement extends UmbLitElement {
37
+ constructor() {
38
+ super(...arguments);
39
+ _uSyncContentTypePreviewElement_instances.add(this);
40
+ _uSyncContentTypePreviewElement_sides.set(this, { compositions: [] });
41
+ _uSyncContentTypePreviewElement_compositions.set(this, new Map());
42
+ _uSyncContentTypePreviewElement_dataTypes.set(this, new Map());
43
+ _uSyncContentTypePreviewElement_newDataTypes.set(this, new Set());
44
+ _uSyncContentTypePreviewElement_newCompositions.set(this, new Set());
45
+ _uSyncContentTypePreviewElement_diff.set(this, void 0);
46
+ }
47
+ willUpdate(changed) {
48
+ if (!changed.has('preview') || !this.preview)
49
+ return;
50
+ const model = getPreviewModel(this.preview);
51
+ __classPrivateFieldSet(this, _uSyncContentTypePreviewElement_sides, {
52
+ current: model?.current ?? undefined,
53
+ incoming: model?.incoming ?? undefined,
54
+ compositions: model?.compositions ?? [],
55
+ }, "f");
56
+ __classPrivateFieldSet(this, _uSyncContentTypePreviewElement_compositions, new Map(__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_sides, "f").compositions.map((c) => [c.id, c])), "f");
57
+ __classPrivateFieldSet(this, _uSyncContentTypePreviewElement_dataTypes, new Map((model?.dataTypes ?? []).map((d) => [d.id, d])), "f");
58
+ __classPrivateFieldSet(this, _uSyncContentTypePreviewElement_newDataTypes, new Set(model?.newDataTypes), "f");
59
+ __classPrivateFieldSet(this, _uSyncContentTypePreviewElement_newCompositions, new Set(model?.newCompositions), "f");
60
+ __classPrivateFieldSet(this, _uSyncContentTypePreviewElement_diff, diffContentTypes(__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_sides, "f").current, __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_sides, "f").incoming), "f");
61
+ this._activeTab = undefined;
62
+ }
63
+ render() {
64
+ if (!this.preview)
65
+ return nothing;
66
+ return html `
67
+ <div class="sides">
68
+ ${__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_renderSide).call(this, 'current', __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_sides, "f").current)}
69
+ ${__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_renderSide).call(this, 'incoming', __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_sides, "f").incoming)}
70
+ </div>
71
+ `;
72
+ }
73
+ };
74
+ _uSyncContentTypePreviewElement_sides = new WeakMap();
75
+ _uSyncContentTypePreviewElement_compositions = new WeakMap();
76
+ _uSyncContentTypePreviewElement_dataTypes = new WeakMap();
77
+ _uSyncContentTypePreviewElement_newDataTypes = new WeakMap();
78
+ _uSyncContentTypePreviewElement_newCompositions = new WeakMap();
79
+ _uSyncContentTypePreviewElement_diff = new WeakMap();
80
+ _uSyncContentTypePreviewElement_instances = new WeakSet();
81
+ _uSyncContentTypePreviewElement_renderSide = function _uSyncContentTypePreviewElement_renderSide(side, type) {
82
+ const headline = side === 'current'
83
+ ? this.localize.termOrDefault('uSync_previewCurrent', 'Current (this site)')
84
+ : this.localize.termOrDefault('uSync_previewIncoming', 'Incoming (uSync files)');
85
+ if (!type) {
86
+ return html `<div class="side">
87
+ <h4 class="side-headline">${headline}</h4>
88
+ <uui-box class="info"><p class="empty">${__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_missingMessage).call(this, side)}</p></uui-box>
89
+ </div>`;
90
+ }
91
+ const tabs = buildContentTypeLayout(type, __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_compositions, "f"));
92
+ const active = tabs.find((t) => t.name === this._activeTab) ?? tabs[0];
93
+ return html `
94
+ <div class="side">
95
+ <h4 class="side-headline">${headline}</h4>
96
+ ${__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_renderInfo).call(this, type)}
97
+ ${tabs.length > 1 || (tabs.length === 1 && tabs[0].name)
98
+ ? html `<uui-tab-group>
99
+ ${tabs.map((tab) => __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_renderTabButton).call(this, tab, tab === active))}
100
+ </uui-tab-group>`
101
+ : html `<div></div>`}
102
+ ${active
103
+ ? __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_renderTab).call(this, active)
104
+ : html `<uui-box>
105
+ <p class="empty">
106
+ ${this.localize.termOrDefault('uSync_previewNoProperties', 'This type has no properties')}
107
+ </p>
108
+ </uui-box>`}
109
+ </div>
110
+ `;
111
+ };
112
+ _uSyncContentTypePreviewElement_missingMessage = function _uSyncContentTypePreviewElement_missingMessage(side) {
113
+ if (side === 'current') {
114
+ return this.localize.termOrDefault('uSync_previewNotInSite', 'This item does not exist in the site yet');
115
+ }
116
+ return this.preview?.isDelete
117
+ ? this.localize.termOrDefault('uSync_previewDeleted', 'This item will be deleted or renamed by the import')
118
+ : this.localize.termOrDefault('uSync_previewFailed', 'The incoming item could not be built for the preview');
119
+ };
120
+ _uSyncContentTypePreviewElement_renderInfo = function _uSyncContentTypePreviewElement_renderInfo(type) {
121
+ const changed = (field) => ({
122
+ changed: __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_diff, "f")?.fields.has(field) ?? false,
123
+ });
124
+ const [kindKey, kindDefault] = KIND_LABELS[this.preview?.entityType ?? ''] ?? [
125
+ '',
126
+ '',
127
+ ];
128
+ const compositions = compositionIds(type).map((id) => ({
129
+ name: __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_compositions, "f").get(id)?.name ?? id,
130
+ isNew: __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_newCompositions, "f").has(id),
131
+ }));
132
+ return html `
133
+ <uui-box class="info">
134
+ <div slot="headline" class="headline">
135
+ <umb-icon
136
+ name=${type.icon.split(' ')[0]}
137
+ class=${classMap(changed('icon'))}></umb-icon>
138
+ <span class=${classMap(changed('name'))}>${type.name}</span>
139
+ <code class=${classMap(changed('alias'))}>${type.alias}</code>
140
+ </div>
141
+ <div class="info-body">
142
+ <div class="tags">
143
+ <uui-tag look="secondary" class=${classMap(changed('isElement'))}>
144
+ ${type.isElement
145
+ ? this.localize.termOrDefault('uSync_previewElementType', 'Element type')
146
+ : this.localize.termOrDefault(kindKey, kindDefault)}
147
+ </uui-tag>
148
+ ${type.allowedAsRoot
149
+ ? html `<uui-tag
150
+ look="secondary"
151
+ class=${classMap(changed('allowedAsRoot'))}>
152
+ ${this.localize.termOrDefault('uSync_previewAllowedAtRoot', 'Allowed at root')}
153
+ </uui-tag>`
154
+ : nothing}
155
+ ${type.variesByCulture
156
+ ? html `<uui-tag
157
+ look="secondary"
158
+ class=${classMap(changed('variesByCulture'))}>
159
+ ${this.localize.termOrDefault('uSync_previewVariesByCulture', 'Varies by culture')}
160
+ </uui-tag>`
161
+ : nothing}
162
+ ${type.variesBySegment
163
+ ? html `<uui-tag
164
+ look="secondary"
165
+ class=${classMap(changed('variesBySegment'))}>
166
+ ${this.localize.termOrDefault('uSync_previewVariesBySegment', 'Varies by segment')}
167
+ </uui-tag>`
168
+ : nothing}
169
+ </div>
170
+ ${type.description
171
+ ? html `<p
172
+ class=${classMap({ description: true, ...changed('description') })}>
173
+ ${type.description}
174
+ </p>`
175
+ : nothing}
176
+ ${compositions.length
177
+ ? html `<dl class="meta">
178
+ <dt>
179
+ ${this.localize.termOrDefault('uSync_previewCompositions', 'Compositions')}
180
+ </dt>
181
+ <dd class=${classMap(changed('compositions'))}>
182
+ ${compositions.map((c) => html `<uui-tag
183
+ look="outline"
184
+ color=${c.isNew ? 'positive' : 'default'}
185
+ >${c.name}${c.isNew
186
+ ? ` (${this.localize.termOrDefault('uSync_previewNew', 'new')})`
187
+ : ''}</uui-tag
188
+ > `)}
189
+ </dd>
190
+ </dl>`
191
+ : nothing}
192
+ </div>
193
+ </uui-box>
194
+ `;
195
+ };
196
+ _uSyncContentTypePreviewElement_renderTabButton = function _uSyncContentTypePreviewElement_renderTabButton(tab, active) {
197
+ const status = __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_tabStatus).call(this, tab);
198
+ const label = tab.name || this.localize.termOrDefault('uSync_previewGenericTab', 'Generic');
199
+ return html `<uui-tab
200
+ label=${label}
201
+ ?active=${active}
202
+ @click=${() => (this._activeTab = tab.name)}>
203
+ <span class="tab-label">
204
+ ${label}
205
+ ${status ? html `<span class="dot ${status}" title=${status}></span>` : nothing}
206
+ </span>
207
+ </uui-tab>`;
208
+ };
209
+ _uSyncContentTypePreviewElement_tabStatus = function _uSyncContentTypePreviewElement_tabStatus(tab) {
210
+ const own = tab.ids.map((id) => __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_diff, "f")?.containers.get(id)).find(Boolean);
211
+ if (own)
212
+ return own.status;
213
+ const children = [
214
+ ...tab.groups.flatMap((g) => g.ids.map((id) => __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_diff, "f")?.containers.get(id))),
215
+ ...tab.properties.map((p) => __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_diff, "f")?.properties.get(p.property.id)),
216
+ ...tab.groups.flatMap((g) => g.properties.map((p) => __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_diff, "f")?.properties.get(p.property.id))),
217
+ ];
218
+ return children.some(Boolean) ? 'changed' : undefined;
219
+ };
220
+ _uSyncContentTypePreviewElement_renderTab = function _uSyncContentTypePreviewElement_renderTab(tab) {
221
+ // inert rather than readonly: most editors render only their value when
222
+ // readonly, which is empty here, so you wouldn't see the editor at all.
223
+ return html `
224
+ <umb-property-dataset .value=${[]} inert>
225
+ ${tab.properties.length
226
+ ? html `<uui-box
227
+ >${__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_renderProperties).call(this, tab.properties, __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_ownStatus).call(this, tab.ids))}</uui-box
228
+ >`
229
+ : nothing}
230
+ ${repeat(tab.groups, (group) => group.name, (group) => {
231
+ const change = group.ids
232
+ .map((id) => __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_diff, "f")?.containers.get(id))
233
+ .find(Boolean);
234
+ return html `<uui-box class=${change?.status ?? ''}>
235
+ <div slot="headline" class="headline">
236
+ ${group.name}
237
+ ${group.inherited ? html `<small class="inherited">inherited</small>` : nothing}
238
+ ${__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_renderBadge).call(this, change)}
239
+ </div>
240
+ ${group.properties.length
241
+ ? __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_renderProperties).call(this, group.properties, change?.status ?? __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_ownStatus).call(this, tab.ids))
242
+ : html `<p class="empty">
243
+ ${this.localize.termOrDefault('uSync_previewNoProperties', 'No properties')}
244
+ </p>`}
245
+ </uui-box>`;
246
+ })}
247
+ </umb-property-dataset>
248
+ `;
249
+ };
250
+ _uSyncContentTypePreviewElement_ownStatus = function _uSyncContentTypePreviewElement_ownStatus(ids) {
251
+ return ids.map((id) => __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_diff, "f")?.containers.get(id)).find(Boolean)?.status;
252
+ };
253
+ _uSyncContentTypePreviewElement_renderProperties = function _uSyncContentTypePreviewElement_renderProperties(properties, parentStatus) {
254
+ const markItems = parentStatus !== 'added' && parentStatus !== 'removed';
255
+ return repeat(properties, (entry) => entry.property.id, ({ property: p, inheritedFrom }) => {
256
+ const change = markItems ? __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_diff, "f")?.properties.get(p.id) : undefined;
257
+ const dataType = __classPrivateFieldGet(this, _uSyncContentTypePreviewElement_dataTypes, "f").get(p.dataType.id);
258
+ return html `<div class="property ${change?.status ?? ''}">
259
+ <div class="property-meta">
260
+ <code>${p.alias}</code>
261
+ <span>${dataType?.name ?? p.dataType.id}</span>
262
+ ${__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_newDataTypes, "f").has(p.dataType.id)
263
+ ? html `<uui-tag size="s" look="outline" color="positive"
264
+ >${this.localize.termOrDefault('uSync_previewNewDataType', 'new data type')}</uui-tag
265
+ >`
266
+ : nothing}
267
+ ${inheritedFrom ? html `<small class="inherited">from ${inheritedFrom}</small>` : nothing}
268
+ ${p.variesByCulture ? html `<small>varies by culture</small>` : nothing}
269
+ ${p.variesBySegment ? html `<small>varies by segment</small>` : nothing}
270
+ ${__classPrivateFieldGet(this, _uSyncContentTypePreviewElement_instances, "m", _uSyncContentTypePreviewElement_renderBadge).call(this, change)}
271
+ </div>
272
+ ${dataType
273
+ ? html `<umb-property
274
+ .alias=${p.alias}
275
+ .label=${p.name}
276
+ .description=${p.description ?? ''}
277
+ .propertyEditorUiAlias=${dataType.editorUiAlias}
278
+ .config=${dataType.values}
279
+ .appearance=${p.appearance}
280
+ .validation=${p.validation}></umb-property>`
281
+ : html `<p class="empty">
282
+ ${p.name} -
283
+ ${this.localize.termOrDefault('uSync_previewMissingDataType', 'the data type for this property is not in the site yet')}
284
+ </p>`}
285
+ </div>`;
286
+ });
287
+ };
288
+ _uSyncContentTypePreviewElement_renderBadge = function _uSyncContentTypePreviewElement_renderBadge(change) {
289
+ if (!change)
290
+ return nothing;
291
+ const color = change.status === 'added'
292
+ ? 'positive'
293
+ : change.status === 'removed'
294
+ ? 'danger'
295
+ : 'warning';
296
+ return html `<uui-tag size="s" color=${color} title=${change.fields.join(', ')}
297
+ >${change.status}</uui-tag
298
+ >`;
299
+ };
300
+ uSyncContentTypePreviewElement.styles = css `
301
+ :host {
302
+ display: block;
303
+ container-type: inline-size;
304
+ }
305
+
306
+ /* the two sides share rows (headline, info, tabs, content), so the
307
+ tab bars and groups line up even when the info boxes differ. */
308
+ .sides {
309
+ display: grid;
310
+ grid-template-columns: 1fr 1fr;
311
+ grid-template-rows: auto auto auto 1fr;
312
+ gap: var(--uui-size-space-4) var(--uui-size-space-5);
313
+ }
314
+
315
+ .side {
316
+ display: grid;
317
+ grid-row: span 4;
318
+ grid-template-rows: subgrid;
319
+ align-items: start;
320
+ min-width: 0;
321
+ }
322
+
323
+ /* info boxes match heights across the sides (but a lone "not here" box doesn't stretch). */
324
+ .side > .info:not(:last-child) {
325
+ align-self: stretch;
326
+ }
327
+
328
+ @container (max-width: 760px) {
329
+ .sides {
330
+ grid-template-columns: 1fr;
331
+ grid-template-rows: none;
332
+ row-gap: var(--uui-size-layout-1);
333
+ }
334
+
335
+ .side {
336
+ display: flex;
337
+ flex-direction: column;
338
+ align-items: stretch;
339
+ gap: var(--uui-size-space-4);
340
+ grid-row: auto;
341
+ }
342
+ }
343
+
344
+ umb-property-dataset {
345
+ display: flex;
346
+ flex-direction: column;
347
+ gap: var(--uui-size-space-4);
348
+ min-width: 0;
349
+ }
350
+
351
+ .side-headline {
352
+ margin: 0;
353
+ font-size: var(--uui-type-small-size);
354
+ text-transform: uppercase;
355
+ letter-spacing: 0.04em;
356
+ color: var(--uui-color-text-alt);
357
+ }
358
+
359
+ .headline {
360
+ display: flex;
361
+ align-items: center;
362
+ flex-wrap: wrap;
363
+ gap: var(--uui-size-space-2) var(--uui-size-space-3);
364
+ }
365
+
366
+ .headline code {
367
+ font-size: var(--uui-type-small-size);
368
+ color: var(--uui-color-text-alt);
369
+ }
370
+
371
+ .info-body {
372
+ display: flex;
373
+ flex-direction: column;
374
+ gap: var(--uui-size-space-4);
375
+ }
376
+
377
+ .tags {
378
+ display: flex;
379
+ flex-wrap: wrap;
380
+ gap: var(--uui-size-space-2);
381
+ }
382
+
383
+ .description {
384
+ margin: 0;
385
+ }
386
+
387
+ .meta {
388
+ display: grid;
389
+ grid-template-columns: max-content 1fr;
390
+ align-items: center;
391
+ gap: var(--uui-size-space-2) var(--uui-size-space-5);
392
+ margin: 0;
393
+ }
394
+
395
+ .meta dt {
396
+ font-weight: 700;
397
+ }
398
+
399
+ .meta dd {
400
+ display: flex;
401
+ flex-wrap: wrap;
402
+ gap: var(--uui-size-space-2);
403
+ margin: 0;
404
+ }
405
+
406
+ /* a changed field gets a soft highlight, spread with a shadow so the text doesn't move. */
407
+ .changed:not(.property):not(uui-box) {
408
+ background: color-mix(in srgb, var(--uui-color-warning) 35%, transparent);
409
+ border-radius: var(--uui-border-radius);
410
+ box-shadow: 0 0 0 var(--uui-size-space-1)
411
+ color-mix(in srgb, var(--uui-color-warning) 35%, transparent);
412
+ }
413
+
414
+ uui-tab-group {
415
+ --uui-tab-divider: var(--uui-color-border);
416
+ border-bottom: 1px solid var(--uui-color-border);
417
+ }
418
+
419
+ .tab-label {
420
+ display: inline-flex;
421
+ align-items: center;
422
+ gap: var(--uui-size-space-2);
423
+ white-space: nowrap;
424
+ }
425
+
426
+ .dot {
427
+ display: inline-block;
428
+ width: 8px;
429
+ height: 8px;
430
+ border-radius: 50%;
431
+ }
432
+
433
+ .dot.added {
434
+ background: var(--uui-color-positive);
435
+ }
436
+
437
+ .dot.removed {
438
+ background: var(--uui-color-danger);
439
+ }
440
+
441
+ .dot.changed {
442
+ background: var(--uui-color-warning);
443
+ }
444
+
445
+ uui-box.added {
446
+ border-left: 3px solid var(--uui-color-positive);
447
+ }
448
+
449
+ uui-box.removed {
450
+ border-left: 3px solid var(--uui-color-danger);
451
+ }
452
+
453
+ uui-box.changed {
454
+ border-left: 3px solid var(--uui-color-warning);
455
+ }
456
+
457
+ /* marked with an inset bar rather than a border, so the content doesn't shift. */
458
+ .property.added {
459
+ box-shadow: inset 3px 0 0 var(--uui-color-positive);
460
+ background: color-mix(in srgb, var(--uui-color-positive) 6%, transparent);
461
+ }
462
+
463
+ .property.removed {
464
+ box-shadow: inset 3px 0 0 var(--uui-color-danger);
465
+ background: color-mix(in srgb, var(--uui-color-danger) 6%, transparent);
466
+ }
467
+
468
+ .property.changed {
469
+ box-shadow: inset 3px 0 0 var(--uui-color-warning);
470
+ background: color-mix(in srgb, var(--uui-color-warning) 10%, transparent);
471
+ }
472
+
473
+ /* properties run edge to edge in their box, like the backoffice editor. */
474
+ .property {
475
+ padding: var(--uui-size-space-4) var(--uui-size-space-5) 0;
476
+ margin: 0 calc(-1 * var(--uui-size-space-5));
477
+ }
478
+
479
+ .property:first-child,
480
+ .headline + .property {
481
+ margin-top: calc(-1 * var(--uui-size-space-5));
482
+ }
483
+
484
+ .property:last-child {
485
+ margin-bottom: calc(-1 * var(--uui-size-space-5));
486
+ }
487
+
488
+ .property + .property {
489
+ border-top: 1px solid var(--uui-color-divider);
490
+ }
491
+
492
+ /* umb-property pads itself for a full workspace, tighten it up here. */
493
+ umb-property {
494
+ --uui-size-layout-1: var(--uui-size-space-4);
495
+ }
496
+
497
+ .property-meta {
498
+ display: flex;
499
+ flex-wrap: wrap;
500
+ align-items: center;
501
+ gap: var(--uui-size-space-2) var(--uui-size-space-3);
502
+ font-size: var(--uui-type-small-size);
503
+ color: var(--uui-color-text-alt);
504
+ }
505
+
506
+ .property-meta code {
507
+ color: var(--uui-color-text);
508
+ }
509
+
510
+ .inherited {
511
+ font-style: italic;
512
+ color: var(--uui-color-text-alt);
513
+ }
514
+
515
+ .empty {
516
+ margin: 0;
517
+ color: var(--uui-color-text-alt);
518
+ }
519
+ `;
520
+ __decorate([
521
+ property({ type: Object })
522
+ ], uSyncContentTypePreviewElement.prototype, "preview", void 0);
523
+ __decorate([
524
+ state()
525
+ ], uSyncContentTypePreviewElement.prototype, "_activeTab", void 0);
526
+ uSyncContentTypePreviewElement = __decorate([
527
+ customElement('usync-content-type-preview')
528
+ ], uSyncContentTypePreviewElement);
529
+ export { uSyncContentTypePreviewElement };
530
+ export default uSyncContentTypePreviewElement;
@@ -0,0 +1,21 @@
1
+ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
2
+ import { 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 data type side by side,
7
+ * rendered with the real property editor, so you can see what an import
8
+ * will do before running it.
9
+ */
10
+ export declare class uSyncDataTypePreviewElement extends UmbLitElement {
11
+ #private;
12
+ preview?: SyncItemPreviewResponse;
13
+ render(): typeof nothing | import("lit-html").TemplateResult<1>;
14
+ static styles: import("lit").CSSResult;
15
+ }
16
+ export default uSyncDataTypePreviewElement;
17
+ declare global {
18
+ interface HTMLElementTagNameMap {
19
+ 'usync-data-type-preview': uSyncDataTypePreviewElement;
20
+ }
21
+ }