@js-empire/emperor-ui 1.0.0 → 1.1.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 (216) 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/.vscode/extensions.json +3 -0
  5. package/README.md +68 -1
  6. package/package.json +19 -4
  7. package/public/icons/emperor-ui-logo.ico +0 -0
  8. package/public/images/avatar-female.jpg +0 -0
  9. package/public/images/avatar-male.jpg +0 -0
  10. package/public/images/emperor-ui-logo.png +0 -0
  11. package/src/components/atoms/brand/brand.stories.tsx +27 -0
  12. package/src/components/atoms/brand/brand.tsx +56 -0
  13. package/src/components/atoms/brand/index.ts +1 -0
  14. package/src/components/atoms/brand/styles/classes.ts +9 -0
  15. package/src/components/atoms/brand/styles/index.ts +2 -0
  16. package/src/components/atoms/brand/styles/styles.ts +0 -0
  17. package/src/components/atoms/column/column.stories.tsx +36 -0
  18. package/src/components/atoms/column/column.tsx +21 -0
  19. package/src/components/atoms/column/index.ts +1 -0
  20. package/src/components/atoms/container/column.stories.tsx +36 -0
  21. package/src/components/atoms/container/container.tsx +28 -0
  22. package/src/components/atoms/container/index.ts +1 -0
  23. package/src/components/atoms/index.ts +6 -0
  24. package/src/components/atoms/portal/index.ts +1 -0
  25. package/src/components/atoms/portal/portal.stories.tsx +43 -0
  26. package/src/components/atoms/portal/portal.tsx +23 -0
  27. package/src/components/atoms/row/index.ts +1 -0
  28. package/src/components/atoms/row/row.stories.tsx +36 -0
  29. package/src/components/atoms/row/row.tsx +26 -0
  30. package/src/components/atoms/uploader/avatar-label.tsx +83 -0
  31. package/src/components/atoms/uploader/index.ts +7 -0
  32. package/src/components/atoms/uploader/stories/uploader.stories.tsx +41 -0
  33. package/src/components/atoms/uploader/upload-file-error-box.tsx +29 -0
  34. package/src/components/atoms/uploader/upload-file-input.tsx +36 -0
  35. package/src/components/atoms/uploader/upload-file-label.tsx +74 -0
  36. package/src/components/atoms/uploader/upload-file-listing.tsx +53 -0
  37. package/src/components/atoms/uploader/uploader.tsx +55 -0
  38. package/src/components/atoms/uploader/view-image-modal.tsx +39 -0
  39. package/src/components/index.ts +4 -8
  40. package/src/components/molecules/index.ts +5 -0
  41. package/src/components/molecules/item-card/item-card.tsx +6 -0
  42. package/src/components/molecules/nav-bar/index.ts +3 -0
  43. package/src/components/molecules/nav-bar/nav-bar-item.tsx +70 -0
  44. package/src/components/molecules/nav-bar/nav-bar.tsx +65 -0
  45. package/src/components/molecules/nav-bar/stories/hover-effect/nav-bar-hover-effect.stories.tsx +52 -0
  46. package/src/components/molecules/nav-bar/stories/nav-bar.stories.tsx +50 -0
  47. package/src/components/molecules/nav-bar/styles/classes.ts +68 -0
  48. package/src/components/molecules/nav-bar/styles/index.ts +2 -0
  49. package/src/components/molecules/nav-bar/styles/styles.ts +84 -0
  50. package/src/components/molecules/nav-bar/sub-items-box.tsx +57 -0
  51. package/src/components/molecules/scaffold/scaffold.stories.tsx +21 -0
  52. package/src/components/molecules/scaffold/scaffold.tsx +36 -0
  53. package/src/components/molecules/side-bar/compact-side-bar.tsx +73 -0
  54. package/src/components/molecules/side-bar/index.ts +1 -0
  55. package/src/components/molecules/side-bar/side-bar-drawer.tsx +124 -0
  56. package/src/components/molecules/side-bar/side-bar.stories.tsx +110 -0
  57. package/src/components/molecules/side-bar/side-bar.tsx +31 -0
  58. package/src/components/molecules/side-bar/styles/classes.ts +28 -0
  59. package/src/components/molecules/side-bar/styles/index.ts +2 -0
  60. package/src/components/molecules/side-bar/styles/styles.ts +13 -0
  61. package/src/components/organisms/footer/footer.tsx +20 -0
  62. package/src/components/organisms/footer/styles/classes.ts +15 -0
  63. package/src/components/organisms/footer/styles/index.ts +2 -0
  64. package/src/components/organisms/footer/styles/styles.ts +9 -0
  65. package/src/components/organisms/header/header.tsx +94 -0
  66. package/src/components/organisms/header/segmented-header-content.tsx +37 -0
  67. package/src/components/organisms/header/stories/header.stories.tsx +143 -0
  68. package/src/components/organisms/header/styles/classes.ts +22 -0
  69. package/src/components/organisms/header/styles/index.ts +2 -0
  70. package/src/components/organisms/header/styles/styles.ts +39 -0
  71. package/src/components/organisms/index.ts +4 -0
  72. package/src/components/templates/index.ts +1 -0
  73. package/src/components/templates/landing-page/index.ts +1 -0
  74. package/src/components/templates/landing-page/landing-page.stories.tsx +21 -0
  75. package/src/components/templates/landing-page/landing-page.tsx +57 -0
  76. package/src/components/templates/landing-page/styles/classes.ts +11 -0
  77. package/src/components/templates/landing-page/styles/index.ts +1 -0
  78. package/src/constants/defaults.ts +42 -7
  79. package/src/constants/fake.ts +2 -0
  80. package/src/constants/index.ts +2 -0
  81. package/src/constants/uploader.ts +27 -0
  82. package/src/context/emperor-ui-context.ts +4 -4
  83. package/src/context/index.ts +2 -0
  84. package/src/context/navigation-context.ts +6 -0
  85. package/src/context/uploader-context.ts +6 -0
  86. package/src/enums/index.ts +2 -0
  87. package/src/enums/placeholders.ts +4 -0
  88. package/src/enums/preserved-keys.ts +3 -0
  89. package/src/hooks/index.ts +3 -0
  90. package/src/hooks/use-navigation.ts +12 -0
  91. package/src/hooks/use-uploader-context.ts +14 -0
  92. package/src/hooks/use-uploader.tsx +215 -0
  93. package/src/index.ts +9 -5
  94. package/src/main.tsx +3 -0
  95. package/src/mocks/header.tsx +118 -0
  96. package/src/mocks/index.ts +1 -0
  97. package/src/providers/config-provider.tsx +54 -0
  98. package/src/providers/emperor-ui-provider.tsx +17 -24
  99. package/src/providers/index.ts +3 -0
  100. package/src/providers/navigation-provider.tsx +42 -0
  101. package/src/providers/uploader-provider.tsx +53 -0
  102. package/src/styles/globals.css +13 -0
  103. package/src/styles/hero.ts +2 -0
  104. package/src/types/components/atoms/brand.ts +13 -0
  105. package/src/types/components/atoms/column.ts +3 -0
  106. package/src/types/components/atoms/container.ts +3 -0
  107. package/src/types/components/atoms/index.ts +6 -0
  108. package/src/types/components/atoms/portal.ts +6 -0
  109. package/src/types/components/atoms/row.ts +3 -0
  110. package/src/types/components/atoms/uploader.ts +104 -0
  111. package/src/types/components/index.ts +3 -8
  112. package/src/types/components/molecules/header/header.ts +51 -0
  113. package/src/types/components/molecules/index.ts +9 -0
  114. package/src/types/components/molecules/nav-bar/nav-bar.ts +65 -0
  115. package/src/types/components/molecules/side-bar/index.ts +1 -0
  116. package/src/types/components/molecules/side-bar/side-bar.ts +40 -0
  117. package/src/types/components/templates/index.ts +1 -0
  118. package/src/types/components/templates/landing-page.ts +10 -0
  119. package/src/types/context/config.ts +54 -0
  120. package/src/types/context/index.ts +2 -1
  121. package/src/types/context/navigation.ts +17 -0
  122. package/src/types/shared/components.ts +4 -0
  123. package/src/utils/compress-images.ts +36 -0
  124. package/src/utils/index.ts +2 -0
  125. package/src/utils/storybook.tsx +15 -0
  126. package/tsconfig.app.json +3 -2
  127. package/tsconfig.node.json +0 -1
  128. package/vite.config.ts +5 -1
  129. package/dist/emperor-ui.js +0 -3171
  130. package/dist/emperor-ui.umd.cjs +0 -6
  131. package/dist/src/components/filter/filter.d.ts +0 -3
  132. package/dist/src/components/filter/index.d.ts +0 -1
  133. package/dist/src/components/footer/footer.d.ts +0 -3
  134. package/dist/src/components/footer/index.d.ts +0 -1
  135. package/dist/src/components/header/header.d.ts +0 -9
  136. package/dist/src/components/header/index.d.ts +0 -1
  137. package/dist/src/components/index.d.ts +0 -8
  138. package/dist/src/components/item-card/index.d.ts +0 -1
  139. package/dist/src/components/item-card/item-card.d.ts +0 -3
  140. package/dist/src/components/item-details/index.d.ts +0 -1
  141. package/dist/src/components/item-details/item-details.d.ts +0 -3
  142. package/dist/src/components/listings/index.d.ts +0 -1
  143. package/dist/src/components/listings/listings.d.ts +0 -3
  144. package/dist/src/components/nav-bar/index.d.ts +0 -1
  145. package/dist/src/components/nav-bar/nav-bar.d.ts +0 -3
  146. package/dist/src/components/scaffold/index.d.ts +0 -1
  147. package/dist/src/components/scaffold/scaffold.d.ts +0 -3
  148. package/dist/src/constants/defaults.d.ts +0 -4
  149. package/dist/src/constants/index.d.ts +0 -1
  150. package/dist/src/context/emperor-ui-context.d.ts +0 -3
  151. package/dist/src/context/index.d.ts +0 -1
  152. package/dist/src/examples/index.d.ts +0 -1
  153. package/dist/src/hooks/index.d.ts +0 -1
  154. package/dist/src/hooks/use-emperor-ui.d.ts +0 -1
  155. package/dist/src/index.d.ts +0 -8
  156. package/dist/src/providers/emperor-ui-provider.d.ts +0 -3
  157. package/dist/src/providers/index.d.ts +0 -1
  158. package/dist/src/types/components/filter/filter.d.ts +0 -8
  159. package/dist/src/types/components/filter/index.d.ts +0 -1
  160. package/dist/src/types/components/footer/footer.d.ts +0 -8
  161. package/dist/src/types/components/footer/index.d.ts +0 -1
  162. package/dist/src/types/components/header/header.d.ts +0 -19
  163. package/dist/src/types/components/header/index.d.ts +0 -1
  164. package/dist/src/types/components/index.d.ts +0 -8
  165. package/dist/src/types/components/item-card/index.d.ts +0 -1
  166. package/dist/src/types/components/item-card/item-card.d.ts +0 -8
  167. package/dist/src/types/components/item-details/index.d.ts +0 -1
  168. package/dist/src/types/components/item-details/item-details.d.ts +0 -8
  169. package/dist/src/types/components/listings/index.d.ts +0 -1
  170. package/dist/src/types/components/listings/listings.d.ts +0 -8
  171. package/dist/src/types/components/nav-bar/index.d.ts +0 -1
  172. package/dist/src/types/components/nav-bar/nav-bar.d.ts +0 -8
  173. package/dist/src/types/components/scaffold/index.d.ts +0 -1
  174. package/dist/src/types/components/scaffold/scaffold.d.ts +0 -8
  175. package/dist/src/types/context/emperor-ui.d.ts +0 -31
  176. package/dist/src/types/context/index.d.ts +0 -1
  177. package/dist/src/types/index.d.ts +0 -3
  178. package/dist/src/types/shared/components.d.ts +0 -6
  179. package/dist/src/types/shared/index.d.ts +0 -1
  180. package/dist/src/utils/cn.d.ts +0 -3
  181. package/dist/src/utils/index.d.ts +0 -1
  182. package/src/components/footer/footer.tsx +0 -6
  183. package/src/components/header/header.tsx +0 -49
  184. package/src/components/item-card/item-card.tsx +0 -6
  185. package/src/components/nav-bar/index.ts +0 -1
  186. package/src/components/nav-bar/nav-bar.tsx +0 -6
  187. package/src/components/scaffold/scaffold.tsx +0 -15
  188. package/src/index.css +0 -1
  189. package/src/types/components/header/header.ts +0 -21
  190. package/src/types/components/nav-bar/nav-bar.ts +0 -9
  191. package/src/types/context/emperor-ui.ts +0 -37
  192. package/tailwind.config.js +0 -6
  193. /package/src/components/{filter → molecules/filter}/filter.tsx +0 -0
  194. /package/src/components/{filter → molecules/filter}/index.ts +0 -0
  195. /package/src/components/{item-card → molecules/item-card}/index.ts +0 -0
  196. /package/src/components/{scaffold → molecules/scaffold}/index.ts +0 -0
  197. /package/src/components/{footer → organisms/footer}/index.ts +0 -0
  198. /package/src/components/{header → organisms/header}/index.ts +0 -0
  199. /package/src/components/{item-details → organisms/item-details}/index.ts +0 -0
  200. /package/src/components/{item-details → organisms/item-details}/item-details.tsx +0 -0
  201. /package/src/components/{listings → organisms/listings}/index.ts +0 -0
  202. /package/src/components/{listings → organisms/listings}/listings.tsx +0 -0
  203. /package/src/types/components/{filter → molecules/filter}/filter.ts +0 -0
  204. /package/src/types/components/{filter → molecules/filter}/index.ts +0 -0
  205. /package/src/types/components/{footer → molecules/footer}/footer.ts +0 -0
  206. /package/src/types/components/{footer → molecules/footer}/index.ts +0 -0
  207. /package/src/types/components/{header → molecules/header}/index.ts +0 -0
  208. /package/src/types/components/{item-card → molecules/item-card}/index.ts +0 -0
  209. /package/src/types/components/{item-card → molecules/item-card}/item-card.ts +0 -0
  210. /package/src/types/components/{item-details → molecules/item-details}/index.ts +0 -0
  211. /package/src/types/components/{item-details → molecules/item-details}/item-details.ts +0 -0
  212. /package/src/types/components/{listings → molecules/listings}/index.ts +0 -0
  213. /package/src/types/components/{listings → molecules/listings}/listings.ts +0 -0
  214. /package/src/types/components/{nav-bar → molecules/nav-bar}/index.ts +0 -0
  215. /package/src/types/components/{scaffold → molecules/scaffold}/index.ts +0 -0
  216. /package/src/types/components/{scaffold → molecules/scaffold}/scaffold.ts +0 -0
@@ -0,0 +1,215 @@
1
+ "use client";
2
+
3
+ import { addToast } from "@heroui/react";
4
+ import {
5
+ FileObject,
6
+ FileType,
7
+ UseUploadFileProps,
8
+ UseUploadFileReturn,
9
+ } from "@types";
10
+ import { useState } from "react";
11
+ import { useEmperorUI } from "@hooks";
12
+ import { compressImage } from "@utils";
13
+ import {
14
+ ALLOWED_IMAGES_TYPES,
15
+ ALLOWED_PDF_TYPES,
16
+ ALLOWED_DOC_TYPES,
17
+ ONE_MEGABYTE,
18
+ } from "@constants";
19
+
20
+ export const useUploader = ({
21
+ labelContent,
22
+ labelId,
23
+ fileTypes,
24
+ isRequired = true,
25
+ isDraggable = true,
26
+ isMulti = false,
27
+ preventDuplicates = true,
28
+ maxCount = 5,
29
+ maxFileSize = ONE_MEGABYTE * 10,
30
+ compressFiles = false,
31
+ onChange = () => {},
32
+ }: UseUploadFileProps): UseUploadFileReturn => {
33
+ const { config } = useEmperorUI();
34
+ const [files, setFiles] = useState<FileObject[]>([]);
35
+ const [isLoading, setIsLoading] = useState(false);
36
+
37
+ const locales = config?.interLocalization?.locales;
38
+ const lang = config?.interLocalization?.lang;
39
+
40
+ const locale = locales?.[lang || "en"];
41
+
42
+ // remove all uploaded files
43
+ const handleClearFile = (fileName?: string) => {
44
+ setFiles((prev) => prev?.filter((file) => file?.file?.name !== fileName));
45
+ };
46
+
47
+ // get the corresponding FileType giving the extension of the uploaded file
48
+ const mapFileType = (fileType: string): FileType | null => {
49
+ if (ALLOWED_IMAGES_TYPES.includes(fileType)) return "image";
50
+ if (ALLOWED_PDF_TYPES.includes(fileType)) return "pdf";
51
+ if (ALLOWED_DOC_TYPES.includes(fileType)) return "doc";
52
+
53
+ return null;
54
+ };
55
+
56
+ // get the allowed file types according to the specified types from the 'fileTypes' array
57
+ const getAllowedTypes = (): string[] => {
58
+ const allowedTypes: string[] = [];
59
+
60
+ fileTypes.forEach((fileType) => {
61
+ if (fileType === "image") allowedTypes.push(...ALLOWED_IMAGES_TYPES);
62
+ if (fileType === "doc") allowedTypes.push(...ALLOWED_DOC_TYPES);
63
+ if (fileType === "pdf") allowedTypes.push(...ALLOWED_PDF_TYPES);
64
+ });
65
+
66
+ return allowedTypes;
67
+ };
68
+
69
+ // check if the file size exceeds the maxFileSize
70
+ const isMaxFileSizeExceeded = (fileSize: number): boolean =>
71
+ fileSize > maxFileSize * 1024;
72
+
73
+ const isDuplicated = (name: string): boolean =>
74
+ files?.filter(({ file }) => file?.name === name)?.length > 0;
75
+
76
+ // handle the uploading process including the window upload and the drag-and-drop upload
77
+ const onInputChange = async (
78
+ event: React.ChangeEvent<HTMLInputElement> &
79
+ React.DragEvent<HTMLLabelElement>,
80
+ ): Promise<void> => {
81
+ if (
82
+ (!event.target.files || !event.target.files?.[0]) &&
83
+ (!event?.dataTransfer?.files || !event?.dataTransfer?.files[0])
84
+ ) {
85
+ addToast({
86
+ title: locale?.errorUploadingFile,
87
+ });
88
+ return;
89
+ }
90
+
91
+ // validate the file type according to the given allowed types
92
+ const allowedTypes = getAllowedTypes();
93
+
94
+ // verify if the files exist
95
+ if (!event.target.files && !event.dataTransfer.files) return;
96
+
97
+ // get the uploaded files
98
+ const uploadedFiles = Array.from(
99
+ event.target.files || event.dataTransfer.files,
100
+ );
101
+
102
+ // validate the files' length and prevent exceeded files only in the multiple-mode
103
+ if (
104
+ isMulti &&
105
+ (uploadedFiles?.length > maxCount ||
106
+ files?.length + uploadedFiles?.length > maxCount)
107
+ ) {
108
+ addToast({
109
+ title: `${locale?.maxNumImages} ${maxCount}`,
110
+ });
111
+ return;
112
+ }
113
+
114
+ // validate the files' types according to the given allowed types
115
+ if (
116
+ !uploadedFiles
117
+ ?.map((file) => file?.type)
118
+ ?.every((type) => allowedTypes.includes(type))
119
+ ) {
120
+ addToast({
121
+ title: `${locale?.errorUploadedTypes} ${allowedTypes.join(", ")}`,
122
+ });
123
+ return;
124
+ }
125
+
126
+ // validate the files' sizes if none of them exceeds the maximum allowed size
127
+ // validate files' names to ensure there are no duplicates if specified
128
+ let isInValid = false;
129
+
130
+ const compressedFiles = await Promise.all(
131
+ uploadedFiles?.map(async (file) => {
132
+ if (isMaxFileSizeExceeded(file?.size)) {
133
+ addToast({
134
+ title: locale?.maxSizeExceededError
135
+ .replace("MAX_FILE_SIZE", (maxFileSize / 1024 || 0)?.toString())
136
+ .replace(
137
+ "UPLOADED_FILE_SIZE",
138
+ (file?.size / 1024 / 1024 || 0)?.toFixed(1)?.toString(),
139
+ ),
140
+ });
141
+
142
+ if (compressFiles) {
143
+ return (await compressImage({ file }))?.file;
144
+ } else {
145
+ isInValid = true;
146
+ return file;
147
+ }
148
+ }
149
+
150
+ if (preventDuplicates && isDuplicated(file?.name)) {
151
+ addToast({
152
+ title: locale?.duplicatesDenied,
153
+ });
154
+ isInValid = true;
155
+ }
156
+
157
+ return file;
158
+ }),
159
+ );
160
+
161
+ if (isInValid) return;
162
+
163
+ setIsLoading(true);
164
+
165
+ await Promise.all(
166
+ compressedFiles?.map((uploadedFile) => {
167
+ if (uploadedFile) {
168
+ // validate the file extension according to the allowed extensions
169
+ const fileType = mapFileType(uploadedFile?.type);
170
+ if (!fileType) {
171
+ addToast({
172
+ title: `${locale?.errorUploadedTypes} ${allowedTypes.join(", ")}`,
173
+ });
174
+ return;
175
+ }
176
+
177
+ // set the file to be utilized, and the image to be viewed
178
+ const reader = new FileReader();
179
+ reader.onload = () => {
180
+ setFiles((prevFiles) => [
181
+ ...(isMulti ? prevFiles : []),
182
+ {
183
+ file: uploadedFile,
184
+ view: reader.result as string,
185
+ type: fileType,
186
+ url: URL.createObjectURL(uploadedFile),
187
+ },
188
+ ]);
189
+ };
190
+ reader.readAsDataURL(uploadedFile);
191
+ }
192
+ }),
193
+ ).finally(() => {
194
+ setIsLoading(false);
195
+ });
196
+
197
+ setTimeout(() => {
198
+ onChange();
199
+ }, 200);
200
+ };
201
+
202
+ return {
203
+ files,
204
+ fileTypes,
205
+ labelId,
206
+ isRequired,
207
+ labelContent,
208
+ isDraggable,
209
+ isMulti,
210
+ handleClearFile,
211
+ onInputChange,
212
+ setFiles,
213
+ isLoading,
214
+ };
215
+ };
package/src/index.ts CHANGED
@@ -1,8 +1,12 @@
1
+ import "./styles/globals.css";
2
+
1
3
  export * from "./components";
2
- export type * from "./types";
3
- export * from "./utils";
4
- export * from "./providers";
5
- export * from "./context";
6
- export * from "./hooks";
7
4
  export * from "./constants";
5
+ export * from "./context";
8
6
  export * from "./examples";
7
+ export * from "./hooks";
8
+ export * from "./providers";
9
+ export type * from "./types";
10
+ export * from "./utils";
11
+ export * from "./mocks";
12
+ export * from "./enums";
package/src/main.tsx ADDED
@@ -0,0 +1,3 @@
1
+ export function Main() {
2
+ return <div>Main</div>;
3
+ }
@@ -0,0 +1,118 @@
1
+ import { SideBarAction, NavigationItem } from "@types";
2
+ import {
3
+ HelpCircleIcon,
4
+ HomeIcon,
5
+ InfoIcon,
6
+ LifeBuoyIcon,
7
+ LogOutIcon,
8
+ MailIcon,
9
+ ServerIcon,
10
+ SettingsIcon,
11
+ } from "lucide-react";
12
+
13
+ export const MOCK_HEADER_SUB_ITEMS: NavigationItem[] = [
14
+ {
15
+ id: "info",
16
+ label: "Info",
17
+ href: "#info",
18
+ Icon: InfoIcon,
19
+ },
20
+ {
21
+ id: "contact",
22
+ label: "Contact",
23
+ href: "#contact",
24
+ Icon: MailIcon,
25
+ },
26
+ {
27
+ id: "services",
28
+ label: "Services",
29
+ href: "#services",
30
+ Icon: ServerIcon,
31
+ },
32
+ {
33
+ id: "settings",
34
+ label: "Settings",
35
+ href: "#settings",
36
+ Icon: SettingsIcon,
37
+ },
38
+ {
39
+ id: "help",
40
+ label: "Help",
41
+ href: "#help",
42
+ Icon: HelpCircleIcon,
43
+ },
44
+ {
45
+ id: "support",
46
+ label: "Support",
47
+ href: "#support",
48
+ Icon: LifeBuoyIcon,
49
+ },
50
+ ];
51
+
52
+ export const MOCK_HEADER_ITEMS: NavigationItem[] = [
53
+ {
54
+ id: "home",
55
+ label: "Home",
56
+ href: "#home",
57
+ Icon: HomeIcon,
58
+ },
59
+ {
60
+ id: "about",
61
+ label: "About",
62
+ href: "#about",
63
+ Icon: InfoIcon,
64
+ },
65
+ {
66
+ id: "contact",
67
+ label: "Contact",
68
+ href: "#contact",
69
+ Icon: MailIcon,
70
+ },
71
+ {
72
+ id: "services",
73
+ label: "Services",
74
+ href: "#services",
75
+ Icon: ServerIcon,
76
+ },
77
+ ];
78
+
79
+ export const MOCK_HEADER_ITEMS_WITH_SUB_ITEMS: NavigationItem[] = [
80
+ {
81
+ id: "home",
82
+ label: "Home",
83
+ href: "#home",
84
+ Icon: HomeIcon,
85
+ subItems: MOCK_HEADER_SUB_ITEMS,
86
+ },
87
+ {
88
+ id: "about",
89
+ label: "About",
90
+ href: "#about",
91
+ Icon: InfoIcon,
92
+ subItems: MOCK_HEADER_SUB_ITEMS,
93
+ },
94
+ {
95
+ id: "contact",
96
+ label: "Contact",
97
+ href: "#contact",
98
+ Icon: MailIcon,
99
+ subItems: MOCK_HEADER_SUB_ITEMS,
100
+ },
101
+ {
102
+ id: "services",
103
+ label: "Services",
104
+ href: "#services",
105
+ Icon: ServerIcon,
106
+ subItems: MOCK_HEADER_SUB_ITEMS,
107
+ },
108
+ ];
109
+
110
+ export const MOCK_HEADER_ACTIONS: SideBarAction[] = [
111
+ {
112
+ key: "logout",
113
+ label: "Logout",
114
+ color: "danger",
115
+ onPress: () => console.log("logout"),
116
+ startContent: <LogOutIcon />,
117
+ },
118
+ ];
@@ -0,0 +1 @@
1
+ export * from "./header";
@@ -0,0 +1,54 @@
1
+ import { Scaffold } from "@components";
2
+ import { defaultEmperorUIConfig } from "@constants";
3
+ import { EmperorUIContext } from "@context";
4
+ import type {
5
+ ConfigContextState,
6
+ ConfigProviderProps,
7
+ EmperorUIConfig,
8
+ } from "@types";
9
+ import { useMemo } from "react";
10
+
11
+ export function ConfigProvider({
12
+ children,
13
+ config = defaultEmperorUIConfig,
14
+ }: ConfigProviderProps) {
15
+ const emperorUIProviderValue: ConfigContextState = useMemo(() => {
16
+ const mergedConfig: EmperorUIConfig = {
17
+ layout: {
18
+ ...defaultEmperorUIConfig?.layout,
19
+ ...config?.layout,
20
+ },
21
+ theme: {
22
+ ...defaultEmperorUIConfig?.theme,
23
+ ...config?.theme,
24
+ colors: {
25
+ ...defaultEmperorUIConfig?.theme?.colors,
26
+ ...config?.theme?.colors,
27
+ },
28
+ },
29
+ interLocalization: {
30
+ ...defaultEmperorUIConfig?.interLocalization,
31
+ ...config?.interLocalization,
32
+ },
33
+ };
34
+
35
+ return {
36
+ config: mergedConfig,
37
+ };
38
+ }, [config]);
39
+
40
+ const withScaffold = config.layout?.withScaffold ?? true;
41
+
42
+ if (withScaffold)
43
+ return (
44
+ <EmperorUIContext.Provider value={emperorUIProviderValue}>
45
+ <Scaffold>{children}</Scaffold>
46
+ </EmperorUIContext.Provider>
47
+ );
48
+
49
+ return (
50
+ <EmperorUIContext.Provider value={emperorUIProviderValue}>
51
+ {children}
52
+ </EmperorUIContext.Provider>
53
+ );
54
+ }
@@ -1,31 +1,24 @@
1
- import type { EmperorUIContextState, EmperorUIProviderProps } from "@types";
2
- import { useMemo } from "react";
3
- import { EmperorUIContext } from "@context";
4
- import { defaultEmperorUIConfig } from "@constants";
5
- import { Scaffold } from "@components";
1
+ import { ConfigProviderProps } from "@types";
2
+ import { ConfigProvider, NavigationProvider } from "@providers";
3
+ import { HeroUIProvider, ToastProvider } from "@heroui/react";
4
+ import { Fragment } from "react";
5
+
6
+ type EmperorUIProviderProps = ConfigProviderProps & {};
6
7
 
7
8
  export function EmperorUIProvider({
8
9
  children,
9
- config = defaultEmperorUIConfig,
10
+ ...props
10
11
  }: EmperorUIProviderProps) {
11
- const emperorUIProviderValue: EmperorUIContextState = useMemo(() => {
12
- return {
13
- config,
14
- };
15
- }, [config]);
16
-
17
- const withScaffold = config.layout?.withScaffold ?? true;
18
-
19
- if (withScaffold)
20
- return (
21
- <EmperorUIContext.Provider value={emperorUIProviderValue}>
22
- <Scaffold>{children}</Scaffold>
23
- </EmperorUIContext.Provider>
24
- );
25
-
26
12
  return (
27
- <EmperorUIContext.Provider value={emperorUIProviderValue}>
28
- {children}
29
- </EmperorUIContext.Provider>
13
+ <ConfigProvider {...props}>
14
+ <HeroUIProvider>
15
+ <NavigationProvider>
16
+ <Fragment>
17
+ <ToastProvider {...props?.config?.toast} />
18
+ {children}
19
+ </Fragment>
20
+ </NavigationProvider>
21
+ </HeroUIProvider>
22
+ </ConfigProvider>
30
23
  );
31
24
  }
@@ -1 +1,4 @@
1
+ export * from "./config-provider";
1
2
  export * from "./emperor-ui-provider";
3
+ export * from "./navigation-provider";
4
+ export * from "./uploader-provider";
@@ -0,0 +1,42 @@
1
+ import type {
2
+ NavigationProviderProps,
3
+ NavigationContextState,
4
+ NavigationItem,
5
+ } from "@types";
6
+ import { useMemo, useState } from "react";
7
+ import { NavigationContext } from "@context";
8
+ import { PreservedKeys } from "@enums";
9
+
10
+ export function NavigationProvider({ children }: NavigationProviderProps) {
11
+ const [hoveredItemId, setHoveredItemId] = useState<string | null>(null);
12
+ const [subItems, setSubItems] = useState<NavigationItem[]>([]);
13
+ const [isSubItemsBoxOpen, setIsSubItemsBoxOpen] = useState(false);
14
+ const [subItemsBoxIsHovered, setSubItemsBoxIsHovered] = useState(false);
15
+
16
+ const navigationProviderValue: NavigationContextState = useMemo(() => {
17
+ return {
18
+ hoveredItemId,
19
+ subItems,
20
+ isSubItemsBoxOpen,
21
+ subItemsBoxIsHovered,
22
+ setHoveredItemId,
23
+ setSubItems,
24
+ setIsSubItemsBoxOpen,
25
+ setSubItemsBoxIsHovered,
26
+ };
27
+ }, [hoveredItemId, subItems, isSubItemsBoxOpen, subItemsBoxIsHovered]);
28
+
29
+ return (
30
+ <NavigationContext.Provider
31
+ value={navigationProviderValue}
32
+ data-slot="emperor-navigation-provider"
33
+ >
34
+ <div
35
+ id={PreservedKeys.COMPACT_SIDEBAR_ID}
36
+ data-slot="emperor-compact-sidebar"
37
+ />
38
+
39
+ {children}
40
+ </NavigationContext.Provider>
41
+ );
42
+ }
@@ -0,0 +1,53 @@
1
+ import type {
2
+ UploaderProviderProps,
3
+ UploaderContextState,
4
+ FileObject,
5
+ } from "@types";
6
+ import { useMemo, useState } from "react";
7
+ import { UploaderContext } from "@context";
8
+ import { useDisclosure } from "@heroui/react";
9
+
10
+ export function UploaderProvider({
11
+ children,
12
+ ...props
13
+ }: UploaderProviderProps) {
14
+ const { isOpen, onOpen, onOpenChange } = useDisclosure();
15
+ const [selectedFile, setSelectedFile] = useState<FileObject | null>(null);
16
+
17
+ const isFileViewable = useMemo(
18
+ () =>
19
+ !!selectedFile?.view &&
20
+ !!selectedFile?.file?.name &&
21
+ selectedFile?.type === "image",
22
+ [selectedFile],
23
+ );
24
+
25
+ const uploaderProviderValue: UploaderContextState = useMemo(() => {
26
+ return {
27
+ isOpen,
28
+ onOpen,
29
+ onOpenChange,
30
+ selectedFile,
31
+ setSelectedFile,
32
+ isFileViewable,
33
+ ...props,
34
+ };
35
+ }, [
36
+ isOpen,
37
+ isFileViewable,
38
+ selectedFile,
39
+ onOpen,
40
+ onOpenChange,
41
+ setSelectedFile,
42
+ props,
43
+ ]);
44
+
45
+ return (
46
+ <UploaderContext.Provider
47
+ value={uploaderProviderValue}
48
+ data-slot="emperor-uploader-provider"
49
+ >
50
+ {children}
51
+ </UploaderContext.Provider>
52
+ );
53
+ }
@@ -0,0 +1,13 @@
1
+ @import "tailwindcss";
2
+ @plugin './hero.ts';
3
+ @source '../../node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}';
4
+ @custom-variant dark (&:is(.dark *));
5
+
6
+ .scrollbar-hide {
7
+ -ms-overflow-style: none; /* IE and Edge */
8
+ scrollbar-width: none; /* Firefox */
9
+ }
10
+
11
+ .scrollbar-hide::-webkit-scrollbar {
12
+ display: none; /* Chrome, Safari, Opera */
13
+ }
@@ -0,0 +1,2 @@
1
+ import { heroui } from "@heroui/react";
2
+ export default heroui();
@@ -0,0 +1,13 @@
1
+ import { SharedComponentProps } from "@types";
2
+
3
+ export type BrandProps = SharedComponentProps & {
4
+ src?: string;
5
+ alt?: string;
6
+ name?: string;
7
+ isIconOnly?: boolean;
8
+ classNames?: {
9
+ base?: string;
10
+ logo?: string;
11
+ name?: string;
12
+ };
13
+ };
@@ -0,0 +1,3 @@
1
+ import type { SharedComponentProps } from "@types";
2
+
3
+ export type ColumnProps = SharedComponentProps & {};
@@ -0,0 +1,3 @@
1
+ import type { SharedComponentProps } from "@types";
2
+
3
+ export type ContainerProps = SharedComponentProps & {};
@@ -0,0 +1,6 @@
1
+ export * from "./brand";
2
+ export * from "./portal";
3
+ export * from "./uploader";
4
+ export * from "./column";
5
+ export * from "./row";
6
+ export * from "./container";
@@ -0,0 +1,6 @@
1
+ import { SharedComponentProps } from "@types";
2
+
3
+ export type PortalProps = SharedComponentProps & {
4
+ containerId: string;
5
+ isVisible?: boolean;
6
+ };
@@ -0,0 +1,3 @@
1
+ import type { SharedComponentProps } from "@types";
2
+
3
+ export type RowProps = SharedComponentProps & {};