@open-pioneer/printing 1.4.0-dev.20260625074633 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,16 @@
1
1
  # @open-pioneer/printing
2
2
 
3
- ## 1.4.0-dev.20260625074633
3
+ ## 1.4.0
4
4
 
5
5
  ### Minor Changes
6
6
 
7
- - c30396d: Update Chakra to 3.36.0
7
+ - c30396d: Update Chakra to 3.36.1
8
+ - d862003: Update to trails core-packages 4.7.0
9
+
10
+ ### Patch Changes
11
+
12
+ - 078bef5: Use private JavaScript properties (#) instead of TypeScript keyword.
13
+ - c16a401: Migrated from eslint to oxlint and from prettier to oxfmt.
8
14
 
9
15
  ## 1.3.0
10
16
 
package/Printing.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Printing.js","sources":["Printing.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box, Button, Field, HStack, Input } from \"@chakra-ui/react\";\nimport { NativeSelectField, NativeSelectRoot } from \"@open-pioneer/chakra-snippets/native-select\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { MapModel, MapModelProps, useMapModelValue } from \"@open-pioneer/map\";\nimport { NotificationService } from \"@open-pioneer/notifier\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { useIntl, useService } from \"open-pioneer:react-hooks\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { FC, FormEvent, useEffect, useState } from \"react\";\nimport { FileFormatType, PrintingController } from \"./PrintingController\";\nimport type { PrintingService, ViewPaddingBehavior } from \"./index\";\n\nconst LOG = createLogger(sourceId);\n\n/**\n * This is special property for the Printing.\n */\nexport interface PrintingProps extends CommonComponentProps, MapModelProps {\n /**\n * Whether to respect the map view's padding when printing (default: `\"auto\"`).\n *\n * See also {@link ViewPaddingBehavior}.\n */\n viewPadding?: ViewPaddingBehavior;\n}\n\n/**\n * The `Printing` component can be used to download the current map view as a printable file.\n */\nexport const Printing: FC<PrintingProps> = (props) => {\n const intl = useIntl();\n\n const { viewPadding = \"auto\" } = props;\n const { containerProps } = useCommonComponentProps(\"printing\", props);\n const [selectedFileFormat, setSelectedFileFormat] = useState<FileFormatType>(\"pdf\");\n const [title, setTitle] = useState<string>(\"\");\n const [running, setRunning] = useState<boolean>(false);\n\n const notifier = useService<NotificationService>(\"notifier.NotificationService\");\n\n const map = useMapModelValue(props);\n const controller = useController(map, intl, viewPadding);\n\n function changeFileFormat(fileFormat: string) {\n if (fileFormat === \"png\" || fileFormat === \"pdf\") {\n setSelectedFileFormat(fileFormat);\n }\n }\n\n function exportMap() {\n if (running || !controller) {\n return;\n }\n\n setRunning(true);\n controller\n .handleMapExport({\n title,\n fileFormat: selectedFileFormat\n })\n .catch((error) => {\n const errorMessage = intl.formatMessage({ id: \"printingFailed\" });\n notifier.notify({\n level: \"error\",\n message: errorMessage\n });\n LOG.error(\"Failed to print the map\", error);\n })\n .finally(() => {\n setRunning(false);\n });\n }\n\n return (\n <Box {...containerProps}>\n <Box\n as=\"form\"\n aria-label={intl.formatMessage({ id: \"formLabel\" })}\n m={2}\n alignItems=\"center\"\n onSubmit={(e: FormEvent) => {\n e.preventDefault();\n exportMap();\n }}\n >\n <Field.Root asChild>\n <HStack mb={2}>\n <Field.Label minWidth={82} mb={1}>\n {intl.formatMessage({ id: \"title\" })}\n </Field.Label>\n <Input\n placeholder={intl.formatMessage({ id: \"input.placeholder\" })}\n value={title}\n onChange={(event) => {\n setTitle(event.target.value);\n }}\n />\n </HStack>\n </Field.Root>\n <Field.Root asChild>\n <HStack mb={2}>\n <Field.Label minWidth={82} mb={1}>\n {intl.formatMessage({ id: \"fileFormat\" })}\n </Field.Label>\n <NativeSelectRoot>\n <NativeSelectField\n className=\"printing-select\"\n value={selectedFileFormat}\n onChange={(event) => {\n changeFileFormat(event.target.value);\n }}\n >\n <option value={\"png\"}>PNG</option>\n <option value={\"pdf\"}>PDF</option>\n </NativeSelectField>\n </NativeSelectRoot>\n </HStack>\n </Field.Root>\n <Button\n loading={running}\n loadingText={intl.formatMessage({ id: \"printingMap\" })}\n disabled={running}\n mt={2}\n p={2}\n className=\"printing-export-button\"\n type=\"submit\"\n width=\"100%\"\n >\n {intl.formatMessage({ id: \"export\" })}\n </Button>\n </Box>\n </Box>\n );\n};\n\n/**\n * Create a PrintingController instance to export the map view.\n */\nfunction useController(map: MapModel, intl: PackageIntl, viewPadding: ViewPaddingBehavior) {\n const printingService = useService<PrintingService>(\"printing.PrintingService\");\n const [controller, setController] = useState<PrintingController | undefined>(undefined);\n\n useEffect(() => {\n const controller = new PrintingController(map.olMap, printingService, {\n overlayText: intl.formatMessage({ id: \"printingMap\" })\n });\n setController(controller);\n\n return () => {\n controller.destroy();\n setController(undefined);\n };\n }, [map, intl, printingService]);\n\n useEffect(() => {\n controller?.setViewPadding(viewPadding);\n }, [controller, viewPadding]);\n\n return controller;\n}\n"],"names":["controller"],"mappings":"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"}
1
+ {"version":3,"file":"Printing.js","sources":["Printing.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Box, Button, Field, HStack, Input } from \"@chakra-ui/react\";\nimport { NativeSelectField, NativeSelectRoot } from \"@open-pioneer/chakra-snippets/native-select\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { MapModel, MapModelProps, useMapModelValue } from \"@open-pioneer/map\";\nimport { NotificationService } from \"@open-pioneer/notifier\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { useIntl, useService } from \"open-pioneer:react-hooks\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { FC, FormEvent, useEffect, useState } from \"react\";\nimport type { PrintingService, ViewPaddingBehavior } from \"./index\";\nimport { FileFormatType, PrintingController } from \"./PrintingController\";\n\nconst LOG = createLogger(sourceId);\n\n/**\n * This is special property for the Printing.\n */\nexport interface PrintingProps extends CommonComponentProps, MapModelProps {\n /**\n * Whether to respect the map view's padding when printing (default: `\"auto\"`).\n *\n * See also {@link ViewPaddingBehavior}.\n */\n viewPadding?: ViewPaddingBehavior;\n}\n\n/**\n * The `Printing` component can be used to download the current map view as a printable file.\n */\nexport const Printing: FC<PrintingProps> = (props) => {\n const intl = useIntl();\n\n const { viewPadding = \"auto\" } = props;\n const { containerProps } = useCommonComponentProps(\"printing\", props);\n const [selectedFileFormat, setSelectedFileFormat] = useState<FileFormatType>(\"pdf\");\n const [title, setTitle] = useState<string>(\"\");\n const [running, setRunning] = useState<boolean>(false);\n\n const notifier = useService<NotificationService>(\"notifier.NotificationService\");\n\n const map = useMapModelValue(props);\n const controller = useController(map, intl, viewPadding);\n\n function changeFileFormat(fileFormat: string) {\n if (fileFormat === \"png\" || fileFormat === \"pdf\") {\n setSelectedFileFormat(fileFormat);\n }\n }\n\n function exportMap() {\n if (running || !controller) {\n return;\n }\n\n setRunning(true);\n controller\n .handleMapExport({\n title,\n fileFormat: selectedFileFormat\n })\n .catch((error) => {\n const errorMessage = intl.formatMessage({ id: \"printingFailed\" });\n notifier.notify({\n level: \"error\",\n message: errorMessage\n });\n LOG.error(\"Failed to print the map\", error);\n })\n .finally(() => {\n setRunning(false);\n });\n }\n\n return (\n <Box {...containerProps}>\n <Box\n as=\"form\"\n aria-label={intl.formatMessage({ id: \"formLabel\" })}\n m={2}\n alignItems=\"center\"\n onSubmit={(e: FormEvent) => {\n e.preventDefault();\n exportMap();\n }}\n >\n <Field.Root asChild>\n <HStack mb={2}>\n <Field.Label minWidth={82} mb={1}>\n {intl.formatMessage({ id: \"title\" })}\n </Field.Label>\n <Input\n placeholder={intl.formatMessage({ id: \"input.placeholder\" })}\n value={title}\n onChange={(event) => {\n setTitle(event.target.value);\n }}\n />\n </HStack>\n </Field.Root>\n <Field.Root asChild>\n <HStack mb={2}>\n <Field.Label minWidth={82} mb={1}>\n {intl.formatMessage({ id: \"fileFormat\" })}\n </Field.Label>\n <NativeSelectRoot>\n <NativeSelectField\n className=\"printing-select\"\n value={selectedFileFormat}\n onChange={(event) => {\n changeFileFormat(event.target.value);\n }}\n >\n <option value={\"png\"}>PNG</option>\n <option value={\"pdf\"}>PDF</option>\n </NativeSelectField>\n </NativeSelectRoot>\n </HStack>\n </Field.Root>\n <Button\n loading={running}\n loadingText={intl.formatMessage({ id: \"printingMap\" })}\n disabled={running}\n mt={2}\n p={2}\n className=\"printing-export-button\"\n type=\"submit\"\n width=\"100%\"\n >\n {intl.formatMessage({ id: \"export\" })}\n </Button>\n </Box>\n </Box>\n );\n};\n\n/**\n * Create a PrintingController instance to export the map view.\n */\nfunction useController(map: MapModel, intl: PackageIntl, viewPadding: ViewPaddingBehavior) {\n const printingService = useService<PrintingService>(\"printing.PrintingService\");\n const [controller, setController] = useState<PrintingController | undefined>(undefined);\n\n useEffect(() => {\n const controller = new PrintingController(map.olMap, printingService, {\n overlayText: intl.formatMessage({ id: \"printingMap\" })\n });\n setController(controller);\n\n return () => {\n controller.destroy();\n setController(undefined);\n };\n }, [map, intl, printingService]);\n\n useEffect(() => {\n controller?.setViewPadding(viewPadding);\n }, [controller, viewPadding]);\n\n return controller;\n}\n"],"names":["controller"],"mappings":";;;;;;;;;;;AAgBA,MAAM,GAAA,GAAM,aAAa,QAAQ,CAAA;AAiB1B,MAAM,QAAA,GAA8B,CAAC,KAAA,KAAU;AAClD,EAAA,MAAM,OAAO,OAAA,EAAQ;AAErB,EAAA,MAAM,EAAE,WAAA,GAAc,MAAA,EAAO,GAAI,KAAA;AACjC,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,uBAAA,CAAwB,YAAY,KAAK,CAAA;AACpE,EAAA,MAAM,CAAC,kBAAA,EAAoB,qBAAqB,CAAA,GAAI,SAAyB,KAAK,CAAA;AAClF,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAiB,EAAE,CAAA;AAC7C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAkB,KAAK,CAAA;AAErD,EAAA,MAAM,QAAA,GAAW,WAAgC,8BAA8B,CAAA;AAE/E,EAAA,MAAM,GAAA,GAAM,iBAAiB,KAAK,CAAA;AAClC,EAAA,MAAM,UAAA,GAAa,aAAA,CAAc,GAAA,EAAK,IAAA,EAAM,WAAW,CAAA;AAEvD,EAAA,SAAS,iBAAiB,UAAA,EAAoB;AAC1C,IAAA,IAAI,UAAA,KAAe,KAAA,IAAS,UAAA,KAAe,KAAA,EAAO;AAC9C,MAAA,qBAAA,CAAsB,UAAU,CAAA;AAAA,IACpC;AAAA,EACJ;AAEA,EAAA,SAAS,SAAA,GAAY;AACjB,IAAA,IAAI,OAAA,IAAW,CAAC,UAAA,EAAY;AACxB,MAAA;AAAA,IACJ;AAEA,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,UAAA,CACK,eAAA,CAAgB;AAAA,MACb,KAAA;AAAA,MACA,UAAA,EAAY;AAAA,KACf,CAAA,CACA,KAAA,CAAM,CAAC,KAAA,KAAU;AACd,MAAA,MAAM,eAAe,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,kBAAkB,CAAA;AAChE,MAAA,QAAA,CAAS,MAAA,CAAO;AAAA,QACZ,KAAA,EAAO,OAAA;AAAA,QACP,OAAA,EAAS;AAAA,OACZ,CAAA;AACD,MAAA,GAAA,CAAI,KAAA,CAAM,2BAA2B,KAAK,CAAA;AAAA,IAC9C,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACX,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IACpB,CAAC,CAAA;AAAA,EACT;AAEA,EAAA,uBACI,GAAA,CAAC,GAAA,EAAA,EAAK,GAAG,cAAA,EACL,QAAA,kBAAA,IAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACG,EAAA,EAAG,MAAA;AAAA,MACH,cAAY,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,aAAa,CAAA;AAAA,MAClD,CAAA,EAAG,CAAA;AAAA,MACH,UAAA,EAAW,QAAA;AAAA,MACX,QAAA,EAAU,CAAC,CAAA,KAAiB;AACxB,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,SAAA,EAAU;AAAA,MACd,CAAA;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,CAAM,MAAN,EAAW,OAAA,EAAO,MACf,QAAA,kBAAA,IAAA,CAAC,MAAA,EAAA,EAAO,IAAI,CAAA,EACR,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,CAAM,KAAA,EAAN,EAAY,QAAA,EAAU,EAAA,EAAI,EAAA,EAAI,CAAA,EAC1B,QAAA,EAAA,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,OAAA,EAAS,CAAA,EACvC,CAAA;AAAA,0BACA,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACG,aAAa,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,qBAAqB,CAAA;AAAA,cAC3D,KAAA,EAAO,KAAA;AAAA,cACP,QAAA,EAAU,CAAC,KAAA,KAAU;AACjB,gBAAA,QAAA,CAAS,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,cAC/B;AAAA;AAAA;AACJ,SAAA,EACJ,CAAA,EACJ,CAAA;AAAA,wBACA,GAAA,CAAC,MAAM,IAAA,EAAN,EAAW,SAAO,IAAA,EACf,QAAA,kBAAA,IAAA,CAAC,MAAA,EAAA,EAAO,EAAA,EAAI,CAAA,EACR,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,CAAM,KAAA,EAAN,EAAY,QAAA,EAAU,EAAA,EAAI,EAAA,EAAI,CAAA,EAC1B,QAAA,EAAA,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,YAAA,EAAc,CAAA,EAC5C,CAAA;AAAA,8BACC,gBAAA,EAAA,EACG,QAAA,kBAAA,IAAA;AAAA,YAAC,iBAAA;AAAA,YAAA;AAAA,cACG,SAAA,EAAU,iBAAA;AAAA,cACV,KAAA,EAAO,kBAAA;AAAA,cACP,QAAA,EAAU,CAAC,KAAA,KAAU;AACjB,gBAAA,gBAAA,CAAiB,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,cACvC,CAAA;AAAA,cAEA,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAO,KAAA,EAAO,QAAA,EAAA,KAAA,EAAG,CAAA;AAAA,gCACzB,GAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAO,KAAA,EAAO,QAAA,EAAA,KAAA,EAAG;AAAA;AAAA;AAAA,WAC7B,EACJ;AAAA,SAAA,EACJ,CAAA,EACJ,CAAA;AAAA,wBACA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACG,OAAA,EAAS,OAAA;AAAA,YACT,aAAa,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,eAAe,CAAA;AAAA,YACrD,QAAA,EAAU,OAAA;AAAA,YACV,EAAA,EAAI,CAAA;AAAA,YACJ,CAAA,EAAG,CAAA;AAAA,YACH,SAAA,EAAU,wBAAA;AAAA,YACV,IAAA,EAAK,QAAA;AAAA,YACL,KAAA,EAAM,MAAA;AAAA,YAEL,QAAA,EAAA,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,UAAU;AAAA;AAAA;AACxC;AAAA;AAAA,GACJ,EACJ,CAAA;AAER;AAKA,SAAS,aAAA,CAAc,GAAA,EAAe,IAAA,EAAmB,WAAA,EAAkC;AACvF,EAAA,MAAM,eAAA,GAAkB,WAA4B,0BAA0B,CAAA;AAC9E,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAyC,MAAS,CAAA;AAEtF,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,MAAMA,WAAAA,GAAa,IAAI,kBAAA,CAAmB,GAAA,CAAI,OAAO,eAAA,EAAiB;AAAA,MAClE,aAAa,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,eAAe;AAAA,KACxD,CAAA;AACD,IAAA,aAAA,CAAcA,WAAU,CAAA;AAExB,IAAA,OAAO,MAAM;AACT,MAAAA,YAAW,OAAA,EAAQ;AACnB,MAAA,aAAA,CAAc,MAAS,CAAA;AAAA,IAC3B,CAAA;AAAA,EACJ,CAAA,EAAG,CAAC,GAAA,EAAK,IAAA,EAAM,eAAe,CAAC,CAAA;AAE/B,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,UAAA,EAAY,eAAe,WAAW,CAAA;AAAA,EAC1C,CAAA,EAAG,CAAC,UAAA,EAAY,WAAW,CAAC,CAAA;AAE5B,EAAA,OAAO,UAAA;AACX;;;;"}
@@ -6,19 +6,11 @@ export interface ExportOptions {
6
6
  fileFormat: FileFormatType;
7
7
  }
8
8
  export declare class PrintingController {
9
- private olMap;
10
- private i18n;
11
- private printingService;
12
- private viewPadding;
13
- private printMap;
14
- private overlay;
9
+ #private;
15
10
  constructor(olMap: OlMap, printingService: PrintingService, i18n: I18n);
16
11
  destroy(): void;
17
12
  setViewPadding(padding: ViewPaddingBehavior): void;
18
13
  handleMapExport(options: ExportOptions): Promise<void>;
19
- private begin;
20
- private reset;
21
- private getTitleAndFileName;
22
14
  private exportMapInPNG;
23
15
  private exportMapInPDF;
24
16
  }
@@ -2,34 +2,34 @@ import { createBlockUserOverlay, canvasToPng } from './utils.js';
2
2
 
3
3
  const DEFAULT_FILE_NAME = "map";
4
4
  class PrintingController {
5
- olMap;
6
- i18n;
7
- printingService;
8
- viewPadding;
9
- printMap = void 0;
10
- overlay = void 0;
5
+ #olMap;
6
+ #i18n;
7
+ #printingService;
8
+ #viewPadding;
9
+ #printMap = void 0;
10
+ #overlay = void 0;
11
11
  constructor(olMap, printingService, i18n) {
12
- this.olMap = olMap;
13
- this.printingService = printingService;
14
- this.i18n = i18n;
12
+ this.#olMap = olMap;
13
+ this.#printingService = printingService;
14
+ this.#i18n = i18n;
15
15
  }
16
16
  destroy() {
17
- this.reset();
17
+ this.#reset();
18
18
  }
19
19
  setViewPadding(padding) {
20
- this.viewPadding = padding;
20
+ this.#viewPadding = padding;
21
21
  }
22
22
  async handleMapExport(options) {
23
- if (!this.olMap) {
23
+ if (!this.#olMap) {
24
24
  return;
25
25
  }
26
26
  try {
27
- this.begin();
28
- this.printMap = await this.printingService.printMap(this.olMap, {
27
+ this.#begin();
28
+ this.#printMap = await this.#printingService.printMap(this.#olMap, {
29
29
  blockUserInteraction: false,
30
- viewPadding: this.viewPadding
30
+ viewPadding: this.#viewPadding
31
31
  });
32
- const canvas = this.printMap.getCanvas();
32
+ const canvas = this.#printMap.getCanvas();
33
33
  if (canvas) {
34
34
  if (options.fileFormat == "png") {
35
35
  await this.exportMapInPNG(canvas, options);
@@ -40,24 +40,26 @@ class PrintingController {
40
40
  throw new Error("Canvas export failed");
41
41
  }
42
42
  } finally {
43
- this.reset();
43
+ this.#reset();
44
44
  }
45
45
  }
46
- begin() {
47
- const container = this.olMap.getTargetElement();
46
+ #begin() {
47
+ const container = this.#olMap.getTargetElement();
48
48
  if (container) {
49
- this.overlay = createBlockUserOverlay(container, this.i18n.overlayText);
49
+ this.#overlay = createBlockUserOverlay(container, this.#i18n.overlayText);
50
50
  }
51
51
  }
52
- reset() {
53
- this.overlay?.destroy();
54
- this.overlay = void 0;
52
+ #reset() {
53
+ this.#overlay?.destroy();
54
+ this.#overlay = void 0;
55
55
  }
56
- getTitleAndFileName(options) {
56
+ #getTitleAndFileName(options) {
57
57
  const titleValue = options.title || "";
58
58
  const fileName = options.title || DEFAULT_FILE_NAME;
59
59
  return { title: titleValue, fileName };
60
60
  }
61
+ // Kept as a TypeScript `private` method (not a `#` private) so tests can replace it via
62
+ // `vi.spyOn(controller, ...)` to isolate export-format dispatch from actual file export.
61
63
  async exportMapInPNG(mapCanvas, options) {
62
64
  const containerCanvas = document.createElement("canvas");
63
65
  containerCanvas.width = mapCanvas.width;
@@ -67,7 +69,7 @@ class PrintingController {
67
69
  if (!context) {
68
70
  throw new Error("2d canvas rendering context not available");
69
71
  }
70
- const { title, fileName } = this.getTitleAndFileName(options);
72
+ const { title, fileName } = this.#getTitleAndFileName(options);
71
73
  context.fillStyle = "#fff";
72
74
  context.fillRect(0, 0, containerCanvas.width, containerCanvas.height);
73
75
  context.font = "20px bold sans-serif";
@@ -85,6 +87,8 @@ class PrintingController {
85
87
  link.href = dataURL;
86
88
  link.click();
87
89
  }
90
+ // Kept as a TypeScript `private` method (not a `#` private) so tests can replace it via
91
+ // `vi.spyOn(controller, ...)` to isolate export-format dispatch from actual file export.
88
92
  async exportMapInPDF(canvas, options) {
89
93
  const { jsPDF } = await import('jspdf');
90
94
  const pdf = new jsPDF({
@@ -98,7 +102,7 @@ class PrintingController {
98
102
  const mapOffset = 20;
99
103
  const mapPageHeight = pageHeight - mapOffset;
100
104
  pdf.setFontSize(20);
101
- const { title, fileName } = this.getTitleAndFileName(options);
105
+ const { title, fileName } = this.#getTitleAndFileName(options);
102
106
  pdf.text(title, pageWidth / 2, titleOffset, { align: "center" });
103
107
  const imageAspectRatio = canvas.width / canvas.height;
104
108
  let targetImageHeight = mapPageHeight;
@@ -1 +1 @@
1
- {"version":3,"file":"PrintingController.js","sources":["PrintingController.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport OlMap from \"ol/Map\";\nimport { PrintingService, PrintResult, ViewPaddingBehavior } from \"./index\";\nimport { canvasToPng, createBlockUserOverlay } from \"./utils\";\nimport { Resource } from \"@open-pioneer/core\";\n\nexport type FileFormatType = \"png\" | \"pdf\";\n\nconst DEFAULT_FILE_NAME = \"map\";\n\nexport interface ExportOptions {\n title?: string | undefined;\n fileFormat: FileFormatType;\n}\n\nexport class PrintingController {\n private olMap: OlMap;\n private i18n: I18n;\n\n private printingService: PrintingService;\n private viewPadding: ViewPaddingBehavior | undefined;\n\n private printMap: PrintResult | undefined = undefined;\n private overlay: Resource | undefined = undefined;\n\n constructor(olMap: OlMap, printingService: PrintingService, i18n: I18n) {\n this.olMap = olMap;\n this.printingService = printingService;\n this.i18n = i18n;\n }\n\n destroy() {\n this.reset();\n }\n\n setViewPadding(padding: ViewPaddingBehavior) {\n this.viewPadding = padding;\n }\n\n async handleMapExport(options: ExportOptions) {\n if (!this.olMap) {\n return;\n }\n\n try {\n this.begin();\n this.printMap = await this.printingService.printMap(this.olMap, {\n blockUserInteraction: false,\n viewPadding: this.viewPadding\n });\n const canvas = this.printMap.getCanvas();\n if (canvas) {\n if (options.fileFormat == \"png\") {\n await this.exportMapInPNG(canvas, options);\n } else {\n await this.exportMapInPDF(canvas, options);\n }\n } else {\n throw new Error(\"Canvas export failed\");\n }\n } finally {\n this.reset();\n }\n }\n\n private begin() {\n const container = this.olMap.getTargetElement();\n if (container) {\n this.overlay = createBlockUserOverlay(container, this.i18n.overlayText);\n }\n }\n\n private reset() {\n this.overlay?.destroy();\n this.overlay = undefined;\n }\n\n private getTitleAndFileName(options: ExportOptions) {\n const titleValue = options.title || \"\";\n const fileName = options.title || DEFAULT_FILE_NAME;\n return { title: titleValue, fileName: fileName };\n }\n\n private async exportMapInPNG(mapCanvas: HTMLCanvasElement, options: ExportOptions) {\n const containerCanvas = document.createElement(\"canvas\");\n containerCanvas.width = mapCanvas.width;\n containerCanvas.height = mapCanvas.height + 50;\n containerCanvas.style.backgroundColor = \"#fff\";\n\n const context = containerCanvas.getContext(\"2d\");\n if (!context) {\n throw new Error(\"2d canvas rendering context not available\");\n }\n\n const { title, fileName } = this.getTitleAndFileName(options);\n\n context.fillStyle = \"#fff\"; // background color for background rect\n context.fillRect(0, 0, containerCanvas.width, containerCanvas.height); //draw background rect\n context.font = 20 + \"px bold sans-serif\";\n context.textAlign = \"center\";\n context.fillStyle = \"#000\"; // text color\n\n const x = containerCanvas.width / 2; //align text to center\n context.fillText(title, x, 20);\n context.drawImage(mapCanvas, 0, 50);\n\n const link = document.createElement(\"a\");\n link.setAttribute(\"download\", fileName + \".png\");\n\n const dataURL = canvasToPng(containerCanvas);\n if (!dataURL) {\n throw new Error(\"Failed to get image data URL\");\n }\n\n link.href = dataURL;\n link.click();\n }\n\n private async exportMapInPDF(canvas: HTMLCanvasElement, options: ExportOptions) {\n // Landscape map export.\n // Lazy load pdfjs as well.\n const { jsPDF } = await import(\"jspdf\");\n const pdf = new jsPDF({\n orientation: \"landscape\",\n unit: \"mm\",\n format: \"a4\"\n });\n\n // Simple layout: 50 pixels for the header and\n // the remaining space can be used by the map export.\n const pageWidth = pdf.internal.pageSize.getWidth();\n const pageHeight = pdf.internal.pageSize.getHeight();\n const titleOffset = 15;\n const mapOffset = 20;\n const mapPageHeight = pageHeight - mapOffset;\n\n // Render title\n pdf.setFontSize(20);\n const { title, fileName } = this.getTitleAndFileName(options);\n pdf.text(title, pageWidth / 2, titleOffset, { align: \"center\" });\n\n // Resize image while keeping aspect ratio\n const imageAspectRatio = canvas.width / canvas.height;\n let targetImageHeight = mapPageHeight;\n let targetImageWidth = targetImageHeight * imageAspectRatio;\n if (targetImageWidth >= pageWidth) {\n targetImageWidth = pageWidth;\n targetImageHeight = targetImageWidth / imageAspectRatio;\n }\n\n // Center image\n const imageX = (pageWidth - targetImageWidth) / 2;\n const imageY = mapOffset + (mapPageHeight - targetImageHeight) / 2;\n\n pdf.addImage(canvas, \"\", imageX, imageY, targetImageWidth, targetImageHeight);\n pdf.save(fileName + \".pdf\");\n }\n}\n\ninterface I18n {\n overlayText: string;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PrintingController.js","sources":["PrintingController.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Resource } from \"@open-pioneer/core\";\nimport OlMap from \"ol/Map\";\nimport { PrintingService, PrintResult, ViewPaddingBehavior } from \"./index\";\nimport { canvasToPng, createBlockUserOverlay } from \"./utils\";\n\nexport type FileFormatType = \"png\" | \"pdf\";\n\nconst DEFAULT_FILE_NAME = \"map\";\n\nexport interface ExportOptions {\n title?: string | undefined;\n fileFormat: FileFormatType;\n}\n\nexport class PrintingController {\n #olMap: OlMap;\n #i18n: I18n;\n\n #printingService: PrintingService;\n #viewPadding: ViewPaddingBehavior | undefined;\n\n #printMap: PrintResult | undefined = undefined;\n #overlay: Resource | undefined = undefined;\n\n constructor(olMap: OlMap, printingService: PrintingService, i18n: I18n) {\n this.#olMap = olMap;\n this.#printingService = printingService;\n this.#i18n = i18n;\n }\n\n destroy() {\n this.#reset();\n }\n\n setViewPadding(padding: ViewPaddingBehavior) {\n this.#viewPadding = padding;\n }\n\n async handleMapExport(options: ExportOptions) {\n if (!this.#olMap) {\n return;\n }\n\n try {\n this.#begin();\n this.#printMap = await this.#printingService.printMap(this.#olMap, {\n blockUserInteraction: false,\n viewPadding: this.#viewPadding\n });\n const canvas = this.#printMap.getCanvas();\n if (canvas) {\n if (options.fileFormat == \"png\") {\n await this.exportMapInPNG(canvas, options);\n } else {\n await this.exportMapInPDF(canvas, options);\n }\n } else {\n throw new Error(\"Canvas export failed\");\n }\n } finally {\n this.#reset();\n }\n }\n\n #begin() {\n const container = this.#olMap.getTargetElement();\n if (container) {\n this.#overlay = createBlockUserOverlay(container, this.#i18n.overlayText);\n }\n }\n\n #reset() {\n this.#overlay?.destroy();\n this.#overlay = undefined;\n }\n\n #getTitleAndFileName(options: ExportOptions) {\n const titleValue = options.title || \"\";\n const fileName = options.title || DEFAULT_FILE_NAME;\n return { title: titleValue, fileName: fileName };\n }\n\n // Kept as a TypeScript `private` method (not a `#` private) so tests can replace it via\n // `vi.spyOn(controller, ...)` to isolate export-format dispatch from actual file export.\n private async exportMapInPNG(mapCanvas: HTMLCanvasElement, options: ExportOptions) {\n const containerCanvas = document.createElement(\"canvas\");\n containerCanvas.width = mapCanvas.width;\n containerCanvas.height = mapCanvas.height + 50;\n containerCanvas.style.backgroundColor = \"#fff\";\n\n const context = containerCanvas.getContext(\"2d\");\n if (!context) {\n throw new Error(\"2d canvas rendering context not available\");\n }\n\n const { title, fileName } = this.#getTitleAndFileName(options);\n\n context.fillStyle = \"#fff\"; // background color for background rect\n context.fillRect(0, 0, containerCanvas.width, containerCanvas.height); //draw background rect\n context.font = 20 + \"px bold sans-serif\";\n context.textAlign = \"center\";\n context.fillStyle = \"#000\"; // text color\n\n const x = containerCanvas.width / 2; //align text to center\n context.fillText(title, x, 20);\n context.drawImage(mapCanvas, 0, 50);\n\n const link = document.createElement(\"a\");\n link.setAttribute(\"download\", fileName + \".png\");\n\n const dataURL = canvasToPng(containerCanvas);\n if (!dataURL) {\n throw new Error(\"Failed to get image data URL\");\n }\n\n link.href = dataURL;\n link.click();\n }\n\n // Kept as a TypeScript `private` method (not a `#` private) so tests can replace it via\n // `vi.spyOn(controller, ...)` to isolate export-format dispatch from actual file export.\n private async exportMapInPDF(canvas: HTMLCanvasElement, options: ExportOptions) {\n // Landscape map export.\n // Lazy load pdfjs as well.\n const { jsPDF } = await import(\"jspdf\");\n const pdf = new jsPDF({\n orientation: \"landscape\",\n unit: \"mm\",\n format: \"a4\"\n });\n\n // Simple layout: 50 pixels for the header and\n // the remaining space can be used by the map export.\n const pageWidth = pdf.internal.pageSize.getWidth();\n const pageHeight = pdf.internal.pageSize.getHeight();\n const titleOffset = 15;\n const mapOffset = 20;\n const mapPageHeight = pageHeight - mapOffset;\n\n // Render title\n pdf.setFontSize(20);\n const { title, fileName } = this.#getTitleAndFileName(options);\n pdf.text(title, pageWidth / 2, titleOffset, { align: \"center\" });\n\n // Resize image while keeping aspect ratio\n const imageAspectRatio = canvas.width / canvas.height;\n let targetImageHeight = mapPageHeight;\n let targetImageWidth = targetImageHeight * imageAspectRatio;\n if (targetImageWidth >= pageWidth) {\n targetImageWidth = pageWidth;\n targetImageHeight = targetImageWidth / imageAspectRatio;\n }\n\n // Center image\n const imageX = (pageWidth - targetImageWidth) / 2;\n const imageY = mapOffset + (mapPageHeight - targetImageHeight) / 2;\n\n pdf.addImage(canvas, \"\", imageX, imageY, targetImageWidth, targetImageHeight);\n pdf.save(fileName + \".pdf\");\n }\n}\n\ninterface I18n {\n overlayText: string;\n}\n"],"names":[],"mappings":";;AAUA,MAAM,iBAAA,GAAoB,KAAA;AAOnB,MAAM,kBAAA,CAAmB;AAAA,EAC5B,MAAA;AAAA,EACA,KAAA;AAAA,EAEA,gBAAA;AAAA,EACA,YAAA;AAAA,EAEA,SAAA,GAAqC,MAAA;AAAA,EACrC,QAAA,GAAiC,MAAA;AAAA,EAEjC,WAAA,CAAY,KAAA,EAAc,eAAA,EAAkC,IAAA,EAAY;AACpE,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,IAAA,CAAK,gBAAA,GAAmB,eAAA;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,EACjB;AAAA,EAEA,OAAA,GAAU;AACN,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EAChB;AAAA,EAEA,eAAe,OAAA,EAA8B;AACzC,IAAA,IAAA,CAAK,YAAA,GAAe,OAAA;AAAA,EACxB;AAAA,EAEA,MAAM,gBAAgB,OAAA,EAAwB;AAC1C,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AACd,MAAA;AAAA,IACJ;AAEA,IAAA,IAAI;AACA,MAAA,IAAA,CAAK,MAAA,EAAO;AACZ,MAAA,IAAA,CAAK,YAAY,MAAM,IAAA,CAAK,gBAAA,CAAiB,QAAA,CAAS,KAAK,MAAA,EAAQ;AAAA,QAC/D,oBAAA,EAAsB,KAAA;AAAA,QACtB,aAAa,IAAA,CAAK;AAAA,OACrB,CAAA;AACD,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,SAAA,CAAU,SAAA,EAAU;AACxC,MAAA,IAAI,MAAA,EAAQ;AACR,QAAA,IAAI,OAAA,CAAQ,cAAc,KAAA,EAAO;AAC7B,UAAA,MAAM,IAAA,CAAK,cAAA,CAAe,MAAA,EAAQ,OAAO,CAAA;AAAA,QAC7C,CAAA,MAAO;AACH,UAAA,MAAM,IAAA,CAAK,cAAA,CAAe,MAAA,EAAQ,OAAO,CAAA;AAAA,QAC7C;AAAA,MACJ,CAAA,MAAO;AACH,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MAC1C;AAAA,IACJ,CAAA,SAAE;AACE,MAAA,IAAA,CAAK,MAAA,EAAO;AAAA,IAChB;AAAA,EACJ;AAAA,EAEA,MAAA,GAAS;AACL,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,gBAAA,EAAiB;AAC/C,IAAA,IAAI,SAAA,EAAW;AACX,MAAA,IAAA,CAAK,QAAA,GAAW,sBAAA,CAAuB,SAAA,EAAW,IAAA,CAAK,MAAM,WAAW,CAAA;AAAA,IAC5E;AAAA,EACJ;AAAA,EAEA,MAAA,GAAS;AACL,IAAA,IAAA,CAAK,UAAU,OAAA,EAAQ;AACvB,IAAA,IAAA,CAAK,QAAA,GAAW,MAAA;AAAA,EACpB;AAAA,EAEA,qBAAqB,OAAA,EAAwB;AACzC,IAAA,MAAM,UAAA,GAAa,QAAQ,KAAA,IAAS,EAAA;AACpC,IAAA,MAAM,QAAA,GAAW,QAAQ,KAAA,IAAS,iBAAA;AAClC,IAAA,OAAO,EAAE,KAAA,EAAO,UAAA,EAAY,QAAA,EAAmB;AAAA,EACnD;AAAA;AAAA;AAAA,EAIA,MAAc,cAAA,CAAe,SAAA,EAA8B,OAAA,EAAwB;AAC/E,IAAA,MAAM,eAAA,GAAkB,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AACvD,IAAA,eAAA,CAAgB,QAAQ,SAAA,CAAU,KAAA;AAClC,IAAA,eAAA,CAAgB,MAAA,GAAS,UAAU,MAAA,GAAS,EAAA;AAC5C,IAAA,eAAA,CAAgB,MAAM,eAAA,GAAkB,MAAA;AAExC,IAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,UAAA,CAAW,IAAI,CAAA;AAC/C,IAAA,IAAI,CAAC,OAAA,EAAS;AACV,MAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,IAC/D;AAEA,IAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAI,IAAA,CAAK,qBAAqB,OAAO,CAAA;AAE7D,IAAA,OAAA,CAAQ,SAAA,GAAY,MAAA;AACpB,IAAA,OAAA,CAAQ,SAAS,CAAA,EAAG,CAAA,EAAG,eAAA,CAAgB,KAAA,EAAO,gBAAgB,MAAM,CAAA;AACpE,IAAA,OAAA,CAAQ,IAAA,GAAO,sBAAA;AACf,IAAA,OAAA,CAAQ,SAAA,GAAY,QAAA;AACpB,IAAA,OAAA,CAAQ,SAAA,GAAY,MAAA;AAEpB,IAAA,MAAM,CAAA,GAAI,gBAAgB,KAAA,GAAQ,CAAA;AAClC,IAAA,OAAA,CAAQ,QAAA,CAAS,KAAA,EAAO,CAAA,EAAG,EAAE,CAAA;AAC7B,IAAA,OAAA,CAAQ,SAAA,CAAU,SAAA,EAAW,CAAA,EAAG,EAAE,CAAA;AAElC,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,GAAG,CAAA;AACvC,IAAA,IAAA,CAAK,YAAA,CAAa,UAAA,EAAY,QAAA,GAAW,MAAM,CAAA;AAE/C,IAAA,MAAM,OAAA,GAAU,YAAY,eAAe,CAAA;AAC3C,IAAA,IAAI,CAAC,OAAA,EAAS;AACV,MAAA,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAAA,IAClD;AAEA,IAAA,IAAA,CAAK,IAAA,GAAO,OAAA;AACZ,IAAA,IAAA,CAAK,KAAA,EAAM;AAAA,EACf;AAAA;AAAA;AAAA,EAIA,MAAc,cAAA,CAAe,MAAA,EAA2B,OAAA,EAAwB;AAG5E,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,OAAO,OAAO,CAAA;AACtC,IAAA,MAAM,GAAA,GAAM,IAAI,KAAA,CAAM;AAAA,MAClB,WAAA,EAAa,WAAA;AAAA,MACb,IAAA,EAAM,IAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACX,CAAA;AAID,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,QAAA,CAAS,QAAA,CAAS,QAAA,EAAS;AACjD,IAAA,MAAM,UAAA,GAAa,GAAA,CAAI,QAAA,CAAS,QAAA,CAAS,SAAA,EAAU;AACnD,IAAA,MAAM,WAAA,GAAc,EAAA;AACpB,IAAA,MAAM,SAAA,GAAY,EAAA;AAClB,IAAA,MAAM,gBAAgB,UAAA,GAAa,SAAA;AAGnC,IAAA,GAAA,CAAI,YAAY,EAAE,CAAA;AAClB,IAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAI,IAAA,CAAK,qBAAqB,OAAO,CAAA;AAC7D,IAAA,GAAA,CAAI,IAAA,CAAK,OAAO,SAAA,GAAY,CAAA,EAAG,aAAa,EAAE,KAAA,EAAO,UAAU,CAAA;AAG/D,IAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,KAAA,GAAQ,MAAA,CAAO,MAAA;AAC/C,IAAA,IAAI,iBAAA,GAAoB,aAAA;AACxB,IAAA,IAAI,mBAAmB,iBAAA,GAAoB,gBAAA;AAC3C,IAAA,IAAI,oBAAoB,SAAA,EAAW;AAC/B,MAAA,gBAAA,GAAmB,SAAA;AACnB,MAAA,iBAAA,GAAoB,gBAAA,GAAmB,gBAAA;AAAA,IAC3C;AAGA,IAAA,MAAM,MAAA,GAAA,CAAU,YAAY,gBAAA,IAAoB,CAAA;AAChD,IAAA,MAAM,MAAA,GAAS,SAAA,GAAA,CAAa,aAAA,GAAgB,iBAAA,IAAqB,CAAA;AAEjE,IAAA,GAAA,CAAI,SAAS,MAAA,EAAQ,EAAA,EAAI,MAAA,EAAQ,MAAA,EAAQ,kBAAkB,iBAAiB,CAAA;AAC5E,IAAA,GAAA,CAAI,IAAA,CAAK,WAAW,MAAM,CAAA;AAAA,EAC9B;AACJ;;;;"}
@@ -7,25 +7,14 @@ export declare class PrintingServiceImpl implements PrintingService {
7
7
  printMap(olMap: OlMap, options?: PrintingOptions): Promise<PrintResultImpl>;
8
8
  }
9
9
  export declare class PrintJob {
10
- private olMap;
11
- private blockUserInteraction;
12
- private overlayText;
13
- private viewPadding;
14
- private running;
15
- private drawInformation;
16
- private scaleLine;
17
- private overlay;
10
+ #private;
18
11
  constructor(olMap: OlMap, options: Required<PrintingOptions>);
19
12
  printMap(): Promise<PrintResultImpl>;
20
- private beginExport;
21
- private addScaleLine;
22
13
  private printToCanvas;
23
- private reset;
24
14
  private removePadding;
25
- private getViewPadding;
26
15
  }
27
16
  declare class PrintResultImpl implements PrintResult {
28
- private canvas;
17
+ #private;
29
18
  constructor(canvas: HTMLCanvasElement);
30
19
  getCanvas(): HTMLCanvasElement;
31
20
  getPNGDataURL(quality?: number): string;
@@ -19,63 +19,63 @@ class PrintingServiceImpl {
19
19
  }
20
20
  }
21
21
  class PrintJob {
22
- olMap;
23
- blockUserInteraction = false;
24
- overlayText;
25
- viewPadding;
26
- running = false;
27
- drawInformation = [];
28
- scaleLine = void 0;
29
- overlay = void 0;
22
+ #olMap;
23
+ #blockUserInteraction = false;
24
+ #overlayText;
25
+ #viewPadding;
26
+ #running = false;
27
+ #drawInformation = [];
28
+ #scaleLine = void 0;
29
+ #overlay = void 0;
30
30
  constructor(olMap, options) {
31
- this.olMap = olMap;
32
- this.blockUserInteraction = options.blockUserInteraction;
33
- this.overlayText = options.overlayText;
34
- this.viewPadding = options.viewPadding;
31
+ this.#olMap = olMap;
32
+ this.#blockUserInteraction = options.blockUserInteraction;
33
+ this.#overlayText = options.overlayText;
34
+ this.#viewPadding = options.viewPadding;
35
35
  }
36
36
  async printMap() {
37
- if (this.running) {
37
+ if (this.#running) {
38
38
  throw new Error("Printing already running.");
39
39
  }
40
40
  try {
41
- await this.beginExport();
42
- let canvas = await this.printToCanvas(this.olMap.getViewport());
41
+ await this.#beginExport();
42
+ let canvas = await this.printToCanvas(this.#olMap.getViewport());
43
43
  if (!canvas) {
44
44
  throw new Error("Canvas export failed");
45
45
  }
46
- if (this.viewPadding === "auto") {
47
- canvas = this.removePadding(canvas, this.getViewPadding());
46
+ if (this.#viewPadding === "auto") {
47
+ canvas = this.removePadding(canvas, this.#getViewPadding());
48
48
  }
49
49
  return new PrintResultImpl(canvas);
50
50
  } finally {
51
- this.reset();
51
+ this.#reset();
52
52
  }
53
53
  }
54
- async beginExport() {
55
- this.running = true;
56
- const interactions = this.olMap.getInteractions().getArray().filter((interaction) => {
54
+ async #beginExport() {
55
+ this.#running = true;
56
+ const interactions = this.#olMap.getInteractions().getArray().filter((interaction) => {
57
57
  return interaction.getActive() && interaction instanceof Draw;
58
58
  });
59
- this.drawInformation = [];
59
+ this.#drawInformation = [];
60
60
  interactions?.forEach((interaction) => {
61
61
  const draw = interaction;
62
62
  const previousStyle = draw.getOverlay().getStyle();
63
63
  draw.getOverlay().setStyle(null);
64
- this.drawInformation?.push({
64
+ this.#drawInformation?.push({
65
65
  draw,
66
66
  style: previousStyle
67
67
  });
68
68
  });
69
- if (this.blockUserInteraction) {
70
- const container = this.olMap?.getTargetElement();
69
+ if (this.#blockUserInteraction) {
70
+ const container = this.#olMap?.getTargetElement();
71
71
  if (container) {
72
- this.overlay = createBlockUserOverlay(container, this.overlayText);
72
+ this.#overlay = createBlockUserOverlay(container, this.#overlayText);
73
73
  }
74
74
  }
75
- await this.addScaleLine();
75
+ await this.#addScaleLine();
76
76
  }
77
- async addScaleLine() {
78
- const scaleLine = this.scaleLine = new ScaleLine({
77
+ async #addScaleLine() {
78
+ const scaleLine = this.#scaleLine = new ScaleLine({
79
79
  className: "printing-scale-bar ol-scale-bar",
80
80
  bar: true,
81
81
  text: true,
@@ -87,8 +87,8 @@ class PrintJob {
87
87
  }
88
88
  let bottom = 50;
89
89
  let left = 8;
90
- if (this.viewPadding === "auto") {
91
- const { bottom: paddingBottom, left: paddingLeft } = this.getViewPadding();
90
+ if (this.#viewPadding === "auto") {
91
+ const { bottom: paddingBottom, left: paddingLeft } = this.#getViewPadding();
92
92
  bottom = Math.max(paddingBottom + 8, bottom);
93
93
  left += paddingLeft;
94
94
  }
@@ -98,12 +98,12 @@ class PrintJob {
98
98
  const timeout = setTimeout(() => {
99
99
  renderPromise.reject(new Error("Scale line did not render"));
100
100
  }, 3e3);
101
- const oldRender = this.scaleLine.render;
102
- this.scaleLine.render = (...args) => {
103
- oldRender.apply(this.scaleLine, args);
101
+ const oldRender = this.#scaleLine.render;
102
+ this.#scaleLine.render = (...args) => {
103
+ oldRender.apply(this.#scaleLine, args);
104
104
  renderPromise.resolve();
105
105
  };
106
- this.olMap?.addControl(this.scaleLine);
106
+ this.#olMap?.addControl(this.#scaleLine);
107
107
  try {
108
108
  await renderPromise.promise;
109
109
  await new Promise((resolve) => {
@@ -113,6 +113,8 @@ class PrintJob {
113
113
  clearTimeout(timeout);
114
114
  }
115
115
  }
116
+ // Kept as a TypeScript `private` method (not a `#` private) so tests can replace it via
117
+ // `vi.spyOn(PrintJob.prototype, ...)`: real canvas rendering does not work under jsdom.
116
118
  async printToCanvas(element) {
117
119
  const exportOptions = {
118
120
  useCORS: true,
@@ -128,20 +130,22 @@ class PrintJob {
128
130
  const canvas = await html2canvas(element, exportOptions);
129
131
  return canvas;
130
132
  }
131
- reset() {
132
- if (this.scaleLine) {
133
- this.olMap?.removeControl(this.scaleLine);
134
- this.scaleLine = void 0;
133
+ #reset() {
134
+ if (this.#scaleLine) {
135
+ this.#olMap?.removeControl(this.#scaleLine);
136
+ this.#scaleLine = void 0;
135
137
  }
136
- if (this.overlay) {
137
- this.overlay.destroy();
138
- this.overlay = void 0;
138
+ if (this.#overlay) {
139
+ this.#overlay.destroy();
140
+ this.#overlay = void 0;
139
141
  }
140
- this.running = false;
141
- this.drawInformation?.length && this.drawInformation.forEach((drawInfo) => {
142
+ this.#running = false;
143
+ this.#drawInformation?.length && this.#drawInformation.forEach((drawInfo) => {
142
144
  drawInfo.draw.getOverlay().setStyle(drawInfo.style);
143
145
  });
144
146
  }
147
+ // Kept as a TypeScript `private` method (not a `#` private) so tests can replace it via
148
+ // `vi.spyOn(PrintJob.prototype, ...)`: `canvas.getContext()` is unavailable under jsdom.
145
149
  removePadding(canvas, rawPadding) {
146
150
  const dpr = window.devicePixelRatio || 1;
147
151
  const dprPadding = {
@@ -174,8 +178,8 @@ class PrintJob {
174
178
  );
175
179
  return newCanvas;
176
180
  }
177
- getViewPadding() {
178
- const map = this.olMap;
181
+ #getViewPadding() {
182
+ const map = this.#olMap;
179
183
  const rawPadding = map.getView().padding ?? [0, 0, 0, 0];
180
184
  return {
181
185
  top: rawPadding[0] ?? 0,
@@ -186,15 +190,15 @@ class PrintJob {
186
190
  }
187
191
  }
188
192
  class PrintResultImpl {
189
- canvas;
193
+ #canvas;
190
194
  constructor(canvas) {
191
- this.canvas = canvas;
195
+ this.#canvas = canvas;
192
196
  }
193
197
  getCanvas() {
194
- return this.canvas;
198
+ return this.#canvas;
195
199
  }
196
200
  getPNGDataURL(quality) {
197
- return canvasToPng(this.canvas, quality);
201
+ return canvasToPng(this.#canvas, quality);
198
202
  }
199
203
  }
200
204
 
@@ -1 +1 @@
1
- {"version":3,"file":"PrintingServiceImpl.js","sources":["PrintingServiceImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createManualPromise, Resource } from \"@open-pioneer/core\";\nimport { PackageIntl, ServiceOptions } from \"@open-pioneer/runtime\";\nimport { Options } from \"html2canvas\";\nimport { ScaleLine } from \"ol/control\";\nimport { Interaction } from \"ol/interaction\";\nimport Draw from \"ol/interaction/Draw\";\nimport OlMap from \"ol/Map\";\nimport { FlatStyleLike } from \"ol/style/flat\";\nimport { StyleLike } from \"ol/style/Style\";\nimport type { PrintingOptions, PrintingService, PrintResult, ViewPaddingBehavior } from \"./index\";\nimport { canvasToPng, createBlockUserOverlay, PRINTING_HIDE_CLASS } from \"./utils\";\nimport { ReadonlyReactive } from \"@conterra/reactivity-core\";\n\nexport class PrintingServiceImpl implements PrintingService {\n #intl: ReadonlyReactive<PackageIntl>;\n\n constructor(options: ServiceOptions) {\n this.#intl = options.currentIntl;\n }\n\n async printMap(olMap: OlMap, options?: PrintingOptions): Promise<PrintResultImpl> {\n const job = new PrintJob(olMap, {\n blockUserInteraction: true,\n overlayText: this.#intl.value.formatMessage({ id: \"printingMap\" }),\n viewPadding: \"auto\",\n ...options\n });\n return await job.printMap();\n }\n}\n\ninterface ViewPadding {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\ninterface DrawInfo {\n draw: Draw;\n style: StyleLike | FlatStyleLike | null | undefined;\n}\n\n// Exported just for test (mocking)\nexport class PrintJob {\n private olMap: OlMap;\n private blockUserInteraction: boolean = false;\n private overlayText: string;\n private viewPadding: ViewPaddingBehavior;\n\n private running = false;\n private drawInformation: DrawInfo[] | undefined = [];\n private scaleLine: ScaleLine | undefined = undefined;\n private overlay: Resource | undefined = undefined;\n\n constructor(olMap: OlMap, options: Required<PrintingOptions>) {\n this.olMap = olMap;\n this.blockUserInteraction = options.blockUserInteraction;\n this.overlayText = options.overlayText;\n this.viewPadding = options.viewPadding;\n }\n\n async printMap(): Promise<PrintResultImpl> {\n if (this.running) {\n throw new Error(\"Printing already running.\");\n }\n\n try {\n await this.beginExport();\n\n let canvas = await this.printToCanvas(this.olMap.getViewport());\n if (!canvas) {\n throw new Error(\"Canvas export failed\");\n }\n\n if (this.viewPadding === \"auto\") {\n canvas = this.removePadding(canvas, this.getViewPadding());\n }\n return new PrintResultImpl(canvas);\n } finally {\n // Always remove scale bar\n this.reset();\n }\n }\n\n private async beginExport() {\n this.running = true;\n\n /** hides active draw interactions while printing (set feature style to null ) */\n const interactions = this.olMap\n .getInteractions()\n .getArray()\n .filter((interaction: Interaction) => {\n return interaction.getActive() && interaction instanceof Draw;\n });\n this.drawInformation = [];\n interactions?.forEach((interaction) => {\n const draw = interaction as Draw;\n const previousStyle = draw.getOverlay().getStyle();\n draw.getOverlay().setStyle(null);\n this.drawInformation?.push({\n draw: draw,\n style: previousStyle\n });\n });\n\n if (this.blockUserInteraction) {\n const container = this.olMap?.getTargetElement();\n if (container) {\n this.overlay = createBlockUserOverlay(container, this.overlayText);\n }\n }\n await this.addScaleLine();\n }\n\n private async addScaleLine() {\n const scaleLine = (this.scaleLine = new ScaleLine({\n className: \"printing-scale-bar ol-scale-bar\",\n bar: true,\n text: true,\n minWidth: 125\n }));\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const scaleLineElement = (scaleLine as any).element as HTMLElement;\n if (!scaleLineElement) {\n throw new Error(\"Scale line does not have an element\");\n }\n\n // Position the scale bar manually.\n // The 50px should be plenty to avoid overlapping with open layers attributions on most cases.\n // Additionally, take the view padding into account (if behavior is 'auto').\n let bottom = 50;\n let left = 8;\n if (this.viewPadding === \"auto\") {\n const { bottom: paddingBottom, left: paddingLeft } = this.getViewPadding();\n bottom = Math.max(paddingBottom + 8, bottom);\n left += paddingLeft;\n }\n scaleLineElement.style.setProperty(\"--printing-scale-bar-bottom\", `${bottom}px`);\n scaleLineElement.style.setProperty(\"--printing-scale-bar-left\", `${left}px`);\n\n const renderPromise = createManualPromise<void>();\n\n // We expect the scale line to be rendered by the open layers map.\n // This is a sanity check that throws an error when that either doesn't happen\n // or if it takes an extremely large time.\n const timeout = setTimeout(() => {\n renderPromise.reject(new Error(\"Scale line did not render\"));\n }, 3000);\n\n const oldRender = this.scaleLine.render;\n this.scaleLine.render = (...args) => {\n oldRender.apply(this.scaleLine, args);\n renderPromise.resolve();\n };\n this.olMap?.addControl(this.scaleLine);\n\n try {\n // Wait until render (+ one additional frame just to be sure).\n await renderPromise.promise;\n await new Promise((resolve) => {\n requestAnimationFrame(resolve);\n });\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private async printToCanvas(element: HTMLElement): Promise<HTMLCanvasElement> {\n // export options for html2canvas.\n const exportOptions: Partial<Options> = {\n useCORS: true,\n ignoreElements: function (element: Element) {\n if (element.classList && typeof element.classList === \"object\") {\n const classList = element.classList;\n return (\n classList.contains(\"map-anchors\") || classList.contains(PRINTING_HIDE_CLASS)\n );\n }\n return false;\n }\n };\n\n // Lazy load html2canvas: it is a large dependency (a few hundred KiB) that is only\n // required when actually printed. This speeds up the initial page load.\n const html2canvas = (await import(\"html2canvas\")).default;\n const canvas = await html2canvas(element, exportOptions);\n return canvas;\n }\n\n private reset() {\n if (this.scaleLine) {\n this.olMap?.removeControl(this.scaleLine);\n this.scaleLine = undefined;\n }\n if (this.overlay) {\n this.overlay.destroy();\n this.overlay = undefined;\n }\n\n this.running = false;\n\n /** show active draw interactions after printing (reset feature style to its previous style ) */\n this.drawInformation?.length &&\n this.drawInformation.forEach((drawInfo) => {\n drawInfo.draw.getOverlay().setStyle(drawInfo.style);\n });\n }\n\n private removePadding(canvas: HTMLCanvasElement, rawPadding: ViewPadding): HTMLCanvasElement {\n // The canvas returned by html2canvas is scaled by the device pixel ratio.\n // The padding needs to be adjusted (because its in css pixels).\n const dpr = window.devicePixelRatio || 1;\n const dprPadding = {\n top: rawPadding.top * dpr,\n right: rawPadding.right * dpr,\n bottom: rawPadding.bottom * dpr,\n left: rawPadding.left * dpr\n };\n\n if (\n dprPadding.left === 0 &&\n dprPadding.right === 0 &&\n dprPadding.top === 0 &&\n dprPadding.bottom === 0\n ) {\n return canvas;\n }\n\n const { width, height } = canvas;\n const newCanvas = document.createElement(\"canvas\");\n newCanvas.width = width - dprPadding.left - dprPadding.right;\n newCanvas.height = height - dprPadding.top - dprPadding.bottom;\n\n const newCtx = newCanvas.getContext(\"2d\");\n if (!newCtx) {\n throw new Error(\"Failed to get a canvas context\");\n }\n\n newCtx.drawImage(\n canvas,\n dprPadding.left,\n dprPadding.top,\n newCanvas.width,\n newCanvas.height,\n 0,\n 0,\n newCanvas.width,\n newCanvas.height\n );\n return newCanvas;\n }\n\n private getViewPadding(): ViewPadding {\n const map = this.olMap;\n // top, right, bottom, left\n const rawPadding = (map.getView().padding ?? [0, 0, 0, 0]) as [\n number,\n number,\n number,\n number\n ];\n return {\n top: rawPadding[0] ?? 0,\n right: rawPadding[1] ?? 0,\n bottom: rawPadding[2] ?? 0,\n left: rawPadding[3] ?? 0\n };\n }\n}\n\nclass PrintResultImpl implements PrintResult {\n private canvas: HTMLCanvasElement;\n\n constructor(canvas: HTMLCanvasElement) {\n this.canvas = canvas;\n }\n getCanvas(): HTMLCanvasElement {\n return this.canvas;\n }\n\n getPNGDataURL(quality?: number): string {\n return canvasToPng(this.canvas, quality);\n }\n}\n"],"names":["element"],"mappings":"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"}
1
+ {"version":3,"file":"PrintingServiceImpl.js","sources":["PrintingServiceImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { createManualPromise, Resource } from \"@open-pioneer/core\";\nimport { PackageIntl, ServiceOptions } from \"@open-pioneer/runtime\";\nimport { Options } from \"html2canvas\";\nimport { ScaleLine } from \"ol/control\";\nimport { Interaction } from \"ol/interaction\";\nimport Draw from \"ol/interaction/Draw\";\nimport OlMap from \"ol/Map\";\nimport { FlatStyleLike } from \"ol/style/flat\";\nimport { StyleLike } from \"ol/style/Style\";\nimport type { PrintingOptions, PrintingService, PrintResult, ViewPaddingBehavior } from \"./index\";\nimport { canvasToPng, createBlockUserOverlay, PRINTING_HIDE_CLASS } from \"./utils\";\n\nexport class PrintingServiceImpl implements PrintingService {\n #intl: ReadonlyReactive<PackageIntl>;\n\n constructor(options: ServiceOptions) {\n this.#intl = options.currentIntl;\n }\n\n async printMap(olMap: OlMap, options?: PrintingOptions): Promise<PrintResultImpl> {\n const job = new PrintJob(olMap, {\n blockUserInteraction: true,\n overlayText: this.#intl.value.formatMessage({ id: \"printingMap\" }),\n viewPadding: \"auto\",\n ...options\n });\n return await job.printMap();\n }\n}\n\ninterface ViewPadding {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\ninterface DrawInfo {\n draw: Draw;\n style: StyleLike | FlatStyleLike | null | undefined;\n}\n\n// Exported just for test (mocking)\nexport class PrintJob {\n #olMap: OlMap;\n #blockUserInteraction: boolean = false;\n #overlayText: string;\n #viewPadding: ViewPaddingBehavior;\n\n #running = false;\n #drawInformation: DrawInfo[] | undefined = [];\n #scaleLine: ScaleLine | undefined = undefined;\n #overlay: Resource | undefined = undefined;\n\n constructor(olMap: OlMap, options: Required<PrintingOptions>) {\n this.#olMap = olMap;\n this.#blockUserInteraction = options.blockUserInteraction;\n this.#overlayText = options.overlayText;\n this.#viewPadding = options.viewPadding;\n }\n\n async printMap(): Promise<PrintResultImpl> {\n if (this.#running) {\n throw new Error(\"Printing already running.\");\n }\n\n try {\n await this.#beginExport();\n\n let canvas = await this.printToCanvas(this.#olMap.getViewport());\n if (!canvas) {\n throw new Error(\"Canvas export failed\");\n }\n\n if (this.#viewPadding === \"auto\") {\n canvas = this.removePadding(canvas, this.#getViewPadding());\n }\n return new PrintResultImpl(canvas);\n } finally {\n // Always remove scale bar\n this.#reset();\n }\n }\n\n async #beginExport() {\n this.#running = true;\n\n /** hides active draw interactions while printing (set feature style to null ) */\n const interactions = this.#olMap\n .getInteractions()\n .getArray()\n .filter((interaction: Interaction) => {\n return interaction.getActive() && interaction instanceof Draw;\n });\n this.#drawInformation = [];\n interactions?.forEach((interaction) => {\n const draw = interaction as Draw;\n const previousStyle = draw.getOverlay().getStyle();\n draw.getOverlay().setStyle(null);\n this.#drawInformation?.push({\n draw: draw,\n style: previousStyle\n });\n });\n\n if (this.#blockUserInteraction) {\n const container = this.#olMap?.getTargetElement();\n if (container) {\n this.#overlay = createBlockUserOverlay(container, this.#overlayText);\n }\n }\n await this.#addScaleLine();\n }\n\n async #addScaleLine() {\n const scaleLine = (this.#scaleLine = new ScaleLine({\n className: \"printing-scale-bar ol-scale-bar\",\n bar: true,\n text: true,\n minWidth: 125\n }));\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const scaleLineElement = (scaleLine as any).element as HTMLElement;\n if (!scaleLineElement) {\n throw new Error(\"Scale line does not have an element\");\n }\n\n // Position the scale bar manually.\n // The 50px should be plenty to avoid overlapping with open layers attributions on most cases.\n // Additionally, take the view padding into account (if behavior is 'auto').\n let bottom = 50;\n let left = 8;\n if (this.#viewPadding === \"auto\") {\n const { bottom: paddingBottom, left: paddingLeft } = this.#getViewPadding();\n bottom = Math.max(paddingBottom + 8, bottom);\n left += paddingLeft;\n }\n scaleLineElement.style.setProperty(\"--printing-scale-bar-bottom\", `${bottom}px`);\n scaleLineElement.style.setProperty(\"--printing-scale-bar-left\", `${left}px`);\n\n const renderPromise = createManualPromise<void>();\n\n // We expect the scale line to be rendered by the open layers map.\n // This is a sanity check that throws an error when that either doesn't happen\n // or if it takes an extremely large time.\n const timeout = setTimeout(() => {\n renderPromise.reject(new Error(\"Scale line did not render\"));\n }, 3000);\n\n const oldRender = this.#scaleLine.render;\n this.#scaleLine.render = (...args) => {\n oldRender.apply(this.#scaleLine, args);\n renderPromise.resolve();\n };\n this.#olMap?.addControl(this.#scaleLine);\n\n try {\n // Wait until render (+ one additional frame just to be sure).\n await renderPromise.promise;\n await new Promise((resolve) => {\n requestAnimationFrame(resolve);\n });\n } finally {\n clearTimeout(timeout);\n }\n }\n\n // Kept as a TypeScript `private` method (not a `#` private) so tests can replace it via\n // `vi.spyOn(PrintJob.prototype, ...)`: real canvas rendering does not work under jsdom.\n private async printToCanvas(element: HTMLElement): Promise<HTMLCanvasElement> {\n // export options for html2canvas.\n const exportOptions: Partial<Options> = {\n useCORS: true,\n ignoreElements: function (element: Element) {\n if (element.classList && typeof element.classList === \"object\") {\n const classList = element.classList;\n return (\n classList.contains(\"map-anchors\") || classList.contains(PRINTING_HIDE_CLASS)\n );\n }\n return false;\n }\n };\n\n // Lazy load html2canvas: it is a large dependency (a few hundred KiB) that is only\n // required when actually printed. This speeds up the initial page load.\n const html2canvas = (await import(\"html2canvas\")).default;\n const canvas = await html2canvas(element, exportOptions);\n return canvas;\n }\n\n #reset() {\n if (this.#scaleLine) {\n this.#olMap?.removeControl(this.#scaleLine);\n this.#scaleLine = undefined;\n }\n if (this.#overlay) {\n this.#overlay.destroy();\n this.#overlay = undefined;\n }\n\n this.#running = false;\n\n /** show active draw interactions after printing (reset feature style to its previous style ) */\n this.#drawInformation?.length &&\n this.#drawInformation.forEach((drawInfo) => {\n drawInfo.draw.getOverlay().setStyle(drawInfo.style);\n });\n }\n\n // Kept as a TypeScript `private` method (not a `#` private) so tests can replace it via\n // `vi.spyOn(PrintJob.prototype, ...)`: `canvas.getContext()` is unavailable under jsdom.\n private removePadding(canvas: HTMLCanvasElement, rawPadding: ViewPadding): HTMLCanvasElement {\n // The canvas returned by html2canvas is scaled by the device pixel ratio.\n // The padding needs to be adjusted (because its in css pixels).\n const dpr = window.devicePixelRatio || 1;\n const dprPadding = {\n top: rawPadding.top * dpr,\n right: rawPadding.right * dpr,\n bottom: rawPadding.bottom * dpr,\n left: rawPadding.left * dpr\n };\n\n if (\n dprPadding.left === 0 &&\n dprPadding.right === 0 &&\n dprPadding.top === 0 &&\n dprPadding.bottom === 0\n ) {\n return canvas;\n }\n\n const { width, height } = canvas;\n const newCanvas = document.createElement(\"canvas\");\n newCanvas.width = width - dprPadding.left - dprPadding.right;\n newCanvas.height = height - dprPadding.top - dprPadding.bottom;\n\n const newCtx = newCanvas.getContext(\"2d\");\n if (!newCtx) {\n throw new Error(\"Failed to get a canvas context\");\n }\n\n newCtx.drawImage(\n canvas,\n dprPadding.left,\n dprPadding.top,\n newCanvas.width,\n newCanvas.height,\n 0,\n 0,\n newCanvas.width,\n newCanvas.height\n );\n return newCanvas;\n }\n\n #getViewPadding(): ViewPadding {\n const map = this.#olMap;\n // top, right, bottom, left\n const rawPadding = (map.getView().padding ?? [0, 0, 0, 0]) as [\n number,\n number,\n number,\n number\n ];\n return {\n top: rawPadding[0] ?? 0,\n right: rawPadding[1] ?? 0,\n bottom: rawPadding[2] ?? 0,\n left: rawPadding[3] ?? 0\n };\n }\n}\n\nclass PrintResultImpl implements PrintResult {\n #canvas: HTMLCanvasElement;\n\n constructor(canvas: HTMLCanvasElement) {\n this.#canvas = canvas;\n }\n getCanvas(): HTMLCanvasElement {\n return this.#canvas;\n }\n\n getPNGDataURL(quality?: number): string {\n return canvasToPng(this.#canvas, quality);\n }\n}\n"],"names":["element"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@open-pioneer/printing",
4
- "version": "1.4.0-dev.20260625074633",
4
+ "version": "1.4.0",
5
5
  "description": "This package provides a UI component to export the current map view as a printable file.",
6
6
  "keywords": [
7
7
  "open-pioneer-trails"
@@ -14,17 +14,17 @@
14
14
  "directory": "src/packages/printing"
15
15
  },
16
16
  "dependencies": {
17
- "@chakra-ui/react": "^3.36.0",
18
- "@open-pioneer/chakra-snippets": "4.7.0-dev.20260624141040",
19
- "@open-pioneer/core": "4.7.0-dev.20260624141040",
20
- "@open-pioneer/notifier": "4.7.0-dev.20260624141040",
21
- "@open-pioneer/react-utils": "4.7.0-dev.20260624141040",
22
- "@open-pioneer/runtime": "4.7.0-dev.20260624141040",
17
+ "@chakra-ui/react": "^3.36.1",
18
+ "@open-pioneer/chakra-snippets": "^4.7.0",
19
+ "@open-pioneer/core": "^4.7.0",
20
+ "@open-pioneer/notifier": "^4.7.0",
21
+ "@open-pioneer/react-utils": "^4.7.0",
22
+ "@open-pioneer/runtime": "^4.7.0",
23
23
  "html2canvas": "^1.4.1",
24
24
  "jspdf": "^4.2.1",
25
25
  "ol": "^10.9.0",
26
- "react": "^19.2.7",
27
- "@open-pioneer/map": "1.4.0-dev.20260625074633"
26
+ "react": "^19.2.8",
27
+ "@open-pioneer/map": "1.4.0"
28
28
  },
29
29
  "exports": {
30
30
  "./package.json": "./package.json",
package/styles.css CHANGED
@@ -23,7 +23,6 @@
23
23
  }
24
24
 
25
25
  /* more specific than the open layers selector */
26
-
27
26
  .printing-scale-bar.ol-scale-bar {
28
27
  /* these variables are set in the PrintingService and may include the map view's padding */
29
28
  left: var(--printing-scale-bar-left);
package/styles.css.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["styles.css"],"names":[],"mappings":"AAAA;IACI,yEAAyE;IACzE,kBAAkB;IAClB,QAAQ;IACR,cAAc;;IAEd,4EAA4E;IAC5E,iBAAiB;IACjB,mBAAmB;IACnB,YAAY;;IAEZ,aAAa;IACb,mBAAmB;IACnB,mBAAmB;IACnB,uBAAuB;IACvB,0CAA0C;AAC9C;;AAEA;IACI,cAAc;IACd,gBAAgB;IAChB,kBAAkB;AACtB;;AAEA,gDAAgD;;AAChD;IACI,0FAA0F;IAC1F,oCAAoC;IACpC,wCAAwC;AAC5C","file":"styles.css","sourcesContent":[".printing-overlay {\n /* container uses position relative, so this absolute positioning works */\n position: absolute;\n inset: 0;\n z-index: 10000;\n\n /* non-interactive: the overlay is \"in front\" of the map and blocks events */\n user-select: none;\n pointer-events: all;\n cursor: wait;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n background-color: rgba(180, 180, 180, 0.8);\n}\n\n.printing-overlay-status {\n flex: 1 1 auto;\n font-size: 1.5em;\n text-align: center;\n}\n\n/* more specific than the open layers selector */\n.printing-scale-bar.ol-scale-bar {\n /* these variables are set in the PrintingService and may include the map view's padding */\n left: var(--printing-scale-bar-left);\n bottom: var(--printing-scale-bar-bottom);\n}\n"]}
1
+ {"version":3,"sources":["styles.css"],"names":[],"mappings":"AAAA;IACI,yEAAyE;IACzE,kBAAkB;IAClB,QAAQ;IACR,cAAc;;IAEd,4EAA4E;IAC5E,iBAAiB;IACjB,mBAAmB;IACnB,YAAY;;IAEZ,aAAa;IACb,mBAAmB;IACnB,mBAAmB;IACnB,uBAAuB;IACvB,0CAA0C;AAC9C;;AAEA;IACI,cAAc;IACd,gBAAgB;IAChB,kBAAkB;AACtB;;AAEA,gDAAgD;AAChD;IACI,0FAA0F;IAC1F,oCAAoC;IACpC,wCAAwC;AAC5C","file":"styles.css","sourcesContent":[".printing-overlay {\n /* container uses position relative, so this absolute positioning works */\n position: absolute;\n inset: 0;\n z-index: 10000;\n\n /* non-interactive: the overlay is \"in front\" of the map and blocks events */\n user-select: none;\n pointer-events: all;\n cursor: wait;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n background-color: rgba(180, 180, 180, 0.8);\n}\n\n.printing-overlay-status {\n flex: 1 1 auto;\n font-size: 1.5em;\n text-align: center;\n}\n\n/* more specific than the open layers selector */\n.printing-scale-bar.ol-scale-bar {\n /* these variables are set in the PrintingService and may include the map view's padding */\n left: var(--printing-scale-bar-left);\n bottom: var(--printing-scale-bar-bottom);\n}\n"]}
package/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Resource } from \"@open-pioneer/core\";\n\nconst DEFAULT_QUALITY = 0.8;\n\nexport const PRINTING_HIDE_CLASS = \"printing-hide\";\n\nexport function canvasToPng(canvas: HTMLCanvasElement, quality?: number) {\n return canvas.toDataURL(\"image/png\", quality ?? DEFAULT_QUALITY);\n}\n\nexport function createBlockUserOverlay(container: HTMLElement, text: string): Resource {\n const overlay = document.createElement(\"div\");\n overlay.classList.add(\"printing-overlay\", PRINTING_HIDE_CLASS);\n container.appendChild(overlay);\n\n const message = document.createElement(\"div\");\n message.classList.add(\"printing-overlay-status\");\n message.textContent = text;\n overlay.appendChild(message);\n\n return {\n destroy() {\n overlay.remove();\n }\n };\n}\n"],"names":[],"mappings":"AAIA,MAAM,eAAA,GAAkB,GAAA;AAEjB,MAAM,mBAAA,GAAsB;AAE5B,SAAS,WAAA,CAAY,QAA2B,OAAA,EAAkB;AACrE,EAAA,OAAO,MAAA,CAAO,SAAA,CAAU,WAAA,EAAa,OAAA,IAAW,eAAe,CAAA;AACnE;AAEO,SAAS,sBAAA,CAAuB,WAAwB,IAAA,EAAwB;AACnF,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,SAAA,CAAU,GAAA,CAAI,kBAAA,EAAoB,mBAAmB,CAAA;AAC7D,EAAA,SAAA,CAAU,YAAY,OAAO,CAAA;AAE7B,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,yBAAyB,CAAA;AAC/C,EAAA,OAAA,CAAQ,WAAA,GAAc,IAAA;AACtB,EAAA,OAAA,CAAQ,YAAY,OAAO,CAAA;AAE3B,EAAA,OAAO;AAAA,IACH,OAAA,GAAU;AACN,MAAA,OAAA,CAAQ,MAAA,EAAO;AAAA,IACnB;AAAA,GACJ;AACJ;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Resource } from \"@open-pioneer/core\";\n\nconst DEFAULT_QUALITY = 0.8;\n\nexport const PRINTING_HIDE_CLASS = \"printing-hide\";\n\nexport function canvasToPng(canvas: HTMLCanvasElement, quality?: number) {\n return canvas.toDataURL(\"image/png\", quality ?? DEFAULT_QUALITY);\n}\n\nexport function createBlockUserOverlay(container: HTMLElement, text: string): Resource {\n const overlay = document.createElement(\"div\");\n overlay.classList.add(\"printing-overlay\", PRINTING_HIDE_CLASS);\n container.appendChild(overlay);\n\n const message = document.createElement(\"div\");\n message.classList.add(\"printing-overlay-status\");\n message.textContent = text;\n overlay.appendChild(message);\n\n return {\n destroy() {\n overlay.remove();\n }\n };\n}\n"],"names":[],"mappings":"AAKA,MAAM,eAAA,GAAkB,GAAA;AAEjB,MAAM,mBAAA,GAAsB;AAE5B,SAAS,WAAA,CAAY,QAA2B,OAAA,EAAkB;AACrE,EAAA,OAAO,MAAA,CAAO,SAAA,CAAU,WAAA,EAAa,OAAA,IAAW,eAAe,CAAA;AACnE;AAEO,SAAS,sBAAA,CAAuB,WAAwB,IAAA,EAAwB;AACnF,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,SAAA,CAAU,GAAA,CAAI,kBAAA,EAAoB,mBAAmB,CAAA;AAC7D,EAAA,SAAA,CAAU,YAAY,OAAO,CAAA;AAE7B,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,SAAA,CAAU,IAAI,yBAAyB,CAAA;AAC/C,EAAA,OAAA,CAAQ,WAAA,GAAc,IAAA;AACtB,EAAA,OAAA,CAAQ,YAAY,OAAO,CAAA;AAE3B,EAAA,OAAO;AAAA,IACH,OAAA,GAAU;AACN,MAAA,OAAA,CAAQ,MAAA,EAAO;AAAA,IACnB;AAAA,GACJ;AACJ;;;;"}