@pdfme/schemas 6.1.13-dev.46 → 6.1.13-dev.55

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,5 +1,30 @@
1
1
  import type { Plugin } from '@pdfme/common';
2
2
  import type { Schema } from '@pdfme/common';
3
- export type ImageSchema = Schema;
3
+ export declare const IMAGE_OBJECT_FITS: readonly ['contain', 'cover'];
4
+ export type ImageObjectFit = (typeof IMAGE_OBJECT_FITS)[number];
5
+ export declare const IMAGE_OBJECT_POSITIONS: readonly ['left top', 'center top', 'right top', 'left center', 'center center', 'right center', 'left bottom', 'center bottom', 'right bottom'];
6
+ export type ImageObjectPosition = (typeof IMAGE_OBJECT_POSITIONS)[number];
7
+ export declare const DEFAULT_IMAGE_OBJECT_FIT: ImageObjectFit;
8
+ export declare const DEFAULT_IMAGE_OBJECT_POSITION: ImageObjectPosition;
9
+ export declare const getEffectiveObjectPosition: (schema: ImageSchema) => ImageObjectPosition;
10
+ export declare const getImageFitLayout: (arg: {
11
+ sourceWidth: number;
12
+ sourceHeight: number;
13
+ boxWidth: number;
14
+ boxHeight: number;
15
+ objectFit?: unknown;
16
+ objectPosition?: unknown;
17
+ }) => {
18
+ objectFit: "contain" | "cover";
19
+ objectPosition: "center bottom" | "center center" | "center top" | "left bottom" | "left center" | "left top" | "right bottom" | "right center" | "right top";
20
+ width: number;
21
+ height: number;
22
+ offsetX: number;
23
+ offsetY: number;
24
+ };
25
+ export type ImageSchema = Schema & {
26
+ objectFit?: ImageObjectFit;
27
+ objectPosition?: ImageObjectPosition;
28
+ };
4
29
  declare const imageSchema: Plugin<ImageSchema>;
5
30
  export default imageSchema;
package/dist/index.js CHANGED
@@ -1650,10 +1650,121 @@ var fullSize$1 = {
1650
1650
  width: "100%",
1651
1651
  height: "100%"
1652
1652
  };
1653
+ var IMAGE_OBJECT_FITS = ["contain", "cover"];
1654
+ var IMAGE_OBJECT_POSITIONS = [
1655
+ "left top",
1656
+ "center top",
1657
+ "right top",
1658
+ "left center",
1659
+ "center center",
1660
+ "right center",
1661
+ "left bottom",
1662
+ "center bottom",
1663
+ "right bottom"
1664
+ ];
1665
+ var DEFAULT_IMAGE_OBJECT_FIT = "contain";
1666
+ var DEFAULT_IMAGE_OBJECT_POSITION = "center center";
1667
+ var imageObjectFitSet = new Set(IMAGE_OBJECT_FITS);
1668
+ var imageObjectPositionSet = new Set(IMAGE_OBJECT_POSITIONS);
1669
+ var normalizeObjectFit = (value) => typeof value === "string" && imageObjectFitSet.has(value) ? value : DEFAULT_IMAGE_OBJECT_FIT;
1670
+ var normalizeObjectPosition = (value) => typeof value === "string" && imageObjectPositionSet.has(value) ? value : DEFAULT_IMAGE_OBJECT_POSITION;
1671
+ var getEffectiveObjectPosition = (schema) => {
1672
+ return normalizeObjectFit(schema.objectFit) === "cover" ? DEFAULT_IMAGE_OBJECT_POSITION : normalizeObjectPosition(schema.objectPosition);
1673
+ };
1674
+ var alignOffset = (space, position) => {
1675
+ if (position === "right" || position === "bottom") return space;
1676
+ if (position === "center") return space / 2;
1677
+ return 0;
1678
+ };
1679
+ var getImageFitLayout = (arg) => {
1680
+ const { sourceWidth, sourceHeight, boxWidth, boxHeight } = arg;
1681
+ const objectFit = normalizeObjectFit(arg.objectFit);
1682
+ const objectPosition = objectFit === "cover" ? DEFAULT_IMAGE_OBJECT_POSITION : normalizeObjectPosition(arg.objectPosition);
1683
+ const scale = objectFit === "cover" ? Math.max(boxWidth / sourceWidth, boxHeight / sourceHeight) : Math.min(boxWidth / sourceWidth, boxHeight / sourceHeight);
1684
+ const width = sourceWidth * scale;
1685
+ const height = sourceHeight * scale;
1686
+ const [horizontal, vertical] = objectPosition.split(" ");
1687
+ return {
1688
+ objectFit,
1689
+ objectPosition,
1690
+ width,
1691
+ height,
1692
+ offsetX: alignOffset(boxWidth - width, horizontal),
1693
+ offsetY: alignOffset(boxHeight - height, vertical)
1694
+ };
1695
+ };
1696
+ var getClipPathCorners = (arg) => {
1697
+ const { schema, pageHeight } = arg;
1698
+ const clippingBox = convertForPdfLayoutProps({
1699
+ schema,
1700
+ pageHeight,
1701
+ applyRotateTranslate: false
1702
+ });
1703
+ const { x, y } = clippingBox.position;
1704
+ const width = clippingBox.width;
1705
+ const height = clippingBox.height;
1706
+ const rotateDegrees = schema.rotate ? -schema.rotate : 0;
1707
+ const corners = [
1708
+ {
1709
+ x,
1710
+ y
1711
+ },
1712
+ {
1713
+ x,
1714
+ y: y + height
1715
+ },
1716
+ {
1717
+ x: x + width,
1718
+ y: y + height
1719
+ },
1720
+ {
1721
+ x: x + width,
1722
+ y
1723
+ }
1724
+ ];
1725
+ if (!rotateDegrees) return corners;
1726
+ const pivot = {
1727
+ x: x + width / 2,
1728
+ y: y + height / 2
1729
+ };
1730
+ return corners.map((corner) => rotatePoint(corner, pivot, rotateDegrees));
1731
+ };
1653
1732
  var defaultValue = "data:image/png;base64,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";
1733
+ var getImagePropPanelSchema = ({ i18n, activeSchema }) => {
1734
+ const objectFit = normalizeObjectFit(activeSchema.objectFit);
1735
+ const positionOptions = IMAGE_OBJECT_POSITIONS.map((value) => ({
1736
+ value,
1737
+ label: i18n(`schemas.image.position.${value.replace(" ", ".")}`)
1738
+ }));
1739
+ return {
1740
+ objectFit: {
1741
+ title: i18n("schemas.image.objectFit"),
1742
+ type: "string",
1743
+ widget: "select",
1744
+ default: DEFAULT_IMAGE_OBJECT_FIT,
1745
+ props: { options: [{
1746
+ label: i18n("schemas.image.fit.contain"),
1747
+ value: "contain"
1748
+ }, {
1749
+ label: i18n("schemas.image.fit.cover"),
1750
+ value: "cover"
1751
+ }] },
1752
+ span: 8
1753
+ },
1754
+ objectPosition: {
1755
+ title: i18n("schemas.image.objectPosition"),
1756
+ type: "string",
1757
+ widget: "select",
1758
+ default: DEFAULT_IMAGE_OBJECT_POSITION,
1759
+ hidden: objectFit === "cover",
1760
+ props: { options: positionOptions },
1761
+ span: 16
1762
+ }
1763
+ };
1764
+ };
1654
1765
  var imageSchema = {
1655
1766
  pdf: async (arg) => {
1656
- const { value, schema, pdfDoc, page, _cache } = arg;
1767
+ const { value, schema, pdfDoc, page, pdfLib, _cache } = arg;
1657
1768
  if (!value) return;
1658
1769
  const inputImageCacheKey = getCacheKey(schema, value);
1659
1770
  let image = _cache.get(inputImageCacheKey);
@@ -1678,16 +1789,18 @@ var imageSchema = {
1678
1789
  const imageHeight = px2mm(image.height);
1679
1790
  const boxWidth = _schema.width;
1680
1791
  const boxHeight = _schema.height;
1681
- const imageRatio = imageWidth / imageHeight;
1682
- if (imageRatio > boxWidth / boxHeight) {
1683
- _schema.width = boxWidth;
1684
- _schema.height = boxWidth / imageRatio;
1685
- _schema.position.y += (boxHeight - _schema.height) / 2;
1686
- } else {
1687
- _schema.width = boxHeight * imageRatio;
1688
- _schema.height = boxHeight;
1689
- _schema.position.x += (boxWidth - _schema.width) / 2;
1690
- }
1792
+ const fitLayout = getImageFitLayout({
1793
+ sourceWidth: imageWidth,
1794
+ sourceHeight: imageHeight,
1795
+ boxWidth,
1796
+ boxHeight,
1797
+ objectFit: _schema.objectFit,
1798
+ objectPosition: _schema.objectPosition
1799
+ });
1800
+ _schema.width = fitLayout.width;
1801
+ _schema.height = fitLayout.height;
1802
+ _schema.position.x += fitLayout.offsetX;
1803
+ _schema.position.y += fitLayout.offsetY;
1691
1804
  const pageHeight = page.getHeight();
1692
1805
  const { width, height, rotate, position, opacity } = convertForPdfLayoutProps({
1693
1806
  schema: _schema,
@@ -1702,20 +1815,30 @@ var imageSchema = {
1702
1815
  height,
1703
1816
  opacity
1704
1817
  };
1818
+ if (fitLayout.objectFit === "cover") {
1819
+ const [firstCorner, ...corners] = getClipPathCorners({
1820
+ schema,
1821
+ pageHeight
1822
+ });
1823
+ page.pushOperators(pdfLib.pushGraphicsState(), pdfLib.moveTo(firstCorner.x, firstCorner.y), ...corners.map((corner) => pdfLib.lineTo(corner.x, corner.y)), pdfLib.closePath(), pdfLib.clip(), pdfLib.endPath());
1824
+ }
1705
1825
  page.drawImage(image, drawOptions);
1826
+ if (fitLayout.objectFit === "cover") page.pushOperators(pdfLib.popGraphicsState());
1706
1827
  },
1707
1828
  ui: (arg) => {
1708
1829
  const { value, rootElement, mode, onChange, stopEditing, tabIndex, placeholder, theme, schema } = arg;
1709
1830
  const editable = isEditable(mode, schema);
1710
1831
  const isDefault = value === defaultValue;
1832
+ const objectFit = normalizeObjectFit(schema.objectFit);
1833
+ const objectPosition = getEffectiveObjectPosition(schema);
1711
1834
  const container = document.createElement("div");
1712
1835
  const backgroundStyle = placeholder ? `url(${placeholder})` : "none";
1713
1836
  const containerStyle = {
1714
1837
  ...fullSize$1,
1715
1838
  backgroundImage: value ? "none" : backgroundStyle,
1716
- backgroundSize: `contain`,
1839
+ backgroundSize: objectFit,
1717
1840
  backgroundRepeat: "no-repeat",
1718
- backgroundPosition: "center"
1841
+ backgroundPosition: objectPosition
1719
1842
  };
1720
1843
  Object.assign(container.style, containerStyle);
1721
1844
  container.addEventListener("click", (e) => {
@@ -1724,12 +1847,14 @@ var imageSchema = {
1724
1847
  rootElement.appendChild(container);
1725
1848
  if (value) {
1726
1849
  const img = document.createElement("img");
1727
- Object.assign(img.style, {
1850
+ const imgStyle = {
1728
1851
  height: "100%",
1729
1852
  width: "100%",
1730
1853
  borderRadius: 0,
1731
- objectFit: "contain"
1732
- });
1854
+ objectFit,
1855
+ ...objectPosition === "center center" ? {} : { objectPosition }
1856
+ };
1857
+ Object.assign(img.style, imgStyle);
1733
1858
  img.src = value;
1734
1859
  container.appendChild(img);
1735
1860
  }
@@ -1806,7 +1931,10 @@ var imageSchema = {
1806
1931
  }
1807
1932
  },
1808
1933
  propPanel: {
1809
- schema: {},
1934
+ schema: ({ i18n, activeSchema }) => getImagePropPanelSchema({
1935
+ i18n,
1936
+ activeSchema
1937
+ }),
1810
1938
  defaultSchema: {
1811
1939
  name: "",
1812
1940
  type: "image",
@@ -1817,6 +1945,8 @@ var imageSchema = {
1817
1945
  },
1818
1946
  width: 40,
1819
1947
  height: 40,
1948
+ objectFit: DEFAULT_IMAGE_OBJECT_FIT,
1949
+ objectPosition: DEFAULT_IMAGE_OBJECT_POSITION,
1820
1950
  rotate: 0,
1821
1951
  opacity: 1
1822
1952
  }