@bitrise/bitkit-v2 0.3.283 → 0.3.284

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.
@@ -2,6 +2,12 @@ import { FileUpload } from '@chakra-ui/react/file-upload';
2
2
  import { BitkitFieldProps } from '../BitkitField/BitkitField';
3
3
  declare const BitkitFileInput: import('react').ForwardRefExoticComponent<Omit<BitkitFieldProps, "children" | "state"> & Omit<FileUpload.RootProps, "disabled" | "invalid"> & {
4
4
  aspectRatio?: number;
5
+ /**
6
+ * Max width/height (px) of the cropped output. The Ark cropper emits at the
7
+ * selection's natural resolution with no size cap, so a large source image
8
+ * can produce an oversized file; set this to downscale the output to fit.
9
+ */
10
+ maxCroppedSize?: number;
5
11
  onCropChange?: (file: File) => void;
6
12
  onFileAccepted?: (file: File) => void;
7
13
  state?: "error" | "disabled";
@@ -11,6 +11,37 @@ import { FileUpload, useFileUploadContext } from "@chakra-ui/react/file-upload";
11
11
  import { VStack } from "@chakra-ui/react/stack";
12
12
  import { splitProps } from "@zag-js/file-upload";
13
13
  //#region lib/components/BitkitFileInput/BitkitFileInput.tsx
14
+ var downscaleBlob = (blob, maxSize) => {
15
+ if (!Number.isFinite(maxSize) || maxSize <= 0) return Promise.resolve(blob);
16
+ return new Promise((resolve) => {
17
+ const url = URL.createObjectURL(blob);
18
+ const image = new Image();
19
+ image.onload = () => {
20
+ URL.revokeObjectURL(url);
21
+ const largestSide = Math.max(image.naturalWidth, image.naturalHeight);
22
+ if (largestSide <= maxSize) {
23
+ resolve(blob);
24
+ return;
25
+ }
26
+ const scale = maxSize / largestSide;
27
+ const canvas = document.createElement("canvas");
28
+ canvas.width = Math.round(image.naturalWidth * scale);
29
+ canvas.height = Math.round(image.naturalHeight * scale);
30
+ const context = canvas.getContext("2d");
31
+ if (!context) {
32
+ resolve(blob);
33
+ return;
34
+ }
35
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
36
+ canvas.toBlob((result) => resolve(result ?? blob), blob.type);
37
+ };
38
+ image.onerror = () => {
39
+ URL.revokeObjectURL(url);
40
+ resolve(blob);
41
+ };
42
+ image.src = url;
43
+ });
44
+ };
14
45
  var Dropzone = () => {
15
46
  const { disabled } = useFileUploadContext();
16
47
  const dropzoneLabel = disabled ? "Cannot upload file" : "Drag and drop file here or click to select";
@@ -20,7 +51,7 @@ var Dropzone = () => {
20
51
  })] }) });
21
52
  };
22
53
  var ImagePreviewContent = (props) => {
23
- const { onCropChange } = props;
54
+ const { onCropChange, maxCroppedSize } = props;
24
55
  const { acceptedFiles } = useFileUploadContext();
25
56
  const { dragging, getCroppedImage } = useImageCropperContext();
26
57
  const acceptedFile = acceptedFiles[0];
@@ -34,7 +65,10 @@ var ImagePreviewContent = (props) => {
34
65
  if (!onCropChange || dragging) return;
35
66
  if (!acceptedFile) return;
36
67
  let cancelled = false;
37
- getCroppedImage().then((result) => {
68
+ getCroppedImage({ type: acceptedFile.type || void 0 }).then((result) => {
69
+ if (!(result instanceof Blob)) return result;
70
+ return maxCroppedSize ? downscaleBlob(result, maxCroppedSize) : result;
71
+ }).then((result) => {
38
72
  if (!cancelled && result instanceof Blob) onCropChange(new File([result], acceptedFile.name, { type: result.type }));
39
73
  });
40
74
  return () => {
@@ -44,7 +78,8 @@ var ImagePreviewContent = (props) => {
44
78
  getCroppedImage,
45
79
  acceptedFile,
46
80
  onCropChange,
47
- dragging
81
+ dragging,
82
+ maxCroppedSize
48
83
  ]);
49
84
  return /* @__PURE__ */ jsxs(ImageCropper_default.Viewport, { children: [/* @__PURE__ */ jsx(ImageCropper_default.Image, { src: objectUrl }), /* @__PURE__ */ jsx(ImageCropper_default.Selection, { children: ImageCropper_default.handles.map((position) => /* @__PURE__ */ jsx(ImageCropper_default.Handle, {
50
85
  position,
@@ -52,11 +87,14 @@ var ImagePreviewContent = (props) => {
52
87
  }, position)) })] });
53
88
  };
54
89
  var ImagePreview = (props) => {
55
- const { aspectRatio, onCropChange } = props;
90
+ const { aspectRatio, onCropChange, maxCroppedSize } = props;
56
91
  return /* @__PURE__ */ jsx(ImageCropper_default.Root, {
57
92
  aspectRatio,
58
93
  height: "100%",
59
- children: /* @__PURE__ */ jsx(ImagePreviewContent, { onCropChange })
94
+ children: /* @__PURE__ */ jsx(ImagePreviewContent, {
95
+ onCropChange,
96
+ maxCroppedSize
97
+ })
60
98
  });
61
99
  };
62
100
  var NonImagePreview = () => {
@@ -97,19 +135,20 @@ var NonImagePreview = () => {
97
135
  });
98
136
  };
99
137
  var BitkitFileInputContent = (props) => {
100
- const { variant, aspectRatio, onCropChange } = props;
138
+ const { variant, aspectRatio, onCropChange, maxCroppedSize } = props;
101
139
  const acceptedFile = useFileUploadContext().acceptedFiles[0];
102
140
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
103
141
  !acceptedFile && /* @__PURE__ */ jsx(Dropzone, {}),
104
142
  acceptedFile && variant === "image" && /* @__PURE__ */ jsx(ImagePreview, {
105
143
  aspectRatio,
106
- onCropChange
144
+ onCropChange,
145
+ maxCroppedSize
107
146
  }),
108
147
  acceptedFile && variant !== "image" && /* @__PURE__ */ jsx(NonImagePreview, {})
109
148
  ] });
110
149
  };
111
150
  var BitkitFileInput = forwardRef((props, ref) => {
112
- const { aspectRatio, onCropChange, onFileAccept, onFileAccepted, state, variant, ...rest } = props;
151
+ const { aspectRatio, maxCroppedSize, onCropChange, onFileAccept, onFileAccepted, state, variant, ...rest } = props;
113
152
  const [fileUploadProps, fieldProps] = splitProps(rest);
114
153
  const handleFileAccept = (details) => {
115
154
  onFileAccept?.(details);
@@ -118,7 +157,8 @@ var BitkitFileInput = forwardRef((props, ref) => {
118
157
  const contentProps = {
119
158
  variant,
120
159
  aspectRatio,
121
- onCropChange
160
+ onCropChange,
161
+ maxCroppedSize
122
162
  };
123
163
  return /* @__PURE__ */ jsx(BitkitField, {
124
164
  ref,
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitFileInput.js","names":[],"sources":["../../../lib/components/BitkitFileInput/BitkitFileInput.tsx"],"sourcesContent":["import { Card } from '@chakra-ui/react/card';\nimport {\n FileUpload,\n type FileUploadFileAcceptDetails,\n type FileUploadRootProps,\n useFileUploadContext,\n} from '@chakra-ui/react/file-upload';\nimport { VStack } from '@chakra-ui/react/stack';\nimport { Text } from '@chakra-ui/react/text';\nimport { splitProps as splitFileUploadProps } from '@zag-js/file-upload';\nimport { forwardRef, useEffect, useMemo } from 'react';\n\nimport ImageCropper, { useImageCropperContext } from '../../atoms/ImageCropper/ImageCropper';\nimport { IconMinusCircle, IconUpload } from '../../icons';\nimport BitkitButton from '../BitkitButton/BitkitButton';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField';\n\ntype BitkitFileInputProps = Omit<BitkitFieldProps, 'children' | 'state'> &\n Omit<FileUploadRootProps, 'disabled' | 'invalid'> & {\n aspectRatio?: number;\n onCropChange?: (file: File) => void;\n onFileAccepted?: (file: File) => void;\n state?: 'error' | 'disabled';\n };\n\nconst Dropzone = () => {\n const { disabled } = useFileUploadContext();\n const dropzoneLabel = disabled ? 'Cannot upload file' : 'Drag and drop file here or click to select';\n\n return (\n <FileUpload.Dropzone>\n <FileUpload.DropzoneContent>\n <IconUpload />\n <Text as=\"span\">{dropzoneLabel}</Text>\n </FileUpload.DropzoneContent>\n </FileUpload.Dropzone>\n );\n};\n\nconst ImagePreviewContent = (props: Pick<BitkitFileInputProps, 'onCropChange'>) => {\n const { onCropChange } = props;\n\n const { acceptedFiles } = useFileUploadContext();\n const { dragging, getCroppedImage } = useImageCropperContext();\n\n const acceptedFile = acceptedFiles[0];\n const objectUrl = useMemo(() => (acceptedFile ? URL.createObjectURL(acceptedFile) : undefined), [acceptedFile]);\n\n useEffect(() => {\n return () => {\n if (objectUrl) {\n URL.revokeObjectURL(objectUrl);\n }\n };\n }, [objectUrl]);\n\n useEffect(() => {\n if (!onCropChange || dragging) {\n return;\n }\n\n if (!acceptedFile) {\n return;\n }\n\n let cancelled = false;\n getCroppedImage().then((result) => {\n if (!cancelled && result instanceof Blob) {\n onCropChange(new File([result], acceptedFile.name, { type: result.type }));\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [getCroppedImage, acceptedFile, onCropChange, dragging]);\n\n return (\n <ImageCropper.Viewport>\n <ImageCropper.Image src={objectUrl} />\n <ImageCropper.Selection>\n {ImageCropper.handles.map((position) => (\n <ImageCropper.Handle key={position} position={position}>\n <div />\n </ImageCropper.Handle>\n ))}\n </ImageCropper.Selection>\n </ImageCropper.Viewport>\n );\n};\n\nconst ImagePreview = (props: Pick<BitkitFileInputProps, 'aspectRatio' | 'onCropChange'>) => {\n const { aspectRatio, onCropChange } = props;\n\n return (\n <ImageCropper.Root aspectRatio={aspectRatio} height=\"100%\">\n <ImagePreviewContent onCropChange={onCropChange} />\n </ImageCropper.Root>\n );\n};\n\nconst NonImagePreview = () => {\n const fileUpload = useFileUploadContext();\n const acceptedFile = fileUpload.acceptedFiles[0];\n\n return (\n <Card.Root asChild elevation={false}>\n <Card.Body display=\"flex\" paddingBlock=\"20\" paddingInline=\"24\" alignItems=\"center\" flex=\"1\">\n <VStack gap=\"4\" alignItems=\"flex-start\" flex=\"1\" minWidth=\"0\">\n <Text textStyle=\"comp/input/label\">Selected file</Text>\n <Text whiteSpace=\"nowrap\" textOverflow=\"ellipsis\" overflow=\"hidden\" maxWidth=\"100%\">\n {acceptedFile.name}\n </Text>\n </VStack>\n <BitkitButton icon={IconMinusCircle} variant=\"secondary\" size=\"md\" onClick={fileUpload.clearFiles}>\n Remove\n </BitkitButton>\n </Card.Body>\n </Card.Root>\n );\n};\n\nconst BitkitFileInputContent = (props: Pick<BitkitFileInputProps, 'variant' | 'aspectRatio' | 'onCropChange'>) => {\n const { variant, aspectRatio, onCropChange } = props;\n const acceptedFile = useFileUploadContext().acceptedFiles[0];\n\n return (\n <>\n {!acceptedFile && <Dropzone />}\n {acceptedFile && variant === 'image' && <ImagePreview aspectRatio={aspectRatio} onCropChange={onCropChange} />}\n {acceptedFile && variant !== 'image' && <NonImagePreview />}\n </>\n );\n};\n\nconst BitkitFileInput = forwardRef<HTMLDivElement, BitkitFileInputProps>((props, ref) => {\n const { aspectRatio, onCropChange, onFileAccept, onFileAccepted, state, variant, ...rest } = props;\n const [fileUploadProps, fieldProps] = splitFileUploadProps(rest as never);\n\n const handleFileAccept = (details: FileUploadFileAcceptDetails) => {\n onFileAccept?.(details);\n onFileAccepted?.(details.files[0]);\n };\n\n const contentProps = {\n variant,\n aspectRatio,\n onCropChange,\n };\n\n return (\n <BitkitField ref={ref} state={state} {...fieldProps}>\n <FileUpload.Root variant={variant} onFileAccept={handleFileAccept} {...fileUploadProps}>\n <FileUpload.HiddenInput />\n <BitkitFileInputContent {...contentProps} />\n </FileUpload.Root>\n </BitkitField>\n );\n});\n\nBitkitFileInput.displayName = 'BitkitFileInput';\n\nexport default BitkitFileInput;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BitkitFileInput.js","names":[],"sources":["../../../lib/components/BitkitFileInput/BitkitFileInput.tsx"],"sourcesContent":["import { Card } from '@chakra-ui/react/card';\nimport {\n FileUpload,\n type FileUploadFileAcceptDetails,\n type FileUploadRootProps,\n useFileUploadContext,\n} from '@chakra-ui/react/file-upload';\nimport { VStack } from '@chakra-ui/react/stack';\nimport { Text } from '@chakra-ui/react/text';\nimport { splitProps as splitFileUploadProps } from '@zag-js/file-upload';\nimport { forwardRef, useEffect, useMemo } from 'react';\n\nimport ImageCropper, { useImageCropperContext } from '../../atoms/ImageCropper/ImageCropper';\nimport { IconMinusCircle, IconUpload } from '../../icons';\nimport BitkitButton from '../BitkitButton/BitkitButton';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField';\n\ntype BitkitFileInputProps = Omit<BitkitFieldProps, 'children' | 'state'> &\n Omit<FileUploadRootProps, 'disabled' | 'invalid'> & {\n aspectRatio?: number;\n /**\n * Max width/height (px) of the cropped output. The Ark cropper emits at the\n * selection's natural resolution with no size cap, so a large source image\n * can produce an oversized file; set this to downscale the output to fit.\n */\n maxCroppedSize?: number;\n onCropChange?: (file: File) => void;\n onFileAccepted?: (file: File) => void;\n state?: 'error' | 'disabled';\n };\n\n// Ark's getCroppedImage() emits at the selection's natural resolution and only\n// controls format/quality (no size cap), so downscale here when a max is set —\n// this keeps a large source image from producing an oversized upload. Preserves\n// the blob's MIME type; falls back to the original blob if it can't be decoded.\nconst downscaleBlob = (blob: Blob, maxSize: number): Promise<Blob> => {\n // A non-positive or non-finite max would produce a 0×0 / NaN canvas and corrupt\n // the output, so treat it as \"no cap\" and pass the blob through untouched.\n if (!Number.isFinite(maxSize) || maxSize <= 0) {\n return Promise.resolve(blob);\n }\n\n return new Promise((resolve) => {\n const url = URL.createObjectURL(blob);\n const image = new Image();\n\n image.onload = () => {\n URL.revokeObjectURL(url);\n const largestSide = Math.max(image.naturalWidth, image.naturalHeight);\n if (largestSide <= maxSize) {\n resolve(blob);\n return;\n }\n const scale = maxSize / largestSide;\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(image.naturalWidth * scale);\n canvas.height = Math.round(image.naturalHeight * scale);\n const context = canvas.getContext('2d');\n if (!context) {\n resolve(blob);\n return;\n }\n context.drawImage(image, 0, 0, canvas.width, canvas.height);\n canvas.toBlob((result) => resolve(result ?? blob), blob.type);\n };\n\n image.onerror = () => {\n URL.revokeObjectURL(url);\n resolve(blob);\n };\n\n image.src = url;\n });\n};\n\nconst Dropzone = () => {\n const { disabled } = useFileUploadContext();\n const dropzoneLabel = disabled ? 'Cannot upload file' : 'Drag and drop file here or click to select';\n\n return (\n <FileUpload.Dropzone>\n <FileUpload.DropzoneContent>\n <IconUpload />\n <Text as=\"span\">{dropzoneLabel}</Text>\n </FileUpload.DropzoneContent>\n </FileUpload.Dropzone>\n );\n};\n\nconst ImagePreviewContent = (props: Pick<BitkitFileInputProps, 'onCropChange' | 'maxCroppedSize'>) => {\n const { onCropChange, maxCroppedSize } = props;\n\n const { acceptedFiles } = useFileUploadContext();\n const { dragging, getCroppedImage } = useImageCropperContext();\n\n const acceptedFile = acceptedFiles[0];\n const objectUrl = useMemo(() => (acceptedFile ? URL.createObjectURL(acceptedFile) : undefined), [acceptedFile]);\n\n useEffect(() => {\n return () => {\n if (objectUrl) {\n URL.revokeObjectURL(objectUrl);\n }\n };\n }, [objectUrl]);\n\n useEffect(() => {\n if (!onCropChange || dragging) {\n return;\n }\n\n if (!acceptedFile) {\n return;\n }\n\n let cancelled = false;\n // Preserve the source MIME type — the Ark cropper defaults to image/png, which\n // would mismatch a .jpg name and bloat the file.\n getCroppedImage({ type: acceptedFile.type || undefined })\n .then((result) => {\n if (!(result instanceof Blob)) {\n return result;\n }\n return maxCroppedSize ? downscaleBlob(result, maxCroppedSize) : result;\n })\n .then((result) => {\n if (!cancelled && result instanceof Blob) {\n onCropChange(new File([result], acceptedFile.name, { type: result.type }));\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [getCroppedImage, acceptedFile, onCropChange, dragging, maxCroppedSize]);\n\n return (\n <ImageCropper.Viewport>\n <ImageCropper.Image src={objectUrl} />\n <ImageCropper.Selection>\n {ImageCropper.handles.map((position) => (\n <ImageCropper.Handle key={position} position={position}>\n <div />\n </ImageCropper.Handle>\n ))}\n </ImageCropper.Selection>\n </ImageCropper.Viewport>\n );\n};\n\nconst ImagePreview = (props: Pick<BitkitFileInputProps, 'aspectRatio' | 'onCropChange' | 'maxCroppedSize'>) => {\n const { aspectRatio, onCropChange, maxCroppedSize } = props;\n\n return (\n <ImageCropper.Root aspectRatio={aspectRatio} height=\"100%\">\n <ImagePreviewContent onCropChange={onCropChange} maxCroppedSize={maxCroppedSize} />\n </ImageCropper.Root>\n );\n};\n\nconst NonImagePreview = () => {\n const fileUpload = useFileUploadContext();\n const acceptedFile = fileUpload.acceptedFiles[0];\n\n return (\n <Card.Root asChild elevation={false}>\n <Card.Body display=\"flex\" paddingBlock=\"20\" paddingInline=\"24\" alignItems=\"center\" flex=\"1\">\n <VStack gap=\"4\" alignItems=\"flex-start\" flex=\"1\" minWidth=\"0\">\n <Text textStyle=\"comp/input/label\">Selected file</Text>\n <Text whiteSpace=\"nowrap\" textOverflow=\"ellipsis\" overflow=\"hidden\" maxWidth=\"100%\">\n {acceptedFile.name}\n </Text>\n </VStack>\n <BitkitButton icon={IconMinusCircle} variant=\"secondary\" size=\"md\" onClick={fileUpload.clearFiles}>\n Remove\n </BitkitButton>\n </Card.Body>\n </Card.Root>\n );\n};\n\nconst BitkitFileInputContent = (\n props: Pick<BitkitFileInputProps, 'variant' | 'aspectRatio' | 'onCropChange' | 'maxCroppedSize'>,\n) => {\n const { variant, aspectRatio, onCropChange, maxCroppedSize } = props;\n const acceptedFile = useFileUploadContext().acceptedFiles[0];\n\n return (\n <>\n {!acceptedFile && <Dropzone />}\n {acceptedFile && variant === 'image' && (\n <ImagePreview aspectRatio={aspectRatio} onCropChange={onCropChange} maxCroppedSize={maxCroppedSize} />\n )}\n {acceptedFile && variant !== 'image' && <NonImagePreview />}\n </>\n );\n};\n\nconst BitkitFileInput = forwardRef<HTMLDivElement, BitkitFileInputProps>((props, ref) => {\n const { aspectRatio, maxCroppedSize, onCropChange, onFileAccept, onFileAccepted, state, variant, ...rest } = props;\n const [fileUploadProps, fieldProps] = splitFileUploadProps(rest as never);\n\n const handleFileAccept = (details: FileUploadFileAcceptDetails) => {\n onFileAccept?.(details);\n onFileAccepted?.(details.files[0]);\n };\n\n const contentProps = {\n variant,\n aspectRatio,\n onCropChange,\n maxCroppedSize,\n };\n\n return (\n <BitkitField ref={ref} state={state} {...fieldProps}>\n <FileUpload.Root variant={variant} onFileAccept={handleFileAccept} {...fileUploadProps}>\n <FileUpload.HiddenInput />\n <BitkitFileInputContent {...contentProps} />\n </FileUpload.Root>\n </BitkitField>\n );\n});\n\nBitkitFileInput.displayName = 'BitkitFileInput';\n\nexport default BitkitFileInput;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bitrise/bitkit-v2",
3
3
  "private": false,
4
- "version": "0.3.283",
4
+ "version": "0.3.284",
5
5
  "description": "Bitrise Design System Components built with Chakra UI V3",
6
6
  "keywords": [
7
7
  "react",