@siemens/element-ng 51.3.0 → 51.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/siemens-element-ng-breadcrumb.mjs +8 -46
- package/fesm2022/siemens-element-ng-breadcrumb.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-chat-messages.mjs +2 -2
- package/fesm2022/siemens-element-ng-chat-messages.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-common.mjs +5 -0
- package/fesm2022/siemens-element-ng-common.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-dashboard.mjs +2 -3
- package/fesm2022/siemens-element-ng-dashboard.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-filtered-search.mjs +255 -160
- package/fesm2022/siemens-element-ng-filtered-search.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-formly.mjs +12 -8
- package/fesm2022/siemens-element-ng-formly.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-maplibre.mjs +293 -10
- package/fesm2022/siemens-element-ng-maplibre.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-markdown-extensions-katex.mjs +2 -2
- package/fesm2022/siemens-element-ng-markdown-extensions-katex.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-popover.mjs +3 -1
- package/fesm2022/siemens-element-ng-popover.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-shadow-root.mjs +54 -1
- package/fesm2022/siemens-element-ng-shadow-root.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-theme.mjs +59 -23
- package/fesm2022/siemens-element-ng-theme.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-tooltip.mjs +82 -10
- package/fesm2022/siemens-element-ng-tooltip.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-translate.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-tree-view.mjs +2 -2
- package/fesm2022/siemens-element-ng-tree-view.mjs.map +1 -1
- package/maplibre/styles/maplibre-gl.scss +4 -0
- package/package.json +7 -7
- package/template-i18n.json +6 -0
- package/types/siemens-element-ng-breadcrumb.d.ts +1 -1
- package/types/siemens-element-ng-common.d.ts +5 -0
- package/types/siemens-element-ng-dashboard.d.ts +0 -1
- package/types/siemens-element-ng-filtered-search.d.ts +26 -10
- package/types/siemens-element-ng-maplibre.d.ts +112 -5
- package/types/siemens-element-ng-popover.d.ts +1 -0
- package/types/siemens-element-ng-shadow-root.d.ts +16 -1
- package/types/siemens-element-ng-theme.d.ts +35 -7
- package/types/siemens-element-ng-tooltip.d.ts +14 -1
- package/types/siemens-element-ng-translate.d.ts +6 -0
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { assertInInjectionContext, computed, input, output, Component, signal } from '@angular/core';
|
|
2
|
+
import { assertInInjectionContext, computed, input, output, Component, signal, viewChild, Directive, inject, DestroyRef, DOCUMENT, booleanAttribute, numberAttribute, linkedSignal, resource, contentChild, TemplateRef, effect, afterRenderEffect } from '@angular/core';
|
|
3
3
|
import { injectIsDarkTheme } from '@siemens/element-ng/theme';
|
|
4
4
|
import { siMapStyle } from '@siemens/map-styles/common';
|
|
5
|
-
import {
|
|
5
|
+
import { GeoJSONSourceComponent, ClusterPointDirective, MarkersForClustersComponent, MapService, PopupComponent } from '@maplibre/ngx-maplibre-gl';
|
|
6
6
|
import { t, SiTranslatePipe, injectSiTranslateService } from '@siemens/element-translate-ng/translate';
|
|
7
|
+
import { FocusTrapFactory } from '@angular/cdk/a11y';
|
|
8
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
9
|
+
import { elementCancel } from '@siemens/element-icons';
|
|
10
|
+
import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
|
|
11
|
+
import { SiLoadingSpinnerDirective } from '@siemens/element-ng/loading-spinner';
|
|
12
|
+
import { ResizeObserverService } from '@siemens/element-ng/resize-observer';
|
|
13
|
+
import { from, map } from 'rxjs';
|
|
7
14
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
8
|
-
import { map } from 'rxjs';
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* Copyright (c) Siemens 2016 - 2026
|
|
@@ -292,12 +298,17 @@ class SiClusterSourceComponent {
|
|
|
292
298
|
/** Stores selection for the projected cluster-popover integration. */
|
|
293
299
|
selectedCluster = signal(undefined, /* @ts-ignore */
|
|
294
300
|
...(ngDevMode ? [{ debugName: "selectedCluster" }] : /* istanbul ignore next */ []));
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
301
|
+
source = viewChild.required(GeoJSONSourceComponent, /* @ts-ignore */
|
|
302
|
+
...(ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []));
|
|
303
|
+
/**
|
|
304
|
+
* Returns a page of original points belonging to a cluster.
|
|
305
|
+
* @see https://maplibre.org/maplibre-gl-js/docs/API/classes/GeoJSONSource/#getclusterleaves
|
|
306
|
+
*/
|
|
307
|
+
getClusterLeaves(clusterId, limit, offset) {
|
|
308
|
+
return this.source().getClusterLeaves(clusterId, limit, offset);
|
|
298
309
|
}
|
|
299
310
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SiClusterSourceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
300
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
311
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.8", type: SiClusterSourceComponent, isStandalone: true, selector: "si-cluster-source", inputs: { sourceId: { classPropertyName: "sourceId", publicName: "sourceId", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, groupProperty: { classPropertyName: "groupProperty", publicName: "groupProperty", isSignal: true, isRequired: false, transformFunction: null }, groupColors: { classPropertyName: "groupColors", publicName: "groupColors", isSignal: true, isRequired: false, transformFunction: null }, statusProperty: { classPropertyName: "statusProperty", publicName: "statusProperty", isSignal: true, isRequired: false, transformFunction: null }, clusterRadius: { classPropertyName: "clusterRadius", publicName: "clusterRadius", isSignal: true, isRequired: false, transformFunction: null }, clusterMaxZoom: { classPropertyName: "clusterMaxZoom", publicName: "clusterMaxZoom", isSignal: true, isRequired: false, transformFunction: null }, clusterMinPoints: { classPropertyName: "clusterMinPoints", publicName: "clusterMinPoints", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clusterClick: "clusterClick" }, viewQueries: [{ propertyName: "source", first: true, predicate: GeoJSONSourceComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<mgl-geojson-source\n #source\n [id]=\"sourceId()\"\n [data]=\"data()\"\n [cluster]=\"true\"\n [clusterRadius]=\"clusterRadius()\"\n [clusterMaxZoom]=\"clusterMaxZoom()\"\n [clusterMinPoints]=\"clusterMinPoints()\"\n [clusterProperties]=\"clusterConfiguration().clusterProperties\"\n/>\n\n<mgl-markers-for-clusters [source]=\"sourceId()\">\n <ng-template let-feature mglClusterPoint>\n <si-cluster-marker\n [feature]=\"feature\"\n [segments]=\"clusterConfiguration().segments\"\n (markerClick)=\"clusterClick.emit(feature)\"\n />\n </ng-template>\n</mgl-markers-for-clusters>\n\n<ng-content />\n", dependencies: [{ kind: "directive", type: ClusterPointDirective, selector: "ng-template[mglClusterPoint]" }, { kind: "component", type: GeoJSONSourceComponent, selector: "mgl-geojson-source", inputs: ["data", "maxzoom", "attribution", "buffer", "tolerance", "cluster", "clusterRadius", "clusterMaxZoom", "clusterMinPoints", "clusterProperties", "lineMetrics", "generateId", "promoteId", "filter"] }, { kind: "component", type: MarkersForClustersComponent, selector: "mgl-markers-for-clusters", inputs: ["source"] }, { kind: "component", type: SiClusterMarkerComponent, selector: "si-cluster-marker", inputs: ["feature", "segments"], outputs: ["markerClick"] }] });
|
|
301
312
|
}
|
|
302
313
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SiClusterSourceComponent, decorators: [{
|
|
303
314
|
type: Component,
|
|
@@ -306,8 +317,280 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
306
317
|
GeoJSONSourceComponent,
|
|
307
318
|
MarkersForClustersComponent,
|
|
308
319
|
SiClusterMarkerComponent
|
|
309
|
-
], template: "<mgl-geojson-source\n #source\n [id]=\"sourceId()\"\n [data]=\"data()\"\n [cluster]=\"true\"\n [clusterRadius]=\"clusterRadius()\"\n [clusterMaxZoom]=\"clusterMaxZoom()\"\n [clusterMinPoints]=\"clusterMinPoints()\"\n [clusterProperties]=\"clusterConfiguration().clusterProperties\"\n/>\n\n<mgl-markers-for-clusters [source]=\"sourceId()\">\n <ng-template let-feature mglClusterPoint>\n <si-cluster-marker\n [feature]=\"feature\"\n [segments]=\"clusterConfiguration().segments\"\n (markerClick)=\"
|
|
310
|
-
}], propDecorators: { sourceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "sourceId", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], groupProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupProperty", required: false }] }], groupColors: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupColors", required: false }] }], statusProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusProperty", required: false }] }], clusterRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "clusterRadius", required: false }] }], clusterMaxZoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "clusterMaxZoom", required: false }] }], clusterMinPoints: [{ type: i0.Input, args: [{ isSignal: true, alias: "clusterMinPoints", required: false }] }], clusterClick: [{ type: i0.Output, args: ["clusterClick"] }] } });
|
|
320
|
+
], template: "<mgl-geojson-source\n #source\n [id]=\"sourceId()\"\n [data]=\"data()\"\n [cluster]=\"true\"\n [clusterRadius]=\"clusterRadius()\"\n [clusterMaxZoom]=\"clusterMaxZoom()\"\n [clusterMinPoints]=\"clusterMinPoints()\"\n [clusterProperties]=\"clusterConfiguration().clusterProperties\"\n/>\n\n<mgl-markers-for-clusters [source]=\"sourceId()\">\n <ng-template let-feature mglClusterPoint>\n <si-cluster-marker\n [feature]=\"feature\"\n [segments]=\"clusterConfiguration().segments\"\n (markerClick)=\"clusterClick.emit(feature)\"\n />\n </ng-template>\n</mgl-markers-for-clusters>\n\n<ng-content />\n" }]
|
|
321
|
+
}], propDecorators: { sourceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "sourceId", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], groupProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupProperty", required: false }] }], groupColors: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupColors", required: false }] }], statusProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusProperty", required: false }] }], clusterRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "clusterRadius", required: false }] }], clusterMaxZoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "clusterMaxZoom", required: false }] }], clusterMinPoints: [{ type: i0.Input, args: [{ isSignal: true, alias: "clusterMinPoints", required: false }] }], clusterClick: [{ type: i0.Output, args: ["clusterClick"] }], source: [{ type: i0.ViewChild, args: [i0.forwardRef(() => GeoJSONSourceComponent), { isSignal: true }] }] } });
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Copyright (c) Siemens 2016 - 2026
|
|
325
|
+
* SPDX-License-Identifier: MIT
|
|
326
|
+
*/
|
|
327
|
+
/**
|
|
328
|
+
* Template for custom location content inside `si-cluster-popover`.
|
|
329
|
+
*
|
|
330
|
+
* Receives a {@link ClusterPopoverContext} with all locations loaded so far. Loading feedback,
|
|
331
|
+
* error recovery, and the "Load more" button are handled by the popover.
|
|
332
|
+
*
|
|
333
|
+
* @experimental
|
|
334
|
+
*/
|
|
335
|
+
class SiClusterPopoverTemplateDirective {
|
|
336
|
+
/** @internal */
|
|
337
|
+
static ngTemplateContextGuard(directive, context) {
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SiClusterPopoverTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
341
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.8", type: SiClusterPopoverTemplateDirective, isStandalone: true, selector: "[siClusterPopoverTemplate]", ngImport: i0 });
|
|
342
|
+
}
|
|
343
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SiClusterPopoverTemplateDirective, decorators: [{
|
|
344
|
+
type: Directive,
|
|
345
|
+
args: [{
|
|
346
|
+
selector: '[siClusterPopoverTemplate]'
|
|
347
|
+
}]
|
|
348
|
+
}] });
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Copyright (c) Siemens 2016 - 2026
|
|
352
|
+
* SPDX-License-Identifier: MIT
|
|
353
|
+
*/
|
|
354
|
+
/**
|
|
355
|
+
* Optional popup with incrementally loaded locations projected into a `si-cluster-source`.
|
|
356
|
+
*
|
|
357
|
+
* @experimental
|
|
358
|
+
*/
|
|
359
|
+
class SiClusterPopoverComponent {
|
|
360
|
+
static idCounter = 0;
|
|
361
|
+
destroyRef = inject(DestroyRef);
|
|
362
|
+
focusTrapFactory = inject(FocusTrapFactory);
|
|
363
|
+
document = inject(DOCUMENT);
|
|
364
|
+
source = inject(SiClusterSourceComponent);
|
|
365
|
+
mapService = inject(MapService);
|
|
366
|
+
resizeObserver = inject(ResizeObserverService);
|
|
367
|
+
/**
|
|
368
|
+
* Maximum width passed to the MapLibre popup.
|
|
369
|
+
* @defaultValue '320px'
|
|
370
|
+
*/
|
|
371
|
+
maxWidth = input('320px', /* @ts-ignore */
|
|
372
|
+
...(ngDevMode ? [{ debugName: "maxWidth" }] : /* istanbul ignore next */ []));
|
|
373
|
+
/**
|
|
374
|
+
* Whether the popup closes when the map moves.
|
|
375
|
+
* @defaultValue true
|
|
376
|
+
*/
|
|
377
|
+
closeOnMove = input(true, { ...(ngDevMode ? { debugName: "closeOnMove" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
378
|
+
/**
|
|
379
|
+
* Number of locations loaded initially and with each "Load more" action.
|
|
380
|
+
* @defaultValue 8
|
|
381
|
+
*/
|
|
382
|
+
pageSize = input(8, { ...(ngDevMode ? { debugName: "pageSize" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
383
|
+
/**
|
|
384
|
+
* Feature property displayed in the default list.
|
|
385
|
+
* @defaultValue 'name'
|
|
386
|
+
*/
|
|
387
|
+
labelProperty = input('name', /* @ts-ignore */
|
|
388
|
+
...(ngDevMode ? [{ debugName: "labelProperty" }] : /* istanbul ignore next */ []));
|
|
389
|
+
/**
|
|
390
|
+
* Feature property displayed as the description in the default list.
|
|
391
|
+
* @defaultValue 'description'
|
|
392
|
+
*/
|
|
393
|
+
descriptionProperty = input('description', /* @ts-ignore */
|
|
394
|
+
...(ngDevMode ? [{ debugName: "descriptionProperty" }] : /* istanbul ignore next */ []));
|
|
395
|
+
dialog = viewChild('dialog', /* @ts-ignore */
|
|
396
|
+
...(ngDevMode ? [{ debugName: "dialog" }] : /* istanbul ignore next */ []));
|
|
397
|
+
scrollRegion = viewChild('scrollRegion', /* @ts-ignore */
|
|
398
|
+
...(ngDevMode ? [{ debugName: "scrollRegion" }] : /* istanbul ignore next */ []));
|
|
399
|
+
batchButton = viewChild('batchButton', /* @ts-ignore */
|
|
400
|
+
...(ngDevMode ? [{ debugName: "batchButton" }] : /* istanbul ignore next */ []));
|
|
401
|
+
selectedCluster = linkedSignal(() => {
|
|
402
|
+
this.source.sourceId();
|
|
403
|
+
this.source.data();
|
|
404
|
+
this.source.groupProperty();
|
|
405
|
+
this.source.groupColors();
|
|
406
|
+
this.source.statusProperty();
|
|
407
|
+
this.source.clusterRadius();
|
|
408
|
+
this.source.clusterMaxZoom();
|
|
409
|
+
this.source.clusterMinPoints();
|
|
410
|
+
return undefined;
|
|
411
|
+
}, /* @ts-ignore */
|
|
412
|
+
...(ngDevMode ? [{ debugName: "selectedCluster" }] : /* istanbul ignore next */ []));
|
|
413
|
+
batchFocusRequested = linkedSignal(() => {
|
|
414
|
+
this.selectedCluster();
|
|
415
|
+
this.pageSize();
|
|
416
|
+
return false;
|
|
417
|
+
}, /* @ts-ignore */
|
|
418
|
+
...(ngDevMode ? [{ debugName: "batchFocusRequested" }] : /* istanbul ignore next */ []));
|
|
419
|
+
offset = linkedSignal(() => {
|
|
420
|
+
this.selectedCluster();
|
|
421
|
+
this.pageSize();
|
|
422
|
+
return 0;
|
|
423
|
+
}, /* @ts-ignore */
|
|
424
|
+
...(ngDevMode ? [{ debugName: "offset" }] : /* istanbul ignore next */ []));
|
|
425
|
+
displayedFeatures = linkedSignal({ ...(ngDevMode ? { debugName: "displayedFeatures" } : /* istanbul ignore next */ {}), source: () => ({
|
|
426
|
+
cluster: this.selectedCluster(),
|
|
427
|
+
limit: this.pageSize(),
|
|
428
|
+
offset: this.offset(),
|
|
429
|
+
features: this.leaves.hasValue() ? this.leaves.value() : undefined
|
|
430
|
+
}),
|
|
431
|
+
computation: (current, previous) => {
|
|
432
|
+
if (!current.cluster) {
|
|
433
|
+
return [];
|
|
434
|
+
}
|
|
435
|
+
const retainedFeatures = current.cluster === previous?.source.cluster && current.limit === previous.source.limit
|
|
436
|
+
? previous.value
|
|
437
|
+
: [];
|
|
438
|
+
return current.features
|
|
439
|
+
? [...retainedFeatures.slice(0, current.offset), ...current.features]
|
|
440
|
+
: retainedFeatures;
|
|
441
|
+
} });
|
|
442
|
+
titleId = `__si-cluster-popover-title-${SiClusterPopoverComponent.idCounter++}`;
|
|
443
|
+
popupCoordinates = linkedSignal(() => this.selectedCluster()?.geometry.coordinates, /* @ts-ignore */
|
|
444
|
+
...(ngDevMode ? [{ debugName: "popupCoordinates" }] : /* istanbul ignore next */ []));
|
|
445
|
+
availableBlockSize = signal(undefined, /* @ts-ignore */
|
|
446
|
+
...(ngDevMode ? [{ debugName: "availableBlockSize" }] : /* istanbul ignore next */ []));
|
|
447
|
+
leaves = resource({ ...(ngDevMode ? { debugName: "leaves" } : /* istanbul ignore next */ {}), params: () => {
|
|
448
|
+
const cluster = this.selectedCluster();
|
|
449
|
+
return cluster
|
|
450
|
+
? {
|
|
451
|
+
cluster,
|
|
452
|
+
limit: this.pageSize(),
|
|
453
|
+
offset: this.offset()
|
|
454
|
+
}
|
|
455
|
+
: undefined;
|
|
456
|
+
},
|
|
457
|
+
loader: ({ params }) => this.source.getClusterLeaves(Number(params.cluster.properties?.cluster_id), params.limit, params.offset) });
|
|
458
|
+
context = computed(() => {
|
|
459
|
+
const features = this.displayedFeatures();
|
|
460
|
+
const cluster = this.selectedCluster();
|
|
461
|
+
if (!cluster) {
|
|
462
|
+
return undefined;
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
$implicit: features,
|
|
466
|
+
features,
|
|
467
|
+
total: Number(cluster.properties?.point_count),
|
|
468
|
+
loading: this.leaves.isLoading(),
|
|
469
|
+
error: this.leaves.error(),
|
|
470
|
+
cluster,
|
|
471
|
+
close: this.close
|
|
472
|
+
};
|
|
473
|
+
}, /* @ts-ignore */
|
|
474
|
+
...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
|
|
475
|
+
template = contentChild(SiClusterPopoverTemplateDirective, { ...(ngDevMode ? { debugName: "template" } : /* istanbul ignore next */ {}), read: TemplateRef });
|
|
476
|
+
clusterPopoverTitle = t(() => $localize `:@@SI_MAP_CLUSTER.POPOVER_TITLE:Cluster with {{count}} locations`);
|
|
477
|
+
locationsLabel = t(() => $localize `:@@SI_MAP_CLUSTER.LOCATIONS:Cluster locations`);
|
|
478
|
+
errorText = t(() => $localize `:@@SI_MAP_CLUSTER.ERROR:Could not load locations.`);
|
|
479
|
+
loadMoreText = t(() => $localize `:@@SI_MAP_CLUSTER.LOAD_MORE:Load more`);
|
|
480
|
+
retryText = t(() => $localize `:@@SI_MAP_CLUSTER.RETRY:Retry`);
|
|
481
|
+
closeText = t(() => $localize `:@@SI_MAP_CLUSTER.CLOSE:Close`);
|
|
482
|
+
icons = addIcons({ elementCancel });
|
|
483
|
+
close = () => this.selectedCluster.set(undefined);
|
|
484
|
+
loadBatch = () => {
|
|
485
|
+
if (this.leaves.isLoading()) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
// Safari does not focus buttons on click.
|
|
489
|
+
this.batchButton()?.nativeElement.focus({ preventScroll: true });
|
|
490
|
+
this.batchFocusRequested.set(true);
|
|
491
|
+
if (this.leaves.error()) {
|
|
492
|
+
this.leaves.reload();
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
this.offset.set(this.displayedFeatures().length);
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
constructor() {
|
|
499
|
+
const subscription = this.source.clusterClick.subscribe(cluster => {
|
|
500
|
+
this.selectedCluster.set(cluster);
|
|
501
|
+
});
|
|
502
|
+
this.destroyRef.onDestroy(() => subscription.unsubscribe());
|
|
503
|
+
effect(onCleanup => {
|
|
504
|
+
const dialog = this.dialog()?.nativeElement;
|
|
505
|
+
const cluster = this.selectedCluster();
|
|
506
|
+
if (!dialog || !cluster) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const focusTrap = this.focusTrapFactory.create(dialog);
|
|
510
|
+
const focusSubscription = from(focusTrap.focusFirstTabbableElementWhenReady()).subscribe();
|
|
511
|
+
const map = this.mapService.mapInstance;
|
|
512
|
+
const mapContainer = map.getContainer();
|
|
513
|
+
const updateAvailableSpace = () => {
|
|
514
|
+
const [longitude, latitude] = cluster.geometry.coordinates;
|
|
515
|
+
const { y } = map.project([longitude, latitude]);
|
|
516
|
+
const height = mapContainer.clientHeight;
|
|
517
|
+
this.availableBlockSize.set(Math.min(height, Math.max(y, height - y)));
|
|
518
|
+
};
|
|
519
|
+
updateAvailableSpace();
|
|
520
|
+
const mapResizeSubscription = this.resizeObserver
|
|
521
|
+
.observe(mapContainer, 0)
|
|
522
|
+
.subscribe(updateAvailableSpace);
|
|
523
|
+
const dialogResizeSubscription = this.resizeObserver.observe(dialog, 0).subscribe(() => {
|
|
524
|
+
// A new coordinate reference refreshes MapLibre's popup anchor.
|
|
525
|
+
this.popupCoordinates.update(coordinates => (coordinates ? [...coordinates] : undefined));
|
|
526
|
+
});
|
|
527
|
+
const moveSubscription = map.on('move', updateAvailableSpace);
|
|
528
|
+
onCleanup(() => {
|
|
529
|
+
mapResizeSubscription.unsubscribe();
|
|
530
|
+
dialogResizeSubscription.unsubscribe();
|
|
531
|
+
moveSubscription.unsubscribe();
|
|
532
|
+
focusSubscription.unsubscribe();
|
|
533
|
+
focusTrap.destroy();
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
afterRenderEffect({
|
|
537
|
+
earlyRead: () => {
|
|
538
|
+
if (!this.batchFocusRequested()) {
|
|
539
|
+
return undefined;
|
|
540
|
+
}
|
|
541
|
+
const loading = this.leaves.isLoading();
|
|
542
|
+
const button = this.batchButton()?.nativeElement;
|
|
543
|
+
const active = this.document.activeElement;
|
|
544
|
+
return {
|
|
545
|
+
loading,
|
|
546
|
+
button: active === button ? button : undefined,
|
|
547
|
+
scrollRegion: !button && active === this.document.body
|
|
548
|
+
? this.scrollRegion()?.nativeElement
|
|
549
|
+
: undefined
|
|
550
|
+
};
|
|
551
|
+
},
|
|
552
|
+
write: state => {
|
|
553
|
+
const request = state();
|
|
554
|
+
if (!request || request.loading) {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
this.batchFocusRequested.set(false);
|
|
558
|
+
if (request.button) {
|
|
559
|
+
request.button.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
request.scrollRegion?.focus({ preventScroll: true });
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
effect(onCleanup => {
|
|
567
|
+
if (!this.selectedCluster()) {
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
const trigger = this.document.activeElement;
|
|
571
|
+
onCleanup(() => {
|
|
572
|
+
const active = this.document.activeElement;
|
|
573
|
+
if (trigger instanceof HTMLElement &&
|
|
574
|
+
trigger.isConnected &&
|
|
575
|
+
(active === this.document.body || this.dialog()?.nativeElement.contains(active))) {
|
|
576
|
+
trigger.focus();
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SiClusterPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
582
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SiClusterPopoverComponent, isStandalone: true, selector: "si-cluster-popover", inputs: { maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, closeOnMove: { classPropertyName: "closeOnMove", publicName: "closeOnMove", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, labelProperty: { classPropertyName: "labelProperty", publicName: "labelProperty", isSignal: true, isRequired: false, transformFunction: null }, descriptionProperty: { classPropertyName: "descriptionProperty", publicName: "descriptionProperty", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "template", first: true, predicate: SiClusterPopoverTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "dialog", first: true, predicate: ["dialog"], descendants: true, isSignal: true }, { propertyName: "scrollRegion", first: true, predicate: ["scrollRegion"], descendants: true, isSignal: true }, { propertyName: "batchButton", first: true, predicate: ["batchButton"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (context(); as context) {\n <mgl-popup\n [maxWidth]=\"maxWidth()\"\n [lngLat]=\"popupCoordinates()\"\n [closeOnMove]=\"closeOnMove()\"\n [focusAfterOpen]=\"false\"\n [closeButton]=\"false\"\n (popupClose)=\"context.close()\"\n >\n <section\n #dialog\n class=\"cluster-popover d-flex flex-column\"\n role=\"dialog\"\n [attr.aria-labelledby]=\"titleId\"\n [style.--_si-cluster-popover-available-block-size.px]=\"availableBlockSize()\"\n (keydown.escape)=\"$event.stopPropagation(); context.close()\"\n >\n <div class=\"popover-header flex-shrink-0\">\n <strong class=\"flex-grow-1\" [id]=\"titleId\">\n {{ clusterPopoverTitle | translate: { count: context.total } }}\n </strong>\n <button\n type=\"button\"\n class=\"btn btn-circle btn-sm btn-ghost ms-2\"\n [attr.aria-label]=\"closeText | translate\"\n (click)=\"context.close()\"\n >\n <si-icon [icon]=\"icons.elementCancel\" />\n </button>\n </div>\n <div\n class=\"cluster-popover-body d-flex flex-column p-2\"\n [siLoading]=\"context.loading\"\n [blocking]=\"true\"\n >\n <div\n #scrollRegion\n class=\"cluster-popover-scroll overflow-auto\"\n role=\"region\"\n tabindex=\"0\"\n [attr.aria-label]=\"locationsLabel | translate\"\n >\n <div [inert]=\"context.loading\" [attr.aria-busy]=\"context.loading\">\n @if (template(); as customTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"customTemplate\"\n [ngTemplateOutletContext]=\"context\"\n />\n } @else {\n <ul class=\"list-unstyled mb-0\">\n @for (feature of context.features; track feature.id ?? $index) {\n <li class=\"list-item p-4\">\n <div class=\"list-item-title pt-0\">\n {{ feature.properties?.[labelProperty()] }}\n </div>\n <div class=\"list-item-description mb-0\">\n {{ feature.properties?.[descriptionProperty()] }}\n </div>\n </li>\n }\n </ul>\n }\n </div>\n @if (context.error && !context.loading) {\n <p role=\"alert\" class=\"mt-4 mb-0\">{{ errorText | translate }}</p>\n }\n @if (\n context.error ||\n (context.features.length > 0 && context.features.length < context.total)\n ) {\n <button\n #batchButton\n type=\"button\"\n class=\"btn btn-link d-flex w-100 justify-content-center p-4 focus-inside\"\n [class.disabled]=\"context.loading\"\n [attr.aria-disabled]=\"context.loading\"\n (click)=\"loadBatch()\"\n >\n {{ (context.error ? retryText : loadMoreText) | translate }}\n </button>\n }\n </div>\n </div>\n </section>\n </mgl-popup>\n}\n", styles: [".cluster-popover{min-inline-size:200px;max-block-size:calc(var(--_si-cluster-popover-available-block-size, 100dvb) - var(--si-sys-sizing-spacing-y-60) * 2)}.cluster-popover-body,.cluster-popover-scroll{min-block-size:0}.cluster-popover-scroll{overscroll-behavior-block:contain}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PopupComponent, selector: "mgl-popup", inputs: ["closeButton", "closeOnClick", "closeOnMove", "focusAfterOpen", "anchor", "className", "maxWidth", "subpixelPositioning", "feature", "lngLat", "marker", "offset"], outputs: ["popupClose", "popupOpen"] }, { kind: "component", type: SiIconComponent, selector: "si-icon", inputs: ["icon"] }, { kind: "directive", type: SiLoadingSpinnerDirective, selector: "[siLoading]", inputs: ["siLoading", "blocking", "initialDelay"] }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }] });
|
|
583
|
+
}
|
|
584
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SiClusterPopoverComponent, decorators: [{
|
|
585
|
+
type: Component,
|
|
586
|
+
args: [{ selector: 'si-cluster-popover', imports: [
|
|
587
|
+
NgTemplateOutlet,
|
|
588
|
+
PopupComponent,
|
|
589
|
+
SiIconComponent,
|
|
590
|
+
SiLoadingSpinnerDirective,
|
|
591
|
+
SiTranslatePipe
|
|
592
|
+
], template: "@if (context(); as context) {\n <mgl-popup\n [maxWidth]=\"maxWidth()\"\n [lngLat]=\"popupCoordinates()\"\n [closeOnMove]=\"closeOnMove()\"\n [focusAfterOpen]=\"false\"\n [closeButton]=\"false\"\n (popupClose)=\"context.close()\"\n >\n <section\n #dialog\n class=\"cluster-popover d-flex flex-column\"\n role=\"dialog\"\n [attr.aria-labelledby]=\"titleId\"\n [style.--_si-cluster-popover-available-block-size.px]=\"availableBlockSize()\"\n (keydown.escape)=\"$event.stopPropagation(); context.close()\"\n >\n <div class=\"popover-header flex-shrink-0\">\n <strong class=\"flex-grow-1\" [id]=\"titleId\">\n {{ clusterPopoverTitle | translate: { count: context.total } }}\n </strong>\n <button\n type=\"button\"\n class=\"btn btn-circle btn-sm btn-ghost ms-2\"\n [attr.aria-label]=\"closeText | translate\"\n (click)=\"context.close()\"\n >\n <si-icon [icon]=\"icons.elementCancel\" />\n </button>\n </div>\n <div\n class=\"cluster-popover-body d-flex flex-column p-2\"\n [siLoading]=\"context.loading\"\n [blocking]=\"true\"\n >\n <div\n #scrollRegion\n class=\"cluster-popover-scroll overflow-auto\"\n role=\"region\"\n tabindex=\"0\"\n [attr.aria-label]=\"locationsLabel | translate\"\n >\n <div [inert]=\"context.loading\" [attr.aria-busy]=\"context.loading\">\n @if (template(); as customTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"customTemplate\"\n [ngTemplateOutletContext]=\"context\"\n />\n } @else {\n <ul class=\"list-unstyled mb-0\">\n @for (feature of context.features; track feature.id ?? $index) {\n <li class=\"list-item p-4\">\n <div class=\"list-item-title pt-0\">\n {{ feature.properties?.[labelProperty()] }}\n </div>\n <div class=\"list-item-description mb-0\">\n {{ feature.properties?.[descriptionProperty()] }}\n </div>\n </li>\n }\n </ul>\n }\n </div>\n @if (context.error && !context.loading) {\n <p role=\"alert\" class=\"mt-4 mb-0\">{{ errorText | translate }}</p>\n }\n @if (\n context.error ||\n (context.features.length > 0 && context.features.length < context.total)\n ) {\n <button\n #batchButton\n type=\"button\"\n class=\"btn btn-link d-flex w-100 justify-content-center p-4 focus-inside\"\n [class.disabled]=\"context.loading\"\n [attr.aria-disabled]=\"context.loading\"\n (click)=\"loadBatch()\"\n >\n {{ (context.error ? retryText : loadMoreText) | translate }}\n </button>\n }\n </div>\n </div>\n </section>\n </mgl-popup>\n}\n", styles: [".cluster-popover{min-inline-size:200px;max-block-size:calc(var(--_si-cluster-popover-available-block-size, 100dvb) - var(--si-sys-sizing-spacing-y-60) * 2)}.cluster-popover-body,.cluster-popover-scroll{min-block-size:0}.cluster-popover-scroll{overscroll-behavior-block:contain}\n"] }]
|
|
593
|
+
}], ctorParameters: () => [], propDecorators: { maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], closeOnMove: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnMove", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], labelProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelProperty", required: false }] }], descriptionProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "descriptionProperty", required: false }] }], dialog: [{ type: i0.ViewChild, args: ['dialog', { isSignal: true }] }], scrollRegion: [{ type: i0.ViewChild, args: ['scrollRegion', { isSignal: true }] }], batchButton: [{ type: i0.ViewChild, args: ['batchButton', { isSignal: true }] }], template: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SiClusterPopoverTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }] } });
|
|
311
594
|
|
|
312
595
|
const createDefaultLocale = () => ({
|
|
313
596
|
'AttributionControl.ToggleAttribution': t(() => $localize `:@@SI_MAP.TOGGLE_ATTRIBUTION:Toggle attribution`),
|
|
@@ -397,5 +680,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
397
680
|
* Generated bundle index. Do not edit.
|
|
398
681
|
*/
|
|
399
682
|
|
|
400
|
-
export { SiClusterSourceComponent, SiStatusMarkerComponent, injectSiMapStyle, injectSiMapTranslations };
|
|
683
|
+
export { SiClusterPopoverComponent, SiClusterPopoverTemplateDirective, SiClusterSourceComponent, SiStatusMarkerComponent, injectSiMapStyle, injectSiMapTranslations };
|
|
401
684
|
//# sourceMappingURL=siemens-element-ng-maplibre.mjs.map
|