@geoit/ui 0.0.4 → 0.0.5
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/AGENTS.md +12 -8
- package/README.md +49 -62
- package/ai/AGENTS.md +38 -28
- package/ai/README.md +35 -1
- package/ai/catalog.json +2796 -288
- package/ai/components/geo-alert.md +3 -3
- package/ai/components/geo-back-button.md +2 -2
- package/ai/components/geo-breadcrumb.md +1 -1
- package/ai/components/geo-button.md +3 -3
- package/ai/components/geo-chart.md +103 -0
- package/ai/components/geo-checkbox.md +4 -6
- package/ai/components/geo-column-picker.md +3 -3
- package/ai/components/geo-confirm-modal.md +4 -5
- package/ai/components/geo-dashboard.md +91 -0
- package/ai/components/geo-date-picker.md +5 -3
- package/ai/components/geo-date-range-picker.md +5 -3
- package/ai/components/geo-empty-state.md +75 -0
- package/ai/components/geo-feedback-form.md +97 -0
- package/ai/components/geo-file-picker.md +4 -2
- package/ai/components/geo-forgot-password.md +78 -0
- package/ai/components/geo-form-modal.md +9 -10
- package/ai/components/geo-icon.md +3 -3
- package/ai/components/geo-input.md +8 -6
- package/ai/components/geo-layout-footer.md +70 -0
- package/ai/components/geo-layout-header-actions.md +82 -0
- package/ai/components/geo-layout-header.md +89 -0
- package/ai/components/geo-layout-sidebar.md +86 -0
- package/ai/components/geo-layout.md +155 -0
- package/ai/components/geo-list-page.md +72 -0
- package/ai/components/geo-login.md +94 -0
- package/ai/components/geo-map-admin-filter.md +80 -0
- package/ai/components/geo-map-basemap-switcher.md +75 -0
- package/ai/components/geo-map-help.md +72 -0
- package/ai/components/geo-map-layer-card.md +73 -0
- package/ai/components/geo-map-layer-panel.md +75 -0
- package/ai/components/geo-map-layers-drawer.md +78 -0
- package/ai/components/geo-map-legend.md +74 -0
- package/ai/components/geo-map-locate.md +75 -0
- package/ai/components/geo-map-location-chip.md +71 -0
- package/ai/components/geo-map-measure.md +74 -0
- package/ai/components/geo-map-opacity.md +75 -0
- package/ai/components/geo-map-parcel-popup.md +79 -0
- package/ai/components/geo-map-search.md +83 -0
- package/ai/components/geo-map-shell.md +110 -0
- package/ai/components/geo-map-snapshot.md +75 -0
- package/ai/components/geo-map-swipe.md +73 -0
- package/ai/components/geo-map-toolbar.md +76 -0
- package/ai/components/geo-map-zoom.md +74 -0
- package/ai/components/geo-map.md +205 -0
- package/ai/components/geo-overlap-result.md +88 -0
- package/ai/components/geo-page-header.md +72 -0
- package/ai/components/geo-page-title.md +1 -1
- package/ai/components/geo-pagination.md +4 -7
- package/ai/components/geo-radio.md +3 -1
- package/ai/components/geo-row-actions.md +3 -3
- package/ai/components/geo-select.md +4 -2
- package/ai/components/geo-slider.md +5 -7
- package/ai/components/geo-stat-card.md +98 -0
- package/ai/components/geo-status-tag.md +2 -2
- package/ai/components/geo-step-form-layout.md +7 -8
- package/ai/components/geo-stepper.md +3 -4
- package/ai/components/geo-table-filter.md +4 -5
- package/ai/components/geo-table-pagination.md +4 -7
- package/ai/components/geo-table-toolbar.md +7 -7
- package/ai/components/geo-table.md +17 -20
- package/ai/components/geo-tabs.md +4 -6
- package/ai/components/geo-textarea.md +4 -2
- package/ai/components/geo-toast.md +4 -4
- package/ai/components/geo-tree.md +4 -6
- package/ai/components/geo-typography.md +1 -1
- package/ai/components/geo-upload.md +9 -10
- package/ai/mockup.html +1194 -0
- package/ai/recipes.md +98 -85
- package/esm2022/lib/figma/geo-alert/geo-alert.component.mjs +19 -36
- package/esm2022/lib/figma/geo-back-button/geo-back-button.component.mjs +14 -24
- package/esm2022/lib/figma/geo-breadcrumb/geo-breadcrumb.component.mjs +8 -11
- package/esm2022/lib/figma/geo-button/geo-button.component.mjs +30 -59
- package/esm2022/lib/figma/geo-chart/geo-chart.component.mjs +88 -0
- package/esm2022/lib/figma/geo-chart/geo-chart.types.mjs +2 -0
- package/esm2022/lib/figma/geo-checkbox/geo-checkbox.component.mjs +11 -22
- package/esm2022/lib/figma/geo-confirm-modal/geo-confirm-modal.component.mjs +22 -54
- package/esm2022/lib/figma/geo-dashboard/geo-dashboard.component.mjs +49 -0
- package/esm2022/lib/figma/geo-dashboard/geo-dashboard.types.mjs +2 -0
- package/esm2022/lib/figma/geo-date-picker/geo-date-picker.component.mjs +48 -78
- package/esm2022/lib/figma/geo-date-range-picker/geo-date-range-picker.component.mjs +47 -75
- package/esm2022/lib/figma/geo-empty-state/geo-empty-state.component.mjs +25 -0
- package/esm2022/lib/figma/geo-feedback-form/geo-feedback-form.component.mjs +75 -0
- package/esm2022/lib/figma/geo-feedback-form/geo-feedback-form.types.mjs +2 -0
- package/esm2022/lib/figma/geo-file-picker/geo-file-picker.component.mjs +59 -81
- package/esm2022/lib/figma/geo-forgot-password/geo-forgot-password.component.mjs +51 -0
- package/esm2022/lib/figma/geo-form-modal/geo-form-modal.component.mjs +45 -112
- package/esm2022/lib/figma/geo-icon/geo-icon.component.mjs +22 -32
- package/esm2022/lib/figma/geo-input/geo-input.component.mjs +41 -70
- package/esm2022/lib/figma/geo-layout/footer/geo-layout-footer.component.mjs +18 -0
- package/esm2022/lib/figma/geo-layout/geo-layout-actions.directive.mjs +15 -0
- package/esm2022/lib/figma/geo-layout/geo-layout.component.mjs +79 -0
- package/esm2022/lib/figma/geo-layout/geo-layout.types.mjs +42 -0
- package/esm2022/lib/figma/geo-layout/header/geo-layout-header.component.mjs +60 -0
- package/esm2022/lib/figma/geo-layout/header-actions/geo-layout-header-actions.component.mjs +70 -0
- package/esm2022/lib/figma/geo-layout/sidebar/geo-layout-sidebar.component.mjs +90 -0
- package/esm2022/lib/figma/geo-list-page/geo-list-page.component.mjs +22 -0
- package/esm2022/lib/figma/geo-login/geo-login.component.mjs +58 -0
- package/esm2022/lib/figma/geo-login/geo-login.types.mjs +2 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-admin-filter/geo-map-admin-filter.component.mjs +52 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-basemap-switcher/geo-map-basemap-switcher.component.mjs +61 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-help/geo-map-help.component.mjs +26 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-layer-card/geo-map-layer-card.component.mjs +24 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-layer-panel/geo-map-layer-panel.component.mjs +146 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-layers-drawer/geo-map-layers-drawer.component.mjs +37 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-legend/geo-map-legend.component.mjs +30 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-locate/geo-map-locate.component.mjs +72 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-location-chip/geo-map-location-chip.component.mjs +21 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-measure/geo-map-measure.component.mjs +375 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-opacity/geo-map-opacity.component.mjs +94 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-parcel-popup/geo-map-parcel-popup.component.mjs +136 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-search/geo-map-search.component.mjs +182 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-shell/geo-map-shell.component.mjs +577 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-snapshot/geo-map-snapshot.component.mjs +93 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-swipe/geo-map-swipe.component.mjs +129 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-toolbar/geo-map-toolbar.component.mjs +64 -0
- package/esm2022/lib/figma/geo-map/chrome/geo-map-zoom/geo-map-zoom.component.mjs +295 -0
- package/esm2022/lib/figma/geo-map/geo-map-toolbar.icons.mjs +18 -0
- package/esm2022/lib/figma/geo-map/geo-map.component.mjs +144 -0
- package/esm2022/lib/figma/geo-map/geo-map.constants.mjs +497 -0
- package/esm2022/lib/figma/geo-map/geo-map.controller.mjs +71 -0
- package/esm2022/lib/figma/geo-map/geo-map.types.mjs +2 -0
- package/esm2022/lib/figma/geo-map/services/geo-map-layer.service.mjs +368 -0
- package/esm2022/lib/figma/geo-map/services/geo-map-projection.service.mjs +110 -0
- package/esm2022/lib/figma/geo-map/services/geo-map.service.mjs +540 -0
- package/esm2022/lib/figma/geo-map/utils/geo-map-fullscreen-overlay.util.mjs +47 -0
- package/esm2022/lib/figma/geo-map/utils/geo-map-interactions.util.mjs +30 -0
- package/esm2022/lib/figma/geo-overlap-result/geo-overlap-result.component.mjs +25 -0
- package/esm2022/lib/figma/geo-overlap-result/geo-overlap-result.types.mjs +2 -0
- package/esm2022/lib/figma/geo-page-header/geo-page-header.component.mjs +23 -0
- package/esm2022/lib/figma/geo-page-title/geo-page-title.component.mjs +20 -35
- package/esm2022/lib/figma/geo-pagination/geo-pagination.component.mjs +13 -43
- package/esm2022/lib/figma/geo-radio/geo-radio.component.mjs +32 -52
- package/esm2022/lib/figma/geo-select/geo-select.component.mjs +46 -72
- package/esm2022/lib/figma/geo-slider/geo-slider.component.mjs +12 -28
- package/esm2022/lib/figma/geo-stat-card/geo-stat-card.component.mjs +163 -0
- package/esm2022/lib/figma/geo-stat-card/geo-stat-card.types.mjs +2 -0
- package/esm2022/lib/figma/geo-status-tag/geo-status-tag.component.mjs +23 -27
- package/esm2022/lib/figma/geo-step-form-layout/geo-step-form-layout.component.mjs +39 -96
- package/esm2022/lib/figma/geo-stepper/geo-stepper.component.mjs +18 -33
- package/esm2022/lib/figma/geo-table/geo-column-picker/geo-column-picker.component.mjs +14 -24
- package/esm2022/lib/figma/geo-table/geo-row-actions/geo-row-actions.component.mjs +18 -36
- package/esm2022/lib/figma/geo-table/geo-table-filter/geo-table-filter.component.mjs +41 -98
- package/esm2022/lib/figma/geo-table/geo-table-pagination/geo-table-pagination.component.mjs +40 -73
- package/esm2022/lib/figma/geo-table/geo-table-toolbar/geo-table-toolbar.component.mjs +26 -56
- package/esm2022/lib/figma/geo-table/geo-table.component.mjs +110 -210
- package/esm2022/lib/figma/geo-tabs/geo-tabs.component.mjs +33 -63
- package/esm2022/lib/figma/geo-textarea/geo-textarea.component.mjs +28 -44
- package/esm2022/lib/figma/geo-toast/geo-toast.component.mjs +18 -39
- package/esm2022/lib/figma/geo-tree/geo-tree.component.mjs +12 -40
- package/esm2022/lib/figma/geo-typography/geo-typography.component.mjs +49 -64
- package/esm2022/lib/figma/geo-upload/geo-upload.component.mjs +50 -101
- package/esm2022/lib/figma/index.mjs +50 -1
- package/esm2022/lib/styles/tokens.mjs +56 -24
- package/fesm2022/geoit-ui.mjs +5981 -1825
- package/fesm2022/geoit-ui.mjs.map +1 -1
- package/lib/figma/geo-alert/geo-alert.component.d.ts +10 -11
- package/lib/figma/geo-back-button/geo-back-button.component.d.ts +6 -7
- package/lib/figma/geo-breadcrumb/geo-breadcrumb.component.d.ts +2 -2
- package/lib/figma/geo-button/geo-button.component.d.ts +21 -17
- package/lib/figma/geo-chart/geo-chart.component.d.ts +40 -0
- package/lib/figma/geo-chart/geo-chart.types.d.ts +13 -0
- package/lib/figma/geo-checkbox/geo-checkbox.component.d.ts +6 -7
- package/lib/figma/geo-confirm-modal/geo-confirm-modal.component.d.ts +15 -17
- package/lib/figma/geo-dashboard/geo-dashboard.component.d.ts +29 -0
- package/lib/figma/geo-dashboard/geo-dashboard.types.d.ts +7 -0
- package/lib/figma/geo-date-picker/geo-date-picker.component.d.ts +26 -21
- package/lib/figma/geo-date-range-picker/geo-date-range-picker.component.d.ts +25 -20
- package/lib/figma/geo-empty-state/geo-empty-state.component.d.ts +17 -0
- package/lib/figma/geo-feedback-form/geo-feedback-form.component.d.ts +36 -0
- package/lib/figma/geo-feedback-form/geo-feedback-form.types.d.ts +8 -0
- package/lib/figma/geo-file-picker/geo-file-picker.component.d.ts +23 -20
- package/lib/figma/geo-forgot-password/geo-forgot-password.component.d.ts +24 -0
- package/lib/figma/geo-form-modal/geo-form-modal.component.d.ts +33 -35
- package/lib/figma/geo-icon/geo-icon.component.d.ts +7 -7
- package/lib/figma/geo-input/geo-input.component.d.ts +23 -21
- package/lib/figma/geo-layout/footer/geo-layout-footer.component.d.ts +10 -0
- package/lib/figma/geo-layout/geo-layout-actions.directive.d.ts +6 -0
- package/lib/figma/geo-layout/geo-layout.component.d.ts +48 -0
- package/lib/figma/geo-layout/geo-layout.types.d.ts +44 -0
- package/lib/figma/geo-layout/header/geo-layout-header.component.d.ts +31 -0
- package/lib/figma/geo-layout/header-actions/geo-layout-header-actions.component.d.ts +32 -0
- package/lib/figma/geo-layout/sidebar/geo-layout-sidebar.component.d.ts +34 -0
- package/lib/figma/geo-list-page/geo-list-page.component.d.ts +16 -0
- package/lib/figma/geo-login/geo-login.component.d.ts +27 -0
- package/lib/figma/geo-login/geo-login.types.d.ts +6 -0
- package/lib/figma/geo-map/chrome/geo-map-admin-filter/geo-map-admin-filter.component.d.ts +28 -0
- package/lib/figma/geo-map/chrome/geo-map-basemap-switcher/geo-map-basemap-switcher.component.d.ts +26 -0
- package/lib/figma/geo-map/chrome/geo-map-help/geo-map-help.component.d.ts +20 -0
- package/lib/figma/geo-map/chrome/geo-map-layer-card/geo-map-layer-card.component.d.ts +15 -0
- package/lib/figma/geo-map/chrome/geo-map-layer-panel/geo-map-layer-panel.component.d.ts +40 -0
- package/lib/figma/geo-map/chrome/geo-map-layers-drawer/geo-map-layers-drawer.component.d.ts +25 -0
- package/lib/figma/geo-map/chrome/geo-map-legend/geo-map-legend.component.d.ts +18 -0
- package/lib/figma/geo-map/chrome/geo-map-locate/geo-map-locate.component.d.ts +24 -0
- package/lib/figma/geo-map/chrome/geo-map-location-chip/geo-map-location-chip.component.d.ts +14 -0
- package/lib/figma/geo-map/chrome/geo-map-measure/geo-map-measure.component.d.ts +49 -0
- package/lib/figma/geo-map/chrome/geo-map-opacity/geo-map-opacity.component.d.ts +30 -0
- package/lib/figma/geo-map/chrome/geo-map-parcel-popup/geo-map-parcel-popup.component.d.ts +44 -0
- package/lib/figma/geo-map/chrome/geo-map-search/geo-map-search.component.d.ts +56 -0
- package/lib/figma/geo-map/chrome/geo-map-shell/geo-map-shell.component.d.ts +103 -0
- package/lib/figma/geo-map/chrome/geo-map-snapshot/geo-map-snapshot.component.d.ts +21 -0
- package/lib/figma/geo-map/chrome/geo-map-swipe/geo-map-swipe.component.d.ts +33 -0
- package/lib/figma/geo-map/chrome/geo-map-toolbar/geo-map-toolbar.component.d.ts +30 -0
- package/lib/figma/geo-map/chrome/geo-map-zoom/geo-map-zoom.component.d.ts +67 -0
- package/lib/figma/geo-map/geo-map-toolbar.icons.d.ts +17 -0
- package/lib/figma/geo-map/geo-map.component.d.ts +53 -0
- package/lib/figma/geo-map/geo-map.constants.d.ts +73 -0
- package/lib/figma/geo-map/geo-map.controller.d.ts +49 -0
- package/lib/figma/geo-map/geo-map.types.d.ts +224 -0
- package/lib/figma/geo-map/services/geo-map-layer.service.d.ts +42 -0
- package/lib/figma/geo-map/services/geo-map-projection.service.d.ts +32 -0
- package/lib/figma/geo-map/services/geo-map.service.d.ts +99 -0
- package/lib/figma/geo-map/utils/geo-map-fullscreen-overlay.util.d.ts +13 -0
- package/lib/figma/geo-map/utils/geo-map-interactions.util.d.ts +9 -0
- package/lib/figma/geo-overlap-result/geo-overlap-result.component.d.ts +18 -0
- package/lib/figma/geo-overlap-result/geo-overlap-result.types.d.ts +7 -0
- package/lib/figma/geo-page-header/geo-page-header.component.d.ts +16 -0
- package/lib/figma/geo-page-title/geo-page-title.component.d.ts +9 -9
- package/lib/figma/geo-pagination/geo-pagination.component.d.ts +9 -14
- package/lib/figma/geo-radio/geo-radio.component.d.ts +17 -15
- package/lib/figma/geo-select/geo-select.component.d.ts +24 -19
- package/lib/figma/geo-slider/geo-slider.component.d.ts +7 -9
- package/lib/figma/geo-stat-card/geo-stat-card.component.d.ts +50 -0
- package/lib/figma/geo-stat-card/geo-stat-card.types.d.ts +11 -0
- package/lib/figma/geo-status-tag/geo-status-tag.component.d.ts +7 -7
- package/lib/figma/geo-step-form-layout/geo-step-form-layout.component.d.ts +27 -29
- package/lib/figma/geo-stepper/geo-stepper.component.d.ts +6 -8
- package/lib/figma/geo-table/geo-column-picker/geo-column-picker.component.d.ts +6 -7
- package/lib/figma/geo-table/geo-row-actions/geo-row-actions.component.d.ts +11 -12
- package/lib/figma/geo-table/geo-table-filter/geo-table-filter.component.d.ts +21 -28
- package/lib/figma/geo-table/geo-table-pagination/geo-table-pagination.component.d.ts +17 -20
- package/lib/figma/geo-table/geo-table-toolbar/geo-table-toolbar.component.d.ts +17 -18
- package/lib/figma/geo-table/geo-table.component.d.ts +58 -62
- package/lib/figma/geo-tabs/geo-tabs.component.d.ts +14 -17
- package/lib/figma/geo-textarea/geo-textarea.component.d.ts +15 -13
- package/lib/figma/geo-toast/geo-toast.component.d.ts +11 -12
- package/lib/figma/geo-tree/geo-tree.component.d.ts +8 -13
- package/lib/figma/geo-typography/geo-typography.component.d.ts +13 -13
- package/lib/figma/geo-upload/geo-upload.component.d.ts +26 -28
- package/lib/figma/index.d.ts +49 -0
- package/lib/styles/tokens.d.ts +56 -23
- package/package.json +4 -2
- package/src/lib/figma/geo-map/assets/toolbar/fullscreen.svg +8 -0
- package/src/lib/figma/geo-map/assets/toolbar/home.svg +3 -0
- package/src/lib/figma/geo-map/assets/toolbar/layers.svg +3 -0
- package/src/lib/figma/geo-map/assets/toolbar/measure-area.svg +12 -0
- package/src/lib/figma/geo-map/assets/toolbar/measure-distance.svg +5 -0
- package/src/lib/figma/geo-map/assets/toolbar/pan.svg +13 -0
- package/src/lib/figma/geo-map/assets/toolbar/search.svg +3 -0
- package/src/lib/figma/geo-map/assets/toolbar/zoom-in.svg +3 -0
- package/src/lib/figma/geo-map/assets/toolbar/zoom-out.svg +5 -0
- package/src/lib/styles/design-tokens.scss +108 -35
- package/src/lib/styles/scrollbar.scss +2 -2
- package/src/lib/styles/theme.scss +1 -1
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, effect, inject, input, model, output, signal, ViewEncapsulation, } from '@angular/core';
|
|
2
|
+
import GeometryCollection from 'ol/geom/GeometryCollection';
|
|
3
|
+
import { LineString, Point, Polygon } from 'ol/geom';
|
|
4
|
+
import Draw from 'ol/interaction/Draw';
|
|
5
|
+
import VectorLayer from 'ol/layer/Vector';
|
|
6
|
+
import { getArea, getLength } from 'ol/sphere';
|
|
7
|
+
import VectorSource from 'ol/source/Vector';
|
|
8
|
+
import { Circle as CircleStyle, Fill, Icon, Stroke, Style, Text, } from 'ol/style';
|
|
9
|
+
import { GEO_MAP_MEASURE_LAYER_ID } from '../../geo-map.constants';
|
|
10
|
+
import { pauseConflictingInteractions } from '../../utils/geo-map-interactions.util';
|
|
11
|
+
import * as i0 from "@angular/core";
|
|
12
|
+
/**
|
|
13
|
+
* Distance / area measure tools on the map.
|
|
14
|
+
*
|
|
15
|
+
* @summary Distance / area measure tools on the map.
|
|
16
|
+
* @whenToUse Đo khoảng cách / diện tích (E-tien-ich).
|
|
17
|
+
* @doNotUseWhen Permanent vector editing — app-owned draw tools.
|
|
18
|
+
*/
|
|
19
|
+
export class GeoMapMeasureComponent {
|
|
20
|
+
destroyRef = inject(DestroyRef);
|
|
21
|
+
controller = input(null);
|
|
22
|
+
mode = model('none');
|
|
23
|
+
showResult = input(true);
|
|
24
|
+
measureChange = output();
|
|
25
|
+
result = signal(null);
|
|
26
|
+
source = null;
|
|
27
|
+
layer = null;
|
|
28
|
+
draw = null;
|
|
29
|
+
boundMap = null;
|
|
30
|
+
resumeInteractions = null;
|
|
31
|
+
constructor() {
|
|
32
|
+
// Writes `result` when (re)entering a measure mode — allow inside effect.
|
|
33
|
+
effect(() => {
|
|
34
|
+
const ctrl = this.controller();
|
|
35
|
+
const mode = this.mode();
|
|
36
|
+
this.syncInteraction(ctrl, mode);
|
|
37
|
+
}, { allowSignalWrites: true });
|
|
38
|
+
this.destroyRef.onDestroy(() => this.teardown());
|
|
39
|
+
}
|
|
40
|
+
ngOnDestroy() {
|
|
41
|
+
this.teardown();
|
|
42
|
+
}
|
|
43
|
+
clear() {
|
|
44
|
+
this.source?.clear();
|
|
45
|
+
this.result.set(null);
|
|
46
|
+
this.measureChange.emit(null);
|
|
47
|
+
this.mode.set('none');
|
|
48
|
+
}
|
|
49
|
+
syncInteraction(ctrl, mode) {
|
|
50
|
+
const map = ctrl?.getMap() ?? null;
|
|
51
|
+
if (!map) {
|
|
52
|
+
this.teardown();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (this.boundMap !== map) {
|
|
56
|
+
this.teardown();
|
|
57
|
+
this.ensureLayer(map);
|
|
58
|
+
this.boundMap = map;
|
|
59
|
+
}
|
|
60
|
+
else if (!this.source || !this.layer) {
|
|
61
|
+
this.ensureLayer(map);
|
|
62
|
+
}
|
|
63
|
+
this.removeDraw(map);
|
|
64
|
+
if (mode === 'none') {
|
|
65
|
+
// Leave cursor to the shell / host (pan grab hand, etc.).
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.source?.clear();
|
|
69
|
+
this.result.set(null);
|
|
70
|
+
this.measureChange.emit(null);
|
|
71
|
+
// Double-click finishes the sketch; pause OL DoubleClickZoom while measuring.
|
|
72
|
+
this.resumeInteractions = pauseConflictingInteractions(map, {
|
|
73
|
+
dragPan: false,
|
|
74
|
+
doubleClickZoom: true,
|
|
75
|
+
});
|
|
76
|
+
const type = mode === 'distance' ? 'LineString' : 'Polygon';
|
|
77
|
+
const style = this.createStyle();
|
|
78
|
+
this.draw = new Draw({
|
|
79
|
+
source: this.source,
|
|
80
|
+
type,
|
|
81
|
+
style,
|
|
82
|
+
stopClick: true,
|
|
83
|
+
});
|
|
84
|
+
const capturedMode = mode;
|
|
85
|
+
this.draw.on('drawend', (evt) => {
|
|
86
|
+
const geometry = evt.feature.getGeometry();
|
|
87
|
+
if (!geometry) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const measured = this.formatResult(capturedMode, geometry);
|
|
91
|
+
this.result.set(measured);
|
|
92
|
+
this.measureChange.emit(measured);
|
|
93
|
+
// Exit draw mode after the Draw interaction finishes removing the sketch.
|
|
94
|
+
queueMicrotask(() => {
|
|
95
|
+
if (this.mode() === capturedMode) {
|
|
96
|
+
this.mode.set('none');
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
map.addInteraction(this.draw);
|
|
101
|
+
this.layer?.setVisible(true);
|
|
102
|
+
this.setMapCursor(map, 'crosshair');
|
|
103
|
+
}
|
|
104
|
+
ensureLayer(map) {
|
|
105
|
+
if (this.layer) {
|
|
106
|
+
map.removeLayer(this.layer);
|
|
107
|
+
}
|
|
108
|
+
this.source = new VectorSource();
|
|
109
|
+
const layer = new VectorLayer({
|
|
110
|
+
source: this.source,
|
|
111
|
+
properties: { geoLayerId: GEO_MAP_MEASURE_LAYER_ID },
|
|
112
|
+
style: this.createStyle(),
|
|
113
|
+
zIndex: 500,
|
|
114
|
+
updateWhileAnimating: true,
|
|
115
|
+
updateWhileInteracting: true,
|
|
116
|
+
});
|
|
117
|
+
this.layer = layer;
|
|
118
|
+
map.addLayer(layer);
|
|
119
|
+
}
|
|
120
|
+
createStyle() {
|
|
121
|
+
return (feature) => {
|
|
122
|
+
const geometry = feature.getGeometry();
|
|
123
|
+
if (!geometry) {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
// Draw / Vector features expose an OL Geometry (not RenderFeature).
|
|
127
|
+
return this.buildMeasureStyles(geometry);
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/** Dashed stroke, numbered vertices, segment labels (distance + area). */
|
|
131
|
+
buildMeasureStyles(geometry) {
|
|
132
|
+
if (!geometry) {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
if (geometry instanceof GeometryCollection) {
|
|
136
|
+
return geometry
|
|
137
|
+
.getGeometries()
|
|
138
|
+
.flatMap((part) => this.buildMeasureStyles(part));
|
|
139
|
+
}
|
|
140
|
+
const color = this.cssColor('--geo-color-primary-default', '#9a4828');
|
|
141
|
+
const fill = this.cssColor('--geo-color-primary-default', '#9a4828', 0.12);
|
|
142
|
+
const fontFamily = this.cssFontFamily();
|
|
143
|
+
const styles = [
|
|
144
|
+
new Style({
|
|
145
|
+
fill: new Fill({ color: fill }),
|
|
146
|
+
stroke: new Stroke({
|
|
147
|
+
color,
|
|
148
|
+
width: 2,
|
|
149
|
+
lineDash: [7, 7],
|
|
150
|
+
}),
|
|
151
|
+
}),
|
|
152
|
+
];
|
|
153
|
+
if (geometry instanceof Point) {
|
|
154
|
+
styles.push(...this.vertexStyles(geometry.getCoordinates(), 1, color));
|
|
155
|
+
return styles;
|
|
156
|
+
}
|
|
157
|
+
let points = [];
|
|
158
|
+
if (geometry instanceof LineString) {
|
|
159
|
+
points = geometry.getCoordinates();
|
|
160
|
+
}
|
|
161
|
+
else if (geometry instanceof Polygon) {
|
|
162
|
+
const ring = geometry.getCoordinates()[0] ?? [];
|
|
163
|
+
points = this.openRing(ring);
|
|
164
|
+
}
|
|
165
|
+
if (!points.length) {
|
|
166
|
+
return styles;
|
|
167
|
+
}
|
|
168
|
+
for (let i = 0; i < points.length; i++) {
|
|
169
|
+
styles.push(...this.vertexStyles(points[i], i + 1, color));
|
|
170
|
+
}
|
|
171
|
+
const closed = geometry instanceof Polygon && points.length >= 2;
|
|
172
|
+
const segmentCount = closed ? points.length : Math.max(0, points.length - 1);
|
|
173
|
+
for (let i = 0; i < segmentCount; i++) {
|
|
174
|
+
const a = points[i];
|
|
175
|
+
const b = points[(i + 1) % points.length];
|
|
176
|
+
styles.push(this.segmentLabelStyle(a, b, color, fontFamily));
|
|
177
|
+
}
|
|
178
|
+
if (geometry instanceof Polygon && points.length >= 3) {
|
|
179
|
+
const areaLabel = this.areaCentroidLabel(geometry, color, fontFamily);
|
|
180
|
+
if (areaLabel) {
|
|
181
|
+
styles.push(areaLabel);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return styles;
|
|
185
|
+
}
|
|
186
|
+
openRing(ring) {
|
|
187
|
+
if (ring.length < 2) {
|
|
188
|
+
return ring;
|
|
189
|
+
}
|
|
190
|
+
const first = ring[0];
|
|
191
|
+
const last = ring[ring.length - 1];
|
|
192
|
+
if (first[0] === last[0] && first[1] === last[1]) {
|
|
193
|
+
return ring.slice(0, -1);
|
|
194
|
+
}
|
|
195
|
+
return ring;
|
|
196
|
+
}
|
|
197
|
+
vertexStyles(coord, index, color) {
|
|
198
|
+
return [
|
|
199
|
+
new Style({
|
|
200
|
+
geometry: new Point(coord),
|
|
201
|
+
image: new CircleStyle({
|
|
202
|
+
radius: 3.5,
|
|
203
|
+
fill: new Fill({ color }),
|
|
204
|
+
}),
|
|
205
|
+
}),
|
|
206
|
+
new Style({
|
|
207
|
+
geometry: new Point(coord),
|
|
208
|
+
image: new Icon({
|
|
209
|
+
src: this.numberBadgeDataUrl(index, color),
|
|
210
|
+
anchor: [0.5, 1.35],
|
|
211
|
+
anchorXUnits: 'fraction',
|
|
212
|
+
anchorYUnits: 'fraction',
|
|
213
|
+
scale: 1,
|
|
214
|
+
}),
|
|
215
|
+
}),
|
|
216
|
+
];
|
|
217
|
+
}
|
|
218
|
+
numberBadgeDataUrl(index, color) {
|
|
219
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22">` +
|
|
220
|
+
`<circle cx="11" cy="11" r="10" fill="${color}"/>` +
|
|
221
|
+
`<text x="11" y="15" text-anchor="middle" fill="#ffffff" ` +
|
|
222
|
+
`font-size="11" font-weight="700" font-family="sans-serif">${index}</text>` +
|
|
223
|
+
`</svg>`;
|
|
224
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
225
|
+
}
|
|
226
|
+
segmentLabelStyle(a, b, color, fontFamily) {
|
|
227
|
+
const mid = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];
|
|
228
|
+
const meters = getLength(new LineString([a, b]));
|
|
229
|
+
let rotation = -Math.atan2(b[1] - a[1], b[0] - a[0]);
|
|
230
|
+
// Keep labels upright/readable.
|
|
231
|
+
if (rotation > Math.PI / 2 || rotation < -Math.PI / 2) {
|
|
232
|
+
rotation += Math.PI;
|
|
233
|
+
}
|
|
234
|
+
return new Style({
|
|
235
|
+
geometry: new Point(mid),
|
|
236
|
+
text: new Text({
|
|
237
|
+
text: this.formatLengthLabel(meters),
|
|
238
|
+
font: `500 12px ${fontFamily}`,
|
|
239
|
+
fill: new Fill({ color }),
|
|
240
|
+
stroke: new Stroke({
|
|
241
|
+
color: 'rgba(255, 255, 255, 0.9)',
|
|
242
|
+
width: 3,
|
|
243
|
+
}),
|
|
244
|
+
rotation,
|
|
245
|
+
rotateWithView: true,
|
|
246
|
+
textAlign: 'center',
|
|
247
|
+
textBaseline: 'middle',
|
|
248
|
+
}),
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
areaCentroidLabel(geometry, color, fontFamily) {
|
|
252
|
+
const interior = geometry.getInteriorPoint()?.getCoordinates();
|
|
253
|
+
if (!interior) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
const sqMeters = getArea(geometry);
|
|
257
|
+
return new Style({
|
|
258
|
+
geometry: new Point(interior),
|
|
259
|
+
text: new Text({
|
|
260
|
+
text: this.formatAreaLabel(sqMeters),
|
|
261
|
+
font: `600 12px ${fontFamily}`,
|
|
262
|
+
fill: new Fill({ color }),
|
|
263
|
+
stroke: new Stroke({
|
|
264
|
+
color: 'rgba(255, 255, 255, 0.92)',
|
|
265
|
+
width: 3.5,
|
|
266
|
+
}),
|
|
267
|
+
textAlign: 'center',
|
|
268
|
+
textBaseline: 'middle',
|
|
269
|
+
}),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
formatLengthLabel(meters) {
|
|
273
|
+
if (meters >= 1000) {
|
|
274
|
+
return `${(meters / 1000).toFixed(1)} km`;
|
|
275
|
+
}
|
|
276
|
+
return `${meters.toFixed(1)} m`;
|
|
277
|
+
}
|
|
278
|
+
formatAreaLabel(sqMeters) {
|
|
279
|
+
if (sqMeters >= 10_000) {
|
|
280
|
+
return `${(sqMeters / 10_000).toFixed(2)} ha`;
|
|
281
|
+
}
|
|
282
|
+
return `${sqMeters.toFixed(1)} m²`;
|
|
283
|
+
}
|
|
284
|
+
/** Resolve a design token for OpenLayers canvas styles. */
|
|
285
|
+
cssColor(token, fallback, alpha) {
|
|
286
|
+
if (typeof document === 'undefined') {
|
|
287
|
+
return alpha != null ? this.withAlpha(fallback, alpha) : fallback;
|
|
288
|
+
}
|
|
289
|
+
const raw = getComputedStyle(document.documentElement)
|
|
290
|
+
.getPropertyValue(token)
|
|
291
|
+
.trim();
|
|
292
|
+
const color = raw || fallback;
|
|
293
|
+
return alpha != null ? this.withAlpha(color, alpha) : color;
|
|
294
|
+
}
|
|
295
|
+
cssFontFamily() {
|
|
296
|
+
if (typeof document === 'undefined') {
|
|
297
|
+
return 'sans-serif';
|
|
298
|
+
}
|
|
299
|
+
const raw = getComputedStyle(document.documentElement)
|
|
300
|
+
.getPropertyValue('--geo-font-family')
|
|
301
|
+
.trim();
|
|
302
|
+
return raw || 'sans-serif';
|
|
303
|
+
}
|
|
304
|
+
withAlpha(color, alpha) {
|
|
305
|
+
const hex = color.match(/^#([0-9a-f]{6})$/i);
|
|
306
|
+
if (hex) {
|
|
307
|
+
const n = parseInt(hex[1], 16);
|
|
308
|
+
const r = (n >> 16) & 255;
|
|
309
|
+
const g = (n >> 8) & 255;
|
|
310
|
+
const b = n & 255;
|
|
311
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
312
|
+
}
|
|
313
|
+
return color;
|
|
314
|
+
}
|
|
315
|
+
formatResult(mode, geometry) {
|
|
316
|
+
if (mode === 'distance' && geometry instanceof LineString) {
|
|
317
|
+
const meters = getLength(geometry);
|
|
318
|
+
return {
|
|
319
|
+
mode,
|
|
320
|
+
value: meters,
|
|
321
|
+
label: this.formatLengthLabel(meters),
|
|
322
|
+
geometry,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
if (mode === 'area' && geometry instanceof Polygon) {
|
|
326
|
+
const sqMeters = getArea(geometry);
|
|
327
|
+
return {
|
|
328
|
+
mode,
|
|
329
|
+
value: sqMeters,
|
|
330
|
+
label: this.formatAreaLabel(sqMeters),
|
|
331
|
+
geometry,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return { mode, value: 0, label: '-', geometry };
|
|
335
|
+
}
|
|
336
|
+
removeDraw(map) {
|
|
337
|
+
if (this.draw) {
|
|
338
|
+
map.removeInteraction(this.draw);
|
|
339
|
+
this.draw = null;
|
|
340
|
+
}
|
|
341
|
+
this.resumeInteractions?.();
|
|
342
|
+
this.resumeInteractions = null;
|
|
343
|
+
}
|
|
344
|
+
setMapCursor(map, cursor) {
|
|
345
|
+
const el = map.getTargetElement();
|
|
346
|
+
if (!el) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
el.style.cursor = cursor ?? '';
|
|
350
|
+
}
|
|
351
|
+
teardown() {
|
|
352
|
+
const map = this.boundMap ?? this.controller()?.getMap() ?? null;
|
|
353
|
+
if (map) {
|
|
354
|
+
this.removeDraw(map);
|
|
355
|
+
this.setMapCursor(map, null);
|
|
356
|
+
if (this.layer) {
|
|
357
|
+
map.removeLayer(this.layer);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
this.draw = null;
|
|
361
|
+
this.layer = null;
|
|
362
|
+
this.source = null;
|
|
363
|
+
this.boundMap = null;
|
|
364
|
+
}
|
|
365
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapMeasureComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
366
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: GeoMapMeasureComponent, isStandalone: true, selector: "geo-map-measure", inputs: { controller: { classPropertyName: "controller", publicName: "controller", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, showResult: { classPropertyName: "showResult", publicName: "showResult", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { mode: "modeChange", measureChange: "measureChange" }, host: { properties: { "class.geo-map-measure-host--active": "mode() !== \"none\"" }, classAttribute: "geo-map-measure-host" }, ngImport: i0, template: "@if (showResult() && result(); as measured) {\n <div class=\"geo-map-measure__result\" role=\"status\">\n <span class=\"geo-map-measure__result-label\">\n {{ measured.mode === 'distance' ? 'Kho\u1EA3ng c\u00E1ch' : 'Di\u1EC7n t\u00EDch' }}:\n <strong>{{ measured.label }}</strong>\n </span>\n <button\n type=\"button\"\n class=\"geo-map-measure__clear\"\n (click)=\"clear()\"\n >\n X\u00F3a\n </button>\n </div>\n}\n\n@if (mode() !== 'none') {\n <div class=\"geo-map-measure__hint\" role=\"status\">\n {{\n mode() === 'distance'\n ? 'Nh\u1EA5p c\u00E1c \u0111i\u1EC3m \u0111\u1EC3 \u0111o kho\u1EA3ng c\u00E1ch. Nh\u00E1y \u0111\u00FAp \u0111\u1EC3 k\u1EBFt th\u00FAc.'\n : 'Nh\u1EA5p c\u00E1c \u0111i\u1EC3m \u0111\u1EC3 \u0111o di\u1EC7n t\u00EDch. Nh\u00E1y \u0111\u00FAp \u0111\u1EC3 k\u1EBFt th\u00FAc.'\n }}\n <button type=\"button\" class=\"geo-map-measure__clear\" (click)=\"clear()\">\n H\u1EE7y\n </button>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.geo-map-measure-host{display:contents}.geo-map-measure__result,.geo-map-measure__hint{border:1px solid var(--geo-color-border-default);border-radius:var(--geo-radius-lg);background:var(--geo-color-surface-elevated);box-shadow:var(--geo-shadow-sm);display:inline-flex;align-items:center;gap:10px;padding:8px 12px;font-size:var(--geo-font-size-body-small);color:var(--geo-color-neutral-800);pointer-events:auto}.geo-map-measure__result-label strong{color:var(--geo-color-primary-default);font-weight:var(--geo-font-weight-semibold)}.geo-map-measure__clear{border:0;border-radius:var(--geo-radius);background:var(--geo-color-primary-soft);color:var(--geo-color-primary-default);font:inherit;font-size:var(--geo-font-size-caption);font-weight:var(--geo-font-weight-semibold);padding:4px 8px;cursor:pointer}.geo-map-measure__clear:hover{background:var(--geo-color-primary-soft-hover)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
367
|
+
}
|
|
368
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapMeasureComponent, decorators: [{
|
|
369
|
+
type: Component,
|
|
370
|
+
args: [{ selector: 'geo-map-measure', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
371
|
+
class: 'geo-map-measure-host',
|
|
372
|
+
'[class.geo-map-measure-host--active]': 'mode() !== "none"',
|
|
373
|
+
}, template: "@if (showResult() && result(); as measured) {\n <div class=\"geo-map-measure__result\" role=\"status\">\n <span class=\"geo-map-measure__result-label\">\n {{ measured.mode === 'distance' ? 'Kho\u1EA3ng c\u00E1ch' : 'Di\u1EC7n t\u00EDch' }}:\n <strong>{{ measured.label }}</strong>\n </span>\n <button\n type=\"button\"\n class=\"geo-map-measure__clear\"\n (click)=\"clear()\"\n >\n X\u00F3a\n </button>\n </div>\n}\n\n@if (mode() !== 'none') {\n <div class=\"geo-map-measure__hint\" role=\"status\">\n {{\n mode() === 'distance'\n ? 'Nh\u1EA5p c\u00E1c \u0111i\u1EC3m \u0111\u1EC3 \u0111o kho\u1EA3ng c\u00E1ch. Nh\u00E1y \u0111\u00FAp \u0111\u1EC3 k\u1EBFt th\u00FAc.'\n : 'Nh\u1EA5p c\u00E1c \u0111i\u1EC3m \u0111\u1EC3 \u0111o di\u1EC7n t\u00EDch. Nh\u00E1y \u0111\u00FAp \u0111\u1EC3 k\u1EBFt th\u00FAc.'\n }}\n <button type=\"button\" class=\"geo-map-measure__clear\" (click)=\"clear()\">\n H\u1EE7y\n </button>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.geo-map-measure-host{display:contents}.geo-map-measure__result,.geo-map-measure__hint{border:1px solid var(--geo-color-border-default);border-radius:var(--geo-radius-lg);background:var(--geo-color-surface-elevated);box-shadow:var(--geo-shadow-sm);display:inline-flex;align-items:center;gap:10px;padding:8px 12px;font-size:var(--geo-font-size-body-small);color:var(--geo-color-neutral-800);pointer-events:auto}.geo-map-measure__result-label strong{color:var(--geo-color-primary-default);font-weight:var(--geo-font-weight-semibold)}.geo-map-measure__clear{border:0;border-radius:var(--geo-radius);background:var(--geo-color-primary-soft);color:var(--geo-color-primary-default);font:inherit;font-size:var(--geo-font-size-caption);font-weight:var(--geo-font-weight-semibold);padding:4px 8px;cursor:pointer}.geo-map-measure__clear:hover{background:var(--geo-color-primary-soft-hover)}\n"] }]
|
|
374
|
+
}], ctorParameters: () => [] });
|
|
375
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvLW1hcC1tZWFzdXJlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2dlby11aS9zcmMvbGliL2ZpZ21hL2dlby1tYXAvY2hyb21lL2dlby1tYXAtbWVhc3VyZS9nZW8tbWFwLW1lYXN1cmUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZ2VvLXVpL3NyYy9saWIvZmlnbWEvZ2VvLW1hcC9jaHJvbWUvZ2VvLW1hcC1tZWFzdXJlL2dlby1tYXAtbWVhc3VyZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsTUFBTSxFQUNOLE1BQU0sRUFDTixLQUFLLEVBQ0wsS0FBSyxFQUVMLE1BQU0sRUFDTixNQUFNLEVBQ04saUJBQWlCLEdBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sa0JBQWtCLE1BQU0sNEJBQTRCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3JELE9BQU8sSUFBSSxNQUFNLHFCQUFxQixDQUFDO0FBRXZDLE9BQU8sV0FBVyxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQy9DLE9BQU8sWUFBWSxNQUFNLGtCQUFrQixDQUFDO0FBRTVDLE9BQU8sRUFDTCxNQUFNLElBQUksV0FBVyxFQUNyQixJQUFJLEVBQ0osSUFBSSxFQUNKLE1BQU0sRUFDTixLQUFLLEVBQ0wsSUFBSSxHQUNMLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25FLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLHVD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QXNCO2tCQWJsQyxTQUFTOytCQUNFLGlCQUFpQixjQUNmLElBQUksV0FDUCxFQUFFLG1CQUdNLHVCQUF1QixDQUFDLE1BQU0saUJBQ2hDLGlCQUFpQixDQUFDLElBQUksUUFDL0I7d0JBQ0osS0FBSyxFQUFFLHNCQUFzQjt3QkFDN0Isc0NBQXNDLEVBQUUsbUJBQW1CO3FCQUM1RCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIERlc3Ryb3lSZWYsXG4gIGVmZmVjdCxcbiAgaW5qZWN0LFxuICBpbnB1dCxcbiAgbW9kZWwsXG4gIE9uRGVzdHJveSxcbiAgb3V0cHV0LFxuICBzaWduYWwsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB0eXBlIHsgRmVhdHVyZUxpa2UgfSBmcm9tICdvbC9GZWF0dXJlJztcbmltcG9ydCB0eXBlIEdlb21ldHJ5IGZyb20gJ29sL2dlb20vR2VvbWV0cnknO1xuaW1wb3J0IEdlb21ldHJ5Q29sbGVjdGlvbiBmcm9tICdvbC9nZW9tL0dlb21ldHJ5Q29sbGVjdGlvbic7XG5pbXBvcnQgeyBMaW5lU3RyaW5nLCBQb2ludCwgUG9seWdvbiB9IGZyb20gJ29sL2dlb20nO1xuaW1wb3J0IERyYXcgZnJvbSAnb2wvaW50ZXJhY3Rpb24vRHJhdyc7XG5pbXBvcnQgdHlwZSBPbE1hcCBmcm9tICdvbC9NYXAnO1xuaW1wb3J0IFZlY3RvckxheWVyIGZyb20gJ29sL2xheWVyL1ZlY3Rvcic7XG5pbXBvcnQgeyBnZXRBcmVhLCBnZXRMZW5ndGggfSBmcm9tICdvbC9zcGhlcmUnO1xuaW1wb3J0IFZlY3RvclNvdXJjZSBmcm9tICdvbC9zb3VyY2UvVmVjdG9yJztcbmltcG9ydCB0eXBlIHsgU3R5bGVMaWtlIH0gZnJvbSAnb2wvc3R5bGUvU3R5bGUnO1xuaW1wb3J0IHtcbiAgQ2lyY2xlIGFzIENpcmNsZVN0eWxlLFxuICBGaWxsLFxuICBJY29uLFxuICBTdHJva2UsXG4gIFN0eWxlLFxuICBUZXh0LFxufSBmcm9tICdvbC9zdHlsZSc7XG5pbXBvcnQgeyBHRU9fTUFQX01FQVNVUkVfTEFZRVJfSUQgfSBmcm9tICcuLi8uLi9nZW8tbWFwLmNvbnN0YW50cyc7XG5pbXBvcnQgeyBwYXVzZUNvbmZsaWN0aW5nSW50ZXJhY3Rpb25zIH0gZnJvbSAnLi4vLi4vdXRpbHMvZ2VvLW1hcC1pbnRlcmFjdGlvbnMudXRpbCc7XG5pbXBvcnQgeyBHZW9NYXBDb250cm9sbGVyIH0gZnJvbSAnLi4vLi4vZ2VvLW1hcC5jb250cm9sbGVyJztcbmltcG9ydCB0eXBlIHsgR2VvTWFwTWVhc3VyZU1vZGUsIEdlb01hcE1lYXN1cmVSZXN1bHQgfSBmcm9tICcuLi8uLi9nZW8tbWFwLnR5cGVzJztcblxuLyoqXG4gKiBEaXN0YW5jZSAvIGFyZWEgbWVhc3VyZSB0b29scyBvbiB0aGUgbWFwLlxuICpcbiAqIEBzdW1tYXJ5IERpc3RhbmNlIC8gYXJlYSBtZWFzdXJlIHRvb2xzIG9uIHRoZSBtYXAuXG4gKiBAd2hlblRvVXNlIMSQbyBraG/huqNuZyBjw6FjaCAvIGRp4buHbiB0w61jaCAoRS10aWVuLWljaCkuXG4gKiBAZG9Ob3RVc2VXaGVuIFBlcm1hbmVudCB2ZWN0b3IgZWRpdGluZyDigJQgYXBwLW93bmVkIGRyYXcgdG9vbHMuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2dlby1tYXAtbWVhc3VyZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtdLFxuICB0ZW1wbGF0ZVVybDogJy4vZ2VvLW1hcC1tZWFzdXJlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2dlby1tYXAtbWVhc3VyZS5jb21wb25lbnQuc2NzcycsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBob3N0OiB7XG4gICAgY2xhc3M6ICdnZW8tbWFwLW1lYXN1cmUtaG9zdCcsXG4gICAgJ1tjbGFzcy5nZW8tbWFwLW1lYXN1cmUtaG9zdC0tYWN0aXZlXSc6ICdtb2RlKCkgIT09IFwibm9uZVwiJyxcbiAgfSxcbn0pXG5leHBvcnQgY2xhc3MgR2VvTWFwTWVhc3VyZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcblxuICByZWFkb25seSBjb250cm9sbGVyID0gaW5wdXQ8R2VvTWFwQ29udHJvbGxlciB8IG51bGw+KG51bGwpO1xuICByZWFkb25seSBtb2RlID0gbW9kZWw8R2VvTWFwTWVhc3VyZU1vZGU+KCdub25lJyk7XG4gIHJlYWRvbmx5IHNob3dSZXN1bHQgPSBpbnB1dCh0cnVlKTtcblxuICByZWFkb25seSBtZWFzdXJlQ2hhbmdlID0gb3V0cHV0PEdlb01hcE1lYXN1cmVSZXN1bHQgfCBudWxsPigpO1xuXG4gIHJlYWRvbmx5IHJlc3VsdCA9IHNpZ25hbDxHZW9NYXBNZWFzdXJlUmVzdWx0IHwgbnVsbD4obnVsbCk7XG5cbiAgcHJpdmF0ZSBzb3VyY2U6IFZlY3RvclNvdXJjZSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGxheWVyOiBWZWN0b3JMYXllcjxWZWN0b3JTb3VyY2U+IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgZHJhdzogRHJhdyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGJvdW5kTWFwOiBPbE1hcCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHJlc3VtZUludGVyYWN0aW9uczogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgLy8gV3JpdGVzIGByZXN1bHRgIHdoZW4gKHJlKWVudGVyaW5nIGEgbWVhc3VyZSBtb2RlIOKAlCBhbGxvdyBpbnNpZGUgZWZmZWN0LlxuICAgIGVmZmVjdChcbiAgICAgICgpID0+IHtcbiAgICAgICAgY29uc3QgY3RybCA9IHRoaXMuY29udHJvbGxlcigpO1xuICAgICAgICBjb25zdCBtb2RlID0gdGhpcy5tb2RlKCk7XG4gICAgICAgIHRoaXMuc3luY0ludGVyYWN0aW9uKGN0cmwsIG1vZGUpO1xuICAgICAgfSxcbiAgICAgIHsgYWxsb3dTaWduYWxXcml0ZXM6IHRydWUgfSxcbiAgICApO1xuXG4gICAgdGhpcy5kZXN0cm95UmVmLm9uRGVzdHJveSgoKSA9PiB0aGlzLnRlYXJkb3duKCkpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy50ZWFyZG93bigpO1xuICB9XG5cbiAgY2xlYXIoKTogdm9pZCB7XG4gICAgdGhpcy5zb3VyY2U/LmNsZWFyKCk7XG4gICAgdGhpcy5yZXN1bHQuc2V0KG51bGwpO1xuICAgIHRoaXMubWVhc3VyZUNoYW5nZS5lbWl0KG51bGwpO1xuICAgIHRoaXMubW9kZS5zZXQoJ25vbmUnKTtcbiAgfVxuXG4gIHByaXZhdGUgc3luY0ludGVyYWN0aW9uKFxuICAgIGN0cmw6IEdlb01hcENvbnRyb2xsZXIgfCBudWxsLFxuICAgIG1vZGU6IEdlb01hcE1lYXN1cmVNb2RlLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBtYXAgPSBjdHJsPy5nZXRNYXAoKSA/PyBudWxsO1xuICAgIGlmICghbWFwKSB7XG4gICAgICB0aGlzLnRlYXJkb3duKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYm91bmRNYXAgIT09IG1hcCkge1xuICAgICAgdGhpcy50ZWFyZG93bigpO1xuICAgICAgdGhpcy5lbnN1cmVMYXllcihtYXApO1xuICAgICAgdGhpcy5ib3VuZE1hcCA9IG1hcDtcbiAgICB9IGVsc2UgaWYgKCF0aGlzLnNvdXJjZSB8fCAhdGhpcy5sYXllcikge1xuICAgICAgdGhpcy5lbnN1cmVMYXllcihtYXApO1xuICAgIH1cblxuICAgIHRoaXMucmVtb3ZlRHJhdyhtYXApO1xuXG4gICAgaWYgKG1vZGUgPT09ICdub25lJykge1xuICAgICAgLy8gTGVhdmUgY3Vyc29yIHRvIHRoZSBzaGVsbCAvIGhvc3QgKHBhbiBncmFiIGhhbmQsIGV0Yy4pLlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc291cmNlPy5jbGVhcigpO1xuICAgIHRoaXMucmVzdWx0LnNldChudWxsKTtcbiAgICB0aGlzLm1lYXN1cmVDaGFuZ2UuZW1pdChudWxsKTtcblxuICAgIC8vIERvdWJsZS1jbGljayBmaW5pc2hlcyB0aGUgc2tldGNoOyBwYXVzZSBPTCBEb3VibGVDbGlja1pvb20gd2hpbGUgbWVhc3VyaW5nLlxuICAgIHRoaXMucmVzdW1lSW50ZXJhY3Rpb25zID0gcGF1c2VDb25mbGljdGluZ0ludGVyYWN0aW9ucyhtYXAsIHtcbiAgICAgIGRyYWdQYW46IGZhbHNlLFxuICAgICAgZG91YmxlQ2xpY2tab29tOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgY29uc3QgdHlwZSA9IG1vZGUgPT09ICdkaXN0YW5jZScgPyAnTGluZVN0cmluZycgOiAnUG9seWdvbic7XG4gICAgY29uc3Qgc3R5bGUgPSB0aGlzLmNyZWF0ZVN0eWxlKCk7XG4gICAgdGhpcy5kcmF3ID0gbmV3IERyYXcoe1xuICAgICAgc291cmNlOiB0aGlzLnNvdXJjZSEsXG4gICAgICB0eXBlLFxuICAgICAgc3R5bGUsXG4gICAgICBzdG9wQ2xpY2s6IHRydWUsXG4gICAgfSk7XG5cbiAgICBjb25zdCBjYXB0dXJlZE1vZGUgPSBtb2RlO1xuICAgIHRoaXMuZHJhdy5vbignZHJhd2VuZCcsIChldnQpID0+IHtcbiAgICAgIGNvbnN0IGdlb21ldHJ5ID0gZXZ0LmZlYXR1cmUuZ2V0R2VvbWV0cnkoKTtcbiAgICAgIGlmICghZ2VvbWV0cnkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgbWVhc3VyZWQgPSB0aGlzLmZvcm1hdFJlc3VsdChjYXB0dXJlZE1vZGUsIGdlb21ldHJ5KTtcbiAgICAgIHRoaXMucmVzdWx0LnNldChtZWFzdXJlZCk7XG4gICAgICB0aGlzLm1lYXN1cmVDaGFuZ2UuZW1pdChtZWFzdXJlZCk7XG4gICAgICAvLyBFeGl0IGRyYXcgbW9kZSBhZnRlciB0aGUgRHJhdyBpbnRlcmFjdGlvbiBmaW5pc2hlcyByZW1vdmluZyB0aGUgc2tldGNoLlxuICAgICAgcXVldWVNaWNyb3Rhc2soKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5tb2RlKCkgPT09IGNhcHR1cmVkTW9kZSkge1xuICAgICAgICAgIHRoaXMubW9kZS5zZXQoJ25vbmUnKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBtYXAuYWRkSW50ZXJhY3Rpb24odGhpcy5kcmF3KTtcbiAgICB0aGlzLmxheWVyPy5zZXRWaXNpYmxlKHRydWUpO1xuICAgIHRoaXMuc2V0TWFwQ3Vyc29yKG1hcCwgJ2Nyb3NzaGFpcicpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbnN1cmVMYXllcihtYXA6IE9sTWFwKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubGF5ZXIpIHtcbiAgICAgIG1hcC5yZW1vdmVMYXllcih0aGlzLmxheWVyKTtcbiAgICB9XG4gICAgdGhpcy5zb3VyY2UgPSBuZXcgVmVjdG9yU291cmNlKCk7XG4gICAgY29uc3QgbGF5ZXIgPSBuZXcgVmVjdG9yTGF5ZXIoe1xuICAgICAgc291cmNlOiB0aGlzLnNvdXJjZSxcbiAgICAgIHByb3BlcnRpZXM6IHsgZ2VvTGF5ZXJJZDogR0VPX01BUF9NRUFTVVJFX0xBWUVSX0lEIH0sXG4gICAgICBzdHlsZTogdGhpcy5jcmVhdGVTdHlsZSgpLFxuICAgICAgekluZGV4OiA1MDAsXG4gICAgICB1cGRhdGVXaGlsZUFuaW1hdGluZzogdHJ1ZSxcbiAgICAgIHVwZGF0ZVdoaWxlSW50ZXJhY3Rpbmc6IHRydWUsXG4gICAgfSk7XG4gICAgdGhpcy5sYXllciA9IGxheWVyO1xuICAgIG1hcC5hZGRMYXllcihsYXllcik7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVN0eWxlKCk6IFN0eWxlTGlrZSB7XG4gICAgcmV0dXJuIChmZWF0dXJlOiBGZWF0dXJlTGlrZSkgPT4ge1xuICAgICAgY29uc3QgZ2VvbWV0cnkgPSBmZWF0dXJlLmdldEdlb21ldHJ5KCk7XG4gICAgICBpZiAoIWdlb21ldHJ5KSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIC8vIERyYXcgLyBWZWN0b3IgZmVhdHVyZXMgZXhwb3NlIGFuIE9MIEdlb21ldHJ5IChub3QgUmVuZGVyRmVhdHVyZSkuXG4gICAgICByZXR1cm4gdGhpcy5idWlsZE1lYXN1cmVTdHlsZXMoZ2VvbWV0cnkgYXMgR2VvbWV0cnkpO1xuICAgIH07XG4gIH1cblxuICAvKiogRGFzaGVkIHN0cm9rZSwgbnVtYmVyZWQgdmVydGljZXMsIHNlZ21lbnQgbGFiZWxzIChkaXN0YW5jZSArIGFyZWEpLiAqL1xuICBwcml2YXRlIGJ1aWxkTWVhc3VyZVN0eWxlcyhnZW9tZXRyeTogR2VvbWV0cnkgfCBudWxsKTogU3R5bGVbXSB7XG4gICAgaWYgKCFnZW9tZXRyeSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGlmIChnZW9tZXRyeSBpbnN0YW5jZW9mIEdlb21ldHJ5Q29sbGVjdGlvbikge1xuICAgICAgcmV0dXJuIGdlb21ldHJ5XG4gICAgICAgIC5nZXRHZW9tZXRyaWVzKClcbiAgICAgICAgLmZsYXRNYXAoKHBhcnQpID0+IHRoaXMuYnVpbGRNZWFzdXJlU3R5bGVzKHBhcnQpKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2xvciA9IHRoaXMuY3NzQ29sb3IoJy0tZ2VvLWNvbG9yLXByaW1hcnktZGVmYXVsdCcsICcjOWE0ODI4Jyk7XG4gICAgY29uc3QgZmlsbCA9IHRoaXMuY3NzQ29sb3IoJy0tZ2VvLWNvbG9yLXByaW1hcnktZGVmYXVsdCcsICcjOWE0ODI4JywgMC4xMik7XG4gICAgY29uc3QgZm9udEZhbWlseSA9IHRoaXMuY3NzRm9udEZhbWlseSgpO1xuICAgIGNvbnN0IHN0eWxlczogU3R5bGVbXSA9IFtcbiAgICAgIG5ldyBTdHlsZSh7XG4gICAgICAgIGZpbGw6IG5ldyBGaWxsKHsgY29sb3I6IGZpbGwgfSksXG4gICAgICAgIHN0cm9rZTogbmV3IFN0cm9rZSh7XG4gICAgICAgICAgY29sb3IsXG4gICAgICAgICAgd2lkdGg6IDIsXG4gICAgICAgICAgbGluZURhc2g6IFs3LCA3XSxcbiAgICAgICAgfSksXG4gICAgICB9KSxcbiAgICBdO1xuXG4gICAgaWYgKGdlb21ldHJ5IGluc3RhbmNlb2YgUG9pbnQpIHtcbiAgICAgIHN0eWxlcy5wdXNoKC4uLnRoaXMudmVydGV4U3R5bGVzKGdlb21ldHJ5LmdldENvb3JkaW5hdGVzKCksIDEsIGNvbG9yKSk7XG4gICAgICByZXR1cm4gc3R5bGVzO1xuICAgIH1cblxuICAgIGxldCBwb2ludHM6IG51bWJlcltdW10gPSBbXTtcbiAgICBpZiAoZ2VvbWV0cnkgaW5zdGFuY2VvZiBMaW5lU3RyaW5nKSB7XG4gICAgICBwb2ludHMgPSBnZW9tZXRyeS5nZXRDb29yZGluYXRlcygpO1xuICAgIH0gZWxzZSBpZiAoZ2VvbWV0cnkgaW5zdGFuY2VvZiBQb2x5Z29uKSB7XG4gICAgICBjb25zdCByaW5nID0gZ2VvbWV0cnkuZ2V0Q29vcmRpbmF0ZXMoKVswXSA/PyBbXTtcbiAgICAgIHBvaW50cyA9IHRoaXMub3BlblJpbmcocmluZyk7XG4gICAgfVxuXG4gICAgaWYgKCFwb2ludHMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gc3R5bGVzO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzdHlsZXMucHVzaCguLi50aGlzLnZlcnRleFN0eWxlcyhwb2ludHNbaV0sIGkgKyAxLCBjb2xvcikpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsb3NlZCA9IGdlb21ldHJ5IGluc3RhbmNlb2YgUG9seWdvbiAmJiBwb2ludHMubGVuZ3RoID49IDI7XG4gICAgY29uc3Qgc2VnbWVudENvdW50ID0gY2xvc2VkID8gcG9pbnRzLmxlbmd0aCA6IE1hdGgubWF4KDAsIHBvaW50cy5sZW5ndGggLSAxKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlZ21lbnRDb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBhID0gcG9pbnRzW2ldO1xuICAgICAgY29uc3QgYiA9IHBvaW50c1soaSArIDEpICUgcG9pbnRzLmxlbmd0aF07XG4gICAgICBzdHlsZXMucHVzaCh0aGlzLnNlZ21lbnRMYWJlbFN0eWxlKGEsIGIsIGNvbG9yLCBmb250RmFtaWx5KSk7XG4gICAgfVxuXG4gICAgaWYgKGdlb21ldHJ5IGluc3RhbmNlb2YgUG9seWdvbiAmJiBwb2ludHMubGVuZ3RoID49IDMpIHtcbiAgICAgIGNvbnN0IGFyZWFMYWJlbCA9IHRoaXMuYXJlYUNlbnRyb2lkTGFiZWwoZ2VvbWV0cnksIGNvbG9yLCBmb250RmFtaWx5KTtcbiAgICAgIGlmIChhcmVhTGFiZWwpIHtcbiAgICAgICAgc3R5bGVzLnB1c2goYXJlYUxhYmVsKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc3R5bGVzO1xuICB9XG5cbiAgcHJpdmF0ZSBvcGVuUmluZyhyaW5nOiBudW1iZXJbXVtdKTogbnVtYmVyW11bXSB7XG4gICAgaWYgKHJpbmcubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIHJpbmc7XG4gICAgfVxuICAgIGNvbnN0IGZpcnN0ID0gcmluZ1swXTtcbiAgICBjb25zdCBsYXN0ID0gcmluZ1tyaW5nLmxlbmd0aCAtIDFdO1xuICAgIGlmIChmaXJzdFswXSA9PT0gbGFzdFswXSAmJiBmaXJzdFsxXSA9PT0gbGFzdFsxXSkge1xuICAgICAgcmV0dXJuIHJpbmcuc2xpY2UoMCwgLTEpO1xuICAgIH1cbiAgICByZXR1cm4gcmluZztcbiAgfVxuXG4gIHByaXZhdGUgdmVydGV4U3R5bGVzKGNvb3JkOiBudW1iZXJbXSwgaW5kZXg6IG51bWJlciwgY29sb3I6IHN0cmluZyk6IFN0eWxlW10ge1xuICAgIHJldHVybiBbXG4gICAgICBuZXcgU3R5bGUoe1xuICAgICAgICBnZW9tZXRyeTogbmV3IFBvaW50KGNvb3JkKSxcbiAgICAgICAgaW1hZ2U6IG5ldyBDaXJjbGVTdHlsZSh7XG4gICAgICAgICAgcmFkaXVzOiAzLjUsXG4gICAgICAgICAgZmlsbDogbmV3IEZpbGwoeyBjb2xvciB9KSxcbiAgICAgICAgfSksXG4gICAgICB9KSxcbiAgICAgIG5ldyBTdHlsZSh7XG4gICAgICAgIGdlb21ldHJ5OiBuZXcgUG9pbnQoY29vcmQpLFxuICAgICAgICBpbWFnZTogbmV3IEljb24oe1xuICAgICAgICAgIHNyYzogdGhpcy5udW1iZXJCYWRnZURhdGFVcmwoaW5kZXgsIGNvbG9yKSxcbiAgICAgICAgICBhbmNob3I6IFswLjUsIDEuMzVdLFxuICAgICAgICAgIGFuY2hvclhVbml0czogJ2ZyYWN0aW9uJyxcbiAgICAgICAgICBhbmNob3JZVW5pdHM6ICdmcmFjdGlvbicsXG4gICAgICAgICAgc2NhbGU6IDEsXG4gICAgICAgIH0pLFxuICAgICAgfSksXG4gICAgXTtcbiAgfVxuXG4gIHByaXZhdGUgbnVtYmVyQmFkZ2VEYXRhVXJsKGluZGV4OiBudW1iZXIsIGNvbG9yOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHN2ZyA9XG4gICAgICBgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIyMlwiIGhlaWdodD1cIjIyXCIgdmlld0JveD1cIjAgMCAyMiAyMlwiPmAgK1xuICAgICAgYDxjaXJjbGUgY3g9XCIxMVwiIGN5PVwiMTFcIiByPVwiMTBcIiBmaWxsPVwiJHtjb2xvcn1cIi8+YCArXG4gICAgICBgPHRleHQgeD1cIjExXCIgeT1cIjE1XCIgdGV4dC1hbmNob3I9XCJtaWRkbGVcIiBmaWxsPVwiI2ZmZmZmZlwiIGAgK1xuICAgICAgYGZvbnQtc2l6ZT1cIjExXCIgZm9udC13ZWlnaHQ9XCI3MDBcIiBmb250LWZhbWlseT1cInNhbnMtc2VyaWZcIj4ke2luZGV4fTwvdGV4dD5gICtcbiAgICAgIGA8L3N2Zz5gO1xuICAgIHJldHVybiBgZGF0YTppbWFnZS9zdmcreG1sO2NoYXJzZXQ9dXRmLTgsJHtlbmNvZGVVUklDb21wb25lbnQoc3ZnKX1gO1xuICB9XG5cbiAgcHJpdmF0ZSBzZWdtZW50TGFiZWxTdHlsZShcbiAgICBhOiBudW1iZXJbXSxcbiAgICBiOiBudW1iZXJbXSxcbiAgICBjb2xvcjogc3RyaW5nLFxuICAgIGZvbnRGYW1pbHk6IHN0cmluZyxcbiAgKTogU3R5bGUge1xuICAgIGNvbnN0IG1pZDogW251bWJlciwgbnVtYmVyXSA9IFsoYVswXSArIGJbMF0pIC8gMiwgKGFbMV0gKyBiWzFdKSAvIDJdO1xuICAgIGNvbnN0IG1ldGVycyA9IGdldExlbmd0aChuZXcgTGluZVN0cmluZyhbYSwgYl0pKTtcbiAgICBsZXQgcm90YXRpb24gPSAtTWF0aC5hdGFuMihiWzFdIC0gYVsxXSwgYlswXSAtIGFbMF0pO1xuICAgIC8vIEtlZXAgbGFiZWxzIHVwcmlnaHQvcmVhZGFibGUuXG4gICAgaWYgKHJvdGF0aW9uID4gTWF0aC5QSSAvIDIgfHwgcm90YXRpb24gPCAtTWF0aC5QSSAvIDIpIHtcbiAgICAgIHJvdGF0aW9uICs9IE1hdGguUEk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBTdHlsZSh7XG4gICAgICBnZW9tZXRyeTogbmV3IFBvaW50KG1pZCksXG4gICAgICB0ZXh0OiBuZXcgVGV4dCh7XG4gICAgICAgIHRleHQ6IHRoaXMuZm9ybWF0TGVuZ3RoTGFiZWwobWV0ZXJzKSxcbiAgICAgICAgZm9udDogYDUwMCAxMnB4ICR7Zm9udEZhbWlseX1gLFxuICAgICAgICBmaWxsOiBuZXcgRmlsbCh7IGNvbG9yIH0pLFxuICAgICAgICBzdHJva2U6IG5ldyBTdHJva2Uoe1xuICAgICAgICAgIGNvbG9yOiAncmdiYSgyNTUsIDI1NSwgMjU1LCAwLjkpJyxcbiAgICAgICAgICB3aWR0aDogMyxcbiAgICAgICAgfSksXG4gICAgICAgIHJvdGF0aW9uLFxuICAgICAgICByb3RhdGVXaXRoVmlldzogdHJ1ZSxcbiAgICAgICAgdGV4dEFsaWduOiAnY2VudGVyJyxcbiAgICAgICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJyxcbiAgICAgIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhcmVhQ2VudHJvaWRMYWJlbChcbiAgICBnZW9tZXRyeTogUG9seWdvbixcbiAgICBjb2xvcjogc3RyaW5nLFxuICAgIGZvbnRGYW1pbHk6IHN0cmluZyxcbiAgKTogU3R5bGUgfCBudWxsIHtcbiAgICBjb25zdCBpbnRlcmlvciA9IGdlb21ldHJ5LmdldEludGVyaW9yUG9pbnQoKT8uZ2V0Q29vcmRpbmF0ZXMoKTtcbiAgICBpZiAoIWludGVyaW9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3Qgc3FNZXRlcnMgPSBnZXRBcmVhKGdlb21ldHJ5KTtcbiAgICByZXR1cm4gbmV3IFN0eWxlKHtcbiAgICAgIGdlb21ldHJ5OiBuZXcgUG9pbnQoaW50ZXJpb3IpLFxuICAgICAgdGV4dDogbmV3IFRleHQoe1xuICAgICAgICB0ZXh0OiB0aGlzLmZvcm1hdEFyZWFMYWJlbChzcU1ldGVycyksXG4gICAgICAgIGZvbnQ6IGA2MDAgMTJweCAke2ZvbnRGYW1pbHl9YCxcbiAgICAgICAgZmlsbDogbmV3IEZpbGwoeyBjb2xvciB9KSxcbiAgICAgICAgc3Ryb2tlOiBuZXcgU3Ryb2tlKHtcbiAgICAgICAgICBjb2xvcjogJ3JnYmEoMjU1LCAyNTUsIDI1NSwgMC45MiknLFxuICAgICAgICAgIHdpZHRoOiAzLjUsXG4gICAgICAgIH0pLFxuICAgICAgICB0ZXh0QWxpZ246ICdjZW50ZXInLFxuICAgICAgICB0ZXh0QmFzZWxpbmU6ICdtaWRkbGUnLFxuICAgICAgfSksXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGZvcm1hdExlbmd0aExhYmVsKG1ldGVyczogbnVtYmVyKTogc3RyaW5nIHtcbiAgICBpZiAobWV0ZXJzID49IDEwMDApIHtcbiAgICAgIHJldHVybiBgJHsobWV0ZXJzIC8gMTAwMCkudG9GaXhlZCgxKX0ga21gO1xuICAgIH1cbiAgICByZXR1cm4gYCR7bWV0ZXJzLnRvRml4ZWQoMSl9IG1gO1xuICB9XG5cbiAgcHJpdmF0ZSBmb3JtYXRBcmVhTGFiZWwoc3FNZXRlcnM6IG51bWJlcik6IHN0cmluZyB7XG4gICAgaWYgKHNxTWV0ZXJzID49IDEwXzAwMCkge1xuICAgICAgcmV0dXJuIGAkeyhzcU1ldGVycyAvIDEwXzAwMCkudG9GaXhlZCgyKX0gaGFgO1xuICAgIH1cbiAgICByZXR1cm4gYCR7c3FNZXRlcnMudG9GaXhlZCgxKX0gbcKyYDtcbiAgfVxuXG4gIC8qKiBSZXNvbHZlIGEgZGVzaWduIHRva2VuIGZvciBPcGVuTGF5ZXJzIGNhbnZhcyBzdHlsZXMuICovXG4gIHByaXZhdGUgY3NzQ29sb3IoXG4gICAgdG9rZW46IHN0cmluZyxcbiAgICBmYWxsYmFjazogc3RyaW5nLFxuICAgIGFscGhhPzogbnVtYmVyLFxuICApOiBzdHJpbmcge1xuICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gYWxwaGEgIT0gbnVsbCA/IHRoaXMud2l0aEFscGhhKGZhbGxiYWNrLCBhbHBoYSkgOiBmYWxsYmFjaztcbiAgICB9XG4gICAgY29uc3QgcmF3ID0gZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpXG4gICAgICAuZ2V0UHJvcGVydHlWYWx1ZSh0b2tlbilcbiAgICAgIC50cmltKCk7XG4gICAgY29uc3QgY29sb3IgPSByYXcgfHwgZmFsbGJhY2s7XG4gICAgcmV0dXJuIGFscGhhICE9IG51bGwgPyB0aGlzLndpdGhBbHBoYShjb2xvciwgYWxwaGEpIDogY29sb3I7XG4gIH1cblxuICBwcml2YXRlIGNzc0ZvbnRGYW1pbHkoKTogc3RyaW5nIHtcbiAgICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuICdzYW5zLXNlcmlmJztcbiAgICB9XG4gICAgY29uc3QgcmF3ID0gZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpXG4gICAgICAuZ2V0UHJvcGVydHlWYWx1ZSgnLS1nZW8tZm9udC1mYW1pbHknKVxuICAgICAgLnRyaW0oKTtcbiAgICByZXR1cm4gcmF3IHx8ICdzYW5zLXNlcmlmJztcbiAgfVxuXG4gIHByaXZhdGUgd2l0aEFscGhhKGNvbG9yOiBzdHJpbmcsIGFscGhhOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IGhleCA9IGNvbG9yLm1hdGNoKC9eIyhbMC05YS1mXXs2fSkkL2kpO1xuICAgIGlmIChoZXgpIHtcbiAgICAgIGNvbnN0IG4gPSBwYXJzZUludChoZXhbMV0sIDE2KTtcbiAgICAgIGNvbnN0IHIgPSAobiA+PiAxNikgJiAyNTU7XG4gICAgICBjb25zdCBnID0gKG4gPj4gOCkgJiAyNTU7XG4gICAgICBjb25zdCBiID0gbiAmIDI1NTtcbiAgICAgIHJldHVybiBgcmdiYSgke3J9LCAke2d9LCAke2J9LCAke2FscGhhfSlgO1xuICAgIH1cbiAgICByZXR1cm4gY29sb3I7XG4gIH1cblxuICBwcml2YXRlIGZvcm1hdFJlc3VsdChcbiAgICBtb2RlOiBFeGNsdWRlPEdlb01hcE1lYXN1cmVNb2RlLCAnbm9uZSc+LFxuICAgIGdlb21ldHJ5OiBHZW9tZXRyeSxcbiAgKTogR2VvTWFwTWVhc3VyZVJlc3VsdCB7XG4gICAgaWYgKG1vZGUgPT09ICdkaXN0YW5jZScgJiYgZ2VvbWV0cnkgaW5zdGFuY2VvZiBMaW5lU3RyaW5nKSB7XG4gICAgICBjb25zdCBtZXRlcnMgPSBnZXRMZW5ndGgoZ2VvbWV0cnkpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbW9kZSxcbiAgICAgICAgdmFsdWU6IG1ldGVycyxcbiAgICAgICAgbGFiZWw6IHRoaXMuZm9ybWF0TGVuZ3RoTGFiZWwobWV0ZXJzKSxcbiAgICAgICAgZ2VvbWV0cnksXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChtb2RlID09PSAnYXJlYScgJiYgZ2VvbWV0cnkgaW5zdGFuY2VvZiBQb2x5Z29uKSB7XG4gICAgICBjb25zdCBzcU1ldGVycyA9IGdldEFyZWEoZ2VvbWV0cnkpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbW9kZSxcbiAgICAgICAgdmFsdWU6IHNxTWV0ZXJzLFxuICAgICAgICBsYWJlbDogdGhpcy5mb3JtYXRBcmVhTGFiZWwoc3FNZXRlcnMpLFxuICAgICAgICBnZW9tZXRyeSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgbW9kZSwgdmFsdWU6IDAsIGxhYmVsOiAnLScsIGdlb21ldHJ5IH07XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZURyYXcobWFwOiBPbE1hcCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRyYXcpIHtcbiAgICAgIG1hcC5yZW1vdmVJbnRlcmFjdGlvbih0aGlzLmRyYXcpO1xuICAgICAgdGhpcy5kcmF3ID0gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5yZXN1bWVJbnRlcmFjdGlvbnM/LigpO1xuICAgIHRoaXMucmVzdW1lSW50ZXJhY3Rpb25zID0gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgc2V0TWFwQ3Vyc29yKG1hcDogT2xNYXAsIGN1cnNvcjogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIGNvbnN0IGVsID0gbWFwLmdldFRhcmdldEVsZW1lbnQoKTtcbiAgICBpZiAoIWVsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGVsLnN0eWxlLmN1cnNvciA9IGN1cnNvciA/PyAnJztcbiAgfVxuXG4gIHByaXZhdGUgdGVhcmRvd24oKTogdm9pZCB7XG4gICAgY29uc3QgbWFwID0gdGhpcy5ib3VuZE1hcCA/PyB0aGlzLmNvbnRyb2xsZXIoKT8uZ2V0TWFwKCkgPz8gbnVsbDtcbiAgICBpZiAobWFwKSB7XG4gICAgICB0aGlzLnJlbW92ZURyYXcobWFwKTtcbiAgICAgIHRoaXMuc2V0TWFwQ3Vyc29yKG1hcCwgbnVsbCk7XG4gICAgICBpZiAodGhpcy5sYXllcikge1xuICAgICAgICBtYXAucmVtb3ZlTGF5ZXIodGhpcy5sYXllcik7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuZHJhdyA9IG51bGw7XG4gICAgdGhpcy5sYXllciA9IG51bGw7XG4gICAgdGhpcy5zb3VyY2UgPSBudWxsO1xuICAgIHRoaXMuYm91bmRNYXAgPSBudWxsO1xuICB9XG59XG4iLCJAaWYgKHNob3dSZXN1bHQoKSAmJiByZXN1bHQoKTsgYXMgbWVhc3VyZWQpIHtcbiAgPGRpdiBjbGFzcz1cImdlby1tYXAtbWVhc3VyZV9fcmVzdWx0XCIgcm9sZT1cInN0YXR1c1wiPlxuICAgIDxzcGFuIGNsYXNzPVwiZ2VvLW1hcC1tZWFzdXJlX19yZXN1bHQtbGFiZWxcIj5cbiAgICAgIHt7IG1lYXN1cmVkLm1vZGUgPT09ICdkaXN0YW5jZScgPyAnS2hv4bqjbmcgY8OhY2gnIDogJ0Rp4buHbiB0w61jaCcgfX06XG4gICAgICA8c3Ryb25nPnt7IG1lYXN1cmVkLmxhYmVsIH19PC9zdHJvbmc+XG4gICAgPC9zcGFuPlxuICAgIDxidXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgY2xhc3M9XCJnZW8tbWFwLW1lYXN1cmVfX2NsZWFyXCJcbiAgICAgIChjbGljayk9XCJjbGVhcigpXCJcbiAgICA+XG4gICAgICBYw7NhXG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxufVxuXG5AaWYgKG1vZGUoKSAhPT0gJ25vbmUnKSB7XG4gIDxkaXYgY2xhc3M9XCJnZW8tbWFwLW1lYXN1cmVfX2hpbnRcIiByb2xlPVwic3RhdHVzXCI+XG4gICAge3tcbiAgICAgIG1vZGUoKSA9PT0gJ2Rpc3RhbmNlJ1xuICAgICAgICA/ICdOaOG6pXAgY8OhYyDEkWnhu4NtIMSR4buDIMSRbyBraG/huqNuZyBjw6FjaC4gTmjDoXkgxJHDunAgxJHhu4Mga+G6v3QgdGjDumMuJ1xuICAgICAgICA6ICdOaOG6pXAgY8OhYyDEkWnhu4NtIMSR4buDIMSRbyBkaeG7h24gdMOtY2guIE5ow6F5IMSRw7pwIMSR4buDIGvhur90IHRow7pjLidcbiAgICB9fVxuICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiZ2VvLW1hcC1tZWFzdXJlX19jbGVhclwiIChjbGljayk9XCJjbGVhcigpXCI+XG4gICAgICBI4buneVxuICAgIDwvYnV0dG9uPlxuICA8L2Rpdj5cbn1cbiJdfQ==
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, computed, effect, input, model, signal, ViewEncapsulation, } from '@angular/core';
|
|
2
|
+
import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
|
|
3
|
+
import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
|
|
4
|
+
import { GeoIconComponent } from '../../../geo-icon/geo-icon.component';
|
|
5
|
+
import { GeoSliderComponent } from '../../../geo-slider/geo-slider.component';
|
|
6
|
+
import { GEO_MAP_BASEMAP_LAYER_ID } from '../../geo-map.constants';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
import * as i1 from "ng-zorro-antd/dropdown";
|
|
9
|
+
import * as i2 from "ng-zorro-antd/tooltip";
|
|
10
|
+
/**
|
|
11
|
+
* Pick a layer and adjust opacity 0–100%.
|
|
12
|
+
*
|
|
13
|
+
* @summary Layer opacity slider for map chrome.
|
|
14
|
+
* @whenToUse Điều chỉnh độ trong suốt khi so sánh lớp.
|
|
15
|
+
* @doNotUseWhen Generic sliders outside map — use geo-slider.
|
|
16
|
+
*/
|
|
17
|
+
export class GeoMapOpacityComponent {
|
|
18
|
+
controller = input(null);
|
|
19
|
+
title = input('Độ trong suốt');
|
|
20
|
+
layerId = model(null);
|
|
21
|
+
/** Opacity percent 0–100. */
|
|
22
|
+
opacity = model(100);
|
|
23
|
+
variant = input('panel');
|
|
24
|
+
/** When compact and no layerId, apply to first non-basemap overlay. */
|
|
25
|
+
applyToFirstLayer = input(true);
|
|
26
|
+
open = signal(false);
|
|
27
|
+
layerOptions = computed(() => {
|
|
28
|
+
const ctrl = this.controller();
|
|
29
|
+
if (!ctrl) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
return ctrl
|
|
33
|
+
.getLayers()
|
|
34
|
+
.filter((item) => item.id !== GEO_MAP_BASEMAP_LAYER_ID)
|
|
35
|
+
.map((item) => ({
|
|
36
|
+
id: item.id,
|
|
37
|
+
title: item.config.title || item.id,
|
|
38
|
+
}));
|
|
39
|
+
});
|
|
40
|
+
constructor() {
|
|
41
|
+
effect(() => {
|
|
42
|
+
const ctrl = this.controller();
|
|
43
|
+
const id = this.resolveTargetId();
|
|
44
|
+
if (!ctrl || !id) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const managed = ctrl.getLayers().find((item) => item.id === id);
|
|
48
|
+
if (!managed) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const pct = Math.round((managed.config.opacity ?? 1) * 100);
|
|
52
|
+
if (pct !== this.opacity()) {
|
|
53
|
+
this.opacity.set(pct);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
effect(() => {
|
|
57
|
+
const ctrl = this.controller();
|
|
58
|
+
const id = this.resolveTargetId();
|
|
59
|
+
const pct = this.opacity();
|
|
60
|
+
if (!ctrl || !id) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
ctrl.setLayerOpacity(id, Math.min(1, Math.max(0, pct / 100)));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
onVisible(visible) {
|
|
67
|
+
this.open.set(visible);
|
|
68
|
+
}
|
|
69
|
+
selectLayer(id) {
|
|
70
|
+
this.layerId.set(id);
|
|
71
|
+
}
|
|
72
|
+
resolveTargetId() {
|
|
73
|
+
const explicit = this.layerId();
|
|
74
|
+
if (explicit) {
|
|
75
|
+
return explicit;
|
|
76
|
+
}
|
|
77
|
+
if (!this.applyToFirstLayer()) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
return this.layerOptions()[0]?.id ?? null;
|
|
81
|
+
}
|
|
82
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapOpacityComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
83
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: GeoMapOpacityComponent, isStandalone: true, selector: "geo-map-opacity", inputs: { controller: { classPropertyName: "controller", publicName: "controller", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, layerId: { classPropertyName: "layerId", publicName: "layerId", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, applyToFirstLayer: { classPropertyName: "applyToFirstLayer", publicName: "applyToFirstLayer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { layerId: "layerIdChange", opacity: "opacityChange" }, host: { classAttribute: "geo-map-opacity-host" }, ngImport: i0, template: "@if (variant() === 'compact') {\n <button\n type=\"button\"\n class=\"geo-map-opacity__trigger\"\n nz-dropdown\n nzTrigger=\"click\"\n nzPlacement=\"bottomLeft\"\n nzOverlayClassName=\"geo-map-opacity-overlay\"\n [nzDropdownMenu]=\"menu\"\n [nzVisible]=\"open()\"\n (nzVisibleChange)=\"onVisible($event)\"\n [nz-tooltip]=\"title()\"\n nzTooltipPlacement=\"left\"\n [attr.aria-label]=\"title()\"\n [disabled]=\"!controller()\"\n >\n <geo-icon type=\"bg-colors\" size=\"md\" />\n </button>\n\n <nz-dropdown-menu #menu=\"nzDropdownMenu\">\n <div class=\"geo-map-opacity__panel geo-map-opacity__panel--popup\">\n <div class=\"geo-map-opacity__title\">{{ title() }}</div>\n @if (layerOptions().length > 1) {\n <ul class=\"geo-map-opacity__layers\">\n @for (layer of layerOptions(); track layer.id) {\n <li>\n <button\n type=\"button\"\n class=\"geo-map-opacity__layer\"\n [class.geo-map-opacity__layer--active]=\"\n layer.id === (layerId() || layerOptions()[0].id)\n \"\n (click)=\"selectLayer(layer.id)\"\n >\n {{ layer.title }}\n </button>\n </li>\n }\n </ul>\n } @else if (layerOptions().length === 1) {\n <div class=\"geo-map-opacity__layer-name\">\n {{ layerOptions()[0].title }}\n </div>\n } @else {\n <div class=\"geo-map-opacity__empty\">Ch\u01B0a c\u00F3 l\u1EDBp \u0111\u1EC3 ch\u1EC9nh.</div>\n }\n\n <div class=\"geo-map-opacity__slider\">\n <geo-slider [(value)]=\"opacity\" [min]=\"0\" [max]=\"100\" [step]=\"1\" />\n <span class=\"geo-map-opacity__value\">{{ opacity() }}%</span>\n </div>\n </div>\n </nz-dropdown-menu>\n} @else {\n <div class=\"geo-map-opacity__panel\">\n <div class=\"geo-map-opacity__title\">{{ title() }}</div>\n @if (layerOptions().length > 1) {\n <ul class=\"geo-map-opacity__layers\">\n @for (layer of layerOptions(); track layer.id) {\n <li>\n <button\n type=\"button\"\n class=\"geo-map-opacity__layer\"\n [class.geo-map-opacity__layer--active]=\"\n layer.id === (layerId() || layerOptions()[0].id)\n \"\n (click)=\"selectLayer(layer.id)\"\n >\n {{ layer.title }}\n </button>\n </li>\n }\n </ul>\n } @else if (layerOptions().length === 1) {\n <div class=\"geo-map-opacity__layer-name\">{{ layerOptions()[0].title }}</div>\n } @else {\n <div class=\"geo-map-opacity__empty\">Ch\u01B0a c\u00F3 l\u1EDBp \u0111\u1EC3 ch\u1EC9nh.</div>\n }\n\n <div class=\"geo-map-opacity__slider\">\n <geo-slider [(value)]=\"opacity\" [min]=\"0\" [max]=\"100\" [step]=\"1\" />\n <span class=\"geo-map-opacity__value\">{{ opacity() }}%</span>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.geo-map-opacity-host{display:block}.geo-map-opacity__trigger{border:1px solid var(--geo-color-border-default);border-radius:var(--geo-radius-lg);background:var(--geo-color-surface-elevated);box-shadow:var(--geo-shadow-sm);display:inline-flex;align-items:center;justify-content:center;gap:6px;min-width:40px;min-height:40px;border:0;border-radius:var(--geo-radius);background:transparent;color:var(--geo-color-neutral-700);font:inherit;font-size:var(--geo-font-size-body-small);font-weight:var(--geo-font-weight-medium);line-height:1;cursor:pointer;transition:background-color .15s ease,color .15s ease,transform .1s ease;width:48px;min-height:48px;padding:0}.geo-map-opacity__trigger:hover:not(:disabled){background:var(--geo-color-primary-soft-hover);color:var(--geo-color-primary-default)}.geo-map-opacity__trigger:active:not(:disabled){transform:scale(.98)}.geo-map-opacity__trigger:disabled{opacity:.45;cursor:not-allowed}.geo-map-opacity__trigger--active,.geo-map-opacity__trigger--checked{background:var(--geo-color-primary-soft-active);color:var(--geo-color-primary-default)}.geo-map-opacity__trigger--icon-only{width:40px;padding:0}.geo-map-opacity-overlay .ant-dropdown-menu{padding:0;border:0;background:transparent;box-shadow:none}.geo-map-opacity__panel{border:1px solid var(--geo-color-border-default);border-radius:var(--geo-radius-lg);background:var(--geo-color-surface-elevated);box-shadow:var(--geo-shadow-sm);min-width:220px;padding:10px 12px}.geo-map-opacity__panel--popup{box-shadow:var(--geo-shadow-md)}.geo-map-opacity__title{margin-bottom:8px;font-size:var(--geo-font-size-body-small);font-weight:var(--geo-font-weight-semibold);color:var(--geo-color-neutral-900)}.geo-map-opacity__layers{display:flex;flex-direction:column;gap:4px;margin:0 0 10px;padding:0;list-style:none}.geo-map-opacity__layer{width:100%;padding:6px 8px;border:0;border-radius:var(--geo-radius);background:transparent;color:var(--geo-color-neutral-800);font:inherit;font-size:var(--geo-font-size-body-small);text-align:left;cursor:pointer}.geo-map-opacity__layer:hover{background:var(--geo-color-primary-soft-hover);color:var(--geo-color-primary-default)}.geo-map-opacity__layer--active{background:var(--geo-color-primary-soft-active);color:var(--geo-color-primary-default);font-weight:var(--geo-font-weight-semibold)}.geo-map-opacity__layer-name,.geo-map-opacity__empty{margin-bottom:8px;font-size:var(--geo-font-size-caption);color:var(--geo-color-neutral-600)}.geo-map-opacity__slider{display:flex;align-items:center;gap:10px}.geo-map-opacity__slider geo-slider{flex:1;min-width:0}.geo-map-opacity__value{flex-shrink:0;min-width:40px;font-size:var(--geo-font-size-caption);font-weight:var(--geo-font-weight-semibold);color:var(--geo-color-neutral-700);text-align:right}\n"], dependencies: [{ kind: "ngmodule", type: NzDropDownModule }, { kind: "directive", type: i1.NzDropDownDirective, selector: "[nz-dropdown]", inputs: ["nzDropdownMenu", "nzTrigger", "nzMatchWidthElement", "nzBackdrop", "nzClickHide", "nzDisabled", "nzVisible", "nzOverlayClassName", "nzOverlayStyle", "nzPlacement"], outputs: ["nzVisibleChange"], exportAs: ["nzDropdown"] }, { kind: "component", type: i1.NzDropdownMenuComponent, selector: "nz-dropdown-menu", exportAs: ["nzDropdownMenu"] }, { kind: "ngmodule", type: NzToolTipModule }, { kind: "directive", type: i2.NzTooltipDirective, selector: "[nz-tooltip]", inputs: ["nzTooltipTitle", "nzTooltipTitleContext", "nz-tooltip", "nzTooltipTrigger", "nzTooltipPlacement", "nzTooltipOrigin", "nzTooltipVisible", "nzTooltipMouseEnterDelay", "nzTooltipMouseLeaveDelay", "nzTooltipOverlayClassName", "nzTooltipOverlayStyle", "nzTooltipArrowPointAtCenter", "cdkConnectedOverlayPush", "nzTooltipColor"], outputs: ["nzTooltipVisibleChange"], exportAs: ["nzTooltip"] }, { kind: "component", type: GeoIconComponent, selector: "geo-icon", inputs: ["type", "theme", "spin", "size", "color"] }, { kind: "component", type: GeoSliderComponent, selector: "geo-slider", inputs: ["value", "min", "max", "step", "disabled", "tipFormatter"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
84
|
+
}
|
|
85
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapOpacityComponent, decorators: [{
|
|
86
|
+
type: Component,
|
|
87
|
+
args: [{ selector: 'geo-map-opacity', standalone: true, imports: [
|
|
88
|
+
NzDropDownModule,
|
|
89
|
+
NzToolTipModule,
|
|
90
|
+
GeoIconComponent,
|
|
91
|
+
GeoSliderComponent,
|
|
92
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'geo-map-opacity-host' }, template: "@if (variant() === 'compact') {\n <button\n type=\"button\"\n class=\"geo-map-opacity__trigger\"\n nz-dropdown\n nzTrigger=\"click\"\n nzPlacement=\"bottomLeft\"\n nzOverlayClassName=\"geo-map-opacity-overlay\"\n [nzDropdownMenu]=\"menu\"\n [nzVisible]=\"open()\"\n (nzVisibleChange)=\"onVisible($event)\"\n [nz-tooltip]=\"title()\"\n nzTooltipPlacement=\"left\"\n [attr.aria-label]=\"title()\"\n [disabled]=\"!controller()\"\n >\n <geo-icon type=\"bg-colors\" size=\"md\" />\n </button>\n\n <nz-dropdown-menu #menu=\"nzDropdownMenu\">\n <div class=\"geo-map-opacity__panel geo-map-opacity__panel--popup\">\n <div class=\"geo-map-opacity__title\">{{ title() }}</div>\n @if (layerOptions().length > 1) {\n <ul class=\"geo-map-opacity__layers\">\n @for (layer of layerOptions(); track layer.id) {\n <li>\n <button\n type=\"button\"\n class=\"geo-map-opacity__layer\"\n [class.geo-map-opacity__layer--active]=\"\n layer.id === (layerId() || layerOptions()[0].id)\n \"\n (click)=\"selectLayer(layer.id)\"\n >\n {{ layer.title }}\n </button>\n </li>\n }\n </ul>\n } @else if (layerOptions().length === 1) {\n <div class=\"geo-map-opacity__layer-name\">\n {{ layerOptions()[0].title }}\n </div>\n } @else {\n <div class=\"geo-map-opacity__empty\">Ch\u01B0a c\u00F3 l\u1EDBp \u0111\u1EC3 ch\u1EC9nh.</div>\n }\n\n <div class=\"geo-map-opacity__slider\">\n <geo-slider [(value)]=\"opacity\" [min]=\"0\" [max]=\"100\" [step]=\"1\" />\n <span class=\"geo-map-opacity__value\">{{ opacity() }}%</span>\n </div>\n </div>\n </nz-dropdown-menu>\n} @else {\n <div class=\"geo-map-opacity__panel\">\n <div class=\"geo-map-opacity__title\">{{ title() }}</div>\n @if (layerOptions().length > 1) {\n <ul class=\"geo-map-opacity__layers\">\n @for (layer of layerOptions(); track layer.id) {\n <li>\n <button\n type=\"button\"\n class=\"geo-map-opacity__layer\"\n [class.geo-map-opacity__layer--active]=\"\n layer.id === (layerId() || layerOptions()[0].id)\n \"\n (click)=\"selectLayer(layer.id)\"\n >\n {{ layer.title }}\n </button>\n </li>\n }\n </ul>\n } @else if (layerOptions().length === 1) {\n <div class=\"geo-map-opacity__layer-name\">{{ layerOptions()[0].title }}</div>\n } @else {\n <div class=\"geo-map-opacity__empty\">Ch\u01B0a c\u00F3 l\u1EDBp \u0111\u1EC3 ch\u1EC9nh.</div>\n }\n\n <div class=\"geo-map-opacity__slider\">\n <geo-slider [(value)]=\"opacity\" [min]=\"0\" [max]=\"100\" [step]=\"1\" />\n <span class=\"geo-map-opacity__value\">{{ opacity() }}%</span>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.geo-map-opacity-host{display:block}.geo-map-opacity__trigger{border:1px solid var(--geo-color-border-default);border-radius:var(--geo-radius-lg);background:var(--geo-color-surface-elevated);box-shadow:var(--geo-shadow-sm);display:inline-flex;align-items:center;justify-content:center;gap:6px;min-width:40px;min-height:40px;border:0;border-radius:var(--geo-radius);background:transparent;color:var(--geo-color-neutral-700);font:inherit;font-size:var(--geo-font-size-body-small);font-weight:var(--geo-font-weight-medium);line-height:1;cursor:pointer;transition:background-color .15s ease,color .15s ease,transform .1s ease;width:48px;min-height:48px;padding:0}.geo-map-opacity__trigger:hover:not(:disabled){background:var(--geo-color-primary-soft-hover);color:var(--geo-color-primary-default)}.geo-map-opacity__trigger:active:not(:disabled){transform:scale(.98)}.geo-map-opacity__trigger:disabled{opacity:.45;cursor:not-allowed}.geo-map-opacity__trigger--active,.geo-map-opacity__trigger--checked{background:var(--geo-color-primary-soft-active);color:var(--geo-color-primary-default)}.geo-map-opacity__trigger--icon-only{width:40px;padding:0}.geo-map-opacity-overlay .ant-dropdown-menu{padding:0;border:0;background:transparent;box-shadow:none}.geo-map-opacity__panel{border:1px solid var(--geo-color-border-default);border-radius:var(--geo-radius-lg);background:var(--geo-color-surface-elevated);box-shadow:var(--geo-shadow-sm);min-width:220px;padding:10px 12px}.geo-map-opacity__panel--popup{box-shadow:var(--geo-shadow-md)}.geo-map-opacity__title{margin-bottom:8px;font-size:var(--geo-font-size-body-small);font-weight:var(--geo-font-weight-semibold);color:var(--geo-color-neutral-900)}.geo-map-opacity__layers{display:flex;flex-direction:column;gap:4px;margin:0 0 10px;padding:0;list-style:none}.geo-map-opacity__layer{width:100%;padding:6px 8px;border:0;border-radius:var(--geo-radius);background:transparent;color:var(--geo-color-neutral-800);font:inherit;font-size:var(--geo-font-size-body-small);text-align:left;cursor:pointer}.geo-map-opacity__layer:hover{background:var(--geo-color-primary-soft-hover);color:var(--geo-color-primary-default)}.geo-map-opacity__layer--active{background:var(--geo-color-primary-soft-active);color:var(--geo-color-primary-default);font-weight:var(--geo-font-weight-semibold)}.geo-map-opacity__layer-name,.geo-map-opacity__empty{margin-bottom:8px;font-size:var(--geo-font-size-caption);color:var(--geo-color-neutral-600)}.geo-map-opacity__slider{display:flex;align-items:center;gap:10px}.geo-map-opacity__slider geo-slider{flex:1;min-width:0}.geo-map-opacity__value{flex-shrink:0;min-width:40px;font-size:var(--geo-font-size-caption);font-weight:var(--geo-font-weight-semibold);color:var(--geo-color-neutral-700);text-align:right}\n"] }]
|
|
93
|
+
}], ctorParameters: () => [] });
|
|
94
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvLW1hcC1vcGFjaXR5LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2dlby11aS9zcmMvbGliL2ZpZ21hL2dlby1tYXAvY2hyb21lL2dlby1tYXAtb3BhY2l0eS9nZW8tbWFwLW9wYWNpdHkuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZ2VvLXVpL3NyYy9saWIvZmlnbWEvZ2VvLW1hcC9jaHJvbWUvZ2VvLW1hcC1vcGFjaXR5L2dlby1tYXAtb3BhY2l0eS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxRQUFRLEVBQ1IsTUFBTSxFQUNOLEtBQUssRUFDTCxLQUFLLEVBQ0wsTUFBTSxFQUNOLGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMxRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDeEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDOUUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0seUJBQXlCLENBQUM7Ozs7QUFHbkU7Ozs7OztHQU1HO0FBZ0JILE1BQU0sT0FBTyxzQkFBc0I7SUFDeEIsVUFBVSxHQUFHLEtBQUssQ0FBMEIsSUFBSSxDQUFDLENBQUM7SUFDbEQsS0FBSyxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUMvQixPQUFPLEdBQUcsS0FBSyxDQUFnQixJQUFJLENBQUMsQ0FBQztJQUM5Qyw2QkFBNkI7SUFDcEIsT0FBTyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNy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TyxRQUFRLENBQUM7UUFDbEIsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxDQUFDO1lBQzlCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsSUFBSSxJQUFJLENBQUM7SUFDNUMsQ0FBQzt3R0F2RVUsc0JBQXNCOzRGQUF0QixzQkFBc0IsKzlCQ3ZDbkMsazlGQXFGQSw2eEZEekRJLGdCQUFnQiwwY0FDaEIsZUFBZSx5ZkFDZixnQkFBZ0IseUdBQ2hCLGtCQUFrQjs7NEZBUVQsc0JBQXNCO2tCQWZsQyxTQUFTOytCQUNFLGlCQUFpQixjQUNmLElBQUksV0FDUDt3QkFDUCxnQkFBZ0I7d0JBQ2hCLGVBQWU7d0JBQ2YsZ0JBQWdCO3dCQUNoQixrQkFBa0I7cUJBQ25CLG1CQUdnQix1QkFBdUIsQ0FBQyxNQUFNLGlCQUNoQyxpQkFBaUIsQ0FBQyxJQUFJLFFBQy9CLEVBQUUsS0FBSyxFQUFFLHNCQUFzQixFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgY29tcHV0ZWQsXG4gIGVmZmVjdCxcbiAgaW5wdXQsXG4gIG1vZGVsLFxuICBzaWduYWwsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE56RHJvcERvd25Nb2R1bGUgfSBmcm9tICduZy16b3Jyby1hbnRkL2Ryb3Bkb3duJztcbmltcG9ydCB7IE56VG9vbFRpcE1vZHVsZSB9IGZyb20gJ25nLXpvcnJvLWFudGQvdG9vbHRpcCc7XG5pbXBvcnQgeyBHZW9JY29uQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vLi4vZ2VvLWljb24vZ2VvLWljb24uY29tcG9uZW50JztcbmltcG9ydCB7IEdlb1NsaWRlckNvbXBvbmVudCB9IGZyb20gJy4uLy4uLy4uL2dlby1zbGlkZXIvZ2VvLXNsaWRlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgR0VPX01BUF9CQVNFTUFQX0xBWUVSX0lEIH0gZnJvbSAnLi4vLi4vZ2VvLW1hcC5jb25zdGFudHMnO1xuaW1wb3J0IHsgR2VvTWFwQ29udHJvbGxlciB9IGZyb20gJy4uLy4uL2dlby1tYXAuY29udHJvbGxlcic7XG5cbi8qKlxuICogUGljayBhIGxheWVyIGFuZCBhZGp1c3Qgb3BhY2l0eSAw4oCTMTAwJS5cbiAqXG4gKiBAc3VtbWFyeSBMYXllciBvcGFjaXR5IHNsaWRlciBmb3IgbWFwIGNocm9tZS5cbiAqIEB3aGVuVG9Vc2UgxJBp4buBdSBjaOG7iW5oIMSR4buZIHRyb25nIHN14buRdCBraGkgc28gc8OhbmggbOG7m3AuXG4gKiBAZG9Ob3RVc2VXaGVuIEdlbmVyaWMgc2xpZGVycyBvdXRzaWRlIG1hcCDigJQgdXNlIGdlby1zbGlkZXIuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2dlby1tYXAtb3BhY2l0eScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBOekRyb3BEb3duTW9kdWxlLFxuICAgIE56VG9vbFRpcE1vZHVsZSxcbiAgICBHZW9JY29uQ29tcG9uZW50LFxuICAgIEdlb1NsaWRlckNvbXBvbmVudCxcbiAgXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2dlby1tYXAtb3BhY2l0eS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9nZW8tbWFwLW9wYWNpdHkuY29tcG9uZW50LnNjc3MnLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgaG9zdDogeyBjbGFzczogJ2dlby1tYXAtb3BhY2l0eS1ob3N0JyB9LFxufSlcbmV4cG9ydCBjbGFzcyBHZW9NYXBPcGFjaXR5Q29tcG9uZW50IHtcbiAgcmVhZG9ubHkgY29udHJvbGxlciA9IGlucHV0PEdlb01hcENvbnRyb2xsZXIgfCBudWxsPihudWxsKTtcbiAgcmVhZG9ubHkgdGl0bGUgPSBpbnB1dCgnxJDhu5kgdHJvbmcgc3Xhu5F0Jyk7XG4gIHJlYWRvbmx5IGxheWVySWQgPSBtb2RlbDxzdHJpbmcgfCBudWxsPihudWxsKTtcbiAgLyoqIE9wYWNpdHkgcGVyY2VudCAw4oCTMTAwLiAqL1xuICByZWFkb25seSBvcGFjaXR5ID0gbW9kZWwoMTAwKTtcbiAgcmVhZG9ubHkgdmFyaWFudCA9IGlucHV0PCdwYW5lbCcgfCAnY29tcGFjdCc+KCdwYW5lbCcpO1xuICAvKiogV2hlbiBjb21wYWN0IGFuZCBubyBsYXllcklkLCBhcHBseSB0byBmaXJzdCBub24tYmFzZW1hcCBvdmVybGF5LiAqL1xuICByZWFkb25seSBhcHBseVRvRmlyc3RMYXllciA9IGlucHV0KHRydWUpO1xuXG4gIHJlYWRvbmx5IG9wZW4gPSBzaWduYWwoZmFsc2UpO1xuXG4gIHJlYWRvbmx5IGxheWVyT3B0aW9ucyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBjdHJsID0gdGhpcy5jb250cm9sbGVyKCk7XG4gICAgaWYgKCFjdHJsKSB7XG4gICAgICByZXR1cm4gW10gYXMgQXJyYXk8eyBpZDogc3RyaW5nOyB0aXRsZTogc3RyaW5nIH0+O1xuICAgIH1cbiAgICByZXR1cm4gY3RybFxuICAgICAgLmdldExheWVycygpXG4gICAgICAuZmlsdGVyKChpdGVtKSA9PiBpdGVtLmlkICE9PSBHRU9fTUFQX0JBU0VNQVBfTEFZRVJfSUQpXG4gICAgICAubWFwKChpdGVtKSA9PiAoe1xuICAgICAgICBpZDogaXRlbS5pZCxcbiAgICAgICAgdGl0bGU6IGl0ZW0uY29uZmlnLnRpdGxlIHx8IGl0ZW0uaWQsXG4gICAgICB9KSk7XG4gIH0pO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICBjb25zdCBjdHJsID0gdGhpcy5jb250cm9sbGVyKCk7XG4gICAgICBjb25zdCBpZCA9IHRoaXMucmVzb2x2ZVRhcmdldElkKCk7XG4gICAgICBpZiAoIWN0cmwgfHwgIWlkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG1hbmFnZWQgPSBjdHJsLmdldExheWVycygpLmZpbmQoKGl0ZW0pID0+IGl0ZW0uaWQgPT09IGlkKTtcbiAgICAgIGlmICghbWFuYWdlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBwY3QgPSBNYXRoLnJvdW5kKChtYW5hZ2VkLmNvbmZpZy5vcGFjaXR5ID8/IDEpICogMTAwKTtcbiAgICAgIGlmIChwY3QgIT09IHRoaXMub3BhY2l0eSgpKSB7XG4gICAgICAgIHRoaXMub3BhY2l0eS5zZXQocGN0KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICBjb25zdCBjdHJsID0gdGhpcy5jb250cm9sbGVyKCk7XG4gICAgICBjb25zdCBpZCA9IHRoaXMucmVzb2x2ZVRhcmdldElkKCk7XG4gICAgICBjb25zdCBwY3QgPSB0aGlzLm9wYWNpdHkoKTtcbiAgICAgIGlmICghY3RybCB8fCAhaWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY3RybC5zZXRMYXllck9wYWNpdHkoaWQsIE1hdGgubWluKDEsIE1hdGgubWF4KDAsIHBjdCAvIDEwMCkpKTtcbiAgICB9KTtcbiAgfVxuXG4gIG9uVmlzaWJsZSh2aXNpYmxlOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5vcGVuLnNldCh2aXNpYmxlKTtcbiAgfVxuXG4gIHNlbGVjdExheWVyKGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmxheWVySWQuc2V0KGlkKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzb2x2ZVRhcmdldElkKCk6IHN0cmluZyB8IG51bGwge1xuICAgIGNvbnN0IGV4cGxpY2l0ID0gdGhpcy5sYXllcklkKCk7XG4gICAgaWYgKGV4cGxpY2l0KSB7XG4gICAgICByZXR1cm4gZXhwbGljaXQ7XG4gICAgfVxuICAgIGlmICghdGhpcy5hcHBseVRvRmlyc3RMYXllcigpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubGF5ZXJPcHRpb25zKClbMF0/LmlkID8/IG51bGw7XG4gIH1cbn1cbiIsIkBpZiAodmFyaWFudCgpID09PSAnY29tcGFjdCcpIHtcbiAgPGJ1dHRvblxuICAgIHR5cGU9XCJidXR0b25cIlxuICAgIGNsYXNzPVwiZ2VvLW1hcC1vcGFjaXR5X190cmlnZ2VyXCJcbiAgICBuei1kcm9wZG93blxuICAgIG56VHJpZ2dlcj1cImNsaWNrXCJcbiAgICBuelBsYWNlbWVudD1cImJvdHRvbUxlZnRcIlxuICAgIG56T3ZlcmxheUNsYXNzTmFtZT1cImdlby1tYXAtb3BhY2l0eS1vdmVybGF5XCJcbiAgICBbbnpEcm9wZG93bk1lbnVdPVwibWVudVwiXG4gICAgW256VmlzaWJsZV09XCJvcGVuKClcIlxuICAgIChuelZpc2libGVDaGFuZ2UpPVwib25WaXNpYmxlKCRldmVudClcIlxuICAgIFtuei10b29sdGlwXT1cInRpdGxlKClcIlxuICAgIG56VG9vbHRpcFBsYWNlbWVudD1cImxlZnRcIlxuICAgIFthdHRyLmFyaWEtbGFiZWxdPVwidGl0bGUoKVwiXG4gICAgW2Rpc2FibGVkXT1cIiFjb250cm9sbGVyKClcIlxuICA+XG4gICAgPGdlby1pY29uIHR5cGU9XCJiZy1jb2xvcnNcIiBzaXplPVwibWRcIiAvPlxuICA8L2J1dHRvbj5cblxuICA8bnotZHJvcGRvd24tbWVudSAjbWVudT1cIm56RHJvcGRvd25NZW51XCI+XG4gICAgPGRpdiBjbGFzcz1cImdlby1tYXAtb3BhY2l0eV9fcGFuZWwgZ2VvLW1hcC1vcGFjaXR5X19wYW5lbC0tcG9wdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJnZW8tbWFwLW9wYWNpdHlfX3RpdGxlXCI+e3sgdGl0bGUoKSB9fTwvZGl2PlxuICAgICAgQGlmIChsYXllck9wdGlvbnMoKS5sZW5ndGggPiAxKSB7XG4gICAgICAgIDx1bCBjbGFzcz1cImdlby1tYXAtb3BhY2l0eV9fbGF5ZXJzXCI+XG4gICAgICAgICAgQGZvciAobGF5ZXIgb2YgbGF5ZXJPcHRpb25zKCk7IHRyYWNrIGxheWVyLmlkKSB7XG4gICAgICAgICAgICA8bGk+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImdlby1tYXAtb3BhY2l0eV9fbGF5ZXJcIlxuICAgICAgICAgICAgICAgIFtjbGFzcy5nZW8tbWFwLW9wYWNpdHlfX2xheWVyLS1hY3RpdmVdPVwiXG4gICAgICAgICAgICAgICAgICBsYXllci5pZCA9PT0gKGxheWVySWQoKSB8fCBsYXllck9wdGlvbnMoKVswXS5pZClcbiAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3RMYXllcihsYXllci5pZClcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAge3sgbGF5ZXIudGl0bGUgfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2xpPlxuICAgICAgICAgIH1cbiAgICAgICAgPC91bD5cbiAgICAgIH0gQGVsc2UgaWYgKGxheWVyT3B0aW9ucygpLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwiZ2VvLW1hcC1vcGFjaXR5X19sYXllci1uYW1lXCI+XG4gICAgICAgICAge3sgbGF5ZXJPcHRpb25zKClbMF0udGl0bGUgfX1cbiAgICAgICAgPC9kaXY+XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cImdlby1tYXAtb3BhY2l0eV9fZW1wdHlcIj5DaMawYSBjw7MgbOG7m3AgxJHhu4MgY2jhu4luaC48L2Rpdj5cbiAgICAgIH1cblxuICAgICAgPGRpdiBjbGFzcz1cImdlby1tYXAtb3BhY2l0eV9fc2xpZGVyXCI+XG4gICAgICAgIDxnZW8tc2xpZGVyIFsodmFsdWUpXT1cIm9wYWNpdHlcIiBbbWluXT1cIjBcIiBbbWF4XT1cIjEwMFwiIFtzdGVwXT1cIjFcIiAvPlxuICAgICAgICA8c3BhbiBjbGFzcz1cImdlby1tYXAtb3BhY2l0eV9fdmFsdWVcIj57eyBvcGFjaXR5KCkgfX0lPC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvbnotZHJvcGRvd24tbWVudT5cbn0gQGVsc2Uge1xuICA8ZGl2IGNsYXNzPVwiZ2VvLW1hcC1vcGFjaXR5X19wYW5lbFwiPlxuICAgIDxkaXYgY2xhc3M9XCJnZW8tbWFwLW9wYWNpdHlfX3RpdGxlXCI+e3sgdGl0bGUoKSB9fTwvZGl2PlxuICAgIEBpZiAobGF5ZXJPcHRpb25zKCkubGVuZ3RoID4gMSkge1xuICAgICAgPHVsIGNsYXNzPVwiZ2VvLW1hcC1vcGFjaXR5X19sYXllcnNcIj5cbiAgICAgICAgQGZvciAobGF5ZXIgb2YgbGF5ZXJPcHRpb25zKCk7IHRyYWNrIGxheWVyLmlkKSB7XG4gICAgICAgICAgPGxpPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJnZW8tbWFwLW9wYWNpdHlfX2xheWVyXCJcbiAgICAgICAgICAgICAgW2NsYXNzLmdlby1tYXAtb3BhY2l0eV9fbGF5ZXItLWFjdGl2ZV09XCJcbiAgICAgICAgICAgICAgICBsYXllci5pZCA9PT0gKGxheWVySWQoKSB8fCBsYXllck9wdGlvbnMoKVswXS5pZClcbiAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdExheWVyKGxheWVyLmlkKVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt7IGxheWVyLnRpdGxlIH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2xpPlxuICAgICAgICB9XG4gICAgICA8L3VsPlxuICAgIH0gQGVsc2UgaWYgKGxheWVyT3B0aW9ucygpLmxlbmd0aCA9PT0gMSkge1xuICAgICAgPGRpdiBjbGFzcz1cImdlby1tYXAtb3BhY2l0eV9fbGF5ZXItbmFtZVwiPnt7IGxheWVyT3B0aW9ucygpWzBdLnRpdGxlIH19PC9kaXY+XG4gICAgfSBAZWxzZSB7XG4gICAgICA8ZGl2IGNsYXNzPVwiZ2VvLW1hcC1vcGFjaXR5X19lbXB0eVwiPkNoxrBhIGPDsyBs4bubcCDEkeG7gyBjaOG7iW5oLjwvZGl2PlxuICAgIH1cblxuICAgIDxkaXYgY2xhc3M9XCJnZW8tbWFwLW9wYWNpdHlfX3NsaWRlclwiPlxuICAgICAgPGdlby1zbGlkZXIgWyh2YWx1ZSldPVwib3BhY2l0eVwiIFttaW5dPVwiMFwiIFttYXhdPVwiMTAwXCIgW3N0ZXBdPVwiMVwiIC8+XG4gICAgICA8c3BhbiBjbGFzcz1cImdlby1tYXAtb3BhY2l0eV9fdmFsdWVcIj57eyBvcGFjaXR5KCkgfX0lPC9zcGFuPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbn1cbiJdfQ==
|