@odx/angular 13.0.1 → 13.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/cdk/autocomplete-control/index.d.ts +1 -1
- package/components/notification/testing/index.d.ts +1 -1
- package/fesm2022/odx-angular-cdk-connected-overlay.mjs +3 -1
- package/fesm2022/odx-angular-cdk-connected-overlay.mjs.map +1 -1
- package/fesm2022/odx-angular-components-notification.mjs +1 -1
- package/fesm2022/odx-angular-localization.mjs +121 -45
- package/fesm2022/odx-angular-localization.mjs.map +1 -1
- package/fesm2022/odx-angular.mjs +1 -1
- package/index.d.ts +1 -1
- package/localization/index.d.ts +31 -24
- package/package.json +1 -1
- package/utils/index.d.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @odx/angular
|
|
2
2
|
|
|
3
|
+
## 13.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 300a59e: Fix: max-width and max-height for overlay content container
|
|
8
|
+
|
|
9
|
+
## 13.1.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- d9d0c60: Add: `angularLocale` support in `provideLocalization`, migrated to `provideAppInitializer`, unified locale source/registration, and added Storybook localization docs.
|
|
14
|
+
|
|
15
|
+
Note: `browserLanguageLoader` is now synchronous. `loadActiveLanguage()` is now idempotent (loader runs once). `activeLanguageLoader` is invoked eagerly at `LocalizationService` construction time — sync loaders apply the language immediately without waiting for `loadActiveLanguage()`.
|
|
16
|
+
|
|
3
17
|
## 13.0.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { AfterViewInit, QueryList, ChangeDetectorRef, EventEmitter,
|
|
2
|
+
import { AfterViewInit, QueryList, ChangeDetectorRef, EventEmitter, PipeTransform, InjectionToken } from '@angular/core';
|
|
3
3
|
import * as rxjs from 'rxjs';
|
|
4
4
|
import { ActiveDescendantKeyManager, Highlightable } from '@angular/cdk/a11y';
|
|
5
5
|
import { StringifyFn, StringSearchHandler } from '@odx/angular';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Notification,
|
|
1
|
+
import { Notification, NotificationRef, NotificationCollection, NotificationOptions } from '@odx/angular/components/notification';
|
|
2
2
|
|
|
3
3
|
declare const ICON_NAME_MOCK = "core::placeholder";
|
|
4
4
|
declare function mockNotification(props?: Partial<Notification>): Notification;
|
|
@@ -33,9 +33,11 @@ async function computeOverlayPosition(referenceElement, overlayElement, contentE
|
|
|
33
33
|
...flipMiddleWare,
|
|
34
34
|
size({
|
|
35
35
|
padding: outerPadding,
|
|
36
|
-
apply: ({ availableHeight, rects }) => {
|
|
36
|
+
apply: ({ availableHeight, availableWidth, rects }) => {
|
|
37
37
|
contentElement.style.setProperty?.(`${variablePrefix}-min-height`, minHeight ? px(Math.min(availableHeight, minHeight)) : null);
|
|
38
38
|
contentElement.style.setProperty?.(`${variablePrefix}-min-width`, matchReferenceWidth ? px(rects.reference.width) : null);
|
|
39
|
+
contentElement.style.setProperty?.(`${variablePrefix}-max-height`, px(availableHeight));
|
|
40
|
+
contentElement.style.setProperty?.(`${variablePrefix}-max-width`, px(matchReferenceWidth ? rects.reference.width : availableWidth));
|
|
39
41
|
},
|
|
40
42
|
}),
|
|
41
43
|
...arrowMiddleware,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odx-angular-cdk-connected-overlay.mjs","sources":["../../../../libs/angular/cdk/connected-overlay/src/lib/helpers/compute-overlay-position.ts","../../../../libs/angular/cdk/connected-overlay/src/lib/models/connected-overlay-options.ts","../../../../libs/angular/cdk/connected-overlay/src/lib/models/connected-overlay-ref.ts","../../../../libs/angular/cdk/connected-overlay/src/lib/connected-overlay.component.ts","../../../../libs/angular/cdk/connected-overlay/src/lib/connected-overlay.component.html","../../../../libs/angular/cdk/connected-overlay/src/lib/connected-overlay.service.ts","../../../../libs/angular/cdk/connected-overlay/src/odx-angular-cdk-connected-overlay.ts"],"sourcesContent":["import { ComputePositionReturn, VirtualElement, arrow, computePosition, flip, hide, shift, size, offset as withOffset } from '@floating-ui/dom';\nimport { applyStyles, getOppositeSide, getSide, px } from '@odx/angular/utils';\nimport { ConnectedOverlayOptions } from '../models';\n\n/**\n * Computes the position of an overlay element relative to a reference element.\n *\n * @param referenceElement - The reference element to position the overlay relative to.\n * @param overlayElement - The overlay element to be positioned.\n * @param contentElement - The content element within the overlay.\n * @param arrowElement - The arrow element within the overlay.\n * @param options - The options for positioning the overlay.\n * @returns A promise that resolves to the computed position of the overlay.\n */\nexport async function computeOverlayPosition(\n referenceElement: VirtualElement,\n overlayElement: HTMLElement,\n contentElement: HTMLElement,\n arrowElement: HTMLElement,\n options: ConnectedOverlayOptions,\n): Promise<ComputePositionReturn> {\n const variablePrefix = '--odx-cdk-connected-overlay';\n const { position, offset, outerPadding, matchReferenceWidth, enableFallback, fallbackAxisSideDirection, strategy, minHeight } = options;\n const arrowSize = options.showArrow ? arrowElement.offsetWidth : 0;\n const arrowMiddleware = options.showArrow ? [arrow({ element: arrowElement, padding: 8 })] : [];\n const flipMiddleWare = enableFallback ? [flip({ fallbackAxisSideDirection })] : [];\n return computePosition(referenceElement, overlayElement, {\n strategy,\n placement: position,\n middleware: [\n withOffset(Math.max(offset, arrowSize + offset)),\n shift({ padding: outerPadding }),\n ...flipMiddleWare,\n size({\n padding: outerPadding,\n apply: ({ availableHeight, rects }) => {\n contentElement.style.setProperty?.(`${variablePrefix}-min-height`, minHeight ? px(Math.min(availableHeight, minHeight)) : null);\n contentElement.style.setProperty?.(`${variablePrefix}-min-width`, matchReferenceWidth ? px(rects.reference.width) : null);\n },\n }),\n ...arrowMiddleware,\n hide({ rootBoundary: 'viewport' }),\n ],\n }).then((result) => {\n overlayElement.style.setProperty?.(`${variablePrefix}-position-x`, px(result.x));\n overlayElement.style.setProperty?.(`${variablePrefix}-position-y`, px(result.y));\n if (options.hiddenClass) {\n overlayElement.classList.toggle(options.hiddenClass, !!result.middlewareData.hide?.referenceHidden);\n }\n if (options.showArrow) {\n const overlaySide = getSide(result.placement);\n const arrowSide = getOppositeSide(result.placement);\n applyStyles(arrowElement, {\n display: null,\n top: px(result.middlewareData.arrow?.y),\n left: px(result.middlewareData.arrow?.x),\n [arrowSide]: px(-arrowSize / 2),\n [overlaySide]: null,\n });\n } else {\n applyStyles(arrowElement, { display: 'none' });\n }\n\n return result;\n });\n}\n","import { Strategy } from '@floating-ui/dom';\nimport { DynamicContent } from '@odx/angular/cdk/dynamic-view';\nimport { Position } from '@odx/angular/utils';\n\nexport interface ConnectedOverlayOptions {\n content?: DynamicContent | null;\n context?: Record<string, unknown>;\n containerClass?: string | null;\n hiddenClass: string | null;\n enableFallback: boolean;\n fallbackAxisSideDirection: 'start' | 'end';\n matchReferenceWidth: boolean;\n minHeight?: number | null;\n offset: number;\n outerPadding: number;\n position: Position;\n strategy: Strategy;\n showArrow?: boolean;\n updateOnAnimationFrame?: boolean;\n nonInteractive?: boolean;\n hooks?: {\n beforeOpen?: () => void;\n afterOpen?: () => void;\n beforeClose?: () => void;\n afterClose?: () => void;\n };\n}\n\nexport const DefaultConnectedOverlayOptions: ConnectedOverlayOptions = {\n hiddenClass: 'is-hidden',\n enableFallback: false,\n fallbackAxisSideDirection: 'start',\n matchReferenceWidth: false,\n offset: 8,\n outerPadding: 12,\n position: Position.BOTTOM,\n strategy: 'fixed',\n};\n","import { DynamicViewRef } from '@odx/angular/cdk/dynamic-view';\nimport { waitForAnimations } from '@odx/angular/utils';\nimport { EMPTY, Observable } from 'rxjs';\nimport { ConnectedOverlayComponent } from '../connected-overlay.component';\nimport { ConnectedOverlayOptions } from './connected-overlay-options';\n\n/**\n * A reference to a connected overlay created by the `ConnectedOverlayService`. This class provides methods to interact\n * with the overlay, such as updating its options or closing it. It encapsulates the `DynamicViewRef` for the overlay's instance,\n * allowing for direct manipulation of the overlay's state and behavior.\n *\n * This example demonstrates how to use a `ConnectedOverlayRef` to update and close a connected overlay in response\n * to user interactions.\n *\n * @example\n * ```ts\n * class MyComponent {\n * private overlayRef?: ConnectedOverlayRef;\n *\n * constructor(private overlayService: ConnectedOverlayService) {}\n *\n * openOverlay() {\n * this.overlayRef = this.overlayService.createOverlay(this.someElementRef.nativeElement, { position: 'bottom' });\n * }\n *\n * updateOverlayPosition() {\n * if (this.overlayRef) {\n * this.overlayRef.update({ position: 'top' });\n * }\n * }\n *\n * closeOverlay() {\n * this.overlayRef?.close();\n * }\n * }\n * ```\n *\n * In this example, `MyComponent` uses the `ConnectedOverlayService` to create an overlay. It stores a reference to\n * the created overlay in `overlayRef`, allowing it to update the overlay's position or close it when necessary.\n */\nexport class ConnectedOverlayRef {\n public readonly element = this.dynamicViewRef.getElement();\n\n /**\n * An Observable that emits when the overlay is closed.\n *\n * @emits {void} - Emits when the overlay is closed.\n *\n */\n public readonly onClose$: Observable<void> = this.dynamicViewRef.getContext().closed ?? EMPTY;\n\n constructor(private readonly dynamicViewRef: DynamicViewRef<typeof ConnectedOverlayComponent>) {}\n\n /**\n * Updates the connected overlay with new options.\n *\n * @param options {Partial<ConnectedOverlayOptions>} - The new options to be applied to the connected overlay.\n */\n public update(options: Partial<ConnectedOverlayOptions>): void {\n this.dynamicViewRef.update({ options: options as ConnectedOverlayOptions });\n }\n\n /**\n * Closes the connected overlay.\n *\n * @returns {void}\n */\n public async close(force = false) {\n const hiddenClass = force ? 'force-hidden' : this.dynamicViewRef.getContext().options?.hiddenClass || 'is-hidden';\n this.element?.classList.add(hiddenClass);\n await waitForAnimations(this.element);\n this.dynamicViewRef.destroy();\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n Injector,\n Input,\n NgZone,\n OnChanges,\n OnDestroy,\n OnInit,\n Output,\n ViewChild,\n ViewEncapsulation,\n inject,\n} from '@angular/core';\nimport { VirtualElement, autoUpdate } from '@floating-ui/dom';\nimport { CoreModule } from '@odx/angular';\nimport { DynamicViewDirective } from '@odx/angular/cdk/dynamic-view';\nimport { CSSComponent } from '@odx/angular/internal';\nimport { NgChanges, Side, deferFn, getSide, hasChanged, injectElement, isPresent } from '@odx/angular/utils';\nimport { Subject } from 'rxjs';\nimport { computeOverlayPosition } from './helpers';\nimport { ConnectedOverlayOptions, DefaultConnectedOverlayOptions } from './models';\n\n@CSSComponent('cdk-connected-overlay')\n@Component({\n standalone: true,\n selector: 'odx-connected-overlay[popover=\"manual\"]',\n imports: [CoreModule, DynamicViewDirective],\n templateUrl: 'connected-overlay.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n})\nexport class ConnectedOverlayComponent implements OnInit, OnChanges, OnDestroy {\n private readonly zone = inject(NgZone);\n private positionUpdater: (() => void) | null = null;\n\n protected readonly injector = inject(Injector);\n protected overlaySide?: Side;\n\n @ViewChild('content', { static: true })\n protected contentElement!: ElementRef<HTMLElement>;\n\n @ViewChild('arrow', { static: true })\n protected arrowElement!: ElementRef<HTMLElement>;\n\n public readonly element = injectElement();\n\n @Input()\n public referenceElement!: VirtualElement;\n\n @Input()\n public options: ConnectedOverlayOptions = DefaultConnectedOverlayOptions;\n\n @Output()\n public closed = new Subject<void>();\n\n public ngOnInit(): void {\n this.options.hooks?.beforeOpen?.();\n deferFn(() => {\n this.element.nativeElement?.isConnected && this.element.nativeElement?.showPopover?.();\n this.options.hooks?.afterOpen?.();\n });\n }\n\n public ngOnChanges(changes: NgChanges<ConnectedOverlayComponent>): void {\n if (hasChanged(changes, ['options'], false)) {\n this.overlaySide = getSide(this.options.position);\n this.element.nativeElement.classList.toggle('odx-cdk-connected-overlay--non-interactive', this.options.nonInteractive ?? false);\n }\n if (hasChanged(changes, ['referenceElement', 'options'], false)) {\n this.stopPositionUpdater();\n this.startPositionUpdater();\n }\n }\n\n public ngOnDestroy(): void {\n this.options.hooks?.beforeClose?.();\n this.stopPositionUpdater();\n this.element.nativeElement?.hidePopover?.();\n this.closed.next();\n this.options.hooks?.afterClose?.();\n }\n\n private startPositionUpdater(): void {\n this.positionUpdater = this.zone.runOutsideAngular(() =>\n autoUpdate(this.referenceElement, this.element.nativeElement, () => this.updatePosition(), {\n elementResize: isPresent(window.ResizeObserver),\n animationFrame: this.options.updateOnAnimationFrame,\n }),\n );\n }\n\n private stopPositionUpdater(): void {\n this.positionUpdater?.();\n this.positionUpdater = null;\n }\n\n private async updatePosition(): Promise<void> {\n return computeOverlayPosition(\n this.referenceElement,\n this.element.nativeElement,\n this.contentElement.nativeElement,\n this.arrowElement.nativeElement,\n this.options,\n ).then(({ placement }) => {\n this.overlaySide = getSide(placement);\n });\n }\n}\n","<div class=\"odx-cdk-connected-overlay__content {{ options.containerClass }}\" #content>\n <ng-template [odxDynamicView]=\"options.content\" [odxDynamicViewContext]=\"options.context\" [odxDynamicViewInjector]=\"injector\" />\n <div class=\"odx-cdk-connected-overlay-arrow\" #arrow></div>\n</div>\n","import { inject, Injectable } from '@angular/core';\nimport { VirtualElement } from '@floating-ui/dom';\nimport { DynamicViewRenderingOptions, DynamicViewService } from '@odx/angular/cdk/dynamic-view';\nimport { deepmerge } from '@odx/angular/internal';\nimport { ConnectedOverlayComponent } from './connected-overlay.component';\nimport { ConnectedOverlayOptions, ConnectedOverlayRef, DefaultConnectedOverlayOptions } from './models';\n\n/**\n * Service for creating and managing connected overlays. These overlays are UI elements such as popovers, tooltips,\n * or dropdown menus that are positioned relative to a reference element in the DOM. This service leverages the `DynamicViewService`\n * for dynamic component rendering and provides a streamlined API for creating overlays with custom positioning and options.\n *\n * Use the `ConnectedOverlayService` to dynamically create an overlay next to a specific element in your Angular application.\n * This example demonstrates creating a connected overlay next to a button element when the button is clicked.\n *\n * @example\n * ```ts\n * import { Component, ElementRef, ViewChild } from '@angular/core';\n * import { ConnectedOverlayService, ConnectedOverlayOptions } from '@odx/angular/cdk/connected-overlay';\n *\n * @Component({\n * selector: 'app-example',\n * template: `<button #triggerElement>Click me</button>`,\n * })\n * class AppComponent {\n * @ViewChild('triggerElement') triggerElementRef!: ElementRef;\n *\n * constructor(private connectedOverlayService: ConnectedOverlayService) {}\n *\n * showOverlay(): void {\n * const options: Partial<ConnectedOverlayOptions> = {\n * position: 'bottom-start',\n * showArrow: true,\n * content: 'Hello, world!',\n * };\n *\n * this.connectedOverlayService.createOverlay(this.triggerElementRef.nativeElement, options);\n * }\n * }\n * ```\n *\n * This service simplifies the process of creating dynamic, positionally aware overlays that enhance the interactivity\n * and visual appeal of Angular applications.\n */\n@Injectable({ providedIn: 'root' })\nexport class ConnectedOverlayService {\n private readonly dynamicViewService = inject(DynamicViewService);\n\n /**\n * Creates a connected overlay.\n * @param referenceElement - The reference element to which the overlay will be connected.\n * @param options - Optional configuration for the connected overlay.\n * @param renderingOptions - Optional rendering options for the connected overlay.\n * @returns {ConnectedOverlayRef} The created Connected Overlay reference instance.\n */\n public createOverlay(\n referenceElement: VirtualElement,\n options?: Partial<ConnectedOverlayOptions>,\n renderingOptions?: Partial<DynamicViewRenderingOptions>,\n ): ConnectedOverlayRef {\n const dynamicViewRef = this.dynamicViewService.createView(ConnectedOverlayComponent, {\n ...renderingOptions,\n context: { options: deepmerge(DefaultConnectedOverlayOptions, options) as ConnectedOverlayOptions, referenceElement },\n });\n\n return new ConnectedOverlayRef(dynamicViewRef);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["offset","withOffset"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"odx-angular-cdk-connected-overlay.mjs","sources":["../../../../libs/angular/cdk/connected-overlay/src/lib/helpers/compute-overlay-position.ts","../../../../libs/angular/cdk/connected-overlay/src/lib/models/connected-overlay-options.ts","../../../../libs/angular/cdk/connected-overlay/src/lib/models/connected-overlay-ref.ts","../../../../libs/angular/cdk/connected-overlay/src/lib/connected-overlay.component.ts","../../../../libs/angular/cdk/connected-overlay/src/lib/connected-overlay.component.html","../../../../libs/angular/cdk/connected-overlay/src/lib/connected-overlay.service.ts","../../../../libs/angular/cdk/connected-overlay/src/odx-angular-cdk-connected-overlay.ts"],"sourcesContent":["import { ComputePositionReturn, VirtualElement, arrow, computePosition, flip, hide, shift, size, offset as withOffset } from '@floating-ui/dom';\nimport { applyStyles, getOppositeSide, getSide, px } from '@odx/angular/utils';\nimport { ConnectedOverlayOptions } from '../models';\n\n/**\n * Computes the position of an overlay element relative to a reference element.\n *\n * @param referenceElement - The reference element to position the overlay relative to.\n * @param overlayElement - The overlay element to be positioned.\n * @param contentElement - The content element within the overlay.\n * @param arrowElement - The arrow element within the overlay.\n * @param options - The options for positioning the overlay.\n * @returns A promise that resolves to the computed position of the overlay.\n */\nexport async function computeOverlayPosition(\n referenceElement: VirtualElement,\n overlayElement: HTMLElement,\n contentElement: HTMLElement,\n arrowElement: HTMLElement,\n options: ConnectedOverlayOptions,\n): Promise<ComputePositionReturn> {\n const variablePrefix = '--odx-cdk-connected-overlay';\n const { position, offset, outerPadding, matchReferenceWidth, enableFallback, fallbackAxisSideDirection, strategy, minHeight } = options;\n const arrowSize = options.showArrow ? arrowElement.offsetWidth : 0;\n const arrowMiddleware = options.showArrow ? [arrow({ element: arrowElement, padding: 8 })] : [];\n const flipMiddleWare = enableFallback ? [flip({ fallbackAxisSideDirection })] : [];\n return computePosition(referenceElement, overlayElement, {\n strategy,\n placement: position,\n middleware: [\n withOffset(Math.max(offset, arrowSize + offset)),\n shift({ padding: outerPadding }),\n ...flipMiddleWare,\n size({\n padding: outerPadding,\n apply: ({ availableHeight, availableWidth, rects }) => {\n contentElement.style.setProperty?.(`${variablePrefix}-min-height`, minHeight ? px(Math.min(availableHeight, minHeight)) : null);\n contentElement.style.setProperty?.(`${variablePrefix}-min-width`, matchReferenceWidth ? px(rects.reference.width) : null);\n contentElement.style.setProperty?.(`${variablePrefix}-max-height`, px(availableHeight));\n contentElement.style.setProperty?.(`${variablePrefix}-max-width`, px(matchReferenceWidth ? rects.reference.width : availableWidth));\n },\n }),\n ...arrowMiddleware,\n hide({ rootBoundary: 'viewport' }),\n ],\n }).then((result) => {\n overlayElement.style.setProperty?.(`${variablePrefix}-position-x`, px(result.x));\n overlayElement.style.setProperty?.(`${variablePrefix}-position-y`, px(result.y));\n if (options.hiddenClass) {\n overlayElement.classList.toggle(options.hiddenClass, !!result.middlewareData.hide?.referenceHidden);\n }\n if (options.showArrow) {\n const overlaySide = getSide(result.placement);\n const arrowSide = getOppositeSide(result.placement);\n applyStyles(arrowElement, {\n display: null,\n top: px(result.middlewareData.arrow?.y),\n left: px(result.middlewareData.arrow?.x),\n [arrowSide]: px(-arrowSize / 2),\n [overlaySide]: null,\n });\n } else {\n applyStyles(arrowElement, { display: 'none' });\n }\n\n return result;\n });\n}\n","import { Strategy } from '@floating-ui/dom';\nimport { DynamicContent } from '@odx/angular/cdk/dynamic-view';\nimport { Position } from '@odx/angular/utils';\n\nexport interface ConnectedOverlayOptions {\n content?: DynamicContent | null;\n context?: Record<string, unknown>;\n containerClass?: string | null;\n hiddenClass: string | null;\n enableFallback: boolean;\n fallbackAxisSideDirection: 'start' | 'end';\n matchReferenceWidth: boolean;\n minHeight?: number | null;\n offset: number;\n outerPadding: number;\n position: Position;\n strategy: Strategy;\n showArrow?: boolean;\n updateOnAnimationFrame?: boolean;\n nonInteractive?: boolean;\n hooks?: {\n beforeOpen?: () => void;\n afterOpen?: () => void;\n beforeClose?: () => void;\n afterClose?: () => void;\n };\n}\n\nexport const DefaultConnectedOverlayOptions: ConnectedOverlayOptions = {\n hiddenClass: 'is-hidden',\n enableFallback: false,\n fallbackAxisSideDirection: 'start',\n matchReferenceWidth: false,\n offset: 8,\n outerPadding: 12,\n position: Position.BOTTOM,\n strategy: 'fixed',\n};\n","import { DynamicViewRef } from '@odx/angular/cdk/dynamic-view';\nimport { waitForAnimations } from '@odx/angular/utils';\nimport { EMPTY, Observable } from 'rxjs';\nimport { ConnectedOverlayComponent } from '../connected-overlay.component';\nimport { ConnectedOverlayOptions } from './connected-overlay-options';\n\n/**\n * A reference to a connected overlay created by the `ConnectedOverlayService`. This class provides methods to interact\n * with the overlay, such as updating its options or closing it. It encapsulates the `DynamicViewRef` for the overlay's instance,\n * allowing for direct manipulation of the overlay's state and behavior.\n *\n * This example demonstrates how to use a `ConnectedOverlayRef` to update and close a connected overlay in response\n * to user interactions.\n *\n * @example\n * ```ts\n * class MyComponent {\n * private overlayRef?: ConnectedOverlayRef;\n *\n * constructor(private overlayService: ConnectedOverlayService) {}\n *\n * openOverlay() {\n * this.overlayRef = this.overlayService.createOverlay(this.someElementRef.nativeElement, { position: 'bottom' });\n * }\n *\n * updateOverlayPosition() {\n * if (this.overlayRef) {\n * this.overlayRef.update({ position: 'top' });\n * }\n * }\n *\n * closeOverlay() {\n * this.overlayRef?.close();\n * }\n * }\n * ```\n *\n * In this example, `MyComponent` uses the `ConnectedOverlayService` to create an overlay. It stores a reference to\n * the created overlay in `overlayRef`, allowing it to update the overlay's position or close it when necessary.\n */\nexport class ConnectedOverlayRef {\n public readonly element = this.dynamicViewRef.getElement();\n\n /**\n * An Observable that emits when the overlay is closed.\n *\n * @emits {void} - Emits when the overlay is closed.\n *\n */\n public readonly onClose$: Observable<void> = this.dynamicViewRef.getContext().closed ?? EMPTY;\n\n constructor(private readonly dynamicViewRef: DynamicViewRef<typeof ConnectedOverlayComponent>) {}\n\n /**\n * Updates the connected overlay with new options.\n *\n * @param options {Partial<ConnectedOverlayOptions>} - The new options to be applied to the connected overlay.\n */\n public update(options: Partial<ConnectedOverlayOptions>): void {\n this.dynamicViewRef.update({ options: options as ConnectedOverlayOptions });\n }\n\n /**\n * Closes the connected overlay.\n *\n * @returns {void}\n */\n public async close(force = false) {\n const hiddenClass = force ? 'force-hidden' : this.dynamicViewRef.getContext().options?.hiddenClass || 'is-hidden';\n this.element?.classList.add(hiddenClass);\n await waitForAnimations(this.element);\n this.dynamicViewRef.destroy();\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n Injector,\n Input,\n NgZone,\n OnChanges,\n OnDestroy,\n OnInit,\n Output,\n ViewChild,\n ViewEncapsulation,\n inject,\n} from '@angular/core';\nimport { VirtualElement, autoUpdate } from '@floating-ui/dom';\nimport { CoreModule } from '@odx/angular';\nimport { DynamicViewDirective } from '@odx/angular/cdk/dynamic-view';\nimport { CSSComponent } from '@odx/angular/internal';\nimport { NgChanges, Side, deferFn, getSide, hasChanged, injectElement, isPresent } from '@odx/angular/utils';\nimport { Subject } from 'rxjs';\nimport { computeOverlayPosition } from './helpers';\nimport { ConnectedOverlayOptions, DefaultConnectedOverlayOptions } from './models';\n\n@CSSComponent('cdk-connected-overlay')\n@Component({\n standalone: true,\n selector: 'odx-connected-overlay[popover=\"manual\"]',\n imports: [CoreModule, DynamicViewDirective],\n templateUrl: 'connected-overlay.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n})\nexport class ConnectedOverlayComponent implements OnInit, OnChanges, OnDestroy {\n private readonly zone = inject(NgZone);\n private positionUpdater: (() => void) | null = null;\n\n protected readonly injector = inject(Injector);\n protected overlaySide?: Side;\n\n @ViewChild('content', { static: true })\n protected contentElement!: ElementRef<HTMLElement>;\n\n @ViewChild('arrow', { static: true })\n protected arrowElement!: ElementRef<HTMLElement>;\n\n public readonly element = injectElement();\n\n @Input()\n public referenceElement!: VirtualElement;\n\n @Input()\n public options: ConnectedOverlayOptions = DefaultConnectedOverlayOptions;\n\n @Output()\n public closed = new Subject<void>();\n\n public ngOnInit(): void {\n this.options.hooks?.beforeOpen?.();\n deferFn(() => {\n this.element.nativeElement?.isConnected && this.element.nativeElement?.showPopover?.();\n this.options.hooks?.afterOpen?.();\n });\n }\n\n public ngOnChanges(changes: NgChanges<ConnectedOverlayComponent>): void {\n if (hasChanged(changes, ['options'], false)) {\n this.overlaySide = getSide(this.options.position);\n this.element.nativeElement.classList.toggle('odx-cdk-connected-overlay--non-interactive', this.options.nonInteractive ?? false);\n }\n if (hasChanged(changes, ['referenceElement', 'options'], false)) {\n this.stopPositionUpdater();\n this.startPositionUpdater();\n }\n }\n\n public ngOnDestroy(): void {\n this.options.hooks?.beforeClose?.();\n this.stopPositionUpdater();\n this.element.nativeElement?.hidePopover?.();\n this.closed.next();\n this.options.hooks?.afterClose?.();\n }\n\n private startPositionUpdater(): void {\n this.positionUpdater = this.zone.runOutsideAngular(() =>\n autoUpdate(this.referenceElement, this.element.nativeElement, () => this.updatePosition(), {\n elementResize: isPresent(window.ResizeObserver),\n animationFrame: this.options.updateOnAnimationFrame,\n }),\n );\n }\n\n private stopPositionUpdater(): void {\n this.positionUpdater?.();\n this.positionUpdater = null;\n }\n\n private async updatePosition(): Promise<void> {\n return computeOverlayPosition(\n this.referenceElement,\n this.element.nativeElement,\n this.contentElement.nativeElement,\n this.arrowElement.nativeElement,\n this.options,\n ).then(({ placement }) => {\n this.overlaySide = getSide(placement);\n });\n }\n}\n","<div class=\"odx-cdk-connected-overlay__content {{ options.containerClass }}\" #content>\n <ng-template [odxDynamicView]=\"options.content\" [odxDynamicViewContext]=\"options.context\" [odxDynamicViewInjector]=\"injector\" />\n <div class=\"odx-cdk-connected-overlay-arrow\" #arrow></div>\n</div>\n","import { inject, Injectable } from '@angular/core';\nimport { VirtualElement } from '@floating-ui/dom';\nimport { DynamicViewRenderingOptions, DynamicViewService } from '@odx/angular/cdk/dynamic-view';\nimport { deepmerge } from '@odx/angular/internal';\nimport { ConnectedOverlayComponent } from './connected-overlay.component';\nimport { ConnectedOverlayOptions, ConnectedOverlayRef, DefaultConnectedOverlayOptions } from './models';\n\n/**\n * Service for creating and managing connected overlays. These overlays are UI elements such as popovers, tooltips,\n * or dropdown menus that are positioned relative to a reference element in the DOM. This service leverages the `DynamicViewService`\n * for dynamic component rendering and provides a streamlined API for creating overlays with custom positioning and options.\n *\n * Use the `ConnectedOverlayService` to dynamically create an overlay next to a specific element in your Angular application.\n * This example demonstrates creating a connected overlay next to a button element when the button is clicked.\n *\n * @example\n * ```ts\n * import { Component, ElementRef, ViewChild } from '@angular/core';\n * import { ConnectedOverlayService, ConnectedOverlayOptions } from '@odx/angular/cdk/connected-overlay';\n *\n * @Component({\n * selector: 'app-example',\n * template: `<button #triggerElement>Click me</button>`,\n * })\n * class AppComponent {\n * @ViewChild('triggerElement') triggerElementRef!: ElementRef;\n *\n * constructor(private connectedOverlayService: ConnectedOverlayService) {}\n *\n * showOverlay(): void {\n * const options: Partial<ConnectedOverlayOptions> = {\n * position: 'bottom-start',\n * showArrow: true,\n * content: 'Hello, world!',\n * };\n *\n * this.connectedOverlayService.createOverlay(this.triggerElementRef.nativeElement, options);\n * }\n * }\n * ```\n *\n * This service simplifies the process of creating dynamic, positionally aware overlays that enhance the interactivity\n * and visual appeal of Angular applications.\n */\n@Injectable({ providedIn: 'root' })\nexport class ConnectedOverlayService {\n private readonly dynamicViewService = inject(DynamicViewService);\n\n /**\n * Creates a connected overlay.\n * @param referenceElement - The reference element to which the overlay will be connected.\n * @param options - Optional configuration for the connected overlay.\n * @param renderingOptions - Optional rendering options for the connected overlay.\n * @returns {ConnectedOverlayRef} The created Connected Overlay reference instance.\n */\n public createOverlay(\n referenceElement: VirtualElement,\n options?: Partial<ConnectedOverlayOptions>,\n renderingOptions?: Partial<DynamicViewRenderingOptions>,\n ): ConnectedOverlayRef {\n const dynamicViewRef = this.dynamicViewService.createView(ConnectedOverlayComponent, {\n ...renderingOptions,\n context: { options: deepmerge(DefaultConnectedOverlayOptions, options) as ConnectedOverlayOptions, referenceElement },\n });\n\n return new ConnectedOverlayRef(dynamicViewRef);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["offset","withOffset"],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@ import { Logger, deepmerge, CSSComponent } from '@odx/angular/internal';
|
|
|
20
20
|
import { TranslatePipe, provideTranslations } from '@odx/angular/internal/translate';
|
|
21
21
|
import { isFunction, createConfigTokens, orderBy, Queue, getUniqueId, isString, injectElement, Position } from '@odx/angular/utils';
|
|
22
22
|
import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
23
|
-
import { tap, map, shareReplay, filter, switchMap,
|
|
23
|
+
import { tap, map, shareReplay, filter, switchMap, isObservable, of, combineLatest, from, firstValueFrom, merge, startWith } from 'rxjs';
|
|
24
24
|
import { LocalizationService } from '@odx/angular/localization';
|
|
25
25
|
import { AvatarComponent } from '@odx/angular/components/avatar';
|
|
26
26
|
import * as i1$1 from '@odx/angular';
|
|
@@ -1,12 +1,42 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { registerLocaleData } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import {
|
|
3
|
+
import { provideAppInitializer, inject, makeEnvironmentProviders, Injector, runInInjectionContext, Injectable, isDevMode, LOCALE_ID } from '@angular/core';
|
|
4
|
+
import localeDe from '@angular/common/locales/de';
|
|
5
|
+
import localeEn from '@angular/common/locales/en';
|
|
6
|
+
import localeEnGb from '@angular/common/locales/en-GB';
|
|
7
|
+
import localeEs from '@angular/common/locales/es';
|
|
8
|
+
import localeFr from '@angular/common/locales/fr';
|
|
9
|
+
import localeFrCa from '@angular/common/locales/fr-CA';
|
|
10
|
+
import { BehaviorSubject, map, distinctUntilChanged, shareReplay, firstValueFrom, isObservable, from, of, take, switchMap } from 'rxjs';
|
|
4
11
|
import { createConfigTokens, matchUrl } from '@odx/angular/utils';
|
|
5
|
-
import { BehaviorSubject, filter, map, distinctUntilChanged, shareReplay, firstValueFrom, isObservable, from, of, take, switchMap } from 'rxjs';
|
|
6
12
|
import { Logger } from '@odx/angular/internal';
|
|
13
|
+
import { provideHttpClient, withInterceptors } from '@angular/common/http';
|
|
7
14
|
import { WindowRef } from '@odx/angular';
|
|
8
15
|
|
|
9
|
-
|
|
16
|
+
// Order determines DEFAULT_AVAILABLE_LANGUAGES — the first entry is the default language.
|
|
17
|
+
const LOCALE_DATA_BY_ID = new Map([
|
|
18
|
+
['en-us', localeEn],
|
|
19
|
+
['en-gb', localeEnGb],
|
|
20
|
+
['en', localeEn],
|
|
21
|
+
['de-de', localeDe],
|
|
22
|
+
['de', localeDe],
|
|
23
|
+
['es-es', localeEs],
|
|
24
|
+
['es', localeEs],
|
|
25
|
+
['fr-fr', localeFr],
|
|
26
|
+
['fr-ca', localeFrCa],
|
|
27
|
+
['fr', localeFr],
|
|
28
|
+
]);
|
|
29
|
+
const DEFAULT_AVAILABLE_LANGUAGES = [...LOCALE_DATA_BY_ID.keys()].map((key) => new Intl.Locale(key).baseName);
|
|
30
|
+
function resolveAngularLocaleData(localeId) {
|
|
31
|
+
try {
|
|
32
|
+
const locale = new Intl.Locale(localeId);
|
|
33
|
+
return LOCALE_DATA_BY_ID.get(locale.baseName.toLowerCase()) ?? LOCALE_DATA_BY_ID.get(locale.language.toLowerCase());
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
10
40
|
/**
|
|
11
41
|
* Utilizes `createConfigTokens` to generate configuration tokens and related utilities for the
|
|
12
42
|
* localization settings within the application. It defines a structured and type-safe approach
|
|
@@ -51,6 +81,7 @@ const DEFAULT_AVAILABLE_LANGUAGES = ['en-US', 'en-GB', 'en', 'de-DE', 'de', 'es-
|
|
|
51
81
|
* ```
|
|
52
82
|
*/
|
|
53
83
|
const { LocalizationConfig, LocalizationDefaultConfig, injectLocalizationConfig, provideLocalizationConfig } = createConfigTokens('Localization', '@odx/angular/internal/translate', {
|
|
84
|
+
angularLocale: false,
|
|
54
85
|
availableLanguages: DEFAULT_AVAILABLE_LANGUAGES,
|
|
55
86
|
});
|
|
56
87
|
/**
|
|
@@ -81,15 +112,15 @@ const { LocalizationConfig, LocalizationDefaultConfig, injectLocalizationConfig,
|
|
|
81
112
|
* ```
|
|
82
113
|
*/
|
|
83
114
|
function provideLocalization(config, ...features) {
|
|
115
|
+
const localeFeatures = config.angularLocale ? [withAngularLocale()] : [];
|
|
116
|
+
// Base initializer is only needed when withAngularLocale is not present,
|
|
117
|
+
// since withAngularLocale's own initializer already calls loadActiveLanguage().
|
|
118
|
+
const baseInitializers = localeFeatures.length === 0 ? [provideAppInitializer(() => inject(LocalizationService).loadActiveLanguage())] : [];
|
|
84
119
|
return makeEnvironmentProviders([
|
|
85
120
|
provideLocalizationConfig(config),
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
deps: [LocalizationService],
|
|
90
|
-
multi: true,
|
|
91
|
-
},
|
|
92
|
-
features,
|
|
121
|
+
...baseInitializers,
|
|
122
|
+
...localeFeatures,
|
|
123
|
+
...features,
|
|
93
124
|
]);
|
|
94
125
|
}
|
|
95
126
|
|
|
@@ -99,6 +130,7 @@ class LocalizationService {
|
|
|
99
130
|
constructor() {
|
|
100
131
|
this.localizationConfig = injectLocalizationConfig();
|
|
101
132
|
this.injector = inject(Injector);
|
|
133
|
+
this.initialLoadedLanguage = this.localizationConfig.activeLanguageLoader?.();
|
|
102
134
|
this.localeState$ = new BehaviorSubject(new Intl.Locale(this.localizationConfig.availableLanguages[0]));
|
|
103
135
|
/**
|
|
104
136
|
* Represents an observable stream of the active language in the localization service.
|
|
@@ -106,27 +138,30 @@ class LocalizationService {
|
|
|
106
138
|
*
|
|
107
139
|
* @emits {string} The active language.
|
|
108
140
|
*/
|
|
109
|
-
this.activeLanguage$ = this.localeState$.pipe(
|
|
141
|
+
this.activeLanguage$ = this.localeState$.pipe(map((x) => x.baseName), distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }));
|
|
110
142
|
/**
|
|
111
143
|
* Gets the list of available languages for localization.
|
|
112
144
|
*
|
|
113
145
|
* @type {string[]} The list of available languages.
|
|
114
146
|
*/
|
|
115
147
|
this.availableLanguages = this.localizationConfig.availableLanguages;
|
|
116
|
-
/**
|
|
148
|
+
/**
|
|
149
|
+
* Default language derived from the first entry in the available languages list.
|
|
117
150
|
*
|
|
118
151
|
* @type {string}
|
|
119
152
|
*/
|
|
120
153
|
this.defaultLanguage = this.availableLanguages[0];
|
|
154
|
+
if (typeof this.initialLoadedLanguage === 'string') {
|
|
155
|
+
this.setActiveLanguage(this.initialLoadedLanguage);
|
|
156
|
+
}
|
|
121
157
|
}
|
|
122
158
|
/**
|
|
123
|
-
* Retrieves the currently active language.
|
|
124
|
-
* no active language is set.
|
|
159
|
+
* Retrieves the currently active language.
|
|
125
160
|
*
|
|
126
161
|
* @returns {string} Full locale name e.g. 'en-US' or just 'en' if no region info is attached.
|
|
127
162
|
*/
|
|
128
163
|
getActiveLanguage() {
|
|
129
|
-
return this.localeState$.getValue()
|
|
164
|
+
return this.localeState$.getValue().baseName;
|
|
130
165
|
}
|
|
131
166
|
/**
|
|
132
167
|
* Retrieves the active language subtag.
|
|
@@ -134,7 +169,7 @@ class LocalizationService {
|
|
|
134
169
|
* @returns {string} The two-digit language subtag, e.g. 'en', 'fr'.
|
|
135
170
|
*/
|
|
136
171
|
getActiveLanguageSubtag() {
|
|
137
|
-
return this.localeState$.getValue()
|
|
172
|
+
return this.localeState$.getValue().language;
|
|
138
173
|
}
|
|
139
174
|
/**
|
|
140
175
|
* Sets the active language based on the provided language code. If the language is not
|
|
@@ -167,14 +202,17 @@ class LocalizationService {
|
|
|
167
202
|
* @returns {Promise<void>} A promise that resolves when the active language is loaded and set.
|
|
168
203
|
*/
|
|
169
204
|
async loadActiveLanguage() {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
205
|
+
if (!this.loadActiveLanguagePromise) {
|
|
206
|
+
this.loadActiveLanguagePromise = runInInjectionContext(this.injector, async () => {
|
|
207
|
+
const activeLanguageLoader$ = this.createActiveLanguageLoader$();
|
|
208
|
+
const activeLanguage = await firstValueFrom(activeLanguageLoader$).catch(() => null);
|
|
209
|
+
this.setActiveLanguage(activeLanguage ?? this.defaultLanguage);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return this.loadActiveLanguagePromise;
|
|
175
213
|
}
|
|
176
214
|
createActiveLanguageLoader$() {
|
|
177
|
-
const language = this.localizationConfig.activeLanguageLoader?.();
|
|
215
|
+
const language = this.initialLoadedLanguage ?? this.localizationConfig.activeLanguageLoader?.();
|
|
178
216
|
if (isObservable(language)) {
|
|
179
217
|
return language;
|
|
180
218
|
}
|
|
@@ -189,7 +227,7 @@ class LocalizationService {
|
|
|
189
227
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: LocalizationService, decorators: [{
|
|
190
228
|
type: Injectable,
|
|
191
229
|
args: [{ providedIn: 'root' }]
|
|
192
|
-
}] });
|
|
230
|
+
}], ctorParameters: () => [] });
|
|
193
231
|
|
|
194
232
|
/**
|
|
195
233
|
* @internal
|
|
@@ -202,6 +240,54 @@ function makeLocalizationFeature(provider) {
|
|
|
202
240
|
return provider;
|
|
203
241
|
}
|
|
204
242
|
|
|
243
|
+
async function registerAngularLocale(localeId, registeredLocales) {
|
|
244
|
+
const locale = new Intl.Locale(localeId);
|
|
245
|
+
const localeKey = locale.baseName.toLowerCase();
|
|
246
|
+
if (registeredLocales.has(localeKey)) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const localeData = resolveAngularLocaleData(localeKey);
|
|
250
|
+
if (!localeData) {
|
|
251
|
+
if (isDevMode()) {
|
|
252
|
+
console.warn(`[withAngularLocale] No built-in locale data found for "${locale.baseName}". ` +
|
|
253
|
+
`Register locale data manually using registerLocaleData() before bootstrapping.`);
|
|
254
|
+
}
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
registerLocaleData(localeData, locale.baseName);
|
|
258
|
+
registeredLocales.add(localeKey);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* @internal
|
|
262
|
+
*
|
|
263
|
+
* Provides Angular locale integration by synchronizing `LOCALE_ID` with the active
|
|
264
|
+
* localization language and registering locale data for built-in Angular pipes.
|
|
265
|
+
*
|
|
266
|
+
* Use `angularLocale: true` in `provideLocalization` config instead of calling this directly.
|
|
267
|
+
*/
|
|
268
|
+
function withAngularLocale() {
|
|
269
|
+
const registeredLocales = new Set();
|
|
270
|
+
return makeLocalizationFeature(makeEnvironmentProviders([
|
|
271
|
+
provideAppInitializer(async () => {
|
|
272
|
+
const localizationService = inject(LocalizationService);
|
|
273
|
+
const preLoadLanguage = localizationService.getActiveLanguage();
|
|
274
|
+
await localizationService.loadActiveLanguage();
|
|
275
|
+
const resolvedLanguage = localizationService.getActiveLanguage();
|
|
276
|
+
if (isDevMode() && preLoadLanguage !== resolvedLanguage) {
|
|
277
|
+
console.warn(`[withAngularLocale] Active language resolved asynchronously: ` +
|
|
278
|
+
`initial value was "${preLoadLanguage}", loaded value is "${resolvedLanguage}". ` +
|
|
279
|
+
`Any LOCALE_ID consumer initialized before this APP_INITIALIZER completed will use "${preLoadLanguage}". ` +
|
|
280
|
+
`Use a synchronous activeLanguageLoader (e.g. browserLanguageLoader) for predictable LOCALE_ID behavior.`);
|
|
281
|
+
}
|
|
282
|
+
await registerAngularLocale(resolvedLanguage, registeredLocales);
|
|
283
|
+
}),
|
|
284
|
+
{
|
|
285
|
+
provide: LOCALE_ID,
|
|
286
|
+
useFactory: () => inject(LocalizationService).getActiveLanguage(),
|
|
287
|
+
},
|
|
288
|
+
]));
|
|
289
|
+
}
|
|
290
|
+
|
|
205
291
|
const HTTP_LANGUAGE_HEADER = 'Accept-Language';
|
|
206
292
|
/**
|
|
207
293
|
* Creates an HTTP interceptor function that adds a language header to outgoing HTTP requests,
|
|
@@ -341,38 +427,28 @@ function withHttpLanguageQueryParam(config) {
|
|
|
341
427
|
}
|
|
342
428
|
|
|
343
429
|
/**
|
|
344
|
-
*
|
|
430
|
+
* Loads the browser's current language setting using the `WindowRef` service.
|
|
345
431
|
* This function is intended to be used as a dynamic language loader within a localization configuration,
|
|
346
|
-
* allowing applications to automatically adapt to the user's preferred language as specified in
|
|
347
|
-
* browser settings.
|
|
432
|
+
* allowing applications to automatically adapt to the user's preferred language as specified in browser settings.
|
|
348
433
|
*
|
|
349
434
|
* The `WindowRef` service abstracts window-related operations, making it easier to interact with global
|
|
350
435
|
* browser properties and methods in a testable and platform-agnostic way. This function makes use of
|
|
351
436
|
* `WindowRef` to access the navigator's language setting in a safe and Angular-friendly manner.
|
|
352
437
|
*
|
|
353
|
-
* @returns {
|
|
354
|
-
*
|
|
355
|
-
* localization configuration.
|
|
438
|
+
* @returns {string} The language code (e.g., 'en', 'fr') of the browser's currently configured language.
|
|
439
|
+
* This value can then be used to set the active language in a localization configuration.
|
|
356
440
|
*
|
|
357
441
|
* @example
|
|
358
442
|
* ```ts
|
|
359
|
-
*
|
|
360
|
-
* import { provideLocalization } from '@odx/angular/utils';
|
|
361
|
-
* import { browserLanguageLoader } from '@odx/angular/localization';
|
|
443
|
+
* import { provideLocalization, browserLanguageLoader } from '@odx/angular/localization';
|
|
362
444
|
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
* availableLanguages: ['en', 'es', 'fr'],
|
|
368
|
-
* availableLocales: ['en-US', 'es-ES', 'fr-FR']
|
|
369
|
-
* })
|
|
370
|
-
* ]
|
|
371
|
-
* })
|
|
372
|
-
* export class AppModule { }
|
|
445
|
+
* provideLocalization({
|
|
446
|
+
* activeLanguageLoader: browserLanguageLoader,
|
|
447
|
+
* availableLanguages: ['en', 'es', 'fr'],
|
|
448
|
+
* });
|
|
373
449
|
* ```
|
|
374
450
|
*/
|
|
375
|
-
const browserLanguageLoader =
|
|
451
|
+
const browserLanguageLoader = () => {
|
|
376
452
|
return inject(WindowRef).getLanguage();
|
|
377
453
|
};
|
|
378
454
|
|
|
@@ -380,5 +456,5 @@ const browserLanguageLoader = async () => {
|
|
|
380
456
|
* Generated bundle index. Do not edit.
|
|
381
457
|
*/
|
|
382
458
|
|
|
383
|
-
export { DEFAULT_AVAILABLE_LANGUAGES, HTTP_LANGUAGE_HEADER, HTTP_LANGUAGE_QUERY, LocalizationConfig, LocalizationDefaultConfig, LocalizationService, browserLanguageLoader, httpLanguageHeaderInterceptor, injectLocalizationConfig, makeLocalizationFeature, provideLocalization, provideLocalizationConfig, withHttpLanguageHeader, withHttpLanguageQueryParam, withHttpLanguageQueryParamInterceptor };
|
|
459
|
+
export { DEFAULT_AVAILABLE_LANGUAGES, HTTP_LANGUAGE_HEADER, HTTP_LANGUAGE_QUERY, LocalizationConfig, LocalizationDefaultConfig, LocalizationService, browserLanguageLoader, httpLanguageHeaderInterceptor, injectLocalizationConfig, makeLocalizationFeature, provideLocalization, provideLocalizationConfig, withAngularLocale, withHttpLanguageHeader, withHttpLanguageQueryParam, withHttpLanguageQueryParamInterceptor };
|
|
384
460
|
//# sourceMappingURL=odx-angular-localization.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odx-angular-localization.mjs","sources":["../../../../libs/angular/localization/src/lib/localization.config.ts","../../../../libs/angular/localization/src/lib/localization.logger.ts","../../../../libs/angular/localization/src/lib/localization.service.ts","../../../../libs/angular/localization/src/lib/models/localization-feature.ts","../../../../libs/angular/localization/src/lib/features/with-http-language-header.ts","../../../../libs/angular/localization/src/lib/features/with-http-language-query-param.ts","../../../../libs/angular/localization/src/lib/loaders/browser-language-loader.ts","../../../../libs/angular/localization/src/odx-angular-localization.ts"],"sourcesContent":["import { APP_INITIALIZER, EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { createConfigTokens } from '@odx/angular/utils';\nimport { LocalizationService } from './localization.service';\nimport { LanguageLoaderFn, LocalizationFeature } from './models';\n\nexport const DEFAULT_AVAILABLE_LANGUAGES = ['en-US', 'en-GB', 'en', 'de-DE', 'de', 'es-ES', 'es', 'fr-FR', 'fr-CA', 'fr'];\n\n/**\n * Defines the structure for the localization configuration used throughout the application.\n * It allows specifying available languages, and includes an optional loader\n * function for dynamically determining the active language.\n *\n * @property {LanguageLoaderFn} [activeLanguageLoader] Optional function for loading the\n * active language dynamically, useful for scenarios where the application's language\n * needs to be determined based on user settings, browser settings, or external data.\n * @property {string[]} availableLanguages An array of language codes representing the\n * languages available in the application.\n */\nexport interface LocalizationConfig {\n activeLanguageLoader?: LanguageLoaderFn;\n availableLanguages: string[];\n}\n\n/**\n * Utilizes `createConfigTokens` to generate configuration tokens and related utilities for the\n * localization settings within the application. It defines a structured and type-safe approach\n * for managing localization configurations, such as available languages, and potentially\n * a dynamic loader for the active language. The generated tokens and utilities facilitate accessing\n * and providing these configurations throughout the application.\n *\n * @const {InjectionToken<LocalizationConfig>} LocalizationConfig - An InjectionToken for accessing\n * the localization configuration within Angular's dependency injection framework. Use this token to inject\n * localization configurations into services, components, or other tokens.\n *\n * @const {LocalizationConfig} LocalizationDefaultConfig - The default configuration values for localization,\n * based on the provided settings. Includes the default available languages.\n *\n * @const {Function} injectLocalizationConfig - A utility function that returns the injected value of\n * `LocalizationConfig` token. Use this function to access the current localization configuration in\n * a type-safe manner.\n *\n * @const {Function} provideLocalizationConfig - A utility function to provide the `LocalizationConfig` token\n * with specific values. Use this function to configure and override default localization settings within\n * an Angular module or component.\n *\n * @example\n * ```ts\n * // Providing localization settings in an Angular module\n * @NgModule({\n * providers: [\n * provideLocalizationConfig({\n * availableLanguages: ['en', 'es', 'fr'],\n * })\n * ]\n * })\n * export class AppModule { }\n *\n * // Injecting and using the localization configuration in a service\n * @Injectable({ providedIn: 'root' })\n * export class MyLocalizationService {\n * constructor(@Inject(LocalizationConfig) private config: LocalizationConfig) {\n * console.log('Available languages:', config.availableLanguages);\n * }\n * }\n * ```\n */\nexport const { LocalizationConfig, LocalizationDefaultConfig, injectLocalizationConfig, provideLocalizationConfig } = createConfigTokens(\n 'Localization',\n '@odx/angular/internal/translate',\n {\n availableLanguages: DEFAULT_AVAILABLE_LANGUAGES,\n } as LocalizationConfig,\n);\n\n/**\n * Sets up the localization configuration for the application and initializes the localization\n * system with the provided configuration and features. This function is typically called\n * within the main module or a core module of the application to ensure localization settings\n * are available and active as early as possible.\n *\n * @param {Partial<LocalizationConfig>} config The localization configuration settings, including\n * available languages and optionally, a custom loader for the active language.\n * @param {...LocalizationFeature[]} features Additional localization features or configurations\n * to be registered as part of the application's environment providers.\n * @returns {EnvironmentProviders} A collection of providers for setting up the application's\n * localization environment, to be used with Angular's environment-specific injector configuration.\n * @example\n * ```ts\n * // Example of providing localization settings in an Angular module\n * @NgModule({\n * imports: [...],\n * providers: [\n * provideLocalization({\n * availableLanguages: ['en', 'es', 'fr'],\n * activeLanguageLoader: () => fetch('/api/user/language').then(res => res.text()),\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\nexport function provideLocalization(config: Partial<LocalizationConfig>, ...features: LocalizationFeature[]): EnvironmentProviders {\n return makeEnvironmentProviders([\n provideLocalizationConfig(config),\n {\n provide: APP_INITIALIZER,\n useFactory: (localizationService: LocalizationService) => () => localizationService.loadActiveLanguage(),\n deps: [LocalizationService],\n multi: true,\n },\n features,\n ]);\n}\n","import { Logger } from '@odx/angular/internal';\n\nexport default new Logger('@odx/angular/localization');\n","import { Injectable, Injector, inject, runInInjectionContext } from '@angular/core';\nimport { BehaviorSubject, Observable, distinctUntilChanged, filter, firstValueFrom, from, isObservable, map, of, shareReplay } from 'rxjs';\nimport { injectLocalizationConfig } from './localization.config';\nimport logger from './localization.logger';\n\n@Injectable({ providedIn: 'root' })\nexport class LocalizationService {\n private readonly localizationConfig = injectLocalizationConfig();\n private readonly injector = inject(Injector);\n private readonly localeState$ = new BehaviorSubject<Intl.Locale | undefined>(new Intl.Locale(this.localizationConfig.availableLanguages[0]));\n\n /**\n * Represents an observable stream of the active language in the localization service.\n * The active language is determined by the locale state.\n *\n * @emits {string} The active language.\n */\n public readonly activeLanguage$ = this.localeState$.pipe(\n filter(Boolean),\n map((x) => x.baseName),\n distinctUntilChanged(),\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n\n /**\n * Gets the list of available languages for localization.\n *\n * @type {string[]} The list of available languages.\n */\n public readonly availableLanguages = this.localizationConfig.availableLanguages;\n\n /** Default language derived from the first entry in the available languages list.\n *\n * @type {string}\n */\n public readonly defaultLanguage = this.availableLanguages[0];\n\n /**\n * Retrieves the currently active language. Falls back to the default language if\n * no active language is set.\n *\n * @returns {string} Full locale name e.g. 'en-US' or just 'en' if no region info is attached.\n */\n public getActiveLanguage(): string {\n return this.localeState$.getValue()?.baseName ?? new Intl.Locale(this.defaultLanguage).baseName;\n }\n\n /**\n * Retrieves the active language subtag.\n *\n * @returns {string} The two-digit language subtag, e.g. 'en', 'fr'.\n */\n public getActiveLanguageSubtag(): string {\n return this.localeState$.getValue()?.language ?? new Intl.Locale(this.defaultLanguage).language;\n }\n\n /**\n * Sets the active language based on the provided language code. If the language is not\n * recognized, it logs an error and does not change the active language.\n *\n * @param {string} language The language code to set as the active language.\n */\n public setActiveLanguage(language: string): void {\n try {\n const locale = new Intl.Locale(language);\n if (this.availableLanguages.includes(locale.baseName)) {\n this.localeState$.next(locale);\n } else if (this.availableLanguages.includes(locale.language)) {\n this.localeState$.next(new Intl.Locale(locale.language));\n } else {\n throw new Error(`Unrecognizable language '${language}'. Make sure it's a part of availableLanguages inside LocalizationService config.`);\n }\n } catch (error) {\n logger.error(error);\n }\n }\n\n /**\n * Loads the active language for the localization service.\n * This method runs in an injection context and sets the active language based on the result of the active language loader.\n * If the active language loader fails, the default language is set as the active language.\n *\n * @returns {Promise<void>} A promise that resolves when the active language is loaded and set.\n */\n public async loadActiveLanguage(): Promise<void> {\n return runInInjectionContext(this.injector, async () => {\n const activeLanguageLoader$ = this.createActiveLanguageLoader$();\n const activeLanguage = await firstValueFrom(activeLanguageLoader$).catch(() => null);\n this.setActiveLanguage(activeLanguage ?? this.defaultLanguage);\n });\n }\n\n private createActiveLanguageLoader$(): Observable<string | undefined> {\n const language = this.localizationConfig.activeLanguageLoader?.();\n if (isObservable(language)) {\n return language;\n }\n if (language instanceof Promise) {\n return from(language);\n }\n return of(language);\n }\n}\n","import { EnvironmentProviders, Provider } from '@angular/core';\n\nexport type LocalizationFeature = EnvironmentProviders & { ɵodxBrand: '@odx/angular/localization::LocalizationFeature' };\n\n/**\n * @internal\n * Creates a feature provider for the localization module.\n *\n * @param {Provider[] | EnvironmentProviders} provider - The providers to be used for the localization feature.\n * @returns {LocalizationFeature} The localization feature provider.\n */\nexport function makeLocalizationFeature(provider: Provider[] | EnvironmentProviders): LocalizationFeature {\n return provider as never as LocalizationFeature;\n}\n","import { HttpInterceptorFn, provideHttpClient, withInterceptors } from '@angular/common/http';\nimport { inject } from '@angular/core';\nimport { matchUrl } from '@odx/angular/utils';\nimport { switchMap, take } from 'rxjs';\nimport { LocalizationService } from '../localization.service';\nimport { LocalizationFeature, makeLocalizationFeature } from '../models';\n\nexport const HTTP_LANGUAGE_HEADER = 'Accept-Language';\n\n/**\n * Configuration object for the HTTP language header interceptor. It specifies which URLs\n * the interceptor should apply to and allows customizing the name of the header used to transmit\n * the current language setting.\n *\n * @property {Array<string | RegExp>} allowedUrls - An array of strings or RegExp patterns\n * indicating the URLs to which the language header should be added.\n * @property {string} [headerName=HTTP_LANGUAGE_HEADER] - Optional. The name of the HTTP header\n * through which the current language setting will be transmitted. Defaults to 'Accept-Language'.\n */\nexport interface HttpLanguageHeaderInterceptorConfig {\n allowedUrls: Array<string | RegExp>;\n headerName?: string;\n}\n\n/**\n * Creates an HTTP interceptor function that adds a language header to outgoing HTTP requests,\n * but only for URLs matching the provided criteria. This allows the server to respond with\n * resources localized in the user's current language.\n *\n * @param {HttpLanguageHeaderInterceptorConfig} config - The configuration for the interceptor,\n * including the list of allowed URLs and optionally a custom header name.\n * @returns {HttpInterceptorFn} An Angular HTTP interceptor function that conditionally adds\n * the current language as an HTTP header based on the request URL.\n *\n * @example\n * ```ts\n * // Use in HTTP client module setup\n * import { HttpClientModule } from '@angular/common/http';\n * import { httpLanguageHeaderInterceptor, HTTP_LANGUAGE_HEADER } from '@odx/angular/localization';\n *\n * @NgModule({\n * imports: [HttpClientModule],\n * providers: [\n * provideHttpClient(withInterceptors([\n * httpLanguageHeaderInterceptor({ allowedUrls: ['/api'], headerName: HTTP_LANGUAGE_HEADER })\n * ]))\n * ]\n * })\n * export class AppModule {}\n * ```\n */\nexport function httpLanguageHeaderInterceptor({ allowedUrls, headerName }: HttpLanguageHeaderInterceptorConfig): HttpInterceptorFn {\n return (req, next) => {\n const language$ = inject(LocalizationService).activeLanguage$.pipe(take(1));\n for (const allowedUrl of allowedUrls) {\n if (!matchUrl(req.url, allowedUrl)) continue;\n return language$.pipe(switchMap((language) => next(req.clone({ setHeaders: { [headerName ?? HTTP_LANGUAGE_HEADER]: language } }))));\n }\n return next(req);\n };\n}\n\n/**\n * Provides a localization feature that automatically adds a language header to HTTP requests\n * for specified URLs, using the current active language. This function simplifies setting up\n * the HTTP language header interceptor by wrapping it into a LocalizationFeature, making it easy\n * to integrate with the application's localization infrastructure.\n *\n * @param {HttpLanguageHeaderInterceptorConfig} config - The configuration for the language header\n * interceptor, specifying which URLs should include the language header and optionally defining a\n * custom header name.\n * @returns {LocalizationFeature} A localization feature object that can be used to configure\n * the application's localization settings to include automatic language header addition for HTTP requests.\n *\n * @example\n * ```ts\n * // Example usage with the localization provider\n * import { provideLocalization, LocalizationModule, withHttpLanguageHeader } from '@odx/angular/localization';\n *\n * @NgModule({\n * imports: [LocalizationModule],\n * providers: [\n * provideLocalization({}, withHttpLanguageHeader({ allowedUrls: ['/api'] }))\n * ]\n * })\n * export class AppModule {}\n * ```\n */\nexport function withHttpLanguageHeader(config: HttpLanguageHeaderInterceptorConfig): LocalizationFeature {\n const providers = provideHttpClient(withInterceptors([httpLanguageHeaderInterceptor(config)]));\n\n return makeLocalizationFeature(providers);\n}\n","import { HttpInterceptorFn, provideHttpClient, withInterceptors } from '@angular/common/http';\nimport { inject } from '@angular/core';\nimport { matchUrl } from '@odx/angular/utils';\nimport { switchMap, take } from 'rxjs';\nimport { LocalizationService } from '../localization.service';\nimport { LocalizationFeature, makeLocalizationFeature } from '../models';\n\nexport const HTTP_LANGUAGE_QUERY = 'language';\n\n/**\n * Defines the configuration options for the HTTP interceptor that appends the current\n * language setting as a query parameter to outgoing requests. This configuration specifies\n * which requests should have the language parameter appended based on their URLs.\n *\n * @property {Array<string | RegExp>} allowedUrls - URLs (or patterns matching URLs) to which\n * the language query parameter should be appended.\n * @property {string} [queryParamName=HTTP_LANGUAGE_QUERY] - The name of the query parameter\n * used to transmit the current language. Defaults to 'language'.\n */\nexport interface HttpLanguageQueryParamInterceptorConfig {\n allowedUrls: Array<string | RegExp>;\n queryParamName?: string;\n}\n\n/**\n * Creates an HTTP interceptor function that appends the current language as a query parameter\n * to outgoing HTTP requests that match specified URLs. This interceptor enables dynamic content\n * localization by informing the backend of the user's preferred language.\n *\n * @param {HttpLanguageQueryParamInterceptorConfig} config - Configuration for the interceptor,\n * including allowed URLs and an optional custom name for the query parameter.\n * @returns {HttpInterceptorFn} The interceptor function ready to be applied to the HTTP client.\n *\n * @example\n * ```ts\n * // Applying the interceptor in an Angular module\n * import { HttpClientModule } from '@angular/common/http';\n * import { withHttpLanguageQueryParam } from '@odx/angular/localization';\n *\n * @NgModule({\n * imports: [HttpClientModule],\n * providers: [\n * provideHttpClient(withInterceptors([\n * withHttpLanguageQueryParam({ allowedUrls: ['/api/resources'] })\n * ]))\n * ]\n * })\n * export class ApiModule {}\n * ```\n */\nexport function withHttpLanguageQueryParamInterceptor({ allowedUrls, queryParamName }: HttpLanguageQueryParamInterceptorConfig): HttpInterceptorFn {\n return (req, next) => {\n const language$ = inject(LocalizationService).activeLanguage$.pipe(take(1));\n for (const allowedUrl of allowedUrls) {\n if (!matchUrl(req.url, allowedUrl)) continue;\n return language$.pipe(switchMap((language) => next(req.clone({ setParams: { [queryParamName ?? HTTP_LANGUAGE_QUERY]: language } }))));\n }\n return next(req);\n };\n}\n\n/**\n * Registers the HTTP interceptor that appends the current language as a query parameter to\n * outgoing requests for configured URLs as a localization feature. This utility function\n * simplifies the setup by bundling the interceptor into a feature that can be easily integrated\n * with localization configurations.\n *\n * @param {HttpLanguageQueryParamInterceptorConfig} config - Configuration for appending the\n * language query parameter, including allowed URLs and an optional parameter name.\n * @returns {LocalizationFeature} A localization feature encapsulating the interceptor, ready\n * for integration with the application's localization setup.\n *\n * @example\n * ```ts\n * // Integrating the localization feature in an Angular module\n * import { provideLocalization } from '@angular/core';\n * import { withHttpLanguageQueryParam } from '@odx/angular/localization';\n *\n * @NgModule({\n * providers: [\n * provideLocalization({}, withHttpLanguageQueryParam({ allowedUrls: ['/api'] }))\n * ]\n * })\n * export class AppModule {}\n * ```\n */\nexport function withHttpLanguageQueryParam(config: HttpLanguageQueryParamInterceptorConfig): LocalizationFeature {\n const providers = provideHttpClient(withInterceptors([withHttpLanguageQueryParamInterceptor(config)]));\n\n return makeLocalizationFeature(providers);\n}\n","import { inject } from '@angular/core';\nimport { WindowRef } from '@odx/angular';\nimport { LanguageLoaderFn } from '../models';\n\n/**\n * Asynchronously loads the browser's current language setting by utilizing the `WindowRef` service.\n * This function is intended to be used as a dynamic language loader within a localization configuration,\n * allowing applications to automatically adapt to the user's preferred language as specified in their\n * browser settings.\n *\n * The `WindowRef` service abstracts window-related operations, making it easier to interact with global\n * browser properties and methods in a testable and platform-agnostic way. This function makes use of\n * `WindowRef` to access the navigator's language setting in a safe and Angular-friendly manner.\n *\n * @returns {Promise<string>} A promise that resolves to the language code (e.g., 'en', 'fr') of the\n * browser's currently configured language. This can then be used to set the active language in a\n * localization configuration.\n *\n * @example\n * ```ts\n * // Example usage in a localization configuration\n * import { provideLocalization } from '@odx/angular/utils';\n * import { browserLanguageLoader } from '@odx/angular/localization';\n *\n * @NgModule({\n * providers: [\n * provideLocalization({\n * activeLanguageLoader: browserLanguageLoader,\n * availableLanguages: ['en', 'es', 'fr'],\n * availableLocales: ['en-US', 'es-ES', 'fr-FR']\n * })\n * ]\n * })\n * export class AppModule { }\n * ```\n */\nexport const browserLanguageLoader: LanguageLoaderFn = async () => {\n return inject(WindowRef).getLanguage();\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"odx-angular-localization.mjs","sources":["../../../../libs/angular/localization/src/lib/localization-locales.ts","../../../../libs/angular/localization/src/lib/localization.config.ts","../../../../libs/angular/localization/src/lib/localization.logger.ts","../../../../libs/angular/localization/src/lib/localization.service.ts","../../../../libs/angular/localization/src/lib/models/localization-feature.ts","../../../../libs/angular/localization/src/lib/features/with-angular-locale.ts","../../../../libs/angular/localization/src/lib/features/with-http-language-header.ts","../../../../libs/angular/localization/src/lib/features/with-http-language-query-param.ts","../../../../libs/angular/localization/src/lib/loaders/browser-language-loader.ts","../../../../libs/angular/localization/src/odx-angular-localization.ts"],"sourcesContent":["import localeDe from '@angular/common/locales/de';\nimport localeEn from '@angular/common/locales/en';\nimport localeEnGb from '@angular/common/locales/en-GB';\nimport localeEs from '@angular/common/locales/es';\nimport localeFr from '@angular/common/locales/fr';\nimport localeFrCa from '@angular/common/locales/fr-CA';\n\n// Order determines DEFAULT_AVAILABLE_LANGUAGES — the first entry is the default language.\nconst LOCALE_DATA_BY_ID = new Map<string, unknown>([\n ['en-us', localeEn],\n ['en-gb', localeEnGb],\n ['en', localeEn],\n ['de-de', localeDe],\n ['de', localeDe],\n ['es-es', localeEs],\n ['es', localeEs],\n ['fr-fr', localeFr],\n ['fr-ca', localeFrCa],\n ['fr', localeFr],\n]);\n\nexport const DEFAULT_AVAILABLE_LANGUAGES = [...LOCALE_DATA_BY_ID.keys()].map(\n (key) => new Intl.Locale(key).baseName,\n);\n\nexport function resolveAngularLocaleData(localeId: string): unknown | undefined {\n try {\n const locale = new Intl.Locale(localeId);\n return LOCALE_DATA_BY_ID.get(locale.baseName.toLowerCase()) ?? LOCALE_DATA_BY_ID.get(locale.language.toLowerCase());\n } catch {\n return undefined;\n }\n}\n","import { EnvironmentProviders, inject, makeEnvironmentProviders, provideAppInitializer } from '@angular/core';\nimport { createConfigTokens } from '@odx/angular/utils';\nimport { withAngularLocale } from './features/with-angular-locale';\nimport { DEFAULT_AVAILABLE_LANGUAGES } from './localization-locales';\nimport { LocalizationService } from './localization.service';\nimport { LanguageLoaderFn, LocalizationFeature } from './models';\n\n/**\n * Defines the structure for the localization configuration used throughout the application.\n * It allows specifying available languages, and includes an optional loader\n * function for dynamically determining the active language.\n *\n * @property {LanguageLoaderFn} [activeLanguageLoader] Optional function for loading the\n * active language dynamically, useful for scenarios where the application's language\n * needs to be determined based on user settings, browser settings, or external data.\n * @property {boolean} [angularLocale=false] Enables Angular locale integration (`LOCALE_ID`\n * and locale data registration) based on the resolved active language.\n * @property {string[]} availableLanguages An array of language codes representing the\n * languages available in the application.\n */\nexport interface LocalizationConfig {\n activeLanguageLoader?: LanguageLoaderFn;\n angularLocale?: boolean;\n availableLanguages: string[];\n}\n\n/**\n * Utilizes `createConfigTokens` to generate configuration tokens and related utilities for the\n * localization settings within the application. It defines a structured and type-safe approach\n * for managing localization configurations, such as available languages, and potentially\n * a dynamic loader for the active language. The generated tokens and utilities facilitate accessing\n * and providing these configurations throughout the application.\n *\n * @const {InjectionToken<LocalizationConfig>} LocalizationConfig - An InjectionToken for accessing\n * the localization configuration within Angular's dependency injection framework. Use this token to inject\n * localization configurations into services, components, or other tokens.\n *\n * @const {LocalizationConfig} LocalizationDefaultConfig - The default configuration values for localization,\n * based on the provided settings. Includes the default available languages.\n *\n * @const {Function} injectLocalizationConfig - A utility function that returns the injected value of\n * `LocalizationConfig` token. Use this function to access the current localization configuration in\n * a type-safe manner.\n *\n * @const {Function} provideLocalizationConfig - A utility function to provide the `LocalizationConfig` token\n * with specific values. Use this function to configure and override default localization settings within\n * an Angular module or component.\n *\n * @example\n * ```ts\n * // Providing localization settings in an Angular module\n * @NgModule({\n * providers: [\n * provideLocalizationConfig({\n * availableLanguages: ['en', 'es', 'fr'],\n * })\n * ]\n * })\n * export class AppModule { }\n *\n * // Injecting and using the localization configuration in a service\n * @Injectable({ providedIn: 'root' })\n * export class MyLocalizationService {\n * constructor(@Inject(LocalizationConfig) private config: LocalizationConfig) {\n * console.log('Available languages:', config.availableLanguages);\n * }\n * }\n * ```\n */\nexport const { LocalizationConfig, LocalizationDefaultConfig, injectLocalizationConfig, provideLocalizationConfig } = createConfigTokens(\n 'Localization',\n '@odx/angular/internal/translate',\n {\n angularLocale: false,\n availableLanguages: DEFAULT_AVAILABLE_LANGUAGES,\n } as LocalizationConfig,\n);\n\n/**\n * Sets up the localization configuration for the application and initializes the localization\n * system with the provided configuration and features. This function is typically called\n * within the main module or a core module of the application to ensure localization settings\n * are available and active as early as possible.\n *\n * @param {Partial<LocalizationConfig>} config The localization configuration settings, including\n * available languages and optionally, a custom loader for the active language.\n * @param {...LocalizationFeature[]} features Additional localization features or configurations\n * to be registered as part of the application's environment providers.\n * @returns {EnvironmentProviders} A collection of providers for setting up the application's\n * localization environment, to be used with Angular's environment-specific injector configuration.\n * @example\n * ```ts\n * // Example of providing localization settings in an Angular module\n * @NgModule({\n * imports: [...],\n * providers: [\n * provideLocalization({\n * availableLanguages: ['en', 'es', 'fr'],\n * activeLanguageLoader: () => fetch('/api/user/language').then(res => res.text()),\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\nexport function provideLocalization(config: Partial<LocalizationConfig>, ...features: LocalizationFeature[]): EnvironmentProviders {\n const localeFeatures = config.angularLocale ? [withAngularLocale()] : [];\n // Base initializer is only needed when withAngularLocale is not present,\n // since withAngularLocale's own initializer already calls loadActiveLanguage().\n const baseInitializers = localeFeatures.length === 0 ? [provideAppInitializer(() => inject(LocalizationService).loadActiveLanguage())] : [];\n\n return makeEnvironmentProviders([\n provideLocalizationConfig(config),\n ...baseInitializers,\n ...localeFeatures,\n ...features,\n ]);\n}\n","import { Logger } from '@odx/angular/internal';\n\nexport default new Logger('@odx/angular/localization');\n","import { Injectable, Injector, inject, runInInjectionContext } from '@angular/core';\nimport { BehaviorSubject, Observable, distinctUntilChanged, firstValueFrom, from, isObservable, map, of, shareReplay } from 'rxjs';\nimport { injectLocalizationConfig } from './localization.config';\nimport logger from './localization.logger';\n\n@Injectable({ providedIn: 'root' })\nexport class LocalizationService {\n private readonly localizationConfig = injectLocalizationConfig();\n private readonly injector = inject(Injector);\n private readonly initialLoadedLanguage = this.localizationConfig.activeLanguageLoader?.();\n private readonly localeState$ = new BehaviorSubject<Intl.Locale>(new Intl.Locale(this.localizationConfig.availableLanguages[0]));\n private loadActiveLanguagePromise?: Promise<void>;\n\n /**\n * Represents an observable stream of the active language in the localization service.\n * The active language is determined by the locale state.\n *\n * @emits {string} The active language.\n */\n public readonly activeLanguage$ = this.localeState$.pipe(\n map((x) => x.baseName),\n distinctUntilChanged(),\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n\n /**\n * Gets the list of available languages for localization.\n *\n * @type {string[]} The list of available languages.\n */\n public readonly availableLanguages = this.localizationConfig.availableLanguages;\n\n /**\n * Default language derived from the first entry in the available languages list.\n *\n * @type {string}\n */\n public readonly defaultLanguage = this.availableLanguages[0];\n\n constructor() {\n if (typeof this.initialLoadedLanguage === 'string') {\n this.setActiveLanguage(this.initialLoadedLanguage);\n }\n }\n\n /**\n * Retrieves the currently active language.\n *\n * @returns {string} Full locale name e.g. 'en-US' or just 'en' if no region info is attached.\n */\n public getActiveLanguage(): string {\n return this.localeState$.getValue().baseName;\n }\n\n /**\n * Retrieves the active language subtag.\n *\n * @returns {string} The two-digit language subtag, e.g. 'en', 'fr'.\n */\n public getActiveLanguageSubtag(): string {\n return this.localeState$.getValue().language;\n }\n\n /**\n * Sets the active language based on the provided language code. If the language is not\n * recognized, it logs an error and does not change the active language.\n *\n * @param {string} language The language code to set as the active language.\n */\n public setActiveLanguage(language: string): void {\n try {\n const locale = new Intl.Locale(language);\n if (this.availableLanguages.includes(locale.baseName)) {\n this.localeState$.next(locale);\n } else if (this.availableLanguages.includes(locale.language)) {\n this.localeState$.next(new Intl.Locale(locale.language));\n } else {\n throw new Error(`Unrecognizable language '${language}'. Make sure it's a part of availableLanguages inside LocalizationService config.`);\n }\n } catch (error) {\n logger.error(error);\n }\n }\n\n /**\n * Loads the active language for the localization service.\n * This method runs in an injection context and sets the active language based on the result of the active language loader.\n * If the active language loader fails, the default language is set as the active language.\n *\n * @returns {Promise<void>} A promise that resolves when the active language is loaded and set.\n */\n public async loadActiveLanguage(): Promise<void> {\n if (!this.loadActiveLanguagePromise) {\n this.loadActiveLanguagePromise = runInInjectionContext(this.injector, async () => {\n const activeLanguageLoader$ = this.createActiveLanguageLoader$();\n const activeLanguage = await firstValueFrom(activeLanguageLoader$).catch(() => null);\n this.setActiveLanguage(activeLanguage ?? this.defaultLanguage);\n });\n }\n\n return this.loadActiveLanguagePromise;\n }\n\n private createActiveLanguageLoader$(): Observable<string | undefined> {\n const language = this.initialLoadedLanguage ?? this.localizationConfig.activeLanguageLoader?.();\n if (isObservable(language)) {\n return language;\n }\n if (language instanceof Promise) {\n return from(language);\n }\n return of(language);\n }\n}\n\n","import { EnvironmentProviders, Provider } from '@angular/core';\n\nexport type LocalizationFeature = EnvironmentProviders & { ɵodxBrand: '@odx/angular/localization::LocalizationFeature' };\n\n/**\n * @internal\n * Creates a feature provider for the localization module.\n *\n * @param {Provider[] | EnvironmentProviders} provider - The providers to be used for the localization feature.\n * @returns {LocalizationFeature} The localization feature provider.\n */\nexport function makeLocalizationFeature(provider: Provider[] | EnvironmentProviders): LocalizationFeature {\n return provider as never as LocalizationFeature;\n}\n","import { registerLocaleData } from '@angular/common';\nimport { LOCALE_ID, inject, isDevMode, makeEnvironmentProviders, provideAppInitializer } from '@angular/core';\nimport { resolveAngularLocaleData } from '../localization-locales';\nimport { LocalizationService } from '../localization.service';\nimport { LocalizationFeature, makeLocalizationFeature } from '../models';\n\nasync function registerAngularLocale(localeId: string, registeredLocales: Set<string>): Promise<void> {\n const locale = new Intl.Locale(localeId);\n const localeKey = locale.baseName.toLowerCase();\n\n if (registeredLocales.has(localeKey)) {\n return;\n }\n\n const localeData = resolveAngularLocaleData(localeKey);\n if (!localeData) {\n if (isDevMode()) {\n console.warn(\n `[withAngularLocale] No built-in locale data found for \"${locale.baseName}\". ` +\n `Register locale data manually using registerLocaleData() before bootstrapping.`,\n );\n }\n return;\n }\n\n registerLocaleData(localeData, locale.baseName);\n registeredLocales.add(localeKey);\n}\n\n/**\n * @internal\n *\n * Provides Angular locale integration by synchronizing `LOCALE_ID` with the active\n * localization language and registering locale data for built-in Angular pipes.\n *\n * Use `angularLocale: true` in `provideLocalization` config instead of calling this directly.\n */\nexport function withAngularLocale(): LocalizationFeature {\n const registeredLocales = new Set<string>();\n\n return makeLocalizationFeature(\n makeEnvironmentProviders([\n provideAppInitializer(async () => {\n const localizationService = inject(LocalizationService);\n const preLoadLanguage = localizationService.getActiveLanguage();\n await localizationService.loadActiveLanguage();\n const resolvedLanguage = localizationService.getActiveLanguage();\n\n if (isDevMode() && preLoadLanguage !== resolvedLanguage) {\n console.warn(\n `[withAngularLocale] Active language resolved asynchronously: ` +\n `initial value was \"${preLoadLanguage}\", loaded value is \"${resolvedLanguage}\". ` +\n `Any LOCALE_ID consumer initialized before this APP_INITIALIZER completed will use \"${preLoadLanguage}\". ` +\n `Use a synchronous activeLanguageLoader (e.g. browserLanguageLoader) for predictable LOCALE_ID behavior.`,\n );\n }\n\n await registerAngularLocale(resolvedLanguage, registeredLocales);\n }),\n {\n provide: LOCALE_ID,\n useFactory: () => inject(LocalizationService).getActiveLanguage(),\n },\n ]),\n );\n}\n","import { HttpInterceptorFn, provideHttpClient, withInterceptors } from '@angular/common/http';\nimport { inject } from '@angular/core';\nimport { matchUrl } from '@odx/angular/utils';\nimport { switchMap, take } from 'rxjs';\nimport { LocalizationService } from '../localization.service';\nimport { LocalizationFeature, makeLocalizationFeature } from '../models';\n\nexport const HTTP_LANGUAGE_HEADER = 'Accept-Language';\n\n/**\n * Configuration object for the HTTP language header interceptor. It specifies which URLs\n * the interceptor should apply to and allows customizing the name of the header used to transmit\n * the current language setting.\n *\n * @property {Array<string | RegExp>} allowedUrls - An array of strings or RegExp patterns\n * indicating the URLs to which the language header should be added.\n * @property {string} [headerName=HTTP_LANGUAGE_HEADER] - Optional. The name of the HTTP header\n * through which the current language setting will be transmitted. Defaults to 'Accept-Language'.\n */\nexport interface HttpLanguageHeaderInterceptorConfig {\n allowedUrls: Array<string | RegExp>;\n headerName?: string;\n}\n\n/**\n * Creates an HTTP interceptor function that adds a language header to outgoing HTTP requests,\n * but only for URLs matching the provided criteria. This allows the server to respond with\n * resources localized in the user's current language.\n *\n * @param {HttpLanguageHeaderInterceptorConfig} config - The configuration for the interceptor,\n * including the list of allowed URLs and optionally a custom header name.\n * @returns {HttpInterceptorFn} An Angular HTTP interceptor function that conditionally adds\n * the current language as an HTTP header based on the request URL.\n *\n * @example\n * ```ts\n * // Use in HTTP client module setup\n * import { HttpClientModule } from '@angular/common/http';\n * import { httpLanguageHeaderInterceptor, HTTP_LANGUAGE_HEADER } from '@odx/angular/localization';\n *\n * @NgModule({\n * imports: [HttpClientModule],\n * providers: [\n * provideHttpClient(withInterceptors([\n * httpLanguageHeaderInterceptor({ allowedUrls: ['/api'], headerName: HTTP_LANGUAGE_HEADER })\n * ]))\n * ]\n * })\n * export class AppModule {}\n * ```\n */\nexport function httpLanguageHeaderInterceptor({ allowedUrls, headerName }: HttpLanguageHeaderInterceptorConfig): HttpInterceptorFn {\n return (req, next) => {\n const language$ = inject(LocalizationService).activeLanguage$.pipe(take(1));\n for (const allowedUrl of allowedUrls) {\n if (!matchUrl(req.url, allowedUrl)) continue;\n return language$.pipe(switchMap((language) => next(req.clone({ setHeaders: { [headerName ?? HTTP_LANGUAGE_HEADER]: language } }))));\n }\n return next(req);\n };\n}\n\n/**\n * Provides a localization feature that automatically adds a language header to HTTP requests\n * for specified URLs, using the current active language. This function simplifies setting up\n * the HTTP language header interceptor by wrapping it into a LocalizationFeature, making it easy\n * to integrate with the application's localization infrastructure.\n *\n * @param {HttpLanguageHeaderInterceptorConfig} config - The configuration for the language header\n * interceptor, specifying which URLs should include the language header and optionally defining a\n * custom header name.\n * @returns {LocalizationFeature} A localization feature object that can be used to configure\n * the application's localization settings to include automatic language header addition for HTTP requests.\n *\n * @example\n * ```ts\n * // Example usage with the localization provider\n * import { provideLocalization, LocalizationModule, withHttpLanguageHeader } from '@odx/angular/localization';\n *\n * @NgModule({\n * imports: [LocalizationModule],\n * providers: [\n * provideLocalization({}, withHttpLanguageHeader({ allowedUrls: ['/api'] }))\n * ]\n * })\n * export class AppModule {}\n * ```\n */\nexport function withHttpLanguageHeader(config: HttpLanguageHeaderInterceptorConfig): LocalizationFeature {\n const providers = provideHttpClient(withInterceptors([httpLanguageHeaderInterceptor(config)]));\n\n return makeLocalizationFeature(providers);\n}\n","import { HttpInterceptorFn, provideHttpClient, withInterceptors } from '@angular/common/http';\nimport { inject } from '@angular/core';\nimport { matchUrl } from '@odx/angular/utils';\nimport { switchMap, take } from 'rxjs';\nimport { LocalizationService } from '../localization.service';\nimport { LocalizationFeature, makeLocalizationFeature } from '../models';\n\nexport const HTTP_LANGUAGE_QUERY = 'language';\n\n/**\n * Defines the configuration options for the HTTP interceptor that appends the current\n * language setting as a query parameter to outgoing requests. This configuration specifies\n * which requests should have the language parameter appended based on their URLs.\n *\n * @property {Array<string | RegExp>} allowedUrls - URLs (or patterns matching URLs) to which\n * the language query parameter should be appended.\n * @property {string} [queryParamName=HTTP_LANGUAGE_QUERY] - The name of the query parameter\n * used to transmit the current language. Defaults to 'language'.\n */\nexport interface HttpLanguageQueryParamInterceptorConfig {\n allowedUrls: Array<string | RegExp>;\n queryParamName?: string;\n}\n\n/**\n * Creates an HTTP interceptor function that appends the current language as a query parameter\n * to outgoing HTTP requests that match specified URLs. This interceptor enables dynamic content\n * localization by informing the backend of the user's preferred language.\n *\n * @param {HttpLanguageQueryParamInterceptorConfig} config - Configuration for the interceptor,\n * including allowed URLs and an optional custom name for the query parameter.\n * @returns {HttpInterceptorFn} The interceptor function ready to be applied to the HTTP client.\n *\n * @example\n * ```ts\n * // Applying the interceptor in an Angular module\n * import { HttpClientModule } from '@angular/common/http';\n * import { withHttpLanguageQueryParam } from '@odx/angular/localization';\n *\n * @NgModule({\n * imports: [HttpClientModule],\n * providers: [\n * provideHttpClient(withInterceptors([\n * withHttpLanguageQueryParam({ allowedUrls: ['/api/resources'] })\n * ]))\n * ]\n * })\n * export class ApiModule {}\n * ```\n */\nexport function withHttpLanguageQueryParamInterceptor({ allowedUrls, queryParamName }: HttpLanguageQueryParamInterceptorConfig): HttpInterceptorFn {\n return (req, next) => {\n const language$ = inject(LocalizationService).activeLanguage$.pipe(take(1));\n for (const allowedUrl of allowedUrls) {\n if (!matchUrl(req.url, allowedUrl)) continue;\n return language$.pipe(switchMap((language) => next(req.clone({ setParams: { [queryParamName ?? HTTP_LANGUAGE_QUERY]: language } }))));\n }\n return next(req);\n };\n}\n\n/**\n * Registers the HTTP interceptor that appends the current language as a query parameter to\n * outgoing requests for configured URLs as a localization feature. This utility function\n * simplifies the setup by bundling the interceptor into a feature that can be easily integrated\n * with localization configurations.\n *\n * @param {HttpLanguageQueryParamInterceptorConfig} config - Configuration for appending the\n * language query parameter, including allowed URLs and an optional parameter name.\n * @returns {LocalizationFeature} A localization feature encapsulating the interceptor, ready\n * for integration with the application's localization setup.\n *\n * @example\n * ```ts\n * // Integrating the localization feature in an Angular module\n * import { provideLocalization } from '@angular/core';\n * import { withHttpLanguageQueryParam } from '@odx/angular/localization';\n *\n * @NgModule({\n * providers: [\n * provideLocalization({}, withHttpLanguageQueryParam({ allowedUrls: ['/api'] }))\n * ]\n * })\n * export class AppModule {}\n * ```\n */\nexport function withHttpLanguageQueryParam(config: HttpLanguageQueryParamInterceptorConfig): LocalizationFeature {\n const providers = provideHttpClient(withInterceptors([withHttpLanguageQueryParamInterceptor(config)]));\n\n return makeLocalizationFeature(providers);\n}\n","import { inject } from '@angular/core';\nimport { WindowRef } from '@odx/angular';\nimport { LanguageLoaderFn } from '../models';\n\n/**\n * Loads the browser's current language setting using the `WindowRef` service.\n * This function is intended to be used as a dynamic language loader within a localization configuration,\n * allowing applications to automatically adapt to the user's preferred language as specified in browser settings.\n *\n * The `WindowRef` service abstracts window-related operations, making it easier to interact with global\n * browser properties and methods in a testable and platform-agnostic way. This function makes use of\n * `WindowRef` to access the navigator's language setting in a safe and Angular-friendly manner.\n *\n * @returns {string} The language code (e.g., 'en', 'fr') of the browser's currently configured language.\n * This value can then be used to set the active language in a localization configuration.\n *\n * @example\n * ```ts\n * import { provideLocalization, browserLanguageLoader } from '@odx/angular/localization';\n *\n * provideLocalization({\n * activeLanguageLoader: browserLanguageLoader,\n * availableLanguages: ['en', 'es', 'fr'],\n * });\n * ```\n */\nexport const browserLanguageLoader: LanguageLoaderFn = (): string => {\n return inject(WindowRef).getLanguage();\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/fesm2022/odx-angular.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { inject, ChangeDetectorRef, Directive, InjectionToken, Optional, Host, forwardRef, booleanAttribute, Input, ElementRef, Renderer2, EventEmitter, Output, HostListener, signal, NgModule, DOCUMENT, reflectComponentType, Injectable } from '@angular/core';
|
|
3
3
|
import { pluckFromArray, isPresent, injectElement, hasChanged, deferFn, booleanToOptionalAttributeString, reactiveAttributeBinding, getLanguageCode } from '@odx/angular/utils';
|
|
4
|
-
import {
|
|
4
|
+
import { EMPTY, merge, tap, Subject, shareReplay, map, distinctUntilChanged, switchMap, NEVER, debounceTime, Observable, startWith, of, combineLatest, filter } from 'rxjs';
|
|
5
5
|
import { CommonModule } from '@angular/common';
|
|
6
6
|
import { toObservable } from '@angular/core/rxjs-interop';
|
|
7
7
|
import { Title } from '@angular/platform-browser';
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { OnChanges, OnDestroy, ChangeDetectorRef,
|
|
2
|
+
import { OnChanges, OnDestroy, ChangeDetectorRef, Provider, InjectionToken, ElementRef, OnInit, EventEmitter, Type } from '@angular/core';
|
|
3
3
|
import * as rxjs from 'rxjs';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
5
|
import { NgChanges } from '@odx/angular/utils';
|
package/localization/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { HttpInterceptorFn } from '@angular/common/http';
|
|
2
1
|
import * as _angular_core from '@angular/core';
|
|
3
2
|
import { EnvironmentProviders, Provider } from '@angular/core';
|
|
3
|
+
import { HttpInterceptorFn } from '@angular/common/http';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
5
|
import * as _odx_angular_utils from '@odx/angular/utils';
|
|
6
6
|
|
|
@@ -18,6 +18,16 @@ type LocalizationFeature = EnvironmentProviders & {
|
|
|
18
18
|
*/
|
|
19
19
|
declare function makeLocalizationFeature(provider: Provider[] | EnvironmentProviders): LocalizationFeature;
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
*
|
|
24
|
+
* Provides Angular locale integration by synchronizing `LOCALE_ID` with the active
|
|
25
|
+
* localization language and registering locale data for built-in Angular pipes.
|
|
26
|
+
*
|
|
27
|
+
* Use `angularLocale: true` in `provideLocalization` config instead of calling this directly.
|
|
28
|
+
*/
|
|
29
|
+
declare function withAngularLocale(): LocalizationFeature;
|
|
30
|
+
|
|
21
31
|
declare const HTTP_LANGUAGE_HEADER = "Accept-Language";
|
|
22
32
|
/**
|
|
23
33
|
* Configuration object for the HTTP language header interceptor. It specifies which URLs
|
|
@@ -159,40 +169,31 @@ declare function withHttpLanguageQueryParamInterceptor({ allowedUrls, queryParam
|
|
|
159
169
|
declare function withHttpLanguageQueryParam(config: HttpLanguageQueryParamInterceptorConfig): LocalizationFeature;
|
|
160
170
|
|
|
161
171
|
/**
|
|
162
|
-
*
|
|
172
|
+
* Loads the browser's current language setting using the `WindowRef` service.
|
|
163
173
|
* This function is intended to be used as a dynamic language loader within a localization configuration,
|
|
164
|
-
* allowing applications to automatically adapt to the user's preferred language as specified in
|
|
165
|
-
* browser settings.
|
|
174
|
+
* allowing applications to automatically adapt to the user's preferred language as specified in browser settings.
|
|
166
175
|
*
|
|
167
176
|
* The `WindowRef` service abstracts window-related operations, making it easier to interact with global
|
|
168
177
|
* browser properties and methods in a testable and platform-agnostic way. This function makes use of
|
|
169
178
|
* `WindowRef` to access the navigator's language setting in a safe and Angular-friendly manner.
|
|
170
179
|
*
|
|
171
|
-
* @returns {
|
|
172
|
-
*
|
|
173
|
-
* localization configuration.
|
|
180
|
+
* @returns {string} The language code (e.g., 'en', 'fr') of the browser's currently configured language.
|
|
181
|
+
* This value can then be used to set the active language in a localization configuration.
|
|
174
182
|
*
|
|
175
183
|
* @example
|
|
176
184
|
* ```ts
|
|
177
|
-
*
|
|
178
|
-
* import { provideLocalization } from '@odx/angular/utils';
|
|
179
|
-
* import { browserLanguageLoader } from '@odx/angular/localization';
|
|
185
|
+
* import { provideLocalization, browserLanguageLoader } from '@odx/angular/localization';
|
|
180
186
|
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* availableLanguages: ['en', 'es', 'fr'],
|
|
186
|
-
* availableLocales: ['en-US', 'es-ES', 'fr-FR']
|
|
187
|
-
* })
|
|
188
|
-
* ]
|
|
189
|
-
* })
|
|
190
|
-
* export class AppModule { }
|
|
187
|
+
* provideLocalization({
|
|
188
|
+
* activeLanguageLoader: browserLanguageLoader,
|
|
189
|
+
* availableLanguages: ['en', 'es', 'fr'],
|
|
190
|
+
* });
|
|
191
191
|
* ```
|
|
192
192
|
*/
|
|
193
193
|
declare const browserLanguageLoader: LanguageLoaderFn;
|
|
194
194
|
|
|
195
195
|
declare const DEFAULT_AVAILABLE_LANGUAGES: string[];
|
|
196
|
+
|
|
196
197
|
/**
|
|
197
198
|
* Defines the structure for the localization configuration used throughout the application.
|
|
198
199
|
* It allows specifying available languages, and includes an optional loader
|
|
@@ -201,11 +202,14 @@ declare const DEFAULT_AVAILABLE_LANGUAGES: string[];
|
|
|
201
202
|
* @property {LanguageLoaderFn} [activeLanguageLoader] Optional function for loading the
|
|
202
203
|
* active language dynamically, useful for scenarios where the application's language
|
|
203
204
|
* needs to be determined based on user settings, browser settings, or external data.
|
|
205
|
+
* @property {boolean} [angularLocale=false] Enables Angular locale integration (`LOCALE_ID`
|
|
206
|
+
* and locale data registration) based on the resolved active language.
|
|
204
207
|
* @property {string[]} availableLanguages An array of language codes representing the
|
|
205
208
|
* languages available in the application.
|
|
206
209
|
*/
|
|
207
210
|
interface LocalizationConfig {
|
|
208
211
|
activeLanguageLoader?: LanguageLoaderFn;
|
|
212
|
+
angularLocale?: boolean;
|
|
209
213
|
availableLanguages: string[];
|
|
210
214
|
}
|
|
211
215
|
/**
|
|
@@ -287,7 +291,9 @@ declare function provideLocalization(config: Partial<LocalizationConfig>, ...fea
|
|
|
287
291
|
declare class LocalizationService {
|
|
288
292
|
private readonly localizationConfig;
|
|
289
293
|
private readonly injector;
|
|
294
|
+
private readonly initialLoadedLanguage;
|
|
290
295
|
private readonly localeState$;
|
|
296
|
+
private loadActiveLanguagePromise?;
|
|
291
297
|
/**
|
|
292
298
|
* Represents an observable stream of the active language in the localization service.
|
|
293
299
|
* The active language is determined by the locale state.
|
|
@@ -301,14 +307,15 @@ declare class LocalizationService {
|
|
|
301
307
|
* @type {string[]} The list of available languages.
|
|
302
308
|
*/
|
|
303
309
|
readonly availableLanguages: string[];
|
|
304
|
-
/**
|
|
310
|
+
/**
|
|
311
|
+
* Default language derived from the first entry in the available languages list.
|
|
305
312
|
*
|
|
306
313
|
* @type {string}
|
|
307
314
|
*/
|
|
308
315
|
readonly defaultLanguage: string;
|
|
316
|
+
constructor();
|
|
309
317
|
/**
|
|
310
|
-
* Retrieves the currently active language.
|
|
311
|
-
* no active language is set.
|
|
318
|
+
* Retrieves the currently active language.
|
|
312
319
|
*
|
|
313
320
|
* @returns {string} Full locale name e.g. 'en-US' or just 'en' if no region info is attached.
|
|
314
321
|
*/
|
|
@@ -339,5 +346,5 @@ declare class LocalizationService {
|
|
|
339
346
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<LocalizationService>;
|
|
340
347
|
}
|
|
341
348
|
|
|
342
|
-
export { DEFAULT_AVAILABLE_LANGUAGES, HTTP_LANGUAGE_HEADER, HTTP_LANGUAGE_QUERY, LocalizationConfig, LocalizationDefaultConfig, LocalizationService, browserLanguageLoader, httpLanguageHeaderInterceptor, injectLocalizationConfig, makeLocalizationFeature, provideLocalization, provideLocalizationConfig, withHttpLanguageHeader, withHttpLanguageQueryParam, withHttpLanguageQueryParamInterceptor };
|
|
349
|
+
export { DEFAULT_AVAILABLE_LANGUAGES, HTTP_LANGUAGE_HEADER, HTTP_LANGUAGE_QUERY, LocalizationConfig, LocalizationDefaultConfig, LocalizationService, browserLanguageLoader, httpLanguageHeaderInterceptor, injectLocalizationConfig, makeLocalizationFeature, provideLocalization, provideLocalizationConfig, withAngularLocale, withHttpLanguageHeader, withHttpLanguageQueryParam, withHttpLanguageQueryParamInterceptor };
|
|
343
350
|
export type { HttpLanguageHeaderInterceptorConfig, HttpLanguageQueryParamInterceptorConfig, LanguageLoaderFn, LocalizationFeature };
|
package/package.json
CHANGED
package/utils/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { ElementRef, OnDestroy, Type, InjectionToken, FactoryProvider, ValueProvider,
|
|
2
|
+
import { ElementRef, OnDestroy, Type, InjectionToken, FactoryProvider, ValueProvider, TemplateRef, ViewContainerRef } from '@angular/core';
|
|
3
3
|
import { Observable, Subscriber, MonoTypeOperatorFunction } from 'rxjs';
|
|
4
4
|
export { coerceArray, coerceCssPixelValue, coerceElement, coerceStringArray } from '@angular/cdk/coercion';
|
|
5
5
|
|