@maplat/ui 0.11.0 → 0.11.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.
@@ -1,55 +1,55 @@
1
- import { Control, Rotate, Zoom as BaseZoom } from 'ol/control';
2
- import { MaplatUi } from './index';
3
- import { ControlOptions } from './types';
4
- export declare let control_settings: Record<string, string>;
5
- export declare function setControlSettings(options: Record<string, string>): void;
6
- export declare class SliderNew extends Control {
7
- constructor(opt_options: ControlOptions);
8
- setMap(map: import('ol').Map): void;
9
- setEnable(cond: boolean): void;
10
- setValue(res: number): void;
11
- }
12
- export declare class CustomControl extends Control {
13
- center_: import('ol/coordinate').Coordinate | undefined;
14
- zoom_: number | undefined;
15
- callResetNorth_: unknown;
16
- lastRotation_: number;
17
- label_: HTMLElement;
18
- ui: MaplatUi;
19
- moveTo_: boolean;
20
- constructor(optOptions: ControlOptions);
21
- }
22
- export declare class GoHome extends CustomControl {
23
- constructor(optOptions: ControlOptions);
24
- }
25
- export declare class SetGPS extends CustomControl {
26
- constructor(optOptions: ControlOptions);
27
- }
28
- export declare class CompassRotate extends Rotate {
29
- center_?: import('ol/coordinate').Coordinate;
30
- zoom_?: number;
31
- customLabel_: HTMLElement;
32
- lastRotation_: number;
33
- constructor(optOptions: ControlOptions);
34
- }
35
- export declare class Share extends CustomControl {
36
- constructor(optOptions: ControlOptions);
37
- }
38
- export declare class Border extends CustomControl {
39
- constructor(optOptions: ControlOptions);
40
- }
41
- export declare class Maplat extends CustomControl {
42
- constructor(optOptions: ControlOptions);
43
- }
44
- export declare class Copyright extends CustomControl {
45
- constructor(optOptions: ControlOptions);
46
- }
47
- export declare class HideMarker extends CustomControl {
48
- constructor(optOptions: ControlOptions);
49
- }
50
- export declare class MarkerList extends CustomControl {
51
- constructor(optOptions: ControlOptions);
52
- }
53
- export declare class Zoom extends BaseZoom {
54
- constructor(options?: ControlOptions);
55
- }
1
+ import { Control, Rotate, Zoom as BaseZoom } from 'ol/control';
2
+ import { MaplatUi } from './index';
3
+ import { ControlOptions } from './types';
4
+ export declare let control_settings: Record<string, string>;
5
+ export declare function setControlSettings(options: Record<string, string>): void;
6
+ export declare class SliderNew extends Control {
7
+ constructor(opt_options: ControlOptions);
8
+ setMap(map: import('ol').Map): void;
9
+ setEnable(cond: boolean): void;
10
+ setValue(res: number): void;
11
+ }
12
+ export declare class CustomControl extends Control {
13
+ center_: import('ol/coordinate').Coordinate | undefined;
14
+ zoom_: number | undefined;
15
+ callResetNorth_: unknown;
16
+ lastRotation_: number;
17
+ label_: HTMLElement;
18
+ ui: MaplatUi;
19
+ moveTo_: boolean;
20
+ constructor(optOptions: ControlOptions);
21
+ }
22
+ export declare class GoHome extends CustomControl {
23
+ constructor(optOptions: ControlOptions);
24
+ }
25
+ export declare class SetGPS extends CustomControl {
26
+ constructor(optOptions: ControlOptions);
27
+ }
28
+ export declare class CompassRotate extends Rotate {
29
+ center_?: import('ol/coordinate').Coordinate;
30
+ zoom_?: number;
31
+ customLabel_: HTMLElement;
32
+ lastRotation_: number;
33
+ constructor(optOptions: ControlOptions);
34
+ }
35
+ export declare class Share extends CustomControl {
36
+ constructor(optOptions: ControlOptions);
37
+ }
38
+ export declare class Border extends CustomControl {
39
+ constructor(optOptions: ControlOptions);
40
+ }
41
+ export declare class Maplat extends CustomControl {
42
+ constructor(optOptions: ControlOptions);
43
+ }
44
+ export declare class Copyright extends CustomControl {
45
+ constructor(optOptions: ControlOptions);
46
+ }
47
+ export declare class HideMarker extends CustomControl {
48
+ constructor(optOptions: ControlOptions);
49
+ }
50
+ export declare class MarkerList extends CustomControl {
51
+ constructor(optOptions: ControlOptions);
52
+ }
53
+ export declare class Zoom extends BaseZoom {
54
+ constructor(options?: ControlOptions);
55
+ }
@@ -1,2 +1,2 @@
1
- declare const pointer: Record<string, string>;
2
- export default pointer;
1
+ declare const pointer: Record<string, string>;
2
+ export default pointer;
@@ -1,2 +1,2 @@
1
- import { default as Swiper } from 'swiper';
2
- export { Swiper };
1
+ import { default as Swiper } from 'swiper';
2
+ export { Swiper };
package/dist/types.d.ts CHANGED
@@ -1,173 +1,185 @@
1
- import { Swiper as SwiperClass } from 'swiper';
2
- import { Control } from 'ol/control';
3
- import { MaplatUi } from './index';
4
- export interface MaplatAppOption {
5
- appid?: string;
6
- fake?: boolean;
7
- pwaManifest?: boolean | string;
8
- pwaWorker?: string;
9
- pwaScope?: string;
10
- overlay?: boolean;
11
- enableHideMarker?: boolean;
12
- enableMarkerList?: boolean;
13
- enableBorder?: boolean;
14
- enableCache?: boolean;
15
- stateUrl?: boolean;
16
- enableShare?: boolean;
17
- enablePoiHtmlNoScroll?: boolean;
18
- disableNoimage?: boolean;
19
- alwaysGpsOn?: boolean;
20
- mobileIF?: boolean;
21
- debug?: boolean;
22
- appEnvelope?: boolean;
23
- mapboxToken?: string;
24
- googleApiKey?: string;
25
- lang?: string;
26
- restore?: RestoreState;
27
- restoreSession?: boolean;
28
- presentationMode?: boolean;
29
- northTop?: boolean;
30
- mapboxgl?: unknown;
31
- maplibregl?: unknown;
32
- markerList?: boolean;
33
- icon?: string;
34
- translateUI?: boolean;
35
- }
36
- export interface RestoreState {
37
- mapID?: string;
38
- backgroundID?: string;
39
- transparency?: number;
40
- position?: {
41
- rotation?: number;
42
- zoom?: number;
43
- x?: number;
44
- y?: number;
45
- };
46
- showBorder?: boolean;
47
- hideMarker?: boolean;
48
- hideLayer?: string;
49
- openedMarker?: string;
50
- }
51
- export interface MapSource {
52
- mapID: string;
53
- title?: string;
54
- officialTitle?: string;
55
- label?: string;
56
- width?: number;
57
- height?: number;
58
- envelope?: {
59
- geometry: {
60
- coordinates: number[][][];
61
- };
62
- };
63
- envelopeColor?: string;
64
- envelopeAreaIndex?: number;
65
- xy2SysCoord?: (xy: number[]) => Promise<number[]> | number[];
66
- thumbnail?: string;
67
- }
68
- export interface MarkerData {
69
- markerId: string;
70
- lnglat?: number[];
71
- title?: string;
72
- icon?: string;
73
- description?: string;
74
- images?: string[];
75
- image?: string | string[] | {
76
- src: string;
77
- desc?: string;
78
- }[];
79
- address?: string;
80
- desc?: string;
81
- url?: string;
82
- html?: string;
83
- directgo?: string | {
84
- href: string;
85
- blank?: boolean;
86
- };
87
- namespaceID?: string;
88
- name?: string;
89
- }
90
- export interface ClickMarkersEvent {
91
- pixel: number[];
92
- coord: number[];
93
- list: MarkerData[];
94
- }
95
- export interface ContextMenuInterface {
96
- clear: () => void;
97
- extend: (items: unknown[]) => void;
98
- on: (event: string, handler: (e: unknown) => void) => void;
99
- un: (event: string, handler: (e: unknown) => void) => void;
100
- Internal?: {
101
- openMenu: (pixel: number[], coord: number[]) => void;
102
- closeMenu: () => void;
103
- opened: boolean;
104
- };
105
- }
106
- export interface ClickMarkersEvent {
107
- pixel: number[];
108
- coord: number[];
109
- list: MarkerData[];
110
- }
111
- export type EventCallback = (event: unknown) => void;
112
- export type SwiperInstance = SwiperClass;
113
- export type SliderControl = Control & {
114
- get(prop: string): number;
115
- set(prop: string, value: number): void;
116
- element?: HTMLElement;
117
- setEnable(flag: boolean): void;
118
- };
119
- export interface RGB {
120
- red: number;
121
- green: number;
122
- blue: number;
123
- }
124
- export interface ControlOptions {
125
- target?: HTMLElement | string;
126
- render?: (event: import('ol').MapEvent) => void;
127
- className?: string;
128
- tipLabel?: string;
129
- initialValue?: number;
130
- character?: string;
131
- callback?: (this: Control) => void;
132
- long_callback?: (this: Control) => void;
133
- cls?: string;
134
- ui?: MaplatUi;
135
- zoomInLabel?: string | HTMLElement;
136
- zoomOutLabel?: string | HTMLElement;
137
- autoHide?: boolean;
138
- label?: string | HTMLElement;
139
- reverse?: boolean;
140
- }
141
- export interface ContextMenuItem {
142
- text?: string;
143
- classname?: string;
144
- icon?: string;
145
- callback?: (obj: {
146
- coordinate: number[];
147
- data: unknown;
148
- }, map: unknown) => void;
149
- data?: unknown;
150
- items?: ContextMenuItem[];
151
- separator?: boolean;
152
- }
153
- export interface ContextMenuOptions {
154
- width?: number;
155
- defaultItems?: boolean;
156
- items?: ContextMenuItem[];
157
- eventType?: string;
158
- }
159
- export interface ContextMenuInternalItem {
160
- id: string;
161
- submenu: number;
162
- separator: boolean;
163
- callback?: (obj: {
164
- coordinate: number[];
165
- data: unknown;
166
- }, map: unknown) => void;
167
- data?: unknown;
168
- }
169
- export interface ContextMenuEvent {
170
- type: string;
171
- pixel?: number[];
172
- coordinate?: number[];
173
- }
1
+ import { Swiper as SwiperClass } from 'swiper';
2
+ import { Control } from 'ol/control';
3
+ import { MaplatUi } from './index';
4
+ export interface MaplatAppOption {
5
+ appid?: string;
6
+ fake?: boolean;
7
+ pwaManifest?: boolean | string;
8
+ pwaWorker?: string;
9
+ pwaScope?: string;
10
+ overlay?: boolean;
11
+ enableHideMarker?: boolean;
12
+ enableMarkerList?: boolean;
13
+ enableBorder?: boolean;
14
+ enableCache?: boolean;
15
+ stateUrl?: boolean;
16
+ enableShare?: boolean;
17
+ enablePoiHtmlNoScroll?: boolean;
18
+ disableNoimage?: boolean;
19
+ alwaysGpsOn?: boolean;
20
+ mobileIF?: boolean;
21
+ debug?: boolean;
22
+ appEnvelope?: boolean;
23
+ mapboxToken?: string;
24
+ googleApiKey?: string;
25
+ lang?: string;
26
+ restore?: RestoreState;
27
+ restoreSession?: boolean;
28
+ presentationMode?: boolean;
29
+ northTop?: boolean;
30
+ mapboxgl?: unknown;
31
+ maplibregl?: unknown;
32
+ markerList?: boolean;
33
+ icon?: string;
34
+ translateUI?: boolean;
35
+ }
36
+ export interface RestoreState {
37
+ mapID?: string;
38
+ backgroundID?: string;
39
+ transparency?: number;
40
+ position?: {
41
+ rotation?: number;
42
+ zoom?: number;
43
+ x?: number;
44
+ y?: number;
45
+ };
46
+ showBorder?: boolean;
47
+ hideMarker?: boolean;
48
+ hideLayer?: string;
49
+ openedMarker?: string;
50
+ }
51
+ export interface MapSource {
52
+ mapID: string;
53
+ title?: string;
54
+ officialTitle?: string;
55
+ label?: string;
56
+ width?: number;
57
+ height?: number;
58
+ envelope?: {
59
+ geometry: {
60
+ coordinates: number[][][];
61
+ };
62
+ };
63
+ envelopeColor?: string;
64
+ envelopeAreaIndex?: number;
65
+ xy2SysCoord?: (xy: number[]) => Promise<number[]> | number[];
66
+ thumbnail?: string;
67
+ }
68
+ export type MediaObject = {
69
+ src: string;
70
+ thumbnail?: string;
71
+ type?: string;
72
+ caption?: string;
73
+ desc?: string;
74
+ "fit-to-container"?: boolean;
75
+ "debug-mode"?: boolean;
76
+ "camera-position"?: string;
77
+ "camera-target"?: string;
78
+ "show-texture"?: boolean;
79
+ [key: string]: unknown;
80
+ };
81
+ export type MediaSetting = string | MediaObject;
82
+ export interface MarkerData {
83
+ markerId: string;
84
+ lnglat?: number[];
85
+ title?: string;
86
+ icon?: string;
87
+ description?: string;
88
+ images?: string[];
89
+ image?: MediaSetting | MediaSetting[];
90
+ media?: MediaSetting | MediaSetting[];
91
+ address?: string;
92
+ desc?: string;
93
+ url?: string;
94
+ html?: string;
95
+ directgo?: string | {
96
+ href: string;
97
+ blank?: boolean;
98
+ };
99
+ namespaceID?: string;
100
+ name?: string;
101
+ }
102
+ export interface ClickMarkersEvent {
103
+ pixel: number[];
104
+ coord: number[];
105
+ list: MarkerData[];
106
+ }
107
+ export interface ContextMenuInterface {
108
+ clear: () => void;
109
+ extend: (items: unknown[]) => void;
110
+ on: (event: string, handler: (e: unknown) => void) => void;
111
+ un: (event: string, handler: (e: unknown) => void) => void;
112
+ Internal?: {
113
+ openMenu: (pixel: number[], coord: number[]) => void;
114
+ closeMenu: () => void;
115
+ opened: boolean;
116
+ };
117
+ }
118
+ export interface ClickMarkersEvent {
119
+ pixel: number[];
120
+ coord: number[];
121
+ list: MarkerData[];
122
+ }
123
+ export type EventCallback = (event: unknown) => void;
124
+ export type SwiperInstance = SwiperClass;
125
+ export type SliderControl = Control & {
126
+ get(prop: string): number;
127
+ set(prop: string, value: number): void;
128
+ element?: HTMLElement;
129
+ setEnable(flag: boolean): void;
130
+ };
131
+ export interface RGB {
132
+ red: number;
133
+ green: number;
134
+ blue: number;
135
+ }
136
+ export interface ControlOptions {
137
+ target?: HTMLElement | string;
138
+ render?: (event: import('ol').MapEvent) => void;
139
+ className?: string;
140
+ tipLabel?: string;
141
+ initialValue?: number;
142
+ character?: string;
143
+ callback?: (this: Control) => void;
144
+ long_callback?: (this: Control) => void;
145
+ cls?: string;
146
+ ui?: MaplatUi;
147
+ zoomInLabel?: string | HTMLElement;
148
+ zoomOutLabel?: string | HTMLElement;
149
+ autoHide?: boolean;
150
+ label?: string | HTMLElement;
151
+ reverse?: boolean;
152
+ }
153
+ export interface ContextMenuItem {
154
+ text?: string;
155
+ classname?: string;
156
+ icon?: string;
157
+ callback?: (obj: {
158
+ coordinate: number[];
159
+ data: unknown;
160
+ }, map: unknown) => void;
161
+ data?: unknown;
162
+ items?: ContextMenuItem[];
163
+ separator?: boolean;
164
+ }
165
+ export interface ContextMenuOptions {
166
+ width?: number;
167
+ defaultItems?: boolean;
168
+ items?: ContextMenuItem[];
169
+ eventType?: string;
170
+ }
171
+ export interface ContextMenuInternalItem {
172
+ id: string;
173
+ submenu: number;
174
+ separator: boolean;
175
+ callback?: (obj: {
176
+ coordinate: number[];
177
+ data: unknown;
178
+ }, map: unknown) => void;
179
+ data?: unknown;
180
+ }
181
+ export interface ContextMenuEvent {
182
+ type: string;
183
+ pixel?: number[];
184
+ coordinate?: number[];
185
+ }
package/dist/ui_init.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { MaplatUi } from './index';
2
- import { MaplatAppOption } from './types';
3
- export declare const META_KEYS: string[];
4
- export declare function uiInit(ui: MaplatUi, appOption: MaplatAppOption): Promise<void>;
1
+ import { MaplatUi } from './index';
2
+ import { MaplatAppOption } from './types';
3
+ export declare const META_KEYS: string[];
4
+ export declare function uiInit(ui: MaplatUi, appOption: MaplatAppOption): Promise<void>;
@@ -1,9 +1,9 @@
1
- import { MaplatUi } from './index';
2
- import { MarkerData } from './types';
3
- export declare function poiWebControl(ui: MaplatUi, div: HTMLElement, data: MarkerData): (((_event?: Event) => void) | undefined)[] | undefined;
4
- export declare function handleMarkerAction(ui: MaplatUi, data: MarkerData): void;
5
- export declare function showContextMenu(ui: MaplatUi, list: MarkerData[]): void;
6
- export declare function xyToMapIDs(ui: MaplatUi, xy: any, threshold?: number): Promise<any>;
7
- export declare function setHideMarker(ui: MaplatUi, flag: boolean): void;
8
- export declare function checkOverlayID(ui: MaplatUi, mapID: string): boolean;
9
- export declare function handleMarkerActionById(_ui: MaplatUi, markerId: string): void;
1
+ import { MaplatUi } from './index';
2
+ import { MarkerData } from './types';
3
+ export declare function poiWebControl(ui: MaplatUi, div: HTMLElement, data: MarkerData): undefined;
4
+ export declare function handleMarkerAction(ui: MaplatUi, data: MarkerData): void;
5
+ export declare function showContextMenu(ui: MaplatUi, list: MarkerData[]): void;
6
+ export declare function xyToMapIDs(ui: MaplatUi, xy: any, threshold?: number): Promise<any>;
7
+ export declare function setHideMarker(ui: MaplatUi, flag: boolean): void;
8
+ export declare function checkOverlayID(ui: MaplatUi, mapID: string): boolean;
9
+ export declare function handleMarkerActionById(_ui: MaplatUi, markerId: string): void;
@@ -1,9 +1,9 @@
1
- export declare function resolveRelativeLink(file: string, fallbackPath: string | null): string;
2
- export declare function ellips(mapDivDocument: HTMLElement): void;
3
- export declare function isMaplatSource(source: unknown): source is {
4
- setGPSMarkerAsync: () => unknown;
5
- constructor: {
6
- isBasemap_?: boolean;
7
- };
8
- };
9
- export declare function isBasemap(source: unknown): boolean;
1
+ export declare function resolveRelativeLink(file: string, fallbackPath: string | null): string;
2
+ export declare function ellips(mapDivDocument: HTMLElement): void;
3
+ export declare function isMaplatSource(source: unknown): source is {
4
+ setGPSMarkerAsync: () => unknown;
5
+ constructor: {
6
+ isBasemap_?: boolean;
7
+ };
8
+ };
9
+ export declare function isBasemap(source: unknown): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maplat/ui",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Maplat is the cool Historical Map/Illustrated Map Viewer.\nIt can transform each map coordinates with nonlinear but homeomorphic projection and makes possible that the maps can collaborate with GPS/accurate maps, without distorting original maps.",
5
5
  "type": "module",
6
6
  "main": "dist/maplat-ui.umd.js",
@@ -36,7 +36,7 @@
36
36
  "dependencies": {
37
37
  "@c4h/chuci": "0.2.4",
38
38
  "@c4h/weiwudi": "^0.2.0",
39
- "@maplat/core": "0.12.0",
39
+ "@maplat/core": "0.12.1",
40
40
  "@maplat/transform": "^0.4.0",
41
41
  "@turf/turf": "^7.3.1",
42
42
  "@types/page": "^1.11.9",
package/src/index.ts CHANGED
@@ -74,6 +74,7 @@ export class MaplatUi extends EventTarget {
74
74
  html_id_seed: string;
75
75
  lastClickPixel: Pixel | undefined;
76
76
  lastClickCoordinate: Coordinate | undefined;
77
+ lastGPSError: string | undefined;
77
78
 
78
79
  constructor(appOption: MaplatAppOption) {
79
80
  super();
@@ -4,7 +4,6 @@ import { MapEvent } from "ol";
4
4
 
5
5
  import pointer from "./pointer_images";
6
6
  import { createElement, MaplatApp } from "@maplat/core";
7
- import * as bsn from "bootstrap.native";
8
7
  import { getIcon } from "./icons";
9
8
  import type { MaplatUi } from "./index";
10
9
  import type { ControlOptions } from "./types";
@@ -356,6 +355,10 @@ export class SetGPS extends CustomControl {
356
355
 
357
356
  if (core.alwaysGpsOn) {
358
357
  core.handleGPS(true);
358
+ if (self.ui.lastGPSError === "gps_out") {
359
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
360
+ self.ui.core!.dispatchEvent(new CustomEvent("outOfMap") as any);
361
+ }
359
362
  } else {
360
363
  core.handleGPS(!currentlyEnabled);
361
364
  }
@@ -366,66 +369,6 @@ export class SetGPS extends CustomControl {
366
369
  this.ui = options.ui!;
367
370
  this.moveTo_ = false;
368
371
 
369
- if (this.ui && this.ui.core) {
370
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
371
- this.ui.core.addEventListener("gps_error", (evt: any) => {
372
- console.log("GPS Error:", evt);
373
- const errorMap: Record<string, string> = {
374
- user_gps_deny: "app.user_gps_deny",
375
- gps_miss: "app.gps_miss",
376
- gps_timeout: "app.gps_timeout"
377
- };
378
-
379
- if (!this.ui.core) return;
380
- (this.ui.core.mapDivDocument!.querySelector(
381
- ".modal_title"
382
- ) as HTMLElement)!.innerText = this.ui.core.t("app.gps_error");
383
- (this.ui.core.mapDivDocument!.querySelector(
384
- ".modal_gpsD_content"
385
- ) as HTMLElement)!.innerText = this.ui.core.t(
386
- errorMap[evt.detail] || "app.gps_error"
387
- );
388
- const modalElm =
389
- this.ui.core.mapDivDocument!.querySelector(".modalBase")!;
390
- const modal = new bsn.Modal(modalElm, {
391
- root: this.ui.core.mapDivDocument
392
- });
393
- this.ui.modalSetting("gpsD");
394
- modal.show();
395
- });
396
-
397
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
398
- this.ui.core.addEventListener("gps_result", (evt: any) => {
399
- console.log("GPS Result:", evt);
400
- if (evt.detail && evt.detail.error) {
401
- const errorMap: Record<string, string> = {
402
- user_gps_deny: "app.user_gps_deny",
403
- gps_miss: "app.gps_miss",
404
- gps_timeout: "app.gps_timeout",
405
- gps_off: "app.out_of_map"
406
- };
407
-
408
- if (!this.ui.core) return;
409
-
410
- (this.ui.core.mapDivDocument!.querySelector(
411
- ".modal_title"
412
- ) as HTMLElement)!.innerText = this.ui.core.t("app.gps_error");
413
- (this.ui.core.mapDivDocument!.querySelector(
414
- ".modal_gpsD_content"
415
- ) as HTMLElement)!.innerText = this.ui.core.t(
416
- errorMap[evt.detail.error] || "app.gps_error"
417
- );
418
- const modalElm =
419
- this.ui.core.mapDivDocument!.querySelector(".modalBase")!;
420
- const modal = new bsn.Modal(modalElm, {
421
- root: this.ui.core.mapDivDocument
422
- });
423
- this.ui.modalSetting("gpsD");
424
- modal.show();
425
- }
426
- });
427
- }
428
-
429
372
  if (control_settings["gps"]) {
430
373
  const button = this.element.querySelector("button");
431
374
  if (button) button.style.backgroundColor = "rgba(0,0,0,0)";