@geoit/ui 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ai/README.md CHANGED
@@ -76,6 +76,6 @@ Agent rules: [`AGENTS.md`](./AGENTS.md) · Recipes: [`recipes.md`](./recipes.md)
76
76
  | `geo-typography` | display | Text with GEO type scale (h1–tiny) and semantic colors. | [geo-typography.md](./components/geo-typography.md) |
77
77
  | `geo-upload` | forms | Drag-drop upload zone with progress list. | [geo-upload.md](./components/geo-upload.md) |
78
78
 
79
- Generated: 2026-09-09T08:26:14.960Z
79
+ Generated: 2026-09-11T02:34:24.165Z
80
80
 
81
81
  Regenerate: `npm run ai:docs`
package/ai/catalog.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "package": "@geoit/ui",
3
3
  "import": "@geoit/ui",
4
- "version": "0.1.0",
5
- "generatedAt": "2026-09-09T08:26:14.960Z",
4
+ "version": "0.1.1",
5
+ "generatedAt": "2026-09-11T02:34:24.165Z",
6
6
  "styles": [
7
7
  "@geoit/ui/src/lib/styles/design-tokens.scss",
8
8
  "@geoit/ui/src/lib/styles/theme.scss"
@@ -3558,6 +3558,12 @@
3558
3558
  "default": "GEO_MAP_DEMO_LEGEND_ITEMS",
3559
3559
  "note": ""
3560
3560
  },
3561
+ {
3562
+ "name": "legendCatalogMissing",
3563
+ "type": "boolean",
3564
+ "default": "false",
3565
+ "note": "Host app sets true when the legend catalog (loại đất/ký hiệu/màu) failed to load."
3566
+ },
3561
3567
  {
3562
3568
  "name": "showNav",
3563
3569
  "type": "boolean",
@@ -3708,11 +3714,21 @@
3708
3714
  "type": "OutputEmitterRef<GeoMapClickEvent>",
3709
3715
  "note": ""
3710
3716
  },
3717
+ {
3718
+ "name": "located",
3719
+ "type": "OutputEmitterRef<void>",
3720
+ "note": ""
3721
+ },
3711
3722
  {
3712
3723
  "name": "locateDenied",
3713
3724
  "type": "OutputEmitterRef<void>",
3714
3725
  "note": ""
3715
3726
  },
3727
+ {
3728
+ "name": "locateError",
3729
+ "type": "OutputEmitterRef<{ reason: GeoMapLocateErrorReason; message?: string; }>",
3730
+ "note": ""
3731
+ },
3716
3732
  {
3717
3733
  "name": "actionClick",
3718
3734
  "type": "OutputEmitterRef<GeoMapToolbarAction>",
@@ -53,6 +53,7 @@ Every supported Input (do not invent others):
53
53
  | `toolbarActions` | `GeoMapToolbarAction[]` | `GEO_MAP_DEFAULT_TOOLBAR_ACTIONS` | — |
54
54
  | `layers` | `GeoMapLayerConfig[]` | `[]` | Extra overlays merged after demo thematic + traffic. |
55
55
  | `legendItems` | `GeoMapLegendItem[]` | `GEO_MAP_DEMO_LEGEND_ITEMS` | — |
56
+ | `legendCatalogMissing` | `boolean` | `false` | Host app sets true when the legend catalog (loại đất/ký hiệu/màu) failed to load. |
56
57
  | `showNav` | `boolean` | `true` | — |
57
58
  | `includeDemoLayers` | `boolean` | `true` | — |
58
59
  | `adminNodes` | `GeoTreeNode[]` | `GEO_MAP_DEMO_ADMIN_NODES` | — |
@@ -83,7 +84,9 @@ Every supported Input (do not invent others):
83
84
  |--------|---------|-------------|
84
85
  | `mapReady` | `OutputEmitterRef<GeoMapController>` | — |
85
86
  | `mapClick` | `OutputEmitterRef<GeoMapClickEvent>` | — |
87
+ | `located` | `OutputEmitterRef<void>` | — |
86
88
  | `locateDenied` | `OutputEmitterRef<void>` | — |
89
+ | `locateError` | `OutputEmitterRef<{ reason: GeoMapLocateErrorReason; message?: string; }>` | — |
87
90
  | `actionClick` | `OutputEmitterRef<GeoMapToolbarAction>` | — |
88
91
  | `search` | `OutputEmitterRef<GeoMapSearchQuery>` | — |
89
92
  | `searchReset` | `OutputEmitterRef<void>` | — |
package/ai/mockup.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <title>@geoit/ui — Component mockup (design tokens)</title>
7
7
  <!-- Generated by tools/generate-mockup.js — do not edit ai/mockup.html by hand -->
8
- <!-- 2026-09-09T08:26:15.022Z -->
8
+ <!-- 2026-09-11T02:34:24.225Z -->
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com" />
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
11
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
@@ -685,7 +685,7 @@
685
685
  HTML tĩnh mô phỏng visual của các <code>geo-*</code> trong <code>ai/components</code>,
686
686
  dùng đúng CSS variables từ <code>design-tokens.scss</code>.
687
687
  Tokens được inject tự động khi <code>npm run ai:docs</code> / <code>npm run build</code>.
688
- <br /><span class="typo-caption typo-secondary">Generated 2026-09-09T08:26:15.022Z · source: projects/geo-ui/src/lib/styles/design-tokens.scss · 69 component docs in ai/components</span>
688
+ <br /><span class="typo-caption typo-secondary">Generated 2026-09-11T02:34:24.225Z · source: projects/geo-ui/src/lib/styles/design-tokens.scss · 69 component docs in ai/components</span>
689
689
  </p>
690
690
  </header>
691
691
 
@@ -1,7 +1,7 @@
1
1
  import { ChangeDetectionStrategy, Component, input, output, signal, ViewEncapsulation, } from '@angular/core';
2
2
  import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
3
- import { fromLonLat } from 'ol/proj';
4
3
  import { GeoIconComponent } from '../../../geo-icon/geo-icon.component';
4
+ import { runGeoMapLocate } from './geo-map-locate.util';
5
5
  import * as i0 from "@angular/core";
6
6
  import * as i1 from "ng-zorro-antd/tooltip";
7
7
  /**
@@ -23,43 +23,20 @@ export class GeoMapLocateComponent {
23
23
  if (!ctrl || this.busy()) {
24
24
  return;
25
25
  }
26
- if (typeof navigator === 'undefined' || !navigator.geolocation) {
27
- this.locateError.emit({
28
- reason: 'unsupported',
29
- message: 'Trình duyệt không hỗ trợ định vị.',
30
- });
31
- return;
32
- }
33
26
  this.busy.set(true);
34
- navigator.geolocation.getCurrentPosition((pos) => {
35
- this.busy.set(false);
36
- const lonLat = [
37
- pos.coords.longitude,
38
- pos.coords.latitude,
39
- ];
40
- const mercator = fromLonLat(lonLat);
41
- ctrl.setCenter(mercator, Math.max(ctrl.getZoom() ?? 14, 14));
42
- this.located.emit(lonLat);
43
- }, (err) => {
44
- this.busy.set(false);
45
- if (err.code === err.PERMISSION_DENIED) {
27
+ runGeoMapLocate(ctrl, {
28
+ onLocated: (lonLat) => {
29
+ this.busy.set(false);
30
+ this.located.emit(lonLat);
31
+ },
32
+ onDenied: () => {
33
+ this.busy.set(false);
46
34
  this.denied.emit();
47
- this.locateError.emit({
48
- reason: 'denied',
49
- message: err.message,
50
- });
51
- return;
52
- }
53
- const reason = err.code === err.POSITION_UNAVAILABLE
54
- ? 'unavailable'
55
- : err.code === err.TIMEOUT
56
- ? 'timeout'
57
- : 'unknown';
58
- this.locateError.emit({ reason, message: err.message });
59
- }, {
60
- enableHighAccuracy: true,
61
- timeout: 12000,
62
- maximumAge: 0,
35
+ },
36
+ onError: (error) => {
37
+ this.busy.set(false);
38
+ this.locateError.emit(error);
39
+ },
63
40
  });
64
41
  }
65
42
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapLocateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -69,4 +46,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
69
46
  type: Component,
70
47
  args: [{ selector: 'geo-map-locate', standalone: true, imports: [GeoIconComponent, NzToolTipModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'geo-map-locate-host' }, template: "<button\n type=\"button\"\n class=\"geo-map-locate__btn\"\n [nz-tooltip]=\"label()\"\n nzTooltipPlacement=\"left\"\n [attr.aria-label]=\"label()\"\n [disabled]=\"!controller() || busy()\"\n (click)=\"locate()\"\n>\n <geo-icon type=\"aim\" size=\"md\" />\n</button>\n", styles: ["@charset \"UTF-8\";.geo-map-locate-host{display:block}.geo-map-locate__btn{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-locate__btn:hover:not(:disabled){background:var(--geo-color-primary-soft-hover);color:var(--geo-color-primary-default)}.geo-map-locate__btn:active:not(:disabled){transform:scale(.98)}.geo-map-locate__btn:disabled{opacity:.45;cursor:not-allowed}.geo-map-locate__btn--active,.geo-map-locate__btn--checked{background:var(--geo-color-primary-soft-active);color:var(--geo-color-primary-default)}.geo-map-locate__btn--icon-only{width:40px;padding:0}\n"] }]
71
48
  }] });
72
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvLW1hcC1sb2NhdGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZ2VvLXVpL3NyYy9saWIvZmlnbWEvZ2VvLW1hcC9jaHJvbWUvZ2VvLW1hcC1sb2NhdGUvZ2VvLW1hcC1sb2NhdGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZ2VvLXVpL3NyYy9saWIvZmlnbWEvZ2VvLW1hcC9jaHJvbWUvZ2VvLW1hcC1sb2NhdGUvZ2VvLW1hcC1sb2NhdGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sRUFDTixNQUFNLEVBQ04saUJBQWlCLEdBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDOzs7QUFJeEU7Ozs7OztHQU1HO0FBV0gsTUFBTSxPQUFPLHFCQUFxQjtJQUN2QixVQUFVLEdBQUcsS0FBSyxDQUEwQixJQUFJLENBQUMsQ0FBQztJQUNsRCxLQUFLLEdBQUcsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFFaEMsT0FBTyxHQUFHLE1BQU0sRUFBb0IsQ0FBQztJQUNyQyxNQUFNLEdBQUcsTUFBTSxFQUFRLENBQUM7SUFDeEIsV0FBVyxHQUFHLE1BQU0sRUFHekIsQ0FBQztJQUVJLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFOUIsTUFBTTtRQUNKLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQ3pCLE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxPQUFPLFNBQVMsS0FBSyxXQUFXLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDL0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7Z0JBQ3BCLE1BQU0sRUFBRSxhQUFhO2dCQUNyQixPQUFPLEVBQUUsbUNBQW1DO2FBQzdDLENBQUMsQ0FBQztZQUNILE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEIsU0FBUyxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FDdEMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUNOLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3JCLE1BQU0sTUFBTSxHQUFxQjtnQkFDL0IsR0FBRyxDQUFDLE1BQU0sQ0FBQyxTQUFTO2dCQUNwQixHQUFHLENBQUMsTUFBTSxDQUFDLFFBQVE7YUFDcEIsQ0FBQztZQUNGLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM3RCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM1QixDQUFDLEVBQ0QsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUNOLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3JCLElBQUksR0FBRyxDQUFDLElBQUksS0FBSyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztnQkFDdkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7b0JBQ3BCLE1BQU0sRUFBRSxRQUFRO29CQUNoQixPQUFPLEVBQUUsR0FBRyxDQUFDLE9BQU87aUJBQ3JCLENBQUMsQ0FBQztnQkFDSCxPQUFPO1lBQ1QsQ0FBQztZQUNELE1BQU0sTUFBTSxHQUNWLEdBQUcsQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLG9CQUFvQjtnQkFDbkMsQ0FBQyxDQUFDLGFBQWE7Z0JBQ2YsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLE9BQU87b0JBQ3hCLENBQUMsQ0FBQyxTQUFTO29CQUNYLENBQUMsQ0FBQyxTQUFTLENBQUM7WUFDbEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzFELENBQUMsRUFDRDtZQUNFLGtCQUFrQixFQUFFLElBQUk7WUFDeEIsT0FBTyxFQUFFLEtBQUs7WUFDZCxVQUFVLEVBQUUsQ0FBQztTQUNkLENBQ0YsQ0FBQztJQUNKLENBQUM7d0dBL0RVLHFCQUFxQjs0RkFBckIscUJBQXFCLHFkQy9CbEMsb1JBV0EsZ3FDRGFZLGdCQUFnQix3R0FBRSxlQUFlOzs0RkFPaEMscUJBQXFCO2tCQVZqQyxTQUFTOytCQUNFLGdCQUFnQixjQUNkLElBQUksV0FDUCxDQUFDLGdCQUFnQixFQUFFLGVBQWUsQ0FBQyxtQkFHM0IsdUJBQXVCLENBQUMsTUFBTSxpQkFDaEMsaUJBQWlCLENBQUMsSUFBSSxRQUMvQixFQUFFLEtBQUssRUFBRSxxQkFBcUIsRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIGlucHV0LFxuICBvdXRwdXQsXG4gIHNpZ25hbCxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTnpUb29sVGlwTW9kdWxlIH0gZnJvbSAnbmctem9ycm8tYW50ZC90b29sdGlwJztcbmltcG9ydCB7IGZyb21Mb25MYXQgfSBmcm9tICdvbC9wcm9qJztcbmltcG9ydCB7IEdlb0ljb25Db21wb25lbnQgfSBmcm9tICcuLi8uLi8uLi9nZW8taWNvbi9nZW8taWNvbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgR2VvTWFwQ29udHJvbGxlciB9IGZyb20gJy4uLy4uL2dlby1tYXAuY29udHJvbGxlcic7XG5pbXBvcnQgdHlwZSB7IEdlb01hcExvY2F0ZUVycm9yUmVhc29uIH0gZnJvbSAnLi4vLi4vZ2VvLW1hcC50eXBlcyc7XG5cbi8qKlxuICogR2VvbG9jYXRpb24gYnV0dG9uOiBjZW50ZXIgbWFwIG9uIHVzZXIgYWZ0ZXIgcGVybWlzc2lvbi5cbiAqXG4gKiBAc3VtbWFyeSBHZW9sb2NhdGlvbiBidXR0b246IGNlbnRlciBtYXAgb24gdXNlciBhZnRlciBwZXJtaXNzaW9uLlxuICogQHdoZW5Ub1VzZSBW4buLIHRyw60gY+G7p2EgdMO0aSB0csOqbiBi4bqjbiDEkeG7ky5cbiAqIEBkb05vdFVzZVdoZW4gU2VydmVyLXNpZGUgdHJhY2tpbmcuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2dlby1tYXAtbG9jYXRlJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0dlb0ljb25Db21wb25lbnQsIE56VG9vbFRpcE1vZHVsZV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9nZW8tbWFwLWxvY2F0ZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9nZW8tbWFwLWxvY2F0ZS5jb21wb25lbnQuc2NzcycsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBob3N0OiB7IGNsYXNzOiAnZ2VvLW1hcC1sb2NhdGUtaG9zdCcgfSxcbn0pXG5leHBvcnQgY2xhc3MgR2VvTWFwTG9jYXRlQ29tcG9uZW50IHtcbiAgcmVhZG9ubHkgY29udHJvbGxlciA9IGlucHV0PEdlb01hcENvbnRyb2xsZXIgfCBudWxsPihudWxsKTtcbiAgcmVhZG9ubHkgbGFiZWwgPSBpbnB1dCgnVuG7iyB0csOtIGPhu6dhIHTDtGknKTtcblxuICByZWFkb25seSBsb2NhdGVkID0gb3V0cHV0PFtudW1iZXIsIG51bWJlcl0+KCk7XG4gIHJlYWRvbmx5IGRlbmllZCA9IG91dHB1dDx2b2lkPigpO1xuICByZWFkb25seSBsb2NhdGVFcnJvciA9IG91dHB1dDx7XG4gICAgcmVhc29uOiBHZW9NYXBMb2NhdGVFcnJvclJlYXNvbjtcbiAgICBtZXNzYWdlPzogc3RyaW5nO1xuICB9PigpO1xuXG4gIHJlYWRvbmx5IGJ1c3kgPSBzaWduYWwoZmFsc2UpO1xuXG4gIGxvY2F0ZSgpOiB2b2lkIHtcbiAgICBjb25zdCBjdHJsID0gdGhpcy5jb250cm9sbGVyKCk7XG4gICAgaWYgKCFjdHJsIHx8IHRoaXMuYnVzeSgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgPT09ICd1bmRlZmluZWQnIHx8ICFuYXZpZ2F0b3IuZ2VvbG9jYXRpb24pIHtcbiAgICAgIHRoaXMubG9jYXRlRXJyb3IuZW1pdCh7XG4gICAgICAgIHJlYXNvbjogJ3Vuc3VwcG9ydGVkJyxcbiAgICAgICAgbWVzc2FnZTogJ1Ryw6xuaCBkdXnhu4d0IGtow7RuZyBo4buXIHRy4bujIMSR4buLbmggduG7iy4nLFxuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5idXN5LnNldCh0cnVlKTtcbiAgICBuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uZ2V0Q3VycmVudFBvc2l0aW9uKFxuICAgICAgKHBvcykgPT4ge1xuICAgICAgICB0aGlzLmJ1c3kuc2V0KGZhbHNlKTtcbiAgICAgICAgY29uc3QgbG9uTGF0OiBbbnVtYmVyLCBudW1iZXJdID0gW1xuICAgICAgICAgIHBvcy5jb29yZHMubG9uZ2l0dWRlLFxuICAgICAgICAgIHBvcy5jb29yZHMubGF0aXR1ZGUsXG4gICAgICAgIF07XG4gICAgICAgIGNvbnN0IG1lcmNhdG9yID0gZnJvbUxvbkxhdChsb25MYXQpO1xuICAgICAgICBjdHJsLnNldENlbnRlcihtZXJjYXRvciwgTWF0aC5tYXgoY3RybC5nZXRab29tKCkgPz8gMTQsIDE0KSk7XG4gICAgICAgIHRoaXMubG9jYXRlZC5lbWl0KGxvbkxhdCk7XG4gICAgICB9LFxuICAgICAgKGVycikgPT4ge1xuICAgICAgICB0aGlzLmJ1c3kuc2V0KGZhbHNlKTtcbiAgICAgICAgaWYgKGVyci5jb2RlID09PSBlcnIuUEVSTUlTU0lPTl9ERU5JRUQpIHtcbiAgICAgICAgICB0aGlzLmRlbmllZC5lbWl0KCk7XG4gICAgICAgICAgdGhpcy5sb2NhdGVFcnJvci5lbWl0KHtcbiAgICAgICAgICAgIHJlYXNvbjogJ2RlbmllZCcsXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVhc29uOiBHZW9NYXBMb2NhdGVFcnJvclJlYXNvbiA9XG4gICAgICAgICAgZXJyLmNvZGUgPT09IGVyci5QT1NJVElPTl9VTkFWQUlMQUJMRVxuICAgICAgICAgICAgPyAndW5hdmFpbGFibGUnXG4gICAgICAgICAgICA6IGVyci5jb2RlID09PSBlcnIuVElNRU9VVFxuICAgICAgICAgICAgICA/ICd0aW1lb3V0J1xuICAgICAgICAgICAgICA6ICd1bmtub3duJztcbiAgICAgICAgdGhpcy5sb2NhdGVFcnJvci5lbWl0KHsgcmVhc29uLCBtZXNzYWdlOiBlcnIubWVzc2FnZSB9KTtcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGVuYWJsZUhpZ2hBY2N1cmFjeTogdHJ1ZSxcbiAgICAgICAgdGltZW91dDogMTIwMDAsXG4gICAgICAgIG1heGltdW1BZ2U6IDAsXG4gICAgICB9LFxuICAgICk7XG4gIH1cbn1cbiIsIjxidXR0b25cbiAgdHlwZT1cImJ1dHRvblwiXG4gIGNsYXNzPVwiZ2VvLW1hcC1sb2NhdGVfX2J0blwiXG4gIFtuei10b29sdGlwXT1cImxhYmVsKClcIlxuICBuelRvb2x0aXBQbGFjZW1lbnQ9XCJsZWZ0XCJcbiAgW2F0dHIuYXJpYS1sYWJlbF09XCJsYWJlbCgpXCJcbiAgW2Rpc2FibGVkXT1cIiFjb250cm9sbGVyKCkgfHwgYnVzeSgpXCJcbiAgKGNsaWNrKT1cImxvY2F0ZSgpXCJcbj5cbiAgPGdlby1pY29uIHR5cGU9XCJhaW1cIiBzaXplPVwibWRcIiAvPlxuPC9idXR0b24+XG4iXX0=
49
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvLW1hcC1sb2NhdGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZ2VvLXVpL3NyYy9saWIvZmlnbWEvZ2VvLW1hcC9jaHJvbWUvZ2VvLW1hcC1sb2NhdGUvZ2VvLW1hcC1sb2NhdGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZ2VvLXVpL3NyYy9saWIvZmlnbWEvZ2VvLW1hcC9jaHJvbWUvZ2VvLW1hcC1sb2NhdGUvZ2VvLW1hcC1sb2NhdGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sRUFDTixNQUFNLEVBQ04saUJBQWlCLEdBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUd4RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7OztBQUV4RDs7Ozs7O0dBTUc7QUFXSCxNQUFNLE9BQU8scUJBQXFCO0lBQ3ZCLFVBQVUsR0FBRyxLQUFLLENBQTBCLElBQUksQ0FBQyxDQUFDO0lBQ2xELEtBQUssR0FBRyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUVoQyxPQUFPLEdBQUcsTUFBTSxFQUFvQixDQUFDO0lBQ3JDLE1BQU0sR0FBRyxNQUFNLEVBQVEsQ0FBQztJQUN4QixXQUFXLEdBQUcsTUFBTSxFQUd6QixDQUFDO0lBRUksSUFBSSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUU5QixNQUFNO1FBQ0osTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQy9CLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDekIsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQixlQUFlLENBQUMsSUFBSSxFQUFFO1lBQ3BCLFNBQVMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFO2dCQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDckIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDNUIsQ0FBQztZQUNELFFBQVEsRUFBRSxHQUFHLEVBQUU7Z0JBQ2IsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckIsQ0FBQztZQUNELE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFO2dCQUNqQixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDckIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDL0IsQ0FBQztTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7d0dBbENVLHFCQUFxQjs0RkFBckIscUJBQXFCLHFkQy9CbEMsb1JBV0EsZ3FDRGFZLGdCQUFnQix3R0FBRSxlQUFlOzs0RkFPaEMscUJBQXFCO2tCQVZqQyxTQUFTOytCQUNFLGdCQUFnQixjQUNkLElBQUksV0FDUCxDQUFDLGdCQUFnQixFQUFFLGVBQWUsQ0FBQyxtQkFHM0IsdUJBQXVCLENBQUMsTUFBTSxpQkFDaEMsaUJBQWlCLENBQUMsSUFBSSxRQUMvQixFQUFFLEtBQUssRUFBRSxxQkFBcUIsRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIGlucHV0LFxuICBvdXRwdXQsXG4gIHNpZ25hbCxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTnpUb29sVGlwTW9kdWxlIH0gZnJvbSAnbmctem9ycm8tYW50ZC90b29sdGlwJztcbmltcG9ydCB7IEdlb0ljb25Db21wb25lbnQgfSBmcm9tICcuLi8uLi8uLi9nZW8taWNvbi9nZW8taWNvbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgR2VvTWFwQ29udHJvbGxlciB9IGZyb20gJy4uLy4uL2dlby1tYXAuY29udHJvbGxlcic7XG5pbXBvcnQgdHlwZSB7IEdlb01hcExvY2F0ZUVycm9yUmVhc29uIH0gZnJvbSAnLi4vLi4vZ2VvLW1hcC50eXBlcyc7XG5pbXBvcnQgeyBydW5HZW9NYXBMb2NhdGUgfSBmcm9tICcuL2dlby1tYXAtbG9jYXRlLnV0aWwnO1xuXG4vKipcbiAqIEdlb2xvY2F0aW9uIGJ1dHRvbjogY2VudGVyIG1hcCBvbiB1c2VyIGFmdGVyIHBlcm1pc3Npb24uXG4gKlxuICogQHN1bW1hcnkgR2VvbG9jYXRpb24gYnV0dG9uOiBjZW50ZXIgbWFwIG9uIHVzZXIgYWZ0ZXIgcGVybWlzc2lvbi5cbiAqIEB3aGVuVG9Vc2UgVuG7iyB0csOtIGPhu6dhIHTDtGkgdHLDqm4gYuG6o24gxJHhu5MuXG4gKiBAZG9Ob3RVc2VXaGVuIFNlcnZlci1zaWRlIHRyYWNraW5nLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdnZW8tbWFwLWxvY2F0ZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtHZW9JY29uQ29tcG9uZW50LCBOelRvb2xUaXBNb2R1bGVdLFxuICB0ZW1wbGF0ZVVybDogJy4vZ2VvLW1hcC1sb2NhdGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZ2VvLW1hcC1sb2NhdGUuY29tcG9uZW50LnNjc3MnLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgaG9zdDogeyBjbGFzczogJ2dlby1tYXAtbG9jYXRlLWhvc3QnIH0sXG59KVxuZXhwb3J0IGNsYXNzIEdlb01hcExvY2F0ZUNvbXBvbmVudCB7XG4gIHJlYWRvbmx5IGNvbnRyb2xsZXIgPSBpbnB1dDxHZW9NYXBDb250cm9sbGVyIHwgbnVsbD4obnVsbCk7XG4gIHJlYWRvbmx5IGxhYmVsID0gaW5wdXQoJ1bhu4sgdHLDrSBj4bunYSB0w7RpJyk7XG5cbiAgcmVhZG9ubHkgbG9jYXRlZCA9IG91dHB1dDxbbnVtYmVyLCBudW1iZXJdPigpO1xuICByZWFkb25seSBkZW5pZWQgPSBvdXRwdXQ8dm9pZD4oKTtcbiAgcmVhZG9ubHkgbG9jYXRlRXJyb3IgPSBvdXRwdXQ8e1xuICAgIHJlYXNvbjogR2VvTWFwTG9jYXRlRXJyb3JSZWFzb247XG4gICAgbWVzc2FnZT86IHN0cmluZztcbiAgfT4oKTtcblxuICByZWFkb25seSBidXN5ID0gc2lnbmFsKGZhbHNlKTtcblxuICBsb2NhdGUoKTogdm9pZCB7XG4gICAgY29uc3QgY3RybCA9IHRoaXMuY29udHJvbGxlcigpO1xuICAgIGlmICghY3RybCB8fCB0aGlzLmJ1c3koKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuYnVzeS5zZXQodHJ1ZSk7XG4gICAgcnVuR2VvTWFwTG9jYXRlKGN0cmwsIHtcbiAgICAgIG9uTG9jYXRlZDogKGxvbkxhdCkgPT4ge1xuICAgICAgICB0aGlzLmJ1c3kuc2V0KGZhbHNlKTtcbiAgICAgICAgdGhpcy5sb2NhdGVkLmVtaXQobG9uTGF0KTtcbiAgICAgIH0sXG4gICAgICBvbkRlbmllZDogKCkgPT4ge1xuICAgICAgICB0aGlzLmJ1c3kuc2V0KGZhbHNlKTtcbiAgICAgICAgdGhpcy5kZW5pZWQuZW1pdCgpO1xuICAgICAgfSxcbiAgICAgIG9uRXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICB0aGlzLmJ1c3kuc2V0KGZhbHNlKTtcbiAgICAgICAgdGhpcy5sb2NhdGVFcnJvci5lbWl0KGVycm9yKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cbn1cbiIsIjxidXR0b25cbiAgdHlwZT1cImJ1dHRvblwiXG4gIGNsYXNzPVwiZ2VvLW1hcC1sb2NhdGVfX2J0blwiXG4gIFtuei10b29sdGlwXT1cImxhYmVsKClcIlxuICBuelRvb2x0aXBQbGFjZW1lbnQ9XCJsZWZ0XCJcbiAgW2F0dHIuYXJpYS1sYWJlbF09XCJsYWJlbCgpXCJcbiAgW2Rpc2FibGVkXT1cIiFjb250cm9sbGVyKCkgfHwgYnVzeSgpXCJcbiAgKGNsaWNrKT1cImxvY2F0ZSgpXCJcbj5cbiAgPGdlby1pY29uIHR5cGU9XCJhaW1cIiBzaXplPVwibWRcIiAvPlxuPC9idXR0b24+XG4iXX0=
@@ -0,0 +1,38 @@
1
+ import { fromLonLat } from 'ol/proj';
2
+ /**
3
+ * Shared browser-geolocation trigger — centers `ctrl` on the user and reports the outcome.
4
+ * Used by both `geo-map-locate` (standalone button) and `geo-map-shell`'s built-in locate
5
+ * toolbar action so the two never drift on error-reason mapping.
6
+ */
7
+ export function runGeoMapLocate(ctrl, callbacks) {
8
+ if (typeof navigator === 'undefined' || !navigator.geolocation) {
9
+ callbacks.onError?.({
10
+ reason: 'unsupported',
11
+ message: 'Trình duyệt không hỗ trợ định vị.',
12
+ });
13
+ return;
14
+ }
15
+ navigator.geolocation.getCurrentPosition((pos) => {
16
+ const lonLat = [pos.coords.longitude, pos.coords.latitude];
17
+ const mercator = fromLonLat(lonLat);
18
+ ctrl.setCenter(mercator, Math.max(ctrl.getZoom() ?? 14, 14));
19
+ callbacks.onLocated?.(lonLat);
20
+ }, (err) => {
21
+ if (err.code === err.PERMISSION_DENIED) {
22
+ callbacks.onDenied?.();
23
+ callbacks.onError?.({ reason: 'denied', message: err.message });
24
+ return;
25
+ }
26
+ const reason = err.code === err.POSITION_UNAVAILABLE
27
+ ? 'unavailable'
28
+ : err.code === err.TIMEOUT
29
+ ? 'timeout'
30
+ : 'unknown';
31
+ callbacks.onError?.({ reason, message: err.message });
32
+ }, {
33
+ enableHighAccuracy: true,
34
+ timeout: 12000,
35
+ maximumAge: 0,
36
+ });
37
+ }
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvLW1hcC1sb2NhdGUudXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2dlby11aS9zcmMvbGliL2ZpZ21hL2dlby1tYXAvY2hyb21lL2dlby1tYXAtbG9jYXRlL2dlby1tYXAtbG9jYXRlLnV0aWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQVVyQzs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FDN0IsSUFBc0IsRUFDdEIsU0FBZ0M7SUFFaEMsSUFBSSxPQUFPLFNBQVMsS0FBSyxXQUFXLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDL0QsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLE1BQU0sRUFBRSxhQUFhO1lBQ3JCLE9BQU8sRUFBRSxtQ0FBbUM7U0FDN0MsQ0FBQyxDQUFDO1FBQ0gsT0FBTztJQUNULENBQUM7SUFFRCxTQUFTLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUN0QyxDQUFDLEdBQUcsRUFBRSxFQUFFO1FBQ04sTUFBTSxNQUFNLEdBQXFCLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM3RSxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDN0QsU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2hDLENBQUMsRUFDRCxDQUFDLEdBQUcsRUFBRSxFQUFFO1FBQ04sSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQ3ZDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQ3ZCLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ2hFLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQ1YsR0FBRyxDQUFDLElBQUksS0FBSyxHQUFHLENBQUMsb0JBQW9CO1lBQ25DLENBQUMsQ0FBQyxhQUFhO1lBQ2YsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLE9BQU87Z0JBQ3hCLENBQUMsQ0FBQyxTQUFTO2dCQUNYLENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDbEIsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUN4RCxDQUFDLEVBQ0Q7UUFDRSxrQkFBa0IsRUFBRSxJQUFJO1FBQ3hCLE9BQU8sRUFBRSxLQUFLO1FBQ2QsVUFBVSxFQUFFLENBQUM7S0FDZCxDQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZnJvbUxvbkxhdCB9IGZyb20gJ29sL3Byb2onO1xuaW1wb3J0IHsgR2VvTWFwQ29udHJvbGxlciB9IGZyb20gJy4uLy4uL2dlby1tYXAuY29udHJvbGxlcic7XG5pbXBvcnQgdHlwZSB7IEdlb01hcExvY2F0ZUVycm9yUmVhc29uIH0gZnJvbSAnLi4vLi4vZ2VvLW1hcC50eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2VvTWFwTG9jYXRlQ2FsbGJhY2tzIHtcbiAgb25Mb2NhdGVkPzogKGxvbkxhdDogW251bWJlciwgbnVtYmVyXSkgPT4gdm9pZDtcbiAgb25EZW5pZWQ/OiAoKSA9PiB2b2lkO1xuICBvbkVycm9yPzogKGVycm9yOiB7IHJlYXNvbjogR2VvTWFwTG9jYXRlRXJyb3JSZWFzb247IG1lc3NhZ2U/OiBzdHJpbmcgfSkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBTaGFyZWQgYnJvd3Nlci1nZW9sb2NhdGlvbiB0cmlnZ2VyIOKAlCBjZW50ZXJzIGBjdHJsYCBvbiB0aGUgdXNlciBhbmQgcmVwb3J0cyB0aGUgb3V0Y29tZS5cbiAqIFVzZWQgYnkgYm90aCBgZ2VvLW1hcC1sb2NhdGVgIChzdGFuZGFsb25lIGJ1dHRvbikgYW5kIGBnZW8tbWFwLXNoZWxsYCdzIGJ1aWx0LWluIGxvY2F0ZVxuICogdG9vbGJhciBhY3Rpb24gc28gdGhlIHR3byBuZXZlciBkcmlmdCBvbiBlcnJvci1yZWFzb24gbWFwcGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJ1bkdlb01hcExvY2F0ZShcbiAgY3RybDogR2VvTWFwQ29udHJvbGxlcixcbiAgY2FsbGJhY2tzOiBHZW9NYXBMb2NhdGVDYWxsYmFja3MsXG4pOiB2b2lkIHtcbiAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgPT09ICd1bmRlZmluZWQnIHx8ICFuYXZpZ2F0b3IuZ2VvbG9jYXRpb24pIHtcbiAgICBjYWxsYmFja3Mub25FcnJvcj8uKHtcbiAgICAgIHJlYXNvbjogJ3Vuc3VwcG9ydGVkJyxcbiAgICAgIG1lc3NhZ2U6ICdUcsOsbmggZHV54buHdCBraMO0bmcgaOG7lyB0cuG7oyDEkeG7i25oIHbhu4suJyxcbiAgICB9KTtcbiAgICByZXR1cm47XG4gIH1cblxuICBuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uZ2V0Q3VycmVudFBvc2l0aW9uKFxuICAgIChwb3MpID0+IHtcbiAgICAgIGNvbnN0IGxvbkxhdDogW251bWJlciwgbnVtYmVyXSA9IFtwb3MuY29vcmRzLmxvbmdpdHVkZSwgcG9zLmNvb3Jkcy5sYXRpdHVkZV07XG4gICAgICBjb25zdCBtZXJjYXRvciA9IGZyb21Mb25MYXQobG9uTGF0KTtcbiAgICAgIGN0cmwuc2V0Q2VudGVyKG1lcmNhdG9yLCBNYXRoLm1heChjdHJsLmdldFpvb20oKSA/PyAxNCwgMTQpKTtcbiAgICAgIGNhbGxiYWNrcy5vbkxvY2F0ZWQ/Lihsb25MYXQpO1xuICAgIH0sXG4gICAgKGVycikgPT4ge1xuICAgICAgaWYgKGVyci5jb2RlID09PSBlcnIuUEVSTUlTU0lPTl9ERU5JRUQpIHtcbiAgICAgICAgY2FsbGJhY2tzLm9uRGVuaWVkPy4oKTtcbiAgICAgICAgY2FsbGJhY2tzLm9uRXJyb3I/Lih7IHJlYXNvbjogJ2RlbmllZCcsIG1lc3NhZ2U6IGVyci5tZXNzYWdlIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCByZWFzb246IEdlb01hcExvY2F0ZUVycm9yUmVhc29uID1cbiAgICAgICAgZXJyLmNvZGUgPT09IGVyci5QT1NJVElPTl9VTkFWQUlMQUJMRVxuICAgICAgICAgID8gJ3VuYXZhaWxhYmxlJ1xuICAgICAgICAgIDogZXJyLmNvZGUgPT09IGVyci5USU1FT1VUXG4gICAgICAgICAgICA/ICd0aW1lb3V0J1xuICAgICAgICAgICAgOiAndW5rbm93bic7XG4gICAgICBjYWxsYmFja3Mub25FcnJvcj8uKHsgcmVhc29uLCBtZXNzYWdlOiBlcnIubWVzc2FnZSB9KTtcbiAgICB9LFxuICAgIHtcbiAgICAgIGVuYWJsZUhpZ2hBY2N1cmFjeTogdHJ1ZSxcbiAgICAgIHRpbWVvdXQ6IDEyMDAwLFxuICAgICAgbWF4aW11bUFnZTogMCxcbiAgICB9LFxuICApO1xufVxuIl19