@siemens/element-ng 51.2.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/README.md +2 -2
- 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-datepicker.mjs +13 -3
- package/fesm2022/siemens-element-ng-datepicker.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-filtered-search.mjs +261 -162
- package/fesm2022/siemens-element-ng-filtered-search.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-form.mjs +4 -4
- package/fesm2022/siemens-element-ng-form.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-number-input.mjs +3 -2
- package/fesm2022/siemens-element-ng-number-input.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-popover.mjs +19 -6
- 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 +15 -10
- package/fesm2022/siemens-element-ng-tree-view.mjs.map +1 -1
- package/fesm2022/siemens-element-ng-typeahead.mjs +9 -0
- package/fesm2022/siemens-element-ng-typeahead.mjs.map +1 -1
- package/maplibre/styles/maplibre-gl.scss +4 -0
- package/package.json +8 -8
- package/schematics/migrations/data/attribute-selectors.js +8 -1
- package/schematics/migrations/data/element-selectors.js +7 -1
- package/schematics/migrations/data/symbol-renaming.js +10 -0
- package/schematics/migrations/utilities/attribute-selector.migration.js +26 -10
- package/schematics/migrations/utilities/element-selector.migration.js +25 -15
- package/schematics/migrations/utilities/symbol-renaming.migration.js +90 -3
- package/schematics/utils/template-edit-utils.js +9 -0
- 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-datepicker.d.ts +6 -1
- package/types/siemens-element-ng-filtered-search.d.ts +26 -10
- package/types/siemens-element-ng-form.d.ts +1 -1
- package/types/siemens-element-ng-maplibre.d.ts +112 -5
- package/types/siemens-element-ng-number-input.d.ts +2 -2
- package/types/siemens-element-ng-popover.d.ts +2 -1
- 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
- package/types/siemens-element-ng-tree-view.d.ts +1 -0
- package/types/siemens-element-ng-typeahead.d.ts +7 -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
|