@minutemailer/kit 1.2.3 → 1.2.4
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.
|
@@ -12,6 +12,7 @@ export interface ImageSlotProps {
|
|
|
12
12
|
alt?: string;
|
|
13
13
|
width: number;
|
|
14
14
|
height: number;
|
|
15
|
+
scale?: number;
|
|
15
16
|
actions?: ImageSlotAction[];
|
|
16
17
|
onAction?: (action: string) => void;
|
|
17
18
|
onRemove?: () => void;
|
|
@@ -21,5 +22,5 @@ export interface ImageSlotProps {
|
|
|
21
22
|
className?: string;
|
|
22
23
|
style?: CSSProperties;
|
|
23
24
|
}
|
|
24
|
-
declare function ImageSlot({ src, s3, alt, width, height, actions, onAction, onRemove, onFile, loading, accept, className, style, }: ImageSlotProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
declare function ImageSlot({ src, s3, alt, width, height, scale, actions, onAction, onRemove, onFile, loading, accept, className, style, }: ImageSlotProps): import("react/jsx-runtime").JSX.Element;
|
|
25
26
|
export { ImageSlot };
|
package/components/image-slot.js
CHANGED
|
@@ -7,8 +7,7 @@ import { Spinner } from '../components/ui/spinner.js';
|
|
|
7
7
|
import { toast } from 'sonner';
|
|
8
8
|
import { ChevronDownIcon, ImageIcon, Trash2Icon } from 'lucide-react';
|
|
9
9
|
import { S3Image } from '../components/s3-image.js';
|
|
10
|
-
function ImageSlot({ src, s3, alt = '', width, height, actions = [], onAction, onRemove, onFile, loading = false, accept = ['image/gif', 'image/png', 'image/jpeg'], className, style, }) {
|
|
11
|
-
const aspectRatio = width / height;
|
|
10
|
+
function ImageSlot({ src, s3, alt = '', width, height, scale = 1, actions = [], onAction, onRemove, onFile, loading = false, accept = ['image/gif', 'image/png', 'image/jpeg'], className, style, }) {
|
|
12
11
|
const [dragState, setDragState] = useState('idle');
|
|
13
12
|
const dragCounterRef = useRef(0);
|
|
14
13
|
const fileInputRef = useRef(null);
|
|
@@ -87,19 +86,19 @@ function ImageSlot({ src, s3, alt = '', width, height, actions = [], onAction, o
|
|
|
87
86
|
onRemove?.();
|
|
88
87
|
setS3ImageData(null);
|
|
89
88
|
};
|
|
90
|
-
const
|
|
91
|
-
const containerHeight = s3ImageData ? s3ImageData.height : height;
|
|
89
|
+
const maxWidth = s3ImageData ? s3ImageData.width * scale : width * scale;
|
|
92
90
|
if (src || s3) {
|
|
93
91
|
return (_jsxs("div", { className: cn('relative group', className), style: {
|
|
94
|
-
width:
|
|
95
|
-
|
|
92
|
+
width: '100%',
|
|
93
|
+
maxWidth,
|
|
94
|
+
aspectRatio: `${width} / ${height}`,
|
|
96
95
|
...style,
|
|
97
96
|
}, children: [s3 ? (_jsx(S3Image, { ...s3, width: width, height: height, onLoaded: onS3ImageLoaded, alt: alt, className: "block w-full h-full object-cover" })) : (_jsx("img", { src: src, alt: alt, width: width, height: height, className: "block w-full h-full object-cover" })), onRemove && (_jsx("div", { className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center", children: _jsx(Button, { variant: "outline", className: "rounded-full", size: "icon", onClick: handleRemove, children: _jsx(Trash2Icon, {}) }) }))] }));
|
|
98
97
|
}
|
|
99
98
|
// Placeholder view
|
|
100
99
|
return (_jsx("div", { "data-slot": "image-slot", className: cn('bg-muted flex items-center justify-center @container transition-colors', dragState === 'over' && 'bg-green-100 dark:bg-green-950', className), style: {
|
|
101
100
|
width: '100%',
|
|
102
|
-
maxWidth: width,
|
|
101
|
+
maxWidth: width * scale,
|
|
103
102
|
aspectRatio: `${width} / ${height}`,
|
|
104
103
|
...style,
|
|
105
104
|
}, onDragEnter: handleDragEnter, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: loading ? (_jsx(Spinner, { className: "size-8" })) : dragState === 'over' ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Drop image to upload" })) : (_jsxs(_Fragment, { children: [_jsx("input", { ref: fileInputRef, type: "file", accept: accept.join(','), onChange: handleFileInputChange, className: "hidden" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", children: [_jsx(ImageIcon, { className: "@xs:hidden" }), _jsx("span", { className: "hidden @xs:inline", children: "Add image" }), _jsx(ChevronDownIcon, { className: "hidden @xs:inline" })] }) }), _jsx(DropdownMenuContent, { children: actions.map((action) => (_jsxs(DropdownMenuItem, { onClick: () => handleActionClick(action), children: [action.icon, action.name] }, action.value))) })] })] })) }));
|
package/components/s3-image.js
CHANGED
|
@@ -9,12 +9,12 @@ function S3Image({ imageKey, width, height = 0, fit = 'inside', retina = true, o
|
|
|
9
9
|
const [loading, setLoading] = useState(true);
|
|
10
10
|
const [error, setError] = useState(false);
|
|
11
11
|
// Calculate container dimensions
|
|
12
|
-
const containerWidth = width === 'auto'
|
|
12
|
+
const containerWidth = imageData?.width || width === 'auto'
|
|
13
13
|
? undefined
|
|
14
14
|
: typeof width === 'string'
|
|
15
15
|
? parseInt(width, 10)
|
|
16
16
|
: width;
|
|
17
|
-
const containerHeight = height === 'auto'
|
|
17
|
+
const containerHeight = imageData?.height || height === 'auto'
|
|
18
18
|
? undefined
|
|
19
19
|
: typeof height === 'string'
|
|
20
20
|
? parseInt(height, 10)
|
|
@@ -48,9 +48,13 @@ function S3Image({ imageKey, width, height = 0, fit = 'inside', retina = true, o
|
|
|
48
48
|
JSON.stringify(edits),
|
|
49
49
|
s3Image,
|
|
50
50
|
]);
|
|
51
|
+
const aspectRatio = containerWidth && containerHeight
|
|
52
|
+
? `${containerWidth} / ${containerHeight}`
|
|
53
|
+
: undefined;
|
|
51
54
|
const containerStyle = {
|
|
52
|
-
width:
|
|
53
|
-
|
|
55
|
+
width: '100%',
|
|
56
|
+
maxWidth: imageData ? imageData.width : containerWidth || undefined,
|
|
57
|
+
aspectRatio: aspectRatio,
|
|
54
58
|
};
|
|
55
59
|
if (!imageKey) {
|
|
56
60
|
return null;
|