@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.
Files changed (189) hide show
  1. package/.husky/pre-commit +4 -0
  2. package/.storybook/main.ts +2 -11
  3. package/.storybook/preview.ts +1 -1
  4. package/.storybook/vitest.setup.ts +3 -3
  5. package/.vscode/extensions.json +1 -0
  6. package/README.md +47 -1
  7. package/dist/emperor-ui.js +69 -3169
  8. package/dist/emperor-ui.umd.cjs +45 -2
  9. package/dist/features-animation-D_Ss-HYx.js +1938 -0
  10. package/dist/globals.css +1 -0
  11. package/dist/icons/emperor-ui-logo.ico +0 -0
  12. package/dist/images/avatar-female.jpg +0 -0
  13. package/dist/images/avatar-male.jpg +0 -0
  14. package/dist/images/emperor-ui-logo.png +0 -0
  15. package/dist/index-C3mfrNCk.js +1630 -0
  16. package/dist/index-CZpTSGZs.js +5 -0
  17. package/dist/index-SRvFgjzo.js +26257 -0
  18. package/dist/index.d.ts +552 -46
  19. package/dist/src-UW24ZMRV-Ducut0ty.js +5 -0
  20. package/eslint.config.js +5 -14
  21. package/package.json +19 -7
  22. package/public/icons/emperor-ui-logo.ico +0 -0
  23. package/public/images/avatar-female.jpg +0 -0
  24. package/public/images/avatar-male.jpg +0 -0
  25. package/public/images/emperor-ui-logo.png +0 -0
  26. package/src/components/atoms/brand/brand.stories.tsx +27 -0
  27. package/src/components/atoms/brand/brand.tsx +56 -0
  28. package/src/components/atoms/brand/index.ts +1 -0
  29. package/src/components/atoms/brand/styles/classes.ts +9 -0
  30. package/src/components/atoms/brand/styles/index.ts +2 -0
  31. package/src/components/atoms/brand/styles/styles.ts +0 -0
  32. package/src/components/atoms/column/column.stories.tsx +37 -0
  33. package/src/components/atoms/column/column.tsx +21 -0
  34. package/src/components/atoms/column/index.ts +1 -0
  35. package/src/components/atoms/container/column.stories.tsx +37 -0
  36. package/src/components/atoms/container/container.tsx +28 -0
  37. package/src/components/atoms/container/index.ts +1 -0
  38. package/src/components/atoms/index.ts +6 -0
  39. package/src/components/atoms/portal/index.ts +1 -0
  40. package/src/components/atoms/portal/portal.stories.tsx +43 -0
  41. package/src/components/atoms/portal/portal.tsx +25 -0
  42. package/src/components/atoms/row/index.ts +1 -0
  43. package/src/components/atoms/row/row.stories.tsx +37 -0
  44. package/src/components/atoms/row/row.tsx +26 -0
  45. package/src/components/atoms/uploader/avatar-label.tsx +83 -0
  46. package/src/components/atoms/uploader/index.ts +7 -0
  47. package/src/components/atoms/uploader/stories/uploader.stories.tsx +160 -0
  48. package/src/components/atoms/uploader/upload-file-error-box.tsx +29 -0
  49. package/src/components/atoms/uploader/upload-file-input.tsx +36 -0
  50. package/src/components/atoms/uploader/upload-file-label.tsx +74 -0
  51. package/src/components/atoms/uploader/upload-file-listing.tsx +55 -0
  52. package/src/components/atoms/uploader/uploader.tsx +55 -0
  53. package/src/components/atoms/uploader/view-image-modal.tsx +40 -0
  54. package/src/components/index.ts +4 -8
  55. package/src/components/{filter → molecules/filter}/filter.tsx +2 -2
  56. package/src/components/molecules/index.ts +5 -0
  57. package/src/components/molecules/item-card/item-card.tsx +6 -0
  58. package/src/components/molecules/nav-bar/index.ts +3 -0
  59. package/src/components/molecules/nav-bar/nav-bar-item.tsx +70 -0
  60. package/src/components/molecules/nav-bar/nav-bar.tsx +65 -0
  61. package/src/components/molecules/nav-bar/stories/hover-effect/nav-bar-hover-effect.stories.tsx +52 -0
  62. package/src/components/molecules/nav-bar/stories/nav-bar.stories.tsx +50 -0
  63. package/src/components/molecules/nav-bar/styles/classes.ts +68 -0
  64. package/src/components/molecules/nav-bar/styles/index.ts +2 -0
  65. package/src/components/molecules/nav-bar/styles/styles.ts +85 -0
  66. package/src/components/molecules/nav-bar/sub-items-box.tsx +57 -0
  67. package/src/components/molecules/scaffold/scaffold.stories.tsx +21 -0
  68. package/src/components/molecules/scaffold/scaffold.tsx +36 -0
  69. package/src/components/molecules/side-bar/compact-side-bar.tsx +75 -0
  70. package/src/components/molecules/side-bar/index.ts +1 -0
  71. package/src/components/molecules/side-bar/side-bar-drawer.tsx +124 -0
  72. package/src/components/molecules/side-bar/side-bar.stories.tsx +111 -0
  73. package/src/components/molecules/side-bar/side-bar.tsx +31 -0
  74. package/src/components/molecules/side-bar/styles/classes.ts +28 -0
  75. package/src/components/molecules/side-bar/styles/index.ts +2 -0
  76. package/src/components/molecules/side-bar/styles/styles.ts +13 -0
  77. package/src/components/organisms/footer/copy-rights-box.tsx +27 -0
  78. package/src/components/organisms/footer/footer.tsx +75 -0
  79. package/src/components/organisms/footer/index.ts +5 -0
  80. package/src/components/organisms/footer/policies-box.tsx +26 -0
  81. package/src/components/organisms/footer/quick-links-box.tsx +45 -0
  82. package/src/components/organisms/footer/social-links-box.tsx +32 -0
  83. package/src/components/organisms/footer/stories/footer.stories.tsx +61 -0
  84. package/src/components/organisms/footer/styles/classes.ts +71 -0
  85. package/src/components/organisms/footer/styles/index.ts +2 -0
  86. package/src/components/organisms/footer/styles/styles.ts +6 -0
  87. package/src/components/organisms/header/header.tsx +94 -0
  88. package/src/components/organisms/header/segmented-header-content.tsx +37 -0
  89. package/src/components/organisms/header/stories/header.stories.tsx +144 -0
  90. package/src/components/organisms/header/styles/classes.ts +22 -0
  91. package/src/components/organisms/header/styles/index.ts +2 -0
  92. package/src/components/organisms/header/styles/styles.ts +39 -0
  93. package/src/components/organisms/index.ts +4 -0
  94. package/src/components/{item-details → organisms/item-details}/item-details.tsx +2 -2
  95. package/src/components/{listings → organisms/listings}/listings.tsx +2 -2
  96. package/src/components/templates/index.ts +1 -0
  97. package/src/components/templates/landing-page/index.ts +1 -0
  98. package/src/components/templates/landing-page/landing-page.stories.tsx +21 -0
  99. package/src/components/templates/landing-page/landing-page.tsx +57 -0
  100. package/src/components/templates/landing-page/styles/classes.ts +11 -0
  101. package/src/components/templates/landing-page/styles/index.ts +1 -0
  102. package/src/constants/defaults.ts +43 -8
  103. package/src/constants/fake.ts +5 -0
  104. package/src/constants/footer.tsx +157 -0
  105. package/src/constants/index.ts +3 -0
  106. package/src/constants/uploader.ts +27 -0
  107. package/src/context/emperor-ui-context.ts +4 -4
  108. package/src/context/index.ts +2 -0
  109. package/src/context/navigation-context.ts +6 -0
  110. package/src/context/uploader-context.ts +6 -0
  111. package/src/enums/index.ts +2 -0
  112. package/src/enums/placeholders.ts +4 -0
  113. package/src/enums/preserved-keys.ts +3 -0
  114. package/src/hooks/index.ts +3 -0
  115. package/src/hooks/use-emperor-ui.ts +1 -1
  116. package/src/hooks/use-navigation.ts +12 -0
  117. package/src/hooks/use-uploader-context.ts +14 -0
  118. package/src/hooks/use-uploader.tsx +151 -0
  119. package/src/index.ts +9 -5
  120. package/src/main.tsx +3 -0
  121. package/src/mocks/header.tsx +118 -0
  122. package/src/mocks/index.ts +1 -0
  123. package/src/providers/config-provider.tsx +54 -0
  124. package/src/providers/emperor-ui-provider.tsx +17 -24
  125. package/src/providers/index.ts +3 -0
  126. package/src/providers/navigation-provider.tsx +42 -0
  127. package/src/providers/uploader-provider.tsx +53 -0
  128. package/src/styles/globals.css +13 -0
  129. package/src/styles/hero.ts +2 -0
  130. package/src/types/components/atoms/brand.ts +13 -0
  131. package/src/types/components/atoms/column.ts +3 -0
  132. package/src/types/components/atoms/container.ts +3 -0
  133. package/src/types/components/atoms/index.ts +6 -0
  134. package/src/types/components/atoms/portal.ts +6 -0
  135. package/src/types/components/atoms/row.ts +3 -0
  136. package/src/types/components/atoms/uploader.ts +97 -0
  137. package/src/types/components/index.ts +3 -8
  138. package/src/types/components/{filter → molecules/filter}/filter.ts +1 -1
  139. package/src/types/components/molecules/footer/footer.ts +68 -0
  140. package/src/types/components/molecules/header/header.ts +51 -0
  141. package/src/types/components/molecules/index.ts +9 -0
  142. package/src/types/components/{item-card → molecules/item-card}/item-card.ts +1 -1
  143. package/src/types/components/{item-details → molecules/item-details}/item-details.ts +1 -1
  144. package/src/types/components/{listings → molecules/listings}/listings.ts +1 -1
  145. package/src/types/components/molecules/nav-bar/nav-bar.ts +66 -0
  146. package/src/types/components/{scaffold → molecules/scaffold}/scaffold.ts +1 -1
  147. package/src/types/components/molecules/side-bar/index.ts +1 -0
  148. package/src/types/components/molecules/side-bar/side-bar.ts +40 -0
  149. package/src/types/components/templates/index.ts +1 -0
  150. package/src/types/components/templates/landing-page.ts +10 -0
  151. package/src/types/context/config.ts +54 -0
  152. package/src/types/context/index.ts +2 -1
  153. package/src/types/context/navigation.ts +17 -0
  154. package/src/types/shared/components.ts +4 -0
  155. package/src/utils/compress-images.ts +36 -0
  156. package/src/utils/index.ts +3 -0
  157. package/src/utils/storybook.tsx +15 -0
  158. package/src/utils/uploader.ts +148 -0
  159. package/tsconfig.app.json +1 -9
  160. package/tsconfig.node.json +0 -1
  161. package/vite.config.ts +3 -8
  162. package/vitest.shims.d.ts +1 -1
  163. package/src/components/footer/footer.tsx +0 -6
  164. package/src/components/footer/index.ts +0 -1
  165. package/src/components/header/header.tsx +0 -49
  166. package/src/components/item-card/item-card.tsx +0 -6
  167. package/src/components/nav-bar/index.ts +0 -1
  168. package/src/components/nav-bar/nav-bar.tsx +0 -6
  169. package/src/components/scaffold/scaffold.tsx +0 -15
  170. package/src/index.css +0 -1
  171. package/src/types/components/footer/footer.ts +0 -9
  172. package/src/types/components/header/header.ts +0 -21
  173. package/src/types/components/nav-bar/nav-bar.ts +0 -9
  174. package/src/types/context/emperor-ui.ts +0 -37
  175. package/tailwind.config.js +0 -6
  176. /package/src/components/{filter → molecules/filter}/index.ts +0 -0
  177. /package/src/components/{item-card → molecules/item-card}/index.ts +0 -0
  178. /package/src/components/{scaffold → molecules/scaffold}/index.ts +0 -0
  179. /package/src/components/{header → organisms/header}/index.ts +0 -0
  180. /package/src/components/{item-details → organisms/item-details}/index.ts +0 -0
  181. /package/src/components/{listings → organisms/listings}/index.ts +0 -0
  182. /package/src/types/components/{filter → molecules/filter}/index.ts +0 -0
  183. /package/src/types/components/{footer → molecules/footer}/index.ts +0 -0
  184. /package/src/types/components/{header → molecules/header}/index.ts +0 -0
  185. /package/src/types/components/{item-card → molecules/item-card}/index.ts +0 -0
  186. /package/src/types/components/{item-details → molecules/item-details}/index.ts +0 -0
  187. /package/src/types/components/{listings → molecules/listings}/index.ts +0 -0
  188. /package/src/types/components/{nav-bar → molecules/nav-bar}/index.ts +0 -0
  189. /package/src/types/components/{scaffold → molecules/scaffold}/index.ts +0 -0
@@ -0,0 +1,5 @@
1
+ import { d as a } from "./features-animation-D_Ss-HYx.js";
2
+ var r = a;
3
+ export {
4
+ r as default
5
+ };
package/eslint.config.js CHANGED
@@ -10,21 +10,13 @@ import { defineConfig, globalIgnores } from "eslint/config";
10
10
 
11
11
  export default defineConfig([
12
12
  globalIgnores(["dist"]),
13
+ js.configs.recommended,
14
+ ...tseslint.configs.recommended,
15
+ reactHooks.configs.flat.recommended,
16
+ reactRefresh.configs.vite,
17
+ ...storybook.configs["flat/recommended"],
13
18
  {
14
19
  files: ["**/*.{ts,tsx}"],
15
- extends: [
16
- js.configs.recommended,
17
- tseslint.configs.recommended,
18
- reactHooks.configs.flat.recommended,
19
- reactRefresh.configs.vite,
20
- "eslint:recommended",
21
- "plugin:@typescript-eslint/recommended",
22
- "plugin:react-hooks/recommended",
23
- "plugin:storybook/recommended"
24
- ],
25
- ignorePatterns: ["dist", ".eslintrc.cjs"],
26
- parser: "@typescript-eslint/parser",
27
- plugins: ["react-refresh"],
28
20
  languageOptions: {
29
21
  ecmaVersion: 2020,
30
22
  globals: globals.browser,
@@ -40,4 +32,3 @@ export default defineConfig([
40
32
  },
41
33
  },
42
34
  ]);
43
-
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@js-empire/emperor-ui",
3
3
  "description": "They provide the atoms, we provide the empire.",
4
- "version": "1.0.1",
4
+ "version": "1.2.0",
5
5
  "author": "JS Empire - Mustafa Alhasanat",
6
6
  "license": "ISC",
7
7
  "type": "module",
@@ -14,7 +14,8 @@
14
14
  "types": "./dist/index.d.ts",
15
15
  "import": "./dist/emperor-ui.js",
16
16
  "require": "./dist/emperor-ui-umd.cjs"
17
- }
17
+ },
18
+ "./globals.css": "./dist/globals.css"
18
19
  },
19
20
  "scripts": {
20
21
  "dev": "vite",
@@ -24,7 +25,8 @@
24
25
  "lint": "eslint .",
25
26
  "preview": "vite preview",
26
27
  "storybook": "storybook dev -p 6006",
27
- "build-storybook": "storybook build"
28
+ "build-storybook": "storybook build",
29
+ "prepare": "husky"
28
30
  },
29
31
  "publishConfig": {
30
32
  "access": "public"
@@ -42,16 +44,29 @@
42
44
  "main"
43
45
  ]
44
46
  },
47
+ "resolutions": {
48
+ "jackspeak": "2.1.1"
49
+ },
45
50
  "dependencies": {
51
+ "@heroui/react": "^2.8.5",
52
+ "@heroui/theme": "^2.4.25",
53
+ "@storybook/react": "^10.1.8",
46
54
  "@tailwindcss/vite": "^4.1.17",
55
+ "browser-image-compression": "^2.0.2",
47
56
  "class-variance-authority": "^0.7.1",
48
57
  "clsx": "^2.1.1",
58
+ "framer-motion": "^12.23.26",
59
+ "husky": "^9.1.7",
60
+ "lucide-react": "^0.560.0",
61
+ "motion": "^12.26.2",
49
62
  "prettier": "^3.7.4",
50
63
  "react": "^19.2.0",
51
64
  "react-dom": "^19.2.0",
52
65
  "tailwind-merge": "^3.4.0",
66
+ "tailwind-scrollbar-hide": "^4.0.0",
53
67
  "tailwindcss": "^4.1.17",
54
- "vite-tsconfig-paths": "^5.1.4"
68
+ "vite-tsconfig-paths": "^5.1.4",
69
+ "xlsx": "^0.18.5"
55
70
  },
56
71
  "devDependencies": {
57
72
  "@chromatic-com/storybook": "^4.1.3",
@@ -78,8 +93,5 @@
78
93
  "vite": "^7.2.4",
79
94
  "vite-plugin-dts": "^4.5.4",
80
95
  "vitest": "^4.0.15"
81
- },
82
- "resolutions": {
83
- "jackspeak": "2.1.1"
84
96
  }
85
97
  }
Binary file
Binary file
Binary file
@@ -0,0 +1,27 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Brand } from "@/components";
3
+ import { getStorybookDecorators } from "@/utils";
4
+
5
+ const meta: Meta<typeof Brand> = {
6
+ title: "Atoms/Brand",
7
+ component: Brand,
8
+ parameters: {
9
+ layout: "centered",
10
+ },
11
+ tags: ["autodocs"],
12
+ decorators: getStorybookDecorators({
13
+ config: {
14
+ layout: {
15
+ withScaffold: false,
16
+ },
17
+ },
18
+ }),
19
+ };
20
+
21
+ export default meta;
22
+
23
+ type Story = StoryObj<typeof meta>;
24
+
25
+ export const Default: Story = {
26
+ args: {},
27
+ };
@@ -0,0 +1,56 @@
1
+ import type { BrandProps } from "@/types";
2
+ import { cn } from "@/utils";
3
+ import { VariantProps } from "class-variance-authority";
4
+ import { ComponentProps, forwardRef } from "react";
5
+ import { Row } from "@/components";
6
+ import { brandStyles } from "./styles";
7
+ import { Image } from "@heroui/react";
8
+
9
+ export const Brand = forwardRef<
10
+ HTMLElement,
11
+ ComponentProps<"div"> & VariantProps<typeof brandStyles> & BrandProps
12
+ >(
13
+ (
14
+ {
15
+ className,
16
+ variant,
17
+ src = "/images/emperor-ui-logo.png",
18
+ alt = "Emperor UI",
19
+ name = "Emperor UI",
20
+ isIconOnly = false,
21
+ classNames,
22
+ ...props
23
+ },
24
+ ref,
25
+ ) => {
26
+ return (
27
+ <Row
28
+ ref={ref}
29
+ data-slot="emperor-brand"
30
+ className={cn(
31
+ brandStyles({ variant, className: cn(className, classNames?.base) }),
32
+ )}
33
+ {...props}
34
+ >
35
+ {src && (
36
+ <Image
37
+ data-slot="emperor-brand-logo"
38
+ src={src}
39
+ alt={alt}
40
+ radius="md"
41
+ className={cn("min-w-7 min-h-7 size-7", classNames?.logo)}
42
+ />
43
+ )}
44
+
45
+ {name && !isIconOnly && (
46
+ <p
47
+ data-slot="emperor-brand-name"
48
+ className={cn("font-semibold text-lg", classNames?.name)}
49
+ >
50
+ {name}
51
+ </p>
52
+ )}
53
+ </Row>
54
+ );
55
+ },
56
+ );
@@ -0,0 +1 @@
1
+ export * from "./brand";
@@ -0,0 +1,9 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ export const brandStyles = cva([""], {
4
+ variants: {
5
+ variant: {},
6
+ },
7
+ defaultVariants: {},
8
+ compoundVariants: [],
9
+ });
@@ -0,0 +1,2 @@
1
+ export * from "./classes";
2
+ export * from "./styles";
File without changes
@@ -0,0 +1,37 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Column } from "@/components";
3
+ import type { ColumnProps } from "@/types";
4
+ import { getStorybookDecorators } from "@/utils";
5
+
6
+ const meta: Meta<typeof Column> = {
7
+ title: "Atoms/Column",
8
+ component: Column,
9
+ parameters: {
10
+ layout: "centered",
11
+ },
12
+ tags: ["autodocs"],
13
+ decorators: getStorybookDecorators({
14
+ config: {
15
+ layout: {
16
+ withScaffold: false,
17
+ },
18
+ },
19
+ }),
20
+ };
21
+
22
+ export default meta;
23
+
24
+ type Story = StoryObj<typeof meta>;
25
+
26
+ export const Default: Story = {
27
+ args: {},
28
+ render: (args: ColumnProps) => (
29
+ <Column {...args}>
30
+ {Array.from({ length: 5 }).map((_, index) => (
31
+ <div key={index} className="bg-blue-300 p-2 rounded-md">
32
+ Item {index + 1}
33
+ </div>
34
+ ))}
35
+ </Column>
36
+ ),
37
+ };
@@ -0,0 +1,21 @@
1
+ import type { ColumnProps } from "@/types";
2
+ import { cn } from "@/utils";
3
+ import { cva, VariantProps } from "class-variance-authority";
4
+ import { forwardRef, ComponentProps } from "react";
5
+
6
+ const columnStyles = cva(["flex flex-col gap-3"], {
7
+ variants: {},
8
+ defaultVariants: {},
9
+ compoundVariants: [],
10
+ });
11
+
12
+ export const Column = forwardRef<
13
+ HTMLElement,
14
+ ComponentProps<"section"> & VariantProps<typeof columnStyles> & ColumnProps
15
+ >(({ className, children, ...props }, ref) => {
16
+ return (
17
+ <section ref={ref} className={cn(columnStyles({ className }))} {...props}>
18
+ {children}
19
+ </section>
20
+ );
21
+ });
@@ -0,0 +1 @@
1
+ export * from "./column";
@@ -0,0 +1,37 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Container } from "@/components";
3
+ import { getStorybookDecorators } from "@/utils";
4
+ import type { ContainerProps } from "@/types";
5
+
6
+ const meta: Meta<typeof Container> = {
7
+ title: "Atoms/Container",
8
+ component: Container,
9
+ parameters: {
10
+ layout: "fullscreen",
11
+ },
12
+ tags: ["autodocs"],
13
+ decorators: getStorybookDecorators({
14
+ config: {
15
+ layout: {
16
+ withScaffold: false,
17
+ },
18
+ },
19
+ }),
20
+ };
21
+
22
+ export default meta;
23
+
24
+ type Story = StoryObj<typeof meta>;
25
+
26
+ export const Default: Story = {
27
+ args: {
28
+ className: "h-screen flex items-center justify-center",
29
+ },
30
+ render: (args: ContainerProps) => (
31
+ <Container {...args}>
32
+ <div className="bg-blue-300 p-2 text-center rounded-md w-full h-fit">
33
+ Responsive contained content
34
+ </div>
35
+ </Container>
36
+ ),
37
+ };
@@ -0,0 +1,28 @@
1
+ import type { ContainerProps } from "@/types";
2
+ import { cn } from "@/utils";
3
+ import { cva, VariantProps } from "class-variance-authority";
4
+ import { forwardRef, ComponentProps } from "react";
5
+
6
+ const containerStyles = cva(["flex w-full container p-4 mx-auto"], {
7
+ variants: {},
8
+ defaultVariants: {},
9
+ compoundVariants: [],
10
+ });
11
+
12
+ export const Container = forwardRef<
13
+ HTMLElement,
14
+ ComponentProps<"section"> &
15
+ VariantProps<typeof containerStyles> &
16
+ ContainerProps
17
+ >(({ className, children, ...props }, ref) => {
18
+ return (
19
+ <section
20
+ ref={ref}
21
+ data-slot="container"
22
+ className={cn(containerStyles({ className }))}
23
+ {...props}
24
+ >
25
+ {children}
26
+ </section>
27
+ );
28
+ });
@@ -0,0 +1 @@
1
+ export * from "./container";
@@ -0,0 +1,6 @@
1
+ export * from "./brand";
2
+ export * from "./column";
3
+ export * from "./container";
4
+ export * from "./row";
5
+ export * from "./portal";
6
+ export * from "./uploader";
@@ -0,0 +1 @@
1
+ export * from "./portal";
@@ -0,0 +1,43 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Portal } from "@/components";
3
+ import { getStorybookDecorators } from "@/utils";
4
+ import { FAKE_PARAGRAPH } from "@/constants";
5
+
6
+ const meta: Meta<typeof Portal> = {
7
+ title: "Atoms/Portal",
8
+ component: Portal,
9
+ parameters: {
10
+ layout: "fullscreen",
11
+ },
12
+ tags: ["autodocs"],
13
+ decorators: getStorybookDecorators({
14
+ config: {
15
+ layout: {
16
+ withScaffold: false,
17
+ },
18
+ },
19
+ }),
20
+ };
21
+
22
+ export default meta;
23
+
24
+ type Story = StoryObj<typeof meta>;
25
+
26
+ export const Default: Story = {
27
+ args: {},
28
+ render: () => (
29
+ <main className="h-screen w-full flex flex-col gap-10 p-5">
30
+ <div id="portal-container" />
31
+
32
+ <p>{FAKE_PARAGRAPH}</p>
33
+ <p>{FAKE_PARAGRAPH}</p>
34
+ <p>{FAKE_PARAGRAPH}</p>
35
+
36
+ <Portal containerId="portal-container">
37
+ <div className="bg-blue-300 p-2 rounded-md absolute top-5 left-1/2 -translate-x-1/2">
38
+ <h2>Portal Content</h2>
39
+ </div>
40
+ </Portal>
41
+ </main>
42
+ ),
43
+ };
@@ -0,0 +1,25 @@
1
+ import { PortalProps } from "@/types";
2
+ import { useEffect, useState } from "react";
3
+ import { createPortal } from "react-dom";
4
+
5
+ export function Portal({
6
+ children,
7
+ containerId,
8
+ isVisible = true,
9
+ }: PortalProps) {
10
+ const [container, setContainer] = useState<HTMLElement | null>(null);
11
+
12
+ useEffect(() => {
13
+ const element = document.getElementById(containerId);
14
+
15
+ setTimeout(() => {
16
+ setContainer(element);
17
+ }, 100);
18
+ }, [containerId]);
19
+
20
+ if (!container || !isVisible) {
21
+ return null;
22
+ }
23
+
24
+ return createPortal(children, container);
25
+ }
@@ -0,0 +1 @@
1
+ export * from "./row";
@@ -0,0 +1,37 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Row } from "@/components";
3
+ import { getStorybookDecorators } from "@/utils";
4
+ import type { RowProps } from "@/types";
5
+
6
+ const meta: Meta<typeof Row> = {
7
+ title: "Atoms/Row",
8
+ component: Row,
9
+ parameters: {
10
+ layout: "centered",
11
+ },
12
+ tags: ["autodocs"],
13
+ decorators: getStorybookDecorators({
14
+ config: {
15
+ layout: {
16
+ withScaffold: false,
17
+ },
18
+ },
19
+ }),
20
+ };
21
+
22
+ export default meta;
23
+
24
+ type Story = StoryObj<typeof meta>;
25
+
26
+ export const Default: Story = {
27
+ args: {},
28
+ render: (args: RowProps) => (
29
+ <Row {...args}>
30
+ {Array.from({ length: 5 }).map((_, index) => (
31
+ <div key={index} className="bg-blue-300 p-2 rounded-md">
32
+ Item {index + 1}
33
+ </div>
34
+ ))}
35
+ </Row>
36
+ ),
37
+ };
@@ -0,0 +1,26 @@
1
+ import type { RowProps } from "@/types";
2
+ import { cn } from "@/utils";
3
+ import { cva, VariantProps } from "class-variance-authority";
4
+ import { forwardRef, ComponentProps } from "react";
5
+
6
+ const rowStyles = cva(["flex items-center gap-3"], {
7
+ variants: {},
8
+ defaultVariants: {},
9
+ compoundVariants: [],
10
+ });
11
+
12
+ export const Row = forwardRef<
13
+ HTMLElement,
14
+ ComponentProps<"section"> & VariantProps<typeof rowStyles> & RowProps
15
+ >(({ className, children, ...props }, ref) => {
16
+ return (
17
+ <section
18
+ ref={ref}
19
+ data-slot="row"
20
+ className={cn(rowStyles({ className }))}
21
+ {...props}
22
+ >
23
+ {children}
24
+ </section>
25
+ );
26
+ });
@@ -0,0 +1,83 @@
1
+ "use client";
2
+
3
+ import { Placeholders } from "@/enums";
4
+ import { Avatar, Spinner, cn } from "@heroui/react";
5
+ import { useEmperorUI, useUploaderContext } from "@/hooks";
6
+ import { useState } from "react";
7
+
8
+ export function AvatarLabel() {
9
+ const { config } = useEmperorUI();
10
+ const [draggableMessage, setDraggableMessage] = useState<string | null>(null);
11
+ const {
12
+ labelId,
13
+ classNames,
14
+ labelContent,
15
+ isDraggable,
16
+ onInputChange,
17
+ avatarLabelContent,
18
+ placeholderImage,
19
+ files,
20
+ isLoading,
21
+ } = useUploaderContext();
22
+
23
+ const locales = config?.interLocalization?.locales;
24
+ const lang = config?.interLocalization?.lang;
25
+
26
+ const locale = locales?.[lang || "en"];
27
+
28
+ const handleDrop = (
29
+ event: React.ChangeEvent<HTMLInputElement> &
30
+ React.DragEvent<HTMLLabelElement>,
31
+ ) => {
32
+ event.preventDefault();
33
+ if (onInputChange) onInputChange(event);
34
+ };
35
+
36
+ const handleDragOver = (
37
+ event: React.ChangeEvent<HTMLInputElement> &
38
+ React.DragEvent<HTMLLabelElement>,
39
+ ) => {
40
+ event.preventDefault();
41
+ setDraggableMessage(locale?.dropHere || "");
42
+ };
43
+
44
+ const handleDragLeave = () => {
45
+ setDraggableMessage("");
46
+ };
47
+
48
+ if (isLoading)
49
+ return (
50
+ <div className={cn("mx-auto", classNames?.label)}>
51
+ <Spinner className="mx-auto" size="lg" />;
52
+ </div>
53
+ );
54
+
55
+ return (
56
+ <label
57
+ className={cn(
58
+ "w-full cursor-pointer mx-auto transition-opacity flex flex-col gap-5",
59
+ draggableMessage && "opacity-60",
60
+ classNames?.label,
61
+ )}
62
+ htmlFor={labelId}
63
+ onDrop={isDraggable ? handleDrop : () => {}}
64
+ onDragOver={isDraggable ? handleDragOver : () => {}}
65
+ onDragLeave={isDraggable ? handleDragLeave : () => {}}
66
+ >
67
+ {avatarLabelContent}
68
+
69
+ {labelContent || (
70
+ <Avatar
71
+ src={
72
+ files?.[0]?.view ||
73
+ placeholderImage ||
74
+ Placeholders.PLACEHOLDER_MALE_AVATAR
75
+ }
76
+ alt="avatar"
77
+ size="lg"
78
+ className={cn("size-24", classNames?.avatar)}
79
+ />
80
+ )}
81
+ </label>
82
+ );
83
+ }
@@ -0,0 +1,7 @@
1
+ export * from "./uploader";
2
+ export * from "./avatar-label";
3
+ export * from "./upload-file-label";
4
+ export * from "./view-image-modal";
5
+ export * from "./upload-file-listing";
6
+ export * from "./upload-file-error-box";
7
+ export * from "./upload-file-input";