@timmbr/ui 1.0.0-beta → 1.2.0
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.
- package/README.md +20 -16
- package/dist/components/Accordion/Accordion.d.ts.map +1 -1
- package/dist/components/Alert/Alert.types.d.ts +2 -4
- package/dist/components/Alert/Alert.types.d.ts.map +1 -1
- package/dist/components/AlertDialog/AlertDialog.d.ts +16 -0
- package/dist/components/AlertDialog/AlertDialog.d.ts.map +1 -0
- package/dist/components/AlertDialog/AlertDialog.js +94 -0
- package/dist/components/AlertDialog/AlertDialog.styles.d.ts +8 -0
- package/dist/components/AlertDialog/AlertDialog.styles.d.ts.map +1 -0
- package/dist/components/AlertDialog/AlertDialog.styles.js +25 -0
- package/dist/components/AlertDialog/AlertDialog.types.d.ts +16 -0
- package/dist/components/AlertDialog/AlertDialog.types.d.ts.map +1 -0
- package/dist/components/AlertDialog/index.d.ts +4 -0
- package/dist/components/AlertDialog/index.d.ts.map +1 -0
- package/dist/components/Avatar/Avatar.styles.d.ts +2 -2
- package/dist/components/Badge/Badge.styles.d.ts +1 -1
- package/dist/components/Button/Button.styles.d.ts +2 -2
- package/dist/components/Chip/Chip.styles.d.ts +1 -1
- package/dist/components/CrossZoneLink/CrossZoneLink.d.ts +10 -0
- package/dist/components/CrossZoneLink/CrossZoneLink.d.ts.map +1 -0
- package/dist/components/CrossZoneLink/CrossZoneLink.js +111 -0
- package/dist/components/CrossZoneLink/CrossZoneLink.styles.d.ts +8 -0
- package/dist/components/CrossZoneLink/CrossZoneLink.styles.d.ts.map +1 -0
- package/dist/components/CrossZoneLink/CrossZoneLink.styles.js +33 -0
- package/dist/components/CrossZoneLink/CrossZoneLink.types.d.ts +31 -0
- package/dist/components/CrossZoneLink/CrossZoneLink.types.d.ts.map +1 -0
- package/dist/components/CrossZoneLink/index.d.ts +4 -0
- package/dist/components/CrossZoneLink/index.d.ts.map +1 -0
- package/dist/components/Dialog/Dialog.d.ts +2 -1
- package/dist/components/Dialog/Dialog.d.ts.map +1 -1
- package/dist/components/Dialog/Dialog.js +8 -6
- package/dist/components/Dialog/Dialog.styles.d.ts +1 -0
- package/dist/components/Dialog/Dialog.styles.d.ts.map +1 -1
- package/dist/components/Dialog/Dialog.styles.js +7 -4
- package/dist/components/Dialog/Dialog.types.d.ts +4 -6
- package/dist/components/Dialog/Dialog.types.d.ts.map +1 -1
- package/dist/components/Divider/Divider.styles.d.ts +1 -1
- package/dist/components/Drawer/Drawer.types.d.ts +3 -6
- package/dist/components/Drawer/Drawer.types.d.ts.map +1 -1
- package/dist/components/Dropdown/Dropdown.types.d.ts +1 -2
- package/dist/components/Dropdown/Dropdown.types.d.ts.map +1 -1
- package/dist/components/FormField/FormField.js +2 -2
- package/dist/components/Heading/Heading.styles.d.ts +2 -2
- package/dist/components/Icon/Icon.styles.d.ts +1 -1
- package/dist/components/ImageUpload/ImageUpload.d.ts +4 -0
- package/dist/components/ImageUpload/ImageUpload.d.ts.map +1 -0
- package/dist/components/ImageUpload/ImageUpload.helpers.d.ts +30 -0
- package/dist/components/ImageUpload/ImageUpload.helpers.d.ts.map +1 -0
- package/dist/components/ImageUpload/ImageUpload.helpers.js +95 -0
- package/dist/components/ImageUpload/ImageUpload.js +365 -0
- package/dist/components/ImageUpload/ImageUpload.styles.d.ts +17 -0
- package/dist/components/ImageUpload/ImageUpload.styles.d.ts.map +1 -0
- package/dist/components/ImageUpload/ImageUpload.styles.js +72 -0
- package/dist/components/ImageUpload/ImageUpload.types.d.ts +112 -0
- package/dist/components/ImageUpload/ImageUpload.types.d.ts.map +1 -0
- package/dist/components/ImageUpload/index.d.ts +6 -0
- package/dist/components/ImageUpload/index.d.ts.map +1 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadDropzone.d.ts +25 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadDropzone.d.ts.map +1 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadDropzone.js +106 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadIcons.d.ts +6 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadIcons.d.ts.map +1 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadIcons.js +61 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadModal.d.ts +12 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadModal.d.ts.map +1 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadModal.js +137 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadSinglePreview.d.ts +14 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadSinglePreview.d.ts.map +1 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadSinglePreview.js +142 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadThumbnailCard.d.ts +23 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadThumbnailCard.d.ts.map +1 -0
- package/dist/components/ImageUpload/subcomponents/ImageUploadThumbnailCard.js +139 -0
- package/dist/components/ImageUpload/subcomponents/index.d.ts +6 -0
- package/dist/components/ImageUpload/subcomponents/index.d.ts.map +1 -0
- package/dist/components/Inline/Inline.styles.d.ts +2 -2
- package/dist/components/Input/Input.js +2 -2
- package/dist/components/Input/Input.styles.d.ts +1 -1
- package/dist/components/Input/Input.styles.js +1 -1
- package/dist/components/Input/Input.types.d.ts +1 -1
- package/dist/components/Input/Input.types.d.ts.map +1 -1
- package/dist/components/LinkButton/LinkButton.d.ts +13 -0
- package/dist/components/LinkButton/LinkButton.d.ts.map +1 -0
- package/dist/components/LinkButton/LinkButton.js +179 -0
- package/dist/components/LinkButton/LinkButton.styles.d.ts +8 -0
- package/dist/components/LinkButton/LinkButton.styles.d.ts.map +1 -0
- package/dist/components/LinkButton/LinkButton.styles.js +61 -0
- package/dist/components/LinkButton/LinkButton.types.d.ts +60 -0
- package/dist/components/LinkButton/LinkButton.types.d.ts.map +1 -0
- package/dist/components/LinkButton/index.d.ts +4 -0
- package/dist/components/LinkButton/index.d.ts.map +1 -0
- package/dist/components/List/List.types.d.ts +2 -4
- package/dist/components/List/List.types.d.ts.map +1 -1
- package/dist/components/Popover/Popover.types.d.ts +1 -2
- package/dist/components/Popover/Popover.types.d.ts.map +1 -1
- package/dist/components/Progress/Progress.styles.d.ts +1 -1
- package/dist/components/Radio/Radio.js +2 -2
- package/dist/components/Select/Select.js +2 -2
- package/dist/components/Select/Select.styles.d.ts +1 -1
- package/dist/components/SideBarNavigation/SideBarNavigation.context.d.ts +15 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.context.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.context.js +10 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.d.ts +4 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.helpers.d.ts +19 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.helpers.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.helpers.js +48 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.js +132 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.styles.d.ts +18 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.styles.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.styles.js +85 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.types.d.ts +69 -0
- package/dist/components/SideBarNavigation/SideBarNavigation.types.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/index.d.ts +13 -0
- package/dist/components/SideBarNavigation/index.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarBranding.d.ts +13 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarBranding.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarBranding.js +58 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarFooter.d.ts +10 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarFooter.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarFooter.js +27 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarNavItem.d.ts +14 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarNavItem.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarNavItem.js +147 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarPopoverMenu.d.ts +13 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarPopoverMenu.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarPopoverMenu.js +106 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarProfile.d.ts +13 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarProfile.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarProfile.js +118 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarSubItem.d.ts +13 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarSubItem.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarSubItem.js +34 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarToggle.d.ts +8 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarToggle.d.ts.map +1 -0
- package/dist/components/SideBarNavigation/subcomponents/SidebarToggle.js +40 -0
- package/dist/components/Stack/Stack.styles.d.ts +2 -2
- package/dist/components/Stat/Stat.types.d.ts +3 -6
- package/dist/components/Stat/Stat.types.d.ts.map +1 -1
- package/dist/components/Table/Table.types.d.ts +7 -14
- package/dist/components/Table/Table.types.d.ts.map +1 -1
- package/dist/components/Tabs/Tabs.styles.d.ts +2 -2
- package/dist/components/Text/Text.styles.d.ts +2 -2
- package/dist/components/Textarea/Textarea.js +2 -2
- package/dist/components/Textarea/Textarea.styles.d.ts +1 -1
- package/dist/components/Toast/Toast.d.ts.map +1 -1
- package/dist/components/Toast/Toast.js +13 -4
- package/dist/components/Toast/Toast.types.d.ts +35 -2
- package/dist/components/Toast/Toast.types.d.ts.map +1 -1
- package/dist/components/Toast/ToastContainer.d.ts +7 -0
- package/dist/components/Toast/ToastContainer.d.ts.map +1 -0
- package/dist/components/Toast/ToastContainer.js +104 -0
- package/dist/components/Toast/index.d.ts +2 -0
- package/dist/components/Toast/index.d.ts.map +1 -1
- package/dist/components/Toast/toastStore.d.ts +31 -0
- package/dist/components/Toast/toastStore.d.ts.map +1 -0
- package/dist/components/Toast/toastStore.js +104 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -3
- package/dist/providers/TimmbrConfigProvider.d.ts +20 -2
- package/dist/providers/TimmbrConfigProvider.d.ts.map +1 -1
- package/dist/providers/TimmbrConfigProvider.js +38 -3
- package/package.json +15 -6
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
2
|
+
export declare const imageUploadZoneVariants: (props?: ({
|
|
3
|
+
aspectRatio?: "video" | "auto" | "square" | "wide" | null | undefined;
|
|
4
|
+
size?: "default" | "compact" | null | undefined;
|
|
5
|
+
isDragging?: boolean | null | undefined;
|
|
6
|
+
isError?: boolean | null | undefined;
|
|
7
|
+
isDisabled?: boolean | null | undefined;
|
|
8
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
9
|
+
export declare const imagePreviewContainerVariants: (props?: ({
|
|
10
|
+
aspectRatio?: "video" | "auto" | "square" | "wide" | null | undefined;
|
|
11
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
12
|
+
export declare const thumbnailCardVariants: (props?: ({
|
|
13
|
+
aspectRatio?: "video" | "auto" | "square" | "wide" | null | undefined;
|
|
14
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
15
|
+
export type ImageUploadZoneVariants = VariantProps<typeof imageUploadZoneVariants>;
|
|
16
|
+
export type ImagePreviewContainerVariants = VariantProps<typeof imagePreviewContainerVariants>;
|
|
17
|
+
//# sourceMappingURL=ImageUpload.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageUpload.styles.d.ts","sourceRoot":"","sources":["../../../src/components/ImageUpload/ImageUpload.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,uBAAuB;;;;;;8EAmCnC,CAAC;AAEF,eAAO,MAAM,6BAA6B;;8EAezC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;8EAejC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACnF,MAAM,MAAM,6BAA6B,GAAG,YAAY,CAAC,OAAO,6BAA6B,CAAC,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { cva } from 'class-variance-authority';
|
|
2
|
+
|
|
3
|
+
const imageUploadZoneVariants = cva(
|
|
4
|
+
"relative rounded-xl border-2 border-dashed transition-all duration-200 flex flex-col items-center justify-center text-center select-none font-sans outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:border-primary",
|
|
5
|
+
{
|
|
6
|
+
variants: {
|
|
7
|
+
aspectRatio: {
|
|
8
|
+
square: "size-32 p-2 aspect-square shrink-0",
|
|
9
|
+
video: "w-full aspect-[16/10] min-h-[160px] p-5",
|
|
10
|
+
wide: "w-full aspect-[21/9] min-h-[130px] p-5",
|
|
11
|
+
auto: "w-full min-h-[130px] p-5"
|
|
12
|
+
},
|
|
13
|
+
size: {
|
|
14
|
+
default: "",
|
|
15
|
+
compact: "py-3 px-2 min-h-[80px]"
|
|
16
|
+
},
|
|
17
|
+
isDragging: {
|
|
18
|
+
true: "border-primary bg-primary-50/40 dark:bg-primary-950/20 scale-[0.99] shadow-sm",
|
|
19
|
+
false: ""
|
|
20
|
+
},
|
|
21
|
+
isError: {
|
|
22
|
+
true: "border-destructive/80 bg-destructive/5 hover:border-destructive",
|
|
23
|
+
false: "border-grey-300 dark:border-grey-700 bg-grey-50/60 dark:bg-grey-900/40 hover:border-grey-400 hover:bg-grey-50 dark:hover:bg-grey-900/60"
|
|
24
|
+
},
|
|
25
|
+
isDisabled: {
|
|
26
|
+
true: "opacity-50 cursor-not-allowed pointer-events-none",
|
|
27
|
+
false: "cursor-pointer"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
defaultVariants: {
|
|
31
|
+
aspectRatio: "auto",
|
|
32
|
+
size: "default",
|
|
33
|
+
isDragging: false,
|
|
34
|
+
isError: false,
|
|
35
|
+
isDisabled: false
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
const imagePreviewContainerVariants = cva(
|
|
40
|
+
"relative group rounded-xl border border-grey-200 dark:border-grey-800 bg-grey-50 dark:bg-grey-900 overflow-hidden flex items-center justify-center transition-all shadow-xs",
|
|
41
|
+
{
|
|
42
|
+
variants: {
|
|
43
|
+
aspectRatio: {
|
|
44
|
+
square: "size-32 aspect-square shrink-0",
|
|
45
|
+
video: "w-full aspect-[16/10]",
|
|
46
|
+
wide: "w-full aspect-[21/9]",
|
|
47
|
+
auto: "w-full h-44"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
defaultVariants: {
|
|
51
|
+
aspectRatio: "auto"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
const thumbnailCardVariants = cva(
|
|
56
|
+
"relative group rounded-xl border border-grey-200 dark:border-grey-800 bg-grey-100 dark:bg-grey-900 overflow-hidden transition-all shadow-xs hover:shadow-md hover:border-grey-300 dark:hover:border-grey-700",
|
|
57
|
+
{
|
|
58
|
+
variants: {
|
|
59
|
+
aspectRatio: {
|
|
60
|
+
square: "aspect-square",
|
|
61
|
+
video: "aspect-[16/10]",
|
|
62
|
+
wide: "aspect-[21/9]",
|
|
63
|
+
auto: "aspect-square min-h-[110px]"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
defaultVariants: {
|
|
67
|
+
aspectRatio: "square"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
export { imagePreviewContainerVariants, imageUploadZoneVariants, thumbnailCardVariants };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
import type { MotionProps } from '../../types/motion';
|
|
3
|
+
export type ImageUploadAspectRatio = 'square' | 'video' | 'wide' | 'auto';
|
|
4
|
+
export type ImageUploadMediaType = 'image' | 'video' | 'all';
|
|
5
|
+
export interface ImageUploadItem {
|
|
6
|
+
url: string;
|
|
7
|
+
key?: string;
|
|
8
|
+
id?: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
size?: number;
|
|
11
|
+
type?: 'image' | 'video' | string;
|
|
12
|
+
}
|
|
13
|
+
export type ImageUploadValue = string | ImageUploadItem;
|
|
14
|
+
export interface ImageUploadProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'value'>, MotionProps {
|
|
15
|
+
/**
|
|
16
|
+
* Current media URL(s) to display as preview.
|
|
17
|
+
* Single string/object for single mode, array for multiple mode.
|
|
18
|
+
*/
|
|
19
|
+
value?: ImageUploadValue | ImageUploadValue[] | null;
|
|
20
|
+
/**
|
|
21
|
+
* Whether multiple media uploads are supported.
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
multiple?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Media types accepted by the component.
|
|
27
|
+
* @default "image"
|
|
28
|
+
*/
|
|
29
|
+
mediaType?: ImageUploadMediaType;
|
|
30
|
+
/**
|
|
31
|
+
* Minimum number of files required (for multiple uploads validation).
|
|
32
|
+
*/
|
|
33
|
+
minFiles?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Maximum number of files allowed (for multiple uploads validation).
|
|
36
|
+
*/
|
|
37
|
+
maxFiles?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Callback fired when files are selected by the user.
|
|
40
|
+
*/
|
|
41
|
+
onChange?: (files: File[] | File | null) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Optional async upload handler.
|
|
44
|
+
*/
|
|
45
|
+
onUpload?: (file: File) => Promise<{
|
|
46
|
+
url: string;
|
|
47
|
+
key?: string;
|
|
48
|
+
type?: string;
|
|
49
|
+
} | string>;
|
|
50
|
+
/**
|
|
51
|
+
* Callback fired when an item is removed by the user.
|
|
52
|
+
* In multi mode, receives the index and item being removed.
|
|
53
|
+
*/
|
|
54
|
+
onRemove?: (index?: number, item?: ImageUploadItem | string) => void;
|
|
55
|
+
/**
|
|
56
|
+
* Disable the upload zone and actions.
|
|
57
|
+
*/
|
|
58
|
+
disabled?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Manually control the global loading state.
|
|
61
|
+
*/
|
|
62
|
+
loading?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Custom loading text displayed during upload.
|
|
65
|
+
*/
|
|
66
|
+
loadingText?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Accepted MIME types or extensions.
|
|
69
|
+
* Defaults automatically based on `mediaType`.
|
|
70
|
+
*/
|
|
71
|
+
accept?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Maximum allowed file size in bytes per file.
|
|
74
|
+
* @default 5242880 (5MB) for images, 52428800 (50MB) for videos
|
|
75
|
+
*/
|
|
76
|
+
maxSizeBytes?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Label rendered above the upload dropzone.
|
|
79
|
+
*/
|
|
80
|
+
label?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Subtitle / helper instructions rendered below the dropzone.
|
|
83
|
+
*/
|
|
84
|
+
helperText?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Error message to display.
|
|
87
|
+
*/
|
|
88
|
+
error?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Aspect ratio of the dropzone / preview cards.
|
|
91
|
+
* @default "auto"
|
|
92
|
+
*/
|
|
93
|
+
aspectRatio?: ImageUploadAspectRatio;
|
|
94
|
+
/**
|
|
95
|
+
* Grid columns for multiple image previews.
|
|
96
|
+
* @default 4 (responsive 2-4 columns)
|
|
97
|
+
*/
|
|
98
|
+
gridCols?: 2 | 3 | 4 | 5;
|
|
99
|
+
/**
|
|
100
|
+
* Layout mode for multiple image previews.
|
|
101
|
+
* - 'grid': Responsive multi-column wrap grid (default)
|
|
102
|
+
* - 'scroll': Sleek horizontal scroll strip with snap points
|
|
103
|
+
* @default "grid"
|
|
104
|
+
*/
|
|
105
|
+
layout?: 'grid' | 'scroll';
|
|
106
|
+
/**
|
|
107
|
+
* Whether to enable the inline full-screen media lightbox popup.
|
|
108
|
+
* @default true
|
|
109
|
+
*/
|
|
110
|
+
enablePreviewModal?: boolean;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=ImageUpload.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageUpload.types.d.ts","sourceRoot":"","sources":["../../../src/components/ImageUpload/ImageUpload.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1E,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;CACnC;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,eAAe,CAAC;AAExD,MAAM,WAAW,gBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,EACtE,WAAW;IACb;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;IAErD;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,oBAAoB,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IAEjD;;OAEG;IACH,QAAQ,CAAC,EAAE,CACT,IAAI,EAAE,IAAI,KACP,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,CAAC;IAEpE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,MAAM,KAAK,IAAI,CAAC;IAErE;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,WAAW,CAAC,EAAE,sBAAsB,CAAC;IAErC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEzB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAE3B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ImageUpload/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ImageUploadAspectRatio, ImageUploadMediaType } from '../ImageUpload.types';
|
|
3
|
+
export interface ImageUploadDropzoneProps {
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
isUploading?: boolean;
|
|
6
|
+
loadingText?: string;
|
|
7
|
+
isDragging: boolean;
|
|
8
|
+
isError: boolean;
|
|
9
|
+
aspectRatio: ImageUploadAspectRatio;
|
|
10
|
+
size?: 'default' | 'compact';
|
|
11
|
+
mediaType: ImageUploadMediaType;
|
|
12
|
+
maxSizeBytes: number;
|
|
13
|
+
maxFiles?: number;
|
|
14
|
+
multiple?: boolean;
|
|
15
|
+
hasItems?: boolean;
|
|
16
|
+
shouldAnimate?: boolean;
|
|
17
|
+
motionClass?: string;
|
|
18
|
+
onClick: () => void;
|
|
19
|
+
onDragEnter: (e: React.DragEvent) => void;
|
|
20
|
+
onDragOver: (e: React.DragEvent) => void;
|
|
21
|
+
onDragLeave: (e: React.DragEvent) => void;
|
|
22
|
+
onDrop: (e: React.DragEvent) => void;
|
|
23
|
+
}
|
|
24
|
+
export declare const ImageUploadDropzone: React.FC<ImageUploadDropzoneProps>;
|
|
25
|
+
//# sourceMappingURL=ImageUploadDropzone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageUploadDropzone.d.ts","sourceRoot":"","sources":["../../../../src/components/ImageUpload/subcomponents/ImageUploadDropzone.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,sBAAsB,CAAC;IACpC,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,SAAS,EAAE,oBAAoB,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;IAC1C,UAAU,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;IACzC,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;CACtC;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAqIlE,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import { cn } from '@timmbr/utils';
|
|
4
|
+
import { Plus } from '@timmbr/icons';
|
|
5
|
+
import { imageUploadZoneVariants } from '../ImageUpload.styles.js';
|
|
6
|
+
import { UploadCloudIcon, ImageIcon, FilmIcon } from './ImageUploadIcons.js';
|
|
7
|
+
import { Spinner } from '../../Spinner/Spinner.js';
|
|
8
|
+
|
|
9
|
+
const ImageUploadDropzone = ({
|
|
10
|
+
disabled,
|
|
11
|
+
isUploading,
|
|
12
|
+
loadingText,
|
|
13
|
+
isDragging,
|
|
14
|
+
isError,
|
|
15
|
+
aspectRatio,
|
|
16
|
+
size = "default",
|
|
17
|
+
mediaType,
|
|
18
|
+
maxSizeBytes,
|
|
19
|
+
maxFiles,
|
|
20
|
+
multiple: _multiple = false,
|
|
21
|
+
hasItems = false,
|
|
22
|
+
shouldAnimate = true,
|
|
23
|
+
motionClass,
|
|
24
|
+
onClick,
|
|
25
|
+
onDragEnter,
|
|
26
|
+
onDragOver,
|
|
27
|
+
onDragLeave,
|
|
28
|
+
onDrop
|
|
29
|
+
}) => {
|
|
30
|
+
const maxMb = Math.round(maxSizeBytes / (1024 * 1024));
|
|
31
|
+
return /* @__PURE__ */ jsx(
|
|
32
|
+
"div",
|
|
33
|
+
{
|
|
34
|
+
role: "button",
|
|
35
|
+
tabIndex: 0,
|
|
36
|
+
onClick,
|
|
37
|
+
onKeyDown: (e) => {
|
|
38
|
+
if ((e.key === "Enter" || e.key === " ") && !disabled && !isUploading) {
|
|
39
|
+
onClick();
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
onDragEnter,
|
|
43
|
+
onDragOver,
|
|
44
|
+
onDragLeave,
|
|
45
|
+
onDrop,
|
|
46
|
+
style: aspectRatio === "square" ? {
|
|
47
|
+
width: "120px",
|
|
48
|
+
height: "120px",
|
|
49
|
+
minWidth: "120px",
|
|
50
|
+
minHeight: "120px",
|
|
51
|
+
maxWidth: "120px",
|
|
52
|
+
maxHeight: "120px"
|
|
53
|
+
} : void 0,
|
|
54
|
+
className: cn(
|
|
55
|
+
imageUploadZoneVariants({
|
|
56
|
+
aspectRatio,
|
|
57
|
+
size,
|
|
58
|
+
isDragging,
|
|
59
|
+
isError,
|
|
60
|
+
isDisabled: disabled
|
|
61
|
+
}),
|
|
62
|
+
!shouldAnimate && "transition-none",
|
|
63
|
+
motionClass
|
|
64
|
+
),
|
|
65
|
+
children: isUploading ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-2", children: [
|
|
66
|
+
/* @__PURE__ */ jsx(Spinner, { size: "md" }),
|
|
67
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-foreground", children: loadingText })
|
|
68
|
+
] }) : size === "compact" ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-1.5 text-center pointer-events-none", children: [
|
|
69
|
+
/* @__PURE__ */ jsx("div", { className: "size-8 rounded-lg bg-white dark:bg-grey-800 border border-grey-200 dark:border-grey-700 shadow-xs flex items-center justify-center text-primary", children: isDragging ? /* @__PURE__ */ jsx(UploadCloudIcon, { className: "size-4 text-primary animate-bounce" }) : /* @__PURE__ */ jsx(Plus, { className: "size-4 text-primary" }) }),
|
|
70
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
71
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
72
|
+
/* @__PURE__ */ jsx("span", { className: "text-primary underline font-semibold", children: hasItems ? "Add more files" : "Click to upload" }),
|
|
73
|
+
" ",
|
|
74
|
+
"or drag & drop"
|
|
75
|
+
] }),
|
|
76
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[11px] text-muted", children: [
|
|
77
|
+
mediaType === "video" ? `MP4, WEBM, MOV (Max ${maxMb}MB)` : mediaType === "all" ? `Images & Videos (Max ${maxMb}MB each)` : `PNG, JPG, WEBP (Max ${maxMb}MB each)`,
|
|
78
|
+
maxFiles && ` • Up to ${maxFiles} items`
|
|
79
|
+
] })
|
|
80
|
+
] })
|
|
81
|
+
] }) : aspectRatio === "square" ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-1.5 text-center pointer-events-none p-1", children: [
|
|
82
|
+
/* @__PURE__ */ jsx("div", { className: "size-8 rounded-lg bg-white dark:bg-grey-800 border border-grey-200 dark:border-grey-700 shadow-xs flex items-center justify-center text-primary", children: isDragging ? /* @__PURE__ */ jsx(UploadCloudIcon, { className: "size-4 text-primary animate-bounce" }) : /* @__PURE__ */ jsx(ImageIcon, { className: "size-4 text-primary" }) }),
|
|
83
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
84
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-primary underline", children: "Upload" }),
|
|
85
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted", children: [
|
|
86
|
+
"Max ",
|
|
87
|
+
maxMb,
|
|
88
|
+
"MB"
|
|
89
|
+
] })
|
|
90
|
+
] })
|
|
91
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-2 text-center pointer-events-none", children: [
|
|
92
|
+
/* @__PURE__ */ jsx("div", { className: "size-10 rounded-xl bg-white dark:bg-grey-800 border border-grey-200 dark:border-grey-700 shadow-xs flex items-center justify-center text-primary", children: isDragging ? /* @__PURE__ */ jsx(UploadCloudIcon, { className: "size-5 text-primary animate-bounce" }) : mediaType === "video" ? /* @__PURE__ */ jsx(FilmIcon, { className: "size-5 text-primary" }) : /* @__PURE__ */ jsx(ImageIcon, { className: "size-5 text-primary" }) }),
|
|
93
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
94
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
95
|
+
/* @__PURE__ */ jsx("span", { className: "text-primary underline font-semibold", children: "Click to upload" }),
|
|
96
|
+
" or drag and drop"
|
|
97
|
+
] }),
|
|
98
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-muted", children: mediaType === "video" ? `MP4, WEBM, MOV (Max ${maxMb}MB)` : mediaType === "all" ? `PNG, JPG, WEBP, MP4 (Max ${maxMb}MB)` : `PNG, JPG, or WEBP (Max ${maxMb}MB)` })
|
|
99
|
+
] })
|
|
100
|
+
] })
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
ImageUploadDropzone.displayName = "ImageUploadDropzone";
|
|
105
|
+
|
|
106
|
+
export { ImageUploadDropzone };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export declare const UploadCloudIcon: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
3
|
+
export declare const ImageIcon: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
4
|
+
export declare const PlayIcon: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
5
|
+
export declare const FilmIcon: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
6
|
+
//# sourceMappingURL=ImageUploadIcons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageUploadIcons.d.ts","sourceRoot":"","sources":["../../../../src/components/ImageUpload/subcomponents/ImageUploadIcons.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAcnE,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAc7D,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAI5D,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAmB5D,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
const UploadCloudIcon = (props) => /* @__PURE__ */ jsxs(
|
|
4
|
+
"svg",
|
|
5
|
+
{
|
|
6
|
+
viewBox: "0 0 24 24",
|
|
7
|
+
fill: "none",
|
|
8
|
+
stroke: "currentColor",
|
|
9
|
+
strokeWidth: "2",
|
|
10
|
+
strokeLinecap: "round",
|
|
11
|
+
strokeLinejoin: "round",
|
|
12
|
+
...props,
|
|
13
|
+
children: [
|
|
14
|
+
/* @__PURE__ */ jsx("path", { d: "M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242" }),
|
|
15
|
+
/* @__PURE__ */ jsx("path", { d: "M12 12v9" }),
|
|
16
|
+
/* @__PURE__ */ jsx("path", { d: "m16 16-4-4-4 4" })
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
const ImageIcon = (props) => /* @__PURE__ */ jsxs(
|
|
21
|
+
"svg",
|
|
22
|
+
{
|
|
23
|
+
viewBox: "0 0 24 24",
|
|
24
|
+
fill: "none",
|
|
25
|
+
stroke: "currentColor",
|
|
26
|
+
strokeWidth: "2",
|
|
27
|
+
strokeLinecap: "round",
|
|
28
|
+
strokeLinejoin: "round",
|
|
29
|
+
...props,
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
|
|
32
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
|
|
33
|
+
/* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
const PlayIcon = (props) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", stroke: "none", ...props, children: /* @__PURE__ */ jsx("polygon", { points: "6 3 20 12 6 21 6 3" }) });
|
|
38
|
+
const FilmIcon = (props) => /* @__PURE__ */ jsxs(
|
|
39
|
+
"svg",
|
|
40
|
+
{
|
|
41
|
+
viewBox: "0 0 24 24",
|
|
42
|
+
fill: "none",
|
|
43
|
+
stroke: "currentColor",
|
|
44
|
+
strokeWidth: "2",
|
|
45
|
+
strokeLinecap: "round",
|
|
46
|
+
strokeLinejoin: "round",
|
|
47
|
+
...props,
|
|
48
|
+
children: [
|
|
49
|
+
/* @__PURE__ */ jsx("rect", { width: "20", height: "20", x: "2", y: "2", rx: "2.18", ry: "2.18" }),
|
|
50
|
+
/* @__PURE__ */ jsx("line", { x1: "7", x2: "7", y1: "2", y2: "22" }),
|
|
51
|
+
/* @__PURE__ */ jsx("line", { x1: "17", x2: "17", y1: "2", y2: "22" }),
|
|
52
|
+
/* @__PURE__ */ jsx("line", { x1: "2", x2: "22", y1: "12", y2: "12" }),
|
|
53
|
+
/* @__PURE__ */ jsx("line", { x1: "2", x2: "7", y1: "7", y2: "7" }),
|
|
54
|
+
/* @__PURE__ */ jsx("line", { x1: "2", x2: "7", y1: "17", y2: "17" }),
|
|
55
|
+
/* @__PURE__ */ jsx("line", { x1: "17", x2: "22", y1: "17", y2: "17" }),
|
|
56
|
+
/* @__PURE__ */ jsx("line", { x1: "17", x2: "22", y1: "7", y2: "7" })
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
export { FilmIcon, ImageIcon, PlayIcon, UploadCloudIcon };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ImageUploadItem } from '../ImageUpload.types';
|
|
3
|
+
export interface ImageUploadModalProps {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
activeIndex: number | null;
|
|
6
|
+
items: ImageUploadItem[];
|
|
7
|
+
shouldAnimate?: boolean;
|
|
8
|
+
onClose: () => void;
|
|
9
|
+
onNavigate: (newIndex: number) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare const ImageUploadModal: React.FC<ImageUploadModalProps>;
|
|
12
|
+
//# sourceMappingURL=ImageUploadModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageUploadModal.d.ts","sourceRoot":"","sources":["../../../../src/components/ImageUpload/subcomponents/ImageUploadModal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAyI5D,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { X, ChevronLeft, ChevronRight } from '@timmbr/icons';
|
|
6
|
+
import { AnimatePresence, motion, getTransition } from '@timmbr/motion';
|
|
7
|
+
import { isVideoMedia } from '../ImageUpload.helpers.js';
|
|
8
|
+
|
|
9
|
+
const ImageUploadModal = ({
|
|
10
|
+
isOpen,
|
|
11
|
+
activeIndex,
|
|
12
|
+
items,
|
|
13
|
+
shouldAnimate = true,
|
|
14
|
+
onClose,
|
|
15
|
+
onNavigate
|
|
16
|
+
}) => {
|
|
17
|
+
const [mounted, setMounted] = React.useState(false);
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
setMounted(true);
|
|
20
|
+
}, []);
|
|
21
|
+
const activeItem = activeIndex !== null && items[activeIndex] ? items[activeIndex] : null;
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
if (!isOpen || activeIndex === null) return;
|
|
24
|
+
const handleKeyDown = (e) => {
|
|
25
|
+
if (e.key === "Escape") {
|
|
26
|
+
onClose();
|
|
27
|
+
} else if (e.key === "ArrowLeft" && items.length > 1) {
|
|
28
|
+
onNavigate(activeIndex > 0 ? activeIndex - 1 : items.length - 1);
|
|
29
|
+
} else if (e.key === "ArrowRight" && items.length > 1) {
|
|
30
|
+
onNavigate(activeIndex < items.length - 1 ? activeIndex + 1 : 0);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
34
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
35
|
+
}, [activeIndex, isOpen, items.length, onClose, onNavigate]);
|
|
36
|
+
if (!mounted) return null;
|
|
37
|
+
return createPortal(
|
|
38
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && activeItem && activeIndex !== null && /* @__PURE__ */ jsx(
|
|
39
|
+
motion.div,
|
|
40
|
+
{
|
|
41
|
+
initial: shouldAnimate ? { opacity: 0 } : false,
|
|
42
|
+
animate: shouldAnimate ? { opacity: 1 } : void 0,
|
|
43
|
+
exit: shouldAnimate ? { opacity: 0 } : void 0,
|
|
44
|
+
transition: getTransition("fast"),
|
|
45
|
+
className: "fixed inset-0 z-[100] flex flex-col items-center justify-center p-4 sm:p-6 bg-black/60 backdrop-blur-xs",
|
|
46
|
+
onClick: onClose,
|
|
47
|
+
children: /* @__PURE__ */ jsxs(
|
|
48
|
+
motion.div,
|
|
49
|
+
{
|
|
50
|
+
initial: shouldAnimate ? { scale: 0.95, opacity: 0 } : false,
|
|
51
|
+
animate: shouldAnimate ? { scale: 1, opacity: 1 } : void 0,
|
|
52
|
+
exit: shouldAnimate ? { scale: 0.95, opacity: 0 } : void 0,
|
|
53
|
+
transition: getTransition("spring"),
|
|
54
|
+
className: "relative max-w-2xl max-h-[85vh] w-full bg-white dark:bg-grey-950 border border-grey-200 dark:border-grey-800 rounded-2xl overflow-hidden shadow-2xl flex flex-col",
|
|
55
|
+
onClick: (e) => e.stopPropagation(),
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-3 border-b border-grey-200 dark:border-grey-800 bg-grey-50/80 dark:bg-grey-900/80 backdrop-blur-xs select-none", children: [
|
|
58
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
59
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-foreground tracking-wide truncate max-w-xs sm:max-w-md", children: activeItem.name || `Media Item #${activeIndex + 1}` }),
|
|
60
|
+
activeIndex === 0 && /* @__PURE__ */ jsx("span", { className: "bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 border border-emerald-500/20 text-[10px] font-semibold px-2 py-0.5 rounded-full", children: "Cover" }),
|
|
61
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[11px] text-muted", children: [
|
|
62
|
+
"(",
|
|
63
|
+
activeIndex + 1,
|
|
64
|
+
" of ",
|
|
65
|
+
items.length,
|
|
66
|
+
")"
|
|
67
|
+
] })
|
|
68
|
+
] }),
|
|
69
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
|
|
70
|
+
"button",
|
|
71
|
+
{
|
|
72
|
+
type: "button",
|
|
73
|
+
onClick: onClose,
|
|
74
|
+
className: "size-7 rounded-full bg-grey-200/70 hover:bg-grey-300 dark:bg-grey-800 dark:hover:bg-grey-700 text-foreground flex items-center justify-center transition-colors cursor-pointer",
|
|
75
|
+
title: "Close preview (Esc)",
|
|
76
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
|
|
77
|
+
}
|
|
78
|
+
) })
|
|
79
|
+
] }),
|
|
80
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 flex items-center justify-center p-4 min-h-[260px] max-h-[70vh] bg-grey-100/50 dark:bg-black/50 overflow-hidden", children: [
|
|
81
|
+
isVideoMedia(activeItem) ? /* @__PURE__ */ jsx(
|
|
82
|
+
"video",
|
|
83
|
+
{
|
|
84
|
+
src: activeItem.url,
|
|
85
|
+
controls: true,
|
|
86
|
+
autoPlay: true,
|
|
87
|
+
playsInline: true,
|
|
88
|
+
className: "max-w-full max-h-[65vh] rounded-lg shadow-md"
|
|
89
|
+
}
|
|
90
|
+
) : /* @__PURE__ */ jsx(
|
|
91
|
+
"img",
|
|
92
|
+
{
|
|
93
|
+
src: activeItem.url,
|
|
94
|
+
alt: activeItem.name || "Preview full size",
|
|
95
|
+
className: "max-w-full max-h-[65vh] object-contain rounded-lg shadow-md select-none"
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
items.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
99
|
+
/* @__PURE__ */ jsx(
|
|
100
|
+
"button",
|
|
101
|
+
{
|
|
102
|
+
type: "button",
|
|
103
|
+
onClick: (e) => {
|
|
104
|
+
e.stopPropagation();
|
|
105
|
+
onNavigate(activeIndex > 0 ? activeIndex - 1 : items.length - 1);
|
|
106
|
+
},
|
|
107
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 size-9 rounded-full bg-white/90 hover:bg-white dark:bg-grey-800/90 dark:hover:bg-grey-800 border border-grey-200 dark:border-grey-700 text-foreground flex items-center justify-center transition-all backdrop-blur-xs cursor-pointer shadow-md",
|
|
108
|
+
title: "Previous (Left Arrow)",
|
|
109
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4" })
|
|
110
|
+
}
|
|
111
|
+
),
|
|
112
|
+
/* @__PURE__ */ jsx(
|
|
113
|
+
"button",
|
|
114
|
+
{
|
|
115
|
+
type: "button",
|
|
116
|
+
onClick: (e) => {
|
|
117
|
+
e.stopPropagation();
|
|
118
|
+
onNavigate(activeIndex < items.length - 1 ? activeIndex + 1 : 0);
|
|
119
|
+
},
|
|
120
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 size-9 rounded-full bg-white/90 hover:bg-white dark:bg-grey-800/90 dark:hover:bg-grey-800 border border-grey-200 dark:border-grey-700 text-foreground flex items-center justify-center transition-all backdrop-blur-xs cursor-pointer shadow-md",
|
|
121
|
+
title: "Next (Right Arrow)",
|
|
122
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" })
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
] })
|
|
126
|
+
] })
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
) }),
|
|
132
|
+
document.body
|
|
133
|
+
);
|
|
134
|
+
};
|
|
135
|
+
ImageUploadModal.displayName = "ImageUploadModal";
|
|
136
|
+
|
|
137
|
+
export { ImageUploadModal };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ImageUploadItem, ImageUploadAspectRatio } from '../ImageUpload.types';
|
|
3
|
+
export interface ImageUploadSinglePreviewProps {
|
|
4
|
+
item: ImageUploadItem;
|
|
5
|
+
aspectRatio: ImageUploadAspectRatio;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
isUploading?: boolean;
|
|
8
|
+
enablePreviewModal?: boolean;
|
|
9
|
+
onReplace: () => void;
|
|
10
|
+
onRemove: (e: React.MouseEvent) => void;
|
|
11
|
+
onPreview: (e: React.MouseEvent) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const ImageUploadSinglePreview: React.FC<ImageUploadSinglePreviewProps>;
|
|
14
|
+
//# sourceMappingURL=ImageUploadSinglePreview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageUploadSinglePreview.d.ts","sourceRoot":"","sources":["../../../../src/components/ImageUpload/subcomponents/ImageUploadSinglePreview.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACvB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,eAAe,CAAC;IACtB,WAAW,EAAE,sBAAsB,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxC,SAAS,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;CAC1C;AAED,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC,6BAA6B,CAqI5E,CAAC"}
|