@mittwald/flow-react-components 0.2.0-alpha.871 → 0.2.0-alpha.873

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.
@@ -210,6 +210,7 @@ import './packages/components/src/components/IllustratedMessage/IllustratedMessa
210
210
  import './packages/components/src/components/Image/Image.mjs';
211
211
  import 'react-easy-crop';
212
212
  import './packages/components/src/components/Slider/Slider.mjs';
213
+ import 'use-debounce';
213
214
  import './packages/components/src/components/Initials/Initials.mjs';
214
215
  export { IntlProvider } from './packages/components/src/components/IntlProvider/IntlProvider.mjs';
215
216
  import './packages/components/src/components/LayoutCard/LayoutCard.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"flr-universal.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"flr-universal.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
  /* */
3
3
  import { jsxs, jsx } from 'react/jsx-runtime';
4
- import { useState, useEffectEvent, useEffect } from 'react';
4
+ import { useState, useEffect } from 'react';
5
5
  import Cropper from 'react-easy-crop';
6
6
  import clsx from 'clsx';
7
7
  import styles from './ImageCropper.module.scss.mjs';
@@ -10,6 +10,7 @@ import { getCroppedImageFile } from './lib/getCroppedImageFile.mjs';
10
10
  import { useLocalizedStringFormatter } from '../TranslationProvider/useLocalizedStringFormatter.mjs';
11
11
  import locales from '../../../../../_virtual/_.locale.json@849e6f494125ee27df10a461562fa893.mjs';
12
12
  import { useImageSrc } from '../../lib/hooks/useImageSrc.mjs';
13
+ import { useDebouncedCallback } from 'use-debounce';
13
14
 
14
15
  const ImageCropper = (props) => {
15
16
  const {
@@ -22,25 +23,31 @@ const ImageCropper = (props) => {
22
23
  ...rest
23
24
  } = props;
24
25
  const imageSrc = useImageSrc(image);
26
+ const [mediaLoaded, setMediaLoaded] = useState(false);
25
27
  const [crop, setCrop] = useState({ x: 0, y: 0 });
26
28
  const [zoom, setZoom] = useState(1);
27
- const [croppedAreaPixels, setCroppedAreaPixels] = useState();
28
- const rootClassName = clsx(styles.imageCropper, className);
29
29
  const stringFormatter = useLocalizedStringFormatter(locales, "ImageCropper");
30
- const onCropAreaPixelsChange = useEffectEvent(async () => {
31
- if (croppedAreaPixels) {
30
+ const rootClassName = clsx(styles.imageCropper, className);
31
+ const debouncedCropComplete = useDebouncedCallback(
32
+ async (croppedAreaPixels) => {
33
+ if (!croppedAreaPixels) {
34
+ return;
35
+ }
32
36
  const croppedImageFile = await getCroppedImageFile(
33
37
  imageSrc,
38
+ image ?? "",
34
39
  croppedAreaPixels
35
40
  );
36
- if (onCropComplete) {
37
- onCropComplete(croppedImageFile);
38
- }
41
+ onCropComplete?.(croppedImageFile);
42
+ },
43
+ 500,
44
+ {
45
+ leading: true
39
46
  }
40
- });
47
+ );
41
48
  useEffect(() => {
42
- void onCropAreaPixelsChange();
43
- }, [croppedAreaPixels]);
49
+ setMediaLoaded(false);
50
+ }, [imageSrc]);
44
51
  return /* @__PURE__ */ jsxs("div", { className: rootClassName, style: { width }, children: [
45
52
  /* @__PURE__ */ jsx("div", { className: styles.cropperContainer, style: { height }, children: /* @__PURE__ */ jsx(
46
53
  Cropper,
@@ -56,7 +63,12 @@ const ImageCropper = (props) => {
56
63
  onCropChange: setCrop,
57
64
  zoom,
58
65
  onZoomChange: setZoom,
59
- onCropComplete: (_, croppedAreaPixels2) => setCroppedAreaPixels(croppedAreaPixels2),
66
+ onMediaLoaded: () => setMediaLoaded(true),
67
+ onCropComplete: (_, croppedAreaPixels) => {
68
+ if (mediaLoaded) {
69
+ debouncedCropComplete(croppedAreaPixels);
70
+ }
71
+ },
60
72
  ...rest
61
73
  }
62
74
  ) }),
@@ -1 +1 @@
1
- {"version":3,"file":"ImageCropper.mjs","sources":["../../../../../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type FC,\n useEffect,\n useEffectEvent,\n useState,\n} from \"react\";\nimport Cropper, { type Area, type CropperProps } from \"react-easy-crop\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport clsx from \"clsx\";\nimport styles from \"./ImageCropper.module.scss\";\nimport { Slider } from \"@/components/Slider\";\nimport { getCroppedImageFile } from \"@/components/ImageCropper/lib/getCroppedImageFile\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"./locales/*.locale.json\";\nimport { useImageSrc } from \"@/lib/hooks/useImageSrc\";\n\nexport interface ImageCropperProps\n extends PropsWithClassName, Partial<Pick<CropperProps, \"cropShape\">> {\n /** The image file to crop. */\n image?: File | string;\n /** Callback on crop complete. */\n onCropComplete?: (croppedImage: File) => void;\n /** The width of the component. @default 300 */\n width?: CSSProperties[\"width\"];\n /** The height of the component. @default 300 */\n height?: CSSProperties[\"height\"];\n /** The aspect ratio of the crop shape. */\n aspectRatio?: number;\n}\n\n/** @flr-generate all */\nexport const ImageCropper: FC<ImageCropperProps> = (props) => {\n const {\n image,\n className,\n onCropComplete,\n width = 300,\n height = 300,\n aspectRatio,\n ...rest\n } = props;\n\n const imageSrc = useImageSrc(image);\n\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area>();\n\n const rootClassName = clsx(styles.imageCropper, className);\n\n const stringFormatter = useLocalizedStringFormatter(locales, \"ImageCropper\");\n\n const onCropAreaPixelsChange = useEffectEvent(async () => {\n if (croppedAreaPixels) {\n const croppedImageFile = await getCroppedImageFile(\n imageSrc,\n croppedAreaPixels,\n );\n if (onCropComplete) {\n onCropComplete(croppedImageFile);\n }\n }\n });\n\n useEffect(() => {\n void onCropAreaPixelsChange();\n }, [croppedAreaPixels]);\n\n return (\n <div className={rootClassName} style={{ width }}>\n <div className={styles.cropperContainer} style={{ height }}>\n <Cropper\n style={{\n containerStyle: {\n borderRadius: \"calc(var(--image-cropper--corner-radius) - 1px)\",\n },\n }}\n aspect={aspectRatio}\n crop={crop}\n image={imageSrc}\n onCropChange={setCrop}\n zoom={zoom}\n onZoomChange={setZoom}\n onCropComplete={(_, croppedAreaPixels) =>\n setCroppedAreaPixels(croppedAreaPixels)\n }\n {...rest}\n />\n </div>\n <Slider\n minValue={1}\n maxValue={3}\n step={0.01}\n value={zoom}\n sliderOnly\n onChange={(zoom) => setZoom(zoom as number)}\n aria-label={stringFormatter.format(\"zoom\")}\n />\n </div>\n );\n};\n\nexport default ImageCropper;\n"],"names":["croppedAreaPixels","zoom"],"mappings":";;;;;;;;;;;AAgCO,MAAM,YAAA,GAAsC,CAAC,KAAA,KAAU;AAC5D,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,SAAA;AAAA,IACA,cAAA;AAAA,IACA,KAAA,GAAQ,GAAA;AAAA,IACR,MAAA,GAAS,GAAA;AAAA,IACT,WAAA;AAAA,IACA,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,MAAM,QAAA,GAAW,YAAY,KAAK,CAAA;AAElC,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,QAAA,CAAS,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA;AAC/C,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,CAAC,CAAA;AAClC,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,QAAA,EAAe;AAEjE,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc,SAAS,CAAA;AAEzD,EAAA,MAAM,eAAA,GAAkB,2BAAA,CAA4B,OAAA,EAAS,cAAc,CAAA;AAE3E,EAAA,MAAM,sBAAA,GAAyB,eAAe,YAAY;AACxD,IAAA,IAAI,iBAAA,EAAmB;AACrB,MAAA,MAAM,mBAAmB,MAAM,mBAAA;AAAA,QAC7B,QAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,cAAA,CAAe,gBAAgB,CAAA;AAAA,MACjC;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,KAAK,sBAAA,EAAuB;AAAA,EAC9B,CAAA,EAAG,CAAC,iBAAiB,CAAC,CAAA;AAEtB,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,eAAe,KAAA,EAAO,EAAE,OAAM,EAC5C,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,SAAI,SAAA,EAAW,MAAA,CAAO,kBAAkB,KAAA,EAAO,EAAE,QAAO,EACvD,QAAA,kBAAA,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO;AAAA,UACL,cAAA,EAAgB;AAAA,YACd,YAAA,EAAc;AAAA;AAChB,SACF;AAAA,QACA,MAAA,EAAQ,WAAA;AAAA,QACR,IAAA;AAAA,QACA,KAAA,EAAO,QAAA;AAAA,QACP,YAAA,EAAc,OAAA;AAAA,QACd,IAAA;AAAA,QACA,YAAA,EAAc,OAAA;AAAA,QACd,cAAA,EAAgB,CAAC,CAAA,EAAGA,kBAAAA,KAClB,qBAAqBA,kBAAiB,CAAA;AAAA,QAEvC,GAAG;AAAA;AAAA,KACN,EACF,CAAA;AAAA,oBACA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,QAAA,EAAU,CAAA;AAAA,QACV,QAAA,EAAU,CAAA;AAAA,QACV,IAAA,EAAM,IAAA;AAAA,QACN,KAAA,EAAO,IAAA;AAAA,QACP,UAAA,EAAU,IAAA;AAAA,QACV,QAAA,EAAU,CAACC,KAAAA,KAAS,OAAA,CAAQA,KAAc,CAAA;AAAA,QAC1C,YAAA,EAAY,eAAA,CAAgB,MAAA,CAAO,MAAM;AAAA;AAAA;AAC3C,GAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"ImageCropper.mjs","sources":["../../../../../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["import { type CSSProperties, type FC, useEffect, useState } from \"react\";\nimport Cropper, { type Area, type CropperProps } from \"react-easy-crop\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport clsx from \"clsx\";\nimport styles from \"./ImageCropper.module.scss\";\nimport { Slider } from \"@/components/Slider\";\nimport { getCroppedImageFile } from \"@/components/ImageCropper/lib/getCroppedImageFile\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"./locales/*.locale.json\";\nimport { useImageSrc } from \"@/lib/hooks/useImageSrc\";\nimport { useDebouncedCallback } from \"use-debounce\";\n\nexport interface ImageCropperProps\n extends PropsWithClassName, Partial<Pick<CropperProps, \"cropShape\">> {\n /** The image file to crop. */\n image?: File | string;\n /** Callback on crop complete. */\n onCropComplete?: (croppedImage: File) => void;\n /** The width of the component. @default 300 */\n width?: CSSProperties[\"width\"];\n /** The height of the component. @default 300 */\n height?: CSSProperties[\"height\"];\n /** The aspect ratio of the crop shape. */\n aspectRatio?: number;\n}\n\n/** @flr-generate all */\nexport const ImageCropper: FC<ImageCropperProps> = (props) => {\n const {\n image,\n className,\n onCropComplete,\n width = 300,\n height = 300,\n aspectRatio,\n ...rest\n } = props;\n\n const imageSrc = useImageSrc(image);\n\n const [mediaLoaded, setMediaLoaded] = useState(false);\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n\n const stringFormatter = useLocalizedStringFormatter(locales, \"ImageCropper\");\n const rootClassName = clsx(styles.imageCropper, className);\n\n const debouncedCropComplete = useDebouncedCallback(\n async (croppedAreaPixels: Area) => {\n if (!croppedAreaPixels) {\n return;\n }\n\n const croppedImageFile = await getCroppedImageFile(\n imageSrc,\n image ?? \"\",\n croppedAreaPixels,\n );\n\n onCropComplete?.(croppedImageFile);\n },\n 500,\n {\n leading: true,\n },\n );\n\n useEffect(() => {\n setMediaLoaded(false);\n }, [imageSrc]);\n\n return (\n <div className={rootClassName} style={{ width }}>\n <div className={styles.cropperContainer} style={{ height }}>\n <Cropper\n style={{\n containerStyle: {\n borderRadius: \"calc(var(--image-cropper--corner-radius) - 1px)\",\n },\n }}\n aspect={aspectRatio}\n crop={crop}\n image={imageSrc}\n onCropChange={setCrop}\n zoom={zoom}\n onZoomChange={setZoom}\n onMediaLoaded={() => setMediaLoaded(true)}\n onCropComplete={(_, croppedAreaPixels) => {\n if (mediaLoaded) {\n debouncedCropComplete(croppedAreaPixels);\n }\n }}\n {...rest}\n />\n </div>\n <Slider\n minValue={1}\n maxValue={3}\n step={0.01}\n value={zoom}\n sliderOnly\n onChange={(zoom) => setZoom(zoom as number)}\n aria-label={stringFormatter.format(\"zoom\")}\n />\n </div>\n );\n};\n\nexport default ImageCropper;\n"],"names":["zoom"],"mappings":";;;;;;;;;;;;AA2BO,MAAM,YAAA,GAAsC,CAAC,KAAA,KAAU;AAC5D,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,SAAA;AAAA,IACA,cAAA;AAAA,IACA,KAAA,GAAQ,GAAA;AAAA,IACR,MAAA,GAAS,GAAA;AAAA,IACT,WAAA;AAAA,IACA,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,MAAM,QAAA,GAAW,YAAY,KAAK,CAAA;AAElC,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,KAAK,CAAA;AACpD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,QAAA,CAAS,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA;AAC/C,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,CAAC,CAAA;AAElC,EAAA,MAAM,eAAA,GAAkB,2BAAA,CAA4B,OAAA,EAAS,cAAc,CAAA;AAC3E,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc,SAAS,CAAA;AAEzD,EAAA,MAAM,qBAAA,GAAwB,oBAAA;AAAA,IAC5B,OAAO,iBAAA,KAA4B;AACjC,MAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,mBAAmB,MAAM,mBAAA;AAAA,QAC7B,QAAA;AAAA,QACA,KAAA,IAAS,EAAA;AAAA,QACT;AAAA,OACF;AAEA,MAAA,cAAA,GAAiB,gBAAgB,CAAA;AAAA,IACnC,CAAA;AAAA,IACA,GAAA;AAAA,IACA;AAAA,MACE,OAAA,EAAS;AAAA;AACX,GACF;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,cAAA,CAAe,KAAK,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,eAAe,KAAA,EAAO,EAAE,OAAM,EAC5C,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,SAAI,SAAA,EAAW,MAAA,CAAO,kBAAkB,KAAA,EAAO,EAAE,QAAO,EACvD,QAAA,kBAAA,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO;AAAA,UACL,cAAA,EAAgB;AAAA,YACd,YAAA,EAAc;AAAA;AAChB,SACF;AAAA,QACA,MAAA,EAAQ,WAAA;AAAA,QACR,IAAA;AAAA,QACA,KAAA,EAAO,QAAA;AAAA,QACP,YAAA,EAAc,OAAA;AAAA,QACd,IAAA;AAAA,QACA,YAAA,EAAc,OAAA;AAAA,QACd,aAAA,EAAe,MAAM,cAAA,CAAe,IAAI,CAAA;AAAA,QACxC,cAAA,EAAgB,CAAC,CAAA,EAAG,iBAAA,KAAsB;AACxC,UAAA,IAAI,WAAA,EAAa;AACf,YAAA,qBAAA,CAAsB,iBAAiB,CAAA;AAAA,UACzC;AAAA,QACF,CAAA;AAAA,QACC,GAAG;AAAA;AAAA,KACN,EACF,CAAA;AAAA,oBACA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,QAAA,EAAU,CAAA;AAAA,QACV,QAAA,EAAU,CAAA;AAAA,QACV,IAAA,EAAM,IAAA;AAAA,QACN,KAAA,EAAO,IAAA;AAAA,QACP,UAAA,EAAU,IAAA;AAAA,QACV,QAAA,EAAU,CAACA,KAAAA,KAAS,OAAA,CAAQA,KAAc,CAAA;AAAA,QAC1C,YAAA,EAAY,eAAA,CAAgB,MAAA,CAAO,MAAM;AAAA;AAAA;AAC3C,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -1,15 +1,17 @@
1
1
  "use client"
2
2
  /* */
3
- function getCroppedImageFile(imageSrc, pixelCrop) {
3
+ import { addAwaitedArrayBuffer } from '../../../../../core/src/file.mjs';
4
+
5
+ function getCroppedImageFile(imageSrc, sourceImage, pixelCrop) {
4
6
  return new Promise((resolve, reject) => {
5
7
  const image = new Image();
6
8
  image.crossOrigin = "anonymous";
7
9
  image.src = imageSrc;
8
10
  image.onload = () => {
9
11
  const canvas = document.createElement("canvas");
12
+ const ctx = canvas.getContext("2d");
10
13
  canvas.width = pixelCrop.width;
11
14
  canvas.height = pixelCrop.height;
12
- const ctx = canvas.getContext("2d");
13
15
  if (!ctx) {
14
16
  reject(new Error("Failed to get canvas context"));
15
17
  return;
@@ -25,18 +27,24 @@ function getCroppedImageFile(imageSrc, pixelCrop) {
25
27
  pixelCrop.width,
26
28
  pixelCrop.height
27
29
  );
30
+ const isSourceImageJsFile = sourceImage instanceof File;
31
+ const sourceImageName = isSourceImageJsFile ? sourceImage.name : "cropped-image.png";
32
+ const sourceImageType = isSourceImageJsFile ? sourceImage.type : "image/png";
33
+ const quality = sourceImageType === "image/jpeg" ? 0.86 : sourceImageType === "image/webp" ? 0.82 : void 0;
28
34
  canvas.toBlob(
29
35
  (blob) => {
30
36
  if (!blob) {
31
37
  return;
32
38
  }
33
- const file = new File([blob], "cropped-image.png", {
34
- type: "image/png"
39
+ const file = new File([blob], sourceImageName, {
40
+ type: sourceImageType
41
+ });
42
+ addAwaitedArrayBuffer(file).then((fileWithArrayBuffer) => {
43
+ resolve(fileWithArrayBuffer);
35
44
  });
36
- resolve(file);
37
45
  },
38
- "image/png",
39
- 85
46
+ sourceImageType,
47
+ quality
40
48
  );
41
49
  };
42
50
  image.onerror = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"getCroppedImageFile.mjs","sources":["../../../../../../../../src/components/ImageCropper/lib/getCroppedImageFile.ts"],"sourcesContent":["import type { Area } from \"react-easy-crop\";\n\nexport function getCroppedImageFile(\n imageSrc: string,\n pixelCrop: Area,\n): Promise<File> {\n return new Promise((resolve, reject) => {\n const image = new Image();\n image.crossOrigin = \"anonymous\";\n image.src = imageSrc;\n\n image.onload = () => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = pixelCrop.width;\n canvas.height = pixelCrop.height;\n const ctx = canvas.getContext(\"2d\");\n\n if (!ctx) {\n reject(new Error(\"Failed to get canvas context\"));\n return;\n }\n\n ctx.drawImage(\n image,\n pixelCrop.x,\n pixelCrop.y,\n pixelCrop.width,\n pixelCrop.height,\n 0,\n 0,\n pixelCrop.width,\n pixelCrop.height,\n );\n\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n return;\n }\n\n const file = new File([blob], \"cropped-image.png\", {\n type: \"image/png\",\n });\n resolve(file);\n },\n \"image/png\",\n 85,\n );\n };\n\n image.onerror = () => {\n reject(new Error(\"Failed to load image\"));\n };\n });\n}\n"],"names":[],"mappings":"AAEO,SAAS,mBAAA,CACd,UACA,SAAA,EACe;AACf,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,EAAM;AACxB,IAAA,KAAA,CAAM,WAAA,GAAc,WAAA;AACpB,IAAA,KAAA,CAAM,GAAA,GAAM,QAAA;AAEZ,IAAA,KAAA,CAAM,SAAS,MAAM;AACnB,MAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,MAAA,MAAA,CAAO,QAAQ,SAAA,CAAU,KAAA;AACzB,MAAA,MAAA,CAAO,SAAS,SAAA,CAAU,MAAA;AAC1B,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,UAAA,CAAW,IAAI,CAAA;AAElC,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,MAAA,CAAO,IAAI,KAAA,CAAM,8BAA8B,CAAC,CAAA;AAChD,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,SAAA;AAAA,QACF,KAAA;AAAA,QACA,SAAA,CAAU,CAAA;AAAA,QACV,SAAA,CAAU,CAAA;AAAA,QACV,SAAA,CAAU,KAAA;AAAA,QACV,SAAA,CAAU,MAAA;AAAA,QACV,CAAA;AAAA,QACA,CAAA;AAAA,QACA,SAAA,CAAU,KAAA;AAAA,QACV,SAAA,CAAU;AAAA,OACZ;AAEA,MAAA,MAAA,CAAO,MAAA;AAAA,QACL,CAAC,IAAA,KAAS;AACR,UAAA,IAAI,CAAC,IAAA,EAAM;AACT,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,OAAO,IAAI,IAAA,CAAK,CAAC,IAAI,GAAG,mBAAA,EAAqB;AAAA,YACjD,IAAA,EAAM;AAAA,WACP,CAAA;AACD,UAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,QACd,CAAA;AAAA,QACA,WAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,CAAA;AAEA,IAAA,KAAA,CAAM,UAAU,MAAM;AACpB,MAAA,MAAA,CAAO,IAAI,KAAA,CAAM,sBAAsB,CAAC,CAAA;AAAA,IAC1C,CAAA;AAAA,EACF,CAAC,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"getCroppedImageFile.mjs","sources":["../../../../../../../../src/components/ImageCropper/lib/getCroppedImageFile.ts"],"sourcesContent":["import type { Area } from \"react-easy-crop\";\nimport { addAwaitedArrayBuffer } from \"@mittwald/flow-core\";\n\nexport function getCroppedImageFile(\n imageSrc: string,\n sourceImage: File | string,\n pixelCrop: Area,\n): Promise<File> {\n return new Promise((resolve, reject) => {\n const image = new Image();\n image.crossOrigin = \"anonymous\";\n image.src = imageSrc;\n\n image.onload = () => {\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n\n canvas.width = pixelCrop.width;\n canvas.height = pixelCrop.height;\n\n if (!ctx) {\n reject(new Error(\"Failed to get canvas context\"));\n return;\n }\n\n ctx.drawImage(\n image,\n pixelCrop.x,\n pixelCrop.y,\n pixelCrop.width,\n pixelCrop.height,\n 0,\n 0,\n pixelCrop.width,\n pixelCrop.height,\n );\n\n const isSourceImageJsFile = sourceImage instanceof File;\n const sourceImageName = isSourceImageJsFile\n ? sourceImage.name\n : \"cropped-image.png\";\n const sourceImageType = isSourceImageJsFile\n ? sourceImage.type\n : \"image/png\";\n\n const quality =\n sourceImageType === \"image/jpeg\"\n ? 0.86\n : sourceImageType === \"image/webp\"\n ? 0.82\n : undefined;\n\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n return;\n }\n\n const file = new File([blob], sourceImageName, {\n type: sourceImageType,\n });\n addAwaitedArrayBuffer(file).then((fileWithArrayBuffer) => {\n resolve(fileWithArrayBuffer);\n });\n },\n sourceImageType,\n quality,\n );\n };\n\n image.onerror = () => {\n reject(new Error(\"Failed to load image\"));\n };\n });\n}\n"],"names":[],"mappings":";;AAGO,SAAS,mBAAA,CACd,QAAA,EACA,WAAA,EACA,SAAA,EACe;AACf,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,EAAM;AACxB,IAAA,KAAA,CAAM,WAAA,GAAc,WAAA;AACpB,IAAA,KAAA,CAAM,GAAA,GAAM,QAAA;AAEZ,IAAA,KAAA,CAAM,SAAS,MAAM;AACnB,MAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,UAAA,CAAW,IAAI,CAAA;AAElC,MAAA,MAAA,CAAO,QAAQ,SAAA,CAAU,KAAA;AACzB,MAAA,MAAA,CAAO,SAAS,SAAA,CAAU,MAAA;AAE1B,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,MAAA,CAAO,IAAI,KAAA,CAAM,8BAA8B,CAAC,CAAA;AAChD,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,SAAA;AAAA,QACF,KAAA;AAAA,QACA,SAAA,CAAU,CAAA;AAAA,QACV,SAAA,CAAU,CAAA;AAAA,QACV,SAAA,CAAU,KAAA;AAAA,QACV,SAAA,CAAU,MAAA;AAAA,QACV,CAAA;AAAA,QACA,CAAA;AAAA,QACA,SAAA,CAAU,KAAA;AAAA,QACV,SAAA,CAAU;AAAA,OACZ;AAEA,MAAA,MAAM,sBAAsB,WAAA,YAAuB,IAAA;AACnD,MAAA,MAAM,eAAA,GAAkB,mBAAA,GACpB,WAAA,CAAY,IAAA,GACZ,mBAAA;AACJ,MAAA,MAAM,eAAA,GAAkB,mBAAA,GACpB,WAAA,CAAY,IAAA,GACZ,WAAA;AAEJ,MAAA,MAAM,UACJ,eAAA,KAAoB,YAAA,GAChB,IAAA,GACA,eAAA,KAAoB,eAClB,IAAA,GACA,MAAA;AAER,MAAA,MAAA,CAAO,MAAA;AAAA,QACL,CAAC,IAAA,KAAS;AACR,UAAA,IAAI,CAAC,IAAA,EAAM;AACT,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,OAAO,IAAI,IAAA,CAAK,CAAC,IAAI,GAAG,eAAA,EAAiB;AAAA,YAC7C,IAAA,EAAM;AAAA,WACP,CAAA;AACD,UAAA,qBAAA,CAAsB,IAAI,CAAA,CAAE,IAAA,CAAK,CAAC,mBAAA,KAAwB;AACxD,YAAA,OAAA,CAAQ,mBAAmB,CAAA;AAAA,UAC7B,CAAC,CAAA;AAAA,QACH,CAAA;AAAA,QACA,eAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,CAAA;AAEA,IAAA,KAAA,CAAM,UAAU,MAAM;AACpB,MAAA,MAAA,CAAO,IAAI,KAAA,CAAM,sBAAsB,CAAC,CAAA;AAAA,IAC1C,CAAA;AAAA,EACF,CAAC,CAAA;AACH;;;;"}
@@ -53,7 +53,7 @@ const AllFiltersModal = (props) => {
53
53
  const isInitiallyLoading = list.loader.useIsInitiallyLoading();
54
54
  const totalItemCount = list.batches.getTotalItemsCount() ?? list.items.entries.length;
55
55
  const availableViewModes = useAvailableViewModes();
56
- const accordionCount = (availableViewModes.length > 0 ? 1 : 0) + (list.sorting.length > 0 ? 1 : 0) + list.filters.length;
56
+ const accordionCount = (availableViewModes.length > 1 ? 1 : 0) + (list.sorting.length > 0 ? 1 : 0) + list.filters.length;
57
57
  const expandAccordions = accordionCount <= 2;
58
58
  const filterAccordions = list.filters.map((f) => /* @__PURE__ */ jsx(
59
59
  FilterAccordion,
@@ -1 +1 @@
1
- {"version":3,"file":"AllFiltersModal.mjs","sources":["../../../../../../../../../../../src/components/List/components/Header/components/AllFiltersModal/AllFiltersModal.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { IconFilter } from \"@/components/Icon/components/icons\";\nimport ButtonView from \"@/views/ButtonView\";\nimport { useList } from \"@/components/List\";\nimport styles from \"@/components/List/components/Header/Header.module.css\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"../../../../locales/*.locale.json\";\nimport ContentView from \"@/views/ContentView\";\nimport SectionView from \"@/views/SectionView\";\nimport { FilterAccordion } from \"@/components/List/components/Header/components/AllFiltersModal/FilterAccordion\";\nimport { ViewModeAccordion } from \"@/components/List/components/Header/components/AllFiltersModal/ViewModeAccordion\";\nimport TextView from \"@/views/TextView\";\nimport { SortingAccordion } from \"@/components/List/components/Header/components/AllFiltersModal/SortingAccordion\";\nimport ActionGroupView from \"@/views/ActionGroupView\";\nimport { useOverlayController } from \"@/lib/controller\";\nimport HeadingView from \"@/views/HeadingView\";\nimport clsx from \"clsx\";\nimport Modal, { ModalTrigger } from \"@/components/Modal\";\nimport { SkeletonText } from \"@/components/SkeletonText\";\nimport { useAvailableViewModes } from \"../../lib\";\n\ninterface Props {\n isDisabled?: boolean;\n}\n\nexport const AllFiltersModal: FC<Props> = (props) => {\n const { isDisabled } = props;\n const list = useList();\n const stringFormatter = useLocalizedStringFormatter(locales, \"List\");\n\n const isInitiallyLoading = list.loader.useIsInitiallyLoading();\n const totalItemCount =\n list.batches.getTotalItemsCount() ?? list.items.entries.length;\n\n const availableViewModes = useAvailableViewModes();\n\n const accordionCount =\n (availableViewModes.length > 0 ? 1 : 0) +\n (list.sorting.length > 0 ? 1 : 0) +\n list.filters.length;\n\n const expandAccordions = accordionCount <= 2;\n\n const filterAccordions = list.filters.map((f) => (\n <FilterAccordion\n filter={f}\n key={f.name}\n expandAccordions={expandAccordions}\n />\n ));\n\n const accordions = [\n availableViewModes.length > 1 && (\n <ViewModeAccordion key=\"viewMode\" expandAccordions={expandAccordions} />\n ),\n list.sorting.length > 0 && (\n <SortingAccordion key=\"sorting\" expandAccordions={expandAccordions} />\n ),\n ...filterAccordions,\n ].filter(Boolean);\n\n const hasSecondaryFilters = list.filters.some(\n (f) => f.priority === \"secondary\",\n );\n\n const controller = useOverlayController(\"Modal\", {\n reuseControllerFromContext: false,\n });\n\n if (accordions.length === 0) {\n return null;\n }\n\n return (\n <ModalTrigger controller={controller}>\n <ButtonView\n className={clsx(\n styles.hideOnMobile,\n hasSecondaryFilters ? undefined : styles.hideOnDesktop,\n )}\n variant=\"outline\"\n color=\"secondary\"\n isDisabled={isDisabled}\n >\n <TextView>{stringFormatter.format(\"filters.all\")}</TextView>\n <IconFilter />\n </ButtonView>\n\n <ButtonView\n className={styles.hideOnDesktop}\n variant=\"outline\"\n color=\"secondary\"\n aria-label={stringFormatter.format(\"filters.all\")}\n >\n <IconFilter />\n </ButtonView>\n\n <Modal offCanvas controller={controller}>\n <HeadingView>{stringFormatter.format(\"filters.all\")}</HeadingView>\n <ContentView>\n <SectionView>{...accordions}</SectionView>\n </ContentView>\n\n <ActionGroupView>\n <ButtonView onPress={() => controller.close()}>\n <TextView>\n {isInitiallyLoading ? (\n <SkeletonText width=\"16ch\" />\n ) : (\n stringFormatter.format(\"results.show\", {\n totalItemCount,\n })\n )}\n </TextView>\n </ButtonView>\n <ButtonView\n color=\"secondary\"\n variant=\"soft\"\n onPress={() => {\n list.resetFilters();\n controller.close();\n }}\n >\n {stringFormatter.format(\"reset\")}\n </ButtonView>\n </ActionGroupView>\n </Modal>\n </ModalTrigger>\n );\n};\n"],"names":["styles"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBO,MAAM,eAAA,GAA6B,CAAC,KAAA,KAAU;AACnD,EAAA,MAAM,EAAE,YAAW,GAAI,KAAA;AACvB,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,eAAA,GAAkB,2BAAA,CAA4B,OAAA,EAAS,MAAM,CAAA;AAEnE,EAAA,MAAM,kBAAA,GAAqB,IAAA,CAAK,MAAA,CAAO,qBAAA,EAAsB;AAC7D,EAAA,MAAM,iBACJ,IAAA,CAAK,OAAA,CAAQ,oBAAmB,IAAK,IAAA,CAAK,MAAM,OAAA,CAAQ,MAAA;AAE1D,EAAA,MAAM,qBAAqB,qBAAA,EAAsB;AAEjD,EAAA,MAAM,cAAA,GAAA,CACH,kBAAA,CAAmB,MAAA,GAAS,CAAA,GAAI,CAAA,GAAI,CAAA,KACpC,IAAA,CAAK,OAAA,CAAQ,MAAA,GAAS,CAAA,GAAI,CAAA,GAAI,CAAA,CAAA,GAC/B,KAAK,OAAA,CAAQ,MAAA;AAEf,EAAA,MAAM,mBAAmB,cAAA,IAAkB,CAAA;AAE3C,EAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,qBACzC,GAAA;AAAA,IAAC,eAAA;AAAA,IAAA;AAAA,MACC,MAAA,EAAQ,CAAA;AAAA,MAER;AAAA,KAAA;AAAA,IADK,CAAA,CAAE;AAAA,GAGV,CAAA;AAED,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,mBAAmB,MAAA,GAAS,CAAA,oBAC1B,GAAA,CAAC,iBAAA,EAAA,EAAiC,oBAAX,UAA+C,CAAA;AAAA,IAExE,KAAK,OAAA,CAAQ,MAAA,GAAS,qBACpB,GAAA,CAAC,gBAAA,EAAA,EAA+B,oBAAV,SAA8C,CAAA;AAAA,IAEtE,GAAG;AAAA,GACL,CAAE,OAAO,OAAO,CAAA;AAEhB,EAAA,MAAM,mBAAA,GAAsB,KAAK,OAAA,CAAQ,IAAA;AAAA,IACvC,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa;AAAA,GACxB;AAEA,EAAA,MAAM,UAAA,GAAa,qBAAqB,OAAA,EAAS;AAAA,IAC/C,0BAAA,EAA4B;AAAA,GAC7B,CAAA;AAED,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,uBACE,IAAA,CAAC,gBAAa,UAAA,EACZ,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,IAAA;AAAA,UACTA,YAAA,CAAO,YAAA;AAAA,UACP,mBAAA,GAAsB,SAAYA,YAAA,CAAO;AAAA,SAC3C;AAAA,QACA,OAAA,EAAQ,SAAA;AAAA,QACR,KAAA,EAAM,WAAA;AAAA,QACN,UAAA;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,QAAA,EAAA,EAAU,QAAA,EAAA,eAAA,CAAgB,MAAA,CAAO,aAAa,CAAA,EAAE,CAAA;AAAA,8BAChD,UAAA,EAAA,EAAW;AAAA;AAAA;AAAA,KACd;AAAA,oBAEA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,WAAWA,YAAA,CAAO,aAAA;AAAA,QAClB,OAAA,EAAQ,SAAA;AAAA,QACR,KAAA,EAAM,WAAA;AAAA,QACN,YAAA,EAAY,eAAA,CAAgB,MAAA,CAAO,aAAa,CAAA;AAAA,QAEhD,8BAAC,UAAA,EAAA,EAAW;AAAA;AAAA,KACd;AAAA,oBAEA,IAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAS,IAAA,EAAC,UAAA,EACf,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,WAAA,EAAA,EAAa,QAAA,EAAA,eAAA,CAAgB,MAAA,CAAO,aAAa,CAAA,EAAE,CAAA;AAAA,sBACpD,GAAA,CAAC,WAAA,EAAA,EACC,QAAA,kBAAA,IAAA,CAAC,WAAA,EAAA,EAAa,QAAA,EAAA;AAAA,QAAA,GAAG;AAAA,OAAA,EAAW,CAAA,EAC9B,CAAA;AAAA,2BAEC,eAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,cAAW,OAAA,EAAS,MAAM,UAAA,CAAW,KAAA,IACpC,QAAA,kBAAA,GAAA,CAAC,QAAA,EAAA,EACE,QAAA,EAAA,kBAAA,mBACC,GAAA,CAAC,gBAAa,KAAA,EAAM,MAAA,EAAO,CAAA,GAE3B,eAAA,CAAgB,OAAO,cAAA,EAAgB;AAAA,UACrC;AAAA,SACD,GAEL,CAAA,EACF,CAAA;AAAA,wBACA,GAAA;AAAA,UAAC,UAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAM,WAAA;AAAA,YACN,OAAA,EAAQ,MAAA;AAAA,YACR,SAAS,MAAM;AACb,cAAA,IAAA,CAAK,YAAA,EAAa;AAClB,cAAA,UAAA,CAAW,KAAA,EAAM;AAAA,YACnB,CAAA;AAAA,YAEC,QAAA,EAAA,eAAA,CAAgB,OAAO,OAAO;AAAA;AAAA;AACjC,OAAA,EACF;AAAA,KAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"AllFiltersModal.mjs","sources":["../../../../../../../../../../../src/components/List/components/Header/components/AllFiltersModal/AllFiltersModal.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { IconFilter } from \"@/components/Icon/components/icons\";\nimport ButtonView from \"@/views/ButtonView\";\nimport { useList } from \"@/components/List\";\nimport styles from \"@/components/List/components/Header/Header.module.css\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"../../../../locales/*.locale.json\";\nimport ContentView from \"@/views/ContentView\";\nimport SectionView from \"@/views/SectionView\";\nimport { FilterAccordion } from \"@/components/List/components/Header/components/AllFiltersModal/FilterAccordion\";\nimport { ViewModeAccordion } from \"@/components/List/components/Header/components/AllFiltersModal/ViewModeAccordion\";\nimport TextView from \"@/views/TextView\";\nimport { SortingAccordion } from \"@/components/List/components/Header/components/AllFiltersModal/SortingAccordion\";\nimport ActionGroupView from \"@/views/ActionGroupView\";\nimport { useOverlayController } from \"@/lib/controller\";\nimport HeadingView from \"@/views/HeadingView\";\nimport clsx from \"clsx\";\nimport Modal, { ModalTrigger } from \"@/components/Modal\";\nimport { SkeletonText } from \"@/components/SkeletonText\";\nimport { useAvailableViewModes } from \"../../lib\";\n\ninterface Props {\n isDisabled?: boolean;\n}\n\nexport const AllFiltersModal: FC<Props> = (props) => {\n const { isDisabled } = props;\n const list = useList();\n const stringFormatter = useLocalizedStringFormatter(locales, \"List\");\n\n const isInitiallyLoading = list.loader.useIsInitiallyLoading();\n const totalItemCount =\n list.batches.getTotalItemsCount() ?? list.items.entries.length;\n\n const availableViewModes = useAvailableViewModes();\n\n const accordionCount =\n (availableViewModes.length > 1 ? 1 : 0) +\n (list.sorting.length > 0 ? 1 : 0) +\n list.filters.length;\n\n const expandAccordions = accordionCount <= 2;\n\n const filterAccordions = list.filters.map((f) => (\n <FilterAccordion\n filter={f}\n key={f.name}\n expandAccordions={expandAccordions}\n />\n ));\n\n const accordions = [\n availableViewModes.length > 1 && (\n <ViewModeAccordion key=\"viewMode\" expandAccordions={expandAccordions} />\n ),\n list.sorting.length > 0 && (\n <SortingAccordion key=\"sorting\" expandAccordions={expandAccordions} />\n ),\n ...filterAccordions,\n ].filter(Boolean);\n\n const hasSecondaryFilters = list.filters.some(\n (f) => f.priority === \"secondary\",\n );\n\n const controller = useOverlayController(\"Modal\", {\n reuseControllerFromContext: false,\n });\n\n if (accordions.length === 0) {\n return null;\n }\n\n return (\n <ModalTrigger controller={controller}>\n <ButtonView\n className={clsx(\n styles.hideOnMobile,\n hasSecondaryFilters ? undefined : styles.hideOnDesktop,\n )}\n variant=\"outline\"\n color=\"secondary\"\n isDisabled={isDisabled}\n >\n <TextView>{stringFormatter.format(\"filters.all\")}</TextView>\n <IconFilter />\n </ButtonView>\n\n <ButtonView\n className={styles.hideOnDesktop}\n variant=\"outline\"\n color=\"secondary\"\n aria-label={stringFormatter.format(\"filters.all\")}\n >\n <IconFilter />\n </ButtonView>\n\n <Modal offCanvas controller={controller}>\n <HeadingView>{stringFormatter.format(\"filters.all\")}</HeadingView>\n <ContentView>\n <SectionView>{...accordions}</SectionView>\n </ContentView>\n\n <ActionGroupView>\n <ButtonView onPress={() => controller.close()}>\n <TextView>\n {isInitiallyLoading ? (\n <SkeletonText width=\"16ch\" />\n ) : (\n stringFormatter.format(\"results.show\", {\n totalItemCount,\n })\n )}\n </TextView>\n </ButtonView>\n <ButtonView\n color=\"secondary\"\n variant=\"soft\"\n onPress={() => {\n list.resetFilters();\n controller.close();\n }}\n >\n {stringFormatter.format(\"reset\")}\n </ButtonView>\n </ActionGroupView>\n </Modal>\n </ModalTrigger>\n );\n};\n"],"names":["styles"],"mappings":"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"}
@@ -1,28 +1,18 @@
1
1
  "use client"
2
2
  /* */
3
- import { useState, useEffectEvent, useEffect } from 'react';
3
+ import { useState, useEffect } from 'react';
4
4
 
5
5
  const useImageSrc = (image) => {
6
- const [imageSrc, setImageSrc] = useState("");
7
- const onImageChange = useEffectEvent(() => {
8
- if (image) {
9
- if (typeof image === "string") {
10
- setImageSrc(image);
11
- } else {
12
- const reader = new FileReader();
13
- reader.onload = () => {
14
- if (typeof reader.result === "string") {
15
- setImageSrc(reader.result);
16
- }
17
- };
18
- reader.readAsDataURL(image);
19
- }
20
- }
21
- });
6
+ const [src, setSrc] = useState(typeof image === "string" ? image : "");
22
7
  useEffect(() => {
23
- onImageChange();
8
+ if (!image || typeof image === "string") {
9
+ return;
10
+ }
11
+ const url = URL.createObjectURL(image);
12
+ setSrc(url);
13
+ return () => URL.revokeObjectURL(url);
24
14
  }, [image]);
25
- return imageSrc;
15
+ return src;
26
16
  };
27
17
 
28
18
  export { useImageSrc };
@@ -1 +1 @@
1
- {"version":3,"file":"useImageSrc.mjs","sources":["../../../../../../../src/lib/hooks/useImageSrc.tsx"],"sourcesContent":["import { useEffect, useEffectEvent, useState } from \"react\";\n\nexport const useImageSrc = (image?: string | File) => {\n const [imageSrc, setImageSrc] = useState<string>(\"\");\n\n const onImageChange = useEffectEvent(() => {\n if (image) {\n if (typeof image === \"string\") {\n setImageSrc(image);\n } else {\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result === \"string\") {\n setImageSrc(reader.result);\n }\n };\n reader.readAsDataURL(image);\n }\n }\n });\n\n useEffect(() => {\n onImageChange();\n }, [image]);\n\n return imageSrc;\n};\n"],"names":[],"mappings":";;AAEO,MAAM,WAAA,GAAc,CAAC,KAAA,KAA0B;AACpD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAiB,EAAE,CAAA;AAEnD,EAAA,MAAM,aAAA,GAAgB,eAAe,MAAM;AACzC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,QAAA,WAAA,CAAY,KAAK,CAAA;AAAA,MACnB,CAAA,MAAO;AACL,QAAA,MAAM,MAAA,GAAS,IAAI,UAAA,EAAW;AAC9B,QAAA,MAAA,CAAO,SAAS,MAAM;AACpB,UAAA,IAAI,OAAO,MAAA,CAAO,MAAA,KAAW,QAAA,EAAU;AACrC,YAAA,WAAA,CAAY,OAAO,MAAM,CAAA;AAAA,UAC3B;AAAA,QACF,CAAA;AACA,QAAA,MAAA,CAAO,cAAc,KAAK,CAAA;AAAA,MAC5B;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,aAAA,EAAc;AAAA,EAChB,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,OAAO,QAAA;AACT;;;;"}
1
+ {"version":3,"file":"useImageSrc.mjs","sources":["../../../../../../../src/lib/hooks/useImageSrc.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport const useImageSrc = (image?: string | File) => {\n const [src, setSrc] = useState(typeof image === \"string\" ? image : \"\");\n\n useEffect(() => {\n if (!image || typeof image === \"string\") {\n return;\n }\n\n const url = URL.createObjectURL(image);\n setSrc(url);\n\n return () => URL.revokeObjectURL(url);\n }, [image]);\n\n return src;\n};\n"],"names":[],"mappings":";;AAEO,MAAM,WAAA,GAAc,CAAC,KAAA,KAA0B;AACpD,EAAA,MAAM,CAAC,KAAK,MAAM,CAAA,GAAI,SAAS,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,EAAE,CAAA;AAErE,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACvC,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,KAAK,CAAA;AACrC,IAAA,MAAA,CAAO,GAAG,CAAA;AAEV,IAAA,OAAO,MAAM,GAAA,CAAI,eAAA,CAAgB,GAAG,CAAA;AAAA,EACtC,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,OAAO,GAAA;AACT;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ImageCropper.d.ts","sourceRoot":"","sources":["../../../../src/components/ImageCropper/ImageCropper.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,EAAE,EAIR,MAAM,OAAO,CAAC;AACf,OAAgB,EAAa,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAS5D,MAAM,WAAW,iBACf,SAAQ,kBAAkB,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACpE,8BAA8B;IAC9B,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,iCAAiC;IACjC,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,KAAK,IAAI,CAAC;IAC9C,+CAA+C;IAC/C,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,gDAAgD;IAChD,MAAM,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACjC,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAwB;AACxB,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAqE9C,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"ImageCropper.d.ts","sourceRoot":"","sources":["../../../../src/components/ImageCropper/ImageCropper.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,EAAE,EAAuB,MAAM,OAAO,CAAC;AACzE,OAAgB,EAAa,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAU5D,MAAM,WAAW,iBACf,SAAQ,kBAAkB,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACpE,8BAA8B;IAC9B,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,iCAAiC;IACjC,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,KAAK,IAAI,CAAC;IAC9C,+CAA+C;IAC/C,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,gDAAgD;IAChD,MAAM,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACjC,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAwB;AACxB,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CA+E9C,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { Area } from 'react-easy-crop';
2
- export declare function getCroppedImageFile(imageSrc: string, pixelCrop: Area): Promise<File>;
2
+ export declare function getCroppedImageFile(imageSrc: string, sourceImage: File | string, pixelCrop: Area): Promise<File>;
3
3
  //# sourceMappingURL=getCroppedImageFile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getCroppedImageFile.d.ts","sourceRoot":"","sources":["../../../../../src/components/ImageCropper/lib/getCroppedImageFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,IAAI,GACd,OAAO,CAAC,IAAI,CAAC,CAiDf"}
1
+ {"version":3,"file":"getCroppedImageFile.d.ts","sourceRoot":"","sources":["../../../../../src/components/ImageCropper/lib/getCroppedImageFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAG5C,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,IAAI,GAAG,MAAM,EAC1B,SAAS,EAAE,IAAI,GACd,OAAO,CAAC,IAAI,CAAC,CAmEf"}
@@ -1 +1 @@
1
- {"version":3,"file":"Default.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/ImageCropper/stories/Default.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAQzD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,YAAY,CAWnC,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,YAAY,EAAE,KAyC1B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAoCtB,CAAC"}
1
+ {"version":3,"file":"Default.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/ImageCropper/stories/Default.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AASzD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,YAAY,CA+BnC,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,YAAY,EAAE,KAmD1B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAoCtB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useImageSrc.d.ts","sourceRoot":"","sources":["../../../../src/lib/hooks/useImageSrc.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,GAAG,IAAI,WAwBhD,CAAC"}
1
+ {"version":3,"file":"useImageSrc.d.ts","sourceRoot":"","sources":["../../../../src/lib/hooks/useImageSrc.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,GAAG,IAAI,WAehD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mittwald/flow-react-components",
3
- "version": "0.2.0-alpha.871",
3
+ "version": "0.2.0-alpha.873",
4
4
  "type": "module",
5
5
  "description": "A React implementation of Flow, mittwald’s design system",
6
6
  "homepage": "https://mittwald.github.io/flow",
@@ -63,9 +63,9 @@
63
63
  "@internationalized/string": "^3.2.9",
64
64
  "@internationalized/string-compiler": "^3.4.1",
65
65
  "@lezer/highlight": "^1.2.3",
66
- "@mittwald/flow-icons": "0.2.0-alpha.871",
66
+ "@mittwald/flow-icons": "0.2.0-alpha.873",
67
67
  "@mittwald/password-tools-js": "3.0.0-alpha.30",
68
- "@mittwald/react-tunnel": "0.2.0-alpha.871",
68
+ "@mittwald/react-tunnel": "0.2.0-alpha.873",
69
69
  "@mittwald/react-use-promise": "^4.2.2",
70
70
  "@react-aria/form": "^3.2.1",
71
71
  "@react-aria/i18n": "^3.13.1",
@@ -110,6 +110,7 @@
110
110
  "remeda": "^2.39.0",
111
111
  "type-fest": "^5.7.0",
112
112
  "use-callback-ref": "^1.3.3",
113
+ "use-debounce": "^10.1.1",
113
114
  "usehooks-ts": "^3.1.1",
114
115
  "zod": "^4.4.3"
115
116
  },
@@ -119,7 +120,7 @@
119
120
  "@lezer/generator": "^1.8.0",
120
121
  "@lezer/lr": "^1.4.10",
121
122
  "@mittwald/flow-core": "",
122
- "@mittwald/flow-design-tokens": "0.2.0-alpha.871",
123
+ "@mittwald/flow-design-tokens": "0.2.0-alpha.873",
123
124
  "@mittwald/flow-icons-base": "",
124
125
  "@mittwald/react-use-promise": "^4.2.2",
125
126
  "@mittwald/remote-dom-react": "1.2.2-mittwald.10",
@@ -174,7 +175,7 @@
174
175
  },
175
176
  "peerDependencies": {
176
177
  "@internationalized/date": "^3.12.2",
177
- "@mittwald/flow-icons-pro": "0.2.0-alpha.870",
178
+ "@mittwald/flow-icons-pro": "0.2.0-alpha.872",
178
179
  "@mittwald/react-use-promise": "^4.2.2",
179
180
  "next": "^16.2.3",
180
181
  "react": "^19.2.0",
@@ -195,5 +196,5 @@
195
196
  "optional": true
196
197
  }
197
198
  },
198
- "gitHead": "4dbca5a7447e3f100335ca065ef229392c5d2889"
199
+ "gitHead": "b3dcaa78222a884b84572558d328546c86c44dbe"
199
200
  }