@js-empire/emperor-ui 1.0.1 → 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/.husky/pre-commit +4 -0
- package/.storybook/main.ts +2 -11
- package/.storybook/preview.ts +1 -1
- package/.storybook/vitest.setup.ts +3 -3
- package/.vscode/extensions.json +1 -0
- package/README.md +47 -1
- package/dist/emperor-ui.js +69 -3169
- package/dist/emperor-ui.umd.cjs +45 -2
- package/dist/features-animation-D_Ss-HYx.js +1938 -0
- package/dist/globals.css +1 -0
- package/dist/icons/emperor-ui-logo.ico +0 -0
- package/dist/images/avatar-female.jpg +0 -0
- package/dist/images/avatar-male.jpg +0 -0
- package/dist/images/emperor-ui-logo.png +0 -0
- package/dist/index-C3mfrNCk.js +1630 -0
- package/dist/index-CZpTSGZs.js +5 -0
- package/dist/index-SRvFgjzo.js +26257 -0
- package/dist/index.d.ts +552 -46
- package/dist/src-UW24ZMRV-Ducut0ty.js +5 -0
- package/eslint.config.js +5 -14
- package/package.json +19 -7
- package/public/icons/emperor-ui-logo.ico +0 -0
- package/public/images/avatar-female.jpg +0 -0
- package/public/images/avatar-male.jpg +0 -0
- package/public/images/emperor-ui-logo.png +0 -0
- package/src/components/atoms/brand/brand.stories.tsx +27 -0
- package/src/components/atoms/brand/brand.tsx +56 -0
- package/src/components/atoms/brand/index.ts +1 -0
- package/src/components/atoms/brand/styles/classes.ts +9 -0
- package/src/components/atoms/brand/styles/index.ts +2 -0
- package/src/components/atoms/brand/styles/styles.ts +0 -0
- package/src/components/atoms/column/column.stories.tsx +37 -0
- package/src/components/atoms/column/column.tsx +21 -0
- package/src/components/atoms/column/index.ts +1 -0
- package/src/components/atoms/container/column.stories.tsx +37 -0
- package/src/components/atoms/container/container.tsx +28 -0
- package/src/components/atoms/container/index.ts +1 -0
- package/src/components/atoms/index.ts +6 -0
- package/src/components/atoms/portal/index.ts +1 -0
- package/src/components/atoms/portal/portal.stories.tsx +43 -0
- package/src/components/atoms/portal/portal.tsx +25 -0
- package/src/components/atoms/row/index.ts +1 -0
- package/src/components/atoms/row/row.stories.tsx +37 -0
- package/src/components/atoms/row/row.tsx +26 -0
- package/src/components/atoms/uploader/avatar-label.tsx +83 -0
- package/src/components/atoms/uploader/index.ts +7 -0
- package/src/components/atoms/uploader/stories/uploader.stories.tsx +160 -0
- package/src/components/atoms/uploader/upload-file-error-box.tsx +29 -0
- package/src/components/atoms/uploader/upload-file-input.tsx +36 -0
- package/src/components/atoms/uploader/upload-file-label.tsx +74 -0
- package/src/components/atoms/uploader/upload-file-listing.tsx +55 -0
- package/src/components/atoms/uploader/uploader.tsx +55 -0
- package/src/components/atoms/uploader/view-image-modal.tsx +40 -0
- package/src/components/index.ts +4 -8
- package/src/components/{filter → molecules/filter}/filter.tsx +2 -2
- package/src/components/molecules/index.ts +5 -0
- package/src/components/molecules/item-card/item-card.tsx +6 -0
- package/src/components/molecules/nav-bar/index.ts +3 -0
- package/src/components/molecules/nav-bar/nav-bar-item.tsx +70 -0
- package/src/components/molecules/nav-bar/nav-bar.tsx +65 -0
- package/src/components/molecules/nav-bar/stories/hover-effect/nav-bar-hover-effect.stories.tsx +52 -0
- package/src/components/molecules/nav-bar/stories/nav-bar.stories.tsx +50 -0
- package/src/components/molecules/nav-bar/styles/classes.ts +68 -0
- package/src/components/molecules/nav-bar/styles/index.ts +2 -0
- package/src/components/molecules/nav-bar/styles/styles.ts +85 -0
- package/src/components/molecules/nav-bar/sub-items-box.tsx +57 -0
- package/src/components/molecules/scaffold/scaffold.stories.tsx +21 -0
- package/src/components/molecules/scaffold/scaffold.tsx +36 -0
- package/src/components/molecules/side-bar/compact-side-bar.tsx +75 -0
- package/src/components/molecules/side-bar/index.ts +1 -0
- package/src/components/molecules/side-bar/side-bar-drawer.tsx +124 -0
- package/src/components/molecules/side-bar/side-bar.stories.tsx +111 -0
- package/src/components/molecules/side-bar/side-bar.tsx +31 -0
- package/src/components/molecules/side-bar/styles/classes.ts +28 -0
- package/src/components/molecules/side-bar/styles/index.ts +2 -0
- package/src/components/molecules/side-bar/styles/styles.ts +13 -0
- package/src/components/organisms/footer/copy-rights-box.tsx +27 -0
- package/src/components/organisms/footer/footer.tsx +75 -0
- package/src/components/organisms/footer/index.ts +5 -0
- package/src/components/organisms/footer/policies-box.tsx +26 -0
- package/src/components/organisms/footer/quick-links-box.tsx +45 -0
- package/src/components/organisms/footer/social-links-box.tsx +32 -0
- package/src/components/organisms/footer/stories/footer.stories.tsx +61 -0
- package/src/components/organisms/footer/styles/classes.ts +71 -0
- package/src/components/organisms/footer/styles/index.ts +2 -0
- package/src/components/organisms/footer/styles/styles.ts +6 -0
- package/src/components/organisms/header/header.tsx +94 -0
- package/src/components/organisms/header/segmented-header-content.tsx +37 -0
- package/src/components/organisms/header/stories/header.stories.tsx +144 -0
- package/src/components/organisms/header/styles/classes.ts +22 -0
- package/src/components/organisms/header/styles/index.ts +2 -0
- package/src/components/organisms/header/styles/styles.ts +39 -0
- package/src/components/organisms/index.ts +4 -0
- package/src/components/{item-details → organisms/item-details}/item-details.tsx +2 -2
- package/src/components/{listings → organisms/listings}/listings.tsx +2 -2
- package/src/components/templates/index.ts +1 -0
- package/src/components/templates/landing-page/index.ts +1 -0
- package/src/components/templates/landing-page/landing-page.stories.tsx +21 -0
- package/src/components/templates/landing-page/landing-page.tsx +57 -0
- package/src/components/templates/landing-page/styles/classes.ts +11 -0
- package/src/components/templates/landing-page/styles/index.ts +1 -0
- package/src/constants/defaults.ts +43 -8
- package/src/constants/fake.ts +5 -0
- package/src/constants/footer.tsx +157 -0
- package/src/constants/index.ts +3 -0
- package/src/constants/uploader.ts +27 -0
- package/src/context/emperor-ui-context.ts +4 -4
- package/src/context/index.ts +2 -0
- package/src/context/navigation-context.ts +6 -0
- package/src/context/uploader-context.ts +6 -0
- package/src/enums/index.ts +2 -0
- package/src/enums/placeholders.ts +4 -0
- package/src/enums/preserved-keys.ts +3 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/use-emperor-ui.ts +1 -1
- package/src/hooks/use-navigation.ts +12 -0
- package/src/hooks/use-uploader-context.ts +14 -0
- package/src/hooks/use-uploader.tsx +151 -0
- package/src/index.ts +9 -5
- package/src/main.tsx +3 -0
- package/src/mocks/header.tsx +118 -0
- package/src/mocks/index.ts +1 -0
- package/src/providers/config-provider.tsx +54 -0
- package/src/providers/emperor-ui-provider.tsx +17 -24
- package/src/providers/index.ts +3 -0
- package/src/providers/navigation-provider.tsx +42 -0
- package/src/providers/uploader-provider.tsx +53 -0
- package/src/styles/globals.css +13 -0
- package/src/styles/hero.ts +2 -0
- package/src/types/components/atoms/brand.ts +13 -0
- package/src/types/components/atoms/column.ts +3 -0
- package/src/types/components/atoms/container.ts +3 -0
- package/src/types/components/atoms/index.ts +6 -0
- package/src/types/components/atoms/portal.ts +6 -0
- package/src/types/components/atoms/row.ts +3 -0
- package/src/types/components/atoms/uploader.ts +97 -0
- package/src/types/components/index.ts +3 -8
- package/src/types/components/{filter → molecules/filter}/filter.ts +1 -1
- package/src/types/components/molecules/footer/footer.ts +68 -0
- package/src/types/components/molecules/header/header.ts +51 -0
- package/src/types/components/molecules/index.ts +9 -0
- package/src/types/components/{item-card → molecules/item-card}/item-card.ts +1 -1
- package/src/types/components/{item-details → molecules/item-details}/item-details.ts +1 -1
- package/src/types/components/{listings → molecules/listings}/listings.ts +1 -1
- package/src/types/components/molecules/nav-bar/nav-bar.ts +66 -0
- package/src/types/components/{scaffold → molecules/scaffold}/scaffold.ts +1 -1
- package/src/types/components/molecules/side-bar/index.ts +1 -0
- package/src/types/components/molecules/side-bar/side-bar.ts +40 -0
- package/src/types/components/templates/index.ts +1 -0
- package/src/types/components/templates/landing-page.ts +10 -0
- package/src/types/context/config.ts +54 -0
- package/src/types/context/index.ts +2 -1
- package/src/types/context/navigation.ts +17 -0
- package/src/types/shared/components.ts +4 -0
- package/src/utils/compress-images.ts +36 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/storybook.tsx +15 -0
- package/src/utils/uploader.ts +148 -0
- package/tsconfig.app.json +1 -9
- package/tsconfig.node.json +0 -1
- package/vite.config.ts +3 -8
- package/vitest.shims.d.ts +1 -1
- package/src/components/footer/footer.tsx +0 -6
- package/src/components/footer/index.ts +0 -1
- package/src/components/header/header.tsx +0 -49
- package/src/components/item-card/item-card.tsx +0 -6
- package/src/components/nav-bar/index.ts +0 -1
- package/src/components/nav-bar/nav-bar.tsx +0 -6
- package/src/components/scaffold/scaffold.tsx +0 -15
- package/src/index.css +0 -1
- package/src/types/components/footer/footer.ts +0 -9
- package/src/types/components/header/header.ts +0 -21
- package/src/types/components/nav-bar/nav-bar.ts +0 -9
- package/src/types/context/emperor-ui.ts +0 -37
- package/tailwind.config.js +0 -6
- /package/src/components/{filter → molecules/filter}/index.ts +0 -0
- /package/src/components/{item-card → molecules/item-card}/index.ts +0 -0
- /package/src/components/{scaffold → molecules/scaffold}/index.ts +0 -0
- /package/src/components/{header → organisms/header}/index.ts +0 -0
- /package/src/components/{item-details → organisms/item-details}/index.ts +0 -0
- /package/src/components/{listings → organisms/listings}/index.ts +0 -0
- /package/src/types/components/{filter → molecules/filter}/index.ts +0 -0
- /package/src/types/components/{footer → molecules/footer}/index.ts +0 -0
- /package/src/types/components/{header → molecules/header}/index.ts +0 -0
- /package/src/types/components/{item-card → molecules/item-card}/index.ts +0 -0
- /package/src/types/components/{item-details → molecules/item-details}/index.ts +0 -0
- /package/src/types/components/{listings → molecules/listings}/index.ts +0 -0
- /package/src/types/components/{nav-bar → molecules/nav-bar}/index.ts +0 -0
- /package/src/types/components/{scaffold → molecules/scaffold}/index.ts +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ComponentRadius,
|
|
3
|
+
ComponentSize,
|
|
4
|
+
SharedComponentProps,
|
|
5
|
+
} from "@/types";
|
|
6
|
+
import type { ElementType } from "react";
|
|
7
|
+
|
|
8
|
+
export type NavBarClassnames = {
|
|
9
|
+
base?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type NavigationItem = {
|
|
13
|
+
id: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
href?: string;
|
|
16
|
+
subItems?: NavigationItem[];
|
|
17
|
+
onClick?: () => void;
|
|
18
|
+
Icon?: ElementType;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type NavBarHoverEffect =
|
|
22
|
+
| "default"
|
|
23
|
+
| "underline"
|
|
24
|
+
| "solid"
|
|
25
|
+
| "ghost"
|
|
26
|
+
| "bordered"
|
|
27
|
+
| "none";
|
|
28
|
+
|
|
29
|
+
export type NavBarVariant = "default" | "solid" | "bordered";
|
|
30
|
+
|
|
31
|
+
export type NavBarStylesProps = {
|
|
32
|
+
primaryColor?: string;
|
|
33
|
+
foregroundColor?: string;
|
|
34
|
+
variant?: NavBarVariant;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
38
|
+
export type NavBarMenuStylesProps = {};
|
|
39
|
+
|
|
40
|
+
export type NavBarItemStylesProps = {
|
|
41
|
+
foregroundColor?: string;
|
|
42
|
+
primaryColor?: string;
|
|
43
|
+
hoverEffect: NavBarHoverEffect;
|
|
44
|
+
isHovered?: boolean;
|
|
45
|
+
variant?: NavBarVariant;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type NavBarProps = SharedComponentProps & {
|
|
49
|
+
items: NavigationItem[];
|
|
50
|
+
classNames?: NavBarClassnames;
|
|
51
|
+
hoverEffect?: NavBarHoverEffect;
|
|
52
|
+
radius?: ComponentRadius;
|
|
53
|
+
size?: ComponentSize;
|
|
54
|
+
variant?: NavBarVariant;
|
|
55
|
+
subItemsColumns?: number;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type NavBarItemProps = {
|
|
59
|
+
item: NavigationItem;
|
|
60
|
+
variant: NavBarVariant;
|
|
61
|
+
hoverEffect: NavBarHoverEffect;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export type SubItemsBoxProps = {
|
|
65
|
+
subItemsColumns?: number;
|
|
66
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type * from "./side-bar";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ButtonProps } from "@heroui/react";
|
|
2
|
+
import type { NavigationItem, SharedComponentProps } from "@/types";
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
export type SideBarVariant = "default" | "compact";
|
|
6
|
+
|
|
7
|
+
export type SideBarClassnames = {
|
|
8
|
+
base?: string;
|
|
9
|
+
trigger?: string;
|
|
10
|
+
title?: string;
|
|
11
|
+
menu?: string;
|
|
12
|
+
menuItem?: string;
|
|
13
|
+
actionsWrapper?: string;
|
|
14
|
+
actionItem?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type SideBarAction = ButtonProps & {
|
|
18
|
+
key: string;
|
|
19
|
+
label?: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type SideBarProps = SharedComponentProps & {
|
|
23
|
+
classNames?: SideBarClassnames;
|
|
24
|
+
variant?: SideBarVariant;
|
|
25
|
+
items: NavigationItem[];
|
|
26
|
+
actions?: SideBarAction[];
|
|
27
|
+
triggerProps?: Omit<ButtonProps, "content"> & { content?: ReactNode };
|
|
28
|
+
isOpen?: boolean;
|
|
29
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
30
|
+
header?: ReactNode;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type SideBarItemStylesProps = {
|
|
34
|
+
foregroundColor?: string;
|
|
35
|
+
primaryColor?: string;
|
|
36
|
+
isHovered?: boolean;
|
|
37
|
+
variant?: SideBarVariant;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type CompactSideBarProps = SideBarProps & {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type * from "./landing-page";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { HeroUIProviderProps } from "@heroui/react";
|
|
3
|
+
|
|
4
|
+
export type ConfigContextState = {
|
|
5
|
+
config: EmperorUIConfig;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type ConfigProviderProps = {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
config?: EmperorUIConfig;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type ColorMode = "light" | "dark";
|
|
14
|
+
export type AppDirection = "ltr" | "rtl";
|
|
15
|
+
|
|
16
|
+
export type ColorsPalette = {
|
|
17
|
+
primary: string;
|
|
18
|
+
secondary: string;
|
|
19
|
+
success: string;
|
|
20
|
+
danger: string;
|
|
21
|
+
warning: string;
|
|
22
|
+
info: string;
|
|
23
|
+
background: string;
|
|
24
|
+
foreground: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type EmperorUITheme = {
|
|
28
|
+
mode: ColorMode;
|
|
29
|
+
colors: Partial<ColorsPalette>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type EmperorUILayout = {
|
|
33
|
+
withScaffold: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type EmperorUILang = "en" | "ar";
|
|
37
|
+
|
|
38
|
+
export type EmperorUILocales = Record<EmperorUILang, Record<string, string>>;
|
|
39
|
+
|
|
40
|
+
export type EmperorUIInterLocalization = {
|
|
41
|
+
lang?: EmperorUILang;
|
|
42
|
+
languages?: EmperorUILang[];
|
|
43
|
+
defaultLanguage?: EmperorUILang;
|
|
44
|
+
isMultiLingual?: boolean;
|
|
45
|
+
dir?: AppDirection;
|
|
46
|
+
locales?: EmperorUILocales;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type EmperorUIConfig = {
|
|
50
|
+
theme?: Partial<EmperorUITheme>;
|
|
51
|
+
layout?: Partial<EmperorUILayout>;
|
|
52
|
+
interLocalization?: Partial<EmperorUIInterLocalization>;
|
|
53
|
+
toast?: HeroUIProviderProps;
|
|
54
|
+
};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export type * from "./
|
|
1
|
+
export type * from "./config";
|
|
2
|
+
export type * from "./navigation";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NavigationItem } from "@/types";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
export type NavigationContextState = {
|
|
5
|
+
hoveredItemId: string | null;
|
|
6
|
+
subItems: NavigationItem[];
|
|
7
|
+
isSubItemsBoxOpen: boolean;
|
|
8
|
+
subItemsBoxIsHovered: boolean;
|
|
9
|
+
setHoveredItemId: (id: string | null) => void;
|
|
10
|
+
setSubItems: (items: NavigationItem[]) => void;
|
|
11
|
+
setIsSubItemsBoxOpen: (isOpen: boolean) => void;
|
|
12
|
+
setSubItemsBoxIsHovered: (isHovered: boolean) => void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type NavigationProviderProps = {
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { FileObject } from "@/types";
|
|
4
|
+
/**
|
|
5
|
+
* Compress an image to reduce its size
|
|
6
|
+
*
|
|
7
|
+
* ! NOTE: This function should ONLY run on CLIENT side
|
|
8
|
+
*/
|
|
9
|
+
import imageCompression from "browser-image-compression";
|
|
10
|
+
|
|
11
|
+
export async function compressImage(
|
|
12
|
+
fileObject: FileObject,
|
|
13
|
+
maxSizeMB?: number,
|
|
14
|
+
): Promise<FileObject | null> {
|
|
15
|
+
try {
|
|
16
|
+
if (!fileObject?.file) return null;
|
|
17
|
+
|
|
18
|
+
const blob = await imageCompression(fileObject?.file, {
|
|
19
|
+
maxSizeMB: maxSizeMB || 2,
|
|
20
|
+
useWebWorker: true, // Optimize performance
|
|
21
|
+
initialQuality: 0.8, // Adjust the compression quality (0.1 to 1)
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const compressedFile = new File([blob], fileObject?.file?.name, {
|
|
25
|
+
type: blob.type,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
...fileObject,
|
|
30
|
+
file: compressedFile,
|
|
31
|
+
};
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error("Image compression failed:", error);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EmperorUIProvider } from "@/providers";
|
|
2
|
+
import { defaultEmperorUIConfig } from "@/constants";
|
|
3
|
+
import { EmperorUIConfig } from "@/types";
|
|
4
|
+
|
|
5
|
+
export const getStorybookDecorators = ({
|
|
6
|
+
config = defaultEmperorUIConfig,
|
|
7
|
+
}: {
|
|
8
|
+
config?: EmperorUIConfig;
|
|
9
|
+
}) => [
|
|
10
|
+
(Story: any) => (
|
|
11
|
+
<EmperorUIProvider config={config}>
|
|
12
|
+
<Story />
|
|
13
|
+
</EmperorUIProvider>
|
|
14
|
+
),
|
|
15
|
+
];
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ALLOWED_DOC_TYPES,
|
|
3
|
+
ALLOWED_IMAGES_TYPES,
|
|
4
|
+
ALLOWED_PDF_TYPES,
|
|
5
|
+
ONE_MEGABYTE,
|
|
6
|
+
} from "@/constants";
|
|
7
|
+
import { FileObject, FileType } from "@/types";
|
|
8
|
+
import { addToast } from "@heroui/react";
|
|
9
|
+
import { compressImage } from "@/utils";
|
|
10
|
+
import { Dispatch, SetStateAction } from "react";
|
|
11
|
+
|
|
12
|
+
// get the corresponding FileType giving the extension of the uploaded file
|
|
13
|
+
export const mapFileType = (fileType: string): FileType | null => {
|
|
14
|
+
if (ALLOWED_IMAGES_TYPES.includes(fileType)) return "image";
|
|
15
|
+
if (ALLOWED_PDF_TYPES.includes(fileType)) return "pdf";
|
|
16
|
+
if (ALLOWED_DOC_TYPES.includes(fileType)) return "doc";
|
|
17
|
+
|
|
18
|
+
return null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// get the allowed file types according to the specified types from the 'fileTypes' array
|
|
22
|
+
export const getAllowedTypes = (fileTypes: FileType[]): string[] => {
|
|
23
|
+
const allowedTypes: string[] = [];
|
|
24
|
+
|
|
25
|
+
fileTypes.forEach((fileType) => {
|
|
26
|
+
if (fileType === "image") allowedTypes.push(...ALLOWED_IMAGES_TYPES);
|
|
27
|
+
if (fileType === "doc") allowedTypes.push(...ALLOWED_DOC_TYPES);
|
|
28
|
+
if (fileType === "pdf") allowedTypes.push(...ALLOWED_PDF_TYPES);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return allowedTypes;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const isFileDuplicated = ({
|
|
35
|
+
files,
|
|
36
|
+
fileName,
|
|
37
|
+
}: {
|
|
38
|
+
files: FileObject[];
|
|
39
|
+
fileName: string;
|
|
40
|
+
}): boolean => files?.filter(({ file }) => file?.name === fileName)?.length > 0;
|
|
41
|
+
|
|
42
|
+
// check if the file size exceeds the maxFileSize
|
|
43
|
+
export const isMaxFileSizeExceeded = ({
|
|
44
|
+
fileSize,
|
|
45
|
+
maxFileSize,
|
|
46
|
+
}: {
|
|
47
|
+
fileSize: number;
|
|
48
|
+
maxFileSize: number;
|
|
49
|
+
}): boolean => fileSize > maxFileSize * 1024;
|
|
50
|
+
|
|
51
|
+
export async function validateUploadedFiles({
|
|
52
|
+
uploadedFiles,
|
|
53
|
+
maxFileSize = ONE_MEGABYTE * 10,
|
|
54
|
+
compressFiles,
|
|
55
|
+
locale,
|
|
56
|
+
preventDuplicates,
|
|
57
|
+
files,
|
|
58
|
+
}: {
|
|
59
|
+
uploadedFiles: File[];
|
|
60
|
+
maxFileSize?: number;
|
|
61
|
+
compressFiles?: boolean;
|
|
62
|
+
locale?: Record<string, string> | undefined;
|
|
63
|
+
preventDuplicates?: boolean;
|
|
64
|
+
files: FileObject[];
|
|
65
|
+
}) {
|
|
66
|
+
let isInValid = false;
|
|
67
|
+
|
|
68
|
+
const compressedFiles = await Promise.all(
|
|
69
|
+
uploadedFiles?.map(async (file) => {
|
|
70
|
+
if (isMaxFileSizeExceeded({ fileSize: file?.size, maxFileSize })) {
|
|
71
|
+
addToast({
|
|
72
|
+
title: locale?.maxSizeExceededError
|
|
73
|
+
.replace("MAX_FILE_SIZE", (maxFileSize / 1024 || 0)?.toString())
|
|
74
|
+
.replace(
|
|
75
|
+
"UPLOADED_FILE_SIZE",
|
|
76
|
+
(file?.size / 1024 / 1024 || 0)?.toFixed(1)?.toString(),
|
|
77
|
+
),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
if (compressFiles) {
|
|
81
|
+
return (await compressImage({ file }))?.file;
|
|
82
|
+
} else {
|
|
83
|
+
isInValid = true;
|
|
84
|
+
return file;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (
|
|
89
|
+
preventDuplicates &&
|
|
90
|
+
isFileDuplicated({ fileName: file?.name, files })
|
|
91
|
+
) {
|
|
92
|
+
addToast({
|
|
93
|
+
title: locale?.duplicatesDenied,
|
|
94
|
+
});
|
|
95
|
+
isInValid = true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return file;
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
compressedFiles,
|
|
104
|
+
isInValid,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function refineUploadedFiles({
|
|
109
|
+
uploadedFiles,
|
|
110
|
+
locale,
|
|
111
|
+
allowedTypes,
|
|
112
|
+
isMulti,
|
|
113
|
+
setFiles,
|
|
114
|
+
}: {
|
|
115
|
+
uploadedFiles: (File | undefined)[];
|
|
116
|
+
locale?: Record<string, string> | undefined;
|
|
117
|
+
allowedTypes: string[];
|
|
118
|
+
isMulti: boolean;
|
|
119
|
+
setFiles: Dispatch<SetStateAction<FileObject[]>>;
|
|
120
|
+
}) {
|
|
121
|
+
return uploadedFiles?.map((uploadedFile) => {
|
|
122
|
+
if (uploadedFile) {
|
|
123
|
+
// validate the file extension according to the allowed extensions
|
|
124
|
+
const fileType = mapFileType(uploadedFile?.type);
|
|
125
|
+
if (!fileType) {
|
|
126
|
+
addToast({
|
|
127
|
+
title: `${locale?.errorUploadedTypes} ${allowedTypes.join(", ")}`,
|
|
128
|
+
});
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// set the file to be utilized, and the image to be viewed
|
|
133
|
+
const reader = new FileReader();
|
|
134
|
+
reader.onload = () => {
|
|
135
|
+
setFiles((prevFiles) => [
|
|
136
|
+
...(isMulti ? prevFiles : []),
|
|
137
|
+
{
|
|
138
|
+
file: uploadedFile,
|
|
139
|
+
view: reader.result as string,
|
|
140
|
+
type: fileType,
|
|
141
|
+
url: URL.createObjectURL(uploadedFile),
|
|
142
|
+
},
|
|
143
|
+
]);
|
|
144
|
+
};
|
|
145
|
+
reader.readAsDataURL(uploadedFile);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
package/tsconfig.app.json
CHANGED
|
@@ -20,20 +20,12 @@
|
|
|
20
20
|
"strict": true,
|
|
21
21
|
"noUnusedLocals": true,
|
|
22
22
|
"noUnusedParameters": true,
|
|
23
|
-
"erasableSyntaxOnly": true,
|
|
24
23
|
"noFallthroughCasesInSwitch": true,
|
|
25
24
|
"noUncheckedSideEffectImports": true,
|
|
26
25
|
|
|
27
26
|
"baseUrl": ".",
|
|
28
27
|
"paths": {
|
|
29
|
-
"
|
|
30
|
-
"@components": ["./src/components"],
|
|
31
|
-
"@constants": ["./src/constants"],
|
|
32
|
-
"@hooks": ["./src/hooks"],
|
|
33
|
-
"@context": ["./src/context"],
|
|
34
|
-
"@examples": ["./src/examples"],
|
|
35
|
-
"@providers": ["./src/providers"],
|
|
36
|
-
"@types": ["./src/types"]
|
|
28
|
+
"@/*": ["./src/*"]
|
|
37
29
|
}
|
|
38
30
|
},
|
|
39
31
|
"include": [
|
package/tsconfig.node.json
CHANGED
package/vite.config.ts
CHANGED
|
@@ -20,14 +20,7 @@ export default defineConfig({
|
|
|
20
20
|
],
|
|
21
21
|
resolve: {
|
|
22
22
|
alias: {
|
|
23
|
-
"@
|
|
24
|
-
"@components": path.resolve(__dirname, "./src/components"),
|
|
25
|
-
"@types": path.resolve(__dirname, "./src/types"),
|
|
26
|
-
"@providers": path.resolve(__dirname, "./src/providers"),
|
|
27
|
-
"@constants": path.resolve(__dirname, "./src/constants"),
|
|
28
|
-
"@hooks": path.resolve(__dirname, "./src/hooks"),
|
|
29
|
-
"@context": path.resolve(__dirname, "./src/context"),
|
|
30
|
-
"@examples": path.resolve(__dirname, "./src/examples"),
|
|
23
|
+
"@": path.resolve(__dirname, "./src"),
|
|
31
24
|
},
|
|
32
25
|
},
|
|
33
26
|
build: {
|
|
@@ -36,6 +29,7 @@ export default defineConfig({
|
|
|
36
29
|
name: "EmperorUI",
|
|
37
30
|
fileName: "emperor-ui",
|
|
38
31
|
},
|
|
32
|
+
cssCodeSplit: false,
|
|
39
33
|
rollupOptions: {
|
|
40
34
|
external: ["react", "react-dom"],
|
|
41
35
|
output: {
|
|
@@ -43,6 +37,7 @@ export default defineConfig({
|
|
|
43
37
|
react: "React",
|
|
44
38
|
"react-dom": "ReactDOM",
|
|
45
39
|
},
|
|
40
|
+
assetFileNames: "globals.css",
|
|
46
41
|
},
|
|
47
42
|
},
|
|
48
43
|
},
|
package/vitest.shims.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
/// <reference types="@vitest/browser-playwright" />
|
|
1
|
+
/// <reference types="@vitest/browser-playwright" />
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./footer";
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { HeaderProps } from "@types";
|
|
2
|
-
import { cn } from "@utils";
|
|
3
|
-
import { cva, VariantProps } from "class-variance-authority";
|
|
4
|
-
import { ComponentProps, forwardRef } from "react";
|
|
5
|
-
|
|
6
|
-
const headerStyles = cva(["flex justify-center items-center min-h-16"], {
|
|
7
|
-
variants: {
|
|
8
|
-
variant: {
|
|
9
|
-
primary: "bg-blue-500 text-white",
|
|
10
|
-
secondary: "bg-gray-500 text-black",
|
|
11
|
-
},
|
|
12
|
-
padding: {
|
|
13
|
-
sm: "p-2",
|
|
14
|
-
md: "p-4",
|
|
15
|
-
lg: "p-6",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
defaultVariants: {
|
|
19
|
-
variant: "primary",
|
|
20
|
-
padding: "md",
|
|
21
|
-
},
|
|
22
|
-
compoundVariants: [
|
|
23
|
-
{
|
|
24
|
-
variant: "primary",
|
|
25
|
-
padding: "lg",
|
|
26
|
-
class: "shadow-lg",
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
variant: "secondary",
|
|
30
|
-
padding: "sm",
|
|
31
|
-
class: "border-2 border-black",
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
export const Header = forwardRef<
|
|
37
|
-
HTMLElement,
|
|
38
|
-
ComponentProps<"header"> & VariantProps<typeof headerStyles> & HeaderProps
|
|
39
|
-
>(({ className, variant, padding, ...props }, ref) => {
|
|
40
|
-
return (
|
|
41
|
-
<header
|
|
42
|
-
ref={ref}
|
|
43
|
-
className={cn(headerStyles({ variant, padding, className }))}
|
|
44
|
-
{...props}
|
|
45
|
-
>
|
|
46
|
-
this is a header
|
|
47
|
-
</header>
|
|
48
|
-
);
|
|
49
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./nav-bar";
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { useEmperorUI } from "@hooks";
|
|
2
|
-
import type { ScaffoldProps } from "@types";
|
|
3
|
-
import { cn } from "@utils";
|
|
4
|
-
|
|
5
|
-
export function Scaffold({ className, children }: ScaffoldProps) {
|
|
6
|
-
const { config } = useEmperorUI();
|
|
7
|
-
|
|
8
|
-
const backgroundColor = config?.theme?.colors?.background;
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
<div className={cn("flex flex-col", className)} style={{ backgroundColor }}>
|
|
12
|
-
{children}
|
|
13
|
-
</div>
|
|
14
|
-
);
|
|
15
|
-
}
|
package/src/index.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { SharedComponentProps } from "@types";
|
|
2
|
-
|
|
3
|
-
export type HeaderClassnames = {
|
|
4
|
-
base?: string;
|
|
5
|
-
logo?: string;
|
|
6
|
-
navbar?: string;
|
|
7
|
-
userDropdown?: string;
|
|
8
|
-
sideMenu?: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export type HeaderActivations = {
|
|
12
|
-
hideLog?: boolean;
|
|
13
|
-
hideNavbar?: boolean;
|
|
14
|
-
hideUserDropdown?: boolean;
|
|
15
|
-
hideSideMenu?: boolean;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type HeaderProps = SharedComponentProps & {
|
|
19
|
-
variant?: "default" | "compact";
|
|
20
|
-
classNames?: HeaderClassnames;
|
|
21
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { type ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
export type EmperorUIContextState = {
|
|
4
|
-
config: EmperorUIConfig;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export type EmperorUIProviderProps = {
|
|
8
|
-
children: ReactNode;
|
|
9
|
-
config: EmperorUIConfig;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export type ColorMode = "light" | "dark";
|
|
13
|
-
|
|
14
|
-
export type ColorsPalette = {
|
|
15
|
-
primary: string;
|
|
16
|
-
secondary: string;
|
|
17
|
-
success: string;
|
|
18
|
-
danger: string;
|
|
19
|
-
warning: string;
|
|
20
|
-
info: string;
|
|
21
|
-
background: string;
|
|
22
|
-
text: string;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type EmperorUITheme = {
|
|
26
|
-
mode: ColorMode;
|
|
27
|
-
colors: Partial<ColorsPalette>;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export type EmperorUILayout = {
|
|
31
|
-
withScaffold: boolean;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export type EmperorUIConfig = {
|
|
35
|
-
theme?: Partial<EmperorUITheme>;
|
|
36
|
-
layout?: Partial<EmperorUILayout>;
|
|
37
|
-
};
|