@umbraco-cms/backoffice 14.0.0--preview005-2dd3b083 → 14.0.0--preview005-7ef2bd26

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 (56) hide show
  1. package/dist-cms/apps/app/app.element.js +19 -15
  2. package/dist-cms/custom-elements.json +40 -6
  3. package/dist-cms/libs/element-api/element.mixin.d.ts +3 -3
  4. package/dist-cms/libs/element-api/element.mixin.js +2 -2
  5. package/dist-cms/libs/extension-api/registry/extension.registry.d.ts +19 -0
  6. package/dist-cms/libs/extension-api/registry/extension.registry.js +42 -1
  7. package/dist-cms/libs/localization-api/index.d.ts +2 -2
  8. package/dist-cms/libs/localization-api/index.js +2 -2
  9. package/dist-cms/libs/localization-api/{localize.controller.d.ts → localization.controller.d.ts} +6 -4
  10. package/dist-cms/libs/localization-api/{localize.controller.js → localization.controller.js} +34 -24
  11. package/dist-cms/libs/localization-api/localization.manager.d.ts +29 -0
  12. package/dist-cms/libs/localization-api/localization.manager.js +94 -0
  13. package/dist-cms/mocks/data/data-type/data-type.data.js +7 -0
  14. package/dist-cms/mocks/data/document-type/document-type.data.js +26 -0
  15. package/dist-cms/packages/block/block/workspace/block-workspace.context.js +0 -1
  16. package/dist-cms/packages/block/block-grid/property-editors/block-grid-group-configuration/manifests.d.ts +2 -0
  17. package/dist-cms/packages/block/block-grid/property-editors/block-grid-group-configuration/manifests.js +11 -0
  18. package/dist-cms/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.d.ts +19 -0
  19. package/dist-cms/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.js +61 -0
  20. package/dist-cms/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.d.ts +10 -3
  21. package/dist-cms/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.js +130 -11
  22. package/dist-cms/packages/block/block-grid/property-editors/manifests.js +8 -1
  23. package/dist-cms/packages/block/block-grid/types.d.ts +9 -2
  24. package/dist-cms/packages/block/block-grid/types.js +1 -1
  25. package/dist-cms/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.d.ts +3 -0
  26. package/dist-cms/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.js +41 -3
  27. package/dist-cms/packages/block/block-list/types.d.ts +1 -0
  28. package/dist-cms/packages/block/block-list/types.js +1 -1
  29. package/dist-cms/packages/block/block-type/components/index.d.ts +1 -1
  30. package/dist-cms/packages/block/block-type/components/index.js +1 -1
  31. package/dist-cms/packages/block/block-type/components/input-block-type/input-block-type.element.d.ts +1 -3
  32. package/dist-cms/packages/block/block-type/components/input-block-type/input-block-type.element.js +42 -46
  33. package/dist-cms/packages/block/block-type/workspace/block-type-workspace.context.d.ts +4 -4
  34. package/dist-cms/packages/block/block-type/workspace/block-type-workspace.context.js +3 -1
  35. package/dist-cms/packages/block/block-type/workspace/block-type-workspace.element.js +4 -2
  36. package/dist-cms/packages/core/localization/registry/localization.registry.d.ts +3 -3
  37. package/dist-cms/packages/core/localization/registry/localization.registry.js +59 -60
  38. package/dist-cms/packages/core/tree/tree-menu-item-default/tree-menu-item-default.element.js +1 -1
  39. package/dist-cms/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.js +1 -1
  40. package/dist-cms/packages/media/media-types/workspace/views/design/media-type-workspace-view-edit.element.js +1 -1
  41. package/dist-cms/packages/user/current-user/current-user.context.js +2 -7
  42. package/dist-cms/shared/auth/auth-flow.d.ts +0 -2
  43. package/dist-cms/shared/auth/auth-flow.js +28 -9
  44. package/dist-cms/shared/auth/auth.context.d.ts +14 -5
  45. package/dist-cms/shared/auth/auth.context.js +15 -3
  46. package/dist-cms/shared/auth/auth.context.token.d.ts +4 -2
  47. package/dist-cms/shared/auth/auth.context.token.js +2 -0
  48. package/dist-cms/shared/auth/index.d.ts +0 -1
  49. package/dist-cms/shared/auth/index.js +0 -1
  50. package/dist-cms/tsconfig.build.tsbuildinfo +1 -1
  51. package/dist-cms/vscode-html-custom-data.json +23 -5
  52. package/package.json +1 -1
  53. package/dist-cms/libs/localization-api/manager.d.ts +0 -18
  54. package/dist-cms/libs/localization-api/manager.js +0 -40
  55. package/dist-cms/shared/auth/auth.context.interface.d.ts +0 -39
  56. package/dist-cms/shared/auth/auth.context.interface.js +0 -1
@@ -18,7 +18,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
18
18
  var _UmbAppElement_instances, _UmbAppElement_authContext, _UmbAppElement_umbIconRegistry, _UmbAppElement_uuiIconRegistry, _UmbAppElement_serverConnection, _UmbAppElement_setup, _UmbAppElement_setAuthStatus, _UmbAppElement_redirect, _UmbAppElement_isAuthorizedGuard, _UmbAppElement_errorPage;
19
19
  import { UmbAppContext } from './app.context.js';
20
20
  import { UmbServerConnection } from './server-connection.js';
21
- import { UmbAuthContext } from '../../shared/auth/index.js';
21
+ import { UMB_STORAGE_REDIRECT_URL, UmbAuthContext } from '../../shared/auth/index.js';
22
22
  import { css, html, customElement, property } from '../../external/lit/index.js';
23
23
  import { UUIIconRegistryEssential } from '../../external/uui/index.js';
24
24
  import { UmbIconRegistry } from '../../shared/icon-registry/index.js';
@@ -46,7 +46,6 @@ let UmbAppElement = class UmbAppElement extends UmbLitElement {
46
46
  /**
47
47
  * Bypass authentication.
48
48
  */
49
- // TODO: this might not be the right solution
50
49
  this.bypassAuth = false;
51
50
  this._routes = [
52
51
  {
@@ -141,6 +140,14 @@ async function _UmbAppElement_setAuthStatus() {
141
140
  OpenAPI.WITH_CREDENTIALS = true;
142
141
  };
143
142
  _UmbAppElement_redirect = function _UmbAppElement_redirect() {
143
+ // If there is a ?code parameter in the url, then we are in the middle of the oauth flow
144
+ // and we need to complete the login (the authorization notifier will redirect after this is done
145
+ // essentially hitting this method again)
146
+ const queryParams = new URLSearchParams(window.location.search);
147
+ if (queryParams.has('code')) {
148
+ __classPrivateFieldGet(this, _UmbAppElement_authContext, "f")?.completeAuthorizationRequest();
149
+ return;
150
+ }
144
151
  switch (__classPrivateFieldGet(this, _UmbAppElement_serverConnection, "f")?.getStatus()) {
145
152
  case RuntimeLevelModel.INSTALL:
146
153
  history.replaceState(null, '', 'install');
@@ -153,16 +160,14 @@ _UmbAppElement_redirect = function _UmbAppElement_redirect() {
153
160
  break;
154
161
  case RuntimeLevelModel.RUN: {
155
162
  const pathname = pathWithoutBasePath({ start: true, end: false });
156
- // If we are on the installer or upgrade page, redirect to the root
157
- // but if not, keep the current path but replace state anyway to initialize the router
158
- let currentRoute = location.href;
159
- const savedRoute = sessionStorage.getItem('umb:auth:redirect');
160
- if (savedRoute) {
161
- sessionStorage.removeItem('umb:auth:redirect');
162
- currentRoute = savedRoute;
163
+ // If we are on installer or upgrade page, redirect to the root since we are in the RUN state
164
+ if (pathname === '/install' || pathname === '/upgrade') {
165
+ history.replaceState(null, '', '/');
166
+ break;
163
167
  }
164
- const finalPath = pathname === '/install' || pathname === '/upgrade' ? '/' : currentRoute;
165
- history.replaceState(null, '', finalPath);
168
+ // Keep the current path but replace state anyway to initialize the router
169
+ // because the router will not initialize a wildcard route by itself
170
+ history.replaceState(null, '', location.href);
166
171
  break;
167
172
  }
168
173
  default:
@@ -179,10 +184,9 @@ _UmbAppElement_isAuthorizedGuard = function _UmbAppElement_isAuthorizedGuard() {
179
184
  return true;
180
185
  }
181
186
  // Save location.href so we can redirect to it after login
182
- window.sessionStorage.setItem('umb:auth:redirect', location.href);
187
+ window.sessionStorage.setItem(UMB_STORAGE_REDIRECT_URL, location.href);
183
188
  // Make a request to the auth server to start the auth flow
184
- // TODO: find better name for this method
185
- __classPrivateFieldGet(this, _UmbAppElement_authContext, "f").login();
189
+ __classPrivateFieldGet(this, _UmbAppElement_authContext, "f").makeAuthorizationRequest();
186
190
  // Return false to prevent the route from being rendered
187
191
  return false;
188
192
  };
@@ -219,7 +223,7 @@ __decorate([
219
223
  ], UmbAppElement.prototype, "serverUrl", void 0);
220
224
  __decorate([
221
225
  property({ type: String })
222
- // TODO: get from server config
226
+ // TODO: get from base element or maybe move to UmbAuthContext.#getRedirectUrl since it is only used there
223
227
  ], UmbAppElement.prototype, "backofficePath", void 0);
224
228
  __decorate([
225
229
  property({ type: Boolean })
@@ -504,6 +504,36 @@
504
504
  }
505
505
  ]
506
506
  },
507
+ {
508
+ "name": "umb-property-editor-ui-block-grid-group-configuration",
509
+ "path": "./../src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts",
510
+ "attributes": [
511
+ {
512
+ "name": "value",
513
+ "type": "UmbBlockGridGroupType[]"
514
+ }
515
+ ],
516
+ "properties": [
517
+ {
518
+ "name": "value",
519
+ "attribute": "value",
520
+ "type": "UmbBlockGridGroupType[]"
521
+ },
522
+ {
523
+ "name": "config"
524
+ },
525
+ {
526
+ "name": "styles",
527
+ "type": "array",
528
+ "default": "[\"UmbTextStyles\",null]"
529
+ }
530
+ ],
531
+ "events": [
532
+ {
533
+ "name": "property-value-change"
534
+ }
535
+ ]
536
+ },
507
537
  {
508
538
  "name": "umb-property-editor-ui-block-grid-layout-stylesheet",
509
539
  "path": "./../src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.element.ts",
@@ -540,8 +570,7 @@
540
570
  "properties": [
541
571
  {
542
572
  "name": "value",
543
- "type": "UmbBlockTypeBaseModel[]",
544
- "default": "[]"
573
+ "type": "UmbBlockTypeWithGroupKey[]"
545
574
  },
546
575
  {
547
576
  "name": "config"
@@ -549,7 +578,7 @@
549
578
  {
550
579
  "name": "styles",
551
580
  "type": "array",
552
- "default": "[\"UmbTextStyles\"]"
581
+ "default": "[\"UmbTextStyles\",null]"
553
582
  }
554
583
  ]
555
584
  },
@@ -722,7 +751,7 @@
722
751
  "path": "./../src/packages/block/block-type/components/input-block-type/input-block-type.element.ts",
723
752
  "attributes": [
724
753
  {
725
- "name": "entity-type",
754
+ "name": "workspacePath",
726
755
  "type": "string | undefined"
727
756
  }
728
757
  ],
@@ -732,8 +761,8 @@
732
761
  "type": "BlockType[]"
733
762
  },
734
763
  {
735
- "name": "entityType",
736
- "attribute": "entity-type",
764
+ "name": "workspacePath",
765
+ "attribute": "workspacePath",
737
766
  "type": "string | undefined"
738
767
  },
739
768
  {
@@ -741,6 +770,11 @@
741
770
  "type": "array",
742
771
  "default": "[null]"
743
772
  }
773
+ ],
774
+ "events": [
775
+ {
776
+ "name": "create"
777
+ }
744
778
  ]
745
779
  },
746
780
  {
@@ -1,4 +1,4 @@
1
- import { UmbLocalizeController } from '../localization-api/index.js';
1
+ import { UmbLocalizationController } from '../localization-api/index.js';
2
2
  import type { Observable } from '../../external/rxjs/index.js';
3
3
  import type { HTMLElementConstructor } from '../extension-api/index.js';
4
4
  import { type UmbControllerHostElement } from '../controller-api/index.js';
@@ -21,8 +21,8 @@ export declare class UmbElement extends UmbControllerHostElement {
21
21
  consumeContext<BaseType = unknown, ResultType extends BaseType = BaseType>(alias: string | UmbContextToken<BaseType, ResultType>, callback: UmbContextCallback<ResultType>): UmbContextConsumerController<BaseType, ResultType>;
22
22
  /**
23
23
  * Use the UmbLocalizeController to localize your element.
24
- * @see UmbLocalizeController
24
+ * @see UmbLocalizationController
25
25
  */
26
- localize: UmbLocalizeController;
26
+ localize: UmbLocalizationController;
27
27
  }
28
28
  export declare const UmbElementMixin: <T extends HTMLElementConstructor>(superClass: T) => HTMLElementConstructor<UmbElement> & T;
@@ -1,4 +1,4 @@
1
- import { UmbLocalizeController } from '../localization-api/index.js';
1
+ import { UmbLocalizationController } from '../localization-api/index.js';
2
2
  import { UmbControllerHostElementMixin } from '../controller-api/index.js';
3
3
  import { UmbContextConsumerController, UmbContextProviderController } from '../context-api/index.js';
4
4
  import { UmbObserverController } from '../observable-api/index.js';
@@ -6,7 +6,7 @@ export const UmbElementMixin = (superClass) => {
6
6
  class UmbElementMixinClass extends UmbControllerHostElementMixin(superClass) {
7
7
  constructor() {
8
8
  super(...arguments);
9
- this.localize = new UmbLocalizeController(this);
9
+ this.localize = new UmbLocalizationController(this);
10
10
  }
11
11
  /**
12
12
  * @description Observe a RxJS source of choice.
@@ -21,6 +21,25 @@ export declare class UmbExtensionRegistry<IncomingManifestTypes extends Manifest
21
21
  getByAlias<T extends ManifestBase = ManifestBase>(alias: string): Observable<T | undefined>;
22
22
  getByTypeAndAlias<Key extends keyof ManifestTypeMap<ManifestTypes> | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase<ManifestTypes, Key>>(type: Key, alias: string): Observable<T | undefined>;
23
23
  getByTypeAndAliases<Key extends keyof ManifestTypeMap<ManifestTypes> | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase<ManifestTypes, Key>>(type: Key, aliases: Array<string>): Observable<T[]>;
24
+ /**
25
+ * Get an observable of an extension by type and a given filter method.
26
+ * This will return the all extensions that matches the type and which filter method returns true.
27
+ * The filter method will be called for each extension manifest of the given type, and the first argument to it is the extension manifest.
28
+ * @param type {string} - The type of the extension to get
29
+ * @param filter {(ext: T): void} - The filter method to use to filter the extensions
30
+ * @returns {Observable<T | undefined>} - An observable of the extensions that matches the type and filter method
31
+ */
32
+ byTypeAndFilter<Key extends keyof ManifestTypeMap<ManifestTypes> | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase<ManifestTypes, Key>>(type: Key, filter: (ext: T) => boolean): Observable<T | undefined>;
33
+ /**
34
+ * Get an observable that provides extensions matching the given type.
35
+ * @param type {string} - The type of the extensions to get.
36
+ * @returns {Observable<T | undefined>} - An observable of the extensions that matches the type.
37
+ */
24
38
  extensionsOfType<Key extends keyof ManifestTypeMap<ManifestTypes> | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase<ManifestTypes, Key>>(type: Key): Observable<T[]>;
39
+ /**
40
+ * Get an observable that provides extensions matching given types.
41
+ * @param type {Array<string>} - The types of the extensions to get.
42
+ * @returns {Observable<T | undefined>} - An observable of the extensions that matches the types.
43
+ */
25
44
  extensionsOfTypes<ExtensionTypes extends ManifestBase = ManifestBase>(types: string[]): Observable<Array<ExtensionTypes>>;
26
45
  }
@@ -1,5 +1,5 @@
1
1
  import { UmbBasicState } from '../../observable-api/index.js';
2
- import { map, distinctUntilChanged, combineLatest, of, switchMap, } from '../../../external/rxjs/index.js';
2
+ import { map, distinctUntilChanged, combineLatest, of, switchMap } from '../../../external/rxjs/index.js';
3
3
  function extensionArrayMemoization(previousValue, currentValue) {
4
4
  // If length is different, data is different:
5
5
  if (previousValue.length !== currentValue.length) {
@@ -137,6 +137,7 @@ export class UmbExtensionRegistry {
137
137
  _extensionsOfTypes(types) {
138
138
  return this.extensions.pipe(map((exts) => exts.filter((ext) => types.indexOf(ext.type) !== -1)), distinctUntilChanged(extensionArrayMemoization));
139
139
  }
140
+ // TODO: get rid of the name get
140
141
  getByAlias(alias) {
141
142
  return this.extensions.pipe(map((exts) => exts.find((ext) => ext.alias === alias)), distinctUntilChanged(extensionSingleMemoization), switchMap((ext) => {
142
143
  if (ext?.kind) {
@@ -160,6 +161,7 @@ export class UmbExtensionRegistry {
160
161
  return of(ext);
161
162
  }), distinctUntilChanged(extensionAndKindMatchSingleMemoization));
162
163
  }
164
+ // TODO: get rid of the name get
163
165
  getByTypeAndAlias(type, alias) {
164
166
  return combineLatest([
165
167
  this.extensions.pipe(map((exts) => exts.find((ext) => ext.type === type && ext.alias === alias)), distinctUntilChanged(extensionSingleMemoization)),
@@ -180,6 +182,7 @@ export class UmbExtensionRegistry {
180
182
  return ext;
181
183
  }), distinctUntilChanged(extensionAndKindMatchSingleMemoization));
182
184
  }
185
+ // TODO: get rid of the name get
183
186
  getByTypeAndAliases(type, aliases) {
184
187
  return combineLatest([
185
188
  this.extensions.pipe(map((exts) => exts.filter((ext) => ext.type === type && aliases.indexOf(ext.alias) !== -1)), distinctUntilChanged(extensionArrayMemoization)),
@@ -199,6 +202,39 @@ export class UmbExtensionRegistry {
199
202
  })
200
203
  .sort(sortExtensions)), distinctUntilChanged(extensionAndKindMatchArrayMemoization));
201
204
  }
205
+ /**
206
+ * Get an observable of an extension by type and a given filter method.
207
+ * This will return the all extensions that matches the type and which filter method returns true.
208
+ * The filter method will be called for each extension manifest of the given type, and the first argument to it is the extension manifest.
209
+ * @param type {string} - The type of the extension to get
210
+ * @param filter {(ext: T): void} - The filter method to use to filter the extensions
211
+ * @returns {Observable<T | undefined>} - An observable of the extensions that matches the type and filter method
212
+ */
213
+ byTypeAndFilter(type, filter) {
214
+ return combineLatest([
215
+ this.extensions.pipe(map((exts) => exts.find((ext) => ext.type === type && filter(ext))), distinctUntilChanged(extensionSingleMemoization)),
216
+ this._kindsOfType(type),
217
+ ]).pipe(map(([ext, kinds]) => {
218
+ // TODO: share one merge function between the different methods of this class:
219
+ // Specific Extension Meta merge (does not merge conditions)
220
+ if (ext) {
221
+ const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest;
222
+ if (baseManifest) {
223
+ const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext };
224
+ if (baseManifest.meta) {
225
+ merged.meta = { ...baseManifest.meta, ...ext.meta };
226
+ }
227
+ return merged;
228
+ }
229
+ }
230
+ return ext;
231
+ }), distinctUntilChanged(extensionAndKindMatchSingleMemoization));
232
+ }
233
+ /**
234
+ * Get an observable that provides extensions matching the given type.
235
+ * @param type {string} - The type of the extensions to get.
236
+ * @returns {Observable<T | undefined>} - An observable of the extensions that matches the type.
237
+ */
202
238
  extensionsOfType(type) {
203
239
  return combineLatest([this._extensionsOfType(type), this._kindsOfType(type)]).pipe(map(([exts, kinds]) => exts
204
240
  .map((ext) => {
@@ -215,6 +251,11 @@ export class UmbExtensionRegistry {
215
251
  })
216
252
  .sort(sortExtensions)), distinctUntilChanged(extensionAndKindMatchArrayMemoization));
217
253
  }
254
+ /**
255
+ * Get an observable that provides extensions matching given types.
256
+ * @param type {Array<string>} - The types of the extensions to get.
257
+ * @returns {Observable<T | undefined>} - An observable of the extensions that matches the types.
258
+ */
218
259
  extensionsOfTypes(types) {
219
260
  return combineLatest([this._extensionsOfTypes(types), this._kindsOfTypes(types)]).pipe(map(([exts, kinds]) => exts
220
261
  .map((ext) => {
@@ -1,3 +1,3 @@
1
- export * from './localize.controller.js';
1
+ export * from './localization.controller.js';
2
2
  export * from './types/localization.js';
3
- export * from './manager.js';
3
+ export * from './localization.manager.js';
@@ -1,3 +1,3 @@
1
- export * from './localize.controller.js';
1
+ export * from './localization.controller.js';
2
2
  export * from './types/localization.js';
3
- export * from './manager.js';
3
+ export * from './localization.manager.js';
@@ -1,4 +1,4 @@
1
- import type { DefaultLocalizationSet, FunctionParams, LocalizationSet } from './manager.js';
1
+ import type { UmbLocalizationSet, FunctionParams, UmbLocalizationSetBase, UmbLocalizationSetKey } from './localization.manager.js';
2
2
  import type { UmbController, UmbControllerHost } from '../controller-api/index.js';
3
3
  /**
4
4
  * The UmbLocalizeController enables localization for your element.
@@ -18,13 +18,15 @@ import type { UmbController, UmbControllerHost } from '../controller-api/index.j
18
18
  * }
19
19
  * ```
20
20
  */
21
- export declare class UmbLocalizeController<LocalizationType extends LocalizationSet = DefaultLocalizationSet> implements UmbController {
21
+ export declare class UmbLocalizationController<LocalizationSetType extends UmbLocalizationSetBase = UmbLocalizationSet> implements UmbController {
22
22
  #private;
23
- controllerAlias: symbol;
23
+ readonly controllerAlias: symbol;
24
24
  constructor(host: UmbControllerHost);
25
25
  hostConnected(): void;
26
26
  hostDisconnected(): void;
27
27
  destroy(): void;
28
+ documentUpdate(): void;
29
+ keysChanged(changedKeys: Set<UmbLocalizationSetKey>): void;
28
30
  /**
29
31
  * Gets the host element's directionality as determined by the `dir` attribute. The return value is transformed to
30
32
  * lowercase.
@@ -37,7 +39,7 @@ export declare class UmbLocalizeController<LocalizationType extends Localization
37
39
  lang(): string;
38
40
  private getLocalizationData;
39
41
  /** Outputs a translated term. */
40
- term<K extends keyof LocalizationType>(key: K, ...args: FunctionParams<LocalizationType[K]>): string;
42
+ term<K extends keyof LocalizationSetType>(key: K, ...args: FunctionParams<LocalizationSetType[K]>): string;
41
43
  /** Outputs a localized date in the specified format. */
42
44
  date(dateToFormat: Date | string, options?: Intl.DateTimeFormatOptions): string;
43
45
  /** Outputs a localized number in the specified format. */
@@ -9,9 +9,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  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");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _UmbLocalizeController_host, _UmbLocalizeController_hostEl;
13
- import { connectedElements, documentDirection, documentLanguage, fallback, localizations, } from './manager.js';
14
- const LocalizeControllerAlias = Symbol();
12
+ var _UmbLocalizationController_host, _UmbLocalizationController_hostEl, _UmbLocalizationController_usedKeys;
13
+ import { umbLocalizationManager } from './localization.manager.js';
14
+ const LocalizationControllerAlias = Symbol();
15
15
  /**
16
16
  * The UmbLocalizeController enables localization for your element.
17
17
  *
@@ -30,52 +30,62 @@ const LocalizeControllerAlias = Symbol();
30
30
  * }
31
31
  * ```
32
32
  */
33
- export class UmbLocalizeController {
33
+ export class UmbLocalizationController {
34
34
  constructor(host) {
35
- _UmbLocalizeController_host.set(this, void 0);
36
- _UmbLocalizeController_hostEl.set(this, void 0);
37
- this.controllerAlias = LocalizeControllerAlias;
38
- __classPrivateFieldSet(this, _UmbLocalizeController_host, host, "f");
39
- __classPrivateFieldSet(this, _UmbLocalizeController_hostEl, host.getHostElement(), "f");
40
- __classPrivateFieldGet(this, _UmbLocalizeController_host, "f").addController(this);
35
+ _UmbLocalizationController_host.set(this, void 0);
36
+ _UmbLocalizationController_hostEl.set(this, void 0);
37
+ this.controllerAlias = LocalizationControllerAlias;
38
+ _UmbLocalizationController_usedKeys.set(this, new Array());
39
+ __classPrivateFieldSet(this, _UmbLocalizationController_host, host, "f");
40
+ __classPrivateFieldSet(this, _UmbLocalizationController_hostEl, host.getHostElement(), "f");
41
+ __classPrivateFieldGet(this, _UmbLocalizationController_host, "f").addController(this);
41
42
  }
42
43
  hostConnected() {
43
- if (connectedElements.has(__classPrivateFieldGet(this, _UmbLocalizeController_hostEl, "f"))) {
44
- return;
45
- }
46
- connectedElements.add(__classPrivateFieldGet(this, _UmbLocalizeController_hostEl, "f"));
44
+ umbLocalizationManager.appendConsumer(this);
47
45
  }
48
46
  hostDisconnected() {
49
- connectedElements.delete(__classPrivateFieldGet(this, _UmbLocalizeController_hostEl, "f"));
47
+ umbLocalizationManager.removeConsumer(this);
50
48
  }
51
49
  destroy() {
52
- __classPrivateFieldGet(this, _UmbLocalizeController_host, "f").removeController(this);
53
- __classPrivateFieldSet(this, _UmbLocalizeController_hostEl, undefined, "f");
50
+ __classPrivateFieldGet(this, _UmbLocalizationController_host, "f").removeController(this);
51
+ __classPrivateFieldSet(this, _UmbLocalizationController_hostEl, undefined, "f");
52
+ }
53
+ documentUpdate() {
54
+ __classPrivateFieldGet(this, _UmbLocalizationController_hostEl, "f")?.requestUpdate?.();
55
+ }
56
+ keysChanged(changedKeys) {
57
+ const hasOneOfTheseKeys = __classPrivateFieldGet(this, _UmbLocalizationController_usedKeys, "f").find((key) => changedKeys.has(key));
58
+ if (hasOneOfTheseKeys) {
59
+ __classPrivateFieldGet(this, _UmbLocalizationController_hostEl, "f")?.requestUpdate?.();
60
+ }
54
61
  }
55
62
  /**
56
63
  * Gets the host element's directionality as determined by the `dir` attribute. The return value is transformed to
57
64
  * lowercase.
58
65
  */
59
66
  dir() {
60
- return `${__classPrivateFieldGet(this, _UmbLocalizeController_hostEl, "f").dir || documentDirection}`.toLowerCase();
67
+ return `${__classPrivateFieldGet(this, _UmbLocalizationController_hostEl, "f")?.dir || umbLocalizationManager.documentDirection}`.toLowerCase();
61
68
  }
62
69
  /**
63
70
  * Gets the host element's language as determined by the `lang` attribute. The return value is transformed to
64
71
  * lowercase.
65
72
  */
66
73
  lang() {
67
- return `${__classPrivateFieldGet(this, _UmbLocalizeController_hostEl, "f").lang || documentLanguage}`.toLowerCase();
74
+ return `${__classPrivateFieldGet(this, _UmbLocalizationController_hostEl, "f")?.lang || umbLocalizationManager.documentLanguage}`.toLowerCase();
68
75
  }
69
76
  getLocalizationData(lang) {
70
77
  const locale = new Intl.Locale(lang);
71
78
  const language = locale?.language.toLowerCase();
72
79
  const region = locale?.region?.toLowerCase() ?? '';
73
- const primary = localizations.get(`${language}-${region}`);
74
- const secondary = localizations.get(language);
80
+ const primary = umbLocalizationManager.localizations.get(`${language}-${region}`);
81
+ const secondary = umbLocalizationManager.localizations.get(language);
75
82
  return { locale, language, region, primary, secondary };
76
83
  }
77
84
  /** Outputs a translated term. */
78
85
  term(key, ...args) {
86
+ if (!__classPrivateFieldGet(this, _UmbLocalizationController_usedKeys, "f").includes(key)) {
87
+ __classPrivateFieldGet(this, _UmbLocalizationController_usedKeys, "f").push(key);
88
+ }
79
89
  const { primary, secondary } = this.getLocalizationData(this.lang());
80
90
  let term;
81
91
  // Look for a matching term using regionCode, code, then the fallback
@@ -85,8 +95,8 @@ export class UmbLocalizeController {
85
95
  else if (secondary && secondary[key]) {
86
96
  term = secondary[key];
87
97
  }
88
- else if (fallback && fallback[key]) {
89
- term = fallback[key];
98
+ else if (umbLocalizationManager.fallback && umbLocalizationManager.fallback[key]) {
99
+ term = umbLocalizationManager.fallback[key];
90
100
  }
91
101
  else {
92
102
  return String(key);
@@ -120,4 +130,4 @@ export class UmbLocalizeController {
120
130
  return new Intl.RelativeTimeFormat(this.lang(), options).format(value, unit);
121
131
  }
122
132
  }
123
- _UmbLocalizeController_host = new WeakMap(), _UmbLocalizeController_hostEl = new WeakMap();
133
+ _UmbLocalizationController_host = new WeakMap(), _UmbLocalizationController_hostEl = new WeakMap(), _UmbLocalizationController_usedKeys = new WeakMap();
@@ -0,0 +1,29 @@
1
+ import type { UmbLocalizationController } from './localization.controller.js';
2
+ import type { UmbLocalizationEntry } from './types/localization.js';
3
+ export type FunctionParams<T> = T extends (...args: infer U) => string ? U : [];
4
+ export interface UmbLocalizationSetBase {
5
+ $code: string;
6
+ $dir: 'ltr' | 'rtl';
7
+ }
8
+ export type UmbLocalizationSetKey = string | number | symbol;
9
+ export interface UmbLocalizationSet extends UmbLocalizationSetBase {
10
+ [key: UmbLocalizationSetKey]: UmbLocalizationEntry;
11
+ }
12
+ export declare const UMB_DEFAULT_LOCALIZATION_CULTURE = "en-us";
13
+ export declare class UmbLocalizationManager {
14
+ #private;
15
+ connectedControllers: Set<UmbLocalizationController<UmbLocalizationSetBase>>;
16
+ localizations: Map<string, UmbLocalizationSetBase>;
17
+ documentDirection: string;
18
+ documentLanguage: string;
19
+ get fallback(): UmbLocalizationSet | undefined;
20
+ constructor();
21
+ appendConsumer(consumer: UmbLocalizationController<UmbLocalizationSetBase>): void;
22
+ removeConsumer(consumer: UmbLocalizationController<UmbLocalizationSetBase>): void;
23
+ /** Registers one or more translations */
24
+ registerLocalization(t: UmbLocalizationSetBase): void;
25
+ registerManyLocalizations(translations: Array<UmbLocalizationSetBase>): void;
26
+ /** Updates all localized elements that are currently connected */
27
+ updateAll: () => void;
28
+ }
29
+ export declare const umbLocalizationManager: UmbLocalizationManager;
@@ -0,0 +1,94 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ 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");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ 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");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _UmbLocalizationManager_instances, _UmbLocalizationManager_documentElementObserver, _UmbLocalizationManager_changedKeys, _UmbLocalizationManager_requestUpdateChangedKeysId, _UmbLocalizationManager_registerLocalizationBind, _UmbLocalizationManager_updateChangedKeys, _UmbLocalizationManager_requestChangedKeysUpdate;
13
+ export const UMB_DEFAULT_LOCALIZATION_CULTURE = 'en-us';
14
+ export class UmbLocalizationManager {
15
+ get fallback() {
16
+ return this.localizations.get(UMB_DEFAULT_LOCALIZATION_CULTURE);
17
+ }
18
+ constructor() {
19
+ _UmbLocalizationManager_instances.add(this);
20
+ this.connectedControllers = new Set();
21
+ _UmbLocalizationManager_documentElementObserver.set(this, void 0);
22
+ _UmbLocalizationManager_changedKeys.set(this, new Set());
23
+ _UmbLocalizationManager_requestUpdateChangedKeysId.set(this, undefined);
24
+ this.localizations = new Map();
25
+ this.documentDirection = document.documentElement.dir || 'ltr';
26
+ this.documentLanguage = document.documentElement.lang || navigator.language;
27
+ _UmbLocalizationManager_registerLocalizationBind.set(this, this.registerLocalization.bind(this));
28
+ /** Updates all localized elements that are currently connected */
29
+ this.updateAll = () => {
30
+ const newDir = document.documentElement.dir || 'ltr';
31
+ const newLang = document.documentElement.lang || navigator.language;
32
+ if (this.documentDirection === newDir && this.documentLanguage === newLang)
33
+ return;
34
+ // The document direction or language did changed, so lets move on:
35
+ this.documentDirection = newDir;
36
+ this.documentLanguage = newLang;
37
+ // Check if there was any changed.
38
+ this.connectedControllers.forEach((ctrl) => {
39
+ ctrl.documentUpdate();
40
+ });
41
+ if (__classPrivateFieldGet(this, _UmbLocalizationManager_requestUpdateChangedKeysId, "f")) {
42
+ cancelAnimationFrame(__classPrivateFieldGet(this, _UmbLocalizationManager_requestUpdateChangedKeysId, "f"));
43
+ __classPrivateFieldSet(this, _UmbLocalizationManager_requestUpdateChangedKeysId, undefined, "f");
44
+ }
45
+ __classPrivateFieldGet(this, _UmbLocalizationManager_changedKeys, "f").clear();
46
+ };
47
+ _UmbLocalizationManager_updateChangedKeys.set(this, () => {
48
+ __classPrivateFieldSet(this, _UmbLocalizationManager_requestUpdateChangedKeysId, undefined, "f");
49
+ this.connectedControllers.forEach((ctrl) => {
50
+ ctrl.keysChanged(__classPrivateFieldGet(this, _UmbLocalizationManager_changedKeys, "f"));
51
+ });
52
+ __classPrivateFieldGet(this, _UmbLocalizationManager_changedKeys, "f").clear();
53
+ });
54
+ __classPrivateFieldSet(this, _UmbLocalizationManager_documentElementObserver, new MutationObserver(this.updateAll), "f");
55
+ __classPrivateFieldGet(this, _UmbLocalizationManager_documentElementObserver, "f").observe(document.documentElement, {
56
+ attributes: true,
57
+ attributeFilter: ['dir', 'lang'],
58
+ });
59
+ }
60
+ appendConsumer(consumer) {
61
+ if (this.connectedControllers.has(consumer))
62
+ return;
63
+ this.connectedControllers.add(consumer);
64
+ }
65
+ removeConsumer(consumer) {
66
+ this.connectedControllers.delete(consumer);
67
+ }
68
+ /** Registers one or more translations */
69
+ registerLocalization(t) {
70
+ const code = t.$code.toLowerCase();
71
+ if (this.localizations.has(code)) {
72
+ // Merge translations that share the same language code
73
+ this.localizations.set(code, { ...this.localizations.get(code), ...t });
74
+ }
75
+ else {
76
+ this.localizations.set(code, t);
77
+ }
78
+ // Declare what keys have been changed:
79
+ const keys = Object.keys(t);
80
+ for (const key of keys) {
81
+ __classPrivateFieldGet(this, _UmbLocalizationManager_changedKeys, "f").add(key);
82
+ }
83
+ __classPrivateFieldGet(this, _UmbLocalizationManager_instances, "m", _UmbLocalizationManager_requestChangedKeysUpdate).call(this);
84
+ }
85
+ registerManyLocalizations(translations) {
86
+ translations.map(__classPrivateFieldGet(this, _UmbLocalizationManager_registerLocalizationBind, "f"));
87
+ }
88
+ }
89
+ _UmbLocalizationManager_documentElementObserver = new WeakMap(), _UmbLocalizationManager_changedKeys = new WeakMap(), _UmbLocalizationManager_requestUpdateChangedKeysId = new WeakMap(), _UmbLocalizationManager_registerLocalizationBind = new WeakMap(), _UmbLocalizationManager_updateChangedKeys = new WeakMap(), _UmbLocalizationManager_instances = new WeakSet(), _UmbLocalizationManager_requestChangedKeysUpdate = function _UmbLocalizationManager_requestChangedKeysUpdate() {
90
+ if (__classPrivateFieldGet(this, _UmbLocalizationManager_requestUpdateChangedKeysId, "f"))
91
+ return;
92
+ __classPrivateFieldSet(this, _UmbLocalizationManager_requestUpdateChangedKeysId, requestAnimationFrame(__classPrivateFieldGet(this, _UmbLocalizationManager_updateChangedKeys, "f")), "f");
93
+ };
94
+ export const umbLocalizationManager = new UmbLocalizationManager();
@@ -692,6 +692,13 @@ export const data = [
692
692
  icon: 'icon-book-alt',
693
693
  groupKey: 'demo-block-group-id',
694
694
  },
695
+ {
696
+ label: 'Test broken group key',
697
+ contentElementTypeKey: 'test-block-id',
698
+ editorSize: 'medium',
699
+ icon: 'icon-war',
700
+ groupKey: 'group-id-that-does-not-exist',
701
+ },
695
702
  ],
696
703
  },
697
704
  ],
@@ -1474,4 +1474,30 @@ export const data = [
1474
1474
  properties: [],
1475
1475
  containers: [],
1476
1476
  },
1477
+ {
1478
+ allowedTemplateIds: [],
1479
+ defaultTemplateId: null,
1480
+ id: 'test-block-id',
1481
+ alias: 'testBlock',
1482
+ name: 'Test broken group key',
1483
+ description: null,
1484
+ icon: 'icon-war',
1485
+ allowedAsRoot: true,
1486
+ variesByCulture: false,
1487
+ variesBySegment: false,
1488
+ isElement: true,
1489
+ hasChildren: false,
1490
+ isContainer: false,
1491
+ parentId: null,
1492
+ isFolder: false,
1493
+ allowedContentTypes: [],
1494
+ compositions: [],
1495
+ cleanup: {
1496
+ preventCleanup: false,
1497
+ keepAllVersionsNewerThanDays: null,
1498
+ keepLatestVersionPerDayForDays: null,
1499
+ },
1500
+ properties: [],
1501
+ containers: [],
1502
+ },
1477
1503
  ];
@@ -19,7 +19,6 @@ import { buildUdi } from '../../../../shared/utils/index.js';
19
19
  import { UMB_MODAL_CONTEXT } from '../../../core/modal/index.js';
20
20
  export class UmbBlockWorkspaceContext extends UmbEditableWorkspaceContextBase {
21
21
  constructor(host, workspaceArgs) {
22
- // TODO: We don't need a repo here, so maybe we should not require this of the UmbEditableWorkspaceContextBase
23
22
  super(host, workspaceArgs.manifest.alias);
24
23
  _UmbBlockWorkspaceContext_instances.add(this);
25
24
  // Just for context token safety: