@oneblink/apps-react 8.10.0-alpha.2 → 8.10.0-beta.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,9 +1,9 @@
1
1
  import * as React from 'react';
2
2
  import { Area } from 'react-easy-crop';
3
- declare function AnnotationModal({ imageSrc, onClose, onSave, }: {
3
+ declare function CropModal({ imageSrc, onClose, onSave, }: {
4
4
  imageSrc: string;
5
5
  onClose: () => void;
6
6
  onSave: (imageArea: Area) => void;
7
7
  }): React.JSX.Element;
8
- declare const _default: React.MemoExoticComponent<typeof AnnotationModal>;
8
+ declare const _default: React.MemoExoticComponent<typeof CropModal>;
9
9
  export default _default;
@@ -1,8 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import ImageCropper from '.';
3
3
  import scrollingService from '../../services/scrolling-service';
4
- function AnnotationModal({ imageSrc, onClose, onSave, }) {
5
- const annotationContentElementRef = React.useRef(null);
4
+ function CropModal({ imageSrc, onClose, onSave, }) {
6
5
  const [croppedAreaPixels, setCroppedAreaPixels] = React.useState(null);
7
6
  const handleSaveCrop = React.useCallback(async () => {
8
7
  if (!croppedAreaPixels)
@@ -18,11 +17,11 @@ function AnnotationModal({ imageSrc, onClose, onSave, }) {
18
17
  return (React.createElement("div", { className: "modal is-active" },
19
18
  React.createElement("div", { className: "modal-background-faded" }),
20
19
  React.createElement("div", { className: "ob-crop ob-border-radius" },
21
- React.createElement("div", { ref: annotationContentElementRef, className: "ob-crop__content ob-border-radius" },
20
+ React.createElement("div", { className: "ob-crop__content ob-border-radius" },
22
21
  React.createElement(ImageCropper, { imgSrc: imageSrc, onCropComplete: setCroppedAreaPixels })),
23
22
  React.createElement("div", { className: "ob-annotation__buttons ob-annotation__buttons-actions" },
24
23
  React.createElement("button", { type: "button", className: "button is-light ob-button ob-annotation__button ob-annotation__button-action cypress-crop-cancel-button", onClick: onClose }, "Cancel"),
25
24
  React.createElement("button", { type: "button", className: "button is-primary ob-button ob-annotation__button ob-annotation__button-action cypress-crop-save-button", disabled: !croppedAreaPixels, onClick: handleSaveCrop }, "Save")))));
26
25
  }
27
- export default React.memo(AnnotationModal);
26
+ export default React.memo(CropModal);
28
27
  //# sourceMappingURL=CropModal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CropModal.js","sourceRoot":"","sources":["../../../src/components/ImageCropper/CropModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,YAAY,MAAM,GAAG,CAAA;AAE5B,OAAO,gBAAgB,MAAM,kCAAkC,CAAA;AAE/D,SAAS,eAAe,CAAC,EACvB,QAAQ,EACR,OAAO,EACP,MAAM,GAKP;IACC,MAAM,2BAA2B,GAAG,KAAK,CAAC,MAAM,CAAiB,IAAI,CAAC,CAAA;IAEtE,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAC9D,IAAI,CACL,CAAA;IAED,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;QAClD,IAAI,CAAC,iBAAiB;YAAE,OAAM;QAE9B,MAAM,CAAC,iBAAiB,CAAC,CAAA;IAC3B,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAA;IAE/B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,gBAAgB,CAAC,gBAAgB,EAAE,CAAA;QAEnC,OAAO,GAAG,EAAE;YACV,gBAAgB,CAAC,eAAe,EAAE,CAAA;QACpC,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CACL,6BAAK,SAAS,EAAC,iBAAiB;QAC9B,6BAAK,SAAS,EAAC,wBAAwB,GAAO;QAC9C,6BAAK,SAAS,EAAC,0BAA0B;YACvC,6BACE,GAAG,EAAE,2BAA2B,EAChC,SAAS,EAAC,mCAAmC;gBAE7C,oBAAC,YAAY,IACX,MAAM,EAAE,QAAQ,EAChB,cAAc,EAAE,oBAAoB,GACpC,CACE;YACN,6BAAK,SAAS,EAAC,uDAAuD;gBACpE,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,yGAAyG,EACnH,OAAO,EAAE,OAAO,aAGT;gBACT,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,yGAAyG,EACnH,QAAQ,EAAE,CAAC,iBAAiB,EAC5B,OAAO,EAAE,cAAc,WAGhB,CACL,CACF,CACF,CACP,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport ImageCropper from '.'\nimport { Area } from 'react-easy-crop'\nimport scrollingService from '../../services/scrolling-service'\n\nfunction AnnotationModal({\n imageSrc,\n onClose,\n onSave,\n}: {\n imageSrc: string\n onClose: () => void\n onSave: (imageArea: Area) => void\n}) {\n const annotationContentElementRef = React.useRef<HTMLDivElement>(null)\n\n const [croppedAreaPixels, setCroppedAreaPixels] = React.useState<Area | null>(\n null,\n )\n\n const handleSaveCrop = React.useCallback(async () => {\n if (!croppedAreaPixels) return\n\n onSave(croppedAreaPixels)\n }, [croppedAreaPixels, onSave])\n\n React.useEffect(() => {\n scrollingService.disableScrolling()\n\n return () => {\n scrollingService.enableScrolling()\n }\n }, [])\n\n return (\n <div className=\"modal is-active\">\n <div className=\"modal-background-faded\"></div>\n <div className=\"ob-crop ob-border-radius\">\n <div\n ref={annotationContentElementRef}\n className=\"ob-crop__content ob-border-radius\"\n >\n <ImageCropper\n imgSrc={imageSrc}\n onCropComplete={setCroppedAreaPixels}\n />\n </div>\n <div className=\"ob-annotation__buttons ob-annotation__buttons-actions\">\n <button\n type=\"button\"\n className=\"button is-light ob-button ob-annotation__button ob-annotation__button-action cypress-crop-cancel-button\"\n onClick={onClose}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"button is-primary ob-button ob-annotation__button ob-annotation__button-action cypress-crop-save-button\"\n disabled={!croppedAreaPixels}\n onClick={handleSaveCrop}\n >\n Save\n </button>\n </div>\n </div>\n </div>\n )\n}\n\nexport default React.memo(AnnotationModal)\n"]}
1
+ {"version":3,"file":"CropModal.js","sourceRoot":"","sources":["../../../src/components/ImageCropper/CropModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,YAAY,MAAM,GAAG,CAAA;AAE5B,OAAO,gBAAgB,MAAM,kCAAkC,CAAA;AAE/D,SAAS,SAAS,CAAC,EACjB,QAAQ,EACR,OAAO,EACP,MAAM,GAKP;IACC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAC9D,IAAI,CACL,CAAA;IAED,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;QAClD,IAAI,CAAC,iBAAiB;YAAE,OAAM;QAE9B,MAAM,CAAC,iBAAiB,CAAC,CAAA;IAC3B,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAA;IAE/B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,gBAAgB,CAAC,gBAAgB,EAAE,CAAA;QAEnC,OAAO,GAAG,EAAE;YACV,gBAAgB,CAAC,eAAe,EAAE,CAAA;QACpC,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CACL,6BAAK,SAAS,EAAC,iBAAiB;QAC9B,6BAAK,SAAS,EAAC,wBAAwB,GAAO;QAC9C,6BAAK,SAAS,EAAC,0BAA0B;YACvC,6BAAK,SAAS,EAAC,mCAAmC;gBAChD,oBAAC,YAAY,IACX,MAAM,EAAE,QAAQ,EAChB,cAAc,EAAE,oBAAoB,GACpC,CACE;YACN,6BAAK,SAAS,EAAC,uDAAuD;gBACpE,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,yGAAyG,EACnH,OAAO,EAAE,OAAO,aAGT;gBACT,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,yGAAyG,EACnH,QAAQ,EAAE,CAAC,iBAAiB,EAC5B,OAAO,EAAE,cAAc,WAGhB,CACL,CACF,CACF,CACP,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport ImageCropper from '.'\nimport { Area } from 'react-easy-crop'\nimport scrollingService from '../../services/scrolling-service'\n\nfunction CropModal({\n imageSrc,\n onClose,\n onSave,\n}: {\n imageSrc: string\n onClose: () => void\n onSave: (imageArea: Area) => void\n}) {\n const [croppedAreaPixels, setCroppedAreaPixels] = React.useState<Area | null>(\n null,\n )\n\n const handleSaveCrop = React.useCallback(async () => {\n if (!croppedAreaPixels) return\n\n onSave(croppedAreaPixels)\n }, [croppedAreaPixels, onSave])\n\n React.useEffect(() => {\n scrollingService.disableScrolling()\n\n return () => {\n scrollingService.enableScrolling()\n }\n }, [])\n\n return (\n <div className=\"modal is-active\">\n <div className=\"modal-background-faded\"></div>\n <div className=\"ob-crop ob-border-radius\">\n <div className=\"ob-crop__content ob-border-radius\">\n <ImageCropper\n imgSrc={imageSrc}\n onCropComplete={setCroppedAreaPixels}\n />\n </div>\n <div className=\"ob-annotation__buttons ob-annotation__buttons-actions\">\n <button\n type=\"button\"\n className=\"button is-light ob-button ob-annotation__button ob-annotation__button-action cypress-crop-cancel-button\"\n onClick={onClose}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"button is-primary ob-button ob-annotation__button ob-annotation__button-action cypress-crop-save-button\"\n disabled={!croppedAreaPixels}\n onClick={handleSaveCrop}\n >\n Save\n </button>\n </div>\n </div>\n </div>\n )\n}\n\nexport default React.memo(CropModal)\n"]}
@@ -14,8 +14,17 @@ export declare const getAspectRatio: ({ width, height, }: {
14
14
  width: number;
15
15
  height: number;
16
16
  }) => number;
17
- export declare const generateCroppedImageBlob: ({ croppedAreaPixels, imgSrc, fileType, }: {
17
+ export declare const generateCroppedImageBlob: ({ croppedAreaPixels, imgSrc, size, fileType, }: {
18
18
  croppedAreaPixels: Area;
19
19
  imgSrc: string;
20
+ /**
21
+ * If provided, the cropped image will be resized to the given size. If not
22
+ * provided, the cropped image will be the same size as the cropped portion of
23
+ * the source image.
24
+ */
25
+ size?: {
26
+ width: number;
27
+ height: number;
28
+ };
20
29
  fileType?: string;
21
30
  }) => Promise<Blob | null>;
@@ -4,7 +4,6 @@ import { CropContainer, ZoomSlider, SLIDER_WHEEL_INTERVAL_VALUE, } from './resou
4
4
  const defaultZoom = 1;
5
5
  const defaultCrop = { x: 0, y: 0 };
6
6
  const emptyFn = () => { };
7
- // 2. Fix up styling and classes
8
7
  const ImageCropper = ({ imgSrc, disabled, onCropComplete, outputAspectRatio, zoomWithScroll, cropperStyles, cropperHeight, }) => {
9
8
  const [crop, setCrop] = React.useState(defaultCrop);
10
9
  const [zoom, setZoom] = React.useState(defaultZoom);
@@ -59,10 +58,8 @@ const createImage = (url) => {
59
58
  return image;
60
59
  });
61
60
  };
62
- export const generateCroppedImageBlob = async ({ croppedAreaPixels, imgSrc,
63
- // width,
64
- // height,
65
- fileType, }) => {
61
+ export const generateCroppedImageBlob = async ({ croppedAreaPixels, imgSrc, size, fileType, }) => {
62
+ var _a, _b, _c, _d;
66
63
  if (!croppedAreaPixels || !imgSrc) {
67
64
  return null;
68
65
  }
@@ -82,8 +79,8 @@ fileType, }) => {
82
79
  if (!croppedCtx) {
83
80
  return null;
84
81
  }
85
- croppedCanvas.width = croppedAreaPixels.width;
86
- croppedCanvas.height = croppedAreaPixels.height;
82
+ croppedCanvas.width = (_a = size === null || size === void 0 ? void 0 : size.width) !== null && _a !== void 0 ? _a : croppedAreaPixels.width;
83
+ croppedCanvas.height = (_b = size === null || size === void 0 ? void 0 : size.height) !== null && _b !== void 0 ? _b : croppedAreaPixels.height;
87
84
  // Draw the cropped source image onto the destination canvas
88
85
  croppedCtx.drawImage(canvas,
89
86
  // source x
@@ -99,9 +96,9 @@ fileType, }) => {
99
96
  // destination y
100
97
  0,
101
98
  // destination width
102
- croppedAreaPixels.width,
99
+ (_c = size === null || size === void 0 ? void 0 : size.width) !== null && _c !== void 0 ? _c : croppedAreaPixels.width,
103
100
  // destination height
104
- croppedAreaPixels.height);
101
+ (_d = size === null || size === void 0 ? void 0 : size.height) !== null && _d !== void 0 ? _d : croppedAreaPixels.height);
105
102
  return new Promise((resolve) => {
106
103
  croppedCanvas.toBlob((file) => {
107
104
  resolve(file);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ImageCropper/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { memo, useMemo } from 'react'\nimport Cropper, { Area, Point, CropperProps } from 'react-easy-crop'\nimport {\n CropContainer,\n ZoomSlider,\n SLIDER_WHEEL_INTERVAL_VALUE,\n} from './resource-components'\n\nconst defaultZoom = 1\nconst defaultCrop = { x: 0, y: 0 }\n\nconst emptyFn = () => {}\n\n// 2. Fix up styling and classes\nconst ImageCropper = ({\n imgSrc,\n disabled,\n onCropComplete,\n outputAspectRatio,\n zoomWithScroll,\n cropperStyles,\n cropperHeight,\n}: {\n imgSrc: string\n disabled?: boolean\n onCropComplete: (croppedAreaPixels: Area) => void\n outputAspectRatio?: number\n zoomWithScroll?: boolean\n cropperStyles?: CropperProps['style']\n cropperHeight?: number\n}) => {\n const [crop, setCrop] = React.useState<Point>(defaultCrop)\n const [zoom, setZoom] = React.useState(defaultZoom)\n const [image, setImage] = React.useState<HTMLImageElement | null>(null)\n\n React.useEffect(() => {\n if (outputAspectRatio) {\n // If we have a desired aspect ratio, we dont need to get it from the current image\n return\n }\n createImage(imgSrc)\n .then(setImage)\n .catch((error) => {\n console.error(\n 'Error loading image to get aspect ratio for cropping',\n error,\n )\n })\n }, [outputAspectRatio, imgSrc])\n\n const calculatedAspectRatio = useMemo(() => {\n if (outputAspectRatio) {\n return outputAspectRatio\n }\n if (image) {\n return getAspectRatio({\n width: image.width,\n height: image.height,\n })\n }\n }, [outputAspectRatio, image])\n\n return (\n <div className=\"ob-cropper__container\">\n <CropContainer\n className=\"ob-cropper__cropper-wrapper\"\n height={cropperHeight}\n >\n <Cropper\n image={imgSrc}\n crop={crop}\n zoom={zoom}\n aspect={calculatedAspectRatio}\n onCropChange={disabled ? emptyFn : setCrop}\n onCropComplete={(...args) => {\n if (disabled) {\n return\n }\n onCropComplete(args[1])\n }}\n onZoomChange={setZoom}\n zoomSpeed={SLIDER_WHEEL_INTERVAL_VALUE}\n zoomWithScroll={zoomWithScroll}\n classes={{\n containerClassName: 'ob-border-radius',\n }}\n style={cropperStyles}\n />\n </CropContainer>\n <div className=\"ob-cropper__zoom-slider-wrapper\">\n <ZoomSlider value={zoom} setValue={setZoom} disabled={disabled} />\n </div>\n </div>\n )\n}\n\nexport default memo(ImageCropper)\n\nexport const getAspectRatio = ({\n width,\n height,\n}: {\n width: number\n height: number\n}) => width / height\n\nconst createImage = (url: string): Promise<HTMLImageElement> => {\n return new Promise((resolve, reject) => {\n const image = new Image()\n image.onload = () => {\n resolve(image)\n }\n image.onerror = (error) => {\n reject(error)\n }\n image.src = url\n return image\n })\n}\n\nexport const generateCroppedImageBlob = async ({\n croppedAreaPixels,\n imgSrc,\n // width,\n // height,\n fileType,\n}: {\n croppedAreaPixels: Area\n imgSrc: string\n // width: number\n // height: number\n fileType?: string\n}): Promise<Blob | null> => {\n if (!croppedAreaPixels || !imgSrc) {\n return null\n }\n // Source image/canvas\n const image = await createImage(imgSrc)\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx) {\n return null\n }\n canvas.width = image.width\n canvas.height = image.height\n ctx.drawImage(image, 0, 0)\n\n // Destination image/canvas\n const croppedCanvas = document.createElement('canvas')\n const croppedCtx = croppedCanvas.getContext('2d')\n if (!croppedCtx) {\n return null\n }\n croppedCanvas.width = croppedAreaPixels.width\n croppedCanvas.height = croppedAreaPixels.height\n\n // Draw the cropped source image onto the destination canvas\n croppedCtx.drawImage(\n canvas,\n // source x\n croppedAreaPixels.x,\n // source y\n croppedAreaPixels.y,\n // source width\n croppedAreaPixels.width,\n // source height\n croppedAreaPixels.height,\n // destination x\n 0,\n // destination y\n 0,\n // destination width\n croppedAreaPixels.width,\n // destination height\n croppedAreaPixels.height,\n )\n\n return new Promise((resolve) => {\n croppedCanvas.toBlob((file) => {\n resolve(file)\n }, fileType)\n })\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ImageCropper/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { memo, useMemo } from 'react'\nimport Cropper, { Area, Point, CropperProps } from 'react-easy-crop'\nimport {\n CropContainer,\n ZoomSlider,\n SLIDER_WHEEL_INTERVAL_VALUE,\n} from './resource-components'\n\nconst defaultZoom = 1\nconst defaultCrop = { x: 0, y: 0 }\n\nconst emptyFn = () => {}\n\nconst ImageCropper = ({\n imgSrc,\n disabled,\n onCropComplete,\n outputAspectRatio,\n zoomWithScroll,\n cropperStyles,\n cropperHeight,\n}: {\n imgSrc: string\n disabled?: boolean\n onCropComplete: (croppedAreaPixels: Area) => void\n outputAspectRatio?: number\n zoomWithScroll?: boolean\n cropperStyles?: CropperProps['style']\n cropperHeight?: number\n}) => {\n const [crop, setCrop] = React.useState<Point>(defaultCrop)\n const [zoom, setZoom] = React.useState(defaultZoom)\n const [image, setImage] = React.useState<HTMLImageElement | null>(null)\n\n React.useEffect(() => {\n if (outputAspectRatio) {\n // If we have a desired aspect ratio, we dont need to get it from the current image\n return\n }\n createImage(imgSrc)\n .then(setImage)\n .catch((error) => {\n console.error(\n 'Error loading image to get aspect ratio for cropping',\n error,\n )\n })\n }, [outputAspectRatio, imgSrc])\n\n const calculatedAspectRatio = useMemo(() => {\n if (outputAspectRatio) {\n return outputAspectRatio\n }\n if (image) {\n return getAspectRatio({\n width: image.width,\n height: image.height,\n })\n }\n }, [outputAspectRatio, image])\n\n return (\n <div className=\"ob-cropper__container\">\n <CropContainer\n className=\"ob-cropper__cropper-wrapper\"\n height={cropperHeight}\n >\n <Cropper\n image={imgSrc}\n crop={crop}\n zoom={zoom}\n aspect={calculatedAspectRatio}\n onCropChange={disabled ? emptyFn : setCrop}\n onCropComplete={(...args) => {\n if (disabled) {\n return\n }\n onCropComplete(args[1])\n }}\n onZoomChange={setZoom}\n zoomSpeed={SLIDER_WHEEL_INTERVAL_VALUE}\n zoomWithScroll={zoomWithScroll}\n classes={{\n containerClassName: 'ob-border-radius',\n }}\n style={cropperStyles}\n />\n </CropContainer>\n <div className=\"ob-cropper__zoom-slider-wrapper\">\n <ZoomSlider value={zoom} setValue={setZoom} disabled={disabled} />\n </div>\n </div>\n )\n}\n\nexport default memo(ImageCropper)\n\nexport const getAspectRatio = ({\n width,\n height,\n}: {\n width: number\n height: number\n}) => width / height\n\nconst createImage = (url: string): Promise<HTMLImageElement> => {\n return new Promise((resolve, reject) => {\n const image = new Image()\n image.onload = () => {\n resolve(image)\n }\n image.onerror = (error) => {\n reject(error)\n }\n image.src = url\n return image\n })\n}\n\nexport const generateCroppedImageBlob = async ({\n croppedAreaPixels,\n imgSrc,\n size,\n fileType,\n}: {\n croppedAreaPixels: Area\n imgSrc: string\n /**\n * If provided, the cropped image will be resized to the given size. If not\n * provided, the cropped image will be the same size as the cropped portion of\n * the source image.\n */\n size?: {\n width: number\n height: number\n }\n fileType?: string\n}): Promise<Blob | null> => {\n if (!croppedAreaPixels || !imgSrc) {\n return null\n }\n // Source image/canvas\n const image = await createImage(imgSrc)\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx) {\n return null\n }\n canvas.width = image.width\n canvas.height = image.height\n ctx.drawImage(image, 0, 0)\n\n // Destination image/canvas\n const croppedCanvas = document.createElement('canvas')\n const croppedCtx = croppedCanvas.getContext('2d')\n if (!croppedCtx) {\n return null\n }\n croppedCanvas.width = size?.width ?? croppedAreaPixels.width\n croppedCanvas.height = size?.height ?? croppedAreaPixels.height\n\n // Draw the cropped source image onto the destination canvas\n croppedCtx.drawImage(\n canvas,\n // source x\n croppedAreaPixels.x,\n // source y\n croppedAreaPixels.y,\n // source width\n croppedAreaPixels.width,\n // source height\n croppedAreaPixels.height,\n // destination x\n 0,\n // destination y\n 0,\n // destination width\n size?.width ?? croppedAreaPixels.width,\n // destination height\n size?.height ?? croppedAreaPixels.height,\n )\n\n return new Promise((resolve) => {\n croppedCanvas.toBlob((file) => {\n resolve(file)\n }, fileType)\n })\n}\n"]}
@@ -99,7 +99,7 @@ const FormElementFile = ({ element, onRemove, file, onChange, disableUpload, ind
99
99
  }
100
100
  }, [file, onChange]);
101
101
  return (React.createElement(React.Fragment, null,
102
- React.createElement(FileCard, { element: element, isUploading: isUploading, isUploadPaused: disableUpload, uploadErrorMessage: uploadErrorMessage, loadAttachmentUrlError: loadAttachmentUrlError, isLoadingAttachmentUrl: isLoadingAttachmentUrl || state.isLoading, attachmentUrl: attachmentUrl, isContentTypeImage: isContentTypeImage, fileName: file.fileName, onDownload: canDownload ? handleDownload : undefined, onRemove: handleRemove, onRetry: handleRetry, progress: progress, index: index, onAnnotate: setIsAnnotating, onCrop: setIsCropping }),
102
+ React.createElement(FileCard, { element: element, isUploading: isUploading, isUploadPaused: disableUpload, uploadErrorMessage: uploadErrorMessage, loadAttachmentUrlError: loadAttachmentUrlError, isLoadingAttachmentUrl: isLoadingAttachmentUrl || state.isLoading, attachmentUrl: attachmentUrl, isContentTypeImage: isContentTypeImage, fileName: file.fileName, onDownload: canDownload ? handleDownload : undefined, onRemove: handleRemove, onRetry: handleRetry, progress: progress, index: index, onAnnotate: isContentTypeImage ? setIsAnnotating : undefined, onCrop: isContentTypeImage ? setIsCropping : undefined }),
103
103
  isCropping && attachmentUrl && (React.createElement(CropModal, { imageSrc: attachmentUrl, onClose: clearIsCropping, onSave: handleSaveCrop })),
104
104
  isAnnotating && attachmentUrl && (React.createElement(AnnotationModal, { imageSrc: attachmentUrl, onClose: clearIsAnnotating, onSave: handleAnnotate })),
105
105
  state.error && (React.createElement(Modal, { isOpen: true, title: "Whoops...", className: "cypress-error-modal", titleClassName: "cypress-error-title", actions: React.createElement("button", { type: "button", className: "button ob-button is-primary cypress-close-error-button", onClick: () => setState({ isLoading: false }), autoFocus: true }, "Okay") },
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementFile.js","sourceRoot":"","sources":["../../src/form-elements/FormElementFile.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport downloadAttachment from '../services/download-file'\nimport { FormTypes } from '@oneblink/types'\nimport useAttachment, { OnChange } from '../hooks/attachments/useAttachment'\nimport FileCard from '../components/renderer/attachments/FileCard'\nimport { attachmentsService } from '@oneblink/apps'\nimport useBooleanState from '../hooks/useBooleanState'\nimport CropModal from '../components/ImageCropper/CropModal'\nimport AnnotationModal, {\n superimposeAnnotationOnImage,\n} from '../components/renderer/AnnotationModal'\nimport { Area } from 'react-easy-crop'\nimport { generateCroppedImageBlob } from '../components/ImageCropper'\nimport { prepareNewAttachment } from '../services/attachments'\nimport Modal from '../components/renderer/Modal'\n\ntype Props = {\n element: FormTypes.FilesElement\n /** If set to `undefined`, the remove button will be hidden */\n onRemove: ((id: string) => void) | undefined\n file: attachmentsService.Attachment\n disableUpload: boolean\n onChange: OnChange\n index: number\n}\n\nconst FormElementFile = ({\n element,\n onRemove,\n file,\n onChange,\n disableUpload,\n index,\n}: Props) => {\n const [isAnnotating, setIsAnnotating, clearIsAnnotating] =\n useBooleanState(false)\n const [isCropping, setIsCropping, clearIsCropping] = useBooleanState(false)\n const [state, setState] = React.useState<{\n isLoading: boolean\n error?: Error\n }>({\n isLoading: false,\n error: undefined,\n })\n const {\n attachmentUrl,\n contentType,\n isUploading,\n uploadErrorMessage,\n isLoadingAttachmentUrl,\n loadAttachmentUrlError,\n isContentTypeImage,\n canDownload,\n progress,\n } = useAttachment(file, element, onChange, disableUpload)\n\n const handleRemove = React.useMemo(() => {\n if (!onRemove) {\n return\n }\n return () => {\n if (!file.type) {\n return onRemove(file.id)\n }\n return onRemove(file._id)\n }\n }, [file, onRemove])\n\n const handleDownload = React.useCallback(async () => {\n await downloadAttachment(file)\n }, [file])\n\n const handleAnnotate = React.useCallback(\n async (annotationDataUri: string) => {\n if (!attachmentUrl || file.type) return\n clearIsAnnotating()\n\n setState({\n isLoading: true,\n })\n\n try {\n const blob = await superimposeAnnotationOnImage({\n annotationDataUri,\n attachmentUrl,\n })\n setState({\n isLoading: false,\n })\n if (!blob) return\n const attachment = prepareNewAttachment(blob, file.fileName, element)\n onChange(file.id, attachment)\n } catch (error) {\n setState({\n error: error as Error,\n isLoading: false,\n })\n }\n },\n [attachmentUrl, clearIsAnnotating, element, file, onChange],\n )\n const handleSaveCrop = React.useCallback(\n async (croppedAreaPixels: Area) => {\n if (!attachmentUrl || file.type) return\n clearIsCropping()\n\n setState({\n isLoading: true,\n })\n\n try {\n const croppedImage = await generateCroppedImageBlob({\n croppedAreaPixels,\n imgSrc: attachmentUrl,\n fileType: contentType,\n })\n setState({\n isLoading: false,\n })\n if (!croppedImage) return\n const attachment = prepareNewAttachment(\n croppedImage,\n file.fileName,\n element,\n )\n onChange(file.id, attachment)\n } catch (error) {\n setState({\n error: error as Error,\n isLoading: false,\n })\n }\n },\n [attachmentUrl, clearIsCropping, contentType, element, file, onChange],\n )\n const handleRetry = React.useMemo(() => {\n if (file.type === 'ERROR' && file.data) {\n return () => {\n onChange(file._id, {\n type: 'NEW',\n _id: file._id,\n data: file.data,\n fileName: file.fileName,\n isPrivate: file.isPrivate,\n })\n }\n }\n }, [file, onChange])\n\n return (\n <>\n <FileCard\n element={element}\n isUploading={isUploading}\n isUploadPaused={disableUpload}\n uploadErrorMessage={uploadErrorMessage}\n loadAttachmentUrlError={loadAttachmentUrlError}\n isLoadingAttachmentUrl={isLoadingAttachmentUrl || state.isLoading}\n attachmentUrl={attachmentUrl}\n isContentTypeImage={isContentTypeImage}\n fileName={file.fileName}\n onDownload={canDownload ? handleDownload : undefined}\n onRemove={handleRemove}\n onRetry={handleRetry}\n progress={progress}\n index={index}\n onAnnotate={setIsAnnotating}\n onCrop={setIsCropping}\n />\n {isCropping && attachmentUrl && (\n <CropModal\n imageSrc={attachmentUrl}\n onClose={clearIsCropping}\n onSave={handleSaveCrop}\n />\n )}\n {isAnnotating && attachmentUrl && (\n <AnnotationModal\n imageSrc={attachmentUrl}\n onClose={clearIsAnnotating}\n onSave={handleAnnotate}\n />\n )}\n {state.error && (\n <Modal\n isOpen\n title=\"Whoops...\"\n className=\"cypress-error-modal\"\n titleClassName=\"cypress-error-title\"\n actions={\n <button\n type=\"button\"\n className=\"button ob-button is-primary cypress-close-error-button\"\n onClick={() => setState({ isLoading: false })}\n autoFocus\n >\n Okay\n </button>\n }\n >\n <p>\n An error occurred while attempting to edit an image. Please click{' '}\n <b>Okay</b> below to try again. If the problem persists, please\n contact support.\n </p>\n\n <div className=\"content has-margin-top-6\">\n <blockquote>{state.error.toString()}</blockquote>\n </div>\n </Modal>\n )}\n </>\n )\n}\n\nexport default React.memo<Props>(FormElementFile)\n"]}
1
+ {"version":3,"file":"FormElementFile.js","sourceRoot":"","sources":["../../src/form-elements/FormElementFile.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport downloadAttachment from '../services/download-file'\nimport { FormTypes } from '@oneblink/types'\nimport useAttachment, { OnChange } from '../hooks/attachments/useAttachment'\nimport FileCard from '../components/renderer/attachments/FileCard'\nimport { attachmentsService } from '@oneblink/apps'\nimport useBooleanState from '../hooks/useBooleanState'\nimport CropModal from '../components/ImageCropper/CropModal'\nimport AnnotationModal, {\n superimposeAnnotationOnImage,\n} from '../components/renderer/AnnotationModal'\nimport { Area } from 'react-easy-crop'\nimport { generateCroppedImageBlob } from '../components/ImageCropper'\nimport { prepareNewAttachment } from '../services/attachments'\nimport Modal from '../components/renderer/Modal'\n\ntype Props = {\n element: FormTypes.FilesElement\n /** If set to `undefined`, the remove button will be hidden */\n onRemove: ((id: string) => void) | undefined\n file: attachmentsService.Attachment\n disableUpload: boolean\n onChange: OnChange\n index: number\n}\n\nconst FormElementFile = ({\n element,\n onRemove,\n file,\n onChange,\n disableUpload,\n index,\n}: Props) => {\n const [isAnnotating, setIsAnnotating, clearIsAnnotating] =\n useBooleanState(false)\n const [isCropping, setIsCropping, clearIsCropping] = useBooleanState(false)\n const [state, setState] = React.useState<{\n isLoading: boolean\n error?: Error\n }>({\n isLoading: false,\n error: undefined,\n })\n const {\n attachmentUrl,\n contentType,\n isUploading,\n uploadErrorMessage,\n isLoadingAttachmentUrl,\n loadAttachmentUrlError,\n isContentTypeImage,\n canDownload,\n progress,\n } = useAttachment(file, element, onChange, disableUpload)\n\n const handleRemove = React.useMemo(() => {\n if (!onRemove) {\n return\n }\n return () => {\n if (!file.type) {\n return onRemove(file.id)\n }\n return onRemove(file._id)\n }\n }, [file, onRemove])\n\n const handleDownload = React.useCallback(async () => {\n await downloadAttachment(file)\n }, [file])\n\n const handleAnnotate = React.useCallback(\n async (annotationDataUri: string) => {\n if (!attachmentUrl || file.type) return\n clearIsAnnotating()\n\n setState({\n isLoading: true,\n })\n\n try {\n const blob = await superimposeAnnotationOnImage({\n annotationDataUri,\n attachmentUrl,\n })\n setState({\n isLoading: false,\n })\n if (!blob) return\n const attachment = prepareNewAttachment(blob, file.fileName, element)\n onChange(file.id, attachment)\n } catch (error) {\n setState({\n error: error as Error,\n isLoading: false,\n })\n }\n },\n [attachmentUrl, clearIsAnnotating, element, file, onChange],\n )\n const handleSaveCrop = React.useCallback(\n async (croppedAreaPixels: Area) => {\n if (!attachmentUrl || file.type) return\n clearIsCropping()\n\n setState({\n isLoading: true,\n })\n\n try {\n const croppedImage = await generateCroppedImageBlob({\n croppedAreaPixels,\n imgSrc: attachmentUrl,\n fileType: contentType,\n })\n setState({\n isLoading: false,\n })\n if (!croppedImage) return\n const attachment = prepareNewAttachment(\n croppedImage,\n file.fileName,\n element,\n )\n onChange(file.id, attachment)\n } catch (error) {\n setState({\n error: error as Error,\n isLoading: false,\n })\n }\n },\n [attachmentUrl, clearIsCropping, contentType, element, file, onChange],\n )\n const handleRetry = React.useMemo(() => {\n if (file.type === 'ERROR' && file.data) {\n return () => {\n onChange(file._id, {\n type: 'NEW',\n _id: file._id,\n data: file.data,\n fileName: file.fileName,\n isPrivate: file.isPrivate,\n })\n }\n }\n }, [file, onChange])\n\n return (\n <>\n <FileCard\n element={element}\n isUploading={isUploading}\n isUploadPaused={disableUpload}\n uploadErrorMessage={uploadErrorMessage}\n loadAttachmentUrlError={loadAttachmentUrlError}\n isLoadingAttachmentUrl={isLoadingAttachmentUrl || state.isLoading}\n attachmentUrl={attachmentUrl}\n isContentTypeImage={isContentTypeImage}\n fileName={file.fileName}\n onDownload={canDownload ? handleDownload : undefined}\n onRemove={handleRemove}\n onRetry={handleRetry}\n progress={progress}\n index={index}\n onAnnotate={isContentTypeImage ? setIsAnnotating : undefined}\n onCrop={isContentTypeImage ? setIsCropping : undefined}\n />\n {isCropping && attachmentUrl && (\n <CropModal\n imageSrc={attachmentUrl}\n onClose={clearIsCropping}\n onSave={handleSaveCrop}\n />\n )}\n {isAnnotating && attachmentUrl && (\n <AnnotationModal\n imageSrc={attachmentUrl}\n onClose={clearIsAnnotating}\n onSave={handleAnnotate}\n />\n )}\n {state.error && (\n <Modal\n isOpen\n title=\"Whoops...\"\n className=\"cypress-error-modal\"\n titleClassName=\"cypress-error-title\"\n actions={\n <button\n type=\"button\"\n className=\"button ob-button is-primary cypress-close-error-button\"\n onClick={() => setState({ isLoading: false })}\n autoFocus\n >\n Okay\n </button>\n }\n >\n <p>\n An error occurred while attempting to edit an image. Please click{' '}\n <b>Okay</b> below to try again. If the problem persists, please\n contact support.\n </p>\n\n <div className=\"content has-margin-top-6\">\n <blockquote>{state.error.toString()}</blockquote>\n </div>\n </Modal>\n )}\n </>\n )\n}\n\nexport default React.memo<Props>(FormElementFile)\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oneblink/apps-react",
3
3
  "description": "Helper functions for OneBlink apps in ReactJS.",
4
- "version": "8.10.0-alpha.2",
4
+ "version": "8.10.0-beta.1",
5
5
  "author": "OneBlink <developers@oneblink.io> (https://oneblink.io)",
6
6
  "bugs": {
7
7
  "url": "https://github.com/oneblink/apps-react/issues"