@umbraco-cms/backoffice 16.0.0-rc4 → 16.0.0-rc5

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 (50) hide show
  1. package/dist-cms/assets/lang/en-us.js +1 -1
  2. package/dist-cms/assets/lang/en-us.ts +1 -1
  3. package/dist-cms/css/uui-css.css +59 -8
  4. package/dist-cms/custom-elements.json +13 -2
  5. package/dist-cms/external/rxjs/index.d.ts +1 -1
  6. package/dist-cms/external/rxjs/index.js +3 -3
  7. package/dist-cms/external/uui/index.js +293 -57
  8. package/dist-cms/libs/extension-api/controller/server-extension-registrator.controller.js +6 -2
  9. package/dist-cms/packages/content/content/components/property-type-based-property/property-type-based-property.context-token.js +1 -1
  10. package/dist-cms/packages/core/collection/components/collection-filter-field.element.js +1 -1
  11. package/dist-cms/packages/core/localization/manifests.js +27 -27
  12. package/dist-cms/packages/core/localization/registry/localization.registry.d.ts +2 -1
  13. package/dist-cms/packages/core/localization/registry/localization.registry.js +97 -37
  14. package/dist-cms/packages/core/menu/menu-variant-tree-structure-workspace-context-base.js +2 -2
  15. package/dist-cms/packages/core/package.json +2 -2
  16. package/dist-cms/packages/core/property/components/property/property.element.js +1 -0
  17. package/dist-cms/packages/core/property-editor/extensions/property-editor-ui-element.interface.d.ts +2 -0
  18. package/dist-cms/packages/core/router/route/router-slot.element.js +3 -1
  19. package/dist-cms/packages/core/workspace/components/workspace-breadcrumb/workspace-variant-menu-breadcrumb/workspace-variant-menu-breadcrumb.element.js +5 -2
  20. package/dist-cms/packages/core/workspace/contexts/tokens/submittable-tree-entity-workspace.context-token.js +1 -1
  21. package/dist-cms/packages/documents/documents/entity-actions/create-blueprint/modal/create-blueprint-modal.element.js +1 -1
  22. package/dist-cms/packages/documents/documents/tree/document-tree.context.js +2 -2
  23. package/dist-cms/packages/log-viewer/components/log-viewer-date-range-selector.element.d.ts +0 -2
  24. package/dist-cms/packages/log-viewer/components/log-viewer-date-range-selector.element.js +12 -24
  25. package/dist-cms/packages/log-viewer/repository/sources/log-viewer.server.data.js +9 -1
  26. package/dist-cms/packages/log-viewer/workspace/views/search/components/log-viewer-message.element.js +1 -1
  27. package/dist-cms/packages/media/media/modals/media-picker/media-picker-modal.element.js +2 -2
  28. package/dist-cms/packages/media/media/tree/media-tree.context.js +2 -2
  29. package/dist-cms/packages/property-editors/dimensions/property-editor-ui-dimensions.element.js +16 -3
  30. package/dist-cms/packages/templating/partial-views/entity-actions/rename/rename-partial-view.server.data-source.js +1 -1
  31. package/dist-cms/packages/templating/partial-views/repository/partial-view-detail.server.data-source.js +3 -3
  32. package/dist-cms/packages/templating/partial-views/tree/folder/repository/partial-view-folder.server.data-source.js +2 -2
  33. package/dist-cms/packages/templating/scripts/entity-actions/rename/rename-script.server.data-source.js +1 -1
  34. package/dist-cms/packages/templating/scripts/repository/script-detail.server.data-source.js +3 -3
  35. package/dist-cms/packages/templating/scripts/tree/folder/repository/script-folder.server.data-source.js +2 -2
  36. package/dist-cms/packages/templating/stylesheets/entity-actions/rename/rename-stylesheet.server.data-source.js +1 -1
  37. package/dist-cms/packages/templating/stylesheets/repository/stylesheet-detail.server.data-source.js +3 -3
  38. package/dist-cms/packages/templating/stylesheets/tree/folder/repository/stylesheet-folder.server.data-source.js +2 -2
  39. package/dist-cms/packages/tiptap/components/character-map/character-map-modal.element.js +0 -4
  40. package/dist-cms/packages/tiptap/components/input-tiptap/input-tiptap.element.js +1 -1
  41. package/dist-cms/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.d.ts +6 -0
  42. package/dist-cms/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.js +7 -1
  43. package/dist-cms/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.js +1 -1
  44. package/dist-cms/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-statusbar-configuration.element.js +0 -4
  45. package/dist-cms/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.js +1 -4
  46. package/dist-cms/packages/user/user-group/collection/user-group-collection.element.js +1 -1
  47. package/dist-cms/tsconfig.build.tsbuildinfo +1 -1
  48. package/dist-cms/umbraco-package.json +1 -1
  49. package/dist-cms/vscode-html-custom-data.json +2 -2
  50. package/package.json +5 -4
@@ -27,7 +27,9 @@ export class UmbServerExtensionRegistrator extends UmbControllerBase {
27
27
  * @remark Users must have the BACKOFFICE_ACCESS permission to access this method.
28
28
  */
29
29
  async registerPrivateExtensions() {
30
- const { data: packages } = await tryExecute(this, ManifestService.getManifestManifestPrivate());
30
+ const { data: packages } = await tryExecute(this, ManifestService.getManifestManifestPrivate(), {
31
+ disableNotifications: true,
32
+ });
31
33
  if (packages) {
32
34
  await this.#loadServerPackages(packages);
33
35
  }
@@ -38,7 +40,9 @@ export class UmbServerExtensionRegistrator extends UmbControllerBase {
38
40
  * @remark Any user can access this method without any permissions.
39
41
  */
40
42
  async registerPublicExtensions() {
41
- const { data: packages } = await tryExecute(this, ManifestService.getManifestManifestPublic());
43
+ const { data: packages } = await tryExecute(this, ManifestService.getManifestManifestPublic(), {
44
+ disableNotifications: true,
45
+ });
42
46
  if (packages) {
43
47
  await this.#loadServerPackages(packages);
44
48
  }
@@ -4,4 +4,4 @@ export const UMB_PROPERTY_TYPE_BASED_PROPERTY_CONTEXT = new UmbContextToken('Umb
4
4
  * @deprecated Use `UMB_PROPERTY_TYPE_BASED_PROPERTY_CONTEXT` instead.
5
5
  * This will be removed in v.18
6
6
  */
7
- export const UMB_CONTENT_PROPERTY_CONTEXT = new UmbContextToken('UmbContentPropertyContext');
7
+ export const UMB_CONTENT_PROPERTY_CONTEXT = new UmbContextToken('UmbPropertyTypeBasedPropertyContext');
@@ -32,7 +32,7 @@ let UmbCollectionFilterFieldElement = class UmbCollectionFilterFieldElement exte
32
32
  static { this.styles = [
33
33
  css `
34
34
  uui-input {
35
- display: block;
35
+ width: 100%;
36
36
  }
37
37
  `,
38
38
  ]; }
@@ -2,7 +2,7 @@ export const manifests = [
2
2
  {
3
3
  type: 'localization',
4
4
  alias: 'Umb.Localization.AR',
5
- weight: -100,
5
+ weight: 100,
6
6
  name: 'Arabic Backoffice UI Localization',
7
7
  meta: {
8
8
  culture: 'ar',
@@ -12,7 +12,7 @@ export const manifests = [
12
12
  {
13
13
  type: 'localization',
14
14
  alias: 'Umb.Localization.BS',
15
- weight: -100,
15
+ weight: 100,
16
16
  name: 'Bosnian Backoffice UI Localization',
17
17
  meta: {
18
18
  culture: 'bs',
@@ -22,7 +22,7 @@ export const manifests = [
22
22
  {
23
23
  type: 'localization',
24
24
  alias: 'Umb.Localization.CS',
25
- weight: -100,
25
+ weight: 100,
26
26
  name: 'Czech Backoffice UI Localization',
27
27
  meta: {
28
28
  culture: 'cs',
@@ -32,7 +32,7 @@ export const manifests = [
32
32
  {
33
33
  type: 'localization',
34
34
  alias: 'Umb.Localization.CY',
35
- weight: -100,
35
+ weight: 100,
36
36
  name: 'Welsh Backoffice UI Localization',
37
37
  meta: {
38
38
  culture: 'cy',
@@ -42,7 +42,7 @@ export const manifests = [
42
42
  {
43
43
  type: 'localization',
44
44
  alias: 'Umb.Localization.DA',
45
- weight: -100,
45
+ weight: 100,
46
46
  name: 'Danish Backoffice UI Localization',
47
47
  meta: {
48
48
  culture: 'da',
@@ -52,7 +52,7 @@ export const manifests = [
52
52
  {
53
53
  type: 'localization',
54
54
  alias: 'Umb.Localization.DE',
55
- weight: -100,
55
+ weight: 100,
56
56
  name: 'German Backoffice UI Localization',
57
57
  meta: {
58
58
  culture: 'de',
@@ -62,7 +62,7 @@ export const manifests = [
62
62
  {
63
63
  type: 'localization',
64
64
  alias: 'Umb.Localization.EN',
65
- weight: -100,
65
+ weight: 100,
66
66
  name: 'English (United Kingdom) Backoffice UI Localization',
67
67
  meta: {
68
68
  culture: 'en',
@@ -72,7 +72,7 @@ export const manifests = [
72
72
  {
73
73
  type: 'localization',
74
74
  alias: 'Umb.Localization.EN_US',
75
- weight: -100,
75
+ weight: 100,
76
76
  name: 'English (United States) Backoffice UI Localization',
77
77
  meta: {
78
78
  culture: 'en-US',
@@ -82,7 +82,7 @@ export const manifests = [
82
82
  {
83
83
  type: 'localization',
84
84
  alias: 'Umb.Localization.ES',
85
- weight: -100,
85
+ weight: 100,
86
86
  name: 'Spanish Backoffice UI Localization',
87
87
  meta: {
88
88
  culture: 'es',
@@ -92,7 +92,7 @@ export const manifests = [
92
92
  {
93
93
  type: 'localization',
94
94
  alias: 'Umb.Localization.FR',
95
- weight: -100,
95
+ weight: 100,
96
96
  name: 'French Backoffice UI Localization',
97
97
  meta: {
98
98
  culture: 'fr',
@@ -102,7 +102,7 @@ export const manifests = [
102
102
  {
103
103
  type: 'localization',
104
104
  alias: 'Umb.Localization.HE',
105
- weight: -100,
105
+ weight: 100,
106
106
  name: 'Hebrew Backoffice UI Localization',
107
107
  meta: {
108
108
  culture: 'he',
@@ -112,7 +112,7 @@ export const manifests = [
112
112
  {
113
113
  type: 'localization',
114
114
  alias: 'Umb.Localization.HR',
115
- weight: -100,
115
+ weight: 100,
116
116
  name: 'Croatian Backoffice UI Localization',
117
117
  meta: {
118
118
  culture: 'hr',
@@ -122,7 +122,7 @@ export const manifests = [
122
122
  {
123
123
  type: 'localization',
124
124
  alias: 'Umb.Localization.IT',
125
- weight: -100,
125
+ weight: 100,
126
126
  name: 'Italian Backoffice UI Localization',
127
127
  meta: {
128
128
  culture: 'it',
@@ -132,7 +132,7 @@ export const manifests = [
132
132
  {
133
133
  type: 'localization',
134
134
  alias: 'Umb.Localization.JA',
135
- weight: -100,
135
+ weight: 100,
136
136
  name: 'Japanese Backoffice UI Localization',
137
137
  meta: {
138
138
  culture: 'ja',
@@ -142,7 +142,7 @@ export const manifests = [
142
142
  {
143
143
  type: 'localization',
144
144
  alias: 'Umb.Localization.KO',
145
- weight: -100,
145
+ weight: 100,
146
146
  name: 'Korean Backoffice UI Localization',
147
147
  meta: {
148
148
  culture: 'ko',
@@ -152,7 +152,7 @@ export const manifests = [
152
152
  {
153
153
  type: 'localization',
154
154
  alias: 'Umb.Localization.NB',
155
- weight: -100,
155
+ weight: 100,
156
156
  name: 'Norwegian Backoffice UI Localization',
157
157
  meta: {
158
158
  culture: 'nb',
@@ -162,7 +162,7 @@ export const manifests = [
162
162
  {
163
163
  type: 'localization',
164
164
  alias: 'Umb.Localization.NL',
165
- weight: -100,
165
+ weight: 100,
166
166
  name: 'Dutch Backoffice UI Localization',
167
167
  meta: {
168
168
  culture: 'nl',
@@ -172,7 +172,7 @@ export const manifests = [
172
172
  {
173
173
  type: 'localization',
174
174
  alias: 'Umb.Localization.PL',
175
- weight: -100,
175
+ weight: 100,
176
176
  name: 'Polish Backoffice UI Localization',
177
177
  meta: {
178
178
  culture: 'pl',
@@ -182,7 +182,7 @@ export const manifests = [
182
182
  {
183
183
  type: 'localization',
184
184
  alias: 'Umb.Localization.PT',
185
- weight: -100,
185
+ weight: 100,
186
186
  name: 'Portuguese Backoffice UI Localization',
187
187
  meta: {
188
188
  culture: 'pt',
@@ -192,7 +192,7 @@ export const manifests = [
192
192
  {
193
193
  type: 'localization',
194
194
  alias: 'Umb.Localization.PT_BR',
195
- weight: -100,
195
+ weight: 100,
196
196
  name: 'Portuguese (Brazil) Backoffice UI Localization',
197
197
  meta: {
198
198
  culture: 'pt-BR',
@@ -202,7 +202,7 @@ export const manifests = [
202
202
  {
203
203
  type: 'localization',
204
204
  alias: 'Umb.Localization.RO',
205
- weight: -100,
205
+ weight: 100,
206
206
  name: 'Romanian Backoffice UI Localization',
207
207
  meta: {
208
208
  culture: 'ro',
@@ -212,7 +212,7 @@ export const manifests = [
212
212
  {
213
213
  type: 'localization',
214
214
  alias: 'Umb.Localization.RU',
215
- weight: -100,
215
+ weight: 100,
216
216
  name: 'Russian Backoffice UI Localization',
217
217
  meta: {
218
218
  culture: 'ru',
@@ -222,7 +222,7 @@ export const manifests = [
222
222
  {
223
223
  type: 'localization',
224
224
  alias: 'Umb.Localization.SV',
225
- weight: -100,
225
+ weight: 100,
226
226
  name: 'Swedish Backoffice UI Localization',
227
227
  meta: {
228
228
  culture: 'sv',
@@ -232,7 +232,7 @@ export const manifests = [
232
232
  {
233
233
  type: 'localization',
234
234
  alias: 'Umb.Localization.TR',
235
- weight: -100,
235
+ weight: 100,
236
236
  name: 'Turkish Backoffice UI Localization',
237
237
  meta: {
238
238
  culture: 'tr',
@@ -242,7 +242,7 @@ export const manifests = [
242
242
  {
243
243
  type: 'localization',
244
244
  alias: 'Umb.Localization.UK',
245
- weight: -100,
245
+ weight: 100,
246
246
  name: 'Ukrainian Backoffice UI Localization',
247
247
  meta: {
248
248
  culture: 'uk',
@@ -252,7 +252,7 @@ export const manifests = [
252
252
  {
253
253
  type: 'localization',
254
254
  alias: 'Umb.Localization.ZH',
255
- weight: -100,
255
+ weight: 100,
256
256
  name: 'Chinese Backoffice UI Localization',
257
257
  meta: {
258
258
  culture: 'zh',
@@ -262,7 +262,7 @@ export const manifests = [
262
262
  {
263
263
  type: 'localization',
264
264
  alias: 'Umb.Localization.ZH_TW',
265
- weight: -100,
265
+ weight: 100,
266
266
  name: 'Chinese (Taiwan) Backoffice UI Localization',
267
267
  meta: {
268
268
  culture: 'zh-TW',
@@ -1,5 +1,5 @@
1
- import { type UmbLocalizationSetBase } from '@umbraco-cms/backoffice/localization-api';
2
1
  import type { UmbBackofficeExtensionRegistry } from '@umbraco-cms/backoffice/extension-registry';
2
+ import type { UmbLocalizationSetBase } from '@umbraco-cms/backoffice/localization-api';
3
3
  export declare class UmbLocalizationRegistry {
4
4
  #private;
5
5
  readonly currentLanguage: import("rxjs").Observable<string>;
@@ -14,5 +14,6 @@ export declare class UmbLocalizationRegistry {
14
14
  * @param {string} locale The locale to load.
15
15
  */
16
16
  loadLanguage(locale: string): void;
17
+ destroy(): void;
17
18
  }
18
19
  export declare const umbLocalizationRegistry: UmbLocalizationRegistry;
@@ -1,14 +1,13 @@
1
- import { UMB_DEFAULT_LOCALIZATION_CULTURE, } from '@umbraco-cms/backoffice/localization-api';
2
- import { umbLocalizationManager } from '@umbraco-cms/backoffice/localization-api';
1
+ import { catchError, distinctUntilChanged, filter, from, map, of, switchMap, } from '@umbraco-cms/backoffice/external/rxjs';
2
+ import { hasDefaultExport, loadManifestPlainJs } from '@umbraco-cms/backoffice/extension-api';
3
3
  import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
4
+ import { umbLocalizationManager, UMB_DEFAULT_LOCALIZATION_CULTURE } from '@umbraco-cms/backoffice/localization-api';
4
5
  import { UmbStringState } from '@umbraco-cms/backoffice/observable-api';
5
- import { combineLatest } from '@umbraco-cms/backoffice/external/rxjs';
6
- import { hasDefaultExport, loadManifestPlainJs } from '@umbraco-cms/backoffice/extension-api';
7
6
  /**
8
- *
9
- * @param innerDictionary
10
- * @param dictionaryName
11
- * @param dictionary
7
+ * Adds or updates a dictionary in the inner dictionary.
8
+ * @param {UmbLocalizationFlatDictionary} innerDictionary The inner dictionary to add or update the dictionary in.
9
+ * @param {string} dictionaryName The name of the dictionary to add or update.
10
+ * @param {UmbLocalizationDictionary['value']} dictionary The dictionary to add or update.
12
11
  */
13
12
  function addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary) {
14
13
  for (const [key, value] of Object.entries(dictionary)) {
@@ -17,7 +16,6 @@ function addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary) {
17
16
  }
18
17
  export class UmbLocalizationRegistry {
19
18
  #currentLanguage;
20
- #loadedExtAliases;
21
19
  /**
22
20
  * Get the current registered translations.
23
21
  * @returns {Map<string, UmbLocalizationSetBase>} Returns the registered translations
@@ -25,12 +23,11 @@ export class UmbLocalizationRegistry {
25
23
  get localizations() {
26
24
  return umbLocalizationManager.localizations;
27
25
  }
26
+ #subscription;
28
27
  constructor(extensionRegistry) {
29
28
  this.#currentLanguage = new UmbStringState(document.documentElement.lang !== '' ? document.documentElement.lang : UMB_DEFAULT_LOCALIZATION_CULTURE);
30
29
  this.currentLanguage = this.#currentLanguage.asObservable();
31
- this.#loadedExtAliases = [];
32
30
  this.#loadExtension = async (extension) => {
33
- this.#loadedExtAliases.push(extension.alias);
34
31
  const innerDictionary = {};
35
32
  // If extension contains a dictionary, add it to the inner dictionary.
36
33
  if (extension.meta.localizations) {
@@ -51,46 +48,109 @@ export class UmbLocalizationRegistry {
51
48
  return {
52
49
  $code: extension.meta.culture.toLowerCase(),
53
50
  $dir: extension.meta.direction ?? 'ltr',
51
+ $weight: extension.weight ?? 100,
54
52
  ...innerDictionary,
55
53
  };
56
54
  };
57
- combineLatest([this.currentLanguage, extensionRegistry.byType('localization')]).subscribe(async ([currentLanguage, extensions]) => {
58
- const locale = new Intl.Locale(currentLanguage);
59
- const currentLanguageExtensions = extensions.filter((ext) => ext.meta.culture.toLowerCase() === locale.baseName.toLowerCase() ||
60
- ext.meta.culture.toLowerCase() === locale.language.toLowerCase());
61
- // If there are no extensions for the current language, return early
62
- if (!currentLanguageExtensions.length)
63
- return;
64
- // Register the new translations only if they have not been registered before
65
- const diff = currentLanguageExtensions.filter((ext) => !this.#loadedExtAliases.includes(ext.alias));
55
+ // Store the locale in a variable to use when setting the document language and direction
56
+ let locale = undefined;
57
+ this.#subscription = this.currentLanguage
58
+ .pipe(
59
+ // Ensure the current language is not empty
60
+ filter((currentLanguage) => !!currentLanguage),
61
+ // Use distinctUntilChanged to avoid unnecessary re-renders when the language hasn't changed
62
+ distinctUntilChanged(),
63
+ // Switch to the extensions registry to get the current language and the extensions for that language
64
+ // Note: This also cancels the previous subscription if the language changes
65
+ switchMap((currentLanguage) => {
66
+ return extensionRegistry.byType('localization').pipe(
67
+ // Filter the extensions to only those that match the current language
68
+ map((extensions) => {
69
+ locale = new Intl.Locale(currentLanguage);
70
+ return extensions.filter((ext) => ext.meta.culture.toLowerCase() === locale.baseName.toLowerCase() ||
71
+ ext.meta.culture.toLowerCase() === locale.language.toLowerCase());
72
+ }));
73
+ }),
74
+ // Ensure we only process extensions that are registered
75
+ filter((extensions) => extensions.length > 0),
76
+ // Ensure we only process extensions that have not been loaded before
77
+ distinctUntilChanged((prev, curr) => {
78
+ const prevAliases = prev.map((ext) => ext.alias).sort();
79
+ const currAliases = curr.map((ext) => ext.alias).sort();
80
+ return this.#arraysEqual(prevAliases, currAliases);
81
+ }),
82
+ // With switchMap, if a new language is selected before the previous translations finish loading,
83
+ // the previous promise is canceled (unsubscribed), and only the latest one is processed.
84
+ // This prevents race conditions and stale state.
85
+ switchMap((extensions) => from((async () => {
66
86
  // Load all localizations
67
- const translations = await Promise.all(currentLanguageExtensions.map(this.#loadExtension));
87
+ const translations = await Promise.all(extensions.map(this.#loadExtension));
68
88
  // If there are no translations, return early
69
89
  if (!translations.length)
70
90
  return;
71
- if (diff.length) {
72
- const filteredTranslations = translations.filter((t) => diff.some((ext) => ext.meta.culture.toLowerCase() === t.$code));
73
- umbLocalizationManager.registerManyLocalizations(filteredTranslations);
74
- }
75
- // Set the document language
76
- const newLang = locale.baseName.toLowerCase();
77
- if (document.documentElement.lang.toLowerCase() !== newLang) {
78
- document.documentElement.lang = newLang;
79
- }
80
- // Set the document direction to the direction of the primary language
81
- const newDir = translations[0].$dir ?? 'ltr';
82
- if (document.documentElement.dir !== newDir) {
83
- document.documentElement.dir = newDir;
84
- }
85
- });
91
+ // Sort translations by their original extension weight (highest-to-lowest)
92
+ // This ensures that the translations with the lowest weight override the others
93
+ translations.sort((a, b) => b.$weight - a.$weight);
94
+ // Load the translations into the localization manager
95
+ umbLocalizationManager.registerManyLocalizations(translations);
96
+ // Set the browser language and direction based on the translations
97
+ this.#setBrowserLanguage(locale, translations);
98
+ })())),
99
+ // Catch any errors that occur while loading the translations
100
+ // This is important to ensure that the observable does not error out and stop the subscription
101
+ catchError((error) => {
102
+ console.error('Error loading translations:', error);
103
+ return of([]);
104
+ }))
105
+ // Subscribe to the observable to trigger the loading of translations
106
+ .subscribe();
86
107
  }
87
108
  #loadExtension;
109
+ #setBrowserLanguage(locale, translations) {
110
+ // Set the document language
111
+ const newLang = locale.baseName.toLowerCase();
112
+ if (document.documentElement.lang.toLowerCase() !== newLang) {
113
+ document.documentElement.lang = newLang;
114
+ }
115
+ // We need to find the direction of the new language, so we look for the best match
116
+ // If the new language is not found, we default to 'ltr'
117
+ const reverseTranslations = translations.slice().reverse();
118
+ // Look for a direct match first
119
+ const directMatch = reverseTranslations.find((t) => t.$code.toLowerCase() === newLang);
120
+ if (directMatch) {
121
+ document.documentElement.dir = directMatch.$dir;
122
+ return;
123
+ }
124
+ // If no direct match, look for a match with the language code only
125
+ const langOnlyDirectMatch = reverseTranslations.find((t) => t.$code.toLowerCase() === locale.language.toLowerCase());
126
+ if (langOnlyDirectMatch) {
127
+ document.documentElement.dir = langOnlyDirectMatch.$dir;
128
+ return;
129
+ }
130
+ // If no match is found, default to 'ltr'
131
+ if (document.documentElement.dir !== 'ltr') {
132
+ document.documentElement.dir = 'ltr';
133
+ }
134
+ }
135
+ #arraysEqual(a, b) {
136
+ if (a.length !== b.length)
137
+ return false;
138
+ for (let i = 0; i < a.length; i++) {
139
+ if (a[i] !== b[i])
140
+ return false;
141
+ }
142
+ return true;
143
+ }
88
144
  /**
89
145
  * Load a language from the extension registry.
90
146
  * @param {string} locale The locale to load.
91
147
  */
92
148
  loadLanguage(locale) {
93
- this.#currentLanguage.setValue(locale.toLowerCase());
149
+ const canonicalLocale = Intl.getCanonicalLocales(locale)[0];
150
+ this.#currentLanguage.setValue(canonicalLocale);
151
+ }
152
+ destroy() {
153
+ this.#subscription.unsubscribe();
94
154
  }
95
155
  }
96
156
  export const umbLocalizationRegistry = new UmbLocalizationRegistry(umbExtensionsRegistry);
@@ -40,10 +40,10 @@ export class UmbMenuVariantTreeStructureWorkspaceContextBase extends UmbContextB
40
40
  async #requestStructure() {
41
41
  const isNew = this.#workspaceContext?.getIsNew();
42
42
  const uniqueObservable = isNew
43
- ? this.#workspaceContext?._internal_createUnderParentEntityType
43
+ ? this.#workspaceContext?._internal_createUnderParentEntityUnique
44
44
  : this.#workspaceContext?.unique;
45
45
  const entityTypeObservable = isNew
46
- ? this.#workspaceContext?._internal_createUnderParentEntityUnique
46
+ ? this.#workspaceContext?._internal_createUnderParentEntityType
47
47
  : this.#workspaceContext?.entityType;
48
48
  let structureItems = [];
49
49
  const unique = (await this.observe(uniqueObservable, () => { })?.asPromise());
@@ -9,10 +9,10 @@
9
9
  "dependencies": {
10
10
  "@types/diff": "^7.0.2",
11
11
  "diff": "^7.0.0",
12
- "uuid": "^11.1.0"
12
+ "uuid": "^11.1.0",
13
+ "@hey-api/client-fetch": "^0.10.0"
13
14
  },
14
15
  "devDependencies": {
15
- "@hey-api/client-fetch": "^0.10.0",
16
16
  "@hey-api/openapi-ts": "^0.66.6"
17
17
  }
18
18
  }
@@ -225,6 +225,7 @@ let UmbPropertyElement = class UmbPropertyElement extends UmbLitElement {
225
225
  this._element.addEventListener('change', this._onPropertyEditorChange);
226
226
  this._element.addEventListener('property-value-change', this._onPropertyEditorChange);
227
227
  // No need to observe mandatory or label, as we already do so and set it on the _element if present: [NL]
228
+ this._element.manifest = manifest;
228
229
  this._element.mandatory = this._mandatory;
229
230
  this._element.name = this._label;
230
231
  // No need for a controller alias, as the clean is handled via the observer prop:
@@ -1,5 +1,7 @@
1
1
  import type { UmbPropertyEditorConfigCollection } from '../config/index.js';
2
+ import type { ManifestPropertyEditorUi } from './property-editor.extension.js';
2
3
  export interface UmbPropertyEditorUiElement extends HTMLElement {
4
+ manifest?: ManifestPropertyEditorUi;
3
5
  name?: string;
4
6
  value?: unknown;
5
7
  config?: UmbPropertyEditorConfigCollection;
@@ -93,9 +93,11 @@ let UmbRouterSlotElement = class UmbRouterSlotElement extends UmbLitElement {
93
93
  }
94
94
  }
95
95
  disconnectedCallback() {
96
- super.disconnectedCallback();
97
96
  window.removeEventListener('navigationsuccess', this._onNavigationChanged);
98
97
  this.#listening = false;
98
+ // Close modals opened by this router slot.
99
+ this.#routeContext._internal_modalRouterChanged(undefined);
100
+ super.disconnectedCallback();
99
101
  }
100
102
  firstUpdated(_changedProperties) {
101
103
  super.firstUpdated(_changedProperties);
@@ -45,9 +45,12 @@ let UmbWorkspaceVariantMenuBreadcrumbElement = class UmbWorkspaceVariantMenuBrea
45
45
  #observeStructure() {
46
46
  if (!this.#structureContext || !this.#workspaceContext)
47
47
  return;
48
- const isNew = this.#workspaceContext.getIsNew();
49
48
  this.observe(this.#structureContext.structure, (value) => {
50
- this._structure = isNew ? value : value.slice(0, -1);
49
+ if (!this.#workspaceContext)
50
+ return;
51
+ const unique = this.#workspaceContext.getUnique();
52
+ // exclude the current unique from the structure. We append this with an observer of the name
53
+ this._structure = value.filter((structureItem) => structureItem.unique !== unique);
51
54
  });
52
55
  }
53
56
  #observeDefaultCulture() {
@@ -1,2 +1,2 @@
1
1
  import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
2
- export const UMB_SUBMITTABLE_TREE_ENTITY_WORKSPACE_CONTEXT = new UmbContextToken('UmbWorkspaceContext', undefined, (context) => 'requestSubmit' in context && 'createUnderParent' in context);
2
+ export const UMB_SUBMITTABLE_TREE_ENTITY_WORKSPACE_CONTEXT = new UmbContextToken('UmbWorkspaceContext', undefined, (context) => 'requestSubmit' in context && '_internal_createUnderParent' in context);
@@ -71,7 +71,7 @@ let UmbCreateBlueprintModalElement = class UmbCreateBlueprintModalElement extend
71
71
  strong,
72
72
  uui-label,
73
73
  uui-input {
74
- display: block;
74
+ width: 100%;
75
75
  }
76
76
 
77
77
  uui-label {
@@ -1,9 +1,9 @@
1
- import { UMB_CONTENT_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/content';
1
+ import { UMB_PROPERTY_TYPE_BASED_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/content';
2
2
  import { UmbDefaultTreeContext } from '@umbraco-cms/backoffice/tree';
3
3
  export class UmbDocumentTreeContext extends UmbDefaultTreeContext {
4
4
  constructor(host) {
5
5
  super(host);
6
- this.consumeContext(UMB_CONTENT_PROPERTY_CONTEXT, (context) => {
6
+ this.consumeContext(UMB_PROPERTY_TYPE_BASED_PROPERTY_CONTEXT, (context) => {
7
7
  this.observe(context?.dataType, (value) => {
8
8
  this.updateAdditionalRequestArgs({ dataType: value });
9
9
  });
@@ -3,10 +3,8 @@ export declare class UmbLogViewerDateRangeSelectorElement extends UmbLitElement
3
3
  #private;
4
4
  private _startDate;
5
5
  private _endDate;
6
- private _inputs;
7
6
  horizontal: boolean;
8
7
  constructor();
9
- disconnectedCallback(): void;
10
8
  render(): import("lit-html").TemplateResult<1>;
11
9
  static styles: import("lit").CSSResult[];
12
10
  }