@js-empire/emperor-ui 1.2.0 → 1.2.2
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/dist/emperor-ui.js +52 -48
- package/dist/emperor-ui.umd.cjs +8 -8
- package/dist/{features-animation-D_Ss-HYx.js → features-animation-uyo1KMg-.js} +1 -1
- package/dist/{index-C3mfrNCk.js → index-B3d8-vnJ.js} +4 -4
- package/dist/{index-SRvFgjzo.js → index-DOwkJus4.js} +3871 -3600
- package/dist/index-DrkA25TM.js +5 -0
- package/dist/index.d.ts +89 -7
- package/dist/src-UW24ZMRV-D6kiVea5.js +5 -0
- package/package.json +1 -1
- package/src/components/atoms/uploader/avatar-label.tsx +1 -1
- package/src/components/atoms/uploader/index.ts +1 -0
- package/src/components/atoms/uploader/stories/uploader.stories.tsx +52 -18
- package/src/components/atoms/uploader/upload-file-error-box.tsx +2 -2
- package/src/components/atoms/uploader/upload-file-label.tsx +7 -3
- package/src/components/atoms/uploader/uploader-title.tsx +21 -0
- package/src/components/atoms/uploader/uploader.tsx +3 -0
- package/src/components/organisms/footer/footer.tsx +1 -1
- package/src/components/organisms/listings/listings.tsx +12 -3
- package/src/components/organisms/listings/stories/listings.stories.tsx +30 -0
- package/src/components/organisms/listings/styles/classes.ts +11 -0
- package/src/components/organisms/listings/styles/index.ts +2 -0
- package/src/components/organisms/listings/styles/styles.ts +6 -0
- package/src/constants/defaults.ts +3 -26
- package/src/hooks/use-uploader.tsx +5 -4
- package/src/i18n/configs/i18n.ts +7 -0
- package/src/i18n/configs/index.ts +1 -0
- package/src/i18n/constants/index.ts +1 -0
- package/src/i18n/constants/locales.ts +4 -0
- package/src/i18n/index.ts +5 -0
- package/src/i18n/locales/ar.ts +15 -0
- package/src/i18n/locales/atoms/ar.ts +15 -0
- package/src/i18n/locales/atoms/en.ts +15 -0
- package/src/i18n/locales/atoms/index.ts +2 -0
- package/src/i18n/locales/common/ar.ts +1 -0
- package/src/i18n/locales/common/en.ts +1 -0
- package/src/i18n/locales/common/index.ts +2 -0
- package/src/i18n/locales/en.ts +15 -0
- package/src/i18n/locales/index.ts +4 -0
- package/src/i18n/locales/molecules/ar.ts +1 -0
- package/src/i18n/locales/molecules/en.ts +1 -0
- package/src/i18n/locales/molecules/index.ts +2 -0
- package/src/i18n/locales/organisms/ar.ts +1 -0
- package/src/i18n/locales/organisms/en.ts +1 -0
- package/src/i18n/locales/organisms/index.ts +2 -0
- package/src/i18n/locales/templates/ar.ts +1 -0
- package/src/i18n/locales/templates/en.ts +1 -0
- package/src/i18n/locales/templates/index.ts +2 -0
- package/src/i18n/locales/toasts/ar.ts +1 -0
- package/src/i18n/locales/toasts/en.ts +1 -0
- package/src/i18n/locales/toasts/index.ts +2 -0
- package/src/i18n/types/index.ts +2 -0
- package/src/i18n/types/locale.ts +5 -0
- package/src/i18n/types/toasts.ts +3 -0
- package/src/i18n/utils/get-locales.ts +4 -0
- package/src/i18n/utils/index.ts +2 -0
- package/src/i18n/utils/localize.ts +15 -0
- package/src/mocks/index.ts +1 -0
- package/src/mocks/listings.ts +200 -0
- package/src/providers/config-provider.tsx +18 -0
- package/src/types/components/atoms/uploader.ts +5 -5
- package/src/types/components/molecules/listings/listings.ts +5 -1
- package/src/types/context/config.ts +1 -32
- package/src/types/context/index.ts +2 -0
- package/src/types/context/localization.ts +23 -0
- package/src/types/context/theme.ts +17 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/locales.ts +54 -0
- package/src/utils/uploader.ts +6 -5
- package/dist/index-CZpTSGZs.js +0 -5
- package/dist/src-UW24ZMRV-Ducut0ty.js +0 -5
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ButtonProps as ButtonProps_2 } from '@heroui/button';
|
|
|
3
3
|
import { ClassAttributes } from 'react';
|
|
4
4
|
import { ClassProp } from 'class-variance-authority/types';
|
|
5
5
|
import { ClassValue } from 'clsx';
|
|
6
|
+
import { ComponentProps } from 'react';
|
|
6
7
|
import { Context } from 'react';
|
|
7
8
|
import { Dispatch } from 'react';
|
|
8
9
|
import { ElementType } from 'react';
|
|
@@ -34,6 +35,27 @@ export declare const ALLOWED_PDF_TYPES: string[];
|
|
|
34
35
|
|
|
35
36
|
export declare type AppDirection = "ltr" | "rtl";
|
|
36
37
|
|
|
38
|
+
declare const ar: {
|
|
39
|
+
common: {};
|
|
40
|
+
toasts: {};
|
|
41
|
+
atoms: {
|
|
42
|
+
uploader: {
|
|
43
|
+
dropHere: string;
|
|
44
|
+
selectFile: string;
|
|
45
|
+
selectionTypes: string;
|
|
46
|
+
selectBtn: string;
|
|
47
|
+
errorUploadingFile: string;
|
|
48
|
+
maxNumImages: string;
|
|
49
|
+
errorUploadedTypes: string;
|
|
50
|
+
maxSizeExceededError: string;
|
|
51
|
+
duplicatesDenied: string;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
molecules: {};
|
|
55
|
+
organisms: {};
|
|
56
|
+
templates: {};
|
|
57
|
+
};
|
|
58
|
+
|
|
37
59
|
export declare function AvatarLabel(): JSX.Element;
|
|
38
60
|
|
|
39
61
|
export declare const Brand: ForwardRefExoticComponent<Omit<ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
@@ -151,7 +173,11 @@ export declare type EmperorUILayout = {
|
|
|
151
173
|
withScaffold: boolean;
|
|
152
174
|
};
|
|
153
175
|
|
|
154
|
-
export declare type EmperorUILocales = Record<EmperorUILang,
|
|
176
|
+
export declare type EmperorUILocales = Record<EmperorUILang, Partial<{
|
|
177
|
+
atoms?: {
|
|
178
|
+
uploader?: Partial<Locale["atoms"]["uploader"]>;
|
|
179
|
+
};
|
|
180
|
+
}>>;
|
|
155
181
|
|
|
156
182
|
export declare function EmperorUIProvider({ children, ...props }: EmperorUIProviderProps): JSX.Element;
|
|
157
183
|
|
|
@@ -162,6 +188,27 @@ export declare type EmperorUITheme = {
|
|
|
162
188
|
colors: Partial<ColorsPalette>;
|
|
163
189
|
};
|
|
164
190
|
|
|
191
|
+
declare const en: {
|
|
192
|
+
common: {};
|
|
193
|
+
toasts: {};
|
|
194
|
+
atoms: {
|
|
195
|
+
uploader: {
|
|
196
|
+
dropHere: string;
|
|
197
|
+
selectFile: string;
|
|
198
|
+
selectionTypes: string;
|
|
199
|
+
selectBtn: string;
|
|
200
|
+
errorUploadingFile: string;
|
|
201
|
+
maxNumImages: string;
|
|
202
|
+
errorUploadedTypes: string;
|
|
203
|
+
maxSizeExceededError: string;
|
|
204
|
+
duplicatesDenied: string;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
molecules: {};
|
|
208
|
+
organisms: {};
|
|
209
|
+
templates: {};
|
|
210
|
+
};
|
|
211
|
+
|
|
165
212
|
export declare const FAKE_PARAGRAPH = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,";
|
|
166
213
|
|
|
167
214
|
export declare const FAKE_SENTENCE = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.";
|
|
@@ -229,6 +276,11 @@ export declare type FooterProps = SharedComponentProps & {
|
|
|
229
276
|
|
|
230
277
|
export declare const getAllowedTypes: (fileTypes: FileType[]) => string[];
|
|
231
278
|
|
|
279
|
+
export declare const getListings: ({ page, pageSize, }: {
|
|
280
|
+
page?: number;
|
|
281
|
+
pageSize?: number;
|
|
282
|
+
}) => MockItemType[];
|
|
283
|
+
|
|
232
284
|
export declare const getStorybookDecorators: ({ config, }: {
|
|
233
285
|
config?: EmperorUIConfig;
|
|
234
286
|
}) => ((Story: any) => JSX.Element)[];
|
|
@@ -330,18 +382,34 @@ export declare type LandingPageProps = SharedComponentProps & {
|
|
|
330
382
|
variant?: "default";
|
|
331
383
|
};
|
|
332
384
|
|
|
333
|
-
export declare function Listings({ className }: ListingsProps): JSX.Element;
|
|
385
|
+
export declare function Listings<ListingType>({ className, variant, }: ListingsProps<ListingType>): JSX.Element;
|
|
334
386
|
|
|
335
387
|
export declare type ListingsClassnames = {
|
|
336
388
|
base?: string;
|
|
337
389
|
};
|
|
338
390
|
|
|
339
|
-
export declare type ListingsProps = SharedComponentProps & {
|
|
391
|
+
export declare type ListingsProps<ListingType> = SharedComponentProps & {
|
|
340
392
|
classNames?: ListingsClassnames;
|
|
393
|
+
variant?: ListingsVariant;
|
|
394
|
+
items: ListingType[];
|
|
341
395
|
};
|
|
342
396
|
|
|
397
|
+
export declare type ListingsVariant = "default";
|
|
398
|
+
|
|
399
|
+
declare type Locale = typeof ar | typeof en;
|
|
400
|
+
|
|
343
401
|
export declare const mapFileType: (fileType: string) => FileType | null;
|
|
344
402
|
|
|
403
|
+
/**
|
|
404
|
+
* Deep-merges config locales into default locales. Default values are used as base,
|
|
405
|
+
* and config values override only the keys they provide. Nested objects are merged
|
|
406
|
+
* recursively so unrelated keys at any level remain unchanged.
|
|
407
|
+
*/
|
|
408
|
+
export declare const mergeLocales: ({ defaultLocales, configLocales, }: {
|
|
409
|
+
defaultLocales: Locale;
|
|
410
|
+
configLocales?: Partial<Locale>;
|
|
411
|
+
}) => Locale;
|
|
412
|
+
|
|
345
413
|
export declare const MOCK_HEADER_ACTIONS: SideBarAction[];
|
|
346
414
|
|
|
347
415
|
export declare const MOCK_HEADER_ITEMS: NavigationItem[];
|
|
@@ -350,6 +418,15 @@ export declare const MOCK_HEADER_ITEMS_WITH_SUB_ITEMS: NavigationItem[];
|
|
|
350
418
|
|
|
351
419
|
export declare const MOCK_HEADER_SUB_ITEMS: NavigationItem[];
|
|
352
420
|
|
|
421
|
+
export declare const MOCK_LISTINGS: MockItemType[];
|
|
422
|
+
|
|
423
|
+
export declare type MockItemType = {
|
|
424
|
+
id: number;
|
|
425
|
+
title: string;
|
|
426
|
+
description: string;
|
|
427
|
+
image: string;
|
|
428
|
+
};
|
|
429
|
+
|
|
353
430
|
export declare const NavBar: ForwardRefExoticComponent<Omit<ClassAttributes<HTMLElement> & HTMLAttributes<HTMLElement> & VariantProps<(props?: ({
|
|
354
431
|
hoverEffect?: "default" | "underline" | "solid" | "ghost" | "bordered" | "none" | null | undefined;
|
|
355
432
|
variant?: "default" | "solid" | "bordered" | null | undefined;
|
|
@@ -475,7 +552,7 @@ export declare function QuickLinksBox({ quickLinks, classNames }: FooterProps):
|
|
|
475
552
|
|
|
476
553
|
export declare function refineUploadedFiles({ uploadedFiles, locale, allowedTypes, isMulti, setFiles, }: {
|
|
477
554
|
uploadedFiles: (File | undefined)[];
|
|
478
|
-
locale?:
|
|
555
|
+
locale?: Locale;
|
|
479
556
|
allowedTypes: string[];
|
|
480
557
|
isMulti: boolean;
|
|
481
558
|
setFiles: Dispatch<SetStateAction<FileObject[]>>;
|
|
@@ -510,7 +587,7 @@ export declare type SharedFilesType = FileObject[];
|
|
|
510
587
|
|
|
511
588
|
export declare type SharedLabelIdType = string;
|
|
512
589
|
|
|
513
|
-
export declare type SharedOnInputChangeType = (event: React.ChangeEvent<HTMLInputElement> & React.DragEvent<HTMLLabelElement>) => Promise<void>;
|
|
590
|
+
export declare type SharedOnInputChangeType = (event: React.ChangeEvent<HTMLInputElement> & React.DragEvent<HTMLLabelElement>) => Promise<void | string | null>;
|
|
514
591
|
|
|
515
592
|
export declare const SideBar: ForwardRefExoticComponent<Omit<ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
516
593
|
variant?: "default" | "compact" | null | undefined;
|
|
@@ -608,6 +685,8 @@ export declare type UploaderContextState = {
|
|
|
608
685
|
labelId: SharedLabelIdType;
|
|
609
686
|
labelContent?: ReactNode;
|
|
610
687
|
avatarLabelContent?: ReactNode;
|
|
688
|
+
title?: ReactNode;
|
|
689
|
+
errorMessage?: ReactNode;
|
|
611
690
|
isFileViewable?: boolean;
|
|
612
691
|
isRequired?: boolean;
|
|
613
692
|
isDraggable?: boolean;
|
|
@@ -628,6 +707,7 @@ export declare type UploaderContextState = {
|
|
|
628
707
|
listing?: string;
|
|
629
708
|
error?: string;
|
|
630
709
|
input?: string;
|
|
710
|
+
title?: string;
|
|
631
711
|
};
|
|
632
712
|
};
|
|
633
713
|
|
|
@@ -643,6 +723,8 @@ export declare type UploaderProviderProps = UploaderContextState & {
|
|
|
643
723
|
children: ReactNode;
|
|
644
724
|
};
|
|
645
725
|
|
|
726
|
+
export declare function UploaderTitle({ ...props }: ComponentProps<"h3">): JSX.Element | null;
|
|
727
|
+
|
|
646
728
|
export declare function UploadFileErrorBox(): JSX.Element | null;
|
|
647
729
|
|
|
648
730
|
export declare function UploadFileInput(): JSX.Element;
|
|
@@ -686,14 +768,14 @@ export declare type UseUploadFileReturn = {
|
|
|
686
768
|
isLoading: boolean;
|
|
687
769
|
setFiles: Dispatch<SetStateAction<FileObject[]>>;
|
|
688
770
|
handleClearFile: (fileName?: string) => void;
|
|
689
|
-
onInputChange:
|
|
771
|
+
onInputChange: SharedOnInputChangeType;
|
|
690
772
|
};
|
|
691
773
|
|
|
692
774
|
export declare function validateUploadedFiles({ uploadedFiles, maxFileSize, compressFiles, locale, preventDuplicates, files, }: {
|
|
693
775
|
uploadedFiles: File[];
|
|
694
776
|
maxFileSize?: number;
|
|
695
777
|
compressFiles?: boolean;
|
|
696
|
-
locale?:
|
|
778
|
+
locale?: Locale;
|
|
697
779
|
preventDuplicates?: boolean;
|
|
698
780
|
files: FileObject[];
|
|
699
781
|
}): Promise<{
|
package/package.json
CHANGED
|
@@ -38,7 +38,7 @@ export function AvatarLabel() {
|
|
|
38
38
|
React.DragEvent<HTMLLabelElement>,
|
|
39
39
|
) => {
|
|
40
40
|
event.preventDefault();
|
|
41
|
-
setDraggableMessage(locale?.dropHere || "");
|
|
41
|
+
setDraggableMessage(locale?.atoms?.uploader?.dropHere || "");
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
const handleDragLeave = () => {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
2
|
import { Uploader } from "@/components";
|
|
3
3
|
import { getStorybookDecorators } from "@/utils";
|
|
4
|
-
import { UploaderProps } from "@/types";
|
|
5
4
|
import { useUploader } from "@/hooks";
|
|
6
5
|
import { useDisclosure } from "@heroui/react";
|
|
6
|
+
import { LangKey } from "@/i18n";
|
|
7
7
|
|
|
8
8
|
const meta: Meta<typeof Uploader> = {
|
|
9
9
|
title: "Atoms/Uploader",
|
|
@@ -17,6 +17,16 @@ const meta: Meta<typeof Uploader> = {
|
|
|
17
17
|
layout: {
|
|
18
18
|
withScaffold: false,
|
|
19
19
|
},
|
|
20
|
+
interLocalization: {
|
|
21
|
+
locales: {
|
|
22
|
+
[LangKey.ENGLISH]: {
|
|
23
|
+
atoms: {
|
|
24
|
+
uploader: {},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
[LangKey.ARABIC]: {},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
20
30
|
},
|
|
21
31
|
}),
|
|
22
32
|
};
|
|
@@ -27,32 +37,32 @@ type Story = StoryObj<typeof meta>;
|
|
|
27
37
|
|
|
28
38
|
export const Default: Story = {
|
|
29
39
|
args: {},
|
|
30
|
-
render: (
|
|
40
|
+
render: () => {
|
|
31
41
|
const uploadProps = useUploader({
|
|
32
42
|
fileTypes: ["image"],
|
|
33
43
|
labelId: "image",
|
|
34
44
|
});
|
|
35
45
|
|
|
36
|
-
return <Uploader {...uploadProps}
|
|
46
|
+
return <Uploader {...uploadProps} />;
|
|
37
47
|
},
|
|
38
48
|
};
|
|
39
49
|
|
|
40
50
|
export const MultiFiles: Story = {
|
|
41
51
|
args: {},
|
|
42
|
-
render: (
|
|
52
|
+
render: () => {
|
|
43
53
|
const uploadProps = useUploader({
|
|
44
54
|
fileTypes: ["image"],
|
|
45
55
|
labelId: "image",
|
|
46
56
|
isMulti: true,
|
|
47
57
|
});
|
|
48
58
|
|
|
49
|
-
return <Uploader {...uploadProps}
|
|
59
|
+
return <Uploader {...uploadProps} />;
|
|
50
60
|
},
|
|
51
61
|
};
|
|
52
62
|
|
|
53
63
|
export const WithMaxCount: Story = {
|
|
54
64
|
args: {},
|
|
55
|
-
render: (
|
|
65
|
+
render: () => {
|
|
56
66
|
const uploadProps = useUploader({
|
|
57
67
|
fileTypes: ["image"],
|
|
58
68
|
labelId: "image",
|
|
@@ -60,38 +70,51 @@ export const WithMaxCount: Story = {
|
|
|
60
70
|
maxCount: 2,
|
|
61
71
|
});
|
|
62
72
|
|
|
63
|
-
return <Uploader {...uploadProps}
|
|
73
|
+
return <Uploader {...uploadProps} />;
|
|
64
74
|
},
|
|
65
75
|
};
|
|
66
76
|
|
|
67
77
|
export const Required: Story = {
|
|
68
78
|
args: {},
|
|
69
|
-
render: (
|
|
79
|
+
render: () => {
|
|
80
|
+
const uploadProps = useUploader({
|
|
81
|
+
fileTypes: ["image"],
|
|
82
|
+
labelId: "image",
|
|
83
|
+
isRequired: true,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return <Uploader {...uploadProps} />;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const CustomErrorMessage: Story = {
|
|
91
|
+
args: {},
|
|
92
|
+
render: () => {
|
|
70
93
|
const uploadProps = useUploader({
|
|
71
94
|
fileTypes: ["image"],
|
|
72
95
|
labelId: "image",
|
|
73
96
|
isRequired: true,
|
|
74
97
|
});
|
|
75
98
|
|
|
76
|
-
return <Uploader {...uploadProps}
|
|
99
|
+
return <Uploader errorMessage="Please upload an image" {...uploadProps} />;
|
|
77
100
|
},
|
|
78
101
|
};
|
|
79
102
|
|
|
80
103
|
export const HideListings: Story = {
|
|
81
104
|
args: {},
|
|
82
|
-
render: (
|
|
105
|
+
render: () => {
|
|
83
106
|
const uploadProps = useUploader({
|
|
84
107
|
fileTypes: ["image"],
|
|
85
108
|
labelId: "image",
|
|
86
109
|
});
|
|
87
110
|
|
|
88
|
-
return <Uploader hideListing {...uploadProps}
|
|
111
|
+
return <Uploader hideListing {...uploadProps} />;
|
|
89
112
|
},
|
|
90
113
|
};
|
|
91
114
|
|
|
92
115
|
export const ViewableImages: Story = {
|
|
93
116
|
args: {},
|
|
94
|
-
render: (
|
|
117
|
+
render: () => {
|
|
95
118
|
const uploadProps = useUploader({
|
|
96
119
|
fileTypes: ["image"],
|
|
97
120
|
labelId: "image",
|
|
@@ -106,7 +129,6 @@ export const ViewableImages: Story = {
|
|
|
106
129
|
...modalProps,
|
|
107
130
|
}}
|
|
108
131
|
{...uploadProps}
|
|
109
|
-
{...args}
|
|
110
132
|
/>
|
|
111
133
|
);
|
|
112
134
|
},
|
|
@@ -114,20 +136,20 @@ export const ViewableImages: Story = {
|
|
|
114
136
|
|
|
115
137
|
export const AllowDuplicates: Story = {
|
|
116
138
|
args: {},
|
|
117
|
-
render: (
|
|
139
|
+
render: () => {
|
|
118
140
|
const uploadProps = useUploader({
|
|
119
141
|
fileTypes: ["image"],
|
|
120
142
|
labelId: "image",
|
|
121
143
|
preventDuplicates: false,
|
|
122
144
|
});
|
|
123
145
|
|
|
124
|
-
return <Uploader {...uploadProps}
|
|
146
|
+
return <Uploader {...uploadProps} />;
|
|
125
147
|
},
|
|
126
148
|
};
|
|
127
149
|
|
|
128
150
|
export const CompressFiles: Story = {
|
|
129
151
|
args: {},
|
|
130
|
-
render: (
|
|
152
|
+
render: () => {
|
|
131
153
|
const uploadProps = useUploader({
|
|
132
154
|
fileTypes: ["image"],
|
|
133
155
|
labelId: "uncompressed-image",
|
|
@@ -145,8 +167,8 @@ export const CompressFiles: Story = {
|
|
|
145
167
|
<h3 className="text-lg font-bold">Uncompressed</h3>
|
|
146
168
|
<h3 className="text-lg font-bold">Compressed</h3>
|
|
147
169
|
|
|
148
|
-
<Uploader {...uploadProps}
|
|
149
|
-
<Uploader {...compressedUploadProps}
|
|
170
|
+
<Uploader {...uploadProps} />
|
|
171
|
+
<Uploader {...compressedUploadProps} />
|
|
150
172
|
|
|
151
173
|
<p className="text-sm text-gray-500">
|
|
152
174
|
File size: {uploadProps.files[0]?.file?.size || "---"}
|
|
@@ -158,3 +180,15 @@ export const CompressFiles: Story = {
|
|
|
158
180
|
);
|
|
159
181
|
},
|
|
160
182
|
};
|
|
183
|
+
|
|
184
|
+
export const WithTitle: Story = {
|
|
185
|
+
args: {},
|
|
186
|
+
render: () => {
|
|
187
|
+
const uploadProps = useUploader({
|
|
188
|
+
fileTypes: ["image"],
|
|
189
|
+
labelId: "image",
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return <Uploader {...uploadProps} title="Upload your image" />;
|
|
193
|
+
},
|
|
194
|
+
};
|
|
@@ -6,7 +6,7 @@ import { useMemo } from "react";
|
|
|
6
6
|
|
|
7
7
|
export function UploadFileErrorBox() {
|
|
8
8
|
const { config } = useEmperorUI();
|
|
9
|
-
const { files, isRequired, classNames } = useUploaderContext();
|
|
9
|
+
const { files, isRequired, classNames, errorMessage } = useUploaderContext();
|
|
10
10
|
|
|
11
11
|
const locales = config?.interLocalization?.locales;
|
|
12
12
|
const lang = config?.interLocalization?.lang;
|
|
@@ -21,7 +21,7 @@ export function UploadFileErrorBox() {
|
|
|
21
21
|
if (isError)
|
|
22
22
|
return (
|
|
23
23
|
<p className={cn("text-[14px] text-danger", classNames?.error)}>
|
|
24
|
-
{locale?.errorUploadingFile}
|
|
24
|
+
{errorMessage || locale?.atoms?.uploader?.errorUploadingFile}
|
|
25
25
|
</p>
|
|
26
26
|
);
|
|
27
27
|
|
|
@@ -35,7 +35,7 @@ export function UploadFileLabel() {
|
|
|
35
35
|
React.DragEvent<HTMLLabelElement>,
|
|
36
36
|
) => {
|
|
37
37
|
event.preventDefault();
|
|
38
|
-
setDraggableMessage(locale?.dropHere || "");
|
|
38
|
+
setDraggableMessage(locale?.atoms?.uploader?.dropHere || "");
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
const handleDragLeave = () => {
|
|
@@ -61,8 +61,12 @@ export function UploadFileLabel() {
|
|
|
61
61
|
<div className="pointer-events-none flex size-full flex-col items-center justify-center gap-2 rounded-md border border-dashed bg-primary/10 px-2 py-8 text-xs">
|
|
62
62
|
<UploadCloud className="size-10 text-primary" />
|
|
63
63
|
|
|
64
|
-
<p className="font-bold">
|
|
65
|
-
|
|
64
|
+
<p className="font-bold">
|
|
65
|
+
{locale?.atoms?.uploader?.selectFile || ""}
|
|
66
|
+
</p>
|
|
67
|
+
<p className="opacity-70">
|
|
68
|
+
{locale?.atoms?.uploader?.selectionTypes || ""}
|
|
69
|
+
</p>
|
|
66
70
|
|
|
67
71
|
{draggableMessage && (
|
|
68
72
|
<p className="text-sm font-bold">{draggableMessage}</p>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useUploaderContext } from "@/hooks";
|
|
4
|
+
import { ComponentProps } from "react";
|
|
5
|
+
import { cn } from "@/utils";
|
|
6
|
+
|
|
7
|
+
export function UploaderTitle({ ...props }: ComponentProps<"h3">) {
|
|
8
|
+
const { title, classNames } = useUploaderContext();
|
|
9
|
+
|
|
10
|
+
if (!title) return null;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<h3
|
|
14
|
+
className={cn("text-lg font-bold", classNames?.title)}
|
|
15
|
+
data-slot="emperor-uploader-title"
|
|
16
|
+
{...props}
|
|
17
|
+
>
|
|
18
|
+
{title}
|
|
19
|
+
</h3>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
UploadFileListing,
|
|
11
11
|
UploadFileErrorBox,
|
|
12
12
|
UploadFileInput,
|
|
13
|
+
UploaderTitle,
|
|
13
14
|
} from "@/components";
|
|
14
15
|
|
|
15
16
|
const uploaderStyles = cva(["w-full flex flex-col gap-2"], {
|
|
@@ -40,6 +41,8 @@ export const Uploader = forwardRef<
|
|
|
40
41
|
return (
|
|
41
42
|
<UploaderProvider {...props}>
|
|
42
43
|
<div ref={ref} className={cn(uploaderStyles({ className }))} {...props}>
|
|
44
|
+
<UploaderTitle />
|
|
45
|
+
|
|
43
46
|
{isAvatar ? <AvatarLabel /> : <UploadFileLabel />}
|
|
44
47
|
|
|
45
48
|
{!hideListing && <UploadFileListing />}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { ListingsProps } from "@/types";
|
|
2
|
-
import {
|
|
2
|
+
import { listingsClasses, listingsStyles } from "./styles";
|
|
3
3
|
|
|
4
|
-
export function Listings({
|
|
5
|
-
|
|
4
|
+
export function Listings<ListingType>({
|
|
5
|
+
className,
|
|
6
|
+
variant = "default",
|
|
7
|
+
}: ListingsProps<ListingType>) {
|
|
8
|
+
return (
|
|
9
|
+
<section
|
|
10
|
+
data-slot="emperor-ui-listings"
|
|
11
|
+
className={listingsClasses({ className, variant })}
|
|
12
|
+
style={listingsStyles({ variant })}
|
|
13
|
+
></section>
|
|
14
|
+
);
|
|
6
15
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { Listings } from "@/components";
|
|
3
|
+
import { getStorybookDecorators } from "@/utils";
|
|
4
|
+
import { getListings, MockItemType } from "@/mocks";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Listings> = {
|
|
7
|
+
title: "Organisms/Listings",
|
|
8
|
+
component: Listings,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "fullscreen",
|
|
11
|
+
},
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
decorators: getStorybookDecorators({}),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default meta;
|
|
17
|
+
|
|
18
|
+
type Story = StoryObj<typeof meta>;
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
args: {},
|
|
22
|
+
render: (args) => {
|
|
23
|
+
const items = getListings({
|
|
24
|
+
page: 1,
|
|
25
|
+
pageSize: 10,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return <Listings<MockItemType> {...args} items={items} />;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { en, ar } from "@/i18n";
|
|
1
2
|
import type { ColorsPalette, EmperorUIConfig } from "@/types";
|
|
2
3
|
|
|
3
4
|
export const defaultColorsPalette: ColorsPalette = {
|
|
@@ -26,32 +27,8 @@ export const defaultEmperorUIConfig: EmperorUIConfig = {
|
|
|
26
27
|
dir: "ltr",
|
|
27
28
|
isMultiLingual: false,
|
|
28
29
|
locales: {
|
|
29
|
-
en
|
|
30
|
-
|
|
31
|
-
selectFile: "Select a file or drag and drop here",
|
|
32
|
-
selectionTypes: "JPG, PNG or PDF, file size no more than 10MB",
|
|
33
|
-
selectBtn: "Select file",
|
|
34
|
-
errorUploadingFile: "No file was uploaded",
|
|
35
|
-
maxNumImages: "Maximum number of uploaded images exceeded: ",
|
|
36
|
-
errorUploadedTypes: "You can only upload files within these types: ",
|
|
37
|
-
maxSizeExceededError:
|
|
38
|
-
"You can only upload files/images with less than MAX_FILE_SIZE Mega Bytes, you're file's size is UPLOADED_FILE_SIZE Mega Bytes",
|
|
39
|
-
duplicatesDenied:
|
|
40
|
-
"You can't upload images with duplicate names, you may rename them before the upload process",
|
|
41
|
-
},
|
|
42
|
-
ar: {
|
|
43
|
-
dropHere: "أسقط الملف هنا",
|
|
44
|
-
selectFile: "حدد ملفًا أو اسحبه وأفلته هنا",
|
|
45
|
-
selectionTypes: "JPG, PNG أو PDF، حجم الملف لا يزيد عن 10MB",
|
|
46
|
-
selectBtn: "حدد ملف",
|
|
47
|
-
errorUploadingFile: "لم يتم تحميل أي ملف",
|
|
48
|
-
maxNumImages: "تم تجاوز الحد الأقصى للصور المرفوعة: ",
|
|
49
|
-
errorUploadedTypes: "يمكنك فقط تحميل الملفات من الأنواع التالية: ",
|
|
50
|
-
maxSizeExceededError:
|
|
51
|
-
"يمكنك فقط رفع ملفات/صور بحجم أقل من MAX_FILE_SIZE ميغابايت، بينما حجم الملف الذي رفعته هو UPLOADED_FILE_SIZE ميغابايت",
|
|
52
|
-
duplicatesDenied:
|
|
53
|
-
"لا يمكنك رفع صور تحمل نفس الاسم، يمكنك إعادة تسميتها قبل عملية الرفع",
|
|
54
|
-
},
|
|
30
|
+
en,
|
|
31
|
+
ar,
|
|
55
32
|
},
|
|
56
33
|
},
|
|
57
34
|
};
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
refineUploadedFiles,
|
|
11
11
|
} from "@/utils";
|
|
12
12
|
import { ONE_MEGABYTE } from "@/constants";
|
|
13
|
+
import { Locale } from "@/i18n";
|
|
13
14
|
|
|
14
15
|
export const useUploader = ({
|
|
15
16
|
labelContent,
|
|
@@ -31,7 +32,7 @@ export const useUploader = ({
|
|
|
31
32
|
const locales = config?.interLocalization?.locales;
|
|
32
33
|
const lang = config?.interLocalization?.lang;
|
|
33
34
|
|
|
34
|
-
const locale = locales?.[lang || "en"];
|
|
35
|
+
const locale = locales?.[lang || "en"] as Locale;
|
|
35
36
|
|
|
36
37
|
// remove a specific uploaded file
|
|
37
38
|
const handleClearFile = (fileName?: string) => {
|
|
@@ -58,7 +59,7 @@ export const useUploader = ({
|
|
|
58
59
|
(!event?.dataTransfer?.files || !event?.dataTransfer?.files[0])
|
|
59
60
|
) {
|
|
60
61
|
return addToast({
|
|
61
|
-
title: locale?.errorUploadingFile,
|
|
62
|
+
title: locale?.atoms?.uploader?.errorUploadingFile,
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
65
|
|
|
@@ -80,7 +81,7 @@ export const useUploader = ({
|
|
|
80
81
|
files?.length + uploadedFiles?.length > maxCount)
|
|
81
82
|
) {
|
|
82
83
|
addToast({
|
|
83
|
-
title: `${locale?.maxNumImages} ${maxCount}`,
|
|
84
|
+
title: `${locale?.atoms?.uploader?.maxNumImages} ${maxCount}`,
|
|
84
85
|
});
|
|
85
86
|
return;
|
|
86
87
|
}
|
|
@@ -92,7 +93,7 @@ export const useUploader = ({
|
|
|
92
93
|
?.every((type) => allowedTypes.includes(type))
|
|
93
94
|
) {
|
|
94
95
|
addToast({
|
|
95
|
-
title: `${locale?.errorUploadedTypes} ${allowedTypes.join(", ")}`,
|
|
96
|
+
title: `${locale?.atoms?.uploader?.errorUploadedTypes} ${allowedTypes.join(", ")}`,
|
|
96
97
|
});
|
|
97
98
|
return;
|
|
98
99
|
}
|